From 5999826d248c425d994b129edc982fbf18eac4c7 Mon Sep 17 00:00:00 2001 From: Reinier Haasjes Date: Sat, 19 Dec 2009 14:16:47 +0100 Subject: [PATCH] Imported Upstream version 20070115 --- Makefile | 201 ++++++++++ common/aiccu.c | 444 ++++++++++++++++++++++ common/aiccu.h | 159 ++++++++ common/aiccu_aix.c | 90 +++++ common/aiccu_darwin.c | 87 +++++ common/aiccu_freebsd4.c | 111 ++++++ common/aiccu_kame.c | 97 +++++ common/aiccu_linux.c | 122 ++++++ common/aiccu_openbsd.c | 88 +++++ common/aiccu_openbsd2.c | 90 +++++ common/aiccu_sunos.c | 74 ++++ common/aiccu_test.c | 179 +++++++++ common/ayiya.c | 473 +++++++++++++++++++++++ common/ayiya.h | 92 +++++ common/common.c | 739 ++++++++++++++++++++++++++++++++++++ common/common.h | 417 +++++++++++++++++++++ common/hash_md5.c | 240 ++++++++++++ common/hash_md5.h | 69 ++++ common/hash_sha1.c | 167 +++++++++ common/hash_sha1.h | 71 ++++ common/heartbeat.c | 295 +++++++++++++++ common/heartbeat.h | 39 ++ common/resolver.c | 209 +++++++++++ common/resolver.h | 84 +++++ common/tic.c | 744 +++++++++++++++++++++++++++++++++++++ common/tic.h | 147 ++++++++ common/tun.c | 866 +++++++++++++++++++++++++++++++++++++++++++ common/tun.h | 45 +++ debian/aiccu.config | 168 +++++++++ debian/aiccu.manpages | 1 + debian/aiccu.postinst | 108 ++++++ debian/aiccu.preinst | 3 + debian/changelog | 198 ++++++++++ debian/control | 18 + debian/dirs | 2 + debian/docs | 3 + debian/postrm.debhelper | 6 + debian/rules | 82 ++++ debian/substvars | 1 + debian/templates | 43 +++ doc/COPYRIGHT | 6 + doc/HOWTO | 40 ++ doc/LICENSE | 29 ++ doc/README | 62 ++++ doc/aiccu.1 | 56 +++ doc/aiccu.conf | 78 ++++ doc/aiccu.init | 68 ++++ doc/aiccu.init.debian | 69 ++++ doc/aiccu.init.freebsd | 31 ++ doc/aiccu.init.gentoo | 36 ++ doc/aiccu.init.rpm | 105 ++++++ doc/aiccu.sgml | 185 +++++++++ doc/changelog | 198 ++++++++++ doc/manpage.refs | 3 + doc/setupscript.cmd | 4 + freebsd/Makefile | 45 +++ freebsd/files/sixxs-aiccu.in | 31 ++ freebsd/pkg-descr | 22 ++ freebsd/pkg-plist | 6 + gentoo/aiccu-ebuild | 36 ++ netbsd/DESCR | 7 + netbsd/Makefile | 46 +++ netbsd/PLIST | 11 + netbsd/options.mk | 15 + openbsd/Makefile | 45 +++ openbsd/README | 10 + openbsd/distinfo | 4 + openbsd/pkg/DESCR | 1 + openbsd/pkg/MESSAGE | 12 + openbsd/pkg/PLIST | 8 + rpm/aiccu.spec | 87 +++++ unix-console/Makefile | 159 ++++++++ unix-console/main.c | 504 +++++++++++++++++++++++++ 73 files changed, 9091 insertions(+) create mode 100644 Makefile create mode 100755 common/aiccu.c create mode 100755 common/aiccu.h create mode 100644 common/aiccu_aix.c create mode 100755 common/aiccu_darwin.c create mode 100755 common/aiccu_freebsd4.c create mode 100755 common/aiccu_kame.c create mode 100755 common/aiccu_linux.c create mode 100755 common/aiccu_openbsd.c create mode 100644 common/aiccu_openbsd2.c create mode 100755 common/aiccu_sunos.c create mode 100755 common/aiccu_test.c create mode 100755 common/ayiya.c create mode 100755 common/ayiya.h create mode 100755 common/common.c create mode 100755 common/common.h create mode 100755 common/hash_md5.c create mode 100755 common/hash_md5.h create mode 100755 common/hash_sha1.c create mode 100755 common/hash_sha1.h create mode 100755 common/heartbeat.c create mode 100755 common/heartbeat.h create mode 100644 common/resolver.c create mode 100755 common/resolver.h create mode 100755 common/tic.c create mode 100755 common/tic.h create mode 100755 common/tun.c create mode 100755 common/tun.h create mode 100755 debian/aiccu.config create mode 100644 debian/aiccu.manpages create mode 100755 debian/aiccu.postinst create mode 100644 debian/aiccu.preinst create mode 100755 debian/changelog create mode 100755 debian/control create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/postrm.debhelper create mode 100755 debian/rules create mode 100644 debian/substvars create mode 100644 debian/templates create mode 100644 doc/COPYRIGHT create mode 100644 doc/HOWTO create mode 100644 doc/LICENSE create mode 100644 doc/README create mode 100644 doc/aiccu.1 create mode 100755 doc/aiccu.conf create mode 100755 doc/aiccu.init create mode 100644 doc/aiccu.init.debian create mode 100755 doc/aiccu.init.freebsd create mode 100644 doc/aiccu.init.gentoo create mode 100755 doc/aiccu.init.rpm create mode 100644 doc/aiccu.sgml create mode 100755 doc/changelog create mode 100644 doc/manpage.refs create mode 100755 doc/setupscript.cmd create mode 100644 freebsd/Makefile create mode 100644 freebsd/files/sixxs-aiccu.in create mode 100644 freebsd/pkg-descr create mode 100644 freebsd/pkg-plist create mode 100644 gentoo/aiccu-ebuild create mode 100644 netbsd/DESCR create mode 100644 netbsd/Makefile create mode 100644 netbsd/PLIST create mode 100644 netbsd/options.mk create mode 100644 openbsd/Makefile create mode 100644 openbsd/README create mode 100644 openbsd/distinfo create mode 120000 openbsd/pkg/DESCR create mode 100644 openbsd/pkg/MESSAGE create mode 100644 openbsd/pkg/PLIST create mode 100644 rpm/aiccu.spec create mode 100755 unix-console/Makefile create mode 100755 unix-console/main.c diff --git a/Makefile b/Makefile new file mode 100644 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 index 0000000..9abb334 --- /dev/null +++ b/common/aiccu.c @@ -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 : ""); + 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 \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 index 0000000..ef65000 --- /dev/null +++ b/common/aiccu.h @@ -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 index 0000000..e29e9ef --- /dev/null +++ b/common/aiccu_aix.c @@ -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 index 0000000..b032e44 --- /dev/null +++ b/common/aiccu_darwin.c @@ -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 index 0000000..95a6554 --- /dev/null +++ b/common/aiccu_freebsd4.c @@ -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 index 0000000..c6d1ea3 --- /dev/null +++ b/common/aiccu_kame.c @@ -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 index 0000000..b86ad67 --- /dev/null +++ b/common/aiccu_linux.c @@ -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 index 0000000..0fe1c96 --- /dev/null +++ b/common/aiccu_openbsd.c @@ -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 index 0000000..3f3c03c --- /dev/null +++ b/common/aiccu_openbsd2.c @@ -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 index 0000000..c1f2cc9 --- /dev/null +++ b/common/aiccu_sunos.c @@ -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 index 0000000..25bbdb2 --- /dev/null +++ b/common/aiccu_test.c @@ -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 index 0000000..f4ed0aa --- /dev/null +++ b/common/ayiya.c @@ -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 index 0000000..0df55ce --- /dev/null +++ b/common/ayiya.h @@ -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 index 0000000..488c145 --- /dev/null +++ b/common/common.c @@ -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 */ +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 of string into 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 index 0000000..575d854 --- /dev/null +++ b/common/common.h @@ -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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_SUNOS) || defined(_AIX) || defined(_DARWIN) +/* Include this as it knows quite a bit about endianess */ +#include +#else +#ifndef _WIN32 +#if defined(_OPENBSD) || defined(_DFBSD) || defined(_FREEBSD) || defined(_NETBSD) +#include +#else +#include +#endif +#endif +#endif + +/* For MD5 routines */ +#define __USE_BSD 1 +#include + +#ifndef _WIN32 + /* Unix Specifics */ + +#ifndef linux + #include +#endif + +#ifdef _DARWIN +#define _BSD_SOCKLEN_T_ +#endif + + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include +#ifdef linux + #include + #include +#else +#ifdef _DFBSD + #include +#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 +/* endif for !_AIX */ +#endif +/* endif for _DARWIN else */ +#endif +/* endif for _DFBSD else */ +#endif +/* endif for linux else */ +#endif + #include + #include + #include + #include + #include + #include + #include + +#if defined(_OPENBSD) || defined(_DARWIN) || defined(_FREEBSD) || defined(_DFBSD) + #include +#endif + + #include + + /* + * 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 + #include + + /* Windows Specifics */ + #include + +/* + * 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 +#include +#include +#include +#endif + +#ifdef AICCU_GNUTLS +#include +#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 index 0000000..160b849 --- /dev/null +++ b/common/hash_md5.c @@ -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 . + * Still in the public domain. + */ + +#include "aiccu.h" +#include "hash_md5.h" + +#include /* for memcpy() */ +#include /* 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<>(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 index 0000000..2bc44a8 --- /dev/null +++ b/common/hash_md5.h @@ -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 . + * 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 index 0000000..57f9488 --- /dev/null +++ b/common/hash_sha1.c @@ -0,0 +1,167 @@ +/* + * sha1.c + * + * Originally witten by Steve Reid + * + * Modified by Aaron D. Gifford + * + * 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 +#include + +#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 index 0000000..5e2edcc --- /dev/null +++ b/common/hash_sha1.h @@ -0,0 +1,71 @@ +/* + * sha.h + * + * Originally taken from the public domain SHA1 implementation + * written by by Steve Reid + * + * Modified by Aaron D. Gifford + * + * 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 index 0000000..0d2a861 --- /dev/null +++ b/common/heartbeat.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) +#include +#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 index 0000000..0e3a4cb --- /dev/null +++ b/common/heartbeat.h @@ -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 index 0000000..39946a9 --- /dev/null +++ b/common/resolver.c @@ -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 +#include +#include +#include + +#include "resolver.h" + +#ifndef _WIN32 +#include +#include +#include +#include +#include + +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 + +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 index 0000000..ba5e520 --- /dev/null +++ b/common/resolver.h @@ -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 index 0000000..e0d70fe --- /dev/null +++ b/common/tic.c @@ -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 +#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 index 0000000..d3c3dfe --- /dev/null +++ b/common/tic.h @@ -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 index 0000000..c5b6323 --- /dev/null +++ b/common/tun.c @@ -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 = π + 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 index 0000000..e19f4e8 --- /dev/null +++ b/common/tun.h @@ -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 index 0000000..6f7d8eb --- /dev/null +++ b/debian/aiccu.config @@ -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 index 0000000..faf63b9 --- /dev/null +++ b/debian/aiccu.manpages @@ -0,0 +1 @@ +doc/aiccu.1 diff --git a/debian/aiccu.postinst b/debian/aiccu.postinst new file mode 100755 index 0000000..eaf35fb --- /dev/null +++ b/debian/aiccu.postinst @@ -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 index 0000000..07fe0c2 --- /dev/null +++ b/debian/aiccu.preinst @@ -0,0 +1,3 @@ +#!/bin/sh -e + +#DEBHELPER# diff --git a/debian/changelog b/debian/changelog new file mode 100755 index 0000000..638c686 --- /dev/null +++ b/debian/changelog @@ -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 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 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 Sun, 6 Aug 2006 13:56:42 +0100 + +aiccu (2006-07-25) stable; urgency=low + * DragonFlyBSD fix + + -- Jeroen Massar 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. and from _aiccu.sixxs.net. + + -- Jeroen Massar 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 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 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 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 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 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 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 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 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 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 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 Sun, 29 Aug 2004 20:55:42 +0100 diff --git a/debian/control b/debian/control new file mode 100755 index 0000000..b428873 --- /dev/null +++ b/debian/control @@ -0,0 +1,18 @@ +Source: aiccu +Section: net +Priority: optional +Maintainer: SixXS Staff +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 index 0000000..0e838db --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/sbin +etc diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..2b70afc --- /dev/null +++ b/debian/docs @@ -0,0 +1,3 @@ +doc/README +doc/LICENSE +doc/HOWTO diff --git a/debian/postrm.debhelper b/debian/postrm.debhelper new file mode 100644 index 0000000..bc035b9 --- /dev/null +++ b/debian/postrm.debhelper @@ -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 index 0000000..876803f --- /dev/null +++ b/debian/rules @@ -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 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 index 0000000..a8fe3cf --- /dev/null +++ b/debian/substvars @@ -0,0 +1 @@ +misc:Depends=debconf (>= 0.5) | debconf-2.0 diff --git a/debian/templates b/debian/templates new file mode 100644 index 0000000..e64b308 --- /dev/null +++ b/debian/templates @@ -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 index 0000000..7b43cc5 --- /dev/null +++ b/doc/COPYRIGHT @@ -0,0 +1,6 @@ +The code for AICCU was written by Jeroen Massar +The copyright for this package is owned by SixXS Staff . +(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 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 index 0000000..06ef53d --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,29 @@ +The SixXS License - http://www.sixxs.net/ + +Copyright (C) SixXS Staff +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 index 0000000..2179e91 --- /dev/null +++ b/doc/README @@ -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 +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 + diff --git a/doc/aiccu.1 b/doc/aiccu.1 new file mode 100644 index 0000000..7eaee06 --- /dev/null +++ b/doc/aiccu.1 @@ -0,0 +1,56 @@ +.\" This manpage has been automatically generated by docbook2man +.\" from a DocBook document. This tool can be found at: +.\" +.\" Please send any bug reports, improvements, comments, patches, +.\" etc. to Steve Cheng . +.TH "AICCU" "1" "18 April 2005" "" "" + +.SH NAME +AICCU \- Automatic IPv6 Connectivity Configuration Utility +.SH SYNOPSIS + +\fBaiccu \fR \fB\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 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 index 0000000..71e8c6c --- /dev/null +++ b/doc/aiccu.conf @@ -0,0 +1,78 @@ +# AICCU Configuration + +# Login information (defaults: none) +#username +#password + +# Protocol and server to use for setting up the tunnel (defaults: none) +#protocol +#server + +# 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 index 0000000..f264bc3 --- /dev/null +++ b/doc/aiccu.init @@ -0,0 +1,68 @@ +#! /bin/sh +# +# /etc/init.d/aiccu: start / stop AICCU +# +# Jeroen Massar + +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 index 0000000..96a3cec --- /dev/null +++ b/doc/aiccu.init.debian @@ -0,0 +1,69 @@ +#! /bin/sh +# +# /etc/init.d/aiccu: start / stop AICCU +# +# Jeroen Massar + +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 index 0000000..10044c5 --- /dev/null +++ b/doc/aiccu.init.freebsd @@ -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 index 0000000..42bc112 --- /dev/null +++ b/doc/aiccu.init.gentoo @@ -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 index 0000000..b80271a --- /dev/null +++ b/doc/aiccu.init.rpm @@ -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 index 0000000..e0e978b --- /dev/null +++ b/doc/aiccu.sgml @@ -0,0 +1,185 @@ + 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 $< > $@ + --> + + + Jeroen"> + Massar"> + + January 09, 2005"> + + 1"> + jeroen@sixxs.net"> + + AICCU"> + + + Debian GNU/Linux"> + GNU"> +]> + + + +
+ &dhemail; +
+ + &dhfirstname; + &dhsurname; + + + 2005 + &dhusername; + + &dhdate; +
+ + &dhucpackage; + + &dhsection; + + + &dhpackage; + + Automatic IPv6 Connectivity Configuration Utility + + + + aiccu + <start|stop|tunnels|test|autotest|license> + config + + + + + DESCRIPTION + + +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. + + + + + OPTIONS + + + + + start + + + Starts aiccu service. + + + + + + stop + + + Stops aiccu service. + + + + + + tunnels + + + Prints a list of currently available tunnels. + + + + + + test + + + Builds the connection and runs a simple selftest allowing a user + to report this back as it should show most obvious problems. + + + + + + autotest + + + Decription here + + + + + + license + + + Shows the license aiccu is released under. + + + + + + config + + + Read the configuration from config file. + + + + + + + + + SEE ALSO + + The AICCU page at sixxs. + + + + + AUTHOR + + AICCU was written by Jeroen Massar with contributions supplied a number of people as mentioned in the Changelog. + + +
+ + diff --git a/doc/changelog b/doc/changelog new file mode 100755 index 0000000..638c686 --- /dev/null +++ b/doc/changelog @@ -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 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 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 Sun, 6 Aug 2006 13:56:42 +0100 + +aiccu (2006-07-25) stable; urgency=low + * DragonFlyBSD fix + + -- Jeroen Massar 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. and from _aiccu.sixxs.net. + + -- Jeroen Massar 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 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 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 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 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 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 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 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 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 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 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 Sun, 29 Aug 2004 20:55:42 +0100 diff --git a/doc/manpage.refs b/doc/manpage.refs new file mode 100644 index 0000000..b4d8bc5 --- /dev/null +++ b/doc/manpage.refs @@ -0,0 +1,3 @@ +{ + '' => '' +} diff --git a/doc/setupscript.cmd b/doc/setupscript.cmd new file mode 100755 index 0000000..7456e57 --- /dev/null +++ b/doc/setupscript.cmd @@ -0,0 +1,4 @@ +echo "The following variables are available to this script as passed by AICCU:" +echo "1: %1%" +echo "2: %2%" +echo "3: %3%" diff --git a/freebsd/Makefile b/freebsd/Makefile new file mode 100644 index 0000000..31f7299 --- /dev/null +++ b/freebsd/Makefile @@ -0,0 +1,45 @@ +# New ports collection makefile for: sixxs-aiccu +# Date created: 2004-09-09 +# Initial FreeBSD port by: Meno Abels +# Comments for this port please to the SixXS staff +# +## $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 + diff --git a/freebsd/files/sixxs-aiccu.in b/freebsd/files/sixxs-aiccu.in new file mode 100644 index 0000000..c2d6e32 --- /dev/null +++ b/freebsd/files/sixxs-aiccu.in @@ -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 index 0000000..f9c4ae2 --- /dev/null +++ b/freebsd/pkg-descr @@ -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 index 0000000..43de74a --- /dev/null +++ b/freebsd/pkg-plist @@ -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 index 0000000..fddb010 --- /dev/null +++ b/gentoo/aiccu-ebuild @@ -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 index 0000000..1c6ea42 --- /dev/null +++ b/netbsd/DESCR @@ -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 index 0000000..3949e0d --- /dev/null +++ b/netbsd/Makefile @@ -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 index 0000000..5a9ed79 --- /dev/null +++ b/netbsd/PLIST @@ -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 index 0000000..6a2e041 --- /dev/null +++ b/netbsd/options.mk @@ -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 index 0000000..4cf32d6 --- /dev/null +++ b/openbsd/Makefile @@ -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 + +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 diff --git a/openbsd/README b/openbsd/README new file mode 100644 index 0000000..be74119 --- /dev/null +++ b/openbsd/README @@ -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 index 0000000..370fb3e --- /dev/null +++ b/openbsd/distinfo @@ -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 index 0000000..c5ac6cb --- /dev/null +++ b/openbsd/pkg/DESCR @@ -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 index 0000000..1be79db --- /dev/null +++ b/openbsd/pkg/MESSAGE @@ -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 index 0000000..b700c3b --- /dev/null +++ b/openbsd/pkg/PLIST @@ -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 index 0000000..417e6ec --- /dev/null +++ b/rpm/aiccu.spec @@ -0,0 +1,87 @@ +############################################################ +# AICCU - Automatic IPv6 Connectivity Client Utility +# by Jeroen Massar +# (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 2005.01.31-4 +- export CFLAGS properly, fix permissions on files for debuginfo + +* Wed Jun 28 2006 Matt Domsch 2005.01.31-3 +- cleanups per Fedora Extras review + +* Sat Apr 22 2006 Matt Domsch 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 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 index 0000000..d5e5c07 --- /dev/null +++ b/unix-console/Makefile @@ -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 index 0000000..8a4d9a9 --- /dev/null +++ b/unix-console/main.c @@ -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. 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) []\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; +} + -- 2.11.4.GIT