]> git.ipfire.org Git - people/stevee/aiccu.git/commitdiff
Import upstream release 2007.01.15
authorStefan Schantl <stefan.schantl@ipfire.org>
Wed, 26 Aug 2015 18:17:57 +0000 (18:17 +0000)
committerStefan Schantl <stefan.schantl@ipfire.org>
Wed, 26 Aug 2015 18:17:57 +0000 (18:17 +0000)
Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
73 files changed:
Makefile [new file with mode: 0644]
common/aiccu.c [new file with mode: 0755]
common/aiccu.h [new file with mode: 0755]
common/aiccu_aix.c [new file with mode: 0644]
common/aiccu_darwin.c [new file with mode: 0755]
common/aiccu_freebsd4.c [new file with mode: 0755]
common/aiccu_kame.c [new file with mode: 0755]
common/aiccu_linux.c [new file with mode: 0755]
common/aiccu_openbsd.c [new file with mode: 0755]
common/aiccu_openbsd2.c [new file with mode: 0644]
common/aiccu_sunos.c [new file with mode: 0755]
common/aiccu_test.c [new file with mode: 0755]
common/ayiya.c [new file with mode: 0755]
common/ayiya.h [new file with mode: 0755]
common/common.c [new file with mode: 0755]
common/common.h [new file with mode: 0755]
common/hash_md5.c [new file with mode: 0755]
common/hash_md5.h [new file with mode: 0755]
common/hash_sha1.c [new file with mode: 0755]
common/hash_sha1.h [new file with mode: 0755]
common/heartbeat.c [new file with mode: 0755]
common/heartbeat.h [new file with mode: 0755]
common/resolver.c [new file with mode: 0644]
common/resolver.h [new file with mode: 0755]
common/tic.c [new file with mode: 0755]
common/tic.h [new file with mode: 0755]
common/tun.c [new file with mode: 0755]
common/tun.h [new file with mode: 0755]
debian/aiccu.config [new file with mode: 0755]
debian/aiccu.manpages [new file with mode: 0644]
debian/aiccu.postinst [new file with mode: 0755]
debian/aiccu.preinst [new file with mode: 0644]
debian/changelog [new file with mode: 0755]
debian/control [new file with mode: 0755]
debian/dirs [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/postrm.debhelper [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/substvars [new file with mode: 0644]
debian/templates [new file with mode: 0644]
doc/COPYRIGHT [new file with mode: 0644]
doc/HOWTO [new file with mode: 0644]
doc/LICENSE [new file with mode: 0644]
doc/README [new file with mode: 0644]
doc/aiccu.1 [new file with mode: 0644]
doc/aiccu.conf [new file with mode: 0755]
doc/aiccu.init [new file with mode: 0755]
doc/aiccu.init.debian [new file with mode: 0644]
doc/aiccu.init.freebsd [new file with mode: 0755]
doc/aiccu.init.gentoo [new file with mode: 0644]
doc/aiccu.init.rpm [new file with mode: 0755]
doc/aiccu.sgml [new file with mode: 0644]
doc/changelog [new file with mode: 0755]
doc/manpage.refs [new file with mode: 0644]
doc/setupscript.cmd [new file with mode: 0755]
freebsd/Makefile [new file with mode: 0644]
freebsd/files/sixxs-aiccu.in [new file with mode: 0644]
freebsd/pkg-descr [new file with mode: 0644]
freebsd/pkg-plist [new file with mode: 0644]
gentoo/aiccu-ebuild [new file with mode: 0644]
netbsd/DESCR [new file with mode: 0644]
netbsd/Makefile [new file with mode: 0644]
netbsd/PLIST [new file with mode: 0644]
netbsd/options.mk [new file with mode: 0644]
openbsd/Makefile [new file with mode: 0644]
openbsd/README [new file with mode: 0644]
openbsd/distinfo [new file with mode: 0644]
openbsd/pkg/DESCR [new symlink]
openbsd/pkg/MESSAGE [new file with mode: 0644]
openbsd/pkg/PLIST [new file with mode: 0644]
rpm/aiccu.spec [new file with mode: 0644]
unix-console/Makefile [new file with mode: 0755]
unix-console/main.c [new file with mode: 0755]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..0e96136
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,201 @@
+# /**********************************************************
+#  SixXS - Automatic IPv6 Connectivity Configuration Utility
+# ***********************************************************
+#  Copyright 2003-2005 SixXS - http://www.sixxs.net
+# ***********************************************************
+#  Packaging Makefile
+# ***********************************************************
+#  $Author: jeroen $
+#  $Id: Makefile,v 1.22 2007-01-11 00:29:33 jeroen Exp $
+#  $Date: 2007-01-11 00:29:33 $
+# **********************************************************/
+#
+# Note for BSD people: use GNU Make (gmake)
+
+PROJECT=aiccu
+PROJECT_DESC="Automatic IPv6 Connectivity Configuration Utility"
+PROJECT_VERSION=$(shell grep "AICCU_VER" common/aiccu.h | head -n 1 | awk '{print $$3}' | tr -d \")
+
+# Misc bins
+RM=@rm -f
+MAKE:=@${MAKE}
+CP=@echo [Copy]; cp
+RPMBUILD=@echo [RPMBUILD]; rpmbuild
+RPMBUILD_SILENCE=>/dev/null 2>/dev/null
+
+# Excludes for limited source release
+EXCLUDES=--exclude "${PROJECT}/windows-*" --exclude "${PROJECT}/common/aiccu_win32.c" --exclude CVS --exclude "${PROJECT}/common/tsp*" --exclude "${PROJECT}/common/teepee*"
+DEBEXCL=-Iwindows-* -Icommon/aiccu_win32.c -I*CVS* -Icommon/tsp* -Icommon/teepee*
+
+# Change this if you want to install into another dirtree
+# Required for eg the Debian Package builder
+DESTDIR=
+export DESTDIR
+
+# This may be updated by RPM's for instance
+CFLAGS=${RPM_OPT_FLAGS}
+
+# Destination Paths (relative to DESTDIR)
+dirsbin=/usr/sbin/
+dirbin=/usr/bin/
+diretc=/etc/
+dirdoc=/usr/share/doc/${PROJECT}/
+
+# Make sure the lower makefile also knows these
+export PROJECT
+export PROJECT_DESC
+export PROJECT_VERSION
+export PROJECT_COPYRIGHT
+export DESTDIR
+export RM
+export MV
+export CC
+export CP
+export MAKE
+export dirsbin
+export dirbin
+export diretc
+export dirdoc
+export RPM_OPT_FLAGS
+export CFLAGS
+
+####################
+## Makefile Targets
+####################
+
+all:   Makefile unix-console/
+       @echo "Building  : $(PROJECT) - $(PROJECT_DESC)"
+       @echo "Copyright : SixXS"
+       @echo "Version   : $(PROJECT_VERSION)"
+       $(MAKE) -C unix-console all
+       @echo "Building done"
+
+install: aiccu
+       @echo "Installing into ${DESTDIR}..."
+       @echo "Binaries..."
+       @mkdir -p ${DESTDIR}${dirsbin}
+       $(MAKE) -C unix-console install
+       @mkdir -p ${DESTDIR}${dirdoc}
+       @echo "Configuration..."
+       @mkdir -p ${DESTDIR}${diretc}
+ifeq ($(shell echo "A${RPM_BUILD_ROOT}"),A)
+       $(shell [ -f ${DESTDIR}${diretc}${PROJECT}.conf ] || cp -R doc/${PROJECT}.conf ${DESTDIR}${diretc}${PROJECT}.conf)
+       @echo "Documentation..."
+       @cp doc/README ${DESTDIR}${dirdoc}
+       @cp doc/LICENSE ${DESTDIR}${dirdoc}
+       @cp doc/HOWTO  ${DESTDIR}${dirdoc}
+       @echo "Installing Debian-style init.d"
+       @mkdir -p ${DESTDIR}${diretc}init.d
+       @cp doc/${PROJECT}.init.debian ${DESTDIR}${diretc}init.d/${PROJECT}
+else
+       @echo "Installing Redhat-style init.d"
+       @mkdir -p ${DESTDIR}${diretc}init.d
+       @cp doc/${PROJECT}.init.rpm ${DESTDIR}${diretc}init.d/${PROJECT}
+       @cp doc/${PROJECT}.conf ${DESTDIR}${diretc}${PROJECT}.conf
+endif
+       @echo "Installation into ${DESTDIR}/ completed"
+
+help:
+       @echo "$(PROJECT) - $(PROJECT_DESC)"
+       @echo
+       @echo "Makefile targets:"
+       @echo "all      : Build everything"
+       @echo "help     : This little text"
+       @echo "install  : Build & Install into ${DESTDIR}/"
+       @echo "clean    : Clean the dirs to be pristine in bondage"
+       @echo
+       @echo "Distribution targets:"
+       @echo "dist     : Make all distribution targets (except rpm's)"
+       @echo "tar      : Make source tarball (tar.gz)"
+       @echo "bz2      : Make source tarball (tar.bz2)"
+       @echo "deb      : Make Debian binary package (.deb)"
+       @echo "debsrc   : Make Debian source packages"
+       @echo "rpm      : Make RPM package (.rpm)"
+       @echo "rpmsrc   : Make RPM source packages"
+       @echo
+       @echo "SixXS targets:"
+       @echo "tarfull  : Full tar including Windows directories" 
+       @echo "bz2full  : Full bz2 including Windows directories" 
+
+aiccu: doc unix-console/
+       $(MAKE) -C unix-console all
+
+doc:   doc/aiccu.1
+
+doc/aiccu.1: doc/aiccu.sgml
+       docbook-to-man doc/aiccu.sgml >doc/aiccu.1
+
+clean: debclean rpmclean
+       $(MAKE) -C unix-console clean
+       -${RM} -r windows-gui/Debug
+       -${RM} -r windows-gui/Release
+       -${RM} windows-gui/AICCU.APS
+       -${RM} windows-gui/AICCU.ncb
+       -${RM} -r windows-console/Debug
+       -${RM} -r windows-console/Release
+       -${RM} windows-console/AICCU.APS
+       -${RM} windows-console/AICCU.ncb
+
+# Generate Distribution files
+dist:  tar bz2 deb
+
+# tar.gz
+tar:   clean
+       -${RM} ../${PROJECT}_${PROJECT_VERSION}.tar.gz
+       tar -zco -C .. ${EXCLUDES} -f ../${PROJECT}_${PROJECT_VERSION}.tar.gz ${PROJECT}
+
+# tar.gz (full)
+tarfull: clean
+       -${RM} ../${PROJECT}_${PROJECT_VERSION}.tar.gz
+       tar -zco -C .. -f ../${PROJECT}_${PROJECT_VERSION}-full.tar.gz ${PROJECT}
+
+# tar.bz2
+bz2:   clean
+       -${RM} ../${PROJECT}_${PROJECT_VERSION}.tar.bz2
+       tar -jco -C .. ${EXCLUDES} -f ../${PROJECT}_${PROJECT_VERSION}.tar.bz2 ${PROJECT}
+
+# tar.bz2 (full)
+bz2full: clean
+       -${RM} ../${PROJECT}_${PROJECT_VERSION}.tar.bz2
+       tar -jco -C .. -f ../${PROJECT}_${PROJECT_VERSION}-full.tar.bz2 ${PROJECT}
+
+# .deb
+deb:   clean
+       # Copy the changelog
+       ${CP} doc/changelog debian/changelog
+       ${CP} doc/${PROJECT}.init.debian debian/${PROJECT}.init
+       dpkg-buildpackage $(DEBEXCL) -rfakeroot
+       ${MAKE} clean
+
+# Cleanup after debian
+debclean:
+       -${RM} debian/${PROJECT}.init debian/${PROJECT}.conffiles
+       if [ -f build-stamp ]; then debian/rules clean; fi
+
+# RPM
+rpm:   clean tar
+       -${RM} /usr/src/redhat/RPMS/i386/${PROJECT}-*.rpm
+       ${RPMBUILD} -tb --define '${PROJECT}_version ${PROJECT_VERSION}' ../${PROJECT}_${PROJECT_VERSION}.tar.gz ${RPMBUILD_SILENCE}
+       @if [ -d /usr/src/redhat/RPMS/i386/ ]; then mv /usr/src/redhat/RPMS/i386/${PROJECT}-*.rpm ../; fi
+       @if [ -d /usr/src/rpm/RPMS/i386/ ]; then mv /usr/src/rpm/RPMS/i386/${PROJECT}-*.rpm ../; fi
+       @echo "Resulting RPM's:"
+       @ls -l ../${PROJECT}-*.rpm
+       ${MAKE} clean
+       @echo "RPMBuild done"
+
+rpmsrc:        clean tar
+       -${RM} /usr/src/redhat/RPMS/i386/${PROJECT}-*src.rpm
+       ${RPMBUILD} -ts --define '${PROJECT}_version ${PROJECT_VERSION}' ../${PROJECT}_${PROJECT_VERSION}.tar.gz ${RPMBUILD_SILENCE}
+       @if [ -d /usr/src/redhat/RPMS/i386/ ]; then mv /usr/src/redhat/RPMS/i386/${PROJECT}-*.src.rpm ../; fi
+       @if [ -d /usr/src/rpm/RPMS/i386/ ]; then mv /usr/src/rpm/RPMS/i386/${PROJECT}-*.src.rpm ../; fi
+       @echo "Resulting RPM's:"
+       @ls -l ../${PROJECT}-*.rpm
+       ${MAKE} clean
+       @echo "RPMBuild-src done"
+
+rpmclean:
+       -${RM} ../${PROJECT}_${PROJECT_VERSION}.tar.gz
+
+# Mark targets as phony
+.PHONY : all install help clean dist tar bz2 deb debclean rpm rpmsrc
+
diff --git a/common/aiccu.c b/common/aiccu.c
new file mode 100755 (executable)
index 0000000..9abb334
--- /dev/null
@@ -0,0 +1,444 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu.c - AICCU Abstracted functions
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu.c,v 1.20 2007-01-15 12:02:10 jeroen Exp $
+ $Date: 2007-01-15 12:02:10 $
+**********************************************************/
+
+#include "aiccu.h"
+
+struct AICCU_conf *g_aiccu = NULL;
+
+/* Config */
+struct pl_rule aiccu_conf_rules[] =
+{
+       /* Configuration */
+       {"username",            PLRT_STRING,    offsetof(struct AICCU_conf, username)},
+       {"password",            PLRT_STRING,    offsetof(struct AICCU_conf, password)},
+       {"protocol",            PLRT_STRING,    offsetof(struct AICCU_conf, protocol)},
+       {"server",              PLRT_STRING,    offsetof(struct AICCU_conf, server)},
+       {"ipv6_interface",      PLRT_STRING,    offsetof(struct AICCU_conf, ipv6_interface)},
+       {"tunnel_id",           PLRT_STRING,    offsetof(struct AICCU_conf, tunnel_id)},
+       {"local_ipv4_override", PLRT_STRING,    offsetof(struct AICCU_conf, local_ipv4_override)},
+
+       /* Post Setup script path */
+       {"setupscript",         PLRT_STRING,    offsetof(struct AICCU_conf, setupscript)},
+
+       /* Automatic */
+       {"automatic",           PLRT_BOOL,      offsetof(struct AICCU_conf, automatic)},
+
+       /* Operational options */
+       {"daemonize",           PLRT_BOOL,      offsetof(struct AICCU_conf, daemonize)},
+       {"verbose",             PLRT_BOOL,      offsetof(struct AICCU_conf, verbose)},
+       {"behindnat",           PLRT_BOOL,      offsetof(struct AICCU_conf, behindnat)},
+       {"requiretls",          PLRT_BOOL,      offsetof(struct AICCU_conf, requiretls)},
+       {"noconfigure",         PLRT_BOOL,      offsetof(struct AICCU_conf, noconfigure)},
+       {"makebeats",           PLRT_BOOL,      offsetof(struct AICCU_conf, makebeats)},
+       {"defaultroute",        PLRT_BOOL,      offsetof(struct AICCU_conf, defaultroute)},
+       {"pidfile",             PLRT_STRING,    offsetof(struct AICCU_conf, pidfile)},
+       {NULL,                  PLRT_END,       0},
+};
+
+#ifdef AICCU_GNUTLS
+void aiccu_tls_log(int level, const char *message);
+void aiccu_tls_log(int level, const char *message)
+{
+       dolog(level, "[GNUTLS] %s\n", message);
+}
+#endif
+
+bool aiccu_InitConfig()
+{
+#ifdef AICCU_GNUTLS
+       int ret;
+#define CAFILE "ca.pem"
+#endif
+       /* Allocate & Initialize */
+       g_aiccu = (struct AICCU_conf *)malloc(sizeof(*g_aiccu));
+       if (!g_aiccu) return false;
+       memset(g_aiccu, 0, sizeof(*g_aiccu));
+       g_aiccu->tic = (struct TIC_conf *)malloc(sizeof(*g_aiccu->tic));
+       memset(g_aiccu->tic, 0, sizeof(*g_aiccu->tic));
+
+       /* Initialize config to defaults */
+       g_aiccu->running        = true;
+       g_aiccu->tunrunning     = false;
+       g_aiccu->daemonize      = 0;
+       g_aiccu->verbose        = false;
+       g_aiccu->requiretls     = false;                /* Not mandatory yet */
+       g_aiccu->noconfigure    = false;
+       g_aiccu->makebeats      = true;
+       g_aiccu->defaultroute   = true;
+       g_aiccu->ipv6_interface = strdup("aiccu");
+       if (!g_aiccu->ipv6_interface) return false;
+       g_aiccu->protocol       = strdup("tic");
+       if (!g_aiccu->protocol) return false;
+       g_aiccu->server         = strdup("tic.sixxs.net");
+       if (!g_aiccu->server) return false;
+       g_aiccu->pidfile        = strdup(AICCU_PID);
+       if (!g_aiccu->pidfile) return false;
+
+#ifdef AICCU_GNUTLS
+       /* Initialize GNUTLS */
+       ret = gnutls_global_init();
+       if (ret != 0)
+       {
+               dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
+               return false;
+       }
+
+       /* X509 credentials */
+       ret = gnutls_certificate_allocate_credentials(&g_aiccu->tls_cred);
+       if (ret != 0)
+       {
+               dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
+               return false;
+       }
+
+       /* For the time being don't load the PEM as it is not there... */
+
+#if 0
+       /* Sets the trusted cas file */
+       ret = gnutls_certificate_set_x509_trust_file(g_aiccu->tls_cred, CAFILE, GNUTLS_X509_FMT_PEM);
+       if (ret < 0)
+       {
+               dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
+               return false;
+       }
+#endif
+
+       /* Configure GNUTLS logging to happen using our own logging interface */
+       gnutls_global_set_log_function(aiccu_tls_log);
+
+#ifdef DEBUG
+       /* Show some GNUTLS debugging information */
+       gnutls_global_set_log_level(5);
+#endif
+
+#endif /* AICCU_GNUTLS */
+
+       return true;
+}
+
+/* Locate where the configfile is stored */
+void aiccu_LocateFile(const char *what, char *filename, unsigned int length);
+void aiccu_LocateFile(const char *what, char *filename, unsigned int length)
+{
+       memset(filename, 0, length);
+#ifdef _WIN32
+       /* Figure out the "C:\Windows" location */
+       /* as that is where we store our configuration */
+       GetWindowsDirectory(filename, length);
+       strncat(filename, "\\", length);
+       strncat(filename, what, length);
+#else
+       /* Use the default location */
+       strncat(filename, what, length);
+#endif
+}
+
+/* configure this client */
+bool aiccu_LoadConfig(const char *filename)
+{
+       FILE                    *f;
+       char                    buf[1000];
+       char                    filenames[256];
+       unsigned int            line = 0;
+
+       if (!filename)
+       {
+               aiccu_LocateFile(AICCU_CONFIG, filenames, sizeof(filenames));
+               filename = filenames;
+       }
+
+       f = fopen(filename, "r");
+       if (!f)
+       {
+               dolog(LOG_ERR, "Could not open config file \"%s\"\n", filename);
+               return false;
+       }
+
+       while (fgets(buf, sizeof(buf), f))
+       {
+               line++;
+               if (parseline(buf, " ", aiccu_conf_rules, g_aiccu)) continue;
+
+               dolog(LOG_WARNING, "Unknown configuration statement on line %u of %s: \"%s\"\n", line, filename, buf);
+       }
+       fclose(f);
+
+       return true;
+}
+
+/* Save the configuration */
+bool aiccu_SaveConfig(const char *filename)
+{
+       FILE *f;
+       char filenames[512];
+
+       if (!filename)
+       {
+               aiccu_LocateFile(AICCU_CONFIG, filenames, sizeof(filenames));
+               filename = filenames;
+       }
+
+       f = fopen(filename, "w");
+       if (!f)
+       {
+               dolog(LOG_ERR, "Could not open config file \"%s\" for writing\n", filename);
+               return false;
+       }
+
+       fprintf(f, "# AICCU Configuration (Saved by AICCU %s)\n", AICCU_VER);
+       fprintf(f, "\n");
+       fprintf(f, "# Login information\n");
+       fprintf(f, "username %s\n", g_aiccu->username);
+       fprintf(f, "password %s\n", g_aiccu->password);
+       fprintf(f, "protocol %s\n", g_aiccu->protocol);
+       fprintf(f, "server %s\n", g_aiccu->server);
+       fprintf(f, "\n");
+       fprintf(f, "# Interface names to use\n");
+       fprintf(f, "ipv6_interface %s\n", g_aiccu->ipv6_interface);
+       fprintf(f, "\n");
+       fprintf(f, "# The tunnel_id to use\n");
+       fprintf(f, "# (only required when there are multiple tunnels in the list)\n");
+       fprintf(f, "tunnel_id %s\n", g_aiccu->tunnel_id);
+       fprintf(f, "\n");
+       fprintf(f, "# Try to automatically login and setup the tunnel?\n");
+       fprintf(f, "automatic %s\n", g_aiccu->automatic ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# Script to run after setting up the interfaces (default: none)\n");
+       fprintf(f, "%ssetupscript %s\n", g_aiccu->setupscript ? "" : "#", g_aiccu->setupscript ? g_aiccu->setupscript : "<path>");
+       fprintf(f, "\n");
+       fprintf(f, "# TLS Required?\n");
+       fprintf(f, "requiretls %s\n", g_aiccu->requiretls ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# Be verbose?\n");
+       fprintf(f, "verbose %s\n", g_aiccu->verbose ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# Daemonize?\n");
+       fprintf(f, "daemonize %s\n", g_aiccu->daemonize ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# Behind NAT (default: false)\n");
+       fprintf(f, "# Notify the user that a NAT-kind network is detected\n");
+       fprintf(f, "behindnat %s\n", g_aiccu->behindnat ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# PID File\n");
+       fprintf(f, "pidfile %s\n", g_aiccu->pidfile);
+       fprintf(f, "\n");
+       fprintf(f, "# Make heartbeats (default true)\n");
+       fprintf(f, "# In general you don't want to turn this off\n");
+       fprintf(f, "# Of course only applies to AYIYA and heartbeat tunnels not to static ones\n");
+       fprintf(f, "makebeats %s\n", g_aiccu->makebeats ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# Add a default route (default: true)\n");
+       fprintf(f, "defaultroute %s\n", g_aiccu->defaultroute ? "true" : "false");
+       fprintf(f, "\n");
+       fprintf(f, "# Don't configure anything (default: false)\n");
+       fprintf(f, "noconfigure %s\n", g_aiccu->noconfigure ? "true" : "false");
+       fclose(f);
+       return true;
+}
+
+void aiccu_FreeConfig()
+{
+       if (!g_aiccu) return;
+
+#ifdef AICCU_GNUTLS
+       gnutls_certificate_free_credentials(g_aiccu->tls_cred);
+       gnutls_global_deinit();
+#endif
+
+       if (g_aiccu->username)          { free(g_aiccu->username);      g_aiccu->username       = NULL; }
+       if (g_aiccu->password)          { free(g_aiccu->password);      g_aiccu->password       = NULL; }
+       if (g_aiccu->ipv6_interface)    { free(g_aiccu->ipv6_interface);g_aiccu->ipv6_interface = NULL; }
+       if (g_aiccu->tunnel_id)         { free(g_aiccu->tunnel_id);     g_aiccu->tunnel_id      = NULL; }
+       if (g_aiccu->tic)               { free(g_aiccu->tic);           g_aiccu->tic            = NULL; }
+       if (g_aiccu->setupscript)       { free(g_aiccu->setupscript);   g_aiccu->setupscript    = NULL; }
+       if (g_aiccu->pidfile)           { free(g_aiccu->pidfile);       g_aiccu->pidfile        = NULL; }
+
+       free(g_aiccu);
+       g_aiccu = NULL;
+}
+
+/* Make sure the OS understands IPv6 */
+void aiccu_install(void)
+{
+       D(dolog(LOG_DEBUG, "aiccu_install()\n");)
+       aiccu_os_install();
+}
+
+bool aiccu_setup(struct TIC_Tunnel *hTunnel, bool firstrun)
+{
+       bool ret = false;
+
+       D(dolog(LOG_DEBUG, "aiccu_setup(%s, %s)\n", hTunnel->sIPv6_Local, firstrun ? "first" : "other");)
+
+       /* AYIYA calls aiccu_setup(hTunnel,false) after preparing the tunnel interface */
+       if (firstrun && strcasecmp(hTunnel->sType, "ayiya") == 0)
+       {
+               ret = ayiya(hTunnel);
+       }
+#ifdef NEWSTUFF_TEEPEE
+       else if (firstrun && strcasecmp(hTunnel->sType, "l2tp") == 0)
+       {
+               ret = teepee(hTunnel);
+       }
+#endif
+       else
+       {
+               ret = aiccu_os_setup(hTunnel);
+       }
+
+       /* Beat for the first time */
+       if (ret) aiccu_beat(hTunnel);
+
+       return ret;
+}
+
+void aiccu_beat(struct TIC_Tunnel *hTunnel)
+{
+       if (!g_aiccu->makebeats)
+       {
+               D(dolog(LOG_DEBUG, "aiccu_beat() - Beating disabled\n"));
+               return;
+       }
+
+       D(dolog(LOG_DEBUG, "aiccu_beat() - Beating %s...\n", hTunnel->sType));
+
+       if (strcasecmp(hTunnel->sType, "6in4-heartbeat") == 0)
+       {
+               heartbeat_beat(hTunnel);
+       }
+       else if (strcasecmp(hTunnel->sType, "ayiya") == 0)
+       {
+               ayiya_beat();
+       }
+       else
+       {
+               D(dolog(LOG_DEBUG, "aiccu_beat() - No beat for %s!?\n", hTunnel->sType));
+       }
+
+       /* L2TP Hello's are handled inside TeePee */
+}
+
+void aiccu_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       D(dolog(LOG_DEBUG, "aiccu_reconfig(%s)\n", hTunnel->sIPv6_Local);)
+       if (!g_aiccu->noconfigure) aiccu_os_reconfig(hTunnel);
+}
+
+void aiccu_delete(struct TIC_Tunnel *hTunnel)
+{
+       D(dolog(LOG_DEBUG, "aiccu_delete(%s)\n", hTunnel->sIPv6_Local);)
+       if (!g_aiccu->noconfigure) aiccu_os_delete(hTunnel);
+}
+
+void aiccu_test(struct TIC_Tunnel *hTunnel, bool automatic)
+{
+       D(dolog(LOG_DEBUG, "aiccu_test()\n"));
+       aiccu_os_test(hTunnel, automatic);
+}
+
+bool aiccu_exec(const char *fmt, ...)
+{
+#ifndef _WIN32
+       char buf[1024];
+       int ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf,sizeof(buf),fmt,ap);
+       D(dolog(LOG_DEBUG, "aiccu_os_exec(\"%s\")\n", buf));
+       ret = system(buf);
+       if (ret == -1) dolog(LOG_WARNING, "Execution of \"%s\" failed!? (Please check if the command is available)\n", buf);
+       va_end(ap);
+#endif
+       return true;
+}
+
+#define SIXXS_LICENSE_PART1 "\
+The SixXS License - http://www.sixxs.net/\n\
+\n\
+Copyright (C) SixXS Staff <info@sixxs.net>\n\
+All rights reserved.\n\
+\n\
+Redistribution and use in source and binary forms, with or without\n\
+modification, are permitted provided that the following conditions\n\
+are met:\n\
+1. Redistributions of source code must retain the above copyright\n\
+   notice, this list of conditions and the following disclaimer.\n"
+
+#define SIXXS_LICENSE_PART2 "\
+2. Redistributions in binary form must reproduce the above copyright\n\
+   notice, this list of conditions and the following disclaimer in the\n\
+   documentation and/or other materials provided with the distribution.\n\
+3. Neither the name of SixXS nor the names of its contributors\n\
+   may be used to endorse or promote products derived from this software\n\
+   without specific prior permission.\n\
+\n\
+\n"
+
+#define SIXXS_LICENSE_PART3 "\
+THIS SOFTWARE IS PROVIDED BY SIXXS AND CONTRIBUTORS ``AS IS'' AND\n\
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n\
+ARE DISCLAIMED.  IN NO EVENT SHALL SIXXS OR CONTRIBUTORS BE LIABLE\n\
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n\
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
+
+#define SIXXS_LICENSE_PART4 "\
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n\
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n\
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n\
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n\
+SUCH DAMAGE.\n"
+
+const char *aiccu_license()
+{
+#ifndef NOPEDANTIC
+       /*
+       * Pedantic doesn't allow this long strings, thus we will
+        * play nice and malloc it, copy them in separately and
+        * then return the buffer.
+        * What we don't do for compliancy....
+       */
+       static char *license = NULL;
+       if (!license)
+       {
+               /*
+                * Make one big block out of it
+                * too bad that the \0's get inserted,
+                * remove them and tada one big text...
+               */
+               static char
+                       l1[] = SIXXS_LICENSE_PART1,
+                       l2[] = SIXXS_LICENSE_PART2,
+                       l3[] = SIXXS_LICENSE_PART3,
+                       l4[] = SIXXS_LICENSE_PART4;
+               size_t
+                       a = strlen(l1),
+                       b = strlen(l2),
+                       c = strlen(l3),
+                       d = strlen(l4);
+
+               /* Create the 'long' string our selves then */
+               license = (char *)malloc(a+b+c+d+1);
+               if (!license) return NULL;
+
+               memset(license, 0, a+b+c+d+1);
+               memcpy(license    , l1, a);
+               memcpy(license + a, l2, b);
+               memcpy(license + a + b, l3, c);
+               memcpy(license + a + b + c, l4, d);
+       }
+       return license;
+#else
+       return SIXXS_LICENSE_PART1 SIXXS_LICENSE_PART2 SIXXS_LICENSE_PART3 SIXXS_LICENSE_PART4;
+#endif
+}
diff --git a/common/aiccu.h b/common/aiccu.h
new file mode 100755 (executable)
index 0000000..ef65000
--- /dev/null
@@ -0,0 +1,159 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu.h - Abstracted Functions and Configuration
+ All compile-time configurable items are in this file
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu.h,v 1.23 2007-01-15 12:01:43 jeroen Exp $
+ $Date: 2007-01-15 12:01:43 $
+**********************************************************/
+
+#ifndef AICCU_H
+#define AICCU_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#include "common.h"
+#include "tic.h"
+#include "heartbeat.h"
+#include "ayiya.h"
+#include "resolver.h"
+
+#ifdef NEWSTUFF_TSP
+#include "tsp.h"
+#endif
+#ifdef NEWSTUFF_TSP
+#include "teepee.h"
+#endif
+
+/* AICCU Version */
+#define AICCU_VER              "2007.01.15"
+#define AICCU_VERSION_NUM      2007,01,15,0
+/* _NUM = required for Windows Resources */
+
+#ifdef _WIN32
+#define AICCU_TYPE "win32"
+#endif
+
+/* Append -gui or -console? */
+#ifndef AICCU_CONSOLE
+#ifdef AICCU_TYPE
+#define AICCU_VERSION AICCU_VER "-gui-" AICCU_TYPE
+#else
+#define AICCU_VERSION AICCU_VER "-gui"
+#endif
+#else
+#ifdef AICCU_TYPE
+#define AICCU_VERSION AICCU_VER "-console-" AICCU_TYPE
+#else
+#define AICCU_VERSION AICCU_VER "-console"
+#endif
+#endif
+
+/* Needed for TIC */
+#define TIC_CLIENT_NAME "AICCU"
+#define TIC_CLIENT_VERSION AICCU_VERSION
+
+/* Needed for TSP */
+#define TSP_CLIENT_NAME TIC_CLIENT_NAME
+#define TSP_CLIENT_VERSION TIC_CLIENT_VERSION
+
+/* 
+ * AICCU configuration Cache
+ * allows reconnects even when we don't update
+ * the data. Could be useful in the event
+ * where we can't make contact to the main server
+ */
+#define AICCU_CACHE    "/var/cache/aiccu.cache"
+
+/* The PID we are running as when daemonized */
+#define AICCU_PID      "/var/run/aiccu.pid"
+
+/* AICCU Configuration file */
+#ifdef _WIN32
+/* GetWindowsDirectory() is used to figure out the directory to store the config */
+#define AICCU_CONFIG   "aiccu.conf"
+#else
+#define AICCU_CONFIG   "/etc/aiccu.conf"
+#endif
+
+/* Inbound listen queue */
+#define LISTEN_QUEUE    128
+
+#ifndef UNUSED
+#ifdef _AIX
+#define UNUSED
+#else
+#define UNUSED __attribute__ ((__unused__))
+#endif
+#endif
+
+/* AICCU Configuration */
+struct AICCU_conf
+{
+       /* Only for AICCU */
+       char            *username;              /* Username */
+       char            *password;              /* Password */
+       char            *protocol;              /* TIC/TSP/L2TP */
+       char            *server;                /* TIC/TSP etc server */
+       char            *ipv6_interface;        /* IPv6 interface (tunnel interface: sit0, tun0 etc) */
+       char            *tunnel_id;             /* ID of the tunnel to use */
+       char            *local_ipv4_override;   /* Local IPv4 override, for behind-NAT scenario's */
+       char            *setupscript;           /* Script to run after having set up the tunnel */
+       char            *pidfile;               /* File to store the PID */
+
+       /* used by other parts */
+
+       struct TIC_conf *tic;                   /* TIC Structure */
+#ifdef NEWSTUFF_TSP
+       struct TSP_conf *tsp;                   /* TSP Structure */
+#endif
+
+#ifdef AICCU_GNUTLS
+       gnutls_certificate_credentials  tls_cred;       /* GNUTLS credentials */
+#endif
+
+       bool            daemonize;              /* Daemonize? */
+       bool            verbose;                /* Verbosity */
+       bool            running;                /* Still running? */
+       bool            tunrunning;             /* Is the tundev running? */
+
+       bool            automatic;              /* Try to be totally automatic? */
+       bool            behindnat;              /* Behind a NAT */
+       bool            requiretls;             /* Require TLS for TIC? */
+       bool            makebeats;              /* Make heartbeats? */
+       bool            noconfigure;            /* No configuration (used to only send heartbeats) */
+       bool            defaultroute;           /* Configure a default route */
+};
+
+/* Global configuration */
+extern struct AICCU_conf *g_aiccu;
+
+/* AICCU Abstracted Functions */
+bool aiccu_InitConfig(void);
+bool aiccu_LoadConfig(const char *filename);
+bool aiccu_SaveConfig(const char *filename);
+void aiccu_FreeConfig(void);
+
+void aiccu_install(void);
+bool aiccu_setup(struct TIC_Tunnel *hTunnel, bool firstrun);
+void aiccu_beat(struct TIC_Tunnel *hTunnel);
+void aiccu_reconfig(struct TIC_Tunnel *hTunnel);
+void aiccu_delete(struct TIC_Tunnel *hTunnel);
+void aiccu_test(struct TIC_Tunnel *hTunnel, bool automatic);
+bool aiccu_exec(const char *fmt, ...);
+const char *aiccu_license(void);
+
+/* OS Specific */
+bool aiccu_os_install(void);
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel);
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel);
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel);
+void aiccu_os_test(struct TIC_Tunnel *hTunnel, bool automatic);
+
+#ifdef _WIN32
+void aiccu_win32_rename_adapter(const char *orig);
+#endif
+
+#endif /* AICCU_H */
diff --git a/common/aiccu_aix.c b/common/aiccu_aix.c
new file mode 100644 (file)
index 0000000..e29e9ef
--- /dev/null
@@ -0,0 +1,90 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_aix.c - AIX
+
+ ipv6_interface has to be eg cti0
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_aix.c,v 1.3 2006-07-23 14:13:57 jeroen Exp $
+ $Date: 2006-07-23 14:13:57 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install()
+{
+       /* Define the CTI (Configured Tunnel Interface) by executing the deftunnel configuration method */
+       return aiccu_exec("/usr/lib/methods/deftunnel -c if -s CTI -t cti");
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               /* Build a normal SIT tunnel */
+               aiccu_exec(
+                       "/usr/sbin/ifconfig %s inet6 ::%s/128 ::%s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+
+               /* Remove the local endpoint, the remote stays though :) */
+               aiccu_exec(
+                       "/usr/sbin/ifconfig %s inet6 ::%s delete",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local);
+
+               /* Add the addresses */
+               aiccu_exec(
+                       "ifconfig %s inet6 %s %s",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv6_Local,
+                       hTunnel->sIPv6_POP);
+       }
+       else
+       {
+               dolog(LOG_DEBUG, "There is no AIX support for tun-devices yet");
+               exit(-1);
+       }
+
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               /* Build a normal SIT tunnel */
+               aiccu_exec(
+                       "/usr/sbin/ifconfig %s inet6 ::%s/128 ::%s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+
+               /* Remove the local endpoint, the remote stays */
+               aiccu_exec(
+                       "/usr/sbin/ifconfig %s inet6 ::%s delete",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local);
+       }
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+}
+
diff --git a/common/aiccu_darwin.c b/common/aiccu_darwin.c
new file mode 100755 (executable)
index 0000000..b032e44
--- /dev/null
@@ -0,0 +1,87 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_darwin.c - Darwin
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_darwin.c,v 1.11 2007-01-07 17:02:11 jeroen Exp $
+ $Date: 2007-01-07 17:02:11 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+
+       /* Bring the interface up */
+       aiccu_exec(
+               "ifconfig %s up",
+               g_aiccu->ipv6_interface);
+
+       /* Configure the MTU */
+       aiccu_exec(
+               "ifconfig %s mtu %u",
+               g_aiccu->ipv6_interface,
+               hTunnel->nMTU);
+
+       /* PtP link, so we can use the PtP syntax */
+       aiccu_exec(
+               "ifconfig %s inet6 %s %s prefixlen 128 alias",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv6_Local,
+               hTunnel->sIPv6_POP);
+
+       /* Configure a path to the other side */
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ifconfig %s deletetunnel",
+                       g_aiccu->ipv6_interface);
+       }
+}
+
diff --git a/common/aiccu_freebsd4.c b/common/aiccu_freebsd4.c
new file mode 100755 (executable)
index 0000000..95a6554
--- /dev/null
@@ -0,0 +1,111 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_freebsd4.c - FreeBSD 3.x/4.x
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_freebsd4.c,v 1.11 2007-01-07 17:05:23 jeroen Exp $
+ $Date: 2007-01-07 17:05:23 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               /* Create the tunnel device */
+               aiccu_exec(
+                       "/sbin/ifconfig %s create",
+                       g_aiccu->ipv6_interface);
+
+               /* Configure the endpoint */
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+
+       /* Mark the interface up */
+       aiccu_exec(
+               "ifconfig %s up",
+               g_aiccu->ipv6_interface);
+
+       /* Configure the MTU */
+       aiccu_exec(
+               "ifconfig %s mtu %u",
+               g_aiccu->ipv6_interface,
+               hTunnel->nMTU);
+
+       if (hTunnel->uses_tundev == 1)
+       {
+               /* Give it a link local address */
+               aiccu_exec(
+                       "ifconfig %s inet6 %s prefixlen 64 alias",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv6_LinkLocal);
+       }
+
+       /* Local side of the tunnel */
+       aiccu_exec(
+               "ifconfig %s inet6 %s prefixlen 128 alias",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv6_Local);
+
+       /* Route to the remote side of the tunnel */
+       aiccu_exec(
+               "route add -inet6 %s -prefixlen 128 %s",
+               hTunnel->sIPv6_POP,
+               hTunnel->sIPv6_Local);
+
+       if (g_aiccu->defaultroute)
+       {
+               /* Add a default route */
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               /* Change the endpoints of the tunnel */
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+
+       /* Mark the interface down */
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+
+       if (hTunnel->uses_tundev == 0)
+       {
+               /* Destroy the tunnel */
+               aiccu_exec(
+                       "ifconfig %s destroy",
+                       g_aiccu->ipv6_interface);
+       }
+}
+
diff --git a/common/aiccu_kame.c b/common/aiccu_kame.c
new file mode 100755 (executable)
index 0000000..c6d1ea3
--- /dev/null
@@ -0,0 +1,97 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_kame.c - NetBSD + FreeBSD 5.x+
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_kame.c,v 1.15 2007-01-11 15:11:27 jeroen Exp $
+ $Date: 2007-01-11 15:11:27 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s create",
+                       g_aiccu->ipv6_interface);
+
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+
+       aiccu_exec(
+               "ifconfig %s up",
+               g_aiccu->ipv6_interface);
+
+        aiccu_exec(
+               "ifconfig %s mtu %u",
+               g_aiccu->ipv6_interface,
+               hTunnel->nMTU);
+
+       if (hTunnel->uses_tundev == 1)
+       {
+               /* Configure a generated linklocal address */
+               aiccu_exec(
+                       "ifconfig %s inet6 %s prefixlen 64 alias",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv6_LinkLocal);
+       }
+
+       /* PtP link, so we can use the PtP syntax */
+       aiccu_exec(
+               "ifconfig %s inet6 %s %s prefixlen 128 alias",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv6_Local,
+               hTunnel->sIPv6_POP);
+
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ifconfig %s deletetunnel",
+                       g_aiccu->ipv6_interface);
+       }
+}
+
diff --git a/common/aiccu_linux.c b/common/aiccu_linux.c
new file mode 100755 (executable)
index 0000000..b86ad67
--- /dev/null
@@ -0,0 +1,122 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_linux.c - AICCU Linux Abstracted functions
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_linux.c,v 1.15 2007-01-15 12:18:58 jeroen Exp $
+ $Date: 2007-01-15 12:18:58 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       /* Check if IPv6 support is available */
+       if (access("/proc/net/if_inet6", F_OK))
+       {
+               /* Doing the modprobe doesn't guarantee success unfortunately */
+               (void)system("modprobe -q ipv6 2>/dev/null >/dev/null");
+
+               /* Thus test it again */
+               if (access("/proc/net/if_inet6", F_OK))
+               {
+                       dolog(LOG_ERR, "No IPv6 Stack found! Please check your kernel and module configuration\n");
+                       return false;
+               }
+       }
+
+       /* Try to load modules (SIT tunnel, TUN/TAP)
+        * They can be kernel builtins and there is no easy
+        * way to check if they are loaded/built except for
+        * trying to use them and fail at that point
+        */
+       (void)system("modprobe -q sit 2>/dev/null >/dev/null");
+       (void)system("modprobe -q tun 2>/dev/null >/dev/null");
+
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ip tunnel add %s mode sit %s%s remote %s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "" : "local ",
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+
+       aiccu_exec(
+               "ip link set %s up",
+               g_aiccu->ipv6_interface);
+
+       aiccu_exec(
+               "ip link set mtu %u dev %s",
+               hTunnel->nMTU,
+               g_aiccu->ipv6_interface);
+
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ip tunnel change %s ttl 64",
+                       g_aiccu->ipv6_interface);
+       }
+       else
+       {
+               /* Add a LinkLocal address for AYIYA tunnels */
+               aiccu_exec(
+                       "ip -6 addr add %s/%u dev %s",
+                       hTunnel->sIPv6_LinkLocal,
+                       64,
+                       g_aiccu->ipv6_interface);
+       }
+
+       aiccu_exec(
+               "ip -6 addr add %s/%u dev %s",
+               hTunnel->sIPv6_Local,
+               hTunnel->nIPv6_PrefixLength,
+               g_aiccu->ipv6_interface);
+
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "ip -6 ro add %s via %s dev %s",
+                       "default",
+                       hTunnel->sIPv6_POP,
+                       g_aiccu->ipv6_interface);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ip tunnel change %s local %s",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv4_Local);
+       }
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ip link set %s down",
+               g_aiccu->ipv6_interface);
+
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ip tunnel del %s",
+                       g_aiccu->ipv6_interface);
+       }
+}
+
diff --git a/common/aiccu_openbsd.c b/common/aiccu_openbsd.c
new file mode 100755 (executable)
index 0000000..0fe1c96
--- /dev/null
@@ -0,0 +1,88 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_openbsd.c - OpenBSD
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_openbsd.c,v 1.11 2007-01-07 16:37:50 jeroen Exp $
+ $Date: 2007-01-07 16:37:50 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s tunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+
+       aiccu_exec(
+               "ifconfig %s up",
+               g_aiccu->ipv6_interface);
+
+       aiccu_exec(
+               "ifconfig %s mtu %u",
+               g_aiccu->ipv6_interface,
+               hTunnel->nMTU);
+
+       if (hTunnel->uses_tundev == 1)
+       {
+               aiccu_exec(
+                       "ifconfig %s inet6 %s prefixlen 64 alias",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv6_LinkLocal);
+       }
+
+       aiccu_exec(
+               "ifconfig %s inet6 %s %s prefixlen 128 alias",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv6_Local,
+               hTunnel->sIPv6_POP);
+
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       aiccu_exec(
+               "/sbin/ifconfig %s tunnel %s %s",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv4_Local,
+               hTunnel->sIPv4_POP);
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "ifconfig %s deletetunnel",
+                       g_aiccu->ipv6_interface);
+       }
+}
+
diff --git a/common/aiccu_openbsd2.c b/common/aiccu_openbsd2.c
new file mode 100644 (file)
index 0000000..3f3c03c
--- /dev/null
@@ -0,0 +1,90 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_openbsd2.c - OpenBSD 2.7-2.9
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_openbsd2.c,v 1.7 2007-01-07 16:37:50 jeroen Exp $
+ $Date: 2007-01-07 16:37:50 $
+
+ Original version provided by Wouter Van Hemel
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s giftunnel %s %s",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+
+       aiccu_exec(
+               "ifconfig %s up",
+               g_aiccu->ipv6_interface);
+
+       aiccu_exec(
+               "ifconfig %s mtu %u",
+               g_aiccu->ipv6_interface,
+               hTunnel->nMTU);
+
+       if (hTunnel->uses_tundev == 1)
+       {
+               aiccu_exec(
+                       "ifconfig %s inet6 %s prefixlen 64 alias",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv6_LinkLocal);
+       }
+
+       aiccu_exec(
+               "ifconfig %s inet6 %s %s prefixlen 128 alias",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv6_Local,
+               hTunnel->sIPv6_POP);
+
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       aiccu_exec(
+               "/sbin/ifconfig %s giftunnel %s %s",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv4_Local,
+               hTunnel->sIPv4_POP);
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+
+       aiccu_exec(
+               "ifconfig %s inet6 %s %s prefixlen 128 -alias",
+               g_aiccu->ipv6_interface,
+               hTunnel->sIPv6_Local,
+               hTunnel->sIPv6_POP);
+
+}
+
diff --git a/common/aiccu_sunos.c b/common/aiccu_sunos.c
new file mode 100755 (executable)
index 0000000..c1f2cc9
--- /dev/null
@@ -0,0 +1,74 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_sunos.c - Sun Solaris / SunOS
+
+ ipv6_interface has to be eg ip.tun0
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_sunos.c,v 1.3 2006-07-23 14:13:57 jeroen Exp $
+ $Date: 2006-07-23 14:13:57 $
+**********************************************************/
+
+#include "aiccu.h"
+
+bool aiccu_os_install(void)
+{
+       return true;
+}
+
+bool aiccu_os_setup(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s inet6 plumb tsrc %s tdst %s up",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+
+               aiccu_exec(
+                       "ifconfig %s inet6 addif %s %s up",
+                       g_aiccu->ipv6_interface,
+                       hTunnel->sIPv6_Local,
+                       hTunnel->sIPv6_POP);
+       }
+       else
+       {
+               dolog(LOG_DEBUG, "There is no Solaris support for tun-devices yet");
+               exit(-1);
+       }
+
+       if (g_aiccu->defaultroute)
+       {
+               aiccu_exec(
+                       "route add -inet6 %s %s",
+                       "default",
+                       hTunnel->sIPv6_POP);
+       }
+
+       return true;
+}
+
+void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel)
+{
+       if (hTunnel->uses_tundev == 0)
+       {
+               aiccu_exec(
+                       "/sbin/ifconfig %s inet6 plumb tsrc %s tdst %s up",
+                       g_aiccu->ipv6_interface,
+                       strcmp(hTunnel->sIPv4_Local, "heartbeat") == 0 ? "0.0.0.0" : hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP);
+       }
+}
+
+void aiccu_os_delete(struct TIC_Tunnel *hTunnel)
+{
+       hTunnel = hTunnel;
+       aiccu_exec(
+               "ifconfig %s down",
+               g_aiccu->ipv6_interface);
+}
+
diff --git a/common/aiccu_test.c b/common/aiccu_test.c
new file mode 100755 (executable)
index 0000000..25bbdb2
--- /dev/null
@@ -0,0 +1,179 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/aiccu_test.c - AICCU Test function
+***********************************************************
+ $Author: jeroen $
+ $Id: aiccu_test.c,v 1.9 2007-01-15 12:00:46 jeroen Exp $
+ $Date: 2007-01-15 12:00:46 $
+**********************************************************/
+
+#include "aiccu.h"
+
+#ifndef _WIN32
+#define PING4 "ping -c %d -v %s 2>&1"
+#define PING6 "ping6 -c %d -v %s 2>&1"
+#define TRACEROUTE4 "traceroute %s 2>&1"
+#define TRACEROUTE6 "traceroute6 %s 2>&1"
+#else
+#define PING4 "ping -4 -n %d %s"
+#define PING6 "ping -6 -n %d %s"
+#define TRACEROUTE4 "tracert %s"
+#define TRACEROUTE6 "tracert6 %s"
+#endif
+
+void system_arg(const char *fmt, ...);
+void system_arg(const char *fmt, ...)
+{
+       char    buf[1024];
+       int     ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+       va_end(ap);
+
+       fflush(stdout);
+       ret = system(buf);
+       if (ret == -1) dolog(LOG_WARNING, "Execution of \"%s\" failed!? (Please check if the command is available)\n", buf);
+}
+
+#define PINGCOUNT 3
+
+bool test_ask(bool automatic);
+bool test_ask(bool automatic)
+{
+       char buf[100];
+
+       if (!g_aiccu->running) return false;
+
+       printf("\n######\n");
+       printf("\n");
+
+       if (automatic) return true;
+       
+       printf("Did this work? [Y/n] ");
+
+       if (fgets(buf, sizeof(buf), stdin) == NULL) return false;
+
+       printf("\n");
+
+       return (buf[0] == 'N' || buf[0] == 'n' ? false : true);
+}
+
+void aiccu_os_test(struct TIC_Tunnel *hTunnel, bool automatic)
+{
+       unsigned int t = 1;
+       unsigned int tottests = 8;
+
+       /* Make sure we have a correct local IPv4 address for some tests */
+       if (strcmp(hTunnel->sType, "6in4-static") != 0)
+       {
+               heartbeat_socket(NULL, 0, "",
+                       &hTunnel->sIPv4_Local,
+                       hTunnel->sIPv4_POP,
+                       NULL);
+       }
+
+       if (!g_aiccu->running) return;
+
+       printf("#######\n");
+       printf("####### AICCU Quick Connectivity Test\n");
+       printf("#######\n\n");
+
+       printf("####### [%u/%u] Ping the IPv4 Local/Your Outer Endpoint (%s)\n",
+               t++, tottests, hTunnel->sIPv4_Local);
+       printf("### This should return so called 'echo replies'\n");
+       printf("### If it doesn't then check your firewall settings\n");
+       printf("### Your local endpoint should always be pingable\n");
+       printf("### It could also indicate problems with your IPv4 stack\n");
+       printf("\n");
+       system_arg(PING4, PINGCOUNT, hTunnel->sIPv4_Local);
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("####### [%u/%u] Ping the IPv4 Remote/PoP Outer Endpoint (%s)\n",
+               t++, tottests, hTunnel->sIPv4_POP);
+       printf("### These pings should reach the PoP and come back to you\n");
+       printf("### In case there are problems along the route between your\n");
+       printf("### host and the PoP this could not return replies\n");
+       printf("### Check your firewall settings if problems occur\n");
+       printf("\n");
+       system_arg(PING4, PINGCOUNT, hTunnel->sIPv4_POP);
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("####### [%u/%u] Traceroute to the PoP (%s) over IPv4\n",
+               t++, tottests, hTunnel->sIPv4_POP);
+       printf("### This traceroute should reach the PoP\n");
+       printf("### In case this traceroute fails then you have no connectivity\n");
+       printf("### to the PoP and this is most probably the problem\n");
+       printf("\n");
+       system_arg(TRACEROUTE4, hTunnel->sIPv4_POP);
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("###### [%u/%u] Checking if we can ping IPv6 localhost (::1)\n",
+               t++, tottests);
+       printf("### This confirms if your IPv6 is working\n");
+       printf("### If ::1 doesn't reply then something is wrong with your IPv6 stack\n");
+       printf("\n");
+       system_arg(PING6, PINGCOUNT, "::1");
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("###### [%u/%u] Ping the IPv6 Local/Your Inner Tunnel Endpoint (%s)\n",
+               t++, tottests, hTunnel->sIPv6_Local);
+       printf("### This confirms that your tunnel is configured\n");
+       printf("### If it doesn't reply then check your interface and routing tables\n");
+       printf("\n");
+       system_arg(PING6, PINGCOUNT, hTunnel->sIPv6_Local);
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("###### [%u/%u] Ping the IPv6 Remote/PoP Inner Tunnel Endpoint (%s)\n",
+               t++, tottests, hTunnel->sIPv6_POP);
+       printf("### This confirms the reachability of the other side of the tunnel\n");
+       printf("### If it doesn't reply then check your interface and routing tables\n");
+       printf("### Don't forget to check your firewall of course\n");
+       printf("### If the previous test was succesful then this could be both\n");
+       printf("### a firewalling and a routing/interface problem\n");
+       printf("\n");
+       system_arg(PING6, PINGCOUNT, hTunnel->sIPv6_POP);
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("###### [%u/%u] Traceroute6 to the central SixXS machine (noc.sixxs.net)\n",
+               t++, tottests);
+       printf("### This confirms that you can reach the central machine of SixXS\n");
+       printf("### If that one is reachable you should be able to reach most IPv6 destinations\n");
+       printf("### Also check http://www.sixxs.net/ipv6calc/ which should show an IPv6 connection\n");
+       printf("### If your browser supports IPv6 and uses it of course.\n");
+       printf("\n");
+       system_arg(TRACEROUTE6, "noc.sixxs.net");
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("###### [%u/%u] Traceroute6 to (www.kame.net)\n",
+               t++, tottests);
+       printf("### This confirms that you can reach a Japanese IPv6 destination\n");
+       printf("### If that one is reachable you should be able to reach most IPv6 destinations\n");
+       printf("### You should also check http://www.kame.net which should display\n");
+       printf("### a animated kame (turtle), of course only when your browser supports and uses IPv6\n");
+       printf("\n");
+       system_arg(TRACEROUTE6, "www.kame.net");
+       if (!test_ask(automatic) || !g_aiccu->running) return;
+
+       printf("###### ACCU Quick Connectivity Test (done)\n\n");
+
+       printf("### Either the above all works and gives no problems\n");
+       printf("### or it shows you where what goes wrong\n");
+       printf("### Check the SixXS FAQ (http://www.sixxs.net/faq/\n");
+       printf("### for more information and possible solutions or hints\n");
+       printf("### Don't forget to check the Forums (http://www.sixxs.net/forum/)\n");
+       printf("### for a helping hand.\n");
+       printf("### Passing the output of 'aiccu autotest >aiccu.log' is a good idea.\n");
+
+       if (!automatic)
+       {
+               /* Wait for a keypress */
+               printf("\n\n*** press a key to continue ***\n");
+               getchar();
+       }
+}
+
diff --git a/common/ayiya.c b/common/ayiya.c
new file mode 100755 (executable)
index 0000000..f4ed0aa
--- /dev/null
@@ -0,0 +1,473 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/ayiya.c - AYIYA - Anything In Anything
+***********************************************************
+ $Author: jeroen $
+ $Id: ayiya.c,v 1.15 2007-01-07 16:17:48 jeroen Exp $
+ $Date: 2007-01-07 16:17:48 $
+**********************************************************/
+
+#include "aiccu.h"
+#include "ayiya.h"
+#include "tic.h"
+#include "tun.h"
+
+struct pseudo_ayh
+{
+       struct ayiyahdr ayh;
+       struct in6_addr identity;
+       sha1_byte       hash[SHA1_DIGEST_LENGTH];
+       char            payload[2048];
+};
+
+struct in_addr         ayiya_ipv4_pop;                 /* IPv4 remote endpoint */
+struct in6_addr                ayiya_ipv6_local,               /* IPv6 local  endpoint */
+                       ayiya_ipv6_pop;                 /* IPv6 remote endpoint */
+sha1_byte              ayiya_hash[SHA1_DIGEST_LENGTH]; /* SHA1 Hash of the shared secret. */
+
+TLSSOCKET ayiya_socket = NULL;
+
+static const char reader_name[]        = "tundev->tun";
+static const char writer_name[]        = "tun->tundev";
+static const char beat_name[]  = "beat";
+
+void ayiya_log(int level, const char *what, struct sockaddr_storage *clientaddr, socklen_t addrlen, const char *fmt, ...);
+void ayiya_log(int level, const char *what, struct sockaddr_storage *clientaddr, socklen_t addrlen, const char *fmt, ...)
+{
+       char    buf[1024];
+       char    clienthost[NI_MAXHOST];
+       char    clientservice[NI_MAXSERV];
+       va_list ap;
+
+       /* Clear them just in case */
+       memset(buf, 0, sizeof(buf));
+       memset(clienthost, 0, sizeof(clienthost));
+       memset(clientservice, 0, sizeof(clientservice));
+
+       if (clientaddr)
+       {
+               int ret;
+               ret = getnameinfo((struct sockaddr *)clientaddr, addrlen,
+                       clienthost, sizeof(clienthost),
+                       clientservice, sizeof(clientservice),
+                       NI_NUMERICHOST|NI_NUMERICSERV);
+               if (ret != 0)
+               {
+                       dolog(LOG_ERR, "ayiya_log() getnameinfo() ret: %d, errno: %u, %s\n", ret, errno, strerror(errno));
+               }
+       }
+
+       /* Print the host+port this is coming from */
+       snprintf(buf, sizeof(buf), "[AYIYA-%s]%s%s%s%s : ",
+               what,
+               clientaddr ? " [" : "",
+               clientaddr ? clienthost : "" ,
+               clientaddr ? "]:" : "",
+               clientservice ? clientservice : "");
+
+       /* Print the log message behind it */
+       va_start(ap, fmt);
+       vsnprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), fmt, ap);
+       va_end(ap);
+       
+       /* Actually Log it */
+       dolog(level, buf);
+}
+
+/* Tun -> Socket */
+void ayiya_reader(char *buf, unsigned int length);
+void ayiya_reader(char *buf, unsigned int length)
+{
+       struct pseudo_ayh       *s = (struct pseudo_ayh *)buf, s2;
+       int                     lenout;
+       SHA_CTX                 sha1;
+       sha1_byte               hash[SHA1_DIGEST_LENGTH];
+       struct sockaddr_in      target;
+
+       /* We tunnel over IPv4 */
+       memcpy(&target.sin_addr, &ayiya_ipv4_pop, sizeof(target.sin_addr));
+       target.sin_family = AF_INET;
+       target.sin_port = htons(atoi(AYIYA_PORT));
+       
+       /* Prefill some standard AYIYA values */
+       memset(&s, 0, sizeof(s));
+       s2.ayh.ayh_idlen        = 4;                    /* 2^4 = 16 bytes = 128 bits (IPv6 address) */
+       s2.ayh.ayh_idtype       = ayiya_id_integer;
+       s2.ayh.ayh_siglen       = 5;                    /* 5*4 = 20 bytes = 160 bits (SHA1) */
+       s2.ayh.ayh_hshmeth      = ayiya_hash_sha1;
+       s2.ayh.ayh_autmeth      = ayiya_auth_sharedsecret;
+       s2.ayh.ayh_opcode       = ayiya_op_forward;
+       s2.ayh.ayh_nextheader   = IPPROTO_IPV6;
+
+       /* Our IPv6 side of this tunnel */
+       memcpy(&s2.identity, &ayiya_ipv6_local, sizeof(s2.identity));
+
+       /* The payload */
+       memcpy(&s2.payload, buf, length);
+
+       /* Fill in the current time */
+       s2.ayh.ayh_epochtime = htonl((u_long)time(NULL));
+
+       /*
+        * The hash of the shared secret needs to be in the
+        * spot where we later put the complete hash
+        */
+       memcpy(&s2.hash, ayiya_hash, sizeof(s2.hash));
+
+       /* Generate a SHA1 */
+       SHA1_Init(&sha1);
+       /* Hash the complete AYIYA packet */
+       SHA1_Update(&sha1, (sha1_byte *)&s2, sizeof(s2)-sizeof(s2.payload)+length);
+       /* Store the hash in the packets hash */
+       SHA1_Final(hash, &sha1);
+
+       /* Store the hash in the actual packet */
+       memcpy(&s2.hash, &hash, sizeof(s2.hash));
+
+       /* Send it onto the network */
+       length = sizeof(s2)-sizeof(s2.payload)+length;
+#if defined(_FREEBSD) || defined(_DFBSD) || defined(_OPENBSD) || defined(_DARWIN) || defined(_NETBSD)
+       lenout = send(ayiya_socket->socket, (const char *)&s2, length, 0);
+#else
+       lenout = sendto(ayiya_socket->socket, (const char *)&s2, length, 0, (struct sockaddr *)&target, sizeof(target));
+#endif
+       if (lenout < 0)
+       {
+               ayiya_log(LOG_ERR, reader_name, NULL, 0, "Error (%d) while sending %u bytes to network: %s (%d)\n", lenout, length, strerror(errno), errno);
+       }
+       else if (length != (unsigned int)lenout)
+       {
+               ayiya_log(LOG_ERR, reader_name, NULL, 0, "Only %u of %u bytes sent to network: %s (%s)\n", lenout, length, strerror(errno), errno);
+       }
+}
+
+struct tun_reader ayiya_tun = { (TUN_PROCESS)ayiya_reader };
+
+/* Socket -> Tun */
+#ifndef _WIN32
+void *ayiya_writer(void UNUSED *arg);
+void *ayiya_writer(void UNUSED *arg)
+#else
+DWORD WINAPI ayiya_writer(LPVOID arg);
+DWORD WINAPI ayiya_writer(LPVOID arg)
+#endif
+{
+       unsigned char           buf[2048];
+       struct pseudo_ayh       *s = (struct pseudo_ayh *)buf;
+       struct sockaddr_storage ci;
+       socklen_t               cl;
+       int                     i, n;
+       unsigned int            payloadlen = 0;
+       SHA_CTX                 sha1;
+       sha1_byte               their_hash[SHA1_DIGEST_LENGTH],
+                               our_hash[SHA1_DIGEST_LENGTH];
+
+       ayiya_log(LOG_INFO, writer_name, NULL, 0, "(Socket to TUN) started\n");
+
+       /* Tun/TAP device is now running */
+       g_aiccu->tunrunning = true;
+
+       while (true)
+       {
+               cl = sizeof(ci);
+               memset(buf, 0, sizeof(buf));
+               n = recvfrom(ayiya_socket->socket, (char *)buf, sizeof(buf), 0, (struct sockaddr *)&ci, &cl);
+
+               if (n < 0) continue;
+
+               if (n < (int)sizeof(struct ayiyahdr))
+               {
+                       ayiya_log(LOG_WARNING, writer_name, &ci, cl, "Received packet is too short");
+                       continue;
+               }
+
+               if (    s->ayh.ayh_idlen != 4 ||
+                       s->ayh.ayh_idtype != ayiya_id_integer ||
+                       s->ayh.ayh_siglen != 5 ||
+                       s->ayh.ayh_hshmeth != ayiya_hash_sha1 ||
+                       s->ayh.ayh_autmeth != ayiya_auth_sharedsecret ||
+                       (s->ayh.ayh_nextheader != IPPROTO_IPV6 &&
+                        s->ayh.ayh_nextheader != IPPROTO_NONE) ||
+                       (s->ayh.ayh_opcode != ayiya_op_forward &&
+                        s->ayh.ayh_opcode != ayiya_op_echo_request &&
+                        s->ayh.ayh_opcode != ayiya_op_echo_request_forward))
+               {
+                       /* Invalid AYIYA packet */
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "Dropping invalid AYIYA packet\n");
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "idlen:   %u != %u\n", s->ayh.ayh_idlen, 4);
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "idtype:  %u != %u\n", s->ayh.ayh_idtype, ayiya_id_integer);
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "siglen:  %u != %u\n", s->ayh.ayh_siglen, 5);
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "hshmeth: %u != %u\n", s->ayh.ayh_hshmeth, ayiya_hash_sha1);
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "autmeth: %u != %u\n", s->ayh.ayh_autmeth, ayiya_auth_sharedsecret);
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "nexth  : %u != %u || %u\n", s->ayh.ayh_nextheader, IPPROTO_IPV6, IPPROTO_NONE);
+                       ayiya_log(LOG_ERR, writer_name, &ci, cl, "opcode : %u != %u || %u || %u\n", s->ayh.ayh_opcode, ayiya_op_forward, ayiya_op_echo_request, ayiya_op_echo_request_forward);
+                       continue;
+               }
+
+               if (memcmp(&s->identity, &ayiya_ipv6_pop, sizeof(s->identity)) != 0)
+               {
+                       memset(buf, 0, sizeof(buf));
+                       inet_ntop(AF_INET6, &s->identity, (char *)&buf, sizeof(buf));
+                       ayiya_log(LOG_WARNING, writer_name, &ci, cl, "Received packet from a wrong identity \"%s\"\n", buf);
+                       continue;
+               }
+       
+               /* Verify the epochtime */
+               i = tic_checktime(ntohl(s->ayh.ayh_epochtime));
+               if (i != 0)
+               {
+                       memset(buf, 0, sizeof(buf));
+                       inet_ntop(AF_INET6, &s->identity, (char *)&buf, sizeof(buf));
+                       ayiya_log(LOG_WARNING, writer_name, &ci, cl, "Time is %d seconds off for %s\n", i, buf);
+                       continue;
+               }
+       
+               /* How long is the payload? */
+               payloadlen = n - (sizeof(*s) - sizeof(s->payload));
+       
+               /* Save their hash */
+               memcpy(&their_hash, &s->hash, sizeof(their_hash));
+
+               /* Copy in our SHA1 hash */
+               memcpy(&s->hash, &ayiya_hash, sizeof(s->hash));
+
+               /* Generate a SHA1 of the header + identity + shared secret */
+               SHA1_Init(&sha1);
+               /* Hash the Packet */
+               SHA1_Update(&sha1, (sha1_byte *)s, n);
+               /* Store the hash */
+               SHA1_Final(our_hash, &sha1);
+
+               memcpy(&s->hash, &our_hash, sizeof(s->hash));
+
+               /* Compare the SHA1's */
+               if (memcmp(&their_hash, &our_hash, sizeof(their_hash)) != 0)
+               {
+                       ayiya_log(LOG_WARNING, writer_name, &ci, cl, "Incorrect Hash received\n");
+                       continue;
+               }
+
+               if (s->ayh.ayh_nextheader == IPPROTO_IPV6)
+               {
+                       /* Verify that this is really IPv6 */
+                       if (s->payload[0] >> 4 != 6)
+                       {
+                               ayiya_log(LOG_ERR, writer_name, &ci, cl, "Received packet didn't start with a 6, thus is not IPv6\n");
+                               continue;
+                       }
+
+                       /* Forward the packet to the kernel */
+                       tun_write(s->payload, payloadlen);
+               }
+       }
+
+       /* Tun/TAP device is not running anymore */
+       g_aiccu->tunrunning = false;
+
+#ifndef _WIN32
+       return NULL;
+#else
+       return 0;
+#endif
+}
+
+/* Construct a beat and send it outwards */
+void ayiya_beat(void)
+{
+       SHA_CTX                 sha1;
+       sha1_byte               hash[SHA1_DIGEST_LENGTH];
+       struct sockaddr_in      target;
+       struct pseudo_ayh       s;
+       int                     lenout, n;
+
+       /* We tunnel over IPv4 */
+       memcpy(&target.sin_addr, &ayiya_ipv4_pop, sizeof(target.sin_addr));
+       target.sin_family       = AF_INET;
+       target.sin_port         = htons(atoi(AYIYA_PORT));
+
+       /* Prefill some standard AYIYA values */
+       memset(&s, 0, sizeof(s));
+       s.ayh.ayh_idlen         = 4;                    /* 2^4 = 16 bytes = 128 bits (IPv6 address) */
+       s.ayh.ayh_idtype        = ayiya_id_integer;
+       s.ayh.ayh_siglen        = 5;                    /* 5*4 = 20 bytes = 160 bits (SHA1) */
+       s.ayh.ayh_hshmeth       = ayiya_hash_sha1;
+       s.ayh.ayh_autmeth       = ayiya_auth_sharedsecret;
+       s.ayh.ayh_opcode        = ayiya_op_noop;
+       s.ayh.ayh_nextheader    = IPPROTO_NONE;
+
+       /* Our IPv6 side of this tunnel */
+       memcpy(&s.identity, &ayiya_ipv6_local, sizeof(s.identity));
+
+       /* No Payload */
+
+       /* Fill in the current time */
+       s.ayh.ayh_epochtime = htonl((u_long)time(NULL));
+
+       /* Our IPv6 side of this tunnel */
+       memcpy(&s.identity, &ayiya_ipv6_local, sizeof(s.identity));
+
+       /*
+        * The hash of the shared secret needs to be in the
+        * spot where we later put the complete hash
+        */
+        memcpy(&s.hash, ayiya_hash, sizeof(s.hash));
+
+       /* Generate a SHA1 */
+       SHA1_Init(&sha1);
+       /* Hash the complete AYIYA packet */
+       SHA1_Update(&sha1, (sha1_byte *)&s, sizeof(s)-sizeof(s.payload));
+       /* Store the hash in the packets hash */
+       SHA1_Final(hash, &sha1);
+
+       /* Store the hash in the actual packet */
+       memcpy(&s.hash, &hash, sizeof(s.hash));
+
+       /* Send it onto the network */
+       n = sizeof(s)-sizeof(s.payload);
+#if defined(_FREEBSD) || defined(_DFBSD) || defined(_OPENBSD) || defined(_DARWIN) || defined(_NETBSD)
+       lenout = send(ayiya_socket->socket, (const char *)&s, (unsigned int)n, 0);
+#else
+       lenout = sendto(ayiya_socket->socket, (const char *)&s, (unsigned int)n, 0, (struct sockaddr *)&target, sizeof(target));
+#endif
+       if (lenout < 0)
+       {
+               ayiya_log(LOG_ERR, beat_name, NULL, 0, "Error (%d) while sending %u bytes sent to network: %s (%d)\n", lenout, n, strerror(errno), errno);
+       }
+       else if (n != lenout)
+       {
+               ayiya_log(LOG_ERR, beat_name, NULL, 0, "Only %u of %u bytes sent to network: %s (%d)\n", lenout, n, strerror(errno), errno);
+       }
+}
+
+bool ayiya(struct TIC_Tunnel *hTunnel)
+{
+        SHA_CTX                        sha1;
+       struct addrinfo hints, *res, *ressave;
+#ifndef _WIN32
+       pthread_t               thread;
+#else
+       DWORD                   pID;
+       HANDLE                  h;
+#endif
+
+       /* Setup the tunnel */
+       if (!tun_start(&ayiya_tun)) return false;
+
+       /* Resolve hTunnel entries */
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET;
+       hints.ai_socktype = SOCK_DGRAM;
+
+       if (getaddrinfo(hTunnel->sIPv4_POP, AYIYA_PORT, &hints, &res) != 0)
+       {
+               dolog(LOG_ERR, "Couldn't resolve PoP IPv4 %s\n", hTunnel->sIPv4_POP);
+               return false;
+       }
+       ressave = res;
+        while (res)
+        {
+               if (res->ai_family != AF_INET)
+               {
+                       res = res->ai_next;
+                       continue;
+               }
+               memcpy(&ayiya_ipv4_pop, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4);
+               break;
+        }
+        freeaddrinfo(ressave);
+        if (res == NULL)
+        {
+               dolog(LOG_ERR, "No valid IPv4 address for PoP address %s could be found\n", hTunnel->sIPv4_POP);
+               return false;
+        }
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET6;
+       if (getaddrinfo(hTunnel->sIPv6_Local, NULL, &hints, &res) != 0)
+       {
+               dolog(LOG_ERR, "Couldn't resolve Local IPv6 %s\n", hTunnel->sIPv6_Local);
+               return false;
+       }
+       ressave = res;
+        while (res)
+        {
+               if (res->ai_family != AF_INET6)
+               {
+                       res = res->ai_next;
+                       continue;
+               }
+               memcpy(&ayiya_ipv6_local, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16);
+               break;
+        }
+        freeaddrinfo(ressave);
+        if (res == NULL)
+        {
+               dolog(LOG_ERR, "No valid IPv6 address for Local IPv6 address %s could be found\n", hTunnel->sIPv6_Local);
+               return false;
+        }
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET6;
+       if (getaddrinfo(hTunnel->sIPv6_POP, NULL, &hints, &res) != 0)
+       {
+               dolog(LOG_ERR, "Couldn't resolve Local IPv6 %s\n", hTunnel->sIPv6_POP);
+               return false;
+       }
+       ressave = res;
+        while (res)
+        {
+               if (res->ai_family != AF_INET6)
+               {
+                       res = res->ai_next;
+                       continue;
+               }
+               memcpy(&ayiya_ipv6_pop, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16);
+               break;
+        }
+        freeaddrinfo(ressave);
+        if (res == NULL)
+        {
+               dolog(LOG_ERR, "No valid IPv6 address for POP IPv6 address %s could be found\n", hTunnel->sIPv6_POP);
+               return false;
+        }
+
+       if (!hTunnel->sPassword)
+       {
+               dolog(LOG_ERR, "A password is required for using AYIYA tunnels\n");
+               return false;
+       }
+
+       /* Generate a SHA1 of the shared secret */
+       SHA1_Init(&sha1);
+       SHA1_Update(&sha1, (const sha1_byte *)hTunnel->sPassword, (unsigned int)strlen(hTunnel->sPassword));
+       SHA1_Final(ayiya_hash, &sha1);
+
+       /* Setup listening socket */
+       ayiya_socket = connect_client(hTunnel->sIPv4_POP , AYIYA_PORT, AF_INET, SOCK_DGRAM);
+       if (!ayiya_socket)
+       {
+               ayiya_log(LOG_ERR, "start", NULL, 0, "Connection error:: could not create connection to AYIYA server\n");
+               return false;
+       }
+
+       /* Let AICCU configure the thing */
+       if (!aiccu_setup(hTunnel, false))
+       {
+               return false;
+       }
+
+       /* Show that we have started */
+       ayiya_log(LOG_INFO, "start", NULL, 0, "Anything in Anything (%s)\n", AYIYA_VERSION);
+
+       /* Launch a thread for reader */
+#ifndef _WIN32
+       pthread_create(&thread, NULL, ayiya_writer, (void *)hTunnel);
+#else
+       h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ayiya_writer, hTunnel, 0, &pID);
+#endif
+
+       return true;
+}
diff --git a/common/ayiya.h b/common/ayiya.h
new file mode 100755 (executable)
index 0000000..0df55ce
--- /dev/null
@@ -0,0 +1,92 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/ayiya.c - AYIYA - Anything In Anything
+***********************************************************
+ $Author: jeroen $
+ $Id: ayiya.h,v 1.10 2006-07-13 19:33:39 jeroen Exp $
+ $Date: 2006-07-13 19:33:39 $
+**********************************************************/
+
+#ifndef AYIYA_H
+#define AYIYA_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#include "common.h"
+#include "tic.h"
+
+/* Anything In Anything - AYIYA (uses UDP in our case) */
+#define AYIYA_PORT     "5072"
+/*#define AYIYA_PORT   "8374"*/
+
+/*
+ * AYIYA version (which document this should conform to)
+ * Per draft-massar-v6ops-ayiya-02 (July 2004)
+ */
+#define AYIYA_VERSION  "draft-02"
+
+enum ayiya_identities
+{
+       ayiya_id_none                   = 0x0,  /* None */
+       ayiya_id_integer                = 0x1,  /* Integer */
+       ayiya_id_string                 = 0x2   /* ASCII String */
+};
+
+enum ayiya_hash
+{
+       ayiya_hash_none                 = 0x0,  /* No hash */
+       ayiya_hash_md5                  = 0x1,  /* MD5 Signature */
+       ayiya_hash_sha1                 = 0x2,  /* SHA1 Signature */
+       ayiya_hash_umac                 = 0x3   /* UMAC Signature (UMAC: Message Authentication Code using Universal Hashing / draft-krovetz-umac-04.txt */
+};
+
+enum ayiya_auth
+{
+       ayiya_auth_none                 = 0x0,  /* No authentication */
+       ayiya_auth_sharedsecret         = 0x1,  /* Shared Secret */
+       ayiya_auth_pgp                  = 0x2   /* Public/Private Key */
+};
+
+enum ayiya_opcode
+{
+       ayiya_op_noop                   = 0x0,  /* No Operation */
+       ayiya_op_forward                = 0x1,  /* Forward */
+       ayiya_op_echo_request           = 0x2,  /* Echo Request */
+       ayiya_op_echo_request_forward   = 0x3,  /* Echo Request and Forward */
+       ayiya_op_echo_response          = 0x4,  /* Echo Response */
+       ayiya_op_motd                   = 0x5,  /* MOTD */
+       ayiya_op_query_request          = 0x6,  /* Query Request */
+       ayiya_op_query_response         = 0x7   /* Query Response */
+};
+
+struct ayiyahdr
+{
+#if BYTE_ORDER == BIG_ENDIAN
+       uint32_t        ayh_idlen:  4;          /* Identity Length */
+       uint32_t        ayh_idtype: 4;          /* Identity Type */
+       uint32_t        ayh_siglen: 4;          /* Signature Length */
+       uint32_t        ayh_hshmeth:4;          /* Hashing Method */
+       uint32_t        ayh_autmeth:4;          /* Authentication Method */
+       uint32_t        ayh_opcode: 4;          /* Operation Code */
+       uint32_t        ayh_nextheader:8;       /* Next Header (PROTO_*) */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+       uint32_t        ayh_idtype: 4;          /* Identity Type */
+       uint32_t        ayh_idlen:  4;          /* Identity Length */
+       uint32_t        ayh_hshmeth:4;          /* Hashing Method */
+       uint32_t        ayh_siglen: 4;          /* Signature Length */
+       uint32_t        ayh_opcode: 4;          /* Operation Code */
+       uint32_t        ayh_autmeth:4;          /* Authentication Method */
+       uint32_t        ayh_nextheader:8;       /* Next Header (PROTO_*) */
+#else
+#error unsupported endianness!
+#endif
+       uint32_t        ayh_epochtime;          /* Time in seconds since "00:00:00 1970-01-01 UTC" */
+};
+
+/* Functions */
+bool ayiya(struct TIC_Tunnel *hTunnel);
+void ayiya_beat(void);
+
+#endif /* AYIYA_H */
+
diff --git a/common/common.c b/common/common.c
new file mode 100755 (executable)
index 0000000..488c145
--- /dev/null
@@ -0,0 +1,739 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/common.c - Common Functions
+***********************************************************
+ $Author: jeroen $
+ $Id: common.c,v 1.14 2006-12-21 14:08:50 jeroen Exp $
+ $Date: 2006-12-21 14:08:50 $
+**********************************************************/
+
+/* Dirty dependency for Windows:GUI version */
+#ifdef _WIN32
+#ifndef AICCU_CONSOLE
+#include "../windows-gui/stdafx.h"
+#include "../windows-gui/AICCUApp.h"
+extern CAICCUApp theApp;
+#endif
+#endif
+
+#include "aiccu.h"
+#include "common.h"
+
+/* getline debugging? */
+/*
+#define E(x) x
+ */
+#define E(x) {}
+
+void dologA(int level, const char *fmt, va_list ap)
+{
+#ifdef _WIN32
+       char buf[1024];
+#endif
+       /* Don't show noise */
+       if (g_aiccu && !g_aiccu->verbose && level == LOG_DEBUG) return;
+
+#ifndef _WIN32
+       if (g_aiccu && g_aiccu->daemonize > 0) vsyslog(LOG_LOCAL7|level, fmt, ap);
+       else
+       {
+               vfprintf(stderr, fmt, ap);
+               fflush(stderr);
+       }
+#else
+       vsnprintf(buf, sizeof(buf), fmt, ap);
+
+#ifndef AICCU_CONSOLE
+       /* Use the debug facility */
+       OutputDebugString(buf);
+
+       /* Store it in a log file if we are running in verbose mode */
+       if (g_aiccu && g_aiccu->verbose)
+       {
+               char    logfile[1024];
+               FILE    *f;
+
+               /* Figure out the "C:\Windows" location */
+               /* as that is where we store our configuration */
+               GetWindowsDirectory(logfile, sizeof(logfile));
+               strncat(logfile, "\\aiccu.log", sizeof(logfile));
+               f = fopen(logfile, "w+");
+               if (f)
+               {
+                       fwrite(buf, strlen(buf), 1, f);
+                       fclose(f);
+               }
+       }
+
+       /*
+        * Always store the last message
+        * which can be displayed as errors etc.
+        */
+
+       /* strip the \n */
+       if (strlen(buf) > 0) buf[strlen(buf)-1] = '\0';
+       theApp.m_sMessage = buf;
+#else
+       OutputDebugString("dolog() - ");
+       OutputDebugString(buf);
+       fprintf(stderr, "%s", buf);
+#endif /* AICCU_CONSOLE */
+#endif /* !_WIN32 */
+}
+
+void dolog(int level, const char *fmt, ...)
+{
+       va_list ap;
+       va_start(ap, fmt);
+       dologA(level, fmt, ap);
+       va_end(ap);
+}
+
+/* 
+ * Check if an address is RFC1918 based
+ * This allows us to warn the user that they are behind a NAT
+ */
+bool is_rfc1918(char *ipv4)
+{
+       unsigned int    addr = inet_addr(ipv4);
+       bool            ret = false;
+
+
+
+       ret = ( /* 10.0.0.0/8 */
+               ((addr & htonl(0xff000000)) == htonl(0x0a000000)) ||
+               /* 172.16.0.0/12 */
+               ((addr & htonl(0xfff00000)) == htonl(0xac100000)) ||
+               /* 192.168.0.0/16 */
+               ((addr & htonl(0xffff0000)) == htonl(0xc0a80000))) ? true : false;
+
+       dolog(LOG_DEBUG, "is_rfc1918(%s) = %s\n", ipv4, ret ? "yes" : "false");
+
+       return ret;
+}
+
+void sock_printf(TLSSOCKET sock, const char *fmt, ...)
+{
+       char            buf[2048];
+       unsigned int    len = 0, done = 0;
+       int             ret;
+
+       va_list ap;
+       va_start(ap, fmt);
+       /* When not a socket send it to the logs */
+       if (sock == NULL || sock->socket == -1) dologA(LOG_INFO, fmt, ap);
+       else
+       {
+               /* Format the string */
+               len = vsnprintf(buf, sizeof(buf), fmt, ap);
+
+               /* Send the line(s) over the network */
+
+               while (done < len)
+               {
+#ifdef AICCU_GNUTLS
+                       if (sock->tls_active) ret = gnutls_record_send(sock->session, &buf[done], len-done);
+                       else
+#endif
+                       ret = send(sock->socket, &buf[done], len-done, 0);
+                       
+                       if (ret > 0) done+=ret;
+                       else break;
+               }
+
+               /* Show this as debug output */
+               if (g_aiccu->verbose)
+               {
+                       /* Strip the last \n */
+                       len = (int)strlen(buf);
+                       if (len > 0) buf[len-1] = '\0';
+                       /* dump the information */
+                       dolog(LOG_DEBUG, "sock_printf()  : \"%s\"\n", buf);
+               }
+       }
+       va_end(ap);
+}
+
+extern char tic_buf[2048];
+
+/* 
+ * Read a line from a socket and store it in ubuf
+ * Note: uses internal caching, this should be the only function
+ * used to read from the sock! The internal cache is rbuf.
+ */
+int sock_getline(TLSSOCKET sock, char *rbuf, unsigned int rbuflen, unsigned int *filled, char *ubuf, unsigned int ubuflen)
+{
+       unsigned int i;
+       
+       if (!sock) return -1;
+       
+       /* A closed socket? -> clear the buffer */
+       if (sock->socket == -1)
+       {
+               memset(rbuf, 0, rbuflen);
+               *filled = 0;
+               return -1;
+       }
+
+       /* Clear the caller supplied buffer, just in case */
+       memset(ubuf, 0, ubuflen);
+
+       for (;;)
+       {
+               E(dolog(LOG_DEBUG, "gl() - Filled %d\n", *filled);)
+
+               /* Did we still have something in the buffer? */
+               if (*filled > 0)
+               {
+                       E(dolog(LOG_DEBUG, "gl() - Seeking newline\n");)
+
+                       /* Walk to the end or until we reach a \n */
+                       for (i=0; (i < (*filled-1)) && (rbuf[i] != '\n'); i++);
+
+                       E(dolog(LOG_DEBUG, "gl() - Seeking newline - end\n");)
+
+                       /* Did we find a newline? */
+                       if (rbuf[i] == '\n')
+                       {
+                               E(dolog(LOG_DEBUG, "gl() - Found newline at %i\n", i+1);)
+
+                               /* Newline with a Linefeed in front of it ? -> remove it */
+                               if (rbuf[i] == '\n' && rbuf[i-1] == '\r')
+                               {
+                                       E(dolog(LOG_DEBUG, "gl() - Removing LF\n");)
+                                       i--;
+                               }
+                               E(else dolog(LOG_DEBUG, "gl() - No LF\n");)
+
+                               /* Copy this over to the caller */
+                               memcpy(ubuf, rbuf, i);
+
+                               E(dolog(LOG_DEBUG, "gl() - Copied %d bytes from %x to %x\n", i, rbuf, ubuf);)
+
+                               /* Count the \r if it is there */
+                               if (rbuf[i] == '\r') i++;
+                               /* Count the \n */
+                               i++;
+
+                               /* filled = what is left in the buffer */
+                               *filled -= i;
+                               
+                               E(dolog(LOG_DEBUG, "gl() - %d bytes left in the buffer\n", *filled);)
+
+                               /* Now move the rest of the buffer to the front */
+                               if (*filled > 0) memmove(rbuf, &rbuf[i], *filled);
+                               else *filled = 0;
+
+                               /* Show this as debug output */
+                               if (g_aiccu->verbose) dolog(LOG_DEBUG, "sock_getline() : \"%s\"\n", ubuf);
+
+                               /* We got ourselves a line in 'buf' thus return to the caller */
+                               return i;
+                       }
+               }
+
+               E(dolog(LOG_DEBUG, "gl() - Trying to receive (max=%d)...\n", rbuflen-*filled-10);)
+
+               /* Fill the rest of the buffer */
+#ifdef AICCU_GNUTLS
+               if (sock->tls_active) i = gnutls_record_recv(sock->session, &rbuf[*filled], rbuflen-*filled-10);
+               else
+#endif
+               i = recv(sock->socket, &rbuf[*filled], rbuflen-*filled-10, 0);
+
+               E(dolog(LOG_DEBUG, "gl() - Received %d\n", i);)
+
+               /* Fail on errors */
+               if (i <= 0) return -1;
+
+               /* We got more filled space! */
+               *filled+=i;
+
+               /* Buffer overflow? */
+               if (    *filled >= (rbuflen-10) ||
+                       *filled >= (ubuflen-10) )
+               {
+                       dolog(LOG_ERR, "Buffer almost flowed over without receiving a newline\n");
+                       return -1;
+               }
+
+               /* And try again in this loop ;) */
+       }
+
+       /* Never reached */
+       return -1;
+}
+
+TLSSOCKET sock_alloc(void);
+TLSSOCKET sock_alloc(void)
+{
+#ifdef AICCU_GNUTLS
+       /* Allow connections to servers that have OpenPGP keys as well */
+       const int       cert_type_priority[3] = { GNUTLS_CRT_X509, GNUTLS_CRT_OPENPGP, 0 };
+       int             ret;
+#endif /* AICCU_GNUTLS*/
+
+       TLSSOCKET       sock;   
+
+       sock = (TLSSOCKET)malloc(sizeof(*sock));
+       if (!sock) return NULL;
+       
+       sock->socket = -1;
+
+#ifdef AICCU_GNUTLS
+       /* TLS is not active yet (use sock_gotls() for that) */
+       sock->tls_active = false;
+
+       /* Initialize TLS session */
+       ret = gnutls_init(&sock->session, GNUTLS_CLIENT);
+       if (ret != 0)
+       {
+               dolog(LOG_ERR, "TLS Init failed: %s (%d)\n", gnutls_strerror(ret), ret);
+               free(sock);
+               return NULL;
+       }
+
+       /* Use default priorities */
+       gnutls_set_default_priority(sock->session);
+       /* XXX: Return value is not documented in GNUTLS documentation! */
+
+       gnutls_certificate_type_set_priority(sock->session, cert_type_priority);
+       /* XXX: Return value is not documented in GNUTLS documentation! */
+
+       /* Configure the x509 credentials for the current session */
+       gnutls_credentials_set(sock->session, GNUTLS_CRD_CERTIFICATE, g_aiccu->tls_cred);
+       /* XXX: Return value is not documented in GNUTLS documentation! */
+
+#endif /* AICCU_GNUTLS*/
+
+       return sock;
+}
+
+void sock_free(TLSSOCKET sock)
+{
+       if (!sock) return;
+       
+#ifdef AICCU_GNUTLS
+       if (sock->tls_active)
+       {
+               sock->tls_active = false;
+               gnutls_bye(sock->session, GNUTLS_SHUT_RDWR);
+       }
+#endif /* AICCU_GNUTLS*/
+
+       if (sock->socket >= 0)
+       {
+               /* Stop communications */
+               shutdown(sock->socket, SHUT_RDWR);
+               closesocket(sock->socket);
+               sock->socket = -1;
+       }
+
+#ifdef AICCU_GNUTLS
+       gnutls_deinit(sock->session);
+#endif /* AICCU_GNUTLS*/
+
+       free(sock);
+}
+
+/* Connect this client to a server */
+TLSSOCKET connect_client(const char *hostname, const char *service, int family, int socktype)
+{
+       TLSSOCKET       sock;
+       struct addrinfo hints, *res, *ressave;
+       
+       sock = sock_alloc();
+       if (!sock) return NULL;
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = family;
+       hints.ai_socktype = socktype;
+
+       if (getaddrinfo(hostname, service, &hints, &res) != 0)
+       {
+               dolog(LOG_ERR, "Couldn't resolve host %s, service %s\n", hostname, service);
+               sock_free(sock);
+               return NULL;
+       }
+
+       ressave = res;
+
+       while (res)
+       {
+               sock->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+               if (sock->socket == -1) continue;
+               if (connect(sock->socket, res->ai_addr, (unsigned int)res->ai_addrlen) == 0) break;
+               closesocket(sock->socket);
+               sock->socket = -1;
+               res = res->ai_next;
+       }
+
+       freeaddrinfo(ressave);
+       
+       if (sock->socket == -1)
+       {
+               sock_free(sock);
+               sock = NULL;
+       }
+
+       return sock;
+}
+
+TLSSOCKET listen_server(const char *description, const char *hostname, const char *service, int family, int socktype)
+{
+       struct addrinfo hints, *res, *ressave;
+       int             n;
+       TLSSOCKET       sock;
+       socklen_t       on = 1;
+/*
+       D(dolog(LOG_DEBUG, "[%s] Trying to get socket for [%s]:%s over %s (%d) using %s (%d)\n",
+               description, hostname, service,
+               family == AF_INET ? "IPv4" : (family == AF_INET6 ? "IPv6" : "??"),
+               family,
+               socktype == IPPROTO_UDP ? "UDP" : (socktype == IPPROTO_TCP ? "TCP" : "??"),
+               socktype);)
+*/
+       sock = sock_alloc();
+       if (!sock) return NULL;
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+
+       /* AI_PASSIVE flag: the resulting address is used to bind
+          to a socket for accepting incoming connections.
+          So, when the hostname==NULL, getaddrinfo function will
+          return one entry per allowed protocol family containing
+          the unspecified address for that family. */
+
+       hints.ai_flags    = AI_PASSIVE;
+       hints.ai_family   = family;
+       hints.ai_socktype = socktype;
+
+       n = getaddrinfo(hostname, service, &hints, &res);
+       if (n < 0)
+       {
+               dolog(LOG_ERR, "[%s] listen_server setup: getaddrinfo error: %s\n", description, gai_strerror(n));
+               sock_free(sock);
+               return NULL;
+       }
+
+       ressave=res;
+
+       /* Try to open socket with each address getaddrinfo returned,
+          until we get one valid listening socket. */
+       while (res)
+       {
+               sock->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+               if (!(sock->socket < 0))
+               {
+                       setsockopt(sock->socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
+                       if (bind(sock->socket, res->ai_addr, (unsigned int)res->ai_addrlen) == 0) break;
+                       closesocket(sock->socket);
+                       sock->socket = -1;
+               }
+               res = res->ai_next;
+       }
+
+       freeaddrinfo(ressave);
+
+       if (sock->socket < 0)
+       {
+               dolog(LOG_ERR, "[%s] listen setup: socket error: could not open socket\n", description);
+               sock_free(sock);
+               return NULL;
+       }
+
+       if (listen(sock->socket, LISTEN_QUEUE) == -1)
+       {
+               dolog(LOG_ERR, "[%s] listen setup: socket error: could not listen on socket\n", description);
+               sock_free(sock);
+               return NULL;
+       }
+
+       dolog(LOG_INFO, "[%s] Listening on [%s]:%s\n", description, hostname, service);
+
+       return sock;
+}
+
+/*
+ * Put a socket into TLS mode
+ */
+#ifdef AICCU_GNUTLS
+bool sock_gotls(TLSSOCKET sock)
+{
+       int ret = 0;
+       
+       if (!sock) return false;
+       
+       if (sock->tls_active)
+       {
+               dolog(LOG_ERR, "Can't go into TLS mode twice!?\n");
+               return false;
+       }
+
+       /* Set the transport */
+       gnutls_transport_set_ptr(sock->session, (gnutls_transport_ptr)sock->socket);
+
+       /* Perform the TLS handshake */
+       ret = gnutls_handshake(sock->session);
+       if (ret < 0)
+       {
+               dolog(LOG_ERR, "TLS Handshake failed: %s (%d)\n", gnutls_strerror(ret), ret);
+               return false;
+       }
+
+       dolog(LOG_DEBUG, "TLS Handshake completed succesfully\n");
+
+       sock->tls_active = true;
+       return true;
+}
+#endif
+
+/* Count the number of fields in <s> */
+unsigned int countfields(char *s)
+{
+       int n = 1, i;
+       if (s == NULL) return 0;
+       for (i=0; s[i] != '\0'; i++) if (s[i] == ' ') n++;
+       return n;
+}
+
+/*
+ * Copy field <n> of string <s> into <buf> with a maximum of buflen
+ * First field is 1
+ */
+bool copyfield(char *s, unsigned int n, char *buf, unsigned int buflen)
+{
+       unsigned int begin = 0, i=0;
+
+       /* Clear the buffer */
+       memset(buf, 0, buflen);
+
+       while (s[i] != '\0')
+       {
+               n--;
+               begin = i;
+
+               /* Find next delimiter */
+               for (; s[i] != '\0' && s[i] != ' '; i++);
+
+               if (n == 0)
+               {
+                       i-=begin;
+                       strncpy(buf, s+begin, i > buflen ? buflen : i);
+                       /* dolog(LOG_DEBUG, "copyfield() : '%s', begin = %d, len = %d\n", buf, begin, i); */
+                       return true;
+               }
+               
+               i++;
+       }
+       dolog(LOG_WARNING, "copyfield() - Field %u didn't exist in '%s'\n", n, s);
+       return false;
+}
+
+bool parseline(char *line, const char *split, struct pl_rule *rules, void *data)
+{
+       unsigned int    r, len;
+       char            *end = NULL, *val = NULL, *p = NULL;
+       void            *store;
+
+       /* Chop off \n and \r and white space */
+       p = &line[strlen(line)-1];
+       while ( p >= line && (
+               *p == '\n' ||
+               *p == '\r' ||
+               *p == '\t' ||
+               *p == ' ')) *p-- = '\0';
+
+       /* Ignore comments and emtpy lines */
+       if (    strlen(line) == 0 ||
+               line[0] == '#' ||
+               line[0] == ';' ||
+               (line[0] == '/' && line[1] == '/'))
+       {
+               return true;
+       }
+
+       /* Get the end of the first argument */
+       p = line;
+       end = &line[strlen(line)-1];
+       /* Skip until whitespace */
+       while ( p < end &&
+               strncmp(p, split, strlen(split)) != 0) p++;
+       /* Terminate this argument */
+       *p = '\0';
+       p++;
+
+       /* Skip whitespace */
+       while ( p < end &&
+               *p == ' ' &&
+               *p == '\t') p++;
+
+       /* Start of the value */
+       val = p+(strlen(split)-1);
+
+       /* If starting with quotes, skip until next quote */
+       if (*p == '"' || *p == '\'')
+       {
+               p++;
+               /* Find next quote */
+               while (p <= end &&
+                       *p != *val &&
+                       *p != '\0') p++;
+               /* Terminate */
+               *p = '\0';
+               /* Skip the first quote */
+               val++;
+       }
+       /* Otherwise it is already terminated above */
+
+       /* Walk through all the rules */
+       for (r = 0; rules[r].type != PLRT_END; r++)
+       {
+               len = (int)strlen(rules[r].title);
+               if (strncmp(line, rules[r].title, len) != 0) continue;
+
+               store = (void *)((char *)data + rules[r].offset);
+
+               switch (rules[r].type)
+               {
+               case PLRT_STRING:
+                       if (*((char **)store)) free(*((char **)store));
+                       *((char **)store) = strdup(val);
+                       break;
+
+               case PLRT_INTEGER:
+                       *((uint32_t *)store) = atoi(val);
+                       break;
+
+               case PLRT_BOOL:
+                       if (    strcmp(val, "yes") == 0 ||
+                               strcmp(val, "true") == 0)
+                       {
+                               *((bool *)store) = true;
+                       }
+                       else if (strcmp(val, "no") == 0 ||
+                               strcmp(val, "false") == 0)
+                       {
+                               *((bool *)store) = false;
+                       }
+                       else
+                       {
+                               dolog(LOG_WARNING, "Unknown boolean value \"%s\" for option \"%s\"\n", val, rules[r].title);
+                       }
+                       break;
+
+               case PLRT_IPV4:
+                       inet_pton(AF_INET, val, store);
+                       break;
+
+               case PLRT_IPV6:
+                       inet_pton(AF_INET6, val, store);
+                       break;
+
+               case PLRT_END:
+                       return false;
+               }
+               return true;
+       }
+       return false;
+}
+
+/* 
+ * MD5 a string
+ * sSignature's size MUST be 32 bytes!
+ */
+void MD5String(const char *sString, char *sSignature, unsigned int siglen)
+{
+       struct MD5Context       md5c;
+       unsigned char           signature[16];
+       unsigned int            i;
+       
+       if (siglen < 32) return;
+
+       /* Initialize MD5 structure */
+       MD5Init(&md5c);
+       /* Calculate MD5 of the string */
+       MD5Update(&md5c, (unsigned char *)sString, (unsigned int)strlen(sString));
+       MD5Final(signature, &md5c);
+       
+       memset(sSignature, 0, siglen);
+
+       for (i=0; i < sizeof(signature); i++)
+       {
+               snprintf(&sSignature[i*2], 3, "%02x", signature[i]);
+       }
+}
+
+#ifdef _AIX
+/* AIX doesn't have vsyslog() thus we implement it here */
+void vsyslog(int priority, const char *format, va_list ap)
+{
+        char buf[1024];
+        vsnprintf(buf, sizeof(buf), format, ap);
+       syslog(priority, buf);
+}
+#endif
+
+#ifdef _WIN32
+const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
+{
+       if (af == AF_INET)
+       {
+               struct sockaddr_in in;
+               memset(&in, 0, sizeof(in));
+               in.sin_family = AF_INET;
+               memcpy(&in.sin_addr, src, sizeof(struct in_addr));
+               getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
+               return dst;
+       }
+       else if (af == AF_INET6)
+       {
+               struct sockaddr_in6 in;
+               memset(&in, 0, sizeof(in));
+               in.sin6_family = AF_INET6;
+               memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
+               getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
+               return dst;
+       }
+       return NULL;
+}
+
+int inet_pton(int af, const char *src, void *dst)
+{
+       struct addrinfo hints, *res, *ressave;
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = af;
+
+       if (getaddrinfo(src, NULL, &hints, &res) != 0)
+       {
+               dolog(LOG_ERR, "Couldn't resolve host %s\n", src);
+               return -1;
+       }
+
+       ressave = res;
+
+       while (res)
+       {
+               /* Check if AF is correct */
+               if (res->ai_family != af)
+               {
+                       res = res->ai_next;
+                       continue;
+               }
+
+               /* This is the one we want */
+               memcpy(dst, res->ai_addr, af == AF_INET6 ? sizeof(struct in_addr6) : sizeof(struct in_addr));
+
+               /* We only need one */
+               break;
+       }
+
+       freeaddrinfo(ressave);
+       return 0;
+}
+
+#endif
diff --git a/common/common.h b/common/common.h
new file mode 100755 (executable)
index 0000000..575d854
--- /dev/null
@@ -0,0 +1,417 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/common.h - Common Definitions
+***********************************************************
+ $Author: jeroen $
+ $Id: common.h,v 1.23 2007-01-11 14:50:51 jeroen Exp $
+ $Date: 2007-01-11 14:50:51 $
+**********************************************************/
+
+#ifndef AICCU_COMMON_H
+#define AICCU_COMMON_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#ifdef _DEBUG
+#define D(x) x
+#else
+#define D(x) {}
+#endif
+
+#ifndef _OPENBSD
+#ifndef _SUNOS
+#ifndef _AIX
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE
+#endif
+#endif
+#endif
+#endif
+#define __STRICT_ANSI__
+
+/* Don't deprecate strncat etc. */
+#ifdef _WIN32
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef _AIX
+#define _H_ARPA_ONAMESER_COMPAT "AICCU workaround"
+#include <net/net_globals.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#if defined(_SUNOS) || defined(_AIX) || defined(_DARWIN)
+/* Include this as it knows quite a bit about endianess */
+#include <arpa/nameser_compat.h>
+#else
+#ifndef _WIN32
+#if defined(_OPENBSD) || defined(_DFBSD) || defined(_FREEBSD) || defined(_NETBSD)
+#include <sys/endian.h>
+#else
+#include <endian.h>
+#endif
+#endif
+#endif
+
+/* For MD5 routines */
+#define __USE_BSD 1
+#include <sys/types.h>
+
+#ifndef _WIN32
+       /* Unix Specifics */
+
+#ifndef linux
+       #include <netinet/in_systm.h>
+#endif
+
+#ifdef _DARWIN
+#define _BSD_SOCKLEN_T_
+#endif
+
+       #include <sys/socket.h>
+       #include <netinet/in.h>
+       #include <netdb.h>
+       #include <unistd.h>
+       #include <strings.h>
+       #include <syslog.h>
+       #include <arpa/inet.h>
+       #include <sys/ioctl.h>
+       #include <sys/select.h>
+
+       #include <net/if.h>
+       #include <netinet/if_ether.h>
+#ifdef linux
+       #include <netpacket/packet.h>
+       #include <linux/if_tun.h>
+#else
+#ifdef _DFBSD
+       #include <net/tun/if_tun.h>
+#else
+#ifdef _DARWIN
+       /*
+        * Darwin doesn't have TUN/TAP support per default
+        * It is available from http://www-user.rhrk.uni-kl.de/~nissler/tuntap/
+        * which is a port made by Mattias Nissler
+        * for compiling convienience we have included the ioctl's here
+        */
+       #define TUNSIFHEAD  _IOW('t', 96, int)
+       #define TUNGIFHEAD  _IOR('t', 97, int)
+#else
+#ifndef _AIX
+       #include <net/if_tun.h>
+/* endif for !_AIX */
+#endif
+/* endif for _DARWIN else */
+#endif
+/* endif for _DFBSD else */
+#endif
+/* endif for linux else */
+#endif
+       #include <netinet/ip.h>
+       #include <netinet/ip6.h>
+       #include <netinet/icmp6.h>
+       #include <netinet/tcp.h>
+       #include <netinet/udp.h>
+       #include <netinet/ip_icmp.h>
+       #include <sys/ioctl.h>
+
+#if defined(_OPENBSD) || defined(_DARWIN) || defined(_FREEBSD) || defined(_DFBSD)
+       #include <sys/uio.h>
+#endif
+
+       #include <pthread.h>
+
+       /*
+        * Windows abstracts sockets to a different
+        * type, as this is actually pretty nice
+        * we'll do it too
+        */
+       #ifndef SOCKET
+               typedef int SOCKET;
+       #endif
+
+       /* closesocket() -> close() on unices */
+       #define closesocket close
+
+       /*
+        * Expect a BSD style in6_addr who puts
+        * this between a #ifdef _KERNEL...
+        * Probably against people doing stuff in userspace?
+        */
+       #ifndef s6_addr
+       #ifndef _SUNOS
+       #define s6_addr __u6_addr.__u6_addr8
+       #else
+       #define s6_addr _S6_un._S6_u8
+       #endif
+       #endif
+#else
+
+       /* Winsock */
+       #include <winsock2.h>
+       #include <ws2tcpip.h>
+
+       /* Windows Specifics */
+       #include <io.h>
+
+/*
+        * Some weird M$ person thought it was
+        * funny to underscore common functions !?
+        */
+       #define snprintf        _snprintf
+       #define vsnprintf       _vsnprintf
+       #define strcasecmp      _stricmp
+       #define strncasecmp     _strnicmp
+       #define strdup          _strdup
+
+       /* 
+        * Capitalize this one
+        * Sleep() is in milliseconds
+        */
+       #define sleep(x) Sleep(x*1000)
+
+       /* No syslog on Windows */
+       #define LOG_DEBUG 1
+       #define LOG_ERR 2
+       #define LOG_WARNING 3
+       #define LOG_INFO 4
+
+       typedef unsigned long u_int32_t;
+       typedef unsigned long long u_int64_t;
+
+       typedef unsigned char u_int8_t;
+       typedef unsigned __int16 u_int16_t;
+       typedef unsigned __int64 u_int64_t;
+
+       /* Not available in the Winsock2 includes */
+       #define IPPROTO_NONE 59 /* IPv6 no next header */
+
+       #define BIG_ENDIAN 4321
+       #define LITTLE_ENDIAN 1234
+
+       #define __BIG_ENDIAN BIG_ENDIAN
+       #define __LITTLE_ENDIAN LITTLE_ENDIAN
+
+       /* Fix byte order */
+       #define __BYTE_ORDER __LITTLE_ENDIAN
+       #define BYTE_ORDER LITTLE_ENDIAN
+
+       #define s6_addr16       _S6_un.Word
+       #define SHUT_RDWR       SD_BOTH
+       #define uint8_t         u_int8_t
+       #define uint16_t        u_int16_t
+       #define uint32_t        u_int32_t
+       #define uint64_t        u_int64_t
+
+       struct ether
+       {
+               uint16_t        ether_dhost[3];
+               uint16_t        ether_shost[3];
+               uint16_t        ether_type;
+       };
+
+       /* The IPv6 Header */   
+       struct ip6_hdr
+       {
+               union
+               {
+                       struct ip6_hdrctl
+                       {
+                               uint32_t        ip6_un1_flow;   /* 4 bits version, 8 bits TC, 20 bits flow-ID */
+                               uint16_t        ip6_un1_plen;   /* payload length */
+                               uint8_t         ip6_un1_nxt;    /* next header */
+                               uint8_t         ip6_un1_hlim;   /* hop limit */
+                       }                       ip6_un1;
+                       uint8_t                 ip6_un2_vfc;    /* 4 bits version, top 4 bits tclass */
+               }                               ip6_ctlun;
+               struct in6_addr ip6_src;                        /* source address */
+               struct in6_addr ip6_dst;                        /* destination address */
+       };
+
+       /* ICMPv6 */
+       struct icmp6_hdr
+       {
+               uint8_t                 icmp6_type;             /* type field */
+               uint8_t                 icmp6_code;             /* code field */
+               uint16_t                icmp6_cksum;            /* checksum field */
+               union
+               {
+                       uint32_t        icmp6_un_data32[1];     /* type-specific field */
+                       uint16_t        icmp6_un_data16[2];     /* type-specific field */
+                       uint8_t         icmp6_un_data8[4];      /* type-specific field */
+               } icmp6_dataun;
+       };
+
+       #define ND_NEIGHBOR_SOLICIT         135
+       #define ND_NEIGHBOR_ADVERT          136
+
+       struct nd_neighbor_solicit
+       {
+               struct in6_addr         nd_ns_target;           /* target address */
+                                                               /* could be followed by options */
+       };
+
+       struct nd_neighbor_advert
+       {
+               struct in6_addr         nd_na_target;           /* target address */
+                                                               /* could be followed by options */
+               uint8_t                 nd_no_type;             /* Option providing the target MAC address */
+               uint8_t                 nd_no_len;              /* Length (1) */
+               uint8_t                 nd_no_mac[6];           /* MAC address */
+
+       };
+
+       const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt);
+       int inet_pton(int af, const char *src, void *dst);
+#endif /* WIN32 */
+
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL   0
+#endif
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN  __LITTLE_ENDIAN
+#endif
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN     __BIG_ENDIAN
+#endif
+#ifndef PDP_ENDIAN
+#define PDP_ENDIAN     __PDP_ENDIAN
+#endif
+#ifndef BYTE_ORDER
+#define BYTE_ORDER     __BYTE_ORDER
+#endif
+
+/* Boolean support */
+#ifndef bool
+#define bool uint32_t
+#endif
+#ifndef false
+#define false 0
+#endif
+#ifndef true
+#define true (!false)
+#endif
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+/* Include MD5 and SHA1 support */
+#include "hash_md5.h"
+#include "hash_sha1.h"
+
+/* Resolver includes */
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#endif
+
+#ifdef AICCU_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#ifndef NS_GET16SZ
+#define NS_INT32SZ      4       /* #/bytes of data in a u_int32_t */
+#endif
+
+#ifndef NS_GET32SZ
+#define NS_INT16SZ      2       /* #/bytes of data in a u_int16_t */
+#endif
+
+
+#ifndef NS_GET16
+#define NS_GET16(s, cp) do { \
+        register u_char *t_cp = (u_char *)(cp); \
+        (s) = ((u_int16_t)t_cp[0] << 8) \
+            | ((u_int16_t)t_cp[1]) \
+            ; \
+        (cp) += NS_INT16SZ; \
+} while (0)
+#endif
+
+#ifndef NS_GET32
+#define NS_GET32(l, cp) do { \
+        register u_char *t_cp = (u_char *)(cp); \
+        (l) = ((u_int32_t)t_cp[0] << 24) \
+            | ((u_int32_t)t_cp[1] << 16) \
+            | ((u_int32_t)t_cp[2] << 8) \
+            | ((u_int32_t)t_cp[3]) \
+            ; \
+        (cp) += NS_INT32SZ; \
+} while (0)
+#endif
+
+/* parseline() rules */
+enum pl_ruletype
+{
+       PLRT_STRING,            /* Offset points to a String (strdup()) */
+       PLRT_INTEGER,           /* Offset points to a Integer (unsigned int) */
+       PLRT_BOOL,              /* Offset points to a Boolean. */
+       PLRT_IPV4,              /* Offset points to a IPv4 address (inet_pton(..., AF_INET)) */
+       PLRT_IPV6,              /* Offset points to a IPv6 address (inet_pton(..., AF_INET6)) */
+       PLRT_END                /* End of rules */
+};
+
+struct pl_rule
+{
+       const char              *title;
+       unsigned int            type;
+       unsigned int            offset;
+};
+
+
+struct tlssocket
+{
+       SOCKET                  socket;
+#ifdef AICCU_GNUTLS
+       bool                    tls_active;     /* TLS active? */
+       gnutls_session          session;        /* The GnuTLS sesision */
+#endif
+};
+
+typedef struct tlssocket * TLSSOCKET;
+
+/* Common Functions */
+void dologA(int level, const char *fmt, va_list ap);
+void dolog(int level, const char *fmt, ...);
+
+#ifdef _AIX
+void vsyslog(int priority, const char *format, va_list ap);
+#endif
+
+/* Networking functions */
+void sock_printf(TLSSOCKET sock, const char *fmt, ...);
+int sock_getline(TLSSOCKET sock, char *rbuf, unsigned int rbuflen, unsigned int *filled, char *ubuf, unsigned int ubuflen);
+TLSSOCKET connect_client(const char *hostname, const char *service, int family, int socktype);
+TLSSOCKET listen_server(const char *description, const char *hostname, const char *service, int family, int socktype);
+void sock_free(TLSSOCKET sock);
+#ifdef AICCU_GNUTLS
+bool sock_gotls(TLSSOCKET sock);
+#endif
+
+/* Parsing functions */
+unsigned int countfields(char *s);
+bool copyfield(char *s, unsigned int n, char *buf, unsigned int buflen);
+bool parseline(char *line, const char *split, struct pl_rule *rules, void *data);
+
+/* Convienience */
+void MD5String(const char *sString, char *sSignature, unsigned int siglen);
+bool is_rfc1918(char *ipv4);
+
+#endif /* AICCU_COMMON_H */
diff --git a/common/hash_md5.c b/common/hash_md5.c
new file mode 100755 (executable)
index 0000000..160b849
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions; now uses stuff from dpkg's config.h.
+ *  - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#include "aiccu.h"
+#include "hash_md5.h"
+
+#include <string.h>     /* for memcpy() */
+#include <sys/types.h> /* for stupid systems */
+
+#ifdef WORDS_BIGENDIAN
+void byteSwap(UWORD32 *buf, unsigned words);
+void byteSwap(UWORD32 *buf, unsigned words)
+{
+       md5byte *p = (md5byte *)buf;
+
+       do {
+               *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
+                       ((unsigned)p[1] << 8 | p[0]);
+               p += 4;
+       } while (--words);
+}
+#else
+#define byteSwap(buf,words)
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx)
+{
+       ctx->buf[0] = 0x67452301;
+       ctx->buf[1] = 0xefcdab89;
+       ctx->buf[2] = 0x98badcfe;
+       ctx->buf[3] = 0x10325476;
+
+       ctx->bytes[0] = 0;
+       ctx->bytes[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len)
+{
+       UWORD32 t;
+
+       /* Update byte count */
+
+       t = ctx->bytes[0];
+       if ((ctx->bytes[0] = t + len) < t)
+               ctx->bytes[1]++;        /* Carry from low to high */
+
+       t = 64 - (t & 0x3f);    /* Space available in ctx->in (at least 1) */
+       if (t > len) {
+               memcpy((md5byte *)ctx->in + 64 - t, buf, len);
+               return;
+       }
+       /* First chunk is an odd size */
+       memcpy((md5byte *)ctx->in + 64 - t, buf, t);
+       byteSwap(ctx->in, 16);
+       MD5Transform(ctx->buf, ctx->in);
+       buf += t;
+       len -= t;
+
+       /* Process data in 64-byte chunks */
+       while (len >= 64) {
+               memcpy(ctx->in, buf, 64);
+               byteSwap(ctx->in, 16);
+               MD5Transform(ctx->buf, ctx->in);
+               buf += 64;
+               len -= 64;
+       }
+
+       /* Handle any remaining bytes of data. */
+       memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(md5byte digest[16], struct MD5Context *ctx)
+{
+       int count = ctx->bytes[0] & 0x3f;       /* Number of bytes in ctx->in */
+       md5byte *p = (md5byte *)ctx->in + count;
+
+       /* Set the first char of padding to 0x80.  There is always room. */
+       *p++ = 0x80;
+
+       /* Bytes of padding needed to make 56 bytes (-8..55) */
+       count = 56 - 1 - count;
+
+       if (count < 0) {        /* Padding forces an extra block */
+               memset(p, 0, count + 8);
+               byteSwap(ctx->in, 16);
+               MD5Transform(ctx->buf, ctx->in);
+               p = (md5byte *)ctx->in;
+               count = 56;
+       }
+       memset(p, 0, count);
+       byteSwap(ctx->in, 14);
+
+       /* Append length in bits and transform */
+       ctx->in[14] = ctx->bytes[0] << 3;
+       ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+       MD5Transform(ctx->buf, ctx->in);
+
+       byteSwap(ctx->buf, 4);
+       memcpy(digest, ctx->buf, 16);
+       memset(ctx, 0, sizeof(ctx));    /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+        (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void
+MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
+{
+       register UWORD32 a, b, c, d;
+
+       a = buf[0];
+       b = buf[1];
+       c = buf[2];
+       d = buf[3];
+
+       MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+       MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+       MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+       MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+       MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+       MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+       MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+       MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+       MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+       MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+       MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+       MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+       MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+       MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+       MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+       MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+       MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+       MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+       MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+       MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+       MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+       MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+       MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+       MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+       MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+       MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+       MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+       MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+       MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+       MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+       MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+       MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+       MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+       MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+       MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+       MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+       MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+       MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+       MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+       MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+       MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+       MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+       MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+       MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+       MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+       MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+       MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+       MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+       MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+       MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+       MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+       MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+       MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+       MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+       MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+       MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+       MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+       MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+       MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+       MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+       MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+       MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+       MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+       MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+       buf[0] += a;
+       buf[1] += b;
+       buf[2] += c;
+       buf[3] += d;
+}
+
+#endif
diff --git a/common/hash_md5.h b/common/hash_md5.h
new file mode 100755 (executable)
index 0000000..2bc44a8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * This is the header file for the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h'
+ * header definitions; now uses stuff from dpkg's config.h
+ *  - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+#include "common.h"
+
+#ifdef _WIN32
+typedef unsigned long uint32;
+#define UWORD32 uint32
+
+#else /* _WIN32 */
+
+#ifdef _SUNOS
+typedef unsigned int uint32;
+#define UWORD32 uint32
+#else
+#define UWORD32 u_int32_t
+#endif /* _SUNOS */
+
+#endif /* _WIN32 */
+
+/* Determine Endianness */
+#if BYTE_ORDER == LITTLE_ENDIAN
+       /* 1234 machines */
+#elif BYTE_ORDER == BIG_ENDIAN
+       /* 4321 machines */
+# define WORDS_BIGENDIAN 1
+#elif BYTE_ORDER == PDP_ENDIAN
+       /* 3412 machines */
+#error PDP endianness not supported yet!
+#else
+#error unknown endianness!
+#endif
+
+#define md5byte unsigned char
+
+struct MD5Context {
+       UWORD32 buf[4];
+       UWORD32 bytes[2];
+       UWORD32 in[16];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
+
+#endif /* !MD5_H */
diff --git a/common/hash_sha1.c b/common/hash_sha1.c
new file mode 100755 (executable)
index 0000000..57f9488
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * sha1.c
+ *
+ * Originally witten by Steve Reid <steve@edmweb.com>
+ * 
+ * Modified by Aaron D. Gifford <agifford@infowest.com>
+ *
+ * NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN
+ *
+ * The original unmodified version is available at:
+ *    ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "hash_sha1.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&(sha1_quadbyte)0xFF00FF00) \
+       |(rol(block->l[i],8)&(sha1_quadbyte)0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+       ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (SHA_R0+SHA_R1), SHA_R2, SHA_R3, SHA_R4 are the different operations used in SHA1 */
+#define SHA_R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define SHA_R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define SHA_R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define SHA_R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define SHA_R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+typedef union _BYTE64QUAD16 {
+       sha1_byte c[64];
+       sha1_quadbyte l[16];
+} BYTE64QUAD16;
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+void SHA1_Transform(sha1_quadbyte state[5], const sha1_byte buffer[64]);
+void SHA1_Transform(sha1_quadbyte state[5], const sha1_byte buffer[64])
+{
+       sha1_quadbyte   a, b, c, d, e;
+       BYTE64QUAD16    *block;
+
+       block = (BYTE64QUAD16*)buffer;
+       /* Copy context->state[] to working vars */
+       a = state[0];
+       b = state[1];
+       c = state[2];
+       d = state[3];
+       e = state[4];
+       /* 4 rounds of 20 operations each. Loop unrolled. */
+       SHA_R0(a,b,c,d,e, 0); SHA_R0(e,a,b,c,d, 1); SHA_R0(d,e,a,b,c, 2); SHA_R0(c,d,e,a,b, 3);
+       SHA_R0(b,c,d,e,a, 4); SHA_R0(a,b,c,d,e, 5); SHA_R0(e,a,b,c,d, 6); SHA_R0(d,e,a,b,c, 7);
+       SHA_R0(c,d,e,a,b, 8); SHA_R0(b,c,d,e,a, 9); SHA_R0(a,b,c,d,e,10); SHA_R0(e,a,b,c,d,11);
+       SHA_R0(d,e,a,b,c,12); SHA_R0(c,d,e,a,b,13); SHA_R0(b,c,d,e,a,14); SHA_R0(a,b,c,d,e,15);
+       SHA_R1(e,a,b,c,d,16); SHA_R1(d,e,a,b,c,17); SHA_R1(c,d,e,a,b,18); SHA_R1(b,c,d,e,a,19);
+       SHA_R2(a,b,c,d,e,20); SHA_R2(e,a,b,c,d,21); SHA_R2(d,e,a,b,c,22); SHA_R2(c,d,e,a,b,23);
+       SHA_R2(b,c,d,e,a,24); SHA_R2(a,b,c,d,e,25); SHA_R2(e,a,b,c,d,26); SHA_R2(d,e,a,b,c,27);
+       SHA_R2(c,d,e,a,b,28); SHA_R2(b,c,d,e,a,29); SHA_R2(a,b,c,d,e,30); SHA_R2(e,a,b,c,d,31);
+       SHA_R2(d,e,a,b,c,32); SHA_R2(c,d,e,a,b,33); SHA_R2(b,c,d,e,a,34); SHA_R2(a,b,c,d,e,35);
+       SHA_R2(e,a,b,c,d,36); SHA_R2(d,e,a,b,c,37); SHA_R2(c,d,e,a,b,38); SHA_R2(b,c,d,e,a,39);
+       SHA_R3(a,b,c,d,e,40); SHA_R3(e,a,b,c,d,41); SHA_R3(d,e,a,b,c,42); SHA_R3(c,d,e,a,b,43);
+       SHA_R3(b,c,d,e,a,44); SHA_R3(a,b,c,d,e,45); SHA_R3(e,a,b,c,d,46); SHA_R3(d,e,a,b,c,47);
+       SHA_R3(c,d,e,a,b,48); SHA_R3(b,c,d,e,a,49); SHA_R3(a,b,c,d,e,50); SHA_R3(e,a,b,c,d,51);
+       SHA_R3(d,e,a,b,c,52); SHA_R3(c,d,e,a,b,53); SHA_R3(b,c,d,e,a,54); SHA_R3(a,b,c,d,e,55);
+       SHA_R3(e,a,b,c,d,56); SHA_R3(d,e,a,b,c,57); SHA_R3(c,d,e,a,b,58); SHA_R3(b,c,d,e,a,59);
+       SHA_R4(a,b,c,d,e,60); SHA_R4(e,a,b,c,d,61); SHA_R4(d,e,a,b,c,62); SHA_R4(c,d,e,a,b,63);
+       SHA_R4(b,c,d,e,a,64); SHA_R4(a,b,c,d,e,65); SHA_R4(e,a,b,c,d,66); SHA_R4(d,e,a,b,c,67);
+       SHA_R4(c,d,e,a,b,68); SHA_R4(b,c,d,e,a,69); SHA_R4(a,b,c,d,e,70); SHA_R4(e,a,b,c,d,71);
+       SHA_R4(d,e,a,b,c,72); SHA_R4(c,d,e,a,b,73); SHA_R4(b,c,d,e,a,74); SHA_R4(a,b,c,d,e,75);
+       SHA_R4(e,a,b,c,d,76); SHA_R4(d,e,a,b,c,77); SHA_R4(c,d,e,a,b,78); SHA_R4(b,c,d,e,a,79);
+       /* Add the working vars back into context.state[] */
+       state[0] += a;
+       state[1] += b;
+       state[2] += c;
+       state[3] += d;
+       state[4] += e;
+       /* Wipe variables */
+       a = b = c = d = e = 0;
+}
+
+
+/* SHA1_Init - Initialize new context */
+void SHA1_Init(SHA_CTX* context) {
+       /* SHA1 initialization constants */
+       context->state[0] = 0x67452301;
+       context->state[1] = 0xEFCDAB89;
+       context->state[2] = 0x98BADCFE;
+       context->state[3] = 0x10325476;
+       context->state[4] = 0xC3D2E1F0;
+       context->count[0] = context->count[1] = 0;
+}
+
+/* Run your data through this. */
+void SHA1_Update(SHA_CTX *context, const sha1_byte *d, unsigned int len) {
+       unsigned int    i, j;
+
+       /* Make a temporary storage as Transform destroys it */
+       sha1_byte *data = (sha1_byte *)malloc(len);
+       if (!data) exit(-42);
+       memcpy(data, d, len);
+
+       j = (context->count[0] >> 3) & 63;
+       if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+       context->count[1] += (len >> 29);
+       if ((j + len) > 63) {
+           memcpy(&context->buffer[j], data, (i = 64-j));
+           SHA1_Transform(context->state, context->buffer);
+           for ( ; i + 63 < len; i += 64) {
+               SHA1_Transform(context->state, &data[i]);
+           }
+           j = 0;
+       }
+       else i = 0;
+       memcpy(&context->buffer[j], &data[i], len - i);
+
+       /* Free the temporary buffer */
+       free(data);
+}
+
+/* Add padding and return the message digest. */
+void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX *context) {
+       sha1_quadbyte   i, j;
+       sha1_byte       finalcount[8];
+
+       for (i = 0; i < 8; i++) {
+           finalcount[i] = (sha1_byte)((context->count[(i >= 4 ? 0 : 1)]
+            >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+       }
+       SHA1_Update(context, (sha1_byte *)"\200", 1);
+       while ((context->count[0] & 504) != 448) {
+           SHA1_Update(context, (sha1_byte *)"\0", 1);
+       }
+       /* Should cause a SHA1_Transform() */
+       SHA1_Update(context, finalcount, 8);
+       for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
+           digest[i] = (sha1_byte)
+            ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+       }
+       /* Wipe variables */
+       i = j = 0;
+       memset(context->buffer, 0, SHA1_BLOCK_LENGTH);
+       memset(context->state, 0, SHA1_DIGEST_LENGTH);
+       memset(context->count, 0, 8);
+       memset(&finalcount, 0, 8);
+}
+
diff --git a/common/hash_sha1.h b/common/hash_sha1.h
new file mode 100755 (executable)
index 0000000..5e2edcc
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * sha.h
+ *
+ * Originally taken from the public domain SHA1 implementation
+ * written by by Steve Reid <steve@edmweb.com>
+ * 
+ * Modified by Aaron D. Gifford <agifford@infowest.com>
+ *
+ * NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN
+ *
+ * The original unmodified version is available at:
+ *    ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __SHA1_H__
+#define __SHA1_H__
+
+#include "common.h"
+
+/* Define this if your machine is LITTLE_ENDIAN, otherwise #undef it: */
+/* Is defined in endian.h */
+/*
+#define LITTLE_ENDIAN
+ */
+
+/* Make sure you define these types for your architecture: */
+typedef uint32_t       sha1_quadbyte;  /* 4 byte type */
+typedef uint8_t                sha1_byte;      /* single byte type */
+
+/*
+ * Be sure to get the above definitions right.  For instance, on my
+ * x86 based FreeBSD box, I define LITTLE_ENDIAN and use the type
+ * "unsigned long" for the quadbyte.  On FreeBSD on the Alpha, however,
+ * while I still use LITTLE_ENDIAN, I must define the quadbyte type
+ * as "unsigned int" instead.
+ */
+
+#define SHA1_BLOCK_LENGTH      64
+#define SHA1_DIGEST_LENGTH     20
+
+/* The SHA1 structure: */
+typedef struct _SHA_CTX {
+       sha1_quadbyte   state[5];
+       sha1_quadbyte   count[2];
+       sha1_byte       buffer[SHA1_BLOCK_LENGTH];
+} SHA_CTX;
+
+#ifndef NOPROTO
+void SHA1_Init(SHA_CTX *context);
+void SHA1_Update(SHA_CTX *context, const sha1_byte *data, unsigned int len);
+void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX* context);
+#else
+void SHA1_Init();
+void SHA1_Update();
+void SHA1_Final();
+#endif
+
+#endif
+
diff --git a/common/heartbeat.c b/common/heartbeat.c
new file mode 100755 (executable)
index 0000000..0d2a861
--- /dev/null
@@ -0,0 +1,295 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/heartbeat.c - Heartbeat Code
+***********************************************************
+ $Author: jeroen $
+ $Id: heartbeat.c,v 1.9 2006-12-21 14:08:50 jeroen Exp $
+ $Date: 2006-12-21 14:08:50 $
+**********************************************************/
+
+#include "heartbeat.h"
+#include "aiccu.h"
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <signal.h>
+#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
+#include <net/if.h>
+#endif
+
+/**************************************
+  Functions
+**************************************/
+
+/* Get a socket and determine the new IP address */
+SOCKET heartbeat_socket(
+       uint32_t *address_changed,
+       int bStaticTunnel,
+       const char *sIPv4Interface,
+       char **sIPv4Local,
+       const char *sIPv4POP,
+       const char *sIPv4LocalResolve)
+{
+       SOCKET          sockfd;
+       struct sockaddr sa;
+       socklen_t       socklen;
+       char            local_ipv4[NI_MAXHOST];
+#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
+       struct ifreq    interface;
+#endif
+       struct addrinfo hints, *res, *ressave;
+
+       D(dolog(LOG_DEBUG, "heartbeat_socket() - Address is %s\n", *sIPv4Local));
+
+       if (address_changed) *address_changed = 0;
+
+       /* Get ourselves a nice IPv4 socket */
+       sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+       if (sockfd < 0)
+       {
+               dolog(LOG_ERR, "Couldn't open a socket for determining current IPv4 address\n");
+               return -1;
+       }
+
+#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE)
+       /*
+        * We don't have to bind to a device if this
+        * is a static tunnel, this allows running
+        * the heartbeat client as non-root.
+        */
+       if (!bStaticTunnel)
+       {
+               /*
+                * Only allowed as root, but we need root rights anyways
+                * to (re)configure the tunnel
+                */
+
+               /* Bind to the underlying IPv4 device */
+               memset(&interface, 0, sizeof(interface));
+               strncpy(interface.ifr_ifrn.ifrn_name, sIPv4Interface, IFNAMSIZ);
+               if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
+                       (char *)&interface, sizeof(interface)) == -1)
+               {
+                       dolog(LOG_ERR, "Couldn't bind to device \"%s\"\n", sIPv4Interface);
+                       close(sockfd);
+
+                       /* We return a -1, thus the app will keep beating */
+                       return -1;
+               }
+       }
+#else
+       /* Make compiler happy and 'use' the param */
+       sIPv4Interface = sIPv4Interface;
+#endif
+
+       /*
+        * connect to the remote port
+        * this causes us to be able to use normal write()
+        * and also gives us the ability to find out the local IP
+        */
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_family = AF_INET;
+       hints.ai_socktype = SOCK_DGRAM;
+
+       /* Get the POP IPv4 into a sockaddr */
+       if (getaddrinfo(sIPv4POP, HEARTBEAT_PORT, &hints, &res) != 0)
+       {
+               dolog(LOG_ERR, "Couldn't resolve POP ip %s\n", sIPv4POP);
+               closesocket(sockfd);
+
+               /* We return a -1, thus the app will keep beating */
+               return -1;
+       }
+
+       ressave = res;
+
+       while (res)
+       {
+               if (connect(sockfd, res->ai_addr, (unsigned int)res->ai_addrlen) == 0) break;
+               res = res->ai_next;
+       }
+       freeaddrinfo(ressave);
+       if (res == NULL)
+       {
+               dolog(LOG_ERR, "Failed to connect() to remote side\n");
+               closesocket(sockfd);
+               /* We return a -1, thus the app will keep beating */
+               return -1;
+       }
+
+       /* Normal operation, find out our local IPv4 address */
+       if (sIPv4LocalResolve == NULL)
+       {
+               /* Figure out our local IP */
+               socklen = sizeof(sa);
+               if (getsockname(sockfd, &sa, &socklen) == -1)
+               {
+                       dolog(LOG_WARNING, "Couldn't get local socketaddress\n");
+                       closesocket(sockfd);
+                       return -1;
+               }
+
+               if (getnameinfo((struct sockaddr *)&sa, sizeof(sa),
+                               local_ipv4, sizeof(local_ipv4),
+                       NULL, 0,
+                       NI_NUMERICHOST) != 0)
+               {
+                       dolog(LOG_WARNING, "Couldn't get local IP\n");
+                       closesocket(sockfd);
+                       return -1;
+               }
+       }
+       else
+       {
+               /*
+                * this causes us to be able to use normal write()
+                * and also gives us the ability to find out the local IP
+                */
+               memset(&hints, 0, sizeof(struct addrinfo));
+               hints.ai_family = AF_INET;
+               hints.ai_socktype = SOCK_DGRAM;
+               
+               /* Get the POP IPv4 into a sockaddr */
+               if (getaddrinfo(sIPv4LocalResolve, NULL, &hints, &res) != 0)
+               {
+                       dolog(LOG_ERR, "Couldn't resolve POP IPv4 %s\n", sIPv4POP);
+                       /* We return a -1, thus the app will keep beating */
+                       return -1;
+               }
+               ressave = res;
+               while (res)
+               {
+                       if (getnameinfo(res->ai_addr, (socklen_t)res->ai_addrlen,
+                               local_ipv4, sizeof(local_ipv4),
+                               NULL, 0,
+                               NI_NUMERICHOST) == 0)
+                       {
+                               break;
+                       }
+                       dolog(LOG_WARNING, "Couldn't get local IP\n");
+                       res = res->ai_next;
+               }
+               freeaddrinfo(ressave);
+       }
+
+       /* Did the IPv4 address change? */
+       if (*sIPv4Local == NULL ||
+               strcmp(*sIPv4Local, local_ipv4) != 0)
+       {
+               if (*sIPv4Local) free(*sIPv4Local);
+               *sIPv4Local = strdup(local_ipv4);
+
+               dolog(LOG_DEBUG, "heartbeat_socket() - IPv4 : %s\n", *sIPv4Local);
+
+               if (!bStaticTunnel)
+               {
+                       /* Run a script to change the address */
+                       if (address_changed) *address_changed = 1;
+               }
+       }
+       D(else dolog(LOG_DEBUG, "heartbeat_socket() - Address stays %s\n", *sIPv4Local));
+
+       /* Return it */
+       return sockfd;
+}
+
+/* Send a heartbeat */
+int heartbeat_send(SOCKET sockfd, char *sIPv4Local, char *sIPv6Local, char *sPassword, bool bBehindNAT)
+{
+       struct MD5Context       md5;
+       unsigned char           *p, our_digest[20], *pn = our_digest, buf[1000];
+       time_t                  time_tee;
+       int                     i;
+
+       time_tee = time(NULL);
+
+       /* Create the string to send including our password */
+       snprintf((char *)buf, sizeof(buf), "HEARTBEAT TUNNEL %s %s %ld %s",
+               sIPv6Local,
+               (bBehindNAT ? "sender" : sIPv4Local),
+               (long int)time_tee, sPassword);
+
+       /* Generate a MD5 */
+       MD5Init(&md5);
+       MD5Update(&md5, buf, (unsigned int)strlen((char *)buf));
+       MD5Final(our_digest, &md5);
+
+       /* Overwrite it without password */
+       p = buf;
+       p += snprintf((char *)buf, sizeof(buf)-17, "HEARTBEAT TUNNEL %s %s %ld ",
+               sIPv6Local,
+               (bBehindNAT == 1 ? "sender" : sIPv4Local),
+               (long int)time_tee);
+
+       /* append the digest */
+       for (i = 0; i < 16; i++)
+       {
+               snprintf((char *)p, 3, (const char *)"%02x", *pn++);
+               p+=2;
+       }
+       *p = '\0';
+
+       /* Send the heartbeat */
+       send(sockfd, (const char *)buf, (unsigned int)strlen((const char *)buf),0);
+
+       dolog(LOG_DEBUG, "[HB] %s\n", buf);
+
+       return 0;
+}
+
+char *heartbeat_getlocalIP(struct TIC_Tunnel *hTunnel)
+{
+       bool address_changed = false;
+       char *ipv4_local = NULL;
+
+       SOCKET sockfd = heartbeat_socket(&address_changed, 0, "",
+               &ipv4_local,
+               hTunnel->sIPv4_POP,
+               NULL);
+       if (sockfd >= 0) closesocket(sockfd);
+
+       dolog(LOG_DEBUG, "Local IPv4 address: %s\n", ipv4_local);
+
+       return ipv4_local;
+}
+
+/* 
+ * Other code can call this every once in a while
+ * and it will take care of everything ("everything?" "everything!")
+ */
+void heartbeat_beat(struct TIC_Tunnel *hTunnel)
+{
+       uint32_t address_changed = 0;
+       SOCKET sockfd = -1;
+
+       D(dolog(LOG_DEBUG, "heartbeat_beat() - Beating from %s\n", hTunnel->sIPv4_Local);)
+
+       sockfd = heartbeat_socket(&address_changed, 0, "",
+               &hTunnel->sIPv4_Local,
+               hTunnel->sIPv4_POP,
+               NULL);
+       if (sockfd >= 0)
+       {
+               if (address_changed == 1)
+               {
+                       D(dolog(LOG_DEBUG, "heartbeat_beat() - Address changed to %s\n", hTunnel->sIPv4_Local);)
+                       aiccu_reconfig(hTunnel);
+               }
+               heartbeat_send(sockfd,
+                       hTunnel->sIPv4_Local,
+                       hTunnel->sIPv6_Local,
+                       hTunnel->sPassword,
+                       1);
+               closesocket(sockfd);
+               sockfd = (SOCKET)-1;
+       }
+}
+
diff --git a/common/heartbeat.h b/common/heartbeat.h
new file mode 100755 (executable)
index 0000000..0e3a4cb
--- /dev/null
@@ -0,0 +1,39 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/heartbeat.h - Heartbeat Definitions
+***********************************************************
+ $Author: jeroen $
+ $Id: heartbeat.h,v 1.6 2006-12-21 14:08:50 jeroen Exp $
+ $Date: 2006-12-21 14:08:50 $
+**********************************************************/
+
+#ifndef HEARTBEAT_H
+#define HEARTBEAT_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#include "common.h"
+#include "tic.h"
+
+/* 
+ * SixXS Heartbeat Protocol
+ * port - uses UDP over IPv4
+ */
+#define HEARTBEAT_PORT "3740"
+
+SOCKET heartbeat_socket(
+       uint32_t *address_changed,
+       int bStaticTunnel,
+       const char *sIPv4Interface,
+       char **sIPv4Local,
+       const char *sIPv4POP,
+       const char *sIPv4LocalResolve);
+
+int heartbeat_send(SOCKET sockfd, char *sIPv4Local, char *sIPv6Local, char *sPassword, bool bBehindNAT);
+
+void heartbeat_beat(struct TIC_Tunnel *hTunnel);
+char *heartbeat_getlocalIP(struct TIC_Tunnel *hTunnel);
+
+#endif /* HEARTBEAT_H */
+
diff --git a/common/resolver.c b/common/resolver.c
new file mode 100644 (file)
index 0000000..39946a9
--- /dev/null
@@ -0,0 +1,209 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/resolver.c - Simple DNS RR lookup function
+***********************************************************
+ $Author: jeroen $
+ $Id: resolver.c,v 1.3 2006-07-23 14:13:57 jeroen Exp $
+ $Date: 2006-07-23 14:13:57 $
+**********************************************************/
+
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "resolver.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+
+int getrrs(const char *label, int rrtype, void gotrec(unsigned int num, int type, const char *record))
+{
+#ifdef _LINUX
+       struct __res_state      res;
+#endif
+       unsigned char           answer[8192];
+       HEADER                  *header = (HEADER *)answer;
+       char                    buf[2048];
+       int                     ret, count;
+       unsigned int            i,j,k,rrnum = 0;
+       unsigned char           *startptr, *endptr, *ptr;
+       uint16_t                type = 0, class = 0;
+       uint32_t                ttl = 0;
+
+#ifdef _LINUX
+       memset(&res, 0, sizeof(res));
+       res.options = RES_DEBUG;
+       res_ninit(&res);
+#else
+       res_init();
+#endif
+
+       memset(answer, 0, sizeof(answer));
+#ifdef _LINUX
+       ret = res_nquery(&res, label, C_IN, rrtype, answer, sizeof(answer));
+#else
+       ret = res_query(label, C_IN, rrtype, answer, sizeof(answer));
+#endif
+       if (ret < 0) return -1;
+
+       /* Our start and end */
+       startptr = &answer[0];
+       endptr = &answer[ret];
+
+       /* Skip the header */
+       ptr = startptr + HFIXEDSZ;
+
+       /* Skip Query part */
+       for (count = ntohs(header->qdcount); count--; ptr += ret + QFIXEDSZ)
+       {
+               if ((ret = dn_skipname(ptr, endptr)) < 0) return -1;
+       }
+
+       /* Only look at the Answer section */
+       count = ntohs(header->ancount);
+
+       /* Go through all the Answer records */
+       while (ptr < endptr && count > 0)
+       {
+               rrnum++;
+
+               memset(buf, 0, sizeof(buf));
+               ret = dn_expand (startptr, endptr, ptr, buf, sizeof(buf));
+               if (ret < 0) break;
+               ptr += ret;
+
+               if (ptr + INT16SZ + INT16SZ + INT32SZ >= endptr) break;
+
+               /* Get the type */
+               NS_GET16(type, ptr);
+
+               /* Get the class */
+               NS_GET16(class, ptr);
+
+               /* Get the TTL */
+               NS_GET32(ttl, ptr);
+
+               /* Get the RDLength */
+               NS_GET16(ret, ptr);
+
+               memset(buf, 0, sizeof(buf));
+
+               switch (type)
+               {
+               case T_TXT:
+                       for (k = ret, j = 0; j < k && &ptr[j] < endptr; j += (i+1))
+                       {
+                               i = ptr[j];
+                               memcpy(buf, &ptr[j+1], i > sizeof(buf) ? sizeof(buf) : i);
+                               buf[i > sizeof(buf) ? sizeof(buf) : i] = '\0';
+                               if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
+                       }
+                       break;
+
+               case T_A:
+                       inet_ntop(AF_INET, ptr, buf, sizeof(buf));
+                       if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
+                       break;
+
+               case T_AAAA:
+                       inet_ntop(AF_INET6, ptr, buf, sizeof(buf));
+                       if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
+                       break;
+
+               case T_MX:
+                       /* Get the MX preference */
+                       NS_GET16(ttl, ptr);
+                       ret = dn_expand(startptr, endptr, ptr, buf, sizeof(buf));
+                       if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
+                       break;
+
+               case T_NS:
+                       ret = dn_expand(startptr, endptr, ptr, buf, sizeof(buf));
+                       if (rrtype == type || rrtype == T_ANY) gotrec(rrnum, type, buf);
+                       break;
+
+               default:
+                       /* Unhandled */
+                       break;
+               }
+
+               ptr += ret;
+               count--;
+       }
+       return 0;
+}
+#else
+/*
+ * Windows Resolver Code, as per:
+ * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dns/dns/dnsquery.asp
+ * http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B831226
+ */
+#include <windns.h>
+
+int getrrs(const char *label, int rrtype, void gotrec(unsigned int num, int type, const char *record))
+{
+       DNS_STATUS      status;                 /* Return value of DnsQuery_A() function */
+       PDNS_RECORD     pResult, pRec;          /* Pointer to DNS_RECORD structure */
+       unsigned int    rrnum = 0, i;
+       uint16_t        type;
+
+       status = DnsQuery(label,                /* Pointer to OwnerName */
+               rrtype,                         /* Type of the record to be queried */
+               DNS_QUERY_STANDARD,             /* Standard Query */
+               NULL,                           /* Contains DNS server IP address */
+               &pResult,                       /* Resource record that contains the response */
+               NULL);                          /* Reserved for future use */
+
+       if (status) return -1;
+       else
+       {
+               for (pRec = pResult; pRec; pRec = pRec->pNext)
+               {
+                       rrnum++;
+                       type = pRec->wType;
+
+                       if (rrtype != type && rrtype != ns_t_any) continue;
+
+                       switch (type)
+                       {
+                       case ns_t_txt:
+                               for (i=0; i < pRec->Data.TXT.dwStringCount; i++)
+                               {
+                                       gotrec(rrnum, type, pRec->Data.TXT.pStringArray[i]);
+                               }
+                               break;
+
+                       case ns_t_a:
+                               gotrec(rrnum, type, (const char *)&pRec->Data.A.IpAddress);
+                               break;
+
+                       case ns_t_aaaa:
+                               gotrec(rrnum, type, (const char *)&pRec->Data.AAAA.Ip6Address);
+                               break;
+
+                       case ns_t_mx:
+                               gotrec(rrnum, type, pRec->Data.MX.pNameExchange);
+                               break;
+
+                       case ns_t_ns:
+                               gotrec(rrnum, type, pRec->Data.NS.pNameHost);
+                               break;
+                       }
+               }
+       }
+
+       /* Free memory allocated for DNS records. */
+       DnsRecordListFree(pResult, DnsFreeRecordListDeep);
+
+       return 0;
+}
+#endif
+
diff --git a/common/resolver.h b/common/resolver.h
new file mode 100755 (executable)
index 0000000..ba5e520
--- /dev/null
@@ -0,0 +1,84 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/resolver.h - Simple DNS RR lookup function
+***********************************************************
+ $Author: jeroen $
+ $Id: resolver.h,v 1.2 2006-07-13 19:33:39 jeroen Exp $
+ $Date: 2006-07-13 19:33:39 $
+**********************************************************/
+
+#ifndef RESOLVER_H
+#define RESOLVER_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#include "common.h"
+
+int getrrs(const char *label, int type, void gotrec(unsigned int num, int type, const char *record));
+
+#ifdef _WIN32
+/*
+ * Windows doesn't have these, there they are named DNS_TYPE_*
+ * but the identical values so we can use them here too.
+ * Looted from arpa/nameser.h which has a BSD license for UC & ISC
+ */
+/*
+ * Currently defined type values for resources and queries.
+ */
+typedef enum __ns_type {
+       ns_t_invalid = 0,       /* Cookie. */
+       ns_t_a = 1,             /* Host address. */
+       ns_t_ns = 2,            /* Authoritative server. */
+       ns_t_md = 3,            /* Mail destination. */
+       ns_t_mf = 4,            /* Mail forwarder. */
+       ns_t_cname = 5,         /* Canonical name. */
+       ns_t_soa = 6,           /* Start of authority zone. */
+       ns_t_mb = 7,            /* Mailbox domain name. */
+       ns_t_mg = 8,            /* Mail group member. */
+       ns_t_mr = 9,            /* Mail rename name. */
+       ns_t_null = 10,         /* Null resource record. */
+       ns_t_wks = 11,          /* Well known service. */
+       ns_t_ptr = 12,          /* Domain name pointer. */
+       ns_t_hinfo = 13,        /* Host information. */
+       ns_t_minfo = 14,        /* Mailbox information. */
+       ns_t_mx = 15,           /* Mail routing information. */
+       ns_t_txt = 16,          /* Text strings. */
+       ns_t_rp = 17,           /* Responsible person. */
+       ns_t_afsdb = 18,        /* AFS cell database. */
+       ns_t_x25 = 19,          /* X_25 calling address. */
+       ns_t_isdn = 20,         /* ISDN calling address. */
+       ns_t_rt = 21,           /* Router. */
+       ns_t_nsap = 22,         /* NSAP address. */
+       ns_t_nsap_ptr = 23,     /* Reverse NSAP lookup (deprecated). */
+       ns_t_sig = 24,          /* Security signature. */
+       ns_t_key = 25,          /* Security key. */
+       ns_t_px = 26,           /* X.400 mail mapping. */
+       ns_t_gpos = 27,         /* Geographical position (withdrawn). */
+       ns_t_aaaa = 28,         /* Ip6 Address. */
+       ns_t_loc = 29,          /* Location Information. */
+       ns_t_nxt = 30,          /* Next domain (security). */
+       ns_t_eid = 31,          /* Endpoint identifier. */
+       ns_t_nimloc = 32,       /* Nimrod Locator. */
+       ns_t_srv = 33,          /* Server Selection. */
+       ns_t_atma = 34,         /* ATM Address */
+       ns_t_naptr = 35,        /* Naming Authority PoinTeR */
+       ns_t_kx = 36,           /* Key Exchange */
+       ns_t_cert = 37,         /* Certification record */
+       ns_t_a6 = 38,           /* IPv6 address (deprecates AAAA) */
+       ns_t_dname = 39,        /* Non-terminal DNAME (for IPv6) */
+       ns_t_sink = 40,         /* Kitchen sink (experimentatl) */
+       ns_t_opt = 41,          /* EDNS0 option (meta-RR) */
+       ns_t_tsig = 250,        /* Transaction signature. */
+       ns_t_ixfr = 251,        /* Incremental zone transfer. */
+       ns_t_axfr = 252,        /* Transfer zone of authority. */
+       ns_t_mailb = 253,       /* Transfer mailbox records. */
+       ns_t_maila = 254,       /* Transfer mail agent records. */
+       ns_t_any = 255,         /* Wildcard match. */
+       ns_t_zxfr = 256,        /* BIND-specific, nonstandard. */
+       ns_t_max = 65536
+} ns_type;
+#endif
+
+#endif /* RESOLVER_H */
+
diff --git a/common/tic.c b/common/tic.c
new file mode 100755 (executable)
index 0000000..e0d70fe
--- /dev/null
@@ -0,0 +1,744 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/tic.c - Tunnel Information & Control Protocol
+***********************************************************
+ $Author: jeroen $
+ $Id: tic.c,v 1.17 2007-01-11 13:41:31 jeroen Exp $
+ $Date: 2007-01-11 13:41:31 $
+**********************************************************/
+
+#include "common.h"
+#include "aiccu.h"
+#include "tic.h"
+
+/* Specific includes only used here */
+#ifndef _WIN32
+#include <sys/utsname.h>
+#endif
+
+/* getline vars */
+char           tic_buf[2048];
+unsigned int   tic_filled;
+
+/* 
+ * epochtime = epochtime as received in the packet
+ * Don't forget to convert byteorder using ntohl()
+ */
+int tic_checktime(time_t epochtime)
+{
+       /* Number of seconds we allow the clock to be off */
+       #define CLOCK_OFF 120
+       int i;
+
+       /* Get the current time */
+       time_t curr_time = time(NULL);
+
+       /* Is one of the times in the loop range? */
+       if (    (curr_time >= -CLOCK_OFF) ||
+               (epochtime >= -CLOCK_OFF))
+       {
+               /* Shift the times out of the loop range */
+               i =(int)(((int)curr_time) + (CLOCK_OFF*2)) -
+                       (((int)epochtime) + (CLOCK_OFF*2));
+       }
+       else i = ((int)curr_time) - ((int)epochtime);
+
+       /* The clock may be faster, thus flip the sign */
+       if (i < 0) i = -i;
+
+       /* Compare the clock offset */
+       if (i > CLOCK_OFF)
+       {
+               /* Time is off */
+               return i;
+       }
+
+       /* Time is in the allowed range */
+       return 0;
+}
+
+bool tic_Login(struct TIC_conf *tic, const char *username, const char *password, const char *server)
+{
+       char            buf[1024], sSignature[33], sChallenge[1024];
+       int             i;
+#ifndef _WIN32
+       struct utsname  uts_name;
+#else
+       OSVERSIONINFO   osv;
+       OSVERSIONINFOEX osvEx;
+       char            *platform = NULL;
+       char            version[100];
+#endif
+
+       D(dolog(LOG_DEBUG, "Trying to connect to TIC server %s\n", server));
+
+       /* Connect to the TIC server */
+       tic->sock = connect_client(server, TIC_PORT, AF_INET, SOCK_STREAM);
+       if (!tic->sock)
+       {
+               dolog(LOG_ERR, "Couldn't connect to the TIC server %s\n", server);
+               return false;
+       }
+
+       /* Fetch the welcome */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return false;
+       }
+       if (buf[0] != '2')
+       {
+               dolog(LOG_ERR, "TIC Server is currently not available\n");
+               return false;
+       }
+
+       /* Send our client identification */
+#ifndef _WIN32
+       uname(&uts_name);
+       sock_printf(tic->sock, "client TIC/%s %s/%s %s/%s\n",
+               TIC_VERSION,
+               TIC_CLIENT_NAME, TIC_CLIENT_VERSION,
+               uts_name.sysname, uts_name.release);
+#else
+       osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       osvEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+
+       if (!GetVersionEx(&osv))
+       {
+               platform = "Windows";
+               snprintf(version, sizeof(version), "%s", "Unknown");
+       }
+       else
+       {
+
+               platform = (osv.dwPlatformId  == VER_PLATFORM_WIN32s)           ? "Win32s" :
+                          ((osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)    ? "Win9x" :
+                          ((osv.dwPlatformId == VER_PLATFORM_WIN32_NT)         ? "WinNT" :
+                                                                                 "Windows"));
+
+               if (    osv.dwMajorVersion < 5 ||
+                       !GetVersionEx((OSVERSIONINFO *)&osvEx) ||
+                       osvEx.wServicePackMajor <= 0)
+               {
+                       snprintf(version, sizeof(version), "%d.%d.%d",
+                               osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber);
+               }
+               else if (osvEx.wServicePackMinor <= 0)
+               {
+                       snprintf(version, sizeof(version), "%d.%d.%d-SP%d",
+                               osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber,
+                               osvEx.wServicePackMajor);
+               }
+               else
+               {
+                       snprintf(version, sizeof(version), "%d.%d.%d-SP%d.%d",
+                               osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber,
+                               osvEx.wServicePackMajor, osvEx.wServicePackMinor);
+               }
+       }
+       sock_printf(tic->sock, "client TIC/%s %s/%s %s/%s\n",
+               TIC_VERSION,
+               TIC_CLIENT_NAME, TIC_CLIENT_VERSION,
+               platform, version);
+#endif
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return false;
+       }
+       if (buf[0] != '2')
+       {
+               dolog(LOG_ERR, "Couldn't pass client information: %s.\n", &buf[4]);
+               return false;
+       }
+
+       /* Request current time */
+       sock_printf(tic->sock, "get unixtime\n");
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return false;
+       }
+       if (buf[0] != '2')
+       {
+               dolog(LOG_ERR, "Time not available? %s\n", &buf[4]);
+               return false;
+       }
+
+       /* Check if the time is correct */
+       i = tic_checktime(atoi(&buf[4]));
+       if (i != 0)
+       {
+               char quitmsg[100];
+               dolog(LOG_ERR, "The clock is off by %d seconds, use NTP to sync it!\n", i);
+               snprintf(quitmsg, sizeof(quitmsg), "Aborting: Clock is off by %d seconds\n", i);
+               tic_Logout(tic, quitmsg);
+               return false;
+       }
+
+#ifdef AICCU_GNUTLS
+  /* Upgrade to TLS */
+       sock_printf(tic->sock, "starttls\n");
+
+       /* Fetch the welcome */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return false;
+       }
+       if (buf[0] == '2')
+       {
+               /* Go to TLS mode */
+               if (!sock_gotls(tic->sock)) return false;
+       }
+       else
+       {
+               if (g_aiccu->requiretls)
+               {
+                       dolog(LOG_ERR, "TIC Server does not support TLS and TLS is required\n");
+                       return false;
+               }
+               if (g_aiccu->verbose) dolog(LOG_WARNING, "TIC Server does not support TLS but TLS is not required, continuing\n");
+       }
+
+#endif
+
+       /* Send our username */
+       sock_printf(tic->sock, "username %s\n", username);
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return false;
+       }
+       if (buf[0] != '2')
+       {
+               dolog(LOG_ERR, "Username not accepted: %s.\n", &buf[4]);
+               return false;
+       }
+       
+       /* Pick a challenge */
+       sock_printf(tic->sock, "challenge md5\n");
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return false;
+       }
+       if (buf[0] != '2')
+       {
+               dolog(LOG_ERR, "Challenge not correct: %s.\n", &buf[4]);
+               return false;
+       }
+
+       /* Send the response */
+       /* sSignature = md5(challenge.md5(password)); */
+       MD5String(password, sSignature, sizeof(sSignature));
+       snprintf(sChallenge, sizeof(sChallenge), "%s%s", &buf[4], sSignature);
+       MD5String(sChallenge, sSignature, sizeof(sSignature));
+
+       sock_printf(tic->sock, "authenticate md5 %s\n", sSignature);
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               tic_Logout(tic, NULL);
+               return false;
+       }
+       if (buf[0] != '2')
+       {
+               tic_Logout(tic, NULL);
+               dolog(LOG_ERR, "Response not accepted: %s.\n", &buf[4]);
+               return false;
+       }
+
+       /* Connect OK */
+       return true;
+}
+
+void tic_Logout(struct TIC_conf *tic, const char *quitmsg)
+{
+       /* A list of appropriate quit messages */
+       const char *byers[] = {
+               /* Swiss-German form of "Ciao" */
+               "Tschau!",
+
+               /* Dutch for "they who are going, greet you" */
+               "Zij die gaan, groeten u",
+               "See you later alligator",
+               "A bitter thought, but I have to go",
+
+               /* Dutch for "see you later" */
+               "Ajuuu paraplu",
+               "Thank you for the information",
+               "It was lovely talking to you again",
+               "Tschussss...",
+               "Aufwiedersehen",
+               "I'll be back. Ha, you didn't know I was going to say that!",
+               "We will be the only two people left in the world, Yes--Adam and Evil!",
+
+               /* Blutengel */
+               "Stranded",
+               "Die With You",
+               "The End Of Love",
+
+               /* Chamber */
+               "In My Garden",
+               "Set Me Free",
+
+               /* Faithless */
+               "Don't Leave",
+               "Insomnia",
+               "Why Go",
+
+               /* Garbage */
+               "The Trick Is To Keep Breathing",
+
+               /* The Gathering */
+               "We just stopped breating",
+               "Even the spirits are afraid",
+
+               /* Goldfrapp */
+               "Deer Stop",
+
+               /* Hooverphonic */
+               "The Last Thing I Need Is You",
+               "Every Time We Live Together",
+               "My Autumn's Done Come",
+
+               /* Infected Mushroom */
+               "Never Ever Land",
+               "None of this is real",
+               "Nothing Comes Easy",
+               "Illuminaughty",
+
+               /* Nine Inch Nails */
+               "Something I can never have",
+               "And All That Could Have Been...",
+               "That's what I get",
+
+               /* Opeth */
+               "Under the weeping moon",
+               "For Absent Friends",
+
+               /* Portishead */
+               "It Could Be Sweet",
+               "Half Day Closing",
+
+               /* Suicide Commando */
+               "Better Off Dead",
+
+               /* VNV Nation */
+               "Solitary",
+               "Forsaken",
+               "Holding On",
+
+               /* Within Temptation */
+               "This is not our farewell",
+               "Running Down That Hill",
+
+               /* Wumpscut */
+               "Schaltet den schmerz ab",
+               "Down where we belong",
+       };
+
+       /* Already disconnected? */
+       if (!tic->sock) return;
+
+       if (!quitmsg)
+       {
+               /* Stupid random quit messages, got to put some form of easteregg in it :) */
+               srand((unsigned)time(NULL));
+
+               quitmsg = (char *)byers[rand()%(sizeof(byers)/sizeof(char *))];
+       }
+
+       /* Send our bye bye */
+       sock_printf(tic->sock, "QUIT %s\n", quitmsg);
+
+       /* Disconnect */
+       sock_free(tic->sock);
+       tic->sock = NULL;
+}
+
+struct TIC_sTunnel *tic_ListTunnels(struct TIC_conf *tic)
+{
+       char                    buf[1024], buf2[1024];
+       struct TIC_sTunnel      *start = NULL, *last = NULL, *tun = NULL;
+       int                     i;
+
+/* Request a list of Tunnels */
+       sock_printf(tic->sock, "tunnel list\n");
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return NULL;
+       }
+
+       /* 201 (start of list) ? */
+       if (buf[0] != '2' || buf[1] != '0' || buf[2] != '1')
+       {
+               dolog(LOG_ERR, "Couldn't list tunnels: %s.\n", &buf[4]);
+               return NULL;
+       }
+
+       /* Process all the lines */
+       while (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) != -1)
+       {
+               /* 202 (end of list) ? */
+               if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2') break;
+               
+               i = countfields(buf);
+               if (i != 4)
+               {
+                       dolog(LOG_ERR, "Wrong field format when listing tunnels\n");
+                       break;
+               }
+
+               /* Allocate a new struct */
+               tun = (struct TIC_sTunnel *)malloc(sizeof(*tun));
+               if (!tun)
+               {
+                       dolog(LOG_ERR, "Memory problem while listing tunnels\n");
+                       break;
+               }
+               memset(tun, 0, sizeof(*tun));
+
+               /* Copy the fields into the struct */
+               if (!copyfield(buf, 1, buf2, sizeof(buf2))) break;
+               tun->sId = strdup(buf2);
+               if (!copyfield(buf, 2, buf2, sizeof(buf2))) break;
+               tun->sIPv6 = strdup(buf2);
+               if (!copyfield(buf, 3, buf2, sizeof(buf2))) break;
+               tun->sIPv4 = strdup(buf2);
+               if (!copyfield(buf, 4, buf2, sizeof(buf2))) break;
+               tun->sPOPId = strdup(buf2);
+               
+               /* Add it into the list */
+               if (last)
+               {
+                       last->next = tun;
+                       last = tun;
+               }
+               else
+               {
+                       start = last = tun;
+               }
+       }
+
+       /* All went okay? */
+       if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
+       {
+               return start;
+       }
+
+       /* Free the structure, it was broken anyway */
+       tic_Free_sTunnel(start);
+
+       dolog(LOG_ERR, "Tunnel list went wrong: %s\n", &buf[4]);
+       return NULL;
+}
+
+struct TIC_sRoute *tic_ListRoutes(struct TIC_conf *tic)
+{
+       dolog(LOG_ERR, "Not implemented - tic_ListRoutes(%x)\n", tic);
+       return NULL;
+}
+
+struct TIC_sPOP *tic_ListPOPs(struct TIC_conf *tic)
+{
+       dolog(LOG_ERR, "Not implemented - tic_ListPOPs(%x)\n", tic);
+       return NULL;
+}
+
+struct pl_rule tunnel_rules[] =
+{
+       {"TunnelId",            PLRT_STRING,    offsetof(struct TIC_Tunnel, sId)},
+       {"Type",                PLRT_STRING,    offsetof(struct TIC_Tunnel, sType)},
+       {"IPv6 Endpoint",       PLRT_STRING,    offsetof(struct TIC_Tunnel, sIPv6_Local)},
+       {"IPv6 POP",            PLRT_STRING,    offsetof(struct TIC_Tunnel, sIPv6_POP)},
+       {"IPv6 PrefixLength",   PLRT_INTEGER,   offsetof(struct TIC_Tunnel, nIPv6_PrefixLength)},
+       {"POP Id",              PLRT_STRING,    offsetof(struct TIC_Tunnel, sPOP_Id)},
+       {"IPv4 Endpoint",       PLRT_STRING,    offsetof(struct TIC_Tunnel, sIPv4_Local)},
+       {"IPv4 POP",            PLRT_STRING,    offsetof(struct TIC_Tunnel, sIPv4_POP)},
+       {"UserState",           PLRT_STRING,    offsetof(struct TIC_Tunnel, sUserState)},
+       {"AdminState",          PLRT_STRING,    offsetof(struct TIC_Tunnel, sAdminState)},
+       {"Password",            PLRT_STRING,    offsetof(struct TIC_Tunnel, sPassword)},
+       {"Heartbeat_Interval",  PLRT_INTEGER,   offsetof(struct TIC_Tunnel, nHeartbeat_Interval)},
+       {"Tunnel MTU",          PLRT_INTEGER,   offsetof(struct TIC_Tunnel, nMTU)},
+       {NULL,                  PLRT_END,       0},
+};
+
+struct TIC_Tunnel *tic_GetTunnel(struct TIC_conf *tic, const char *sId)
+{
+       char                    buf[1024];
+       struct TIC_Tunnel       *tun;
+
+       /* Get a Tunnel */
+       sock_printf(tic->sock, "tunnel show %s\n", sId);
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return NULL;
+       }
+
+       /* 201 (start of information) ? */
+       if (buf[0] != '2' || buf[1] != '0' || buf[2] != '1')
+       {
+               dolog(LOG_ERR, "Couldn't show tunnel %s: %s.\n", sId, buf);
+               return NULL;
+       }
+
+       /* Allocate a new struct */
+       tun = (struct TIC_Tunnel *)malloc(sizeof(*tun));
+       if (!tun)
+       {
+               dolog(LOG_ERR, "Memory problem while getting tunnel %s\n", sId);
+               return NULL;
+       }
+       memset(tun, 0, sizeof(*tun));
+
+       /* Gather the information */
+       while (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) != -1)
+       {
+               /* 202 (end of list) ? */
+               if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2') break;
+               
+               parseline(buf, ": ", tunnel_rules, tun);
+       }
+       /* All went okay? */
+       if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
+       {
+               struct in6_addr ipv6_ll, ipv6_local;
+               char ll[100];
+
+               /* Log that the fetch was succesful */
+               dolog(LOG_INFO, "Succesfully retrieved tunnel information for %s\n", sId);
+
+               /*
+                * Some TUN/TAP devices don't have any
+                * link local addresses and we want multicast and MLD to work
+                * thus we invent one based on the following:
+                *
+                * ipv6_us = 2001:0db8:1234:5678:    :    :    :0001
+                * ipv6_ll = fe80:    :    :    :0db8:1234:5678:0001
+                *
+                * Thus we ignore the first 16bits, take the following 48 bits
+                * and then add the last 16bits.
+                *
+                * As we are not 100% sure that this LL is unique we clear that bit.
+                */
+
+               inet_pton(AF_INET6, tun->sIPv6_Local, &ipv6_local);
+
+               /* Link Local (fe80::/64) */
+               ipv6_ll.s6_addr[ 0] = 0xfe;
+               ipv6_ll.s6_addr[ 1] = 0x80;
+               ipv6_ll.s6_addr[ 2] = 0x00;
+               ipv6_ll.s6_addr[ 3] = 0x00;
+               ipv6_ll.s6_addr[ 4] = 0x00;
+               ipv6_ll.s6_addr[ 5] = 0x00;
+               ipv6_ll.s6_addr[ 6] = 0x00;
+               ipv6_ll.s6_addr[ 7] = 0x00;
+               ipv6_ll.s6_addr[ 8] = ipv6_local.s6_addr[ 2] & 0xfc; /* Clear the LL Unique Bit */
+               ipv6_ll.s6_addr[ 9] = ipv6_local.s6_addr[ 3];
+               ipv6_ll.s6_addr[10] = ipv6_local.s6_addr[ 4];
+               ipv6_ll.s6_addr[11] = ipv6_local.s6_addr[ 5];
+               ipv6_ll.s6_addr[12] = ipv6_local.s6_addr[ 6];
+               ipv6_ll.s6_addr[13] = ipv6_local.s6_addr[ 7];
+               ipv6_ll.s6_addr[14] = ipv6_local.s6_addr[14];
+               ipv6_ll.s6_addr[15] = ipv6_local.s6_addr[15];
+
+               inet_ntop(AF_INET6, &ipv6_ll, ll, sizeof(ll));
+               if (tun->sIPv6_LinkLocal) free(tun->sIPv6_LinkLocal);
+               tun->sIPv6_LinkLocal = strdup(ll);
+
+               if (    strcmp(tun->sType, "ayiya") == 0 ||
+                       strcmp(tun->sType, "l2tp") == 0)
+               {
+                       tun->uses_tundev = 1;
+#ifdef NO_IFHEAD
+                       dolog(LOG_ERR, "This build doesn't support the Tun/TAP device and thus can't instantiate tunnels of type %s, please fix your OS and recompile\n", tun->sType);
+                       tic_Free_Tunnel(tun);
+                       return NULL;
+#endif
+               }
+               else tun->uses_tundev = 0;
+
+               /* Need to override the local IPv4 address? */
+               if (g_aiccu->local_ipv4_override)
+               {
+                       dolog(LOG_INFO, "Overriding Local IPv4 address from %s to %s\n", tun->sIPv4_Local, g_aiccu->local_ipv4_override);
+                       free(tun->sIPv4_Local);
+                       tun->sIPv4_Local = strdup(g_aiccu->local_ipv4_override);
+               }
+
+               return tun;
+       }
+
+       /* Free the structure, it is broken anyway */
+       tic_Free_Tunnel(tun);
+
+       dolog(LOG_ERR, "Tunnel Get for %s went wrong: %s\n", sId, buf);
+       return NULL;
+}
+
+struct TIC_Route *tic_GetRoute(struct TIC_conf *tic, const char *sId)
+{
+       dolog(LOG_ERR, "Not implemented - tic_GetRoute(%x, \"%s\")\n", tic, sId);
+       return NULL;
+}
+
+struct pl_rule pop_rules[] =
+{
+       {"POPId",               PLRT_STRING,    offsetof(struct TIC_POP, sId)},
+       {"City",                PLRT_STRING,    offsetof(struct TIC_POP, sCity)},
+       {"Country",             PLRT_STRING,    offsetof(struct TIC_POP, sCountry)},
+       {"IPv4",                PLRT_STRING,    offsetof(struct TIC_POP, sIPv4)},
+       {"IPv6",                PLRT_STRING,    offsetof(struct TIC_POP, sIPv6)},
+
+       {"ISP Short",           PLRT_STRING,    offsetof(struct TIC_POP, sISP_Short)},
+       {"ISP Name",            PLRT_STRING,    offsetof(struct TIC_POP, sISP_Name)},
+       {"ISP Website",         PLRT_STRING,    offsetof(struct TIC_POP, sISP_Website)},
+       {"ISP ASN",             PLRT_STRING,    offsetof(struct TIC_POP, sISP_ASN)},
+       {"ISP LIR",             PLRT_STRING,    offsetof(struct TIC_POP, sISP_LIR)},
+
+       {NULL,                  PLRT_END,       0},
+};
+
+struct TIC_POP *tic_GetPOP(struct TIC_conf *tic, const char *sId)
+{
+       char                    buf[1024];
+       struct TIC_POP          *pop;
+
+       /* Get a Tunnel */
+       sock_printf(tic->sock, "pop show %s\n", sId);
+
+       /* Fetch the answer */
+       if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
+       {
+               return NULL;
+       }
+
+       /* 201 (start of info) ? */
+       if (buf[0] != '2' || buf[1] != '0' || buf[2] != '1')
+       {
+               dolog(LOG_ERR, "Couldn't show POP %s: %s.\n", sId, buf);
+               return NULL;
+       }
+
+       /* Allocate a new struct */
+       pop = (struct TIC_POP *)malloc(sizeof(*pop));
+       if (!pop)
+       {
+               dolog(LOG_ERR, "Memory problem while getting POP\n");
+               return NULL;
+       }
+       memset(pop, 0, sizeof(*pop));
+
+       /* Gather the information */
+       while (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) != -1)
+       {
+               /* 202 (end of list) ? */
+               if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2') break;
+               
+               parseline(buf, ": ", pop_rules, pop);
+       }
+       /* All went okay? */
+       if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
+       {
+               dolog(LOG_INFO, "Succesfully retrieved POP information for %s\n", sId);
+               return pop;
+       }
+
+       /* Free the structure, it is broken anyway */
+       tic_Free_POP(pop);
+
+       dolog(LOG_ERR, "POP Get for %s went wrong: %s\n", sId, buf);
+       return NULL;
+}
+
+void tic_Free_sTunnel(struct TIC_sTunnel *tun)
+{
+       struct TIC_sTunnel *next;
+
+       for (; tun; tun = next)
+       {
+               next = tun->next;
+               if (tun->sId)           free(tun->sId);
+               if (tun->sIPv6)         free(tun->sIPv6);
+               if (tun->sIPv4)         free(tun->sIPv4);
+               if (tun->sPOPId)        free(tun->sPOPId);
+               free(tun);
+       }
+}
+
+void tic_Free_sRoute(struct TIC_sRoute *rt)
+{
+       struct TIC_sRoute *next;
+
+       for (; rt; rt = next)
+       {
+               next = rt->next;
+               if (rt->sId)            free(rt->sId);
+               if (rt->sTunnelId)      free(rt->sTunnelId);
+               if (rt->sIPv6)          free(rt->sIPv6);
+               free(rt);
+       }
+}
+
+void tic_Free_sPOP(struct TIC_sPOP *pop)
+{
+       struct TIC_sPOP *next;
+
+       for (; pop; pop = next)
+       {
+               next = pop->next;
+               if (pop->sId)   free(pop->sId);
+               free(pop);
+       }
+}
+
+void tic_Free_Tunnel(struct TIC_Tunnel *tun)
+{
+       if (tun->sId)           { free(tun->sId);               tun->sId                = NULL; }
+       if (tun->sType)         { free(tun->sType);             tun->sType              = NULL; }
+       if (tun->sPOP_Id)       { free(tun->sPOP_Id);           tun->sPOP_Id            = NULL; }
+       if (tun->sUserState)    { free(tun->sUserState);        tun->sUserState         = NULL; }
+       if (tun->sAdminState)   { free(tun->sAdminState);       tun->sAdminState        = NULL; }
+       if (tun->sPassword)     { free(tun->sPassword);         tun->sPassword          = NULL; }
+       if (tun->sIPv4_Local)   { free(tun->sIPv4_Local);       tun->sIPv4_Local        = NULL; }
+       if (tun->sIPv4_POP)     { free(tun->sIPv4_POP);         tun->sIPv4_POP          = NULL; }
+       if (tun->sIPv6_Local)   { free(tun->sIPv6_Local);       tun->sIPv6_Local        = NULL; }
+       if (tun->sIPv6_POP)     { free(tun->sIPv6_POP);         tun->sIPv6_POP          = NULL; }
+       free(tun);
+       tun = NULL;
+}
+
+void tic_Free_Route(struct TIC_Route *rt)
+{
+       if (rt->sId)            free(rt->sId);
+       if (rt->sTunnelId)      free(rt->sTunnelId);
+       free(rt);
+}
+
+void tic_Free_POP(struct TIC_POP *pop)
+{
+       if (pop->sId)           free(pop->sId);
+       if (pop->sCity)         free(pop->sCity);
+       if (pop->sCountry)      free(pop->sCountry);
+       if (pop->sIPv4)         free(pop->sIPv4);
+       if (pop->sIPv6)         free(pop->sIPv6);
+       if (pop->sISP_Short)    free(pop->sISP_Short);
+       if (pop->sISP_Name)     free(pop->sISP_Name);
+       if (pop->sISP_Website)  free(pop->sISP_Website);
+       if (pop->sISP_ASN)      free(pop->sISP_ASN);
+       if (pop->sISP_LIR)      free(pop->sISP_LIR);
+
+       free(pop);
+}
diff --git a/common/tic.h b/common/tic.h
new file mode 100755 (executable)
index 0000000..d3c3dfe
--- /dev/null
@@ -0,0 +1,147 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/tic.h - Tunnel Information & Control Protocol
+***********************************************************
+ $Author: jeroen $
+ $Id: tic.h,v 1.12 2006-12-21 14:08:50 jeroen Exp $
+ $Date: 2006-12-21 14:08:50 $
+**********************************************************/
+
+#ifndef TIC_H
+#define TIC_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#include "common.h"
+
+/* 
+ * Tunnel Information Control Protocol
+ * server
+ */
+/* port - uses TCP over IPv4 */
+#define TIC_PORT       "3874"
+
+/* TIC version (which document this should conform to) */
+#define TIC_VERSION    "draft-00"
+
+struct TIC_sTunnel
+{
+       struct TIC_sTunnel      *next;                  /* Next in list */
+       char                    *sId;                   /* Tunnel Id */
+       char                    *sIPv6;                 /* Local IPv6 Endpoint */
+       char                    *sIPv4;                 /* Local IPv4 Endpoint */
+       char                    *sPOPId;                /* POP Id */
+};
+
+struct TIC_Tunnel
+{
+       char                    *sId;                   /* Tunnel Id */
+       char                    *sType;                 /* Tunnel Type */
+
+       /* IPv4 information */
+       char                    *sIPv4_Local;           /* Local endpoint (*) */
+       char                    *sIPv4_POP;             /* POP endpoint  */
+
+       /* IPv6 information */
+       char                    *sIPv6_Local;           /* Local endpoint */
+       char                    *sIPv6_POP;             /* POP endpoint  */
+       char                    *sIPv6_LinkLocal;       /* Link local address */
+
+       /* POP information */
+       char                    *sPOP_Id;               /* POP's Id */
+       
+       /* States */
+       char                    *sUserState;            /* Userstate */
+       char                    *sAdminState;           /* Adminstate */
+       
+       /* AYIYA & Heartbeat */
+       char                    *sPassword;             /* Password for the tunnel */
+       uint32_t                nHeartbeat_Interval;    /* Heartbeat interval */
+
+       /* Misc */
+       uint32_t                uses_tundev;            /* Uses Tunnel (tun/tap) device? */
+       uint32_t                nIPv6_PrefixLength;     /* Length of the prefix's */
+       uint32_t                nMTU;                   /* MTU size */
+};
+
+/* * = 0.0.0.0 for all the dynamic tunnels */
+
+struct TIC_sRoute
+{
+       struct TIC_sRoute       *next;                  /* Next in list */
+       char                    *sId;                   /* Route Id */
+       char                    *sTunnelId;             /* Tunnel Id */
+       char                    *sIPv6;                 /* Prefix */
+};
+
+struct TIC_Route
+{
+       char                    *sId;                   /* Route Id */
+       char                    *sTunnelId;             /* Tunnel Id */
+       struct in6_addr         xIPv6;                  /* Prefix */
+       uint32_t                nPrefixLength;          /* Length of the prefix */
+       uint32_t                __pad;
+};
+
+
+struct TIC_sPOP
+{
+       struct TIC_sPOP         *next;                  /* Next in list */
+       char                    *sId;                   /* POP's Id */
+};
+
+struct TIC_POP
+{
+       char                    *sId;                   /* POP's Id */
+       char                    *sCity;                 /* POP's City */
+       char                    *sCountry;              /* POP's Country */
+       char                    *sIPv4;                 /* POP's Primary IPv4 address */
+       char                    *sIPv6;                 /* POP's Primary IPv6 address */
+
+       char                    *sISP_Short;            /* ISP's Short name */
+       char                    *sISP_Name;             /* ISP's Name */
+       char                    *sISP_Website;          /* ISP's Website */
+       char                    *sISP_ASN;              /* ISP's ASN */
+       char                    *sISP_LIR;              /* ISP's LIR */
+};
+
+/*
+ * This structure makes TIC a bit more abstracted
+ * which makes this cleaner instead of passing 'sock' everywhere
+ */
+struct TIC_conf
+{
+       TLSSOCKET               sock;           /* The socket to which we are connected */
+};
+
+/**********************************************************
+ TIC Functions
+**********************************************************/
+
+/* Login to/Logout from the TIC Server */
+bool tic_Login(struct TIC_conf *tic, const char *username, const char *password, const char *server);
+void tic_Logout(struct TIC_conf *tic, const char *quitmsg);
+
+/* Check if the time is in range */
+int tic_checktime(time_t epochtime);
+
+/* Get Tunnel/Route/POP List */
+struct TIC_sTunnel     *tic_ListTunnels(struct TIC_conf *tic);
+struct TIC_sRoute      *tic_ListRoutes(struct TIC_conf *tic);
+struct TIC_sPOP                *tic_ListPOPs(struct TIC_conf *tic);
+
+/* Get Tunnel/Route/POP Information */
+struct TIC_Tunnel      *tic_GetTunnel(struct TIC_conf *tic, const char *sId);
+struct TIC_Route       *tic_GetRoute(struct TIC_conf *tic, const char *sId);
+struct TIC_POP         *tic_GetPOP(struct TIC_conf *tic, const char *sId);
+
+/* Free Information structures */
+void                   tic_Free_sTunnel(struct TIC_sTunnel *tun);
+void                   tic_Free_sRoute(struct TIC_sRoute *rt);
+void                   tic_Free_sPOP(struct TIC_sPOP *pop);
+void                   tic_Free_Tunnel(struct TIC_Tunnel *tun);
+void                   tic_Free_Route(struct TIC_Route *rt);
+void                   tic_Free_POP(struct TIC_POP *pop);
+
+#endif /* TIC_H */
diff --git a/common/tun.c b/common/tun.c
new file mode 100755 (executable)
index 0000000..c5b6323
--- /dev/null
@@ -0,0 +1,866 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/tun.c - Tunnel Device Handling
+***********************************************************
+ $Author: jeroen $
+ $Id: tun.c,v 1.14 2007-01-11 00:29:18 jeroen Exp $
+ $Date: 2007-01-11 00:29:18 $
+**********************************************************/
+
+#include "tun.h"
+#include "aiccu.h"
+
+/* The tun/tap device HANDLE */
+#ifndef _WIN32
+int                    tun_fd;
+
+/*
+ * HAS_IFHEAD -> Tunnel Device produces packets with a tun_pi in the front
+ * NEED_IFHEAD -> Tunnel Device produces packets with a tun_pi in the front, but it is not active per default
+ */ 
+
+#else
+HANDLE                 device_handle = INVALID_HANDLE_VALUE;
+#define ETH_P_IPV6 0x86dd
+#define ETH_ALEN 6
+struct ether_header
+{
+       uint8_t         ether_dhost[ETH_ALEN];  /* destination eth addr */
+       uint8_t         ether_shost[ETH_ALEN];  /* source ether addr    */
+       uint16_t        ether_type;             /* packet type ID field */
+};
+
+/* Tap device constants which we use */
+#define TAP_CONTROL_CODE(request,method) CTL_CODE(FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
+#define TAP_IOCTL_GET_VERSION           TAP_CONTROL_CODE(2, METHOD_BUFFERED)
+#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE(5, METHOD_BUFFERED)
+#define TAP_IOCTL_SET_MEDIA_STATUS      TAP_CONTROL_CODE(6, METHOD_BUFFERED)
+#define TAP_REGISTRY_KEY               "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+#define TAP_ADAPTER_KEY                        "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"
+#define TAP_DEVICE_DIR                 "\\\\.\\Global\\"
+#define TAP_WIN32_MIN_MAJOR            8
+#define TAP_WIN32_MIN_MINOR            1
+#define TAP_COMPONENT_ID1              "tap0801"       /* Original Tun/Tap driver ID */
+#define TAP_COMPONENT_ID2              "tap0802"       /* Windows Vista marked 801 as broken, thus use another ID */
+
+#endif
+
+void tun_log(int level, const char *what, const char *fmt, ...);
+void tun_log(int level, const char *what, const char *fmt, ...)
+{
+       char    buf[1024];
+       va_list ap;
+
+        /* Clear them just in case */
+        memset(buf, 0, sizeof(buf));
+
+       snprintf(buf, sizeof(buf), "[tun-%s] ", what);
+
+       /* Print the log message behind it */
+       va_start(ap, fmt);
+       vsnprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), fmt, ap);
+       va_end(ap);
+
+       /* Actually Log it */
+       dolog(level, buf);
+}
+
+static const char reader_name[] = "tundev->tun";
+static const char writer_name[] = "tun->tundev";
+
+#ifdef _WIN32
+/* Windows doesn't have writev() but does have WSASend */
+int writev(SOCKET sock, const struct iovec *vector, DWORD count)
+{
+       DWORD sent;
+       WSASend(sock, (LPWSABUF)vector, count, &sent, 0, NULL, NULL);
+       return sent;
+}
+
+uint16_t inchksum(const void *data, uint32_t length);
+uint16_t inchksum(const void *data, uint32_t length)
+{
+        register long           sum = 0;
+        register const uint16_t *wrd = (const uint16_t *)data;
+        register long           slen = (long)length;
+
+        while (slen >= 2)
+        {
+                sum += *wrd++;
+                slen-=2;
+        }
+
+        if (slen > 0) sum+=*(const uint8_t *)wrd;
+
+        while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16);
+
+        return (uint16_t)sum;
+}
+
+uint16_t ipv6_checksum(const struct ip6_hdr *ip6, uint8_t protocol, const void *data, const uint16_t length);
+uint16_t ipv6_checksum(const struct ip6_hdr *ip6, uint8_t protocol, const void *data, const uint16_t length)
+{
+        struct
+        {
+                uint16_t        length;
+                uint16_t        zero1;
+                uint8_t         zero2;
+                uint8_t         next;
+        } pseudo;
+        register uint32_t       chksum = 0;
+
+        pseudo.length   = htons(length);
+        pseudo.zero1    = 0;
+        pseudo.zero2    = 0;
+        pseudo.next     = protocol;
+
+        /* IPv6 Source + Dest */
+        chksum  = inchksum(&ip6->ip6_src, sizeof(ip6->ip6_src) + sizeof(ip6->ip6_dst));
+        chksum += inchksum(&pseudo, sizeof(pseudo));
+        chksum += inchksum(data, length);
+
+        /* Wrap in the carries to reduce chksum to 16 bits. */
+        chksum  = (chksum >> 16) + (chksum & 0xffff);
+        chksum += (chksum >> 16);
+
+        /* Take ones-complement and replace 0 with 0xFFFF. */
+        chksum = (uint16_t) ~chksum;
+        if (chksum == 0UL) chksum = 0xffffUL;
+        return (uint16_t)chksum;
+}
+#endif
+
+/*
+ * Tun -> Socket
+ *
+ * Needs to be started in a separate thread
+ * This gets done by tun_start()
+ *
+ */
+#ifndef _WIN32
+void *tun_reader(void *arg);
+void *tun_reader(void *arg)
+#else
+DWORD WINAPI tun_reader(LPVOID arg);
+DWORD WINAPI tun_reader(LPVOID arg)
+#endif
+{
+       unsigned char           buf[2048];
+
+       /* The function that actually does something with the buffer */
+       struct tun_reader       *tun = (struct tun_reader *)arg;
+
+#ifdef _WIN32
+       DWORD                   n, lenin;
+       OVERLAPPED              overlapped;
+       unsigned int            errcount = 0;
+
+       struct nd_sol
+       {
+               struct ip6_hdr                  ip;
+               struct icmp6_hdr                icmp;
+               struct nd_neighbor_solicit      sol;
+       } *solic = (struct nd_sol *)&buf[sizeof(struct ether)];
+
+       struct nd_adv
+       {
+               struct ip6_hdr                  ip;
+               struct icmp6_hdr                icmp;
+               struct nd_neighbor_advert       adv;
+       } advert;
+
+       /* Create an event for overlapped results */
+       overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+#else
+       ssize_t                 n;
+#endif
+
+       /* Forever */
+       while (true)
+       {
+#ifndef _WIN32 
+               n = read(tun_fd, buf, sizeof(buf));
+               if (n <= 0)
+               {
+                       /* Only report issues when the tunnel is actually up and running */
+                       if (g_aiccu->tunrunning) tun_log(LOG_ERR, reader_name, "Read error on Tun Device: %s (%d)\n", strerror(errno), errno);
+                       continue;
+               }
+
+#if defined(NEED_IFHEAD) || defined(HAS_IFHEAD)
+               /* get the tun_pi struct out of there */
+               memmove(&buf, &buf[4], n-4);
+               n-=4;
+#endif
+
+               tun->function((char *)buf, (unsigned int)n);
+#else /* Windows */
+               overlapped.Offset = 0;
+               overlapped.OffsetHigh = 0;
+
+               memset(buf,0,sizeof(buf));
+               n = ReadFile(device_handle, buf, sizeof(buf), &lenin, &overlapped);
+               if (!n)
+               {
+                       while (!n && GetLastError() == ERROR_IO_PENDING)
+                       {
+                               if (WaitForSingleObject(overlapped.hEvent, 20000) == WAIT_OBJECT_0)
+                               {
+                                       n = GetOverlappedResult(device_handle, &overlapped, &lenin, FALSE);
+                               }
+                       }
+
+                       if (!n)
+                       {
+                               tun_log(LOG_ERR, reader_name, "Error reading from device: %u, %s (%d)\n", GetLastError(), strerror(errno), errno);
+                               errcount++;
+                               if (errcount > 10) break;
+                               continue;
+                       }
+               }
+
+               /* Check for neighbour discovery packets (ICMPv6, ND_SOL, hop=255)
+                * (XXX: doesn't check for a chain, but ND is usually without)
+                */
+               if (    solic->ip.ip6_ctlun.ip6_un1.ip6_un1_nxt == IPPROTO_ICMPV6 &&
+                       solic->icmp.icmp6_type == ND_NEIGHBOR_SOLICIT &&
+                       solic->ip.ip6_ctlun.ip6_un1.ip6_un1_hlim == 255)
+               {
+                       /* Ignore unspecified ND's as they are used for DAD */
+                       if (IN6_IS_ADDR_UNSPECIFIED(&solic->ip.ip6_src)) continue;
+
+                       /* Create our reply */
+                       memset(&advert, 0, sizeof(advert));
+                       advert.ip.ip6_ctlun.ip6_un2_vfc = 6 << 4;
+                       advert.ip.ip6_ctlun.ip6_un1.ip6_un1_flow = solic->ip.ip6_ctlun.ip6_un1.ip6_un1_flow;
+                       advert.ip.ip6_ctlun.ip6_un1.ip6_un1_plen = htons(sizeof(advert.icmp) + sizeof(advert.adv));
+                       advert.ip.ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_ICMPV6;
+                       advert.ip.ip6_ctlun.ip6_un1.ip6_un1_hlim = 255;
+
+                       /* Swap src/dst */
+                       memcpy(&advert.ip.ip6_src, &solic->sol.nd_ns_target, sizeof(advert.ip.ip6_src));
+                       memcpy(&advert.ip.ip6_dst, &solic->ip.ip6_src, sizeof(advert.ip.ip6_dst));
+
+                       /* ICMP Neighbour Advertisement */
+                       advert.icmp.icmp6_type = ND_NEIGHBOR_ADVERT;
+                       advert.icmp.icmp6_code = 0;
+                       advert.icmp.icmp6_dataun.icmp6_un_data8[0] = 0xe0;
+                       memcpy(&advert.adv.nd_na_target, &solic->sol.nd_ns_target, sizeof(advert.adv.nd_na_target));
+                       /* Fake MAC address */
+                       advert.adv.nd_no_type = 2;
+                       advert.adv.nd_no_len = 1;
+                       advert.adv.nd_no_mac[0] = 0x00;
+                       advert.adv.nd_no_mac[1] = 0xff;
+                       advert.adv.nd_no_mac[2] = 0x25;
+                       advert.adv.nd_no_mac[3] = 0x02;
+                       advert.adv.nd_no_mac[4] = 0x19;
+                       advert.adv.nd_no_mac[5] = 0x78;
+
+                       /* ICMP has a checksum */
+                       advert.icmp.icmp6_cksum = ipv6_checksum(&advert.ip, IPPROTO_ICMPV6, (uint8_t *)&advert.icmp, sizeof(advert.icmp) + sizeof(advert.adv));
+
+                       /* We'll need to answer this back to the TAP device */
+                       tun_write((char *)&advert, (unsigned int)sizeof(advert));
+                       continue;
+               }
+               tun->function((char *)&buf[sizeof(struct ether)], (unsigned int)lenin - sizeof(struct ether));
+#endif
+       }
+
+       D(dolog(LOG_DEBUG, "TUN Reader stopping\n"));
+#ifndef _WIN32
+       return NULL;
+#else
+       return 0;
+#endif
+}
+
+/* Socket -> Tun */
+void tun_write(char *buf, unsigned int length)
+{
+       unsigned int    c = 0;
+#ifndef _WIN32
+#ifdef linux
+       struct iovec    dat[2];
+       struct tun_pi   pi;
+       memset(&pi, 0, sizeof(pi));
+
+       pi.proto = htons(ETH_P_IPV6);
+
+       dat[0].iov_base = &pi;
+       dat[0].iov_len  = sizeof(pi);
+       dat[1].iov_base = buf;
+       dat[1].iov_len  = length;
+
+       length += sizeof(pi);
+
+       /* Forward the packet to the kernel */
+       c = writev(tun_fd, dat, 2);
+
+#else /* *BSD/Darwin */
+
+       uint32_t        type = htonl(AF_INET6);
+       struct iovec    dat[2];
+
+       dat[0].iov_base = (void *)&type;
+       dat[0].iov_len  = sizeof(type);
+       dat[1].iov_base = buf;
+       dat[1].iov_len  = length;
+
+       length += sizeof(type);
+
+       /* Forward the packet to the kernel */
+       c = writev(tun_fd, dat, 2);
+
+#endif
+
+       if (c != length)
+       {
+               tun_log(LOG_ERR, writer_name, "Error while writing to TUN: %u != %u\n", c, length);
+       }
+
+#else /* Windows */
+       DWORD           n, lenout;
+       OVERLAPPED      overlapped;
+       unsigned char   mbuf[4096];
+
+       struct ether *eth = (struct ether *)mbuf;
+
+       /* Sent the packet outbound */
+       overlapped.Offset = 0;
+       overlapped.OffsetHigh = 0;
+       overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+       memset(mbuf,0,sizeof(mbuf));
+       eth->ether_dhost[0] = htons(0x3333);
+       eth->ether_dhost[1] = htons(0xff00);
+       eth->ether_dhost[2] = htons(0x0002);
+       eth->ether_shost[0] = htons(0x00ff);
+       eth->ether_shost[1] = htons(0x5342);
+       eth->ether_shost[2] = htons(0x2768);
+       eth->ether_type = htons(ETH_P_IPV6);
+       memcpy(&mbuf[sizeof(*eth)],buf,length);
+
+       n = WriteFile(device_handle, mbuf, sizeof(*eth)+length, &lenout, &overlapped);
+       if (!n && GetLastError() == ERROR_IO_PENDING)
+       {
+               WaitForSingleObject(overlapped.hEvent, INFINITE);
+               n = GetOverlappedResult(device_handle, &overlapped, &lenout, FALSE);
+       }
+
+       if (!n)
+       {
+               tun_log(LOG_ERR, writer_name, "Error writing to device: %u, %s (%d)\n", GetLastError(), strerror(errno), errno);
+       }
+#endif
+}
+
+#ifdef _WIN32
+
+struct tap_reg
+{
+       char                    *guid;
+       struct tap_reg          *next;
+};
+
+struct panel_reg
+{
+       char                    *name;
+       char                    *guid;
+       struct panel_reg        *next;
+};
+
+/* Get a working tunnel adapter */
+struct tap_reg *get_tap_reg(void)
+{
+       HKEY            adapter_key;
+       LONG            status;
+       DWORD           len;
+       struct tap_reg  *first = NULL;
+       struct tap_reg  *last = NULL;
+       int             i = 0;
+
+       status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_ADAPTER_KEY, 0, KEY_READ, &adapter_key);
+       if (status != ERROR_SUCCESS)
+       {
+               dolog(LOG_ERR, "Error opening registry key: %s\n", TAP_ADAPTER_KEY);
+               return NULL;
+       }
+
+       while (true)
+       {
+               char    enum_name[256];
+               char    unit_string[256];
+               HKEY    unit_key;
+               char    component_id_string[] = "ComponentId";
+               char    component_id[256];
+               char    net_cfg_instance_id_string[] = "NetCfgInstanceId";
+               char    net_cfg_instance_id[256];
+               DWORD   data_type;
+
+               len = sizeof(enum_name);
+               status = RegEnumKeyEx(adapter_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
+               if (status == ERROR_NO_MORE_ITEMS) break;
+               else if (status != ERROR_SUCCESS)
+               {
+                       dolog(LOG_ERR, "Error enumerating registry subkeys of key: %s (t0)\n", TAP_ADAPTER_KEY);
+                       break;
+               }
+
+               snprintf(unit_string, sizeof(unit_string), "%s\\%s", TAP_ADAPTER_KEY, enum_name);
+               status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, unit_string, 0, KEY_READ, &unit_key);
+               if (status != ERROR_SUCCESS)
+               {
+                       dolog(LOG_WARNING, "Error opening registry key: %s (t1)\n", unit_string);
+               }
+               else
+               {
+                       len = sizeof(component_id);
+                       status = RegQueryValueEx(unit_key, component_id_string, NULL, &data_type, (LPBYTE)component_id, &len);
+                       if (status != ERROR_SUCCESS || data_type != REG_SZ)
+                       {
+                               dolog(LOG_WARNING, "Error opening registry key: %s\\%s (t2)\n", unit_string, component_id_string);
+                       }
+                       else
+                       {
+                               len = sizeof(net_cfg_instance_id);
+                               status = RegQueryValueEx(unit_key, net_cfg_instance_id_string, NULL, &data_type, (LPBYTE)net_cfg_instance_id, &len);
+                               if (status == ERROR_SUCCESS && data_type == REG_SZ)
+                               {
+                                       if (    strcmp(component_id, TAP_COMPONENT_ID1) == 0 ||
+                                               strcmp(component_id, TAP_COMPONENT_ID2) == 0)
+                                       {
+                                               struct tap_reg *reg = (struct tap_reg *)malloc(sizeof(*reg));
+                                               memset(reg, 0, sizeof(*reg));
+                                               reg->guid = strdup(net_cfg_instance_id);
+
+                                               if (!first) first = reg;
+                                               if (last) last->next = reg;
+                                               last = reg;
+                                       }
+                               }
+                       }
+
+                       RegCloseKey(unit_key);
+               }
+               i++;
+       }
+
+       RegCloseKey(adapter_key);
+       return first;
+}
+
+void free_tap_reg(struct tap_reg *tap_reg)
+{
+       struct tap_reg *tr, *tr1;
+
+       for (tr = tap_reg; tr != NULL; tr = tr1)
+       {
+               tr1 = tr->next;
+               free(tr->guid);
+               free(tr);
+       }
+}
+
+void free_panel_reg(struct panel_reg *panel_reg)
+{
+       struct panel_reg *pr, *pr1;
+
+       for (pr = panel_reg; pr != NULL; pr = pr1)
+       {
+               pr1 = pr->next;
+               free(pr->guid);
+               free(pr->name);
+               free(pr);
+       }
+}
+
+
+/* Collect GUID's and names of all the Connections that are available */
+struct panel_reg *get_panel_reg(void)
+{
+       LONG                    status;
+       HKEY                    network_connections_key;
+       DWORD                   len;
+       struct panel_reg        *first = NULL;
+       struct panel_reg        *last = NULL;
+       int                     i = 0;
+
+       status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_REGISTRY_KEY, 0, KEY_READ, &network_connections_key);
+
+       if (status != ERROR_SUCCESS)
+       {
+               dolog(LOG_ERR, "Error opening registry key: %s (p0)\n", TAP_REGISTRY_KEY);
+               return NULL;
+       }
+
+       while (true)
+       {
+               char            enum_name[256];
+               char            connection_string[256];
+               HKEY            connection_key;
+               char            name_data[256];
+               DWORD           name_type;
+               const char      name_string[] = "Name";
+
+               len = sizeof(enum_name);
+               status = RegEnumKeyEx(network_connections_key, i, enum_name, &len, NULL, NULL, NULL, NULL);
+               if (status == ERROR_NO_MORE_ITEMS) break;
+               else if (status != ERROR_SUCCESS)
+               {
+                       dolog(LOG_ERR, "Error enumerating registry subkeys of key: %s (p1)\n", TAP_REGISTRY_KEY);
+                       break;
+               }
+
+               i++;
+
+               if (enum_name[0] != '{') continue;
+
+               snprintf(connection_string, sizeof(connection_string), "%s\\%s\\Connection", TAP_REGISTRY_KEY, enum_name);
+
+               status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, connection_string, 0, KEY_READ, &connection_key);
+               if (status != ERROR_SUCCESS)
+               {
+                       dolog(LOG_WARNING, "Error opening registry key: %s (p2)\n", connection_string);
+               }
+               else
+               {
+                       len = sizeof(name_data);
+                       status = RegQueryValueEx(connection_key, name_string, NULL, &name_type, (LPBYTE)name_data, &len);
+
+                       if (status != ERROR_SUCCESS || name_type != REG_SZ)
+                       {
+                               dolog(LOG_WARNING, "Error opening registry key: %s\\%s\\%s (p3)\n", TAP_REGISTRY_KEY, (LPBYTE)connection_string, name_string);
+                       }
+                       else
+                       {
+                               struct panel_reg *reg = (struct panel_reg *)malloc(sizeof(*reg));
+                               memset(reg, 0, sizeof(*reg));
+                               reg->name = strdup(name_data);
+                               reg->guid = strdup(enum_name);
+
+                               /* link into return list */
+                               if (!first) first = reg;
+                               if (last) last->next = reg;
+                               last = reg;
+                       }
+
+                       RegCloseKey(connection_key);
+               }
+       }
+
+       RegCloseKey(network_connections_key);
+
+       return first;
+}
+
+void tun_list_tap_adapters(void)
+{
+       int                     links;
+       struct tap_reg          *tap_reg = get_tap_reg(), *tr, *tr1;
+       struct panel_reg        *panel_reg = get_panel_reg(), *pr;
+
+       dolog(LOG_INFO, "Available TAP-WIN32 adapters [name, GUID]:\n");
+
+       /* loop through each TAP-Win32 adapter registry entry */
+       for (tr = tap_reg; tr != NULL; tr = tr->next)
+       {
+               links = 0;
+
+               /* loop through each network connections entry in the control panel */
+               for (pr = panel_reg; pr != NULL; pr = pr->next)
+               {
+                       if (strcmp(tr->guid, pr->guid) == 0)
+                       {
+                               dolog(LOG_INFO, "'%s' %s\n", pr->name, tr->guid);
+                               links++;
+                       }
+               }
+
+               if (links > 1)
+               {
+                       dolog(LOG_WARNING, "*** Adapter with GUID %s has %u links from the Network Connections control panel, it should only be 1\n", tr->guid, links);
+               }
+               else if (links == 0)
+               {
+                       dolog(LOG_WARNING, "[NULL] %s\n", tr->guid);
+                       dolog(LOG_WARNING, "*** Adapter with GUID %s doesn't have a link from the control panel\n", tr->guid);
+               }
+
+               /* check for TAP-Win32 adapter duplicated GUIDs */
+               for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next)
+               {
+                       if (tr != tr1 && strcmp(tr->guid, tr1->guid) == 0)
+                       {
+                               dolog(LOG_WARNING, "*** Duplicate Adapter GUID %s\n", tr->guid);
+                       }
+               }
+       }
+
+       free_tap_reg(tap_reg);
+       free_panel_reg(panel_reg);
+}
+
+bool tun_fixup_adapters(void)
+{
+       int                     links, count = 0, found = 0;
+       struct tap_reg          *tap_reg = get_tap_reg(), *tr = NULL, *tr1 = NULL;
+       struct panel_reg        *panel_reg = get_panel_reg(), *pr = NULL, *first = NULL, *prf = NULL;
+       bool                    ok;
+
+       /* loop through each TAP-Win32 adapter registry entry */
+       for (tr = tap_reg; tr != NULL; tr = tr->next)
+       {
+               links = 0;
+               ok = true;
+
+               /* loop through each network connections entry in the control panel */
+               for (pr = panel_reg; pr != NULL; pr = pr->next)
+               {
+                       if (strcmp(tr->guid, pr->guid) == 0)
+                       {
+                               links++;
+                               prf = pr;
+
+                               /* Is this the one wanted by the user? */
+                               if (strcasecmp(g_aiccu->ipv6_interface, pr->name) == 0) found++;
+                       }
+               }
+
+               if (links > 1)
+               {
+                       dolog(LOG_WARNING, "*** Adapter with GUID %s has %u links from the Network Connections control panel, it should only be 1\n", tr->guid, links);
+                       ok = false;
+               }
+               else if (links == 0)
+               {
+                       dolog(LOG_WARNING, "[NULL] %s\n", tr->guid);
+                       dolog(LOG_WARNING, "*** Adapter with GUID %s doesn't have a link from the control panel\n", tr->guid);
+                       ok = false;
+               }
+
+               /* check for TAP-Win32 adapter duplicated GUIDs */
+               for (tr1 = tap_reg; tr1 != NULL; tr1 = tr1->next)
+               {
+                       if (tr != tr1 && strcmp(tr->guid, tr1->guid) == 0)
+                       {
+                               dolog(LOG_WARNING, "*** Duplicate Adapter GUID %s\n", tr->guid);
+                               ok = false;
+                       }
+               }
+
+               if (ok)
+               {
+                       count++;
+                       first = prf;
+               }
+       }
+
+       ok = false;
+
+       /* When the user didn't configure us correctly and we find a single TAP interface, just rename it */
+       if (found == 0 && count == 1 && first)
+       {
+               dolog(LOG_INFO, "Renaming adapter '%s' to '%s' and using it\n", first->name, g_aiccu->ipv6_interface);
+               aiccu_win32_rename_adapter(first->name);
+               ok = true;
+       }
+       else if (found == 1 && count == 1)
+       {
+               D(dolog(LOG_DEBUG, "Using configured interface %s\n", g_aiccu->ipv6_interface));
+               ok = true;
+       }
+       else
+       {
+               ok = false;
+               dolog(LOG_WARNING, "Found = %u, Count = %u\n", found, count);
+       }
+
+       free_tap_reg(tap_reg);
+       free_panel_reg(panel_reg);
+
+       return ok;
+}
+
+#endif
+
+bool tun_start(struct tun_reader *tun)
+{
+#ifndef _WIN32
+       pthread_t               thread;
+#ifdef linux
+       struct ifreq            ifr;
+
+       /* Create a new tap device */
+       tun_fd = open("/dev/net/tun", O_RDWR);
+       if (tun_fd == -1)
+       {
+               tun_log(LOG_ERR, "start", "Couldn't open device %s: %s (%d)\n", "/dev/net/tun", strerror(errno), errno);
+               return false;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       /* Request a TUN device */
+       ifr.ifr_flags = IFF_TUN;
+       /* Set the interface name */
+       strncpy(ifr.ifr_name, g_aiccu->ipv6_interface, sizeof(ifr.ifr_name));
+
+       if (ioctl(tun_fd, TUNSETIFF, &ifr))
+       {
+               tun_log(LOG_ERR, "start", "Couldn't set interface name to %s: %s (%d)\n",
+                       g_aiccu->ipv6_interface, strerror(errno), errno);
+               return false;
+       }
+
+#else /* *BSD/Darwin */
+
+       char            buf[128];
+       unsigned int    i;
+       int             mode = IFF_MULTICAST | IFF_POINTOPOINT;
+
+       /* Try the configured interface */
+       tun_log(LOG_DEBUG, "start", "Trying Configured TUN/TAP interface %s...\n", g_aiccu->ipv6_interface);
+       snprintf(buf, sizeof(buf), "/dev/%s", g_aiccu->ipv6_interface);
+       tun_fd = open(buf, O_RDWR);
+       if (tun_fd < 0)
+       {
+               /* Fall back to trying all /dev/tun* devices */
+               for (i = 0; i < 256; ++i)
+               {
+                       snprintf(buf, sizeof(buf), "/dev/tun%u", i);
+                       tun_log(LOG_DEBUG, "start", "Trying TUN/TAP interface %s...\n", &buf[8]);
+                       tun_fd = open(buf, O_RDWR);
+                       if (tun_fd >= 0)
+                       {
+                               /* Copy over the name of the interface so that configging goes okay */
+                               if (g_aiccu->ipv6_interface) free(g_aiccu->ipv6_interface);
+                               snprintf(buf, sizeof(buf), "tun%u", i);
+                               g_aiccu->ipv6_interface = strdup(buf);
+                       }
+                       break;
+               }
+       }
+
+       if (tun_fd < 0)
+       {
+               tun_log(LOG_ERR, "start", "Couldn't open device %s or /dev/tun*: %s (%d)\n", g_aiccu->ipv6_interface, strerror(errno), errno);
+               return false;
+       }
+
+       tun_log(LOG_DEBUG, "start", "Using TUN/TAP interface %s\n", g_aiccu->ipv6_interface);
+
+#ifndef _FREEBSD
+#ifndef _DARWIN
+#ifndef _AIX
+       tun_log(LOG_DEBUG, "start", "Setting TUNSIFMODE for %s\n", g_aiccu->ipv6_interface);
+       if (ioctl(tun_fd, TUNSIFMODE, &mode, sizeof(mode)) == -1)
+       {
+               tun_log(LOG_ERR, "start", "Couldn't set interface %s's TUNSIFMODE to MULTICAST|POINTOPOINT: %s (%d)\n",
+                       g_aiccu->ipv6_interface, strerror(errno), errno);
+               close(tun_fd);
+               tun_fd = -1;
+               return false;
+       }
+#endif
+#endif
+#endif
+
+#ifdef NEED_IFHEAD
+       tun_log(LOG_DEBUG, "start", "Setting TUNSIFHEAD for %s\n", g_aiccu->ipv6_interface);
+       mode = 1;
+       if (ioctl(tun_fd, TUNSIFHEAD, &mode, sizeof(mode)) == -1)
+       {
+               tun_log(LOG_ERR, "start", "Couldn't set interface %s's TUNSIFHEAD to enabled: %s (%d)\n",
+                       g_aiccu->ipv6_interface, strerror(errno), errno);
+               close(tun_fd);
+               tun_fd = -1;
+               return false;
+       }
+#endif
+
+#endif /* linux */
+
+
+#else /* Windows */
+
+       HKEY            key;
+       DWORD           pID;
+       HANDLE          h;
+       int             i;
+
+       char            adapterid[1024];
+       char            tapname[1024];
+       DWORD           len;
+
+       if (!tun_fixup_adapters())
+       {
+               tun_log(LOG_ERR, "start", "TAP-Win32 Adapter not configured properly...\n");
+               return false;
+       }
+
+       /* Open registry and look for network adapters */
+       if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TAP_REGISTRY_KEY, 0, KEY_READ, &key))
+       {
+               tun_log(LOG_ERR, "start", "Could not open the networking registry key\n");
+               return false;
+       }
+
+       for (i = 0; device_handle == INVALID_HANDLE_VALUE; i++)
+       {
+               len = sizeof(adapterid);
+               if (RegEnumKeyEx(key, i, adapterid, &len, 0, 0, 0, NULL)) break;
+
+               snprintf(tapname, sizeof(tapname), TAP_DEVICE_DIR "%s.tap", adapterid);
+               tun_log(LOG_DEBUG, "start", "Trying %s\n", tapname);
+               device_handle = CreateFile(tapname, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, 0);
+
+               if (device_handle != INVALID_HANDLE_VALUE)
+               {
+                       unsigned long   status, info[3] = {0,0,0};
+
+                       /* get driver version info */
+                       if (DeviceIoControl(device_handle, TAP_IOCTL_GET_VERSION, &info, sizeof(info), &info, sizeof(info), &len, NULL))
+                       {
+                               D(tun_log(LOG_DEBUG, "start", "TAP-Win32 Driver Version %d.%d %s", (int)info[0], (int)info[1], info[2] ? "(DEBUG)" : ""));
+                       }
+
+                       if (!(info[0] > TAP_WIN32_MIN_MAJOR || (info[0] == TAP_WIN32_MIN_MAJOR && info[1] >= TAP_WIN32_MIN_MINOR)))
+                       {
+                               tun_log(LOG_ERR, "start", "A TAP-Win32 driver is required that is at least version %d.%d -- If you recently upgraded your Tap32 driver, a reboot is probably required at this point to get Windows to see the new driver.", TAP_WIN32_MIN_MAJOR, TAP_WIN32_MIN_MINOR);
+                               CloseHandle(device_handle);
+                               device_handle = INVALID_HANDLE_VALUE;
+                               continue;
+                       }
+
+                       /* Note: we use TAP mode on Windows, not TUN */
+
+                       /* Try to mark the device as 'up */
+                       status = true;
+                       DeviceIoControl(device_handle, TAP_IOCTL_SET_MEDIA_STATUS, &status, sizeof(status), &status, sizeof(status), &len, NULL);
+               }
+       }
+
+       RegCloseKey(key);
+
+       if (device_handle == INVALID_HANDLE_VALUE)
+       {
+               tun_log(LOG_ERR, "start", "No working Tap device found!\n");
+               return false;
+       }
+
+#endif /* _WIN32 */
+
+       /* Launch a thread for reader */
+#ifndef _WIN32
+       pthread_create(&thread, NULL, tun_reader, (void *)tun);
+#else
+       h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tun_reader, tun, 0, &pID);
+#endif
+
+       /* We now return, the real tunneling tool can call tun_write() when it wants */
+
+       return true;
+}
diff --git a/common/tun.h b/common/tun.h
new file mode 100755 (executable)
index 0000000..e19f4e8
--- /dev/null
@@ -0,0 +1,45 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ common/tun.h - Tunnel Device Handling
+***********************************************************
+ $Author: jeroen $
+ $Id: tun.h,v 1.3 2006-07-13 19:33:39 jeroen Exp $
+ $Date: 2006-07-13 19:33:39 $
+**********************************************************/
+
+#ifndef TUN_H
+#define TUN_H "H5K7:W3NDY5UU5N1K1N1C0l3"
+
+#include "common.h"
+
+#ifdef _WIN32
+/* Windows writev() support */
+struct iovec
+{
+       u_long  iov_len;
+       char    *iov_base;
+};
+
+int writev(SOCKET sock, const struct iovec *vector, DWORD count);
+void tun_list_tap_adapters(void);
+#endif
+
+#ifndef _WIN32
+       typedef void (*TUN_PROCESS)(char *, unsigned int);
+#else
+       typedef void (*TUN_PROCESS)(char *, unsigned int);
+#endif
+
+struct tun_reader
+{
+       TUN_PROCESS     function;
+};
+
+void tun_write(char *buf, unsigned int length);
+bool tun_start(struct tun_reader *tun);
+
+#endif /* TUN_H */
+
diff --git a/debian/aiccu.config b/debian/aiccu.config
new file mode 100755 (executable)
index 0000000..6f7d8eb
--- /dev/null
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+CONFIGFILE=/etc/aiccu.conf
+TMPCONF=/etc/aiccu.conf.$$.dpkg-tmp
+TMPFILE=/etc/aiccu.temp.$$.dpkg-tmp
+BINARY=/usr/sbin/aiccu
+
+# Note: the two temp files are placed in /etc thus should be symlink-attack safe
+
+if [ ! -x $BINARY ]; then
+       # Can't configure yet as we don't have our binary yet
+       exit 0;
+fi
+
+# Make sure that files we create are not readable by anyone but us (root)
+umask 077
+
+. /usr/share/debconf/confmodule
+
+if [ -e $CONFIGFILE ]; then
+       USERNAME=$(grep ^username $CONFIGFILE | awk '{print $2}')
+       PASSWORD=$(grep ^password $CONFIGFILE | awk '{print $2}')
+       PROTO=$(grep ^protocol $CONFIGFILE | awk '{print $2}')
+       SERVER=$(grep ^server $CONFIGFILE | awk '{print $2}')
+       TUNNEL=$(grep ^tunnel_id $CONFIGFILE | awk '{print $2}')
+
+       if [ "$USERNAME" != "" ]; then
+               db_set aiccu/username "$USERNAME"
+       fi
+
+       if [ "$PASSWORD" != "" ]; then
+               db_set aiccu/password "$PASSWORD"
+       fi
+
+       if [ "$PROTO" != "" -a "$SERVER" != "" ]; then
+               db_set aiccu/brokername "$PROTO://$SERVER"
+       fi
+
+       if [ "$TUNNEL" != "" ]; then
+               db_set aiccu/tunnelname "$TUNNEL"
+       fi
+fi
+
+
+db_reset aiccu/badauth
+
+#
+# State What
+#   1  Get Tunnel Brokername
+#   2  Get User/pass
+#   3  Get Tunnel ID
+#   4  Exit
+
+STATE=1
+while [ $STATE -ge 1 -a $STATE -le 3 ]; do
+
+       case "$STATE" in
+       1)
+               # Fetch the list of tunnel brokers
+               BROKERS=$($BINARY brokers | sort >$TMPFILE)
+
+               if [ "$?" != "0" ]; then
+                       # No TunnelBrokers found
+                       db_input high aiccu/nobrokers || true
+                       echo "No brokers"
+               else
+                       # Found Tunnel brokers, present them to the user
+                       BROKERS=$(cat $TMPFILE | cut -f1 -d'|' | awk '{print $0","}')
+                       BROKERS=$(echo -n $BROKERS | sed 'N;s/\n//g' | sed 's/,$//g')
+                       db_subst aiccu/brokername brokers "$BROKERS"
+                       db_fset aiccu/brokername seen false
+                       db_input high aiccu/brokername || true
+                       db_go || true
+               fi
+
+               # Remove temporary file
+               rm $TMPFILE
+               ;;
+
+       2)
+               # Request User / Pass
+               db_input high aiccu/username || true
+               db_input high aiccu/password || true
+               db_go || true
+               ;;
+
+       3)
+               # Reset our temp config file
+               echo "# Temporary AICCU config written by debconf" > $TMPCONF
+               #echo "verbose true" >> $TMPCONF
+
+               # Take the Protocol and server from the Brokername
+               db_get aiccu/brokername
+               URL=$($BINARY brokers | grep "$RET")
+               PROTO=$(echo $URL | cut -f2 -d'|' | cut -f1 -d:)
+               SERVER=$(echo $URL | cut -f2 -d'|' | cut -f3 -d/)
+
+               echo "protocol $PROTO" >> $TMPCONF
+               echo "server $SERVER" >> $TMPCONF
+
+               db_get aiccu/username
+               USERNAME="$RET"
+
+               db_get aiccu/password
+               PASSWORD="$RET"
+
+               # Try to get the tunnels using the provided user/pass
+               if [ "$USERNAME" != "" -a "$PASSWORD" != "" ]; then
+                       echo "username $USERNAME" >> $TMPCONF
+                       echo "password $PASSWORD" >> $TMPCONF
+
+                       TUNNELS=$($BINARY tunnels $TMPCONF >$TMPFILE)
+
+                       if [ "$?" != "0" ]; then
+                               db_input high aiccu/badauth || true
+                       else
+                               db_set aiccu/badauth "false"
+
+                               TUNNELS=$(cat $TMPFILE | cut -f1 -d' ' | awk '{print $0","}')
+                               TUNNELS=$(echo -n $TUNNELS | sed 'N;s/\n//g' | sed 's/,$//g')
+
+                               if [ "$TUNNELS" = "" ]; then
+                                       db_input high aiccu/notunnels || true
+                               else
+                                       db_subst aiccu/tunnelname tunnels "$TUNNELS"
+                                       db_input high aiccu/tunnelname || true
+                                       db_go || true
+                               fi
+                       fi
+
+                       # Remove temporary file
+                       rm $TMPFILE
+               else
+                       db_set aiccu/badauth "false"
+               fi
+
+               # Remove the temporary as we don't need it anymore
+               rm $TMPCONF
+               ;;
+       esac
+
+       db_go
+
+       case "$STATE" in
+       1)
+               STATE=2
+               ;;
+       2)
+               STATE=3
+               ;;
+       3)
+               db_get aiccu/badauth
+
+               # When badly authenticated do it all over
+               if [ "$RET" = "true" ]; then
+                       STATE=1
+                       db_reset aiccu/brokername
+                       db_reset aiccu/username
+                       db_reset aiccu/password
+                       db_reset aiccu/tunnelname
+               else
+                       STATE=4
+               fi
+               db_reset aiccu/badauth
+               ;;
+       esac
+done
+
diff --git a/debian/aiccu.manpages b/debian/aiccu.manpages
new file mode 100644 (file)
index 0000000..faf63b9
--- /dev/null
@@ -0,0 +1 @@
+doc/aiccu.1
diff --git a/debian/aiccu.postinst b/debian/aiccu.postinst
new file mode 100755 (executable)
index 0000000..eaf35fb
--- /dev/null
@@ -0,0 +1,108 @@
+#!/bin/sh -e
+
+CONFIGFILE="/etc/aiccu.conf"
+TMPCONF=/etc/aiccu.conf.dpkg-tmp
+EXAMPLE=/usr/share/doc/aiccu/examples/aiccu.conf
+CTLINFO="# Under control from debconf, please use 'dpkg-reconfigure aiccu' to reconfigure"
+BINARY=/usr/sbin/aiccu
+
+. /usr/share/debconf/confmodule
+
+db_get aiccu/username
+USERNAME="$RET"
+
+db_get aiccu/password
+PASSWORD="$RET"
+
+AICCUOUT=$($BINARY brokers)
+
+db_get aiccu/brokername
+URL=$(echo "$AICCUOUT" | grep "$RET")
+PROTO=$(echo $URL | cut -f2 -d'|' | cut -f1 -d:)
+SERVER=$(echo $URL | cut -f2 -d'|' | cut -f3 -d/)
+
+db_get aiccu/tunnelname
+TUNNEL="$RET"
+
+db_stop
+
+if [ "$USERNAME" = "" ]; then
+       # Not configured yet, thus skip
+       exit 0;
+fi
+
+# Defaults when nothing gets chosen
+# This might happen because of broken DNS
+if [ "$PROTO" = "" ]; then
+       PROTO="tic"
+fi
+
+if [ "$SERVER" = "" ]; then
+       SERVER="tic.sixxs.net"
+fi
+
+# Make sure that files we create are not readable by anyone but us (root)
+umask 077
+
+# Check if the /etc/aiccu.conf is actually the example
+if [ diff -q $EXAMPLE $CONFIGFILE 2>/dev/null >/dev/null ]; then
+       DEFAULTCONFIG="true"
+else
+       DEFAULTCONFIG="false"
+fi
+
+# Install a default config when it didn't exist yet or it is the same as the example
+# bash uses '==', dash uses '=', thus use '!=' as that is the same
+if [ "$DEFAULTCONFIG" != "false" -o ! -e "$CONFIGFILE" ]; then
+
+       # Note that it is under debconf control
+       echo $CTLINFO >> $TMPCONF
+
+       # Replace the example lines so that they become normals
+       sed -e "s/^#username .*/username $USERNAME/; s/^#password .*/password $PASSWORD/; s/^#protocol .*/protocol $PROTO/; s/^#server .*/server $SERVER/; s/^#tunnel_id .*/tunnel_id $TUNNEL/;" < $EXAMPLE >> $TMPCONF
+
+# Modify the existing one
+else
+       # Note that it is under debconf control
+       if ! grep -q "^$CTLINFO" $CONFIGFILE; then
+               echo $CTLINFO >> $TMPCONF >>$TMPCONF
+       fi
+
+       # Make sure that all the variables can be stored somewhere
+       if ! grep -q "^username" $CONFIGFILE; then
+               if [ "$USERNAME" != "" ]; then
+                       echo "username $USERNAME" >> $TMPCONF
+               fi
+       fi
+
+       if ! grep -q "^password" $CONFIGFILE; then
+               if [ "$PASSWORD" != "" ]; then
+                       echo "password $PASSWORD" >> $TMPCONF
+               fi
+       fi
+
+       if ! grep -q "^protocol" $CONFIGFILE; then
+               if [ "$PROTO" != "" ]; then
+                       echo "protocol $PROTO" >> $TMPCONF
+               fi
+       fi
+       if ! grep -q "^server" $CONFIGFILE; then
+               if [ "$SERVER" != "" ]; then
+                       echo "server $SERVER" >> $TMPCONF
+               fi
+       fi
+
+       if ! grep -q "^tunnel_id" $CONFIGFILE; then
+               if [ "$TUNNEL" != "" ]; then
+                       echo "tunnel_id $TUNNEL" >> $TMPCONF
+               fi
+       fi
+
+       sed -e "s/^username .*/username $USERNAME/; s/^password .*/password $PASSWORD/; s/^protocol .*/protocol $PROTO/; s/^server .*/server $SERVER/; s/^tunnel_id .*/tunnel_id $TUNNEL/;" < $CONFIGFILE >> $TMPCONF
+fi
+
+# Move it into place
+mv -f $TMPCONF $CONFIGFILE
+# Just in case, make sure the permissions are perfect and dandy
+chmod 600 $CONFIGFILE
+
diff --git a/debian/aiccu.preinst b/debian/aiccu.preinst
new file mode 100644 (file)
index 0000000..07fe0c2
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+#DEBHELPER#
diff --git a/debian/changelog b/debian/changelog
new file mode 100755 (executable)
index 0000000..638c686
--- /dev/null
@@ -0,0 +1,198 @@
+aiccu (20070115) stable; urgency=medium
+  * Fixup in Debian init script (based on original patch by Bernhard Schmidt).
+  * Change in redirections so that errors don't show in debconf menu's etc.
+  * NetBSD fixes as there is not always a Tunnel Device that
+    supports IPv6 (thanks to Geert Hendrickx).
+  * Gentoo ebuild update, adding depends and require ntp-client.
+  * RPM spec update, add build-requirement.
+  * Check return values of system commands.
+  * Added a big warning about running AICCU from Daemontools and similar
+    programs which run AICCU in a loop, thus hammering the TIC server.
+  * Be a bit smarter in checking for support of IPv6.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Mon, 15 Jan 2007 11:00:42 +0000
+
+aiccu (20070107) stable; urgency=high
+  * 2007 Edition of AICCU.
+  * License change to standard 3-clause BSD license.
+    With thanks to Theo de Raadt, Marco d'Itri and Philipp Kern for
+    their wise words and reasoning for coming to this decision.
+  * High urgency because of the above and it fixing large problems.
+  * Fixed Mac OS X / Darwin support on the MacBookPro of Pim van Pelt.
+  * Added MTU, from TIC, configuration on most platforms.
+  * Fixed up silly linux bug, adding LL address to tunnels but not to tun/taps.
+  * Removed Win32 Alpha Endianess (reported by Christian Weisgerber).
+  * Fixed up alignment error in parseline() (reported by Christian Weisgerber).
+  * OpenBSD 4.0 support (patch provided by Christian Weisgerber).
+  * OpenBSD AYIYA fixup (patch provided by Pim van Pelt).
+  * Fedora/RPM init script fixup (bash case's don't fall through)
+    reported and patch supplied by Matt Domsch.
+  * NetBSD AYIYA support (noted by Tobias Riediger)
+    Works on NetBSD 4.x, for NetBSD 3.0 one needs to patch tun/tap to
+    support IPv6. Patch is available from the archives.
+  * local_ipv4_override option so one can use AICCU behind a NAT that
+    has been configured correctly to do proto-41 forwarding. This is
+    usually called a DMZ setup.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 07 Jan 2007 14:00:42 +0000
+
+aiccu (20060806) stable; urgency=low
+  * Changelog version format change as the 'official' (before there where
+    legal issues as they don't understand the word 'SHOULD' which is cleary
+    defined in the IETF and now somebody simply uploaded it anyway it without
+    even asking or notifying us about it) debian packages which are broken,
+    old and unsupported would seem newer and thus this new version would not
+    get updated to even when folks would have the official AICCU repository
+    in their sources.list. This solves that issue.
+  * pidfile fixup and configuration parameter.
+  * Corrected Broker selection in debconf.
+  * Configuration file rewriting by debconf is now done in a 'nice' way.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun,  6 Aug 2006 13:56:42 +0100 
+
+aiccu (2006-07-25) stable; urgency=low
+  * DragonFlyBSD fix
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Tue, 25 Jul 2006 11:22:42 +0100
+
+aiccu (2006-07-23) stable; urgency=low
+  * The Nina'th release.
+  * Verified AYIYA support on Windows, OpenBSD, FreeBSD and Linux ia32/AMD64/armeb.
+  * Disabled TSP and L2TP (Teepee) support as they are not finished.
+  * No more IPv4 interface as it is not used anymore.
+  * On AIX we now compile with xlc_r.
+  * Retrieves Tunnel Brokers from _aiccu.<search path> and from _aiccu.sixxs.net.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 23 Jul 2006 16:48:42 +0100
+
+aiccu (2006-07-13) stable; urgency=low
+  * Added no-configure and defaultroute options.
+  * AYIYA now forks so that AYIYA heartbeats work.
+  * Ctrl-C handling
+  * Protocol and server can be specified in configuration file
+  * AYIYA fixes: header alignment, Win32 TAP 8.1 support
+  * TAP listing using --listtaps (windows)
+  * Confuration can now be saved using a menu entry in the GUI (windows)
+  * TAP interface renaming when it's the only TAP and name not in the config (windows)
+  * Fedora fixes by Matt Domsch
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Thu, 13 Jul 2006 22:42:42 +0100
+
+aiccu (2006-03-10) stable; urgency=low
+  * Changed Debian start/stop priority as noted by Mario 'BitKoenig' Holbe.
+    They now match openvpn/pppd etc.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Fri, 10 Mar 2006 21:24:42 +0100
+
+aiccu (2005-12-05) stable; urgency=low
+  * DragonFlyBSD (uses the FreeBSD4 interface) added as noted by Geert Hendrickx.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 14 Aug 2005 14:10:42 +0200
+
+aiccu (2005-08-14) stable; urgency=low
+  * Mac OS X typo-fix (reported by Wim Biemolt)
+  * GNUTLS support. TIC will go over TLS avoiding cleartext
+    negotiations where possible.
+  * Heartbeat stop & start per signal (requested by Peter Bieringer)
+  * AYIYA Heartbeating.
+  * L2TPv2 Support.
+  * TSP Support.
+  * Gary Coady's <gary@lyranthe.org> Debian/Ubuntu update:
+    * Use dpkg-buildpackage to generate deb files
+    * Remove configuration checks from Debian init script
+    * Use common print functions in Debian init script
+    * Add 'tunnels' parameter to aiccu, which reports available tunnels
+    * Return non-zero exit code if unable to successfully authenticate
+      to POP
+    * Log to stderr instead of stdout
+    * Send signal 0 to existing aiccu binary instead of SIGHUP
+    * Add debconf support
+    Thanks to Gary for these very nice addons!
+  * Added OpenBSD PortInfo by Thomas Kaschwig
+  * Added Makefile changes to support FreeBSD6, noted by Meno Abels
+  * Added _NETBSD_SOURCE define as mentioned by Maarten Dammers
+  * Changed aiccu_kame to do configuration differently depending
+    if the interface is a proto-41 one or a tun device.
+  * Solaris and AIX support + Endian Fixes.
+  * 'version' option for unix_console.
+  * 64bit fixes + compilation check against a big number of platforms.
+  * Multiple Tunnelbrokers Support using TXT records from _aiccu.sixxs.net DNS.
+  * AYIYA Port number set to 5072 (IANA assigned)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 14 Aug 2005 14:10:42 +0200
+
+aiccu (2005-01-31) stable; urgency=low
+  * Full integration of AYIYA, thus normal request procedures
+  * Version -gui/-console correction
+  * FreeBSD/Darwin route fixes (reported by Peter van Dijk)
+  * Windows: New POP logos added
+  * Linklocals for AYIYA tunnels making MLD and thus multicast
+    work (reported by Marco d'Itri)
+  * fflush() during non-syslog logging so that AICCU logs
+    correctly when run from daemontools (Peter van Dijk)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Mon, 31 Jan 2005 20:29:42 +0100
+
+aiccu (2005-01-09) stable; urgency=low
+
+  * Mum's birthday release
+  * MacOS X support (Marc Kramis)
+  * DEBUG messages are not logged anymore
+  * OpenBSD 2.x/3.x support (Wouter van Hemel)
+  * Don't overwrite config when doing a 'make install' (Wouter van Hemel)
+  * Manual page (Antonio Ospite)
+  * Windows Configuration directory based on GetWindowsDirectory()
+    (reported by Thomas B. Ruecker)
+  * Windows NAT message fix (reported by Thomas B. Ruecker)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 9 Jan 2005 09:00:42 +0100
+
+aiccu (2004-09-17-beta2b) stable; urgency=low
+
+  * OpenBSD fixes (AO)
+  * debian/rules debclean - now calls the correct clean (A0)
+  * Debian dependency on iproute (MdI)
+  * Gentoo Port (Thorsten Becker)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 12 Sep 2004 10:24:42 +0100
+
+aiccu (2004-09-09-beta2a) stable; urgency=low
+
+  * Compile with pendantic, removing C++ "//" comments (AO)
+  * Debian fixes: file permissions, distclean (AO)
+  * rc.d addon (AO)
+  * Remove superfluous CVS dirs (AO)
+  * init script fix specifying 'start' (RS)
+  * RPM_OPT_FLAGS passing (RS)
+  * License fixes, making it more open (PvD & MdI)
+  * RPM package (RS)
+  * FreeBSD 4.x + 5.x port (MA)
+  * Many more fixes and cleanups (JM)
+  Who/what:
+  * AO = Antonio Ospite
+  * RS = Robert Schiele
+  * PvD = Peter van Dijk
+  * MdI = Marco d'Itri
+  * MA = Meno Abels
+  * JM = Jeroen Massar
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Thu, 09 Sep 2004 10:24:42 +0100
+
+aiccu (2004-08-30-beta2) stable; urgency=low
+
+  * Updated LICENSE which should now be 100% free(tm)
+  * Local-IP fix when using heartbeat tunnels
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Mon, 30 Aug 2004 21:26:42 +0100
+
+aiccu (2004-08-29-beta2) stable; urgency=low
+
+  * Brand spanking new AICCU
+  * Compiles both on Windows and UNIX
+  * Supports:
+    - TIC
+    - 6in4-static
+    - 6in4-heartbeat
+    - AYIYA
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 29 Aug 2004 20:55:42 +0100
diff --git a/debian/control b/debian/control
new file mode 100755 (executable)
index 0000000..b428873
--- /dev/null
@@ -0,0 +1,18 @@
+Source: aiccu
+Section: net
+Priority: optional
+Maintainer: SixXS Staff <info@sixxs.net>
+Build-Depends: debhelper (>> 3.0.0), libgnutls-dev
+Standards-Version: 3.7.2
+
+Package: aiccu
+Architecture: any
+Depends: ${shlibs:Depends}, iputils-ping, iputils-tracepath, iproute, debconf, lsb-base (>= 1.3-9ubuntu2), gawk | awk, libgnutls13
+Recommends: ntpdate | ntp
+Description: SixXS Automatic IPv6 Connectivity Client Utility
+ This client automatically gives one IPv6 connectivity
+ without having to manually configure interfaces etc.
+ One does need a SixXS account and at least a tunnel. These
+ can be freely & gratis requested from the SixXS website.
+ For more information about SixXS check http://www.sixxs.net
+
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..0e838db
--- /dev/null
@@ -0,0 +1,2 @@
+usr/sbin
+etc
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..2b70afc
--- /dev/null
@@ -0,0 +1,3 @@
+doc/README
+doc/LICENSE
+doc/HOWTO
diff --git a/debian/postrm.debhelper b/debian/postrm.debhelper
new file mode 100644 (file)
index 0000000..bc035b9
--- /dev/null
@@ -0,0 +1,6 @@
+# Automatically added by dh_installdebconf
+if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then
+       . /usr/share/debconf/confmodule
+       db_purge
+fi
+# End automatically added section
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..876803f
--- /dev/null
@@ -0,0 +1,82 @@
+#!/usr/bin/make -f
+# Sample debian/rules that uses debhelper.
+# GNU copyright 1997 to 1999 by Joey Hess.
+# Adjusted by Jeroen Massar <jeroen@sixxs.net> for aiccu
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+# This is the debhelper compatability version to use.
+export DH_COMPAT=4
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+
+       touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+
+       # Add here commands to compile the package.
+       $(MAKE)
+
+       touch build-stamp
+
+clean:
+       dh_testdir
+       rm -f build-stamp configure-stamp
+
+       # Add here commands to clean up after the build process.
+       -$(MAKE) clean
+
+       dh_clean
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+
+       # Add here commands to install the package into debian/aiccu
+       $(MAKE) DESTDIR=`pwd`/debian/aiccu install
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+       dh_testdir
+       dh_testroot
+       dh_installdebconf
+       dh_installdocs
+       dh_installexamples doc/aiccu.conf
+       dh_installmenu
+#      dh_installlogrotate
+#      dh_installemacsen
+#      dh_installpam
+#      dh_installmime
+       dh_installinit -- defaults 16 80
+       dh_installcron
+       dh_installman
+       dh_installinfo
+#      dh_undocumented
+       dh_installchangelogs 
+       dh_link
+       dh_strip
+       dh_compress
+       dh_fixperms
+#      dh_makeshlibs
+       dh_installdeb
+#      dh_perl
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
+
diff --git a/debian/substvars b/debian/substvars
new file mode 100644 (file)
index 0000000..a8fe3cf
--- /dev/null
@@ -0,0 +1 @@
+misc:Depends=debconf (>= 0.5) | debconf-2.0
diff --git a/debian/templates b/debian/templates
new file mode 100644 (file)
index 0000000..e64b308
--- /dev/null
@@ -0,0 +1,43 @@
+Template: aiccu/username
+Type: string
+Default:
+Description: Username
+ To successfully connect, you must have a valid username. This is
+ the same as the handle you use to log into the website.
+
+Template: aiccu/password
+Type: password
+Description: Password
+ To successfully connect, you must have a valid password. This is
+ the same password you use to log into the website.
+
+Template: aiccu/brokername
+Type: select
+Choices: ${brokers}
+Description: Tunnel Broker
+ Select the Tunnel Broker you would like to use.
+
+Template: aiccu/tunnelname
+Type: select
+Choices: ${tunnels}
+Description: Tunnel Name
+ If you have more than one tunnel configured in your account, you must
+ specify which tunnel should be activated.
+
+Template: aiccu/badauth
+Type: boolean
+Description: Recheck authentication details?
+ You most likely have given bad authentication details. Try to login through
+ the website of the Tunnel Broker or contact them to ask about problems.
+
+Template: aiccu/nobrokers
+Type: note
+Description: No Tunnel Brokers available
+ No Tunnel Brokers could be retrieved from DNS (_aiccu + _aiccu.sixxs.net)
+ this most likely indicates a DNS configuration problem.
+
+Template: aiccu/notunnels
+Type: note
+Description: No tunnels available
+ You currently have no tunnels available. Please go to the SixXS website
+ at http://www.sixxs.net/ to request a tunnel for your account.
diff --git a/doc/COPYRIGHT b/doc/COPYRIGHT
new file mode 100644 (file)
index 0000000..7b43cc5
--- /dev/null
@@ -0,0 +1,6 @@
+The code for AICCU was written by Jeroen Massar <jeroen@sixxs.net>
+The copyright for this package is owned by SixXS Staff <info@sixxs.net>.
+(C) Copyright SixXS 2003-2007 All Rights Reserved
+
+Website: http://www.sixxs.net/tools/aiccu/
+
diff --git a/doc/HOWTO b/doc/HOWTO
new file mode 100644 (file)
index 0000000..8987fc1
--- /dev/null
+++ b/doc/HOWTO
@@ -0,0 +1,40 @@
+Howto AICCU
+~~~~~~~~~~~
+
+For AYIYA support:
+ - Windows & Mac OS X: Install the driver mentioned in the FAQ.
+   at http://www.sixxs.net/faq/
+ - Linux, *BSD: make sure that the tun/tap device is available.
+   NetBSD v3 users - check the IPv6 tun/tap patch on
+   http://www.sixxs.net/archive/sixxs/aiccu/unix/
+
+- Windows GUI client:
+  - Just run and follow the dialogs.
+
+- Window GUI client as a service:
+  - Run the GUI client without options.
+  - Choose all the correct settings and check that
+    the tunnel works.
+  - Select the "Auto Enable" button on the info page.
+  - Select the "Save Configuration" option from the menu.
+    (See screenshots for its location)
+  - Quit the GUI.
+  - Install it as a service using "aiccu /i"
+  - Then use "net start aiccu" or start it from the
+    service control manager (services.msc)
+
+  One can uninstall the service with "aiccu /u" and
+  of course use the start/stop options to start/stop it.
+
+- Unix/Windows console client:
+  - Edit /etc/aiccu.conf and fill in the required values.
+  - Run aiccu test; aiccu start
+
+If there any problems:
+ - read the SixXS FAQ at http://www.sixxs.net/faq/
+ - check the SixXS Forum at http://www.sixxs.net/forum/
+
+If then it still fails, contact the SixXS staff as
+described per http://www.sixxs.net/contact/
+For problem reports please read and use the "Reporting Problems" 
+section on that page to determine where the problem occurs.
diff --git a/doc/LICENSE b/doc/LICENSE
new file mode 100644 (file)
index 0000000..06ef53d
--- /dev/null
@@ -0,0 +1,29 @@
+The SixXS License - http://www.sixxs.net/
+
+Copyright (C) SixXS Staff <info@sixxs.net>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of SixXS nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior permission.
+
+THIS SOFTWARE IS PROVIDED BY SIXXS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL SIXXS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
diff --git a/doc/README b/doc/README
new file mode 100644 (file)
index 0000000..2179e91
--- /dev/null
@@ -0,0 +1,62 @@
+SixXS AICCU: Automatic IPv6 Connectivity Configuration Utility
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+AICCU makes it very easy for anybody to get IPv6 connectivity
+everywhere they want. It uses the TIC (Tunnel Information & Control)
+protocol to request the information needed to setup a tunnel through
+which the connectivity is created.
+
+AICCU supports the following tunneling protocols:
+ - 6in4 static    (RFC 2893)
+ - 6in4 heartbeat (RFC 2893 + draft-massar-v6ops-heartbeat)
+ - AYIYA          (draft-massar-v6ops-ayiya)
+As AYIYA even works from behind NAT's, thus unless there is a very
+restrictive firewall in place, anybody should be able to get IPv6
+connectivity without problems and everywhere they want.
+
+WARNING: never run AICCU from DaemonTools or a similar automated
+'restart' tool/script. When AICCU does not start, it has a reason
+not to start which it gives on either the stdout or in the (sys)log
+file. The TIC server *will* automatically disable accounts which
+are detected to run in this mode.
+
+The main AICCU page, containing information, screenshots, updates
+and of course the software itself, unix source + binaries/packages
+and Windows binaries, can be downloaded from:
+
+   http://www.sixxs.net/tools/aiccu/
+
+Author
+~~~~~~
+The author of this code is:
+
+Jeroen Massar
+SixXS Staff <info@sixxs.net>
+http://www.sixxs.net/
+
+With patches accepted from other sources as can be found
+in the changelog.
+
+Contact
+~~~~~~~
+In the event that you find bugs or have questions please see:
+   http://www.sixxs.net/contact/
+which contains the contact details of the SixXS Staff.
+
+If you have problems using this tool you should of course first
+check the FAQ at http://www.sixxs.net/faq/ and check the Forum
+which can be found at http://www.sixxs.net/forum/
+
+If you are using this software please notify us of it. We are
+always interrested to hear in what various ways people are
+using our software.
+
+License
+~~~~~~~
+See the LICENSE file in the doc directory
+
+Copyright
+~~~~~~~~~
+Automatic IPv6 Connectivity Configuration Utility
+AICCU (C) Copyright 2003-2007 SixXS Staff <info@sixxs.net>
+
diff --git a/doc/aiccu.1 b/doc/aiccu.1
new file mode 100644 (file)
index 0000000..7eaee06
--- /dev/null
@@ -0,0 +1,56 @@
+.\" This manpage has been automatically generated by docbook2man 
+.\" from a DocBook document.  This tool can be found at:
+.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> 
+.\" Please send any bug reports, improvements, comments, patches, 
+.\" etc. to Steve Cheng <steve@ggi-project.org>.
+.TH "AICCU" "1" "18 April 2005" "" ""
+
+.SH NAME
+AICCU \- Automatic IPv6 Connectivity Configuration Utility
+.SH SYNOPSIS
+
+\fBaiccu \fR \fB<start|stop|tunnels|test|autotest|license>\fR [ \fB\fIconfig\fB\fR ]
+
+.SH "DESCRIPTION"
+.PP
+AICCU makes it very easy for anybody to get IPv6 connectivity
+everywhere they want. It uses the TIC (Tunnel Information & Control)
+protocol to request the information needed to setup a tunnel through
+which the connectivity is created.
+AICCU supports the following tunneling protocols:
+- 6in4 static    (RFC 2893)
+- 6in4 heartbeat (RFC 2893 + draft-massar-v6ops-heartbeat)
+- tinc           (http://www.tinc-vpn.org)
+- AYIYA          (draft-massar-v6ops-ayiya)
+As AYIYA even works from behind NAT's, thus unless there is a very
+restrictive firewall in place, anybody should be able to get IPv6
+connectivity without problems and everywhere they want.
+.SH "OPTIONS"
+.TP
+\fBstart\fR
+Starts aiccu service.
+.TP
+\fBstop\fR
+Stops aiccu service.
+.TP
+\fBtunnels\fR
+Prints a list of currently available tunnels.
+.TP
+\fBtest\fR
+Builds the connection and runs a simple selftest allowing a user
+to report this back as it should show most obvious problems.
+.TP
+\fBautotest\fR
+Decription here
+.TP
+\fBlicense\fR
+Shows the license aiccu is released under.
+.TP
+\fB\fIconfig\fB\fR
+Read the configuration from \fIconfig\fR file.
+.SH "SEE ALSO"
+.PP
+The AICCU page <URL:http://www.sixxs.net/tools/aiccu/> at sixxs.
+.SH "AUTHOR"
+.PP
+AICCU was written by Jeroen Massar with contributions supplied a number of people as mentioned in the Changelog.
diff --git a/doc/aiccu.conf b/doc/aiccu.conf
new file mode 100755 (executable)
index 0000000..71e8c6c
--- /dev/null
@@ -0,0 +1,78 @@
+# AICCU Configuration
+
+# Login information (defaults: none)
+#username <your nichandle/username>
+#password <your password>
+
+# Protocol and server to use for setting up the tunnel (defaults: none)
+#protocol <tic|tsp|l2tp>
+#server <server to use>
+
+# Interface names to use (default: aiccu)
+# ipv6_interface is the name of the interface that will be used as a tunnel interface.
+# On *BSD the ipv6_interface should be set to gifX (eg gif0) for proto-41 tunnels
+# or tunX (eg tun0) for AYIYA tunnels.
+ipv6_interface sixxs
+
+# The tunnel_id to use (default: none)
+# (only required when there are multiple tunnels in the list)
+#tunnel_id Txxxx
+
+# Be verbose? (default: false)
+verbose false
+
+# Daemonize? (default: true)
+# Set to false if you want to see any output
+# When true output goes to syslog
+#
+# WARNING: never run AICCU from DaemonTools or a similar automated
+# 'restart' tool/script. When AICCU does not start, it has a reason
+# not to start which it gives on either the stdout or in the (sys)log
+# file. The TIC server *will* automatically disable accounts which
+# are detected to run in this mode.
+#
+daemonize true
+
+# Automatic Login and Tunnel activation?
+automatic true
+
+# Require TLS?
+# When set to true, if TLS is not supported on the server
+# the TIC transaction will fail.
+# When set to false, it will try a starttls, when that is
+# not supported it will continue.
+# In any case if AICCU is build with TLS support it will
+# try to do a 'starttls' to the TIC server to see if that
+# is supported.
+requiretls false
+
+# PID File
+#pidfile /var/run/aiccu.pid
+
+# Add a default route (default: true)
+#defaultroute true
+
+# Script to run after setting up the interfaces (default: none)
+#setupscript /usr/local/etc/aiccu-subnets.sh
+
+# Make heartbeats (default true)
+# In general you don't want to turn this off
+# Of course only applies to AYIYA and heartbeat tunnels not to static ones
+#makebeats true
+
+# Don't configure anything (default: false)
+#noconfigure true
+
+# Behind NAT (default: false)
+# Notify the user that a NAT-kind network is detected
+#behindnat true
+
+# Local IPv4 Override (default: none)
+# Overrides the IPv4 parameter received from TIC
+# This allows one to configure a NAT into "DMZ" mode and then
+# forwarding the proto-41 packets to an internal host.
+# 
+# This is only needed for static proto-41 tunnels!
+# AYIYA and heartbeat tunnels don't require this.
+#local_ipv4_override
+
diff --git a/doc/aiccu.init b/doc/aiccu.init
new file mode 100755 (executable)
index 0000000..f264bc3
--- /dev/null
@@ -0,0 +1,68 @@
+#! /bin/sh
+#
+# /etc/init.d/aiccu: start / stop AICCU
+#
+# Jeroen Massar <jeroen@sixxs.net>
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+NAME=aiccu
+DAEMON=/usr/sbin/${NAME}
+DESC="SixXS Automatic IPv6 Connectivity Client Utility (${NAME})"
+BACKGROUND=true
+
+# Options
+OPTIONS=""
+
+test -x $DAEMON || exit 0
+
+# Verify that the configuration file exists
+if [ ! -f /etc/aiccu.conf ]; then
+       echo "AICCU Configuration file /etc/aiccu.conf doesn't exist"
+       exit 0;
+fi
+
+# Verify that the configuration is correct
+if [ `grep -c "^username" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
+       echo "AICCU is not configured, edit /etc/aiccu.conf first"
+       exit 0;
+fi
+
+# Verify that it is in daemonize mode, otherwise it won't ever return
+if [ `grep -c "^daemonize true" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
+       echo "AICCU is not configured to daemonize on run"
+       exit 0;
+fi
+
+if [ -f /etc/default/${NAME} ]; then
+       . /etc/default/${NAME}
+fi
+
+if [ "$BACKGROUND" = "false" ]; then
+       exit 0;
+fi
+
+case "$1" in
+  start)
+       echo -n "Starting $DESC: "
+       start-stop-daemon --start --oknodo --quiet --exec $DAEMON -- start $OPTIONS
+       echo "$NAME."
+       ;;
+  stop)
+       echo -n "Stopping $DESC: "
+       start-stop-daemon --stop --oknodo --quiet --exec $DAEMON -- stop
+       echo "$NAME."
+       ;;
+  restart|reload|force-reload)
+       echo -n "Restarting $DESC: "
+       start-stop-daemon --stop --oknodo --quiet --exec $DAEMON -- stop
+       sleep 2
+       start-stop-daemon --start --oknodo --quiet --exec $DAEMON -- start $OPTIONS
+       echo "$NAME."
+       ;;
+  *)
+       echo "Usage: /etc/init.d/$NAME {start|stop|reload|force-reload|restart}" >&2
+       exit 1
+esac
+
+exit 0
+
diff --git a/doc/aiccu.init.debian b/doc/aiccu.init.debian
new file mode 100644 (file)
index 0000000..96a3cec
--- /dev/null
@@ -0,0 +1,69 @@
+#! /bin/sh
+#
+# /etc/init.d/aiccu: start / stop AICCU
+#
+# Jeroen Massar <jeroen@sixxs.net>
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+NAME=aiccu
+DAEMON=/usr/sbin/${NAME}
+DESC="SixXS Automatic IPv6 Connectivity Client Utility (${NAME})"
+BACKGROUND=true
+
+# Options
+OPTIONS=""
+
+test -x $DAEMON || exit 0
+
+. /lib/lsb/init-functions
+
+if [ -f /etc/default/${NAME} ]; then
+       . /etc/default/${NAME}
+fi
+
+# Verify that the configuration file exists
+if [ ! -f /etc/aiccu.conf ]; then
+       echo "AICCU Configuration file /etc/aiccu.conf doesn't exist"
+       exit 0;
+fi
+
+# Verify that the configuration is correct
+if [ `grep -c "^username" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
+       echo "AICCU is not configured, edit /etc/aiccu.conf first"
+       exit 0;
+fi
+
+# Verify that it is in daemonize mode, otherwise it won't ever return
+if [ `grep -c "^daemonize true" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
+       echo "AICCU is not configured to daemonize on run"
+       exit 0;
+fi
+
+if [ "$BACKGROUND" = "false" ]; then
+       exit 0;
+fi
+
+case "$1" in
+  start)
+       log_begin_msg "Starting $DESC..."
+       start-stop-daemon --start --oknodo --quiet --exec $DAEMON -- start $OPTIONS
+       log_end_msg $?
+       ;;
+  stop)
+       log_begin_msg "Stopping $DESC..."
+       start-stop-daemon --stop --oknodo --quiet --exec $DAEMON -- stop
+       log_end_msg $?
+       ;;
+  restart|reload|force-reload)
+       log_begin_msg "Restarting $DESC..."
+       start-stop-daemon --stop --oknodo --quiet --exec $DAEMON -- stop
+       sleep 2
+       start-stop-daemon --start --oknodo --quiet --exec $DAEMON -- start $OPTIONS
+       log_end_msg $?
+       ;;
+  *)
+       echo "Usage: /etc/init.d/$NAME {start|stop|reload|force-reload|restart}" >&2
+       exit 1
+esac
+
+exit 0
diff --git a/doc/aiccu.init.freebsd b/doc/aiccu.init.freebsd
new file mode 100755 (executable)
index 0000000..10044c5
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# PROVIDE: sixxs-aiccu
+# REQUIRE: NETWORKING
+# KEYWORD: FreeBSD
+
+#
+# Add the following lines to /etc/rc.conf to enable sixxs-aiccu:
+#
+#sixxs_aiccu_enable="YES"
+#
+
+. %%RC_SUBR%%
+
+name=sixxs_aiccu
+rcvar=`set_rcvar`
+
+command="%%PREFIX%%/sbin/sixxs-aiccu start"
+command_args=%%PREFIX%%/etc/aiccu.conf
+stop_cmd="%%PREFIX%%/sbin/sixxs-aiccu stop"
+required_files=%%PREFIX%%/etc/aiccu.conf
+
+# set default
+sixxs_aiccu_enable=${sixxs_aiccu_enable:-"NO"}
+
+load_rc_config ${name}
+run_rc_command "$1"
+
diff --git a/doc/aiccu.init.gentoo b/doc/aiccu.init.gentoo
new file mode 100644 (file)
index 0000000..42bc112
--- /dev/null
@@ -0,0 +1,36 @@
+#!/sbin/runscript
+
+depend() {
+       need net
+       after ntp-client
+}
+
+checkconfig() {
+        # Verify that the configuration file exists
+        if [ ! -f /etc/aiccu.conf ]; then
+               eerror "AICCU Configuration file /etc/aiccu.conf doesn't exist"
+               return 1
+        fi
+       
+        # Verify that the configuration is correct
+        if [ `grep -c "^username" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
+               eerror "AICCU is not configured, edit /etc/aiccu.conf first"
+               return 1
+       fi
+}
+
+
+start() {
+       checkconfig || return 1
+       ebegin "Starting aiccu"
+       start-stop-daemon --start --oknodo --quiet --exec /usr/sbin/aiccu -- start
+       eend $?
+}
+
+
+stop() {
+       ebegin "Stopping aiccu"
+       start-stop-daemon --stop --oknodo --quiet --exec /usr/sbin/aiccu -- stop
+       eend $?
+}
+
diff --git a/doc/aiccu.init.rpm b/doc/aiccu.init.rpm
new file mode 100755 (executable)
index 0000000..b80271a
--- /dev/null
@@ -0,0 +1,105 @@
+#!/bin/sh
+#
+# description: Starts and stops the AICCU daemon
+#
+# aiccu: Starts and stops the AICCU daemon
+# description: hearbeat daemon for IPv6-in-IPv4 (Proto-41, AYIYA, Heartbeat) tunnels
+# pidfile: /var/run/aiccu.pid
+# config:  /etc/aiccu.conf
+# chkconfig: - 59 73
+# processname: aiccu
+
+# Source function library.
+if [ -f /etc/init.d/functions ] ; then
+  . /etc/init.d/functions
+elif [ -f /etc/rc.d/init.d/functions ] ; then
+  . /etc/rc.d/init.d/functions
+else
+  exit 0
+fi
+
+# Avoid using root's TMPDIR
+unset TMPDIR
+
+# Source networking configuration.
+. /etc/sysconfig/network
+
+# Default options
+OPTIONS=
+
+if [ -f /etc/sysconfig/aiccu ]; then
+   . /etc/sysconfig/aiccu
+fi
+
+# Check that networking is up.
+[ ${NETWORKING} = "no" ] && exit 0
+
+# Check that aiccu.conf exists.
+[ -f /etc/aiccu.conf ] || exit 0
+
+# Verify that the configuration is correct
+if [ `grep -c "^username" /etc/aiccu.conf 2>/dev/null` -ne 1 ]; then
+       echo "AICCU is not configured, edit /etc/aiccu.conf first"
+       exit 0;
+fi
+
+RETVAL=0
+
+KIND="AICCU (Automatic IPv6 Connectivity Configuration Utility)"
+
+start() {
+       echo -n $"Starting $KIND services: "
+       daemon aiccu start $OPTIONS
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0  ] && touch /var/lock/subsys/aiccu || \
+          RETVAL=1
+       return $RETVAL
+}      
+
+stop() {
+       echo -n $"Shutting down $KIND services: "
+       killproc aiccu
+       RETVAL=$?
+       echo
+       [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/aiccu
+       echo ""
+       return $RETVAL
+}      
+
+restart() {
+       stop
+       start
+}      
+
+rhstatus() {
+       status aiccu
+}      
+
+
+case "$1" in
+  start)
+       start
+       ;;
+  stop)
+       stop
+       ;;
+  restart)
+       restart
+       ;;
+  reload)
+       restart
+       ;;
+  status)
+       rhstatus
+       ;;
+  condrestart)
+       [ -f /var/lock/subsys/aiccu ] && restart || :
+       ;;
+  *)
+       echo $"Usage: $0 {start|stop|restart|reload|status|condrestart}"
+       exit 1
+esac
+
+exit $?
+
diff --git a/doc/aiccu.sgml b/doc/aiccu.sgml
new file mode 100644 (file)
index 0000000..e0e978b
--- /dev/null
@@ -0,0 +1,185 @@
+<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+
+<!-- Process this file with docbook-to-man to generate an nroff manual
+     page: `docbook-to-man manpage.sgml > manpage.1'.  You may view
+     the manual page with: `docbook-to-man manpage.sgml | nroff -man |
+     less'.  A typical entry in a Makefile or Makefile.am is:
+
+manpage.1: manpage.sgml
+       docbook-to-man $< > $@
+  -->
+
+  <!-- Fill in your name for FIRSTNAME and SURNAME. -->
+  <!ENTITY dhfirstname "<firstname>Jeroen</firstname>">
+  <!ENTITY dhsurname   "<surname>Massar</surname>">
+  <!-- Please adjust the date whenever revising the manpage. -->
+  <!ENTITY dhdate      "<date>January 09, 2005</date>">
+  <!-- SECTION should be 1-8, maybe w/ subsection other parameters are
+       allowed: see man(7), man(1). -->
+  <!ENTITY dhsection   "<manvolnum>1</manvolnum>">
+  <!ENTITY dhemail     "<email>jeroen@sixxs.net</email>">
+  <!ENTITY dhusername  "Jeroen Massar">
+  <!ENTITY dhucpackage "<refentrytitle>AICCU</refentrytitle>">
+  <!ENTITY dhpackage   "AICCU">
+
+  <!ENTITY debian      "<productname>Debian GNU/Linux</productname>">
+  <!ENTITY gnu         "<acronym>GNU</acronym>">
+]>
+
+<refentry>
+  <refentryinfo>
+    <address>
+      &dhemail;
+    </address>
+    <author>
+      &dhfirstname;
+      &dhsurname;
+    </author>
+    <copyright>
+      <year>2005</year>
+      <holder>&dhusername;</holder>
+    </copyright>
+    &dhdate;
+  </refentryinfo>
+  <refmeta>
+    &dhucpackage;
+
+    &dhsection;
+  </refmeta>
+  <refnamediv>
+    <refname>&dhpackage;</refname>
+
+    <refpurpose>Automatic IPv6 Connectivity Configuration Utility</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>aiccu </command>
+      <arg choice="req">&lt;start|stop|tunnels|test|autotest|license&gt;</arg>
+      <arg choice="opt"><replaceable>config</replaceable></arg>
+
+    </cmdsynopsis>
+  </refsynopsisdiv>
+  <refsect1>
+    <title>DESCRIPTION</title>
+
+    <para>
+AICCU makes it very easy for anybody to get IPv6 connectivity
+everywhere they want. It uses the TIC (Tunnel Information & Control)
+protocol to request the information needed to setup a tunnel through
+which the connectivity is created.
+
+AICCU supports the following tunneling protocols:
+ - 6in4 static    (RFC 2893)
+ - 6in4 heartbeat (RFC 2893 + draft-massar-v6ops-heartbeat)
+ - tinc           (http://www.tinc-vpn.org)
+ - AYIYA          (draft-massar-v6ops-ayiya)
+
+As AYIYA even works from behind NAT's, thus unless there is a very
+restrictive firewall in place, anybody should be able to get IPv6
+connectivity without problems and everywhere they want.
+</para>
+
+  </refsect1>
+  <refsect1>
+    <title>OPTIONS</title>
+
+    <variablelist>
+
+      <varlistentry>
+        <term>start</term>
+        <listitem>
+          <para>
+            Starts aiccu service.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>stop</term>
+        <listitem>
+          <para>
+            Stops aiccu service.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>tunnels</term>
+        <listitem>
+          <para>
+            Prints a list of currently available tunnels.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>test</term>
+        <listitem>
+          <para>
+            Builds the connection and runs a simple selftest allowing a user
+            to report this back as it should show most obvious problems.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>autotest</term>
+        <listitem>
+          <para>
+            Decription here
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term>license</term>
+        <listitem>
+          <para>
+            Shows the license aiccu is released under.
+          </para>
+        </listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><replaceable>config</replaceable></term>
+        <listitem>
+          <para>
+            Read the configuration from <replaceable>config</replaceable> file.
+          </para>
+        </listitem>
+      </varlistentry>
+
+    </variablelist>
+  </refsect1>
+  
+  <refsect1>
+    <title>SEE ALSO</title>
+
+    <para>The AICCU <ulink url="http://www.sixxs.net/tools/aiccu/">page</ulink> at sixxs.
+    </para>
+
+  </refsect1>
+  <refsect1>
+    <title>AUTHOR</title>
+
+    <para>AICCU was written by Jeroen Massar with contributions supplied a number of people as mentioned in the Changelog.</para>
+
+  </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:2
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:nil
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/changelog b/doc/changelog
new file mode 100755 (executable)
index 0000000..638c686
--- /dev/null
@@ -0,0 +1,198 @@
+aiccu (20070115) stable; urgency=medium
+  * Fixup in Debian init script (based on original patch by Bernhard Schmidt).
+  * Change in redirections so that errors don't show in debconf menu's etc.
+  * NetBSD fixes as there is not always a Tunnel Device that
+    supports IPv6 (thanks to Geert Hendrickx).
+  * Gentoo ebuild update, adding depends and require ntp-client.
+  * RPM spec update, add build-requirement.
+  * Check return values of system commands.
+  * Added a big warning about running AICCU from Daemontools and similar
+    programs which run AICCU in a loop, thus hammering the TIC server.
+  * Be a bit smarter in checking for support of IPv6.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Mon, 15 Jan 2007 11:00:42 +0000
+
+aiccu (20070107) stable; urgency=high
+  * 2007 Edition of AICCU.
+  * License change to standard 3-clause BSD license.
+    With thanks to Theo de Raadt, Marco d'Itri and Philipp Kern for
+    their wise words and reasoning for coming to this decision.
+  * High urgency because of the above and it fixing large problems.
+  * Fixed Mac OS X / Darwin support on the MacBookPro of Pim van Pelt.
+  * Added MTU, from TIC, configuration on most platforms.
+  * Fixed up silly linux bug, adding LL address to tunnels but not to tun/taps.
+  * Removed Win32 Alpha Endianess (reported by Christian Weisgerber).
+  * Fixed up alignment error in parseline() (reported by Christian Weisgerber).
+  * OpenBSD 4.0 support (patch provided by Christian Weisgerber).
+  * OpenBSD AYIYA fixup (patch provided by Pim van Pelt).
+  * Fedora/RPM init script fixup (bash case's don't fall through)
+    reported and patch supplied by Matt Domsch.
+  * NetBSD AYIYA support (noted by Tobias Riediger)
+    Works on NetBSD 4.x, for NetBSD 3.0 one needs to patch tun/tap to
+    support IPv6. Patch is available from the archives.
+  * local_ipv4_override option so one can use AICCU behind a NAT that
+    has been configured correctly to do proto-41 forwarding. This is
+    usually called a DMZ setup.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 07 Jan 2007 14:00:42 +0000
+
+aiccu (20060806) stable; urgency=low
+  * Changelog version format change as the 'official' (before there where
+    legal issues as they don't understand the word 'SHOULD' which is cleary
+    defined in the IETF and now somebody simply uploaded it anyway it without
+    even asking or notifying us about it) debian packages which are broken,
+    old and unsupported would seem newer and thus this new version would not
+    get updated to even when folks would have the official AICCU repository
+    in their sources.list. This solves that issue.
+  * pidfile fixup and configuration parameter.
+  * Corrected Broker selection in debconf.
+  * Configuration file rewriting by debconf is now done in a 'nice' way.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun,  6 Aug 2006 13:56:42 +0100 
+
+aiccu (2006-07-25) stable; urgency=low
+  * DragonFlyBSD fix
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Tue, 25 Jul 2006 11:22:42 +0100
+
+aiccu (2006-07-23) stable; urgency=low
+  * The Nina'th release.
+  * Verified AYIYA support on Windows, OpenBSD, FreeBSD and Linux ia32/AMD64/armeb.
+  * Disabled TSP and L2TP (Teepee) support as they are not finished.
+  * No more IPv4 interface as it is not used anymore.
+  * On AIX we now compile with xlc_r.
+  * Retrieves Tunnel Brokers from _aiccu.<search path> and from _aiccu.sixxs.net.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 23 Jul 2006 16:48:42 +0100
+
+aiccu (2006-07-13) stable; urgency=low
+  * Added no-configure and defaultroute options.
+  * AYIYA now forks so that AYIYA heartbeats work.
+  * Ctrl-C handling
+  * Protocol and server can be specified in configuration file
+  * AYIYA fixes: header alignment, Win32 TAP 8.1 support
+  * TAP listing using --listtaps (windows)
+  * Confuration can now be saved using a menu entry in the GUI (windows)
+  * TAP interface renaming when it's the only TAP and name not in the config (windows)
+  * Fedora fixes by Matt Domsch
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Thu, 13 Jul 2006 22:42:42 +0100
+
+aiccu (2006-03-10) stable; urgency=low
+  * Changed Debian start/stop priority as noted by Mario 'BitKoenig' Holbe.
+    They now match openvpn/pppd etc.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Fri, 10 Mar 2006 21:24:42 +0100
+
+aiccu (2005-12-05) stable; urgency=low
+  * DragonFlyBSD (uses the FreeBSD4 interface) added as noted by Geert Hendrickx.
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 14 Aug 2005 14:10:42 +0200
+
+aiccu (2005-08-14) stable; urgency=low
+  * Mac OS X typo-fix (reported by Wim Biemolt)
+  * GNUTLS support. TIC will go over TLS avoiding cleartext
+    negotiations where possible.
+  * Heartbeat stop & start per signal (requested by Peter Bieringer)
+  * AYIYA Heartbeating.
+  * L2TPv2 Support.
+  * TSP Support.
+  * Gary Coady's <gary@lyranthe.org> Debian/Ubuntu update:
+    * Use dpkg-buildpackage to generate deb files
+    * Remove configuration checks from Debian init script
+    * Use common print functions in Debian init script
+    * Add 'tunnels' parameter to aiccu, which reports available tunnels
+    * Return non-zero exit code if unable to successfully authenticate
+      to POP
+    * Log to stderr instead of stdout
+    * Send signal 0 to existing aiccu binary instead of SIGHUP
+    * Add debconf support
+    Thanks to Gary for these very nice addons!
+  * Added OpenBSD PortInfo by Thomas Kaschwig
+  * Added Makefile changes to support FreeBSD6, noted by Meno Abels
+  * Added _NETBSD_SOURCE define as mentioned by Maarten Dammers
+  * Changed aiccu_kame to do configuration differently depending
+    if the interface is a proto-41 one or a tun device.
+  * Solaris and AIX support + Endian Fixes.
+  * 'version' option for unix_console.
+  * 64bit fixes + compilation check against a big number of platforms.
+  * Multiple Tunnelbrokers Support using TXT records from _aiccu.sixxs.net DNS.
+  * AYIYA Port number set to 5072 (IANA assigned)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 14 Aug 2005 14:10:42 +0200
+
+aiccu (2005-01-31) stable; urgency=low
+  * Full integration of AYIYA, thus normal request procedures
+  * Version -gui/-console correction
+  * FreeBSD/Darwin route fixes (reported by Peter van Dijk)
+  * Windows: New POP logos added
+  * Linklocals for AYIYA tunnels making MLD and thus multicast
+    work (reported by Marco d'Itri)
+  * fflush() during non-syslog logging so that AICCU logs
+    correctly when run from daemontools (Peter van Dijk)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Mon, 31 Jan 2005 20:29:42 +0100
+
+aiccu (2005-01-09) stable; urgency=low
+
+  * Mum's birthday release
+  * MacOS X support (Marc Kramis)
+  * DEBUG messages are not logged anymore
+  * OpenBSD 2.x/3.x support (Wouter van Hemel)
+  * Don't overwrite config when doing a 'make install' (Wouter van Hemel)
+  * Manual page (Antonio Ospite)
+  * Windows Configuration directory based on GetWindowsDirectory()
+    (reported by Thomas B. Ruecker)
+  * Windows NAT message fix (reported by Thomas B. Ruecker)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 9 Jan 2005 09:00:42 +0100
+
+aiccu (2004-09-17-beta2b) stable; urgency=low
+
+  * OpenBSD fixes (AO)
+  * debian/rules debclean - now calls the correct clean (A0)
+  * Debian dependency on iproute (MdI)
+  * Gentoo Port (Thorsten Becker)
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 12 Sep 2004 10:24:42 +0100
+
+aiccu (2004-09-09-beta2a) stable; urgency=low
+
+  * Compile with pendantic, removing C++ "//" comments (AO)
+  * Debian fixes: file permissions, distclean (AO)
+  * rc.d addon (AO)
+  * Remove superfluous CVS dirs (AO)
+  * init script fix specifying 'start' (RS)
+  * RPM_OPT_FLAGS passing (RS)
+  * License fixes, making it more open (PvD & MdI)
+  * RPM package (RS)
+  * FreeBSD 4.x + 5.x port (MA)
+  * Many more fixes and cleanups (JM)
+  Who/what:
+  * AO = Antonio Ospite
+  * RS = Robert Schiele
+  * PvD = Peter van Dijk
+  * MdI = Marco d'Itri
+  * MA = Meno Abels
+  * JM = Jeroen Massar
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Thu, 09 Sep 2004 10:24:42 +0100
+
+aiccu (2004-08-30-beta2) stable; urgency=low
+
+  * Updated LICENSE which should now be 100% free(tm)
+  * Local-IP fix when using heartbeat tunnels
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Mon, 30 Aug 2004 21:26:42 +0100
+
+aiccu (2004-08-29-beta2) stable; urgency=low
+
+  * Brand spanking new AICCU
+  * Compiles both on Windows and UNIX
+  * Supports:
+    - TIC
+    - 6in4-static
+    - 6in4-heartbeat
+    - AYIYA
+
+ -- Jeroen Massar <jeroen@sixxs.net>  Sun, 29 Aug 2004 20:55:42 +0100
diff --git a/doc/manpage.refs b/doc/manpage.refs
new file mode 100644 (file)
index 0000000..b4d8bc5
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  '' => ''
+}
diff --git a/doc/setupscript.cmd b/doc/setupscript.cmd
new file mode 100755 (executable)
index 0000000..7456e57
--- /dev/null
@@ -0,0 +1,4 @@
+echo "The following variables are available to this script as passed by AICCU:"\r
+echo "1: %1%"\r
+echo "2: %2%"\r
+echo "3: %3%"\r
diff --git a/freebsd/Makefile b/freebsd/Makefile
new file mode 100644 (file)
index 0000000..31f7299
--- /dev/null
@@ -0,0 +1,45 @@
+# New ports collection makefile for:   sixxs-aiccu
+# Date created:                2004-09-09
+# Initial FreeBSD port by: Meno Abels <meno.abels@adviser.com>
+# Comments for this port please to the SixXS staff <info@sixxs.net>
+#
+## $FreeBSD: /repoman/r/pcvs/ports/net/sixxs-aiccu/Makefile,v 1.1 2005/03/14 17:47:07 vs Exp $
+#
+
+#PORTNAME=     sixxs-aiccu
+PORTVERSION=   20070107
+CATEGORIES=    net ipv6
+MASTER_SITES=  http://www.sixxs.net/archive/sixxs/aiccu/unix/
+DISTNAME=      aiccu_20070107
+
+# Maintainer of the FreeBSD port, but always copy: info@sixxs.net
+MAINTAINER=    meno.abels@adviser.com
+COMMENT=       IPv6 Tunnel Broker client capable of configuring using TIC, static, AYIYA and heartbeat tunnels
+
+USE_RC_SUBR=   sixxs-aiccu
+USE_GMAKE=     yes
+CFLAGS+=       ${PTHREAD_CFLAGS}
+LDFLAGS+=      ${PTHREAD_LIBS}
+MAKE_ARGS=     CC="${CC}"
+MAKE_ENV=      CFLAGS="${CFLAGS}" LDFLAGS="${LDFLAGS}"
+WRKSRC=                ${WRKDIR}/aiccu
+BUILD_WRKSRC=  ${WRKDIR}/aiccu/unix-console
+
+PORTDOCS=      README
+
+# FreeBSD doesn't use named interfaces, thus default to gif0
+pre-build:
+       @${SED} \
+               -e 's:ipv6_interface sixxs:ipv6_interface gif0:' \
+               ${WRKSRC}/doc/aiccu.conf > ${WRKDIR}/aiccu.conf
+
+do-install:
+       @${MKDIR} ${DOCSDIR} ${EXAMPLESDIR}
+       ${INSTALL_PROGRAM} ${WRKSRC}/unix-console/aiccu ${PREFIX}/sbin/sixxs-aiccu
+       ${INSTALL_DATA} ${WRKSRC}/doc/README ${DOCSDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/LICENSE ${DOCSDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/aiccu.conf ${EXAMPLESDIR}
+       ${INSTALL_DATA} ${WRKDIR}/aiccu.conf ${PREFIX}/etc/aiccu.conf.sample
+
+.include <bsd.port.mk>
+
diff --git a/freebsd/files/sixxs-aiccu.in b/freebsd/files/sixxs-aiccu.in
new file mode 100644 (file)
index 0000000..c2d6e32
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# $FreeBSD: ports/net/sixxs-aiccu/files/sixxs-aiccu.sh,v 1.3 2006/02/20 20:47:30 dougb Exp $
+#
+
+# PROVIDE: sixxs-aiccu
+# REQUIRE: NETWORKING
+
+#
+# Add the following lines to /etc/rc.conf to enable sixxs-aiccu:
+#
+#sixxs_aiccu_enable="YES"
+#
+
+. %%RC_SUBR%%
+
+name=sixxs_aiccu
+rcvar=`set_rcvar`
+
+command="%%PREFIX%%/sbin/sixxs-aiccu"
+command_args=%%PREFIX%%/etc/aiccu.conf
+start_cmd="%%PREFIX%%/sbin/sixxs-aiccu start $command_args"
+stop_cmd="%%PREFIX%%/sbin/sixxs-aiccu stop $command_args"
+required_files=%%PREFIX%%/etc/aiccu.conf
+
+# set default
+sixxs_aiccu_enable=${sixxs_aiccu_enable:-"NO"}
+
+load_rc_config ${name}
+run_rc_command "$1"
+
diff --git a/freebsd/pkg-descr b/freebsd/pkg-descr
new file mode 100644 (file)
index 0000000..f9c4ae2
--- /dev/null
@@ -0,0 +1,22 @@
+SixXS AICCU: Automatic IPv6 Connectivity Configuration Utility
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+AICCU makes it very easy for anybody to get IPv6 connectivity
+everywhere they want. It uses the TIC (Tunnel Information & Control)
+protocol to request the information needed to setup a tunnel through
+which the connectivity is created.
+
+AICCU supports the following tunneling protocols:
+ - 6in4 static    (RFC 2893)
+ - 6in4 heartbeat (RFC 2893 + draft-massar-v6ops-heartbeat)
+ - tinc           (http://www.tinc-vpn.org)
+ - AYIYA          (draft-massar-v6ops-ayiya)
+
+As AYIYA even works from behind NAT's, thus unless there is a very
+restrictive firewall in place, anybody should be able to get IPv6
+connectivity without problems and everywhere they want.
+
+The main AICCU page, containing information, screenshots, updates
+and of course the software itself, unix source + binaries/packages
+and Windows binaries, can be downloaded from:
+
+WWW: http://www.sixxs.net/tools/aiccu/
diff --git a/freebsd/pkg-plist b/freebsd/pkg-plist
new file mode 100644 (file)
index 0000000..43de74a
--- /dev/null
@@ -0,0 +1,6 @@
+@comment $FreeBSD$
+etc/aiccu.conf.sample
+sbin/sixxs-aiccu
+%%DOCSDIR%%/README
+%%EXAMPLESDIR%%/aiccu.conf
+@dirrm %%EXAMPLESDIR%%
diff --git a/gentoo/aiccu-ebuild b/gentoo/aiccu-ebuild
new file mode 100644 (file)
index 0000000..fddb010
--- /dev/null
@@ -0,0 +1,36 @@
+inherit eutils
+
+DESCRIPTION="AICCU, a cient to configure an IPv6 tunnel to SixXS and other Tunnel Brokers" 
+HOMEPAGE="http://www.sixxs.net/"
+SRC_URI="http://www.sixxs.net/archive/sixxs/aiccu/unix/aiccu_current.tar.gz"
+
+LICENSE="BSD"
+SLOT="0"
+KEYWORDS="x86 amd64 ppc arm hppa"
+IUSE=""
+DEPEND="net-libs/gnutls sys-apps/iproute2"
+S=${WORKDIR}/aiccu
+
+src_compile() {
+       cd ${S}
+       export RPM_OPT_FLAGS=${CFLAGS}
+       make || die "Build Failed"
+}
+
+src_install() {
+       dosbin unix-console/aiccu
+       insopts -m 600
+       insinto /etc
+       doins aiccu.conf
+       dodoc doc/{HOWTO,LICENSE,README,changelog}
+       exeinto /etc/init.d
+       newexe doc/aiccu.init.gentoo aiccu
+}
+
+pkg_postinst() {
+       einfo "The aiccu ebuild installs an init script named 'aiccu'"
+       einfo "To add support for a SixXS connection at startup, do"
+       einfo "edit your /etc/aiccu.conf and do"
+       einfo "# rc-update add aiccu default"
+}
+
diff --git a/netbsd/DESCR b/netbsd/DESCR
new file mode 100644 (file)
index 0000000..1c6ea42
--- /dev/null
@@ -0,0 +1,7 @@
+AICCU (Automatic IPv6 Connectivity Client Utility) makes it easy for users to
+get IPv6 connectivity via SixXs. After having requested an account, tunnel and
+optionally a subnet, AICCU can be used to automatically configure the tunnel.
+AICCU supports TIC (Tunnel Information & Control protocol), which it uses for
+retrieving the tunnel configuration information, AYIYA, which allows tunnels to
+be created even behind firewalls and NATs.
+
diff --git a/netbsd/Makefile b/netbsd/Makefile
new file mode 100644 (file)
index 0000000..3949e0d
--- /dev/null
@@ -0,0 +1,46 @@
+# $NetBSD: Makefile,v 1.7 2006/11/10 20:58:09 rillig Exp $
+
+DISTNAME=              aiccu_2006.07.25
+PKGNAME=               ${DISTNAME:S/_/-/:S/.//g}
+CATEGORIES=            net
+MASTER_SITES=          http://www.sixxs.net/archive/sixxs/aiccu/unix/
+
+MAINTAINER=            ghen@NetBSD.org
+HOMEPAGE=              http://www.sixxs.net/tools/aiccu/
+COMMENT=               Automatic IPv6 Connectivity Client Utility
+
+USE_TOOLS+=            gmake
+CHECK_PORTABILITY_SKIP+=       debian/*
+
+SUBST_CLASSES+=                sysconfdir
+SUBST_STAGE.sysconfdir=        post-patch
+SUBST_FILES.sysconfdir=        common/aiccu.h
+SUBST_SED.sysconfdir=  -e 's,/etc/aiccu.conf,${PKG_SYSCONFDIR}/aiccu.conf,'
+
+EXAMPLESDIR=           ${PREFIX}/share/examples/aiccu
+DOCDIR=                        ${PREFIX}/share/doc/aiccu
+CONF_FILES=            ${EXAMPLESDIR}/aiccu.conf ${PKG_SYSCONFDIR}/aiccu.conf
+CONF_FILES_MODE=       0600
+
+RCD_SCRIPTS=           aiccu
+
+.include "options.mk"
+
+# the distfile untars as ${WRKDIR}/aiccu/ but this would conflict with the
+# rc.d script that gets copied to the same name ${WRKDIR}/${RCD_SCRIPTS}
+post-extract:
+       ${MV} ${WRKDIR}/aiccu ${WRKDIR}/${DISTNAME}
+
+do-install:
+       ${INSTALL_PROGRAM} ${WRKSRC}/unix-console/aiccu ${PREFIX}/sbin/
+       ${INSTALL_MAN} ${WRKSRC}/doc/aiccu.1 ${PREFIX}/${PKGMANDIR}/man1/
+       ${INSTALL_DATA_DIR} ${EXAMPLESDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/aiccu.conf ${EXAMPLESDIR}/
+       ${INSTALL_DATA_DIR} ${DOCDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/README ${DOCDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/LICENSE ${DOCDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/HOWTO ${DOCDIR}
+
+.include "../../mk/pthread.buildlink3.mk"
+.include "../../mk/bsd.pkg.mk"
+
diff --git a/netbsd/PLIST b/netbsd/PLIST
new file mode 100644 (file)
index 0000000..5a9ed79
--- /dev/null
@@ -0,0 +1,11 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2005/12/29 14:53:52 ghen Exp $
+man/man1/aiccu.1
+sbin/aiccu
+share/doc/aiccu/HOWTO
+share/doc/aiccu/LICENSE
+share/doc/aiccu/README
+share/examples/aiccu/aiccu.conf
+share/examples/rc.d/aiccu
+@dirrm share/examples/aiccu
+@dirrm share/doc/aiccu
+
diff --git a/netbsd/options.mk b/netbsd/options.mk
new file mode 100644 (file)
index 0000000..6a2e041
--- /dev/null
@@ -0,0 +1,15 @@
+# $NetBSD: options.mk,v 1.2 2007/01/03 15:25:12 tv Exp $
+
+PKG_OPTIONS_VAR=               PKG_OPTIONS.aiccu
+PKG_SUPPORTED_OPTIONS=         gnutls
+PKG_OPTIONS_REQUIRED_GROUPS=   inet6 # require inet6 capability
+PKG_OPTIONS_GROUP.inet6=       inet6
+
+.include "../../mk/bsd.options.mk"
+
+.if !empty(PKG_OPTIONS:Mgnutls)
+.include "../../security/gnutls/buildlink3.mk"
+CFLAGS+=       -D AICCU_GNUTLS
+LDFLAGS+=      -lgnutls
+.endif
+
diff --git a/openbsd/Makefile b/openbsd/Makefile
new file mode 100644 (file)
index 0000000..4cf32d6
--- /dev/null
@@ -0,0 +1,45 @@
+# $OpenBSD$
+
+COMMENT=       "Automatic IPv6 Connectivity Configuration Utility (AICCU)"
+
+PKGNAME=       sixxs-aiccu-2007-01-07
+DISTNAME=      aiccu_20070107
+CATEGORIES=    net
+
+HOMEPAGE=      http://www.sixxs.net/tools/aiccu/
+MASTER_SITES=  http://www.sixxs.net/archive/sixxs/aiccu/unix/
+
+MAINTAINER=    Thomas Kaschwig <openbsd@kaschwig.net>
+
+SED=           /usr/bin/sed
+
+# GPL
+PERMIT_PACKAGE_CDROM=   Yes
+PERMIT_PACKAGE_FTP=     Yes
+PERMIT_DISTFILES_CDROM= Yes
+PERMIT_DISTFILES_FTP=   Yes
+WANTLIB=               c pthread
+
+EXTRACT_SUFX=  .tar.gz
+WRKDIST=       ${WRKDIR}/aiccu
+
+NO_REGRESS=    Yes
+
+USE_GMAKE=     Yes
+DOCDIR=                ${PREFIX}/share/doc/sixxs-aiccu
+EXAMPLEDIR=    ${PREFIX}/share/examples/sixxs-aiccu
+
+pre-build:
+       ${SED}  -e 's:ipv6_interface sixxs:ipv6_interface gif0:' \
+                       ${WRKSRC}/doc/aiccu.conf > ${WRKSRC}/aiccu.conf
+
+do-install:
+       ${INSTALL_DATA_DIR} ${DOCDIR} ${EXAMPLEDIR}
+       ${INSTALL_PROGRAM} ${WRKSRC}/unix-console/aiccu ${PREFIX}/sbin/sixxs-aiccu
+       ${INSTALL_DATA} ${WRKSRC}/aiccu.conf ${SYSCONFDIR}/aiccu.conf.sample
+       ${INSTALL_DATA} ${WRKSRC}/aiccu.conf ${EXAMPLEDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/README ${DOCDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/LICENSE ${DOCDIR}
+       ${INSTALL_DATA} ${WRKSRC}/doc/HOWTO ${DOCDIR}
+
+.include <bsd.port.mk>
diff --git a/openbsd/README b/openbsd/README
new file mode 100644 (file)
index 0000000..be74119
--- /dev/null
@@ -0,0 +1,10 @@
+Notes on the OpenBSD port of AICCU.
+You should regenerate the checksums in the distinfo file in this directory.
+
+Something like this should do the trick:
+{ 
+   md5 aiccu_2007.01.07.tar.gz
+   sha1 aiccu_2007.01.07.tar.gz
+   rmd160 aiccu_2007.01.07.tar.gz
+   echo "SIZE (aiccu_2007.01.07.tar.gz) = `ls -l aiccu_2007.01.07.tar.gz | awk '{ print $5}'`
+} > distinfo
diff --git a/openbsd/distinfo b/openbsd/distinfo
new file mode 100644 (file)
index 0000000..370fb3e
--- /dev/null
@@ -0,0 +1,4 @@
+MD5 (aiccu_2005.01.31.tar.gz) = 7c3da5feab3d59fb5a99a45203e0ca56
+SHA1 (aiccu_2005.01.31.tar.gz) = 2d3e9e1844e7e2b2ae144b00974a9d1022b45396
+RMD160 (aiccu_2005.01.31.tar.gz) = 48f9508bb62984acc8cde8419765c5003a7200f4
+SIZE (aiccu_2005.01.31.tar.gz) = 45672
diff --git a/openbsd/pkg/DESCR b/openbsd/pkg/DESCR
new file mode 120000 (symlink)
index 0000000..c5ac6cb
--- /dev/null
@@ -0,0 +1 @@
+../../freebsd/pkg-descr
\ No newline at end of file
diff --git a/openbsd/pkg/MESSAGE b/openbsd/pkg/MESSAGE
new file mode 100644 (file)
index 0000000..1be79db
--- /dev/null
@@ -0,0 +1,12 @@
+Copy ${PREFIX}/share/examples/sixxs-aiccu/aiccu.conf to
+${SYSCONFDIR} and insert your account data.
+
+You can start the daemon with:
+/usr/local/sbin/sixxs-aiccu start ${SYSCONFDIR}/aiccu.conf
+
+Add the following to the /etc/rc.local script to start the daemon on boot:
+
+if [ -x ${PREFIX}/sbin/sixxs-aiccu -a -f ${SYSCONFDIR}/aiccu.conf ]; then
+        echo -n ' sixxs-aiccu'
+        ${PREFIX}/sbin/sixxs-aiccu start ${SYSCONFDIR}/aiccu.conf
+fi
diff --git a/openbsd/pkg/PLIST b/openbsd/pkg/PLIST
new file mode 100644 (file)
index 0000000..b700c3b
--- /dev/null
@@ -0,0 +1,8 @@
+@comment $OpenBSD$
+sbin/sixxs-aiccu
+share/doc/sixxs-aiccu/
+share/doc/sixxs-aiccu/HOWTO
+share/doc/sixxs-aiccu/LICENSE
+share/doc/sixxs-aiccu/README
+share/examples/sixxs-aiccu/
+share/examples/sixxs-aiccu/aiccu.conf
diff --git a/rpm/aiccu.spec b/rpm/aiccu.spec
new file mode 100644 (file)
index 0000000..417e6ec
--- /dev/null
@@ -0,0 +1,87 @@
+############################################################
+# AICCU - Automatic IPv6 Connectivity Client Utility
+# by Jeroen Massar <jeroen@sixxs.net>
+# (c) Copyright 2003-2005 SixXS
+############################################################
+# AICCU RPM Spec File
+############################################################
+
+Summary:   AICCU - SixXS Automatic IPv6 Connectivity Client Utility
+Name:      aiccu
+Version:   2007.01.15
+Release:   1%{?dist}
+License:   BSD
+Group:     System Environment/Daemons
+URL:       http://www.sixxs.net/tools/aiccu/
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Source:    http://www.sixxs.net/archive/sixxs/aiccu/unix/aiccu_%{version}.tar.gz
+BuildRequires: gnutls-devel
+Requires:  iproute
+Requires(post): chkconfig
+Requires(preun): chkconfig, initscripts
+Requires(postun): initscripts
+
+%description
+This client automatically gives one IPv6 connectivity
+without having to manually configure interfaces etc.
+One does need a SixXS account and at least a tunnel. These
+can be freely & gratis requested from the SixXS website.
+For more information about SixXS check http://www.sixxs.net
+
+%prep
+%setup -q -n %{name}
+# fix executable permissions on non-executable content
+# so debuginfo can pick them up properly
+find . -type f -not -name rules -and -not -name *init* -exec chmod a-x \{\} \;
+
+%build
+make %{?_smp_mflags} RPM_OPT_FLAGS="$RPM_OPT_FLAGS"
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+
+%post
+if [ "$1" = "1" ]; then
+       /sbin/chkconfig --add aiccu
+fi
+
+%preun
+if [ "$1" = "0" ]; then
+       /sbin/service aiccu stop >/dev/null 2>&1
+       /sbin/chkconfig --del aiccu
+fi
+
+%postun
+/sbin/service aiccu condrestart > /dev/null 2>&1 || :
+
+%clean
+make clean
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root)
+%doc doc/README doc/LICENSE
+%{_sbindir}/aiccu
+# aiccu.conf contains the users's SixXS password, so don't
+# make it readable by non-root
+%attr(600, root,root) %config(noreplace) %{_sysconfdir}/aiccu.conf
+%{_sysconfdir}/init.d/aiccu
+
+
+%changelog
+* Wed Jun 28 2006 Matt Domsch <matt@domsch.com> 2005.01.31-4
+- export CFLAGS properly, fix permissions on files for debuginfo
+
+* Wed Jun 28 2006 Matt Domsch <matt@domsch.com> 2005.01.31-3
+- cleanups per Fedora Extras review
+
+* Sat Apr 22 2006 Matt Domsch <matt@domsch.com> 2005.01.31-2
+- match Fedora Extras spec guidelines
+- add postun condrestart
+- add reload initscript arg to satisfy rpmlint
+
+* Sun Aug 29 2004 Jeroen Massar <jeroen@sixxs.net> 2004.08.29
+- Beta2 with TIC, 6in4, 6in4-heartbeat and AYIYA support
+
diff --git a/unix-console/Makefile b/unix-console/Makefile
new file mode 100755 (executable)
index 0000000..d5e5c07
--- /dev/null
@@ -0,0 +1,159 @@
+# /**********************************************************
+#  SixXS - Automatic IPv6 Connectivity Configuration Utility
+# ***********************************************************
+#  Copyright 2003-2005 SixXS - http://www.sixxs.net
+# ***********************************************************
+#  unix-client/Makefile - Makefile for the UNIX client
+# ***********************************************************
+#  $Author: jeroen $
+#  $Id: Makefile,v 1.32 2007-01-15 11:04:27 jeroen Exp $
+#  $Date: 2007-01-15 11:04:27 $
+# **********************************************************/
+
+SRCS   = main.c ../common/tun.c ../common/aiccu.c ../common/hash_md5.c ../common/hash_sha1.c ../common/common.c ../common/heartbeat.c ../common/tic.c ../common/ayiya.c ../common/aiccu_test.c ../common/resolver.c
+INCS   = ../common/tun.h ../common/aiccu.h ../common/hash_md5.h ../common/hash_sha1.h ../common/common.h ../common/heartbeat.h ../common/tic.h ../common/ayiya.h ../common/resolver.h
+OBJS   = main.o ../common/tun.o ../common/aiccu.o ../common/hash_md5.o ../common/hash_sha1.o ../common/common.o ../common/heartbeat.o ../common/tic.o ../common/ayiya.o ../common/aiccu_test.o ../common/resolver.o
+
+# New features not fully implemented and thus disabled for now
+#CFLAGS        += -D NEWSTUFF_TSP -D NEWSTUFF_TEEPEE
+#SRCS += ../common/tsp.c ../common/teepee.c
+#OBJS += ../common/tsp.o ../common/teepee.o
+#INCS += ../common/tsp.h ../common/teepee.h
+
+# Our very *bliep* set of options to make sure that these things can't cause any issues
+CWARNS += -W -Wall -Wshadow -Wpointer-arith -Wcast-align -Wwrite-strings -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wbad-function-cast -fshort-enums -fstrict-aliasing -fno-common -Wpadded -pedantic -D_REENTRANT
+# CWARNS += -Wpacked
+
+#CFLAGS        += $(CWARNS) -D_GNU_SOURCE -D_DEBUG -g3 -O0
+CFLAGS += $(CWARNS) -D_GNU_SOURCE
+CC      = @gcc
+RM      = rm
+
+# Add -O3 when nothing is specified yet
+ifeq ($(shell echo $(CFLAGS) | grep -c "\-O"),0)
+CFLAGS += -O3
+endif
+
+# This is a console client
+CFLAGS += -D AICCU_CONSOLE
+
+# GnuTLS Support ?
+# Used by TIC to secure that communication
+# Currently defaultly builds only on Linux, but other platforms might easily also support it
+ifeq ($(shell uname | grep -c "Linux"),1)
+CFLAGS += -D AICCU_GNUTLS
+LDFLAGS += -lgnutls
+endif
+
+# Linux
+ifeq ($(shell uname | grep -c "Linux"),1)
+CFLAGS  += -D_LINUX -D HAS_IFHEAD -D AICCU_TYPE="\"linux\""
+SRCS   += ../common/aiccu_linux.c
+OBJS   += ../common/aiccu_linux.o
+LDFLAGS        += -lpthread -lresolv
+endif
+
+# FreeBSD
+ifeq ($(shell uname | grep -c "FreeBSD"),1)
+CFLAGS += -D_FREEBSD
+
+# FreeBSD 4.x
+ifeq ($(shell uname -r | cut -c 1),4)
+CFLAGS += -D AICCU_TYPE="\"freebsd4\""
+SRCS   += ../common/aiccu_freebsd4.c
+OBJS   += ../common/aiccu_freebsd4.o
+else
+# FreeBSD 5.x/6.x/7.x
+CFLAGS += -D NEED_IFHEAD -D AICCU_TYPE="\"kame\""
+SRCS   += ../common/aiccu_kame.c
+OBJS   += ../common/aiccu_kame.o
+endif
+endif
+
+# DragonFlyBSD
+ifeq ($(shell uname | grep -c "DragonFly"),1)
+CFLAGS += -D_DFBSD -D NEED_IFHEAD -D AICCU_TYPE="\"dragonfly\""
+SRCS   += ../common/aiccu_freebsd4.c
+OBJS   += ../common/aiccu_freebsd4.o
+CFLAGS += -pthread
+endif
+
+# NetBSD
+ifeq ($(shell uname | grep -c "NetBSD"),1)
+CFLAGS += -D_NETBSD -D AICCU_TYPE="\"kame\""
+
+# Check if net/if_tun.h has TUNSIFHEAD and enable support for it
+ifneq ($(shell grep -c TUNSIFHEAD /usr/include/net/if_tun.h 2>/dev/null),1)
+# Supports TUNSIFHEAD -> AYIYA/l2tp available
+CFLAGS += -D NEED_IFHEAD
+else
+# Doesn't support TUNSIFHEAD -> No AYIYA/l2tp available
+CFLAGS += -D NO_IFHEAD
+endif
+
+SRCS   += ../common/aiccu_kame.c
+OBJS   += ../common/aiccu_kame.o
+CFLAGS += -pthread -D_NETBSD_SOURCE
+endif
+
+# OpenBSD
+ifeq ($(shell uname | grep -c "OpenBSD"),1)
+CFLAGS += -D_OPENBSD -D HAS_IFHEAD
+# 2.7-2.9
+ifeq ($(shell uname -r | cut -c 1),2)
+CFLAGS += -D AICCU_TYPE="\"openbsd2\""
+SRCS   += ../common/aiccu_openbsd2.c
+OBJS   += ../common/aiccu_openbsd2.o
+else
+# 3.x-4.x etc
+CFLAGS += -D AICCU_TYPE="\"openbsd\""
+SRCS   += ../common/aiccu_openbsd.c
+OBJS   += ../common/aiccu_openbsd.o
+endif
+CFLAGS += -pthread
+endif
+
+# Darwin
+ifeq ($(shell uname | grep -c "Darwin"),1)
+CFLAGS += -D_DARWIN -D NEED_IFHEAD -D AICCU_TYPE="\"darwin\""
+SRCS   += ../common/aiccu_darwin.c
+OBJS   += ../common/aiccu_darwin.o
+LDFLAGS        += -lresolv
+endif
+
+# SunOS / Solaris
+ifeq ($(shell uname | grep -c "SunOS"),1)
+CFLAGS += -D_SUNOS -D AICCU_TYPE="\"sunos\""
+SRCS   += ../common/aiccu_sunos.c
+OBJS   += ../common/aiccu_sunos.o
+LDFLAGS        += -lsocket -lnsl -lresolv
+endif
+
+# AIX
+ifeq ($(shell uname | grep -c "AIX"),1)
+CC     = @/usr/vac/bin/xlc_r
+CFLAGS = -qthreaded -q64 -qlanglvl=stdc99 -bmaxdata:0xD0000000 -D_64BIT -g -qdbxextra -qfullpath -qheapdebug -qformat=all -qcheck=all
+CFLAGS += -D AICCU_CONSOLE
+CFLAGS += -D_AIX -D AICCU_TYPE="\"aix\""
+SRCS   += ../common/aiccu_aix.c
+OBJS   += ../common/aiccu_aix.o
+LDFLAGS        += -lpthread
+endif
+
+
+all: aiccu
+
+aiccu: $(OBJS) ${SRCS} ${INCS}
+       $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS)
+ifeq ($(shell echo $(CFLAGS) | grep -c "DEBUG"),0)
+ifeq ($(shell echo "$(RPM_OPT_FLAGS)" | wc -c),1)
+       strip $@
+endif
+endif
+
+clean:
+       $(RM) -f $(OBJS) aiccu
+
+install: aiccu
+       cp aiccu ${DESTDIR}${dirsbin}aiccu
+
diff --git a/unix-console/main.c b/unix-console/main.c
new file mode 100755 (executable)
index 0000000..8a4d9a9
--- /dev/null
@@ -0,0 +1,504 @@
+/**********************************************************
+ SixXS - Automatic IPv6 Connectivity Configuration Utility
+***********************************************************
+ Copyright 2003-2005 SixXS - http://www.sixxs.net
+***********************************************************
+ unix-client/aiccu.c - AICCU - The client for UNIX
+***********************************************************
+ $Author: jeroen $
+ $Id: main.c,v 1.20 2007-01-15 11:57:34 jeroen Exp $
+ $Date: 2007-01-15 11:57:34 $
+**********************************************************/
+
+#include "../common/aiccu.h"
+#include "../common/tun.h"
+
+#ifndef _WIN32
+/* Enable/Disable heartbeating */
+void sigusr1(int i);
+void sigusr1(int i)
+{
+       /* Toggle the flag */
+       g_aiccu->makebeats = !g_aiccu->makebeats;
+
+       /* Reset the signal */
+       signal(i, &sigusr1);
+}
+
+void sigterm(int i);
+void sigterm(int i)
+{
+       g_aiccu->running = false;
+       signal(i, SIG_IGN);
+}
+
+int sigrunning(int sig);
+int sigrunning(int sig)
+{
+       int     pid;
+       FILE    *f;
+
+       if (!g_aiccu) return 0;
+
+       /* Open our PID file */
+       f = fopen(g_aiccu->pidfile, "r");
+       if (!f) return 0;
+
+       /* Get the PID from the file or make it invalid when the format is wrong */
+       if (fscanf(f, "%d", &pid) != 1) pid = -1;
+
+       /* Close the file again */
+       fclose(f);
+
+       /* If we can HUP it, it still runs */
+       return (pid > 0 && kill(pid, sig) == 0 ? 1 : 0);
+}
+
+#else
+
+static BOOL sigterm(DWORD sig);
+static BOOL sigterm(DWORD sig)
+{
+       D(dolog(LOG_DEBUG, "Terminating due to CTRL event\n"));
+       g_aiccu->running = false;
+       return true;
+}
+static BOOL sigterm_testing(DWORD sig);
+static BOOL sigterm_testing(DWORD sig)
+{
+       D(dolog(LOG_DEBUG, "Ignoring CTRL event\n"));
+       return true;
+}
+
+#endif
+
+int list_tunnels(void);
+int list_tunnels(void)
+{
+       struct TIC_sTunnel *hsTunnel, *t;
+
+       if (!tic_Login(g_aiccu->tic, g_aiccu->username, g_aiccu->password, g_aiccu->server)) return 0;
+
+       hsTunnel = tic_ListTunnels(g_aiccu->tic);
+
+       if (!hsTunnel)
+       {
+               tic_Logout(g_aiccu->tic, "Getting current tunnel listing");
+               return 1;
+       }
+
+       for (t = hsTunnel; t; t = t->next)
+       {
+               printf("%s %s %s %s\n", t->sId, t->sIPv6, t->sIPv4, t->sPOPId);
+       }
+
+       tic_Free_sTunnel(hsTunnel);
+       tic_Logout(g_aiccu->tic, "Getting current tunnel listing");
+       return 1;
+}
+
+static unsigned int prevnum = 54321;
+
+/* Due to broken DNS servers out there, make sure that we get at least the SixXS TIC server */
+static bool foundsixxs = false;
+
+void gotrr(unsigned int num, int type, const char *record);
+void gotrr(unsigned int num, int type, const char *record)
+{
+       /* Skip non-TXT records + Comments */
+       if (type != T_TXT || record[0] == '#') return;
+       /* If the record number changed and it is not the first one, add a return */
+       if (num != prevnum && prevnum != 54321) printf("\n");
+
+       /* The current record = the last one seen */
+       prevnum = num;
+
+       /* Print the component */
+       printf("%s|", record);
+
+       /* Found SixXS? */
+       if (strcmp(record, "SixXS") == 0) foundsixxs = true;
+}
+
+/* Get Tunnel Brokers from _aiccu.<search path> and from _aiccu.sixxs.net */
+int list_brokers(void);
+int list_brokers(void)
+{
+       foundsixxs = false;
+       prevnum = 54321;
+       getrrs("_aiccu", T_TXT, gotrr);
+       prevnum = 54321;
+       getrrs("_aiccu.sixxs.net", T_TXT, gotrr);
+       printf("\n");
+
+       if (!foundsixxs)
+       {
+               printf("SixXS|tic://tic.sixxs.net|http://www.sixxs.net|be de ee fi gb ie it nl pl pt si se us");
+
+               /* Warn the user of the missing global tb's */
+               fprintf(stderr, "Warning: Couldn't find global Tunnel Brokers List, please check your DNS settings and read the FAQ.\n");
+       }
+
+       return 1;
+}
+
+/* 
+ * AICCU! - Aka... let's get connected ;)
+ * returns a TIC_Tunnel which can then be
+ * used for configuring and keeping it running
+ */
+struct TIC_Tunnel *get_tunnel(void);
+struct TIC_Tunnel *get_tunnel(void)
+{
+       
+       struct TIC_sTunnel      *hsTunnel, *t;
+       struct TIC_Tunnel       *hTunnel;
+
+       /* Login to the TIC Server */
+       if (!tic_Login(g_aiccu->tic, g_aiccu->username, g_aiccu->password, g_aiccu->server)) return NULL;
+
+       /* 
+        * Don't try to list the tunnels when
+        * we already have a tunnel_id configured
+        */
+       if (!g_aiccu->tunnel_id)
+       {       
+               hsTunnel = tic_ListTunnels(g_aiccu->tic);
+               if (!hsTunnel)
+               {
+                       dolog(LOG_ERR, "No tunnel available, request one first\n");
+                       tic_Free_sTunnel(hsTunnel);
+                       tic_Logout(g_aiccu->tic, "I didn't have any tunnels to select");
+                       return NULL;
+               }
+       
+               if (hsTunnel->next)
+               {
+                       dolog(LOG_ERR, "Multiple tunnels available, please pick one from the following list and configure the aiccu.conf using it\n");
+                       for (t = hsTunnel; t; t = t->next)
+                       {
+                               dolog(LOG_ERR, "%s %s %s %s\n", t->sId, t->sIPv6, t->sIPv4, t->sPOPId);
+                       }
+                       tic_Free_sTunnel(hsTunnel);
+                       tic_Logout(g_aiccu->tic, "User still needed to select a tunnel");
+                       return NULL;
+               }
+               g_aiccu->tunnel_id = strdup(hsTunnel->sId);
+
+               /* Free the info */
+               tic_Free_sTunnel(hsTunnel);
+       }
+
+       /* Get Tunnel Information */
+       hTunnel = tic_GetTunnel(g_aiccu->tic, g_aiccu->tunnel_id);
+       if (!hTunnel)
+       {
+               tic_Logout(g_aiccu->tic, "No such tunnel");
+               return NULL;
+       }
+
+       /* Logout, TIC is not needed any more */
+       tic_Logout(g_aiccu->tic, NULL);
+
+       /* Swee.... sufficient information */
+       return hTunnel;
+}
+
+enum AICCU_MODES
+{
+       A_NONE = 0,
+       A_START,
+       A_STOP,
+       A_BROKERS,
+       A_TUNNELS,
+       A_TEST,
+       A_AUTOTEST,
+       A_LICENSE,
+#ifdef _WIN32
+       A_LISTTAPS,
+#endif
+       A_VERSION
+};
+
+const char *options = "aiccu (start|stop|brokers|tunnels|test|autotest|license|"
+#ifdef _WIN32
+       "listtaps|"
+#endif
+       "version) [<configfile>]\n";
+
+int main(int argc, char *argv[])
+{
+       enum AICCU_MODES        mode = A_NONE;
+
+       struct TIC_Tunnel       *hTunnel;
+#ifdef _WIN32
+       WSADATA                 wsadata;
+       unsigned int            i;
+
+       /* Initialize Winsock so that we can do network functions */
+       WSAStartup(WINSOCK_VERSION, &wsadata);
+#endif
+
+       /* Initialize Configuration */
+       aiccu_InitConfig();
+
+       /* Make sure we actually have an IPv6 stack */
+       aiccu_install();
+
+       /* Require start/stop/test */
+       if (argc == 2 || argc == 3)
+       {
+                    if (strcasecmp(argv[1], "start")   == 0) mode = A_START;
+               else if (strcasecmp(argv[1], "stop")    == 0) mode = A_STOP;
+               else if (strcasecmp(argv[1], "brokers") == 0) mode = A_BROKERS;
+               else if (strcasecmp(argv[1], "tunnels") == 0) mode = A_TUNNELS;
+               else if (strcasecmp(argv[1], "test")    == 0) mode = A_TEST;
+               else if (strcasecmp(argv[1], "autotest")== 0) mode = A_AUTOTEST;
+               else if (strcasecmp(argv[1], "license") == 0) mode = A_LICENSE;
+#ifdef _WIN32
+               else if (strcasecmp(argv[1], "listtaps") == 0) mode = A_LISTTAPS;
+#endif
+               else if (strcasecmp(argv[1], "version") == 0) mode = A_VERSION;
+       }
+
+       /* Optionally we want a second argument: a config file */
+       if ((   argc != 2 &&
+               argc != 3) ||
+               mode == A_NONE)
+       {
+               dolog(LOG_ERR, "%s", options);
+               return -1;
+       }
+
+       if (    mode == A_LICENSE)
+       {
+               printf("%s\n", aiccu_license());
+               return 0;
+       }
+
+       if (    mode == A_VERSION)
+       {
+               printf("AICCU %s by Jeroen Massar\n", AICCU_VERSION);
+               return 0;
+       }
+
+#ifdef _WIN32
+       if (    mode == A_LISTTAPS)
+       {
+               tun_list_tap_adapters();
+               return 0;
+       }
+#endif
+
+       if (    mode == A_BROKERS)
+       {
+               int ret = list_brokers();
+               aiccu_FreeConfig();
+               return ret == 0 ? -1 : 0;
+       }
+
+       if (!aiccu_LoadConfig(argc <= 2 ? NULL : argv[2]))
+       {
+               return -1;
+       }
+
+#ifndef _WIN32
+       /* start or stop? */
+       if (    mode != A_TEST &&
+               mode != A_AUTOTEST)
+       {
+               /* Already running? */
+               if (sigrunning(mode == A_STOP ? SIGTERM : 0) == 1)
+               {
+                       dolog(LOG_ERR, "Already running instance HUP'ed, exiting\n");
+                       return 0;
+               }
+       }
+#endif
+
+       /* Verify required parameters */
+       if (!g_aiccu->username || !g_aiccu->password)
+       {
+               dolog(LOG_ERR, "Required parameters missing, make sure that username and password are given\n");
+               aiccu_FreeConfig();
+               return -1;
+       }
+
+       if (mode == A_TUNNELS)
+       {
+               int ret = list_tunnels();
+               aiccu_FreeConfig();
+               return ret == 0 ? -1 : 0;
+       }
+
+       /* Get our tunnel */
+       hTunnel = get_tunnel();
+       
+       if (!hTunnel)
+       {
+               dolog(LOG_ERR, "Couldn't retrieve first tunnel for the above reason, aborting\n");
+               aiccu_FreeConfig();
+               return -1;
+       }
+
+       /* 
+        * We now have sufficient information.
+        * Thus we can logout from the TIC server
+        */
+       tic_Logout(g_aiccu->tic, NULL);
+       g_aiccu->tic = NULL;
+
+       if (g_aiccu->verbose)
+       {
+               printf("Tunnel Information for %s:\n",hTunnel->sId);
+               printf("POP Id      : %s\n", hTunnel->sPOP_Id);
+               printf("IPv6 Local  : %s/%u\n", hTunnel->sIPv6_Local,hTunnel->nIPv6_PrefixLength);
+               printf("IPv6 Remote : %s/%u\n", hTunnel->sIPv6_POP,hTunnel->nIPv6_PrefixLength);
+               printf("Tunnel Type : %s\n", hTunnel->sType);
+               printf("Adminstate  : %s\n", hTunnel->sAdminState);
+               printf("Userstate   : %s\n", hTunnel->sUserState);
+       }
+
+       /* One can always try to stop it */
+       if (mode == A_STOP)
+       {
+               aiccu_delete(hTunnel);
+
+               /* Free stuff and exit */
+               tic_Free_Tunnel(hTunnel);
+               aiccu_FreeConfig();
+               return 0;
+       }
+
+       if (    (strcmp(hTunnel->sAdminState,   "enabled") != 0) ||
+               (strcmp(hTunnel->sUserState,    "enabled") != 0))
+       {
+               dolog(LOG_ERR, "Tunnel is not enabled (UserState: %s, AdminState: %s)\n", hTunnel->sAdminState, hTunnel->sUserState);
+               return -1;
+       }
+
+       /* Do the test thing */
+       if (    mode == A_TEST ||
+               mode == A_AUTOTEST)
+       {
+#ifdef _WIN32
+               SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigterm_testing, true);
+#endif
+               /* Setup the tunnel */
+               if (aiccu_setup(hTunnel, true))
+               {
+                       aiccu_test(hTunnel, strcasecmp(argv[1], "autotest") == 0 ? true : false);
+
+                       /* Tear the tunnel down again */
+                       aiccu_delete(hTunnel);
+               }
+               else
+               {
+                       dolog(LOG_ERR, "Tunnel Setup Failed\n");
+               }
+
+               /* exit as all is done */
+               tic_Free_Tunnel(hTunnel);
+               aiccu_FreeConfig();
+               return 0;
+       }
+
+#ifndef _WIN32
+       if (    mode == A_START &&
+               g_aiccu->daemonize != 0)
+       {
+               FILE    *f;
+
+               /* Daemonize */
+               int i = fork();
+               if (i < 0)
+               {
+                       fprintf(stderr, "Couldn't fork\n");
+                       return -1;
+               }
+               /* Exit the mother fork */
+               if (i != 0) return 0;
+
+               /* Child fork */
+               setsid();
+
+               /* Chdir to minimise disruption to FS umounts */
+               (void)chdir("/");
+
+               /* Cleanup stdin/out/err */
+               freopen("/dev/null","r",stdin);
+               freopen("/dev/null","w",stdout);
+               freopen("/dev/null","w",stderr);
+
+               /* */
+               f = fopen(g_aiccu->pidfile, "w");
+               if (!f)
+               {
+                       dolog(LOG_ERR, "Could not store PID in file %s\n", g_aiccu->pidfile);
+                       return 0;
+               }
+
+               fprintf(f, "%d", getpid());
+               fclose(f);
+
+               dolog(LOG_INFO, "AICCU running as PID %d\n", getpid());
+       }
+
+#endif /* !_WIN32 */
+
+       /* mode == A_START */
+
+#ifndef _WIN32
+       /*
+        * Install a signal handler so that
+        * one can disable beating with SIGUSR1
+        */
+       signal(SIGUSR1, &sigusr1);
+
+       /*
+        * Install a signal handler so that
+        * one can stop this program with SIGTERM
+        */
+       signal(SIGTERM, &sigterm);
+       signal(SIGINT, &sigterm);
+#else
+       SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigterm, true);
+#endif
+
+       /* 
+        * Setup our tunnel
+        * This also spawns required threads for AYIYA
+        */
+       if (aiccu_setup(hTunnel, true))
+       {
+               /* We need to stay running when doing Heartbeat or AYIYA */
+               if (    strcasecmp(hTunnel->sType, "6in4-heartbeat") == 0 ||
+                       strcasecmp(hTunnel->sType, "ayiya") == 0)
+               {
+                       /* We are spawned, now just beat once in a while. */
+                       while (g_aiccu->running)
+                       {
+                               aiccu_beat(hTunnel);
+#ifndef _WIN32
+                               sleep(hTunnel->nHeartbeat_Interval);
+#else
+                               for (i=0; g_aiccu->running && i <= hTunnel->nHeartbeat_Interval; i++) Sleep(1000);
+#endif
+                       }
+
+                       /* Clean up the the tunnel, no beat anyway */
+                       aiccu_delete(hTunnel);
+               }
+
+#ifndef _WIN32
+               /* Remove our PID file */
+               if (g_aiccu) unlink(g_aiccu->pidfile);
+#endif
+       }
+
+       /* Free our resources */
+       aiccu_FreeConfig();
+
+       return 0;
+}
+