[hipl-commit] [release-1.0.5] Rev 3802: Syncronized to trunk revisions 3833..4000

  • From: Miika Komu <miika@xxxxxx>
  • To: hipl-commit@xxxxxxxxxxxxx
  • Date: Fri, 19 Mar 2010 11:53:31 +0200

Committer: Miika Komu <miika@xxxxxx>
Date: 19/03/2010 at 11:53:30
Revision: 3802
Revision-id: miika@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Branch nick: release-1.0.5

Log:
  Syncronized to trunk revisions 3833..4000

Modified:
  D  debian/README.Debian
  D  debian/cron.d.ex
  D  debian/emacsen-install.ex
  D  debian/emacsen-remove.ex
  D  debian/emacsen-startup.ex
  D  debian/manpage.1.ex
  D  debian/manpage.sgml.ex
  D  debian/manpage.xml.ex
  D  debian/menu.ex
  D  debian/watch.ex
  D  firewall/proxy.c.doxyme
  D  firewall/proxydb.c.doxyme
  D  hipd/blind.c.doxyme
  D  hipd/bos.c.doxyme
  D  hipd/close.c.doxyme
  D  hipd/cookie.c.doxyme
  D  hipd/dh.c.doxyme
  D  hipd/hadb.c.doxyme
  D  hipd/hadb_legacy.c.doxyme
  D  hipd/hi3.c.doxyme
  D  hipd/hidb.c.doxyme
  D  hipd/hipd.c.doxyme
  D  hipd/hipqueue.c.doxyme
  D  hipd/hipqueue.h.doxyme
  D  hipd/hiprelay.c.doxyme
  D  hipd/icookie.c
  D  hipd/icookie.c.doxyme
  D  hipd/icookie.h
  D  hipd/icookie.h.doxyme
  D  hipd/init.c.doxyme
  D  hipd/keymat.c.doxyme
  D  hipd/maintenance.c.doxyme
  D  hipd/oppdb.c.doxyme
  D  hipd/oppipdb.c.doxyme
  D  lib/core/getendpointinfo.h.doxyme
  D  lib/core/kerncompat.h.doxyme
  D  lib/core/misc.c
  D  lib/core/misc.c.doxyme
  D  lib/core/misc.h
  D  lib/core/misc.h.doxyme
  D  lib/core/utils.h.doxyme
  D  lib/tool/crypto.c.doxyme
  A  lib/core/filemanip.c
  A  lib/core/filemanip.h
  A  lib/core/hip_udp.c
  A  lib/core/hip_udp.h
  A  lib/core/hit.c
  A  lib/core/hit.h
  A  lib/core/hostid.c
  A  lib/core/hostid.h
  A  lib/core/hostsfiles.c
  A  lib/core/hostsfiles.h
  A  lib/core/keylen.c
  A  lib/core/keylen.h
  A  lib/core/solve.c
  A  lib/core/solve.h
  A  lib/core/straddr.c
  A  lib/core/straddr.h
  A  lib/core/transform.c
  A  lib/core/transform.h
  A  lib/ipsec/pfkeyv2.h
  A  lib/tool/checksum.c
  A  lib/tool/checksum.h
  A  patches/kernel/2.6.20/
  A  patches/kernel/2.6.20/beet-2.6.20.21.patch
  A  patches/kernel/2.6.20/beet-2.6.20.patch
  A  patches/kernel/2.6.20/notes.txt
  M  .bzrignore
  M  Android.mk
  M  Makefile.am
  M  agent/agent.c
  M  agent/connhipd.c
  M  autogen.sh
  M  configure.ac
  M  debian/changelog
  M  debian/control
  M  debian/copyright
  M  debian/dirs
  M  debian/docs
  M  debian/rules
  M  doc/HOWTO.xml
  M  firewall/cache.c
  M  firewall/cache_port.c
  M  firewall/common_hipd_msg.c
  M  firewall/conntrack.c
  M  firewall/conntrack.h
  M  firewall/datapkt.c
  M  firewall/esp_prot_api.c
  M  firewall/esp_prot_config.h
  M  firewall/esp_prot_conntrack.c
  M  firewall/esp_prot_conntrack.h
  M  firewall/esp_prot_fw_msg.c
  M  firewall/firewall.c
  M  firewall/firewall.h
  M  firewall/firewall_control.c
  M  firewall/firewall_control.h
  M  firewall/firewall_defines.h
  M  firewall/firewalldb.c
  M  firewall/lsi.c
  M  firewall/lsi.h
  M  firewall/midauth.c
  M  firewall/midauth.h
  M  firewall/opptcp.c
  M  firewall/pisa.c
  M  firewall/proxy.c
  M  firewall/proxy.h
  M  firewall/proxydb.c
  M  firewall/rule_management.c
  M  firewall/sysopp.c
  M  firewall/user_ipsec_api.c
  M  firewall/user_ipsec_api.h
  M  firewall/user_ipsec_esp.c
  M  firewall/user_ipsec_esp.h
  M  firewall/user_ipsec_fw_msg.c
  M  firewall/user_ipsec_sadb.c
  M  firewall/user_ipsec_sadb.h
  M  hipd/accessor.c
  M  hipd/accessor.h
  M  hipd/blind.c
  M  hipd/bos.c
  M  hipd/bos.h
  M  hipd/cert.h
  M  hipd/close.c
  M  hipd/close.h
  M  hipd/configfilereader.c
  M  hipd/configfilereader.h
  M  hipd/cookie.c
  M  hipd/cookie.h
  M  hipd/dh.c
  M  hipd/dht.c
  M  hipd/dht.h
  M  hipd/dhtqueue.c
  M  hipd/esp_prot_anchordb.c
  M  hipd/esp_prot_hipd_msg.c
  M  hipd/esp_prot_light_update.c
  M  hipd/hadb.c
  M  hipd/hadb.h
  M  hipd/hadb_legacy.c
  M  hipd/hi3.c
  M  hipd/hi3.h
  M  hipd/hidb.c
  M  hipd/hipd.c
  M  hipd/hipd.h
  M  hipd/hiprelay.c
  M  hipd/hiprelay.h
  M  hipd/init.c
  M  hipd/input.c
  M  hipd/input.h
  M  hipd/keymat.c
  M  hipd/keymat.h
  M  hipd/maintenance.c
  M  hipd/nat.c
  M  hipd/nat.h
  M  hipd/netdev.c
  M  hipd/netdev.h
  M  hipd/nsupdate.c
  M  hipd/oppdb.c
  M  hipd/oppdb.h
  M  hipd/oppipdb.c
  M  hipd/output.c
  M  hipd/output.h
  M  hipd/pfkeyapi.c
  M  hipd/pfkeyapi.h
  M  hipd/registration.c
  M  hipd/registration.h
  M  hipd/update.c
  M  hipd/user.c
  M  hipd/user_ipsec_hipd_msg.c
  M  i3/i3_client/http.c
  M  i3/i3_client/i3_client_context.c
  M  i3/i3_client/i3_client_pkt.c
  M  i3/i3_client/i3_client_trigger.c
  M  i3/i3_client/i3server_list.c
  M  i3/i3_client/ping.c
  M  i3/i3_client/ping_thread.c
  M  lib/android/regex.c
  M  lib/conf/hipconf.c
  M  lib/conf/hipconf.h
  M  lib/core/builder.c
  M  lib/core/builder.h
  M  lib/core/certtools.c
  M  lib/core/certtools.h
  M  lib/core/crypto.c
  M  lib/core/crypto.h
  M  lib/core/debug.c
  M  lib/core/debug.h
  M  lib/core/hashtable.c
  M  lib/core/hashtable.h
  M  lib/core/hip_capability.c
  M  lib/core/hip_statistics.c
  M  lib/core/message.c
  M  lib/core/message.h
  M  lib/core/prefix.c
  M  lib/core/prefix.h
  M  lib/core/protodefs.h
  M  lib/core/sqlitedbapi.c
  M  lib/core/sqlitedbapi.h
  M  lib/core/state.h
  M  lib/dht/libhipdht.c
  M  lib/dht/libhipdht.h
  M  lib/dht/libhipdhtxml.c
  M  lib/ipsec/ipsec_strerror.c
  M  lib/ipsec/pfkey.c
  M  lib/ipsec/policy_parse.c
  M  lib/ipsec/policy_parse.y
  M  lib/ipsec/policy_token.l
  M  lib/opphip/wrap.c
  M  lib/opphip/wrap_db.c
  M  lib/performance/performance.c
  M  lib/tool/lutil.c
  M  lib/tool/lutil.h
  M  lib/tool/nlink.c
  M  lib/tool/nlink.h
  M  lib/tool/pk.c
  M  lib/tool/xfrmapi.c
  M  lib/tool/xfrmapi.h
  M  patches/openwrt/package/Makefile
  M  release.version
  M  test/auth_performance.c
  M  test/certteststub.c
  M  test/conntest-client-hip.c
  M  test/conntest-client-native.c
  M  test/conntest-client-opp.c
  M  test/conntest-server.c
  M  test/conntest.c
  M  test/conntest.h
  M  test/cookietest.c
  M  test/dh_performance.c
  M  test/dhtteststub.c
  M  test/keygentest.c
  M  test/performance/perf_measure.sh
  M  test/sqliteteststub.c
  M  tools/hipl_autobuild
  M  tools/pisacert.c

=== modified file '.bzrignore'
--- .bzrignore  2010-03-01 12:17:31 +0000
+++ .bzrignore  2010-03-19 09:53:35 +0000
@@ -1,3 +1,4 @@
+*.ho
 *.la
 *.lo
 ./compile

=== modified file 'Android.mk'
--- Android.mk  2010-02-01 13:24:34 +0000
+++ Android.mk  2010-03-19 09:53:35 +0000
@@ -34,7 +34,6 @@
                     netdev.c \
                     bos.c \
                     nat.c \
-                    icookie.c \
                     init.c \
                     maintenance.c \
                     accessor.c \

=== modified file 'Makefile.am'
--- Makefile.am 2010-03-19 09:32:05 +0000
+++ Makefile.am 2010-03-19 09:53:35 +0000
@@ -1,23 +1,20 @@
 ACLOCAL_AMFLAGS  = -I m4
 
+HIPL_HEADER_LIST = $(wildcard $(addprefix $(srcdir)/,agent/*.h firewall/*.h 
hipd/*.h i3/*/*.h lib/*/*.h test/*.h))
+
 # For "make dist"
 #
 # XX FIX: use dist_doc_DATA for all documentation (if you change this,
 # make sure the check the "make bin" still works)
 #
-EXTRA_DIST =  debian doc hipext hipfwmi patches test/packaging test/configs
-EXTRA_DIST += Android.mk check_header_verbosity.sh tcp verbose-headers.txt
+EXTRA_DIST =  debian doc hipext hipfwmi lib/android patches
 EXTRA_DIST += hipsock jip
-EXTRA_DIST += autogen.sh i3-cfg-PL.xml release.version
-EXTRA_DIST += $(wildcard agent/*.h)
-EXTRA_DIST += $(wildcard i3/*/*.h)
-EXTRA_DIST += $(wildcard lib/android/*.c)
-EXTRA_DIST += $(wildcard lib/*/*.h)
-EXTRA_DIST += $(wildcard hipd/*.h)
-EXTRA_DIST += $(wildcard firewall/*.h)
-EXTRA_DIST += $(wildcard test/*.h)
+EXTRA_DIST += test/packaging test/configs
+EXTRA_DIST += Android.mk autogen.sh check_header_verbosity.sh i3-cfg-PL.xml
+EXTRA_DIST += release.version tcp verbose-headers.txt
 EXTRA_DIST += tools/gen-python-starter.sh
 EXTRA_DIST += m4 # required for CentOS "make bin" target
+EXTRA_DIST += $(HIPL_HEADER_LIST)
 
 # XX TODO: remove these when maemo building uses spec files
 EXTRA_DIST += libinet6/include
@@ -167,7 +164,6 @@
                     hipd/registration.c \
                     hipd/user.c \
                     hipd/hadb.c \
-                    hipd/oppdb.c \
                     hipd/close.c \
                     hipd/configfilereader.c \
                     hipd/input.c \
@@ -177,7 +173,6 @@
                     hipd/netdev.c \
                     hipd/bos.c \
                     hipd/nat.c \
-                    hipd/icookie.c \
                     hipd/init.c \
                     hipd/maintenance.c \
                     hipd/accessor.c \
@@ -212,6 +207,10 @@
 hipd_hipd_SOURCES +=  hipd/pisa.c
 endif
 
+if HIP_OPPORTUNISTIC
+hipd_hipd_SOURCES += hipd/oppdb.c
+endif
+
 firewall_hipfw_SOURCES = firewall/firewall.c \
                          firewall/conntrack.c \
                          firewall/rule_management.c \
@@ -279,8 +278,16 @@
                                  lib/core/debug.c \
                                  lib/core/message.c \
                                  lib/core/esp_prot_common.c \
-                                 lib/core/misc.c \
+                                 lib/core/hostsfiles.c \
+                                 lib/core/filemanip.c \
                                  lib/core/hashchain.c \
+                                 lib/core/hostid.c \
+                                 lib/core/hip_udp.c \
+                                 lib/core/solve.c \
+                                 lib/core/transform.c \
+                                 lib/core/keylen.c \
+                                 lib/core/hit.c \
+                                 lib/core/straddr.c \
                                  lib/core/sqlitedbapi.c \
                                  lib/core/hashchain_store.c \
                                  lib/core/hip_statistics.c \
@@ -293,7 +300,8 @@
 
 lib_tool_libhiptool_la_SOURCES = lib/tool/pk.c \
                                  lib/tool/nlink.c \
-                                 lib/tool/lutil.c
+                                 lib/tool/lutil.c \
+                                 lib/tool/checksum.c
 
 ############################ NOTE ##################################
 #
@@ -323,10 +331,8 @@
 #DISTCLEANFILES = policy_parse.c policy_token.c policy_token.h
 DISTCLEANFILES = lib/ipsec/policy_token.h
 
-if HIP_PFKEY
-BUILT_SOURCES += lib/ipsec/policy_parse.h
-else
 # don't use libipsec, but xfrmapi
+if !HIP_PFKEY
 lib_tool_libhiptool_la_SOURCES += lib/tool/xfrmapi.c
 endif # HIPPFKEY
 
@@ -418,13 +424,15 @@
 
 ### *_LDADD ###
 
-test_conntest_client_opp_LDADD = lib/core/libhipcore.la \
-                                 lib/tool/libhiptool.la
+test_conntest_client_opp_LDADD =
 
 if HIP_OPPORTUNISTIC
 test_conntest_client_opp_LDADD += lib/opphip/libopphip.la
 endif
 
+test_conntest_client_opp_LDADD += lib/core/libhipcore.la \
+                                  lib/tool/libhiptool.la
+
 if HIP_PERFORMANCE
 test_conntest_client_opp_LDADD += lib/performance/libperformance.la
 endif
@@ -506,9 +514,9 @@
 
 
 if HIP_DHT
-test_dhtteststub_LDADD = lib/core/libhipcore.la \
-                             lib/tool/libhiptool.la \
-                             lib/dht/libhipdht.la
+test_dhtteststub_LDADD = lib/dht/libhipdht.la \
+                         lib/core/libhipcore.la \
+                         lib/tool/libhiptool.la
 
 if HIP_PERFORMANCE
 test_dhtteststub_LDADD += lib/performance/libperformance.la
@@ -548,9 +556,9 @@
                             lib/performance/libperformance.la
 endif
 
-tools_hipconf_LDADD = lib/core/libhipcore.la \
-                      lib/tool/libhiptool.la \
-                      lib/conf/libhipconf.la
+tools_hipconf_LDADD = lib/conf/libhipconf.la \
+                      lib/core/libhipcore.la \
+                      lib/tool/libhiptool.la
 
 # required by libhipconf
 if HIP_PERFORMANCE
@@ -708,4 +716,11 @@
        rm -f aclocal.m4 compile config.* configure depcomp install-sh
        rm -f ltmain.sh m4/*.m4 Makefile.in missing py-compile
 
-.PHONY: bin deb doxygen increl olddeb rpm syncrepo
+HIPL_HEADER_OBJS = $(HIPL_HEADER_LIST:.h=.ho)
+CLEANFILES += $(HIPL_HEADER_OBJS)
+
+checkheaders: $(HIPL_HEADER_OBJS)
+%.ho: %.h
+       $(CC) -I$(srcdir) -I$(builddir) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) 
$(CFLAGS) -o $@ $<
+
+.PHONY: bin checkheaders deb doxygen increl olddeb rpm syncrepo

=== modified file 'agent/agent.c'
--- agent/agent.c       2010-03-03 13:16:18 +0000
+++ agent/agent.c       2010-03-19 09:53:35 +0000
@@ -16,10 +16,6 @@
 
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #include <fcntl.h>
 #include <sys/un.h>
 #include <sys/types.h>
@@ -32,6 +28,7 @@
 #include <unistd.h>
 #include <time.h>
 
+#include "config.h"
 #include "agent.h"
 #include "tools.h"
 #include "gui_interface.h"

=== modified file 'agent/connhipd.c'
--- agent/connhipd.c    2010-03-19 09:25:52 +0000
+++ agent/connhipd.c    2010-03-19 09:53:35 +0000
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #include "connhipd.h"
 #include "agent.h"
@@ -30,6 +31,7 @@
 #include "lib/core/icomm.h"
 #include "lib/core/message.h"
 #include "lib/core/builder.h"
+#include "lib/core/straddr.h"
 
 /* This socket is used for communication between agent and HIP daemon. */
 int hip_agent_sock           = 0;

=== modified file 'autogen.sh'
--- autogen.sh  2010-03-19 09:32:05 +0000
+++ autogen.sh  2010-03-19 09:53:35 +0000
@@ -6,18 +6,18 @@
     echo "The following packages are needed for building HIPL software bundle:"
     if test -e /etc/debian_version
         then
-        echo "apt-get install automake autoconf libtool gcc g++ libgtk2.0-dev 
libssl-dev libxml2-dev xmlto doxygen iproute netcat6 iptables-dev libcap-dev 
libsqlite3-dev libuuid1 libnet-ip-perl libnet-dns-perl libsocket6-perl 
libio-socket-inet6-perl"
+        echo "apt-get install automake autoconf libtool gcc libgtk2.0-dev 
libssl-dev libxml2-dev xmlto doxygen iproute netcat6 iptables-dev libcap-dev 
libsqlite3-dev libuuid1 libnet-ip-perl libnet-dns-perl libsocket6-perl 
libio-socket-inet6-perl"
         echo "Optional: apt-get install pax miredo bzr"
     elif test -e /etc/redhat-release
         then
-        echo "yum install gcc gcc-c++ openssl-devel libxml2-devel autoconf 
automake libtool iproute gtk2-devel xmlto doxygen iptables-devel libcap-devel 
sqlite-devel rpm-build perl-Net-IP perl-Net-DNS perl-Socket6 
perl-IO-Socket-INET6"
+        echo "yum install gcc openssl-devel libxml2-devel autoconf automake 
libtool iproute gtk2-devel xmlto doxygen iptables-devel libcap-devel 
sqlite-devel rpm-build perl-Net-IP perl-Net-DNS perl-Socket6 
perl-IO-Socket-INET6"
         echo "Optional: yum install uuid miredo bzr"
         echo "If yum does not find a package, try searching 'rpm.pbone.net' or 
'rpmfind.net' or install from sources"
     else
         echo -n "Unknown linux system:"
         cat /etc/lsb-release
         echo "You should install the following software:"
-        echo "autoreconf, automake, autoconf, libtool, gcc, g++, xmlto, 
doxygen, iproute, netcat6, Socket6, IO::Socket::INET6, Net::IP and Net::DNS 
modules for perl"
+        echo "autoreconf, automake, autoconf, libtool, gcc, xmlto, doxygen, 
iproute, netcat6, Socket6, IO::Socket::INET6, Net::IP and Net::DNS modules for 
perl"
         echo "And the following packages with their development headers:"
         echo "libgtk2.0, openssl, libxml2, iptables, libcap, libsqlite3"
         echo "Optionally you can install also uuid, miredo, bzr"

=== modified file 'configure.ac'
--- configure.ac        2010-03-19 09:32:05 +0000
+++ configure.ac        2010-03-19 09:53:35 +0000
@@ -11,11 +11,14 @@
 AC_CONFIG_MACRO_DIR([m4])
 
 AM_INIT_AUTOMAKE([foreign subdir-objects])
+# AC_PROG_LIBTOOL() could be replaced with LT_INIT(disable-shared) but
+# OpenWRT (Mar 2010) is running too old version of libtool
+# LT_INIT(disable-shared)
+AC_PROG_LIBTOOL(disable-shared)
 
 # Checks for programs.
 AC_PROG_CC
 AC_PROG_INSTALL
-AC_PROG_LIBTOOL(disable-shared)
 AM_PROG_CC_C_O # Required in CentOS
 
 # Check for python for tools directory
@@ -24,11 +27,16 @@
 
 # Checks for libraries.
 AC_CHECK_LIB(crypto, DSA_generate_key,, AC_MSG_ERROR(openssl lib not found))
+# Check for ec crypto in openssl
+AC_CHECK_FUNC(EC_KEY_new,
+              AC_DEFINE(HAVE_EC_CRYPTO)
+              AH_TEMPLATE(HAVE_EC_CRYPTO, [Defined to 1 if ec is enabled.]),)
 # We need the math lib in the registration extension.
 AC_CHECK_LIB(m, pow,, AC_MSG_ERROR(Math lib not found))
 
 # Checks for header files.
-# libintl.h and alloca.h are only used in libhipandroid/regex.c - remove if 
possible
+# libintl.h and alloca.h are only used in libhipandroid/regex.c
+# REMOVE IF POSSIBLE
 AC_CHECK_HEADERS([alloca.h libintl.h])
 
 case "$host" in
@@ -90,197 +98,189 @@
 usagi_libc=23
 AC_SUBST(usagi_libc)
 
+
 AC_ARG_ENABLE(firewall,
-              AC_HELP_STRING([--enable-firewall],
-                             [HIP enabled firewall daemon (default is YES)]),
-             [ac_cv_use_firewall=$enableval],
-             [ac_cv_use_firewall=yes])
+               AS_HELP_STRING([--enable-firewall],
+                              [HIP enabled firewall daemon (default is YES)]),
+               [ac_cv_use_firewall=$enableval],
+               [ac_cv_use_firewall=yes])
 AC_CACHE_CHECK([whether to use firewall],
-               [ac_cv_use_firewall], [ac_cv_use_firewall=yes])
+               [ac_cv_use_firewall],
+               [ac_cv_use_firewall=yes])
 if test x"$ac_cv_use_firewall" = x"yes"; then
-        AC_CHECK_LIB(ipq, ipq_create_handle,, [AC_MSG_ERROR([libipq not 
found])])
-        AC_CHECK_LIB(config, config_setting_index,, [AC_MSG_WARN([libconfig 
not found, using default configuration of esp token extension])])
-        AC_DEFINE(CONFIG_HIP_FIREWALL)
-        AH_TEMPLATE(CONFIG_HIP_FIREWALL, [Defined to 1 if firewall is 
enabled.])
+    AC_CHECK_LIB(ipq, ipq_create_handle,, [AC_MSG_ERROR([libipq not found])])
+    AC_CHECK_LIB(config, config_setting_index,,
+                 [AC_MSG_WARN([libconfig not found, using default config])])
+    AC_DEFINE(CONFIG_HIP_FIREWALL)
+    AH_TEMPLATE(CONFIG_HIP_FIREWALL, [Defined to 1 if firewall is enabled.])
 fi
 AM_CONDITIONAL(HIP_FIREWALL, test x"$ac_cv_use_firewall" = x"yes")
 
 # Try to automatically detect GTK if not disabled or enabled by user
-PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.10.0, ac_cv_use_agent=yes, 
ac_cv_use_agent=no)
+PKG_CHECK_MODULES(GTK,
+                  gtk+-2.0 >= 2.10.0,
+                  ac_cv_use_agent=yes,
+                  ac_cv_use_agent=no)
 if test x"$ac_cv_use_agent" = x"no"; then
-        PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, ac_cv_use_agent=yes, 
ac_cv_use_agent=no)
-        if test x"$ac_cv_use_agent" = x"yes"; then
-                AC_MSG_WARN(You are missing >= GTK 2.10, it is VERY 
recommended)
-        fi
+    PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, ac_cv_use_agent=yes,
+                      ac_cv_use_agent=no)
+    if test x"$ac_cv_use_agent" = x"yes"; then
+        AC_MSG_WARN(You are missing >= GTK 2.10, it is VERY recommended)
+    fi
 fi
 
 AC_ARG_ENABLE(agent,
-              AC_HELP_STRING([--enable-agent],
-              [HIP enable user agent (default is YES)]),
-              [ac_cv_use_agent=$enableval],)
+               AS_HELP_STRING([--enable-agent],
+                              [HIP enable user agent (default is YES)]),
+               [ac_cv_use_agent=$enableval],
+               [ac_cv_use_agent=yes])
 AC_CACHE_CHECK([whether to use agent],
-               [ac_cv_use_agent], [ac_cv_use_agent=yes])
+               [ac_cv_use_agent],
+               [ac_cv_use_agent=yes])
 if test x"$ac_cv_use_agent" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_AGENT)
+    AC_CHECK_LIB(sqlite3, sqlite3_open,,
+                 AC_MSG_ERROR(libsqlite3-dev not found))
+    AC_DEFINE(CONFIG_HIP_AGENT)
     AH_TEMPLATE(CONFIG_HIP_AGENT, [Defined to 1 if agent is enabled.])
-        AC_CHECK_LIB(sqlite3, sqlite3_open,, AC_MSG_ERROR(libsqlite3-dev not 
found))
 fi
 AM_CONDITIONAL(HIP_AGENT, test x"$ac_cv_use_agent" = x"yes")
 
-AC_ARG_ENABLE(cookie,
-             AC_HELP_STRING([--enable-cookie],
-                            [HIP cookie extensions (default is NO)]),
-             [ac_cv_use_cookie=$enableval], [ac_cv_use_cookie=no])
-AC_CACHE_CHECK([whether to use cookie extensions],
-               [ac_cv_use_cookie], [ac_cv_use_cookie=no])
-if test x"$ac_cv_use_cookie" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_COOKIE)
-        AH_TEMPLATE(CONFIG_HIP_COOKIE, [Defined to 1 if cookie is enabled.])
-fi
-
 AC_ARG_ENABLE(pfkey,
-             AC_HELP_STRING([--enable-pfkey],
-                            [HIP pfkey extensions (default is NO)]),
-             [ac_cv_use_pfkey=$enableval], [ac_cv_use_pfkey=no])
+               AS_HELP_STRING([--enable-pfkey],
+                              [HIP pfkey extensions (default is NO)]),
+               [ac_cv_use_pfkey=$enableval],
+               [ac_cv_use_pfkey=no])
 AC_CACHE_CHECK([whether to use pfkey extensions],
-               [ac_cv_use_pfkey], [ac_cv_use_pfkey=no])
+               [ac_cv_use_pfkey],
+               [ac_cv_use_pfkey=no])
 if test x"$ac_cv_use_pfkey" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_PFKEY)
-        AH_TEMPLATE(CONFIG_HIP_PFKEY, [Defined to 1 if pfkey is enabled.])
-        AC_DEFINE(PATH_IPSEC_H, "netinet/ipsec.h")
-        AH_TEMPLATE(PATH_IPSEC_H, [Path to ipsec.h.])
-        AM_PROG_LEX
+    AC_DEFINE(CONFIG_HIP_PFKEY)
+    AH_TEMPLATE(CONFIG_HIP_PFKEY, [Defined to 1 if pfkey is enabled.])
+    AM_PROG_LEX
 fi
 AM_CONDITIONAL(HIP_PFKEY, test x"$ac_cv_use_pfkey" = x"yes")
 
-AC_ARG_ENABLE(cert,
-             AC_HELP_STRING([--enable-cert],
-                            [Samus cert extensions (default is NO)]),
-             [ac_cv_use_cert=$enableval], [ac_cv_use_cert=no])
-AC_CACHE_CHECK([whether to use cert extensions],
-               [ac_cv_use_cert], [ac_cv_use_cert=no])
-if test x"$ac_cv_use_cert" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_CERT)
-        AH_TEMPLATE(CONFIG_HIP_CERT, [Defined to 1 if certificates are 
enabled.])
-fi
-
 AC_ARG_ENABLE(rvs,
-             AC_HELP_STRING([--enable-rvs],
-                            [HIP Rendezvous Extensions (default is YES)]),
-             [ac_cv_use_rvs=$enableval], [ac_cv_use_rvs=yes])
+               AS_HELP_STRING([--enable-rvs],
+                              [HIP Rendezvous Extensions (default is YES)]),
+               [ac_cv_use_rvs=$enableval],
+               [ac_cv_use_rvs=yes])
 AC_CACHE_CHECK([whether to use RVS],
-               [ac_cv_use_rvs], [ac_cv_use_rvs=yes])
+               [ac_cv_use_rvs],
+               [ac_cv_use_rvs=yes])
 if test x"$ac_cv_use_rvs" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_RVS)
-        AH_TEMPLATE(CONFIG_HIP_RVS, [Defined to 1 if RVS is enabled.])
+    AC_DEFINE(CONFIG_HIP_RVS)
+    AH_TEMPLATE(CONFIG_HIP_RVS, [Defined to 1 if RVS is enabled.])
 fi
 
 AC_ARG_ENABLE(hipproxy,
-             AC_HELP_STRING([--enable-hipproxy],
-                            [HIP Proxy (default is YES)]),
-             [ac_cv_use_hipproxy=$enableval], [ac_cv_use_hipproxy=yes])
+               AS_HELP_STRING([--enable-hipproxy],
+                              [HIP Proxy (default is YES)]),
+               [ac_cv_use_hipproxy=$enableval],
+               [ac_cv_use_hipproxy=yes])
 AC_CACHE_CHECK([whether to use HIP proxy],
-               [ac_cv_use_hipproxy], [ac_cv_use_hipproxy=yes])
+               [ac_cv_use_hipproxy],
+               [ac_cv_use_hipproxy=yes])
 if test x"$ac_cv_use_hipproxy" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_HIPPROXY)
-        AH_TEMPLATE(CONFIG_HIP_HIPPROXY, [Defined to 1 if the HIP Proxy is 
enabled.])
+    AC_DEFINE(CONFIG_HIP_HIPPROXY)
+    AH_TEMPLATE(CONFIG_HIP_HIPPROXY, [Defined to 1 if HIP Proxy is enabled.])
 fi
 
 AC_ARG_ENABLE(maemo,
-             AC_HELP_STRING([--enable-maemo],
-                            [Maemo (default is NO)]),
-             [ac_cv_use_maemo=$enableval \
-              ac_cv_use_altsep=yes \
-              ac_cv_use_i3=no], [ac_cv_use_maemo=no])
+               AS_HELP_STRING([--enable-maemo],
+                              [Maemo (default is NO)]),
+               [ac_cv_use_maemo=$enableval],
+               [ac_cv_use_maemo=no])
 AC_CACHE_CHECK([whether to use Maemo],
-               [ac_cv_use_maemo], [ac_cv_use_maemo=no])
+               [ac_cv_use_maemo],
+               [ac_cv_use_maemo=no])
 if test x"$ac_cv_use_maemo" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_MAEMO)
-        AC_SUBST(MAEMO_CFLAGS, "-O2 -g -fgnu89-inline")
-        AC_SUBST(MAEMO_CPPFLAGS, "-I/usr/include/libipq/")
-        AH_TEMPLATE(CONFIG_HIP_MAEMO, [Defined to 1 if maemo build is 
enabled.])
+    AC_DEFINE(CONFIG_HIP_MAEMO)
+    AH_TEMPLATE(CONFIG_HIP_MAEMO, [Defined to 1 if Maemo build is enabled.])
+    AC_SUBST(MAEMO_CFLAGS, "-O2 -g -fgnu89-inline")
+    AC_SUBST(MAEMO_CPPFLAGS, "-I/usr/include/libipq/")
 fi
-AM_CONDITIONAL(HIP_MAEMO, test x"$ac_cv_use_maemo" = x"yes")
 
 AC_ARG_ENABLE(openwrt,
-             AC_HELP_STRING([--enable-openwrt],
-                            [OpenWRT (default is NO)]),
-             [ac_cv_use_openwrt=$enableval \
-              ac_cv_use_altsep=yes], [ac_cv_use_openwrt=no])
+               AS_HELP_STRING([--enable-openwrt],
+                              [OpenWRT (default is NO)]),
+               [ac_cv_use_openwrt=$enableval],
+               [ac_cv_use_openwrt=no])
 AC_CACHE_CHECK([whether to use OpenWRT],
-               [ac_cv_use_openwrt], [ac_cv_use_openwrt=no])
+               [ac_cv_use_openwrt],
+               [ac_cv_use_openwrt=no])
 if test x"$ac_cv_use_openwrt" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_OPENWRT)
-        AC_SUBST(OPENWRT_CFLAGS, "-lc")
-        AH_TEMPLATE(CONFIG_HIP_OPENWRT, [Defined to 1 if openwrt support is 
enabled.])
-        if test x"$TARGET" = x"MIPS_LINUX"; then
-                AC_DEFINE(CONFIG_HIP_OPENWRT_MIPSLINUX)
-                AH_TEMPLATE(CONFIG_HIP_OPENWRT_MIPSLINUX, [Defined to 1 if 
mipslinux is enabled.])
-        fi
+    AC_DEFINE(CONFIG_HIP_OPENWRT)
+    AC_SUBST(OPENWRT_CFLAGS, "-lc")
+    AH_TEMPLATE(CONFIG_HIP_OPENWRT,
+                [Defined to 1 if openwrt support is enabled.])
+    if test x"$TARGET" = x"MIPS_LINUX"; then
+        AC_DEFINE(CONFIG_HIP_OPENWRT_MIPSLINUX)
+        AH_TEMPLATE(CONFIG_HIP_OPENWRT_MIPSLINUX,
+                    [Defined to 1 if mipslinux is enabled.])
+    fi
 fi
-AM_CONDITIONAL(HIP_OPENWRT, test x"$ac_cv_use_openwrt" = x"yes")
 
-# if we already set altsep, then don't check the flags anymore
-if test x"$ac_cv_use_altsep" != x"yes"; then
 AC_ARG_ENABLE(altsep,
-             AC_HELP_STRING([--enable-altsep],
-                            [Alternative privilege separation (default is 
NO)]),
-             [ac_cv_use_altsep=$enableval], [ac_cv_use_altsep=no])
-fi
+               AS_HELP_STRING([--enable-altsep],
+                              [Alternative privilege separation (default is 
NO)]),
+               [ac_cv_use_altsep=$enableval],
+               [ac_cv_use_altsep=no])
 AC_CACHE_CHECK([whether to use Alternative privilege separation],
-               [ac_cv_use_altsep], [ac_cv_use_altsep=no])
+               [ac_cv_use_altsep],
+               [ac_cv_use_altsep=no])
 if test x"$ac_cv_use_altsep" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_ALTSEP)
-        AH_TEMPLATE(CONFIG_HIP_ALTSEP, [Defined to 1 if alternative privilege 
separation is enabled.])
-fi
-AM_CONDITIONAL(HIP_ALTSEP, test x"$ac_cv_use_altsep" = x"yes")
-
-# define this iff we have uuid lib
-AM_CONDITIONAL(HIP_UUIDLIB, test "$ac_has_uuid_lib" = "1")
-
-# if we already set i3, then don't check the flags anymore
-if test x"$ac_cv_use_i3" != x"no"; then
+    AC_DEFINE(CONFIG_HIP_ALTSEP)
+    AH_TEMPLATE(CONFIG_HIP_ALTSEP,
+                [Defined to 1 if alternative privilege separation is enabled.])
+fi
+
+AC_ARG_ENABLE(privsep,
+               AS_HELP_STRING([--enable-privsep],
+                              [Privilege separation (default is YES)]),
+               [ac_cv_use_privsep=$enableval],
+               [ac_cv_use_privsep=yes])
+AC_CACHE_CHECK([whether to use privsep],
+               [ac_cv_use_privsep],
+               [ac_cv_use_privsep=yes])
+if test x"$ac_cv_use_privsep" = x"yes"; then
+    if test x"$ac_cv_use_altsep" != x"yes"; then
+        AC_CHECK_LIB(cap, cap_get_proc,,
+                     AC_MSG_ERROR(libcap-dev developer headers not found))
+    fi
+    AC_DEFINE(CONFIG_HIP_PRIVSEP)
+    AH_TEMPLATE(CONFIG_HIP_PRIVSEP,
+                [Defined to 1 if privilege separation is enabled.])
+fi
+AM_CONDITIONAL(HIP_PRIVSEP, test x"$ac_cv_use_privsep" = x"yes")
+
 AC_ARG_ENABLE(i3,
-              AC_HELP_STRING([--enable-i3],
-              [HIP i3  (default is NO)]),
-              [ac_cv_use_i3=$enableval],)
-fi
+               AS_HELP_STRING([--enable-i3],
+               [HIP i3  (default is NO)]),
+               [ac_cv_use_i3=$enableval],)
 AC_CACHE_CHECK([whether to use i3],
-               [ac_cv_use_i3], [ac_cv_use_i3=no])
+               [ac_cv_use_i3],
+               [ac_cv_use_i3=no])
 if test x"$ac_cv_use_i3" = x"yes"; then
-        AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found))
-        AC_CHECK_LIB(pthread, pthread_create,, AC_MSG_ERROR(libpthread not 
found))
-        AC_DEFINE(CONFIG_HIP_I3)
-        AH_TEMPLATE(CONFIG_HIP_I3, [Defined to 1 if i3 is enabled.])
-
+    AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found))
+    AC_CHECK_LIB(pthread, pthread_create,, AC_MSG_ERROR(libpthread not found))
+    AC_DEFINE(CONFIG_HIP_I3)
+    AH_TEMPLATE(CONFIG_HIP_I3, [Defined to 1 if i3 is enabled.])
 fi
 AM_CONDITIONAL(HIP_I3, test x"$ac_cv_use_i3" = x"yes")
 
-AM_CONDITIONAL(HIP_PRIVSEP, test x"$ac_cv_use_privsep" = x"yes")
-AC_ARG_ENABLE(privsep,
-             AC_HELP_STRING([--enable-privsep],
-                            [Privilege separation (default is YES)]),
-             [ac_cv_use_privsep=$enableval], [ac_cv_use_privsep=yes])
-AC_CACHE_CHECK([whether to use privsep],
-               [ac_cv_use_privsep], [ac_cv_use_privsep=yes])
-if test x"$ac_cv_use_privsep" = x"yes"; then
-        if test x"$ac_cv_use_altsep" != x"yes"; then
-                AC_CHECK_LIB(cap, cap_get_proc,, AC_MSG_ERROR(libcap-dev 
developer headers not found))
-        fi
-        AC_DEFINE(CONFIG_HIP_PRIVSEP)
-        AH_TEMPLATE(CONFIG_HIP_PRIVSEP, [Defined to 1 if privilege separation 
is enabled.])
-fi
-AM_CONDITIONAL(HIP_PRIVSEP, test x"$ac_cv_use_privsep" = x"yes")
-
 AC_ARG_ENABLE(opportunistic,
-             AC_HELP_STRING([--enable-opportunistic],
-                            [HIP opportunistic extensions (default is YES)]),
-             [ac_cv_use_opportunistic=$enableval], 
[ac_cv_use_opportunistic=yes])
+               AS_HELP_STRING([--enable-opportunistic],
+                              [HIP opportunistic mode (default is YES)]),
+               [ac_cv_use_opportunistic=$enableval],
+               [ac_cv_use_opportunistic=yes])
 AC_CACHE_CHECK([whether to use opportunistic],
-               [ac_cv_use_opportunistic], [ac_cv_use_opportunistic=yes])
+               [ac_cv_use_opportunistic],
+               [ac_cv_use_opportunistic=yes])
 if test x"$ac_cv_use_opportunistic" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_OPPORTUNISTIC)
-        AH_TEMPLATE(CONFIG_HIP_OPPORTUNISTIC, [Defined to 1 if oppotunistic 
mode is enabled.])
+    AC_DEFINE(CONFIG_HIP_OPPORTUNISTIC)
+    AH_TEMPLATE(CONFIG_HIP_OPPORTUNISTIC,
+                [Defined to 1 if opportunistic mode is enabled.])
 fi
 AM_CONDITIONAL(HIP_OPPORTUNISTIC, test x"$ac_cv_use_opportunistic" = x"yes")
 
@@ -297,27 +297,31 @@
 AM_CONDITIONAL(SAVAH_IP_OPTION, test x"$ac_cv_use_savaipopt" = x"yes")
 
 AC_ARG_ENABLE(dht,
-             AC_HELP_STRING([--enable-dht],
-                            [DHT support (default is YES)]),
-             [ac_cv_use_dht=$enableval], [ac_cv_use_dht=yes])
+               AS_HELP_STRING([--enable-dht],
+                              [DHT support (default is YES)]),
+               [ac_cv_use_dht=$enableval],
+               [ac_cv_use_dht=yes])
 AC_CACHE_CHECK([whether to use dht],
-               [ac_cv_use_dht], [ac_cv_use_dht=yes])
+               [ac_cv_use_dht],
+               [ac_cv_use_dht=yes])
 if test x"$ac_cv_use_dht" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_DHT)
-        AH_TEMPLATE(CONFIG_HIP_DHT, [Defined to 1 if dht is enabled.])
-        AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found))
+    AC_DEFINE(CONFIG_HIP_DHT)
+    AH_TEMPLATE(CONFIG_HIP_DHT, [Defined to 1 if dht is enabled.])
+    AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found))
 fi
 AM_CONDITIONAL(HIP_DHT, test x"$ac_cv_use_dht" = x"yes")
 
 AC_ARG_ENABLE(blind,
-             AC_HELP_STRING([--enable-blind],
-                            [HIP BLIND extensions (default is NO)]),
-             [ac_cv_use_blind=$enableval], [ac_cv_use_blind=no])
+               AS_HELP_STRING([--enable-blind],
+                              [HIP BLIND extensions (default is NO)]),
+               [ac_cv_use_blind=$enableval],
+               [ac_cv_use_blind=no])
 AC_CACHE_CHECK([whether to use BLIND],
-               [ac_cv_use_blind], [ac_cv_use_blind=no])
+               [ac_cv_use_blind],
+               [ac_cv_use_blind=no])
 if test x"$ac_cv_use_blind" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_BLIND)
-        AH_TEMPLATE(CONFIG_HIP_BLIND, [Defined to 1 if the blind extension is 
enabled.])
+    AC_DEFINE(CONFIG_HIP_BLIND)
+    AH_TEMPLATE(CONFIG_HIP_BLIND, [Defined to 1 if  blind is enabled.])
 fi
 
 AC_ARG_ENABLE(libinet6,
@@ -338,38 +342,25 @@
 AM_CONDITIONAL(HIP_LIBINET6, test x"$ac_cv_use_libinet6" = x"yes")
 
 AC_ARG_ENABLE(profiling,
-             AC_HELP_STRING([--enable-profiling],
-                            [compile in gprof profiling support (default is 
NO)]),
-             [ac_cv_use_profiling=$enableval], [ac_cv_use_profiling=no])
+               AS_HELP_STRING([--enable-profiling],
+                              [gprof profiling support (default is NO)]),
+               [ac_cv_use_profiling=$enableval],
+               [ac_cv_use_profiling=no])
 AC_CACHE_CHECK([whether to use grof support],
-               [ac_cv_use_profiling], [ac_cv_use_profiling=no])
+               [ac_cv_use_profiling],
+               [ac_cv_use_profiling=no])
 if test x"$ac_cv_use_profiling" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_PROFILING)
-        AH_TEMPLATE(CONFIG_HIP_PROFILING, [Defined to 1 if profiling is 
enabled.])
-        AC_SUBST(GPROF_CFLAGS, "-pg")
-fi
-AM_CONDITIONAL(HIP_PROFILING, test x"$ac_cv_use_profiling" = x"yes")
-
-AC_ARG_ENABLE(ecdsa,
-             AC_HELP_STRING([--enable-ecdsa],
-                            [compile in ecdsa support (default is NO)]),
-             [ac_cv_use_ecdsa=$enableval], [ac_cv_use_ecdsa=no])
-AC_CACHE_CHECK([whether to use ecdsa support],
-               [ac_cv_use_ecdsa], [ac_cv_use_ecdsa=no])
-if test x"$ac_cv_use_ecdsa" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_ECDSA)
-        AH_TEMPLATE(CONFIG_HIP_ECDSA, [Defined to 1 if ECDSA support is 
enabled.])
-        AC_SUBST(GPROF_CFLAGS, "-pg")
-fi
-AM_CONDITIONAL(HIP_ECDSA, test x"$ac_cv_use_ecdsa" = x"yes")
+    AC_SUBST(GPROF_CFLAGS, "-pg")
+fi
 
 AC_ARG_ENABLE(debug,
-             AC_HELP_STRING([--enable-debug],
-                            [Enable debug (default is YES)]),
-             [ac_cv_use_debug=$enableval],
-             [ac_cv_use_debug=yes])
+               AS_HELP_STRING([--enable-debug],
+                              [Enable debug (default is YES)]),
+               [ac_cv_use_debug=$enableval],
+               [ac_cv_use_debug=yes])
 AC_CACHE_CHECK([whether to have verbose debug],
-               [ac_cv_use_debug], [ac_cv_use_debug=yes])
+               [ac_cv_use_debug],
+               [ac_cv_use_debug=yes])
 if test x"$ac_cv_use_debug" = x"yes"; then
         AC_DEFINE(HIP_LOGFMT_LONG)
         AH_TEMPLATE(HIP_LOGFMT_LONG, [Defined to 1 if long log format output 
is enabled.])
@@ -378,41 +369,47 @@
 fi
 
 AC_ARG_ENABLE(midauth,
-             AC_HELP_STRING([--enable-midauth],
-                            [Enable middlebox authentification (default is 
NO)]),
-             [ac_cv_use_midauth=$enableval],
-             [ac_cv_use_midauth=no])
+               AS_HELP_STRING([--enable-midauth],
+                              [Enable middlebox authentification (default is 
NO)]),
+               [ac_cv_use_midauth=$enableval],
+               [ac_cv_use_midauth=no])
 AC_CACHE_CHECK([whether to have middlebox authentification],
-               [ac_cv_use_midauth], [ac_cv_use_midauth=no])
+               [ac_cv_use_midauth],
+               [ac_cv_use_midauth=no])
 if test x"$ac_cv_use_midauth" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_MIDAUTH)
-        AH_TEMPLATE(CONFIG_HIP_MIDAUTH, [Defined to 1 if midauth extensions 
are enabled.])
+    AC_DEFINE(CONFIG_HIP_MIDAUTH)
+    AH_TEMPLATE(CONFIG_HIP_MIDAUTH,
+                [Defined to 1 if midauth extension is enabled.])
 fi
 AM_CONDITIONAL(HIP_MIDAUTH, test x"$ac_cv_use_midauth" = x"yes")
 
 AC_ARG_ENABLE(performance,
-             AC_HELP_STRING([--enable-performance],
-                            [Performace measurement support (default is NO)]),
-             [ac_cv_use_performance=$enableval], [ac_cv_use_performance=no])
+               AS_HELP_STRING([--enable-performance],
+                              [Performace measurement support (default is 
NO)]),
+               [ac_cv_use_performance=$enableval],
+               [ac_cv_use_performance=no])
 AC_CACHE_CHECK([whether to use performance measurement],
-               [ac_cv_use_performance], [ac_cv_use_performance=no])
+               [ac_cv_use_performance],
+               [ac_cv_use_performance=no])
 if test x"$ac_cv_use_performance" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_PERFORMANCE)
-        AH_TEMPLATE(CONFIG_HIP_PERFORMANCE, [Defined to 1 if performance 
measurements are enabled.])
+    AC_DEFINE(CONFIG_HIP_PERFORMANCE)
+    AH_TEMPLATE(CONFIG_HIP_PERFORMANCE,
+                [Defined to 1 if performance measurements are enabled.])
 fi
 AM_CONDITIONAL(HIP_PERFORMANCE, test x"$ac_cv_use_performance" = x"yes")
 
 AC_ARG_ENABLE(demo,
-             AC_HELP_STRING([--enable-demo],
-                            [Demo output (default is NO)]),
-             [ac_cv_use_demo=$enableval], [ac_cv_use_demo=no])
+               AS_HELP_STRING([--enable-demo],
+                              [Demo output (default is NO)]),
+               [ac_cv_use_demo=$enableval],
+               [ac_cv_use_demo=no])
 AC_CACHE_CHECK([whether to print output for demos],
-               [ac_cv_use_demo], [ac_cv_use_demo=no])
+               [ac_cv_use_demo],
+               [ac_cv_use_demo=no])
 if test x"$ac_cv_use_demo" = x"yes"; then
-        AC_DEFINE(CONFIG_HIP_DEMO)
-        AH_TEMPLATE(CONFIG_HIP_DEMO, [Defined to 1 if demo is enabled.])
+    AC_DEFINE(CONFIG_HIP_DEMO)
+    AH_TEMPLATE(CONFIG_HIP_DEMO, [Defined to 1 if demo is enabled.])
 fi
-AM_CONDITIONAL(HIP_DEMO, test x"$ac_cv_use_demo" = x"yes")
 
 # Set default AM_CFLAGS for the complete project.
 # -funit-at-a-time can be removed when libinet6 is removed.

=== modified file 'debian/changelog'
--- debian/changelog    2010-02-10 15:28:54 +0000
+++ debian/changelog    2010-03-19 09:53:35 +0000
@@ -1,5 +1,5 @@
 hipl (1.0.4-1) unstable; urgency=low
 
-  * Initial release (Closes: #nnnn)  <nnnn is the bug number of your ITP>
+  * Initial release
 
- -- hummen <rene.hummen@xxxxxxxxxxxxxxxxx>  Wed, 10 Feb 2010 16:27:50 +0100
+ -- Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx>  Wed, 10 Feb 2010 16:27:50 
+0100

=== modified file 'debian/control'
--- debian/control      2010-02-10 16:44:07 +0000
+++ debian/control      2010-03-19 09:53:35 +0000
@@ -1,7 +1,5 @@
 Source: hipl
-Section: networt
-Priority: extra
-Maintainer: hummen <rene.hummen@xxxxxxxxxxxxxxxxx>
+Maintainer: Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx>
 Build-Depends: debhelper (>= 5), autotools-dev
 Standards-Version: 3.7.2
 

=== modified file 'debian/copyright'
--- debian/copyright    2010-02-18 13:55:51 +0000
+++ debian/copyright    2010-03-19 09:53:35 +0000
@@ -1,6 +1,8 @@
-This package was debianized by hummen <rene.hummen@xxxxxxxxxxxxxxxxx> on
+This package was debianized by Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx> on
 Wed, 10 Feb 2010 16:27:50 +0100.
 
+# THIS FILE NEEDS TO BE TAKEN CARE OF
+
 It was downloaded from <url://example.com>
 
 Upstream Author(s):

=== modified file 'debian/dirs'
--- debian/dirs 2010-02-10 16:17:46 +0000
+++ debian/dirs 2010-03-19 09:53:35 +0000
@@ -1,5 +1,1 @@
-usr/bin
-usr/sbin
-usr/lib
-usr/lib64
-usr/share
+# This file specifies the directories which our package will create.

=== modified file 'debian/docs'
--- debian/docs 2010-02-10 15:28:54 +0000
+++ debian/docs 2010-03-19 09:53:35 +0000
@@ -1,1 +1,2 @@
-verbose-headers.txt
+# This file includes the files that will be copied to /usr/share/doc/package
+# when the package is installed

=== modified file 'debian/rules'
--- debian/rules        2010-03-01 17:34:58 +0000
+++ debian/rules        2010-03-19 09:53:35 +0000
@@ -31,7 +31,14 @@
 ifneq "$(wildcard /usr/share/misc/config.guess)" ""
        cp -f /usr/share/misc/config.guess config.guess
 endif
-       ./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man 
--infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" --enable-maemo 
--disable-firewall --disable-privsep --enable-midauth --disable-agent 
--disable-opportunistic --disable-savaipopt --disable-dht
+       ./configure $(CROSS) --prefix=/usr \
+                            --enable-midauth \
+                         --enable-maemo \
+                         --disable-dht \
+                         --disable-agent \
+                         --disable-privsep \
+                         --disable-i3 \
+                         --disable-debug
 
 
 build: build-stamp
@@ -75,26 +82,14 @@
        dh_testdir
        dh_testroot
        dh_installchangelogs
-       dh_installdocs
-       dh_installexamples
-#      dh_install
-#      dh_installmenu
-#      dh_installdebconf
-#      dh_installlogrotate
-#      dh_installemacsen
-#      dh_installpam
-#      dh_installmime
+#      dh_installdocs
 #      dh_python
 #      dh_installinit
-#      dh_installcron
-#      dh_installinfo
-       dh_installman
        dh_link
        dh_strip
        dh_compress
        dh_fixperms
 #      dh_perl
-#      dh_makeshlibs
        dh_installdeb
        dh_shlibdeps
        dh_gencontrol

=== modified file 'doc/HOWTO.xml'
--- doc/HOWTO.xml       2010-03-19 09:09:25 +0000
+++ doc/HOWTO.xml       2010-03-19 09:53:35 +0000
@@ -2109,15 +2109,15 @@
         /etc/hosts:
       </para></listitem>
       <listitem><para>
+        HIT_OF_OOPS oops
+      </para></listitem>
+      <listitem><para>
+        /etc/hosts:
+      </para></listitem>
+      <listitem><para>
         3ffe::2 oops
       </para></listitem>
       <listitem><para>
-        /etc/hip/hosts:
-      </para></listitem>
-      <listitem><para>
-        HIT_OF_OOPS oops
-      </para></listitem>
-      <listitem><para>
         ifconfig eth0 inet6 add 3ffe::1/64
       </para></listitem>
       <listitem><para>
@@ -2257,7 +2257,7 @@
             <itemizedlist>
               <listitem>
               <para>
-                    Add the information in /etc/hip/hosts
+                    Add the information in /etc/hosts
                     <itemizedlist>
                     <listitem><para>OOPS_HIT oops</para></listitem>
                     <listitem><para>OOPS_LSI oops 
<emphasis>Optional!</emphasis> If it's not defined,
@@ -2411,7 +2411,7 @@
     <section id="sec_easy_methods">
       <title>Easy Methods</title>
       <para>
-        1. Run the dnshipproxy to handle mapping from hostnames to HITs from 
hosts files.
+        1. Run the dnshipproxy to map hostnames transparently to HITs from 
hosts files and directory services (DNS, DHT).
         See <xref linkend="sec_dns_proxy" /> for more details.
       </para>
       <para>
@@ -2706,7 +2706,7 @@
   <para>
   The name can be
   something found from <emphasis>/etc/hosts</emphasis>
-  and <emphasis>/etc/hip/hosts</emphasis> or you can use DHT to
+  and <emphasis>/etc/hosts</emphasis> or you can use DHT to
   resolve names to HIT and address. Search can also be done directly
   with HIT by command
   </para>
@@ -3065,9 +3065,10 @@
     </para>
 
     <para>
-       Currently HIP daemon performs name resolution in the following order:
+       Currently HIP daemon performs HIP name resolution in the following 
order:
       <itemizedlist>
         <listitem><para>in /etc/hip/hosts</para></listitem>
+        <listitem><para>in /etc/hosts</para></listitem>
         <listitem><para>in hit-to-ip.infrahip.net zone</para></listitem>
         <listitem><para>in DHT</para></listitem>
       </itemizedlist>
@@ -3345,13 +3346,23 @@
         NATs are commonly referred to as "good" NATs.
       </para>
       <para>
-        The primary objective of the HIP relay extension, on the other hand, is
-        to improve reachability when HIP hosts are separated from each other
-        by a NAT device that performs address dependent mapping. Such NATs are
-        commonly referred to as "bad" NATs. In practice, the HIP relay servers
-        are used to relay the Interactive Connectivity Establishment (ICE)
-        address candidates that are encapsulated in HIP messages.
-      </para>
+        HIPL has two experimental relay modes serving NAT traversal
+        purposes. In the first mode, the HIP control plane relay
+        supports <ulink 
url="http://www.ietf.org/id/draft-keranen-hip-native-nat-traversal-00.txt";>
+        Native NAT Traversal Mode for HIP</ulink> which is only
+        partially supported at the moment. The core idea is that two
+        end-points are behind two different NAT boxes and use a HIP
+        control plane relay to be able to contact each other to
+        exchange their locators. Then the hosts "punch holes" to their
+        NAT boxes to establish direct end-to-end connectivity with
+        each other. The second mode, "full-relay" is supported
+        completely and it relays both HIP and ESP traffic. You should
+        use it carefully and whitelist your /etc/hip/relay_config
+        file. Otherwise you risk your host becoming an open HIP and
+        ESP relay. For additional security measure, you can also use
+        also /etc/hip/firewall_conf to further restrict the allowed
+       clients and servers by their HITs.
+       </para>
       <para>
         The main difference between the rendezvous server and the HIP relay
         server is that the RVS only relays I1 packet of the base exchange while
@@ -5053,7 +5064,7 @@
   </section>
 
   <section id="sys_based_opp_mode">
-    <title>System-based opportunistic mode</title>
+    <title>System-based opportunistic mode (experimental)</title>
         <para>
         The system-based opportunistic mode enables HIP communication
         without the use of the opportunistic library. If the peer does

=== modified file 'firewall/cache.c'
--- firewall/cache.c    2010-03-03 13:16:18 +0000
+++ firewall/cache.c    2010-03-19 09:53:35 +0000
@@ -16,7 +16,9 @@
 
 #include "cache.h"
 #include "lib/core/debug.h"
-#include "lib/core/misc.h"
+#include "lib/core/builder.h"
+#include "lib/core/message.h"
+
 #include "firewall.h"
 #include "user_ipsec_api.h"
 

=== modified file 'firewall/cache_port.c'
--- firewall/cache_port.c       2010-02-18 12:26:08 +0000
+++ firewall/cache_port.c       2010-03-19 09:53:35 +0000
@@ -23,13 +23,102 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <stdio.h>
+
 #include "cache_port.h"
 #include "cache.h"
-#include "lib/core/misc.h"
+
+#include <lib/tool/lutil.h>
+
+
 
 static HIP_HASHTABLE *firewall_port_cache_db = NULL;
 
 /**
+ * Check from the proc file system whether a local port is attached
+ * to an IPv4 or IPv6 address. This is required to determine whether
+ * incoming packets should be diverted to an LSI.
+ *
+ * @param port_dest     the port number of the socket
+ * @param *proto        protocol type
+ * @return              1 if it finds the required socket, 0 otherwise
+ *
+ * @note this is used only from the firewall, so move this there
+ */
+int hip_get_proto_info(in_port_t port_dest, char *proto)
+{
+    FILE *fd       = NULL;
+    char line[500], sub_string_addr_hex[8], path[11 + sizeof(proto)];
+    char *fqdn_str = NULL, *separator = NULL, *sub_string_port_hex = NULL;
+    int lineno     = 0, index_addr_port = 0, exists = 0, result;
+    uint32_t result_addr;
+    struct in_addr addr;
+    List list;
+
+    if (!proto) {
+        return 0;
+    }
+
+    if (!strcmp(proto, "tcp6") || !strcmp(proto, "tcp")) {
+        index_addr_port = 15;
+    } else if (!strcmp(proto, "udp6") || !strcmp(proto, "udp")) {
+        index_addr_port = 10;
+    } else {
+        return 0;
+    }
+
+    strcpy(path, "/proc/net/");
+    strcat(path, proto);
+    fd = fopen(path, "r");
+
+    initlist(&list);
+    while (fd && getwithoutnewline(line, 500, fd) != NULL && !exists) {
+        lineno++;
+
+        destroy(&list);
+        initlist(&list);
+
+        if (lineno == 1 || strlen(line) <= 1) {
+            continue;
+        }
+
+        extractsubstrings(line, &list);
+
+        fqdn_str = getitem(&list, index_addr_port);
+        if (fqdn_str) {
+            separator = strrchr(fqdn_str, ':');
+        }
+
+        if (!separator) {
+            continue;
+        }
+
+        sub_string_port_hex = strtok(separator, ":");
+        sscanf(sub_string_port_hex, "%X", &result);
+        HIP_DEBUG("Result %i\n", result);
+        HIP_DEBUG("port dest %i\n", port_dest);
+        if (result == port_dest) {
+            strncpy(sub_string_addr_hex, fqdn_str, 8);
+            sscanf(sub_string_addr_hex, "%X", &result_addr);
+            addr.s_addr = result_addr;
+            if (IS_LSI32(addr.s_addr)) {
+                exists = 2;
+                break;
+            } else {
+                exists = 1;
+                break;
+            }
+        }
+    }     /* end of while */
+    if (fd) {
+        fclose(fd);
+    }
+    destroy(&list);
+
+    return exists;
+}
+
+/**
  * add a default entry in the firewall port cache.
  *
  * @param key       the hash key (a string consisting of concatenation of the 
port, an underscore and the protocol)

=== modified file 'firewall/common_hipd_msg.c'
--- firewall/common_hipd_msg.c  2010-02-17 17:38:08 +0000
+++ firewall/common_hipd_msg.c  2010-03-19 09:53:35 +0000
@@ -5,6 +5,7 @@
 #include "lib/core/ife.h"
 #include "lib/core/debug.h"
 #include "lib/core/builder.h"
+#include "lib/core/message.h"
 #include "firewall.h"
 
 /**

=== modified file 'firewall/conntrack.c'
--- firewall/conntrack.c        2010-03-19 09:24:10 +0000
+++ firewall/conntrack.c        2010-03-19 09:53:35 +0000
@@ -20,16 +20,15 @@
 
 #include <stdio.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "conntrack.h"
 #include "dlist.h"
 #include "hslist.h"
 #include "esp_prot_conntrack.h"
 #include "datapkt.h"
-#include "lib/core/misc.h"
+
+#include "lib/core/hostid.h"
+#include "lib/core/hip_udp.h"
 #include "hipd/hadb.h"
 #include "lib/tool/pk.h"
 #include "firewalldb.h"
@@ -232,7 +231,7 @@
     HIP_IFEL(data->verify(data->src_hi, common), -EINVAL,
              "Verification of signature failed\n");
 
-    HIP_DEBUG("verfied BEX signature\n");
+    HIP_DEBUG("verified BEX signature\n");
 #endif
 
     _HIP_DEBUG("get_hip_data:\n");
@@ -395,7 +394,7 @@
  * Find esp tuple from espList that matches the argument spi and contains the
  * argument ip address
  *
- * @param dst_addr the destination address to be searched for
+ * @param dst_addr the optional destination address to be searched for
  * @param spi the SPI number to be searched for
  * @return a tuple matching to the address and SPI or NULL if not found
  */
@@ -409,17 +408,18 @@
     while (list) {
         struct esp_tuple *tuple = (struct esp_tuple *) list->data;
         if (spi == tuple->spi) {
-            if (get_esp_address(tuple->dst_addr_list, dst_addr) != NULL) {
+            if (dst_addr && get_esp_address(tuple->dst_addr_list, dst_addr) != 
NULL) {
                 HIP_DEBUG("connection found by esp\n");
                 return tuple->tuple;
+            } else if (!dst_addr) {
+                return tuple->tuple;
             }
         }
         list = list->next;
     }
+
     HIP_DEBUG("get_tuple_by_esp: dst addr %s spi 0x%lx no connection found\n",
-              addr_to_numeric(dst_addr), spi);
-
-    HIP_DEBUG_IN6ADDR("DST", dst_addr);
+              (dst_addr ? addr_to_numeric(dst_addr) : "NULL"), spi);
 
     return NULL;
 }
@@ -854,6 +854,103 @@
 }
 
 /**
+ * Hipfw has an experimental mode which allows it to act as an ESP
+ * Relay to pass e.g.  p2p-unfriendly NAT boxes. The ESP relay mode
+ * assumes that the HIP relay (in hipd) and ESP relay (in hipfw) are
+ * running on the same middlehost in a public network. The responder
+ * has to register to the relay with "hipconf add server full-relay"
+ * which operates as defined in <a
+ * href="http://tools.ietf.org/html/draft-ietf-hip-nat-traversal";> NAT
+ * traversal for HIP</a>. Then the initiator can contact the responder
+ * through the IP address of the HIP/ESP relay. The relay acts as a two-way
+ * NAT and hides the addresses of the initiator and responder. This way,
+ * the the relay supports P2P-unfriendly NAT traversal with the cost of
+ * triangular routing. If the initiator and responder wish to communicate
+ * with each other directly, they can exchange locators either in base exchange
+ * or UPDATE.
+ *
+ * @todo implement the same handling for UPDATE
+ *
+ * @param common the R2 packet
+ * @param ctx packet context
+ *
+ * @return zero on success and non-zero on error
+ */
+static int hipfw_handle_relay_to_r2(const struct hip_common *common,
+                                 const hip_fw_context_t *ctx)
+{
+    struct iphdr *iph = (struct iphdr *) ctx->ipq_packet->payload;
+    struct hip_relay_to *relay_to = NULL; /* same format as relay_from */
+    struct tuple *tuple, *reverse_tuple;
+    int err = 0;
+    uint32_t spi;
+    struct hip_esp_info *esp_info;
+
+    HIP_DEBUG_IN6ADDR("ctx->src", &ctx->src);
+    HIP_DEBUG_IN6ADDR("ctx->dst", &ctx->dst);
+
+    HIP_ASSERT((hip_get_msg_type(common) == HIP_R2));
+
+    HIP_IFEL(!(relay_to = hip_get_param(common, HIP_PARAM_RELAY_TO)), -1,
+            "No relay_to, skip\n");
+
+    HIP_DEBUG_IN6ADDR("relay_to_addr", &relay_to->address);
+
+    HIP_IFEL(!((ctx->ip_version == 4) &&
+               (iph->protocol == IPPROTO_UDP)), 0,
+             "Not a relay packet, ignore\n");
+
+    HIP_IFEL((ipv6_addr_cmp(&ctx->dst, &relay_to->address) == 0), 0,
+             "Reinjected control packet, passing it\n");
+
+    esp_info = hip_get_param(common, HIP_PARAM_ESP_INFO);
+    HIP_IFEL(!esp_info, 0, "No ESP_INFO, pass\n");
+    spi = ntohl(esp_info->new_spi);
+
+    HIP_DEBUG("SPI is 0x%lx\n", spi);
+
+    HIP_IFEL(!(tuple = get_tuple_by_esp(NULL, spi)), 0,
+             "No tuple, skip\n");
+
+    HIP_IFEL(!(reverse_tuple = get_tuple_by_hits(&common->hits, 
&common->hitr)), 0,
+             "No reverse tuple, skip\n");
+
+    HIP_DEBUG("tuple src=%d dst=%d\n", tuple->src_port, tuple->dst_port);
+    HIP_DEBUG_IN6ADDR("tuple src ip", tuple->src_ip);
+    HIP_DEBUG_IN6ADDR("tuple dst ip", tuple->dst_ip);
+    HIP_DEBUG("tuple dir=%d, sport=%d, dport=%d, rel=%d\n", tuple->direction,
+              tuple->src_port, tuple->dst_port, tuple->esp_relay);
+
+    HIP_DEBUG("reverse tuple src=%d dst=%d\n", reverse_tuple->src_port,
+              reverse_tuple->dst_port);
+    HIP_DEBUG_IN6ADDR("reverse tuple src ip", reverse_tuple->src_ip);
+    HIP_DEBUG_IN6ADDR("reverse tuple dst ip", reverse_tuple->dst_ip);
+    HIP_DEBUG("reverse tuple dir=%d, sport=%d, dport=%d, rel=%d\n",
+              reverse_tuple->direction, reverse_tuple->src_port,
+              reverse_tuple->dst_port, reverse_tuple->esp_relay);
+
+    /* Store Responder's IP address and port */
+    tuple->esp_relay = 1;
+    ipv6_addr_copy(&tuple->esp_relay_daddr,
+                   &ctx->src);
+    tuple->esp_relay_dport = tuple->dst_port;
+    HIP_DEBUG("tuple relay port=%d\n",
+              tuple->esp_relay_dport);
+    HIP_DEBUG_IN6ADDR("tuple relay ip",
+                      &tuple->esp_relay_daddr);
+
+    /* Store Initiator's IP address and port */
+    reverse_tuple->esp_relay = 1;
+    ipv6_addr_copy(&reverse_tuple->esp_relay_daddr, &relay_to->address);
+    reverse_tuple->esp_relay_dport = ntohs(relay_to->port);
+    HIP_DEBUG("reverse_tuple relay port=%d\n", reverse_tuple->esp_relay_dport);
+    HIP_DEBUG_IN6ADDR("reverse_tuple relay ip", 
&reverse_tuple->esp_relay_daddr);
+
+out_err:
+    return 0;
+}
+
+/**
  * Process an R1 packet. This function also stores the HI of the Responder
  * to be able to verify signatures also later. The HI is stored only if the
  * signature in R1 was valid.
@@ -867,7 +964,7 @@
 
 // first check signature then store hi
 static int handle_r1(struct hip_common *common, struct tuple *tuple,
-                     int verify_responder)
+                     int verify_responder, const hip_fw_context_t *ctx)
 {
     struct in6_addr hit;
     struct hip_host_id *host_id = NULL;
@@ -934,15 +1031,14 @@
  * is re-established. In such a case, the old ESP tuples are not removed. If an
  * attacker spoofs an I2 or R2, the valid peers are still able to send data.
  *
- * @param ip6_src the source address of the I2 packet
- * @param ip6_dst the destination address of the I2 packet
  * @param common the I2 packet
  * @param tuple the connection tracking tuple corresponding to the I2 packet
+ * @param ctx packet context
  *
  * @return one on success or zero failure
  */
-static int handle_i2(const struct in6_addr *ip6_src, const struct in6_addr 
*ip6_dst,
-                     struct hip_common *common, struct tuple *tuple)
+static int handle_i2(struct hip_common *common, struct tuple *tuple,
+                     const hip_fw_context_t *ctx)
 {
     struct hip_esp_info *spi    = NULL;
     struct tuple *other_dir     = NULL;
@@ -953,6 +1049,7 @@
     // assume correct packet
     int err                     = 1;
     hip_tlv_len_t len           = 0;
+    const struct in6_addr *ip6_src = &ctx->src;
 
     HIP_DEBUG("\n");
 
@@ -990,7 +1087,7 @@
         
HIP_IFEL(tuple->hip_tuple->data->verify(tuple->hip_tuple->data->src_pub_key, 
common),
                  -EINVAL, "Verification of signature failed\n");
 
-        HIP_DEBUG("verfied I2 signature\n");
+        HIP_DEBUG("verified I2 signature\n");
     } else {
         HIP_DEBUG("No HOST_ID found in control message\n");
     }
@@ -1048,104 +1145,26 @@
 }
 
 /**
- * Hipfw has an experimental mode which allows it to act as an ESP Relay to 
pass e.g.
- * p2p-unfriendly NAT boxes. It is assumed that the same host is running
- * also a HIP relay. This function adjusts the connection tracking so that
- * the ESP relaying functionality works. As the end-hosts set up their IPsec
- * SAs based on the IP address of the Relay, it must effectively implement
- * source NATting to forward the ESP packets succesfully. At the moment, the 
relay
- * adjusts connection tracking on based on the R2 packet.
- *
- * @todo implement the same handling for UPDATE
- * @see http://hipl.hiit.fi/bugzilla/show_bug.cgi?id=871
- *
- * @param ip6_src the source address of the R2
- * @param ip6_dst the destination address of the R2
- * @param common the R2 packet
- * @param tuple the connection tracking tuple corresponding to the R2 packet
- * @param esp_tuple the connection tracking ESP tuple corresponding to the R2 
packet
- * @param ctx packet context
- *
- * @return zero on success and non-zero on error
- */
-static int hip_handle_esp_in_udp_relay_r2(const struct in6_addr *ip6_src, 
const struct in6_addr *ip6_dst,
-                                          const struct hip_common *common, 
struct tuple *tuple,
-                                          struct esp_tuple *esp_tuple, 
hip_fw_context_t *ctx)
-{
-    struct hip_relay_to *relay_to;
-    struct iphdr *iph   = (struct iphdr *) ctx->ipq_packet->payload;
-    struct udphdr *udph = (struct udphdr *) ((uint8_t *) iph + iph->ihl * 4);
-    int err             = 0;
-
-    relay_to = hip_get_param(common, HIP_PARAM_RELAY_TO);
-
-    HIP_IFEL(!((ctx->ip_version == 4) &&
-               (iph->protocol == IPPROTO_UDP)), 0,
-             "Not a relay packet, ignore\n");
-
-    if (!tuple->connection->original.src_ip && relay_to) {
-        HIP_IFE(!(tuple->connection->original.src_ip =
-                      malloc(sizeof(struct in6_addr))), 0);
-        HIP_IFE(!(tuple->connection->reply.dst_ip =
-                      malloc(sizeof(struct in6_addr))), 0);
-        HIP_IFE(!(tuple->connection->original.dst_ip =
-                      malloc(sizeof(struct in6_addr))), 0);
-        HIP_IFE(!(tuple->connection->reply.src_ip =
-                      malloc(sizeof(struct in6_addr))), 0);
-
-        memcpy(tuple->connection->original.src_ip,
-               &relay_to->address, sizeof(struct in6_addr));
-        memcpy(tuple->connection->reply.dst_ip,
-               &relay_to->address, sizeof(struct in6_addr));
-        memcpy(tuple->connection->original.dst_ip,
-               ip6_src, sizeof(struct in6_addr));
-        memcpy(tuple->connection->reply.src_ip,
-               ip6_src, sizeof(struct in6_addr));
-
-        HIP_DEBUG("%d %d\n",
-                  htons(relay_to->port),
-                  htons(udph->source));
-        tuple->connection->original.relayed_src_port = relay_to->port;
-        tuple->connection->original.relayed_dst_port = udph->source;
-        tuple->connection->reply.relayed_src_port    = udph->source;
-        tuple->connection->reply.relayed_dst_port    = relay_to->port;
-    } else {     /* Relayed R2: we are the source address */
-        HIP_DEBUG_IN6ADDR("I", 
&tuple->connection->original.hip_tuple->data->src_hit);
-        HIP_DEBUG_IN6ADDR("I", tuple->connection->original.src_ip);
-        HIP_DEBUG_IN6ADDR("R", 
&tuple->connection->original.hip_tuple->data->dst_hit);
-        HIP_DEBUG_IN6ADDR("R", tuple->connection->original.dst_ip);
-
-        esp_tuple->dst_addr_list = update_esp_address(
-            esp_tuple->dst_addr_list, ip6_src, NULL);
-    }
-
-out_err:
-    return 0;
-}
-
-/**
  * Process an R2 packet. If connection already exists, the esp tuple is
  * just added to the existing connection. This occurs, for example, when
  * the connection is re-established. In such a case, the old esp
  * tuples are not removed. If an attacker spoofs an I2 or R2, the
  * valid peers are still able to send data.
  *
- * @param ip6_src the source address of the R2
- * @param ip6_dst the destination address of the R2
  * @param common the R2 packet
  * @param tuple the connection tracking tuple corresponding to the R2 packet
  * @param ctx packet context
  *
  * @return one if packet was processed successfully or zero otherwise
  */
-static int handle_r2(const struct in6_addr *ip6_src, const struct in6_addr 
*ip6_dst,
-                     const struct hip_common *common, struct tuple *tuple,
-                     hip_fw_context_t *ctx)
+static int handle_r2(const struct hip_common *common, struct tuple *tuple,
+                     const hip_fw_context_t *ctx)
 {
     struct hip_esp_info *spi    = NULL;
     struct tuple *other_dir     = NULL;
     SList *other_dir_esps       = NULL;
     struct esp_tuple *esp_tuple = NULL;
+    const struct in6_addr *ip6_src = &ctx->src;
     int err                     = 1;
 
     HIP_IFEL(!(spi = (struct hip_esp_info *) hip_get_param(common, 
HIP_PARAM_ESP_INFO)),
@@ -1192,11 +1211,6 @@
         HIP_DEBUG("ESP tuple already exists!\n");
     }
 
-    if (esp_relay) {
-        HIP_IFEL(hip_handle_esp_in_udp_relay_r2(ip6_src, ip6_dst, common, 
tuple, esp_tuple, ctx),
-                 -1, "ESP-in-UDP relay failed\n");
-    }
-
     /* check if the R2 contains ESP protection anchor and store state */
     HIP_IFEL(esp_prot_conntrack_R2_anchor(common, tuple), -1,
              "failed to track esp protection extension state\n");
@@ -1208,6 +1222,11 @@
      * else
      * other_dir = &tuple->connection->original;*/
 
+    if (esp_relay && ctx->udp_encap_hdr) {
+        HIP_IFEL(hipfw_handle_relay_to_r2(common, ctx),
+                     -1, "handling of relay_to failed\n");
+    }
+
 out_err:
     return err;
 }
@@ -1341,26 +1360,23 @@
  * @todo: SPI parameters did not work earlier and could not be used for 
creating
  * connection state for updates - check if the situation is still the same
  *
- * @param ip6_src the source address of the R2
- * @param ip6_dst the destination address of the R2
  * @param common the R2 packet
  * @param tuple the connection tracking tuple corresponding to the R2 packet
+ * @param ctx packet context
  *
  * @return one if packet was processed successfully or zero otherwise
  */
-static int handle_update(const struct in6_addr *ip6_src,
-                         const struct in6_addr *ip6_dst,
-                         const struct hip_common *common,
-                         struct tuple *tuple)
+static int handle_update(const struct hip_common *common,
+                         struct tuple *tuple,
+                         const hip_fw_context_t *ctx)
 {
     struct hip_seq *seq                = NULL;
     struct hip_esp_info *esp_info      = NULL;
     struct hip_ack *ack                = NULL;
     struct hip_locator *locator        = NULL;
     struct hip_spi *spi                = NULL;
-    struct hip_echo_request *echo_req  = NULL;
-    struct hip_echo_response *echo_res = NULL;
     struct tuple *other_dir_tuple      = NULL;
+    const struct in6_addr *ip6_src = &ctx->src;
     int err                            = 0;
 
     _HIP_DEBUG("handle_update\n");
@@ -1371,10 +1387,6 @@
     ack      = (struct hip_ack *) hip_get_param(common, HIP_PARAM_ACK);
     locator  = (struct hip_locator *) hip_get_param(common, HIP_PARAM_LOCATOR);
     spi      = (struct hip_spi *) hip_get_param(common, HIP_PARAM_ESP_INFO);
-    echo_req = (struct hip_echo_request *) hip_get_param(common,
-                                                         
HIP_PARAM_ECHO_REQUEST);
-    echo_res = (struct hip_echo_response *) hip_get_param(common,
-                                                          
HIP_PARAM_ECHO_RESPONSE);
 
     if (spi) {
         _HIP_DEBUG("handle_update: spi param, spi: 0x%lx \n", ntohl(spi->spi));
@@ -1472,47 +1484,21 @@
 
             _HIP_DEBUG("handle_update: esp_info and locator found\n");
 
-            /* TODO check processing of SPI
-             *
-             * old_spi == 0, new_spi = x means that host is requesting a new SA
-             * old_spi == new_spi means only location update
-             * old_spi != new_spi means esp_tuple update */
-            if (esp_info->old_spi != esp_info->new_spi) {          //update 
existing
-                esp_tuple = find_esp_tuple(other_dir_esps, 
ntohl(esp_info->old_spi));
-
-                if (!esp_tuple) {
-                    _HIP_DEBUG("No suitable esp_tuple found for updating\n");
-
-                    err = 0;
-                    goto out_err;
-                }
-
-                if (!update_esp_tuple(esp_info, locator, seq, esp_tuple)) {
-                    _HIP_DEBUG("failed to update the esp_tuple\n");
-
-                    err = 0;
-                    goto out_err;
-                }
-            }
-
-/* why would we want to do that? We already know this connection and this is a 
U1 */
-#if 0
-        } else {       /* create new esp_tuple */
-            new_esp = esp_tuple_from_esp_info_locator(esp_info, locator, seq,
-                                                      other_dir_tuple);
-
-            if (new_esp == NULL) {
-                //locator must contain address for this spi
-                err = 0;
-                goto out_err;
-            }
-
-            other_dir_tuple->esp_tuples = (SList *) append_to_slist((SList *)
-                                                                    
other_dir_esps, (void *) new_esp);
-
-            insert_esp_tuple(new_esp);
-        }
-#endif
+            esp_tuple = find_esp_tuple(other_dir_esps, 
ntohl(esp_info->old_spi));
+
+            if (!esp_tuple) {
+                _HIP_DEBUG("No suitable esp_tuple found for updating\n");
+
+                err = 0;
+                goto out_err;
+            }
+
+            if (!update_esp_tuple(esp_info, locator, seq, esp_tuple)) {
+                _HIP_DEBUG("failed to update the esp_tuple\n");
+
+                err = 0;
+                goto out_err;
+            }
         } else if (locator && seq) {
             /* Readdress without rekeying */
 
@@ -1660,13 +1646,6 @@
         }
 #endif
 
-        if (echo_req) {
-            _HIP_DEBUG("handle_update: echo found req\n");
-        }
-
-        if (echo_res) {
-            _HIP_DEBUG("handle_update: echo found res\n");
-        }
     }
 
     /* everything should be set now in order to process eventual anchor params 
*/
@@ -1680,17 +1659,17 @@
 /**
  * Process a CLOSE packet
  *
- * @param ip6_src the source address of the CLOSE packet
- * @param ip6_dst the destination address of the CLOSE packet
  * @param common the CLOSE packet
  * @param tuple the connection tracking tuple corresponding to the CLOSE packet
+ * @param ctx packet context
  *
  * @return one if packet was processed successfully or zero otherwise
  */
 static int handle_close(const struct in6_addr *ip6_src,
                         const struct in6_addr *ip6_dst,
                         const struct hip_common *common,
-                        struct tuple *tuple)
+                        struct tuple *tuple,
+                        const hip_fw_context_t *ctx)
 {
     int err = 1;
 
@@ -1724,17 +1703,17 @@
 /**
  * Process CLOSE_ACK and remove the connection.
  *
- * @param ip6_src the source address of the CLOSE_ACK
- * @param ip6_dst the destination address of the CLOSE_ACK
  * @param common the CLOSE_ACK packet
  * @param tuple the connection tracking tuple corresponding to the CLOSE_ACK 
packet
+ * @param ctx packet context
  *
  * @return one if packet was processed successfully or zero otherwise
  */
 int handle_close_ack(const struct in6_addr *ip6_src,
                      const struct in6_addr *ip6_dst,
                      const struct hip_common *common,
-                     struct tuple *tuple)
+                     struct tuple *tuple,
+                     const hip_fw_context_t *ctx)
 {
     int err = 1;
 
@@ -1907,11 +1886,11 @@
             goto out_err;
         }
     } else if (common->type_hdr == HIP_R1) {
-        err = handle_r1(common, tuple, verify_responder);
+        err = handle_r1(common, tuple, verify_responder, ctx);
     } else if (common->type_hdr == HIP_I2) {
-        err = handle_i2(ip6_src, ip6_dst, common, tuple);
+        err = handle_i2(common, tuple, ctx);
     } else if (common->type_hdr == HIP_R2) {
-        err = handle_r2(ip6_src, ip6_dst, common, tuple, ctx);
+        err = handle_r2(common, tuple, ctx);
     } else if (common->type_hdr == HIP_UPDATE) {
         if (!(tuple && tuple->hip_tuple->data->src_hi != NULL)) {
             HIP_DEBUG("signature was NOT verified\n");
@@ -1927,7 +1906,7 @@
         }
 
         if (err) {
-            err = handle_update(ip6_src, ip6_dst, common, tuple);
+            err = handle_update(common, tuple, ctx);
         }
     } else if (common->type_hdr == HIP_NOTIFY) {
         // don't process and let pass through
@@ -1936,12 +1915,12 @@
         // don't process and let pass through
         err = 1;
     } else if (common->type_hdr == HIP_CLOSE) {
-        err = handle_close(ip6_src, ip6_dst, common, tuple);
+        err = handle_close(ip6_src, ip6_dst, common, tuple, ctx);
     } else if (common->type_hdr == HIP_CLOSE_ACK) {
-        err   = handle_close_ack(ip6_src, ip6_dst, common, tuple);
+        err   = handle_close_ack(ip6_src, ip6_dst, common, tuple, ctx);
         tuple = NULL;
     } else if (common->type_hdr == HIP_LUPDATE) {
-        err = esp_prot_conntrack_lupdate(ip6_src, ip6_dst, common, tuple);
+        err = esp_prot_conntrack_lupdate(common, tuple, ctx);
     } else {
         HIP_ERROR("unknown packet type\n");
         err = 0;
@@ -1958,6 +1937,16 @@
         }
     }
 
+    HIP_DEBUG("udp_encap_hdr=%p tuple=%p err=%d\n", ctx->udp_encap_hdr, tuple, 
err);
+
+    /* Cache UDP port numbers (at the moment, used only by the ESP relay) */
+    if (ctx->udp_encap_hdr && (err == 1) && tuple) {
+        tuple->src_port = ntohs(ctx->udp_encap_hdr->source);
+        tuple->dst_port = ntohs(ctx->udp_encap_hdr->dest);
+        HIP_DEBUG("UDP src port %d\n", tuple->src_port);
+        HIP_DEBUG("UDP dst port %d\n", tuple->dst_port);
+    }
+
 out_err:
     return err;
 }
@@ -1969,48 +1958,77 @@
  *
  * @param ctx context for the packet
  * @param tuple the tuple corresponding to the packet
- * @return zero on success or non-zero on failure
+ * @return Zero means that a new relay packet was reinjected successfully
+ *         and the original should be dropped.  -1 means that the reinjected
+ *         packet was processed again and should be just accepted without
+ *         ESP filtering. 1 means that the packet was not related to relayin
+ *         and should just proceed to ESP filtering.
  */
-static int relay_esp_in_udp(const hip_fw_context_t *ctx,
-                            const struct tuple *tuple)
+int hipfw_relay_esp(const hip_fw_context_t *ctx)
 {
-    struct iphdr *iph   = (struct iphdr *) ctx->ipq_packet->payload;
+    struct iphdr *iph = (struct iphdr *) ctx->ipq_packet->payload;
     struct udphdr *udph = (struct udphdr *) ((uint8_t *) iph + iph->ihl * 4);
-    int len             = ctx->ipq_packet->data_len - iph->ihl * 4;
-    int err             = 0;
-
-    if (iph->protocol != IPPROTO_UDP) {
-        HIP_DEBUG("Protocol is not UDP. Not relaying packet.\n");
-        goto out_err;
-    }
-
-    _HIP_DEBUG("%d %d %d %d %d %d %d %d %d\n",
-               htons(tuple->connection->original.relayed_src_port),
-               htons(tuple->connection->original.relayed_dst_port),
-               htons(tuple->connection->reply.relayed_src_port),
-               htons(tuple->connection->reply.relayed_dst_port),
-               htons(tuple->relayed_src_port),
-               htons(tuple->relayed_dst_port),
-               htons(udph->source),
-               htons(udph->dest),
-               tuple->direction);
-
-    HIP_DEBUG_IN6ADDR("original src", tuple->src_ip);
-
-    if (udph->source == tuple->connection->original.relayed_src_port) {
-        udph->dest = tuple->connection->original.relayed_src_port;
-    } else {
-        udph->dest = tuple->connection->original.relayed_dst_port;
-    }
+    int len = ctx->ipq_packet->data_len - iph->ihl * 4;
+    SList *list = (SList *) espList;
+    struct tuple *tuple = NULL;
+    struct hip_esp *esp = ctx->transport_hdr.esp;
+    int err = 0;
+    uint32_t spi;
+
+    HIP_IFEL(!list, -1, "List is empty\n");
+    HIP_IFEL((iph->protocol != IPPROTO_UDP), -1,
+             "Protocol is not UDP. Not relaying packet.\n\n");
+    HIP_IFEL(!esp, -1, "No ESP header\n");
+
+    spi = ntohl(esp->esp_spi);
+    HIP_IFEL(!(tuple = get_tuple_by_esp(NULL, spi)), 0,
+             "No tuple, skip\n");
+
+    HIP_DEBUG("SPI is 0x%lx\n", spi);
+
+    HIP_IFEL((tuple->esp_relay == 0), -1, "Relay is off for this tuple\n");
+
+    HIP_IFEL((ipv6_addr_cmp(&ctx->dst, &tuple->esp_relay_daddr) == 0), 1,
+             "Reinjected relayed packet, passing it\n");
+
+    
HIP_IFEL(hip_fw_hit_is_our(&tuple->connection->original.hip_tuple->data->dst_hit),
+             0, "Destination HIT belongs to us, no relaying\n");
+
+    HIP_DEBUG_IN6ADDR("I", 
&tuple->connection->original.hip_tuple->data->src_hit);
+    HIP_DEBUG_IN6ADDR("I", tuple->connection->original.src_ip);
+    HIP_DEBUG_IN6ADDR("R", 
&tuple->connection->original.hip_tuple->data->dst_hit);
+    HIP_DEBUG_IN6ADDR("R", tuple->connection->original.dst_ip);
+
+    HIP_DEBUG("%d %d %d %d %d %d %d %d %d %d\n",
+              tuple->src_port,
+              tuple->dst_port,
+              tuple->connection->original.src_port,
+              tuple->connection->original.dst_port,
+              tuple->connection->reply.src_port,
+              tuple->connection->reply.dst_port,
+              ntohs(udph->source),
+              ntohs(udph->dest),
+              tuple->direction,
+              tuple->esp_relay_dport);
+
+    HIP_DEBUG_IN6ADDR("src", tuple->src_ip);
+    HIP_DEBUG_IN6ADDR("dst", tuple->dst_ip);
+    HIP_DEBUG_IN6ADDR("esp_relay_addr", &tuple->esp_relay_daddr);
+
     udph->source = htons(HIP_NAT_UDP_PORT);
+    udph->dest = htons(tuple->esp_relay_dport);
     udph->check  = 0;
 
     HIP_DEBUG("Relaying packet\n");
 
-    hip_firewall_send_outgoing_pkt(&ctx->dst, tuple->dst_ip,
-                                   (uint8_t *) iph + iph->ihl * 4, len, 
iph->protocol);
+    err = hip_firewall_send_outgoing_pkt(&ctx->dst,
+                                         &tuple->esp_relay_daddr,
+                                         (uint8_t *) iph + iph->ihl * 4, len,
+                                         iph->protocol);
+
 out_err:
-    return err;
+
+    return -err;
 }
 
 /**
@@ -2060,13 +2078,6 @@
         err = 1;
     }
 
-    if (esp_relay && !hip_fw_hit_is_our(&tuple->hip_tuple->data->dst_hit) &&
-        !hip_fw_hit_is_our(&tuple->hip_tuple->data->src_hit) &&
-        ipv6_addr_cmp(dst_addr, tuple->dst_ip) &&
-        ctx->ip_version == 4) {
-        relay_esp_in_udp(ctx, tuple);
-    }
-
 #ifdef CONFIG_HIP_MIDAUTH
     if (use_midauth && tuple->connection->pisa_state == PISA_STATE_DISALLOW) {
         HIP_DEBUG("PISA: ESP unauthorized -> dropped\n");
@@ -2202,13 +2213,14 @@
  * @param buf the control packet
  * @param ctx context for the control packet
  */
-void conntrack(const struct in6_addr *ip6_src,
+int conntrack(const struct in6_addr *ip6_src,
                const struct in6_addr *ip6_dst,
                struct hip_common *buf,
                hip_fw_context_t *ctx)
 {
     struct hip_data *data = NULL;
     struct tuple *tuple   = NULL;
+    int verdict = 0;
 
     _HIP_DEBUG("\n");
     //g_mutex_lock(connectionTableMutex);
@@ -2223,12 +2235,14 @@
 
     // the accept_mobile parameter is true as packets
     // are not filtered here
-    check_packet(ip6_src, ip6_dst, buf, tuple, 0, 1, ctx);
+    verdict = check_packet(ip6_src, ip6_dst, buf, tuple, 0, 1, ctx);
 
     //g_mutex_unlock(connectionTableMutex);
     _HIP_DEBUG("unlocked mutex\n");
 
     free(data);
+
+    return verdict;
 }
 
 /**

=== modified file 'firewall/conntrack.h'
--- firewall/conntrack.h        2010-02-17 17:38:08 +0000
+++ firewall/conntrack.h        2010-03-19 09:53:35 +0000
@@ -1,6 +1,8 @@
 #ifndef HIP_FIREWALL_CONNTRACK_H
 #define HIP_FIREWALL_CONNTRACK_H
 
+#define _BSD_SOURCE
+
 #include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
@@ -22,7 +24,7 @@
                  struct hip_common *buf,
                  const struct state_option *option,
                  const int accept, hip_fw_context_t *ctx);
-void conntrack(const struct in6_addr *ip6_src,
+int conntrack(const struct in6_addr *ip6_src,
                const struct in6_addr *ip6_dst,
                struct hip_common *buf, hip_fw_context_t *ctx);
 
@@ -30,5 +32,6 @@
 
 struct esp_tuple *find_esp_tuple(const SList *esp_list, const uint32_t spi);
 struct tuple *get_tuple_by_hits(const struct in6_addr *src_hit, const struct 
in6_addr *dst_hit);
+int hipfw_relay_esp(const hip_fw_context_t *ctx);
 
 #endif

=== modified file 'firewall/datapkt.c'
--- firewall/datapkt.c  2010-02-17 17:38:08 +0000
+++ firewall/datapkt.c  2010-03-19 09:53:35 +0000
@@ -27,10 +27,9 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
+#include <netinet/ip.h>
 
+#include "config.h"
 #include "datapkt.h"
 #include "user_ipsec_api.h"
 #include "user_ipsec_esp.h"
@@ -38,6 +37,8 @@
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
 #include "lib/core/builder.h"
+#include "lib/core/hostid.h"
+#include "lib/core/message.h"
 
 static unsigned char *hip_data_packet = NULL;
 
@@ -84,6 +85,49 @@
 }
 
 /**
+ * ask hipd to sign a hiccups data packet
+ *
+ * @param src_hit the source HIT of the data packet
+ * @param dst_hit the destination HIT of the data packet
+ * @param payload the payload protocol value
+ * @param msg     An input/output parameter. For input, contains the
+ *                data packet with payload. For output, contains the
+ *                same but including a signature from hipd.
+ * @return        zero on success or negative on error
+ */
+int hip_get_data_packet_header(const struct in6_addr *src_hit,
+                               const struct in6_addr *dst_hit,
+                               int payload,
+                               struct hip_common *msg)
+{
+    int err = 0;
+
+    hip_build_network_hdr(msg, HIP_DATA, 0, src_hit, dst_hit);
+    msg->payload_proto = payload;
+
+    HIP_DEBUG("PAYLOAD_PROTO in HIP DATA HEADER = %d  ", payload );
+
+    /* @todo: this will assert  */
+    HIP_IFEL(hip_build_user_hdr(msg, 
SO_HIP_BUILD_HOST_ID_SIGNATURE_DATAPACKET, 0),
+             -1, "build hdr failed\n");
+    _HIP_DUMP_MSG(msg);
+
+    /* send msg to hipd and receive corresponding reply */
+    HIP_IFEL(hip_send_recv_daemon_info(msg, 0, 0), -1, "send_recv msg 
failed\n");
+
+    /* check error value */
+    HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n");
+    HIP_DEBUG("Send_recv msg succeed \n");
+
+out_err:
+    msg->type_hdr      = HIP_DATA;
+    /* this was overwritten by some mischief.. So reseting it */
+    msg->payload_proto = payload;
+
+    return err;
+}
+
+/**
  * Process an inbound HICCUPS data packet and remove the HIP header. Caller
  * is responsible to reinjecting the decapsulated message back to the 
networking
  * stack.

=== modified file 'firewall/esp_prot_api.c'
--- firewall/esp_prot_api.c     2010-02-18 13:36:05 +0000
+++ firewall/esp_prot_api.c     2010-03-19 09:53:35 +0000
@@ -18,9 +18,7 @@
 #include <openssl/sha.h>
 #include <math.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
+#include "config.h"
 
 #include "lib/core/common_defines.h"
 #include "lib/core/debug.h"

=== modified file 'firewall/esp_prot_config.h'
--- firewall/esp_prot_config.h  2010-02-17 17:38:08 +0000
+++ firewall/esp_prot_config.h  2010-03-19 09:53:35 +0000
@@ -16,9 +16,7 @@
 #ifndef HIP_FIREWALL_ESP_PROT_CONFIG_H
 #define HIP_FIREWALL_ESP_PROT_CONFIG_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
+#include "config.h"
 
 /* WORKAROUND: some platforms don't support libconfig out of the box */
 #ifdef HAVE_LIBCONFIG

=== modified file 'firewall/esp_prot_conntrack.c'
--- firewall/esp_prot_conntrack.c       2010-02-17 17:38:08 +0000
+++ firewall/esp_prot_conntrack.c       2010-03-19 09:53:35 +0000
@@ -15,12 +15,9 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <netinet/udp.h>
 #include "lib/core/builder.h"
-
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "esp_prot_conntrack.h"
 #include "esp_prot_api.h"
 #include "hslist.h"
@@ -968,16 +965,14 @@
 /**
  * Tracks an HHL-based update message
  *
- * @param   ip6_src the source address of the packet
- * @param   ip6_dst the destination address of the packet
  * @param   common the HIP message
  * @param   tuple state maintained for this connection
+ * @param   ctx packet context
  * @return  0 on success, -1 in case of an error
  */
-int esp_prot_conntrack_lupdate(const struct in6_addr *ip6_src,
-                               const struct in6_addr *ip6_dst,
-                               const struct hip_common *common,
-                               struct tuple *tuple)
+int esp_prot_conntrack_lupdate(const struct hip_common *common,
+                               struct tuple *tuple,
+                               const hip_fw_context_t *ctx)
 {
     struct hip_seq *seq          = NULL;
     struct hip_tlv_common *param = NULL;
@@ -987,6 +982,8 @@
     struct esp_prot_root *esp_roots[MAX_NUM_PARALLEL_HCHAINS];
     struct hip_ack *ack           = NULL;
     struct hip_esp_info *esp_info = NULL;
+    const struct in6_addr *ip6_src = &ctx->src;
+    const struct in6_addr *ip6_dst = &ctx->dst;
     int err                       = 0;
     long i;
 

=== modified file 'firewall/esp_prot_conntrack.h'
--- firewall/esp_prot_conntrack.h       2010-02-17 17:38:08 +0000
+++ firewall/esp_prot_conntrack.h       2010-03-19 09:53:35 +0000
@@ -14,6 +14,8 @@
 #ifndef HIP_FIREWALL_ESP_PROT_CONNTRACK_H
 #define HIP_FIREWALL_ESP_PROT_CONNTRACK_H
 
+#define _BSD_SOURCE
+
 #include "lib/core/protodefs.h"
 #include "conntrack.h"
 
@@ -37,10 +39,9 @@
 int esp_prot_conntrack_update(const hip_common_t *update,
                               const struct tuple *tuple);
 int esp_prot_conntrack_remove_state(struct esp_tuple *esp_tuple);
-int esp_prot_conntrack_lupdate(const struct in6_addr *ip6_src,
-                               const struct in6_addr *ip6_dst,
-                               const struct hip_common *common,
-                               struct tuple *tuple);
+int esp_prot_conntrack_lupdate(const struct hip_common *common,
+                               struct tuple *tuple,
+                               const hip_fw_context_t *ctx);
 int esp_prot_conntrack_verify(const hip_fw_context_t *ctx,
                               struct esp_tuple *esp_tuple);
 

=== modified file 'firewall/esp_prot_fw_msg.c'
--- firewall/esp_prot_fw_msg.c  2010-02-17 17:38:08 +0000
+++ firewall/esp_prot_fw_msg.c  2010-03-19 09:53:35 +0000
@@ -13,10 +13,13 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <netinet/udp.h>
+
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
 #include "lib/core/kerncompat.h"
 #include "lib/core/builder.h"
+#include "lib/core/message.h"
 
 #include "esp_prot_fw_msg.h"
 #include "esp_prot_api.h"

=== modified file 'firewall/firewall.c'
--- firewall/firewall.c 2010-03-03 13:16:18 +0000
+++ firewall/firewall.c 2010-03-19 09:53:35 +0000
@@ -30,10 +30,7 @@
 #include <netinet/in.h> /* in_addr, in6_addr */
 #include <linux/netfilter_ipv4.h> /* NF_IP_LOCAL_IN, etc */
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "firewall.h" /* default include */
 #include "conntrack.h" /* connection tracking */
 #include "proxy.h" /* HIP Proxy */
@@ -43,6 +40,7 @@
 #include "cache_port.h" /* required by opptcp */
 #include "lsi.h" /* LSI */
 #include "lib/core/hip_capability.h" /* Priviledge Separation */
+#include "lib/core/hip_udp.h"
 #include "user_ipsec_api.h" /* Userspace IPsec */
 #include "esp_prot_conntrack.h" /* ESP Tokens */
 #include "esp_prot_api.h" /* ESP Tokens */
@@ -58,6 +56,7 @@
 #include "lib/performance/performance.h" /* Performance Analysis */
 #endif
 #include "helpers.h"
+#include "lib/core/filemanip.h"
 
 /* packet types handled by the firewall */
 #define OTHER_PACKET          0
@@ -1122,16 +1121,28 @@
  */
 static int filter_esp(const hip_fw_context_t *ctx)
 {
-    // drop packet by default
-    int verdict = 0;
+    /* drop packet by default */
+    int verdict = 0, ret;
 
-    if (filter_esp_state(ctx) > 0) {
+    if (esp_relay && ctx->udp_encap_hdr &&
+        ((ret = hipfw_relay_esp(ctx)) <= 0)) {
+         /* 0: drop original and reinject new packet
+            -1: accept reinject packet and avoid filter_esp_state
+            1: just let it pass => proceed to filter */
+        if (ret == 0) {
+            HIP_DEBUG("Drop original and reinject relayed ESP packet\n");
+            verdict = 0;
+        } else if (ret == -1) {
+            HIP_DEBUG("Accept reinjected packet\n");
+            verdict = 1;
+        } else {
+             HIP_ASSERT(0);
+        }
+    } else if (filter_esp_state(ctx) > 0) {
         verdict = 1;
-
         HIP_DEBUG("ESP packet successfully passed filtering\n");
     } else {
         verdict = 0;
-
         HIP_DEBUG("ESP packet NOT authed in ESP filtering\n");
     }
 
@@ -1355,13 +1366,8 @@
     //release rule list
     read_rules_exit(0);
 
-    /* FIXME this actually verifies the packet and should be incorporated in 
the
-     *       resulting verdict!!! */
-    // if packet will be accepted and connection tracking is used
-    // but there is no state for the packet in the conntrack module
-    // yet -> show the packet to conntracking
     if (statefulFiltering && verdict && !conntracked) {
-        conntrack(ip6_src, ip6_dst, buf, ctx);
+        verdict = conntrack(ip6_src, ip6_dst, buf, ctx);
     }
 
     return verdict;
@@ -1456,9 +1462,6 @@
         verdict = ACCEPT;
     }
 
-    HIP_INFO("\n");
-
-out_err:
     /* zero return value means that the packet should be dropped */
     return verdict;
 }

=== modified file 'firewall/firewall.h'
--- firewall/firewall.h 2010-02-17 17:38:08 +0000
+++ firewall/firewall.h 2010-03-19 09:53:35 +0000
@@ -1,10 +1,7 @@
 #ifndef HIP_FIREWALL_FIREWALL_H
 #define HIP_FIREWALL_FIREWALL_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/protodefs.h"
 
 /** globally used variables defined in firewall.c */

=== modified file 'firewall/firewall_control.c'
--- firewall/firewall_control.c 2010-03-03 13:16:18 +0000
+++ firewall/firewall_control.c 2010-03-19 09:53:35 +0000
@@ -15,10 +15,7 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "firewall_control.h"
 #include "firewall.h" /* extern int esp_relay */
 #include "proxy.h"

=== modified file 'firewall/firewall_control.h'
--- firewall/firewall_control.h 2010-02-17 17:38:08 +0000
+++ firewall/firewall_control.h 2010-03-19 09:53:35 +0000
@@ -1,10 +1,7 @@
 #ifndef HIP_FIREWALL_FIREWALL_CONTROL_H
 #define HIP_FIREWALL_FIREWALL_CONTROL_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/builder.h"
 #include "lib/core/protodefs.h"
 

=== modified file 'firewall/firewall_defines.h'
--- firewall/firewall_defines.h 2010-02-17 17:38:08 +0000
+++ firewall/firewall_defines.h 2010-03-19 09:53:35 +0000
@@ -1,14 +1,14 @@
 #ifndef HIP_FIREWALL_FIREWALL_DEFINES_H
 #define HIP_FIREWALL_FIREWALL_DEFINES_H
 
+#define _BSD_SOURCE
+
+#include <net/if.h>
 #include <sys/time.h>
 #include <libipq.h>
 #include <string.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/linkedlist.h"
 #include "lib/core/common_defines.h"
 #include "lib/core/esp_prot_common.h"
@@ -108,8 +108,8 @@
     struct hip_tuple * hip_tuple;
     struct in6_addr *  src_ip;
     struct in6_addr *  dst_ip;
-    in_port_t          relayed_src_port;
-    in_port_t          relayed_dst_port;
+    in_port_t          src_port;
+    in_port_t          dst_port;
     SList *            esp_tuples;
     int                direction;
     struct connection *connection;
@@ -118,6 +118,9 @@
 #ifdef CONFIG_HIP_HIPPROXY
     int                hipproxy;
 #endif
+    int esp_relay;
+    struct in6_addr esp_relay_daddr;
+    in_port_t esp_relay_dport;
 };
 
 struct connection {
@@ -139,63 +142,4 @@
     struct hip_esp *esp_data;
 };
 
-typedef struct pseudo_v6 {
-    struct  in6_addr src;
-    struct in6_addr  dst;
-    uint16_t         length;
-    uint16_t         zero1;
-    uint8_t          zero2;
-    uint8_t          next;
-} pseudo_v6;
-
-static inline uint16_t inchksum(const void *data, uint32_t length)
-{
-    long sum            = 0;
-    const uint16_t *wrd =  (uint16_t *) data;
-    long slen           = (long) length;
-
-    while (slen > 1) {
-        sum  += *wrd++;
-        slen -= 2;
-    }
-
-    if (slen > 0) {
-        sum += *((uint8_t *) wrd);
-    }
-
-    while (sum >> 16) {
-        sum = (sum & 0xffff) + (sum >> 16);
-    }
-
-    return (uint16_t) sum;
-}
-
-static inline uint16_t ipv6_checksum(uint8_t protocol,
-                                     struct in6_addr *src,
-                                     struct in6_addr *dst,
-                                     void *data, uint16_t len)
-{
-    uint32_t chksum = 0;
-    pseudo_v6 pseudo;
-    memset(&pseudo, 0, sizeof(pseudo_v6));
-
-    pseudo.src    = *src;
-    pseudo.dst    = *dst;
-    pseudo.length = htons(len);
-    pseudo.next   = protocol;
-
-    chksum        = inchksum(&pseudo, sizeof(pseudo_v6));
-    chksum       += inchksum(data, len);
-
-    chksum        = (chksum >> 16) + (chksum & 0xffff);
-    chksum       += (chksum >> 16);
-
-    chksum        = (uint16_t) (~chksum);
-    if (chksum == 0) {
-        chksum = 0xffff;
-    }
-
-    return chksum;
-}
-
 #endif /*HIP_FIREWALL_FIREWALL_DEFINES_H*/

=== modified file 'firewall/firewalldb.c'
--- firewall/firewalldb.c       2010-03-19 09:24:10 +0000
+++ firewall/firewalldb.c       2010-03-19 09:53:35 +0000
@@ -4,6 +4,7 @@
  * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
  *
  * @todo THIS DATABASE IS REDUDANT WITH CACHE.C AND CONTAINS ONLY A SUBSET OF 
IT. REWRITE AND TEST!!!
+ * @note this code is linked to the use of hip_firewall_set_bex_data()
  * @todo move the raw socket initialization to somewhere else
  *
  * @brief Write a short summary
@@ -17,6 +18,8 @@
 
 #include <netinet/ip_icmp.h>
 #include <netinet/icmp6.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
 
 #include "firewalldb.h"
 #include "cache.h"
@@ -25,7 +28,9 @@
 #include "lib/core/kerncompat.h"
 #include "lib/core/debug.h"
 #include "lib/core/hashtable.h"
-#include "lib/core/misc.h"
+#include "lib/core/builder.h"
+
+#include "lib/tool/checksum.h"
 
 #define DISABLE_hip_firewall_hldb_dump
 #define DISABLE_firewall_init_raw_sock_esp_v6

=== modified file 'firewall/lsi.c'
--- firewall/lsi.c      2010-03-19 09:24:10 +0000
+++ firewall/lsi.c      2010-03-19 09:53:35 +0000
@@ -25,16 +25,126 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
 #include "cache.h"
 #include "cache_port.h"
 #include "firewall.h"
 #include "firewalldb.h"
 #include "lsi.h"
 #include "lib/core/builder.h"
+#include "lib/core/message.h"
 
 #define BUFSIZE HIP_MAX_PACKET
 
 /**
+ * build a message for hipd to trigger a base exchange
+ *
+ * @param src_hit an optional source HIT for the I1
+ * @param dst_hit a destination HIT for the I1
+ * @param src_lsi an optional source LSI (corresponding to a local HIT)
+ * @param dst_lsi a destination LSI for the I1
+ * @param src_ip  an optional source IP address for the I1
+ * @param dst_ip  a destination IP for the I1
+ * @return        zero on success or negative on error
+
+ * @note Many of the parameters are optional, but at least a
+ * destination LSI, HIT or IP (for opportunistic BEX) must to be
+ * provided
+ */
+int hip_trigger_bex(const struct in6_addr *src_hit,
+                    const struct in6_addr *dst_hit,
+                    struct in6_addr *src_lsi,
+                    struct in6_addr *dst_lsi,
+                    struct in6_addr *src_ip,
+                    struct in6_addr *dst_ip)
+{
+    struct hip_common *msg = NULL;
+    int err                = 0;
+    HIP_IFE(!(msg = hip_msg_alloc()), -1);
+    HIP_IFEL(!dst_hit && !dst_ip, -1,
+             "neither destination hit nor ip provided\n");
+
+    /* NOTE: we need this sequence in order to process the incoming
+     * message correctly */
+
+    /* build the message header */
+    HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_TRIGGER_BEX, 0),
+             -1, "build hdr failed\n");
+
+    /* destination HIT, LSI or IP are obligatory */
+    if (dst_hit) {
+        HIP_DEBUG_HIT("dst_hit: ", dst_hit);
+        HIP_IFEL(hip_build_param_contents(msg, (void *) (dst_hit),
+                                          HIP_PARAM_HIT,
+                                          sizeof(struct in6_addr)),
+                 -1, "build param HIP_PARAM_HIT failed\n");
+    }
+
+    /* source HIT is optional */
+    if (src_hit) {
+        HIP_DEBUG_HIT("src_hit: ", src_hit);
+        HIP_IFEL(hip_build_param_contents(msg, (void *) (src_hit),
+                                          HIP_PARAM_HIT,
+                                          sizeof(struct in6_addr)),
+                 -1, "build param HIP_PARAM_HIT failed\n");
+    }
+
+    /* destination LSI is obligatory */
+    if (dst_lsi) {
+        HIP_DEBUG_IN6ADDR("dst lsi: ", dst_lsi);
+        HIP_IFEL(hip_build_param_contents(msg, (void *) (dst_lsi),
+                                          HIP_PARAM_LSI,
+                                          sizeof(struct in6_addr)),
+                 -1, "build param HIP_PARAM_LSI failed\n");
+    }
+
+    /* source LSI is optional */
+    if (src_lsi) {
+        HIP_DEBUG_IN6ADDR("src lsi: ", src_lsi);
+        HIP_IFEL(hip_build_param_contents(msg, (void *) (src_lsi),
+                                          HIP_PARAM_LSI,
+                                          sizeof(struct in6_addr)),
+                 -1, "build param HIP_PARAM_LSI failed\n");
+    }
+
+    /* if no destination HIT is provided, at least destination IP must
+       exist */
+    if (dst_ip) {
+        HIP_DEBUG_IN6ADDR("dst_ip: ", dst_ip);
+        HIP_IFEL(hip_build_param_contents(msg, (void *) (dst_ip),
+                                          HIP_PARAM_IPV6_ADDR,
+                                          sizeof(struct in6_addr)),
+                 -1, "build param HIP_PARAM_IPV6_ADDR failed\n");
+    }
+
+    /* this again is optional */
+    if (src_ip) {
+        HIP_DEBUG_IN6ADDR("src_ip: ", src_ip);
+        HIP_IFEL(hip_build_param_contents(msg, (void *) (src_ip),
+                                          HIP_PARAM_IPV6_ADDR,
+                                          sizeof(struct in6_addr)),
+                 -1, "build param HIP_PARAM_IPV6_ADDR failed\n");
+    }
+
+    HIP_DUMP_MSG(msg);
+
+    /* send msg to hipd and receive corresponding reply */
+    HIP_IFEL(hip_send_recv_daemon_info(msg, 0, 0), -1, "send_recv msg 
failed\n");
+
+    /* check error value */
+    HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n");
+    HIP_DEBUG("Send_recv msg succeed \n");
+
+out_err:
+    if (msg) {
+        HIP_FREE(msg);
+    }
+    return err;
+}
+
+/**
  * Checks if the packet is a reinjection
  *
  * @param ip_src      pointer to the source address
@@ -59,6 +169,67 @@
 }
 
 /**
+ * get the state of the bex for a pair of ip addresses.
+ *
+ * @param src_ip       input for finding the correct entries
+ * @param dst_ip       input for finding the correct entries
+ * @param src_hit      output data of the correct entry
+ * @param dst_hit      output data of the correct entry
+ * @param src_lsi      output data of the correct entry
+ * @param dst_lsi      output data of the correct entry
+ * @return             the state of the bex if the entry is found
+ *                     otherwise returns -1
+ */
+int hip_get_bex_state_from_LSIs(hip_lsi_t       *src_lsi,
+                                hip_lsi_t       *dst_lsi,
+                                struct in6_addr *src_ip,
+                                struct in6_addr *dst_ip,
+                                struct in6_addr *src_hit,
+                                struct in6_addr *dst_hit)
+{
+    int err = 0, res = -1;
+    struct hip_tlv_common *current_param = NULL;
+    struct hip_common *msg               = NULL;
+    struct hip_hadb_user_info_state *ha;
+
+    HIP_ASSERT(src_ip != NULL && dst_ip != NULL);
+
+    HIP_IFEL(!(msg = hip_msg_alloc()), -1, "malloc failed\n");
+    hip_msg_init(msg);
+    HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_GET_HA_INFO, 0),
+             -1, "Building of daemon header failed\n");
+    HIP_IFEL(hip_send_recv_daemon_info(msg, 0, 0), -1, "send recv daemon 
info\n");
+
+    while ((current_param = hip_get_next_param(msg, current_param)) != NULL) {
+        ha = hip_get_param_contents_direct(current_param);
+
+        if ((ipv4_addr_cmp(dst_lsi, &ha->lsi_our) == 0)  &&
+            (ipv4_addr_cmp(src_lsi, &ha->lsi_peer) == 0)) {
+            *src_hit = ha->hit_peer;
+            *dst_hit = ha->hit_our;
+            *src_ip  = ha->ip_peer;
+            *dst_ip  = ha->ip_our;
+            res      = ha->state;
+            break;
+        } else if ((ipv4_addr_cmp(src_lsi, &ha->lsi_our) == 0)  &&
+                   (ipv4_addr_cmp(dst_lsi, &ha->lsi_peer) == 0)) {
+            *src_hit = ha->hit_our;
+            *dst_hit = ha->hit_peer;
+            *src_ip  = ha->ip_our;
+            *dst_ip  = ha->ip_peer;
+            res      = ha->state;
+            break;
+        }
+    }
+
+out_err:
+    if (msg) {
+        HIP_FREE(msg);
+    }
+    return res;
+}
+
+/**
  * Analyzes first whether the ipv6 packet belongs to an ipv6 socket.
  * If not, it then analyzes whether the packet belongs to an
  * ipv4 socket with an LSI as IP address.

=== modified file 'firewall/lsi.h'
--- firewall/lsi.h      2010-03-03 13:16:18 +0000
+++ firewall/lsi.h      2010-03-19 09:53:35 +0000
@@ -1,11 +1,19 @@
 #ifndef HIP_FIREWALL_LSI_H
 #define HIP_FIREWALL_LSI_H
 
+#define _BSD_SOURCE
+
 #include <libipq.h>
 #include <netinet/ip_icmp.h>
 #include <linux/netfilter_ipv4/ip_queue.h>
 #include "lib/core/protodefs.h"
 
+int hip_trigger_bex(const struct in6_addr *src_hit,
+                    const struct in6_addr *dst_hit,
+                    struct in6_addr *src_lsi,
+                    struct in6_addr *dst_lsi,
+                    struct in6_addr *src_ip,
+                    struct in6_addr *dst_ip);
 int hip_fw_handle_incoming_hit(const ipq_packet_msg_t *m,
                                const struct in6_addr *ip_src,
                                const struct in6_addr *ip_dst,

=== modified file 'firewall/midauth.c'
--- firewall/midauth.c  2010-02-18 12:26:08 +0000
+++ firewall/midauth.c  2010-03-19 09:53:35 +0000
@@ -22,14 +22,13 @@
 
 #include <string.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/ife.h"
 #include "midauth.h"
 #include "pisa.h"
 #include "lib/core/builder.h"
+#include "lib/core/solve.h"
+#include "lib/tool/checksum.h"
 
 #ifdef CONFIG_HIP_PERFORMANCE
 #include "lib/performance/performance.h"

=== modified file 'firewall/midauth.h'
--- firewall/midauth.h  2010-02-18 12:26:08 +0000
+++ firewall/midauth.h  2010-03-19 09:53:35 +0000
@@ -12,10 +12,11 @@
 #ifndef HIP_FIREWALL_MIDAUTH_H
 #define HIP_FIREWALL_MIDAUTH_H
 
+#define _BSD_SOURCE
+
 #include <netinet/ip6.h>
 #include <netinet/ip.h>
 #include <netinet/udp.h>
-#include <libipq.h>
 #include <linux/netfilter.h>
 #include "lib/core/protodefs.h"
 #include "lib/core/debug.h"

=== modified file 'firewall/opptcp.c'
--- firewall/opptcp.c   2010-02-17 17:38:08 +0000
+++ firewall/opptcp.c   2010-03-19 09:53:35 +0000
@@ -36,11 +36,13 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <netinet/tcp.h>
 #include "opptcp.h"
 #include "firewalldb.h"
 #include "lib/core/debug.h"
 #include "lib/core/protodefs.h"
 #include "lib/core/builder.h"
+#include "lib/core/message.h"
 #include "common_hipd_msg.h"
 #include "firewall.h"
 

=== modified file 'firewall/pisa.c'
--- firewall/pisa.c     2010-03-19 09:24:10 +0000
+++ firewall/pisa.c     2010-03-19 09:53:35 +0000
@@ -20,13 +20,11 @@
 #include <time.h>
 #include <stdio.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/ife.h"
+#include "lib/core/crypto.h"
 #include "midauth.h"
-#include "lib/core/misc.h"
+
 #include "pisa.h"
 #include "pisa_cert.h"
 #define PISA_RANDOM_LEN 16

=== modified file 'firewall/proxy.c'
--- firewall/proxy.c    2010-03-19 09:24:10 +0000
+++ firewall/proxy.c    2010-03-19 09:53:35 +0000
@@ -1,5 +1,11 @@
-/*
- * HIP proxy
+/** @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * HIP client-side proxy. Documented in detail in Weiwei's thesis when
+ * it's finished.
+ *
+ * @author Weiwei Hu
  */
 
 /* required for s6_addr32 */
@@ -10,6 +16,7 @@
 #include "firewall/proxy.h"
 #include "firewall/proxyconndb.h"
 #include "firewall/firewall_defines.h"
+#include "lib/tool/checksum.h"
 
 int hip_proxy_raw_sock_tcp_v4          = 0;
 int hip_proxy_raw_sock_tcp_v6          = 0;
@@ -21,12 +28,13 @@
 const char hip_proxy_supported_proto[] = { IPPROTO_TCP,
         IPPROTO_ICMP, IPPROTO_UDP };
 
-/**
- *
- *
- * @return zero on success, non-zero on error
- */
+
 #ifdef CONFIG_HIP_HIPPROXY
+/**
+ * Request the status of the HIP proxy
+ *
+ * @return zero on success, non-zero on error
+ */
 int request_hipproxy_status(void)
 {
     struct hip_common *msg = NULL;
@@ -56,6 +64,14 @@
 
 #endif /* CONFIG_HIP_HIPPROXY */
 
+
+/**
+ * Request the peer HIT from HIP Daemon
+ *
+ * @param peer_ip the address of the peer host (HIP Server)
+ * @param local_hit the HIT of the local HIP proxy
+ * @return zero on success, non-zero on error
+ */
 int hip_proxy_request_peer_hit_from_hipd(const struct in6_addr *peer_ip,
                                          const struct in6_addr *local_hit)
 {
@@ -94,6 +110,12 @@
     return err;
 }
 
+/**
+ * Get the local HIT from HIP Daemon
+ *
+ * @param hit the pointer used to store the local HIT
+ * @return zero on success, non-zero on error
+ */
 int hip_get_local_hit_wrapper(hip_hit_t *hit)
 {
     int err                = 0;
@@ -117,6 +139,12 @@
     return err;
 }
 
+/**
+ * Set the peer HIT into the HIP Proxy Database
+ *
+ * @param msg the received message for the HIT request of the peer host
+ * @return zero on success, non-zero on error
+ */
 int hip_fw_proxy_set_peer_hit(hip_common_t *msg)
 {
     int fallback               = 1, reject = 0, addr_found = 0, err = 0;
@@ -210,6 +238,12 @@
     return err;
 }
 
+/**
+ * Initialize the IPv6 socket for TCP connection
+ *
+ * @param hip_raw_sock_v6 the socket pointer used for TCP connection in IPv6
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_tcp_v6(int *hip_raw_sock_v6)
 {
     int on = 1, off = 0, err = 0;
@@ -232,6 +266,12 @@
     return err;
 }
 
+/**
+ * Initialize the IPv4 socket for TCP connection
+ *
+ * @param hip_raw_sock_v4 the socket pointer used for TCP connection in IPv4
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_tcp_v4(int *hip_raw_sock_v4)
 {
     int on  = 1, err = 0;
@@ -258,6 +298,12 @@
     return err;
 }
 
+/**
+ * Initialize the IPv6 socket for UDP connection
+ *
+ * @param hip_raw_sock_v6 the socket pointer used for UDP connection in IPv6
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_udp_v6(int *hip_raw_sock_v6)
 {
     int on = 1, off = 0, err = 0;
@@ -280,6 +326,12 @@
     return err;
 }
 
+/**
+ * Initialize the IPv4 socket for UDP connection
+ *
+ * @param hip_raw_sock_v4 the socket pointer used for UDP connection in IPv4
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_udp_v4(int *hip_raw_sock_v4)
 {
     int on  = 1, err = 0;
@@ -306,6 +358,12 @@
     return err;
 }
 
+/**
+ * Initialize the ICMPv6 socket
+ *
+ * @param hip_raw_sock_v6 the socket pointer used for ICMPv6 connection
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_icmp_v6(int *hip_raw_sock_v6)
 {
     int on = 1, off = 0, err = 0;
@@ -329,6 +387,12 @@
     return err;
 }
 
+/**
+ * Initialize the ICMP socket
+ *
+ * @param hip_raw_sock_v4 the socket pointer used for ICMP
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_icmp_v4(int *hip_raw_sock_v4)
 {
     int on  = 1, err = 0;
@@ -356,6 +420,12 @@
     return err;
 }
 
+/**
+ * Initialize the ICMPV6 socket for Inbound connection
+ *
+ * @param hip_raw_sock_v6 the socket pointer used for ICMPv6 connection in IPv6
+ * @return zero on success, non-zero on error
+ */
 int hip_init_proxy_raw_sock_icmp_inbound(int *hip_raw_sock_v6)
 {
     int on = 1, off = 0, err = 0;
@@ -378,6 +448,11 @@
     return err;
 }
 
+/**
+ * Initialize all the sockets
+ *
+ * @return zero on success, non-zero on error
+ */
 int hip_proxy_init_raw_sockets(void)
 {
     hip_init_proxy_raw_sock_tcp_v6(&hip_proxy_raw_sock_tcp_v6);
@@ -391,8 +466,11 @@
     return 0;
 }
 
-// TODO add hip_proxy_UNinit_raw_sockets()
-
+/**
+ * Initialize the HIP proxy
+ *
+ * @return zero on success, non-zero on error
+ */
 int init_proxy(void)
 {
     int err = 0;
@@ -404,6 +482,11 @@
     return err;
 }
 
+/**
+ * Uninitialize the HIP proxy
+ *
+ * @return zero on success, non-zero on error
+ */
 int uninit_proxy(void)
 {
     int err = 0;
@@ -415,6 +498,15 @@
     return err;
 }
 
+/**
+ * Send packets to the HIP server
+ * @param local_addr the HIT of the sender
+ * @param peer_addr the HIT of the receiver
+ * @param msg the payload of the packet
+ * @param len the len of the packet
+ * @param protocol the protocol of the connection
+ * @return zero on success, non-zero on error
+ */
 static int hip_proxy_send_pkt(struct in6_addr *local_addr,
                               struct in6_addr *peer_addr,
                               uint8_t *msg, uint16_t len, int protocol)
@@ -620,6 +712,14 @@
     return err;
 }
 
+/**
+ * Send packets to the legacy client
+ * @param local_addr the address of the sender
+ * @param peer_addr the address of the receiver
+ * @param buff the payload of the packet
+ * @param len the len of the packet
+ * @return zero on success, non-zero on error
+ */
 static int hip_proxy_send_to_client_pkt(struct in6_addr *local_addr,
                                         struct in6_addr *peer_addr,
                                         uint8_t *buff, uint16_t len)
@@ -915,6 +1015,12 @@
     return err;
 }
 
+/**
+ * Handle the proxy inbound traffic
+ * @param m the ipq packet captured by the hipfw
+ * @param src_addr the source address
+ * @return zero on success, non-zero on error
+ */
 int handle_proxy_inbound_traffic(const ipq_packet_msg_t *m,
                                  const struct in6_addr *src_addr)
 {
@@ -975,15 +1081,23 @@
     return err;
 }
 
-static int hip_proxy_send_inbound_icmp_pkt(struct in6_addr *src_addr, struct 
in6_addr *dst_addr, uint8_t *buff, uint16_t len)
+/**
+ * Send the inbound ICMP packet
+ * @param src_addr the ipq packet captured by the hipfw
+ * @param dst_addr the source address inside the packet
+ * @param buff the payload of the packet
+ * @param len the length of the payload
+ * @return zero on success, non-zero on error
+ */
+static int hip_proxy_send_inbound_icmp_pkt(struct in6_addr *src_addr, struct 
in6_addr *dst_addr, const unsigned char *buff, uint16_t len)
 {
     struct sockaddr_in6 src6, dst6;
-    struct ip *ip;
-    struct ip6_hdr *ip6;
-    struct icmphdr *icmp;
+    struct ip *ip = NULL;
+    struct ip6_hdr *ip6 = NULL;
+    struct icmphdr *icmp = NULL;
     int sa_size, sent;
     int on = 1;
-    uint8_t *msg;
+    unsigned char *msg = NULL;
 
     ip = (struct ip *) buff;
 
@@ -1000,7 +1114,7 @@
     HIP_DEBUG_IN6ADDR("dst6", &dst6.sin6_addr);
 
     sa_size = sizeof(struct sockaddr_in6);
-    msg = (uint8_t *) HIP_MALLOC((len + sizeof(struct ip6_hdr) - ip->ip_hl), 
0);
+    msg = HIP_MALLOC((len + sizeof(struct ip6_hdr) - ip->ip_hl), 0);
     memset(msg, 0, (len + sizeof(struct ip6_hdr) - ip->ip_hl));
 
     ip6 = (struct ip6_hdr *) msg;
@@ -1032,6 +1146,15 @@
     return 0;
 }
 
+/**
+ * Handle the proxy outbound traffic
+ * @param m the ipq packet captured by the hipfw
+ * @param src_addr the source address
+ * @param dst_addr the destination address
+ * @param hdr_size the header size
+ * @param ip_version the IP protocol version
+ * @return zero on success, non-zero on error
+ */
 int handle_proxy_outbound_traffic(const ipq_packet_msg_t *m,
                                   const struct in6_addr *src_addr,
                                   const struct in6_addr *dst_addr,
@@ -1141,7 +1264,7 @@
             }
 
             if ((protocol == IPPROTO_ICMP) || (protocol == IPPROTO_ICMPV6)) {
-                hip_proxy_send_inbound_icmp_pkt(proxy_hit, &entry->hit_peer, 
(uint8_t *) m->payload, m->data_len);
+                hip_proxy_send_inbound_icmp_pkt(proxy_hit, &entry->hit_peer, 
m->payload, m->data_len);
                 /* drop packet */
                 err = 0;
             } else {

=== modified file 'firewall/proxy.h'
--- firewall/proxy.h    2010-02-17 17:38:08 +0000
+++ firewall/proxy.h    2010-03-19 09:53:35 +0000
@@ -1,10 +1,13 @@
 #ifndef HIP_FIREWALL_PROXY_H
 #define HIP_FIREWALL_PROXY_H
 
+#define _BSD_SOURCE
+
 #include <libipq.h>
 
 #include "firewall.h"
 #include "proxydb.h"
+#include "config.h"
 
 #ifdef CONFIG_HIP_HIPPROXY
 int request_hipproxy_status(void);

=== modified file 'firewall/proxydb.c'
--- firewall/proxydb.c  2010-02-17 17:38:08 +0000
+++ firewall/proxydb.c  2010-03-19 09:53:35 +0000
@@ -1,3 +1,13 @@
+/** @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * HIP client-side proxy databases. Documented in detail in Weiwei's
+ * thesis when it's finished.
+ *
+ * @author Weiwei Hu
+ */
+
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
@@ -5,6 +15,13 @@
 
 HIP_HASHTABLE *hip_proxy_db = NULL;
 
+
+/**
+ * Create a hash of the given entry for the hash table
+ *
+ * @param p the connection entry
+ * @return a hash calculated based on the given entry
+ */
 unsigned long hip_proxy_db_hash(const hip_proxy_t *p)
 {
     hip_hit_t hitpair[2];
@@ -28,6 +45,14 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_HASH_FN(hip_proxy_db, const hip_proxy_t)
 
+
+/**
+ * Compare two hash keys
+ *
+ * @param ha1 first hash key
+ * @param ha2 second hash key
+ * @return zero if keys match or one otherwise
+ */
 int hip_proxy_db_cmp(const hip_proxy_t *ha1, const hip_proxy_t *ha2)
 {
     if (ha1 == NULL
@@ -45,12 +70,19 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_COMP_FN(hip_proxy_db, const hip_proxy_t)
 
+
+/**
+ * Initialize the proxy database
+ */
 void hip_init_proxy_db(void)
 {
     hip_proxy_db = hip_ht_init(LHASH_HASH_FN(hip_proxy_db),
                                LHASH_COMP_FN(hip_proxy_db));
 }
 
+/**
+ * Unitialize the proxy database
+ */
 void hip_uninit_proxy_db()
 {
     int i = 0;
@@ -64,6 +96,13 @@
     }
 }
 
+/**
+ * Add an entry to the database of the HIP proxy
+ *
+ * @param addr_client Addess of the legacy client
+ * @param addr_peer Address of the HIP server
+ * @return zero on success or non-zero on failure
+ */
 int hip_proxy_add_entry(const struct in6_addr *addr_client,
                         const struct in6_addr *addr_peer)
 {
@@ -89,6 +128,13 @@
     return err;
 }
 
+/**
+ * Find the proxy database entry corresponding to addresses
+ *
+ * @param addr the address of the legacy client
+ * @param addr2 the address of the HIP server
+ * @return the database entry if found or otherwise NULL
+ */
 hip_proxy_t *hip_proxy_find_by_addr(const struct in6_addr *addr,
                                     const struct in6_addr *addr2)
 {
@@ -99,6 +145,19 @@
     return hip_ht_find(hip_proxy_db, &p);
 }
 
+/**
+ * Update the entry state in the proxy database
+ * Only for known clients
+ *
+ * @param entry the HIP database entry
+ * @param client_addr the IP address of the client
+ * @param peer_addr the IP address of the server
+ * @param proxy_addr the IP address of the HIP proxy
+ * @param proxy_hit the HIT of the HIP proxy
+ * @param peer_hit the HIT of the server
+ * @param state the state of the connection entry
+ * @return zero on success or non-zero on failure
+ */
 int hip_proxy_update_entry_state(hip_proxy_t *entry,
                                  struct in6_addr *client_addr,
                                  struct in6_addr *peer_addr,
@@ -132,6 +191,13 @@
  * The firewall receives R1 and does not know which client to serve.
  * Updates all clients.
  *
+ * @param client_addr the IP address of the client
+ * @param peer_addr the IP address of the server
+ * @param proxy_addr the IP address of the HIP proxy
+ * @param proxy_hit the HIT of the HIP proxy
+ * @param peer_hit the HIT of the server
+ * @param state the state of the connection entry
+ *
  */
 int hip_proxy_update_state_no_client(struct in6_addr *client_addr,
                                      struct in6_addr *peer_addr,
@@ -159,6 +225,19 @@
     return 0;
 }
 
+
+/**
+ * Update the entry state in the proxy database for all cases.
+ * Available for the known clients and unknow clients
+ *
+ * @param client_addr the IP address of the client
+ * @param peer_addr the IP address of the server
+ * @param proxy_addr the IP address of the HIP proxy
+ * @param proxy_hit the HIT of the HIP proxy
+ * @param peer_hit the HIT of the server
+ * @param state the state of the connection entry
+ *
+ */
 int hip_proxy_update_state(struct in6_addr *client_addr,
                            struct in6_addr *peer_addr,
                            struct in6_addr *proxy_addr,

=== modified file 'firewall/rule_management.c'
--- firewall/rule_management.c  2010-03-03 13:16:18 +0000
+++ firewall/rule_management.c  2010-03-19 09:53:35 +0000
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <net/if.h>
 #include <netinet/in.h>
 //#include <linux/types.h>
 #include <linux/netfilter.h>
@@ -28,15 +29,13 @@
 #include <limits.h>
 #include <linux/netfilter_ipv6.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "rule_management.h"
 #include "helpers.h"
 #include "lib/core/builder.h"
 #include "lib/core/crypto.h"
 #include "lib/core/debug.h"
+#include "lib/core/hostid.h"
 
 /* string tokens for rule parsing */
 #define SRC_HIT_STR "-src_hit"
@@ -900,12 +899,12 @@
     } else {
         option->boolean = 1;
     }
-    if (strlen(token) > IFNAMSIZ) {
+    if (strlen(token) > IF_NAMESIZE) {
         HIP_DEBUG("parse_if error: invalid length interface name\n");
         free(option);
         return NULL;
     } else {
-        option->value = (char *) malloc(IFNAMSIZ);
+        option->value = (char *) malloc(IF_NAMESIZE);
         strcpy(option->value, token);
     }
     return option;

=== modified file 'firewall/sysopp.c'
--- firewall/sysopp.c   2010-02-17 17:38:08 +0000
+++ firewall/sysopp.c   2010-03-19 09:53:35 +0000
@@ -1,14 +1,19 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
 #include "lib/core/debug.h"
 #include "lib/core/builder.h"
-
+#include "lib/core/message.h"
 #include "sysopp.h"
 #include "firewall.h"
 #include "firewalldb.h"
 #include "lsi.h"
 #include "common_hipd_msg.h"
+#include "lib/core/hostid.h"
 
 void hip_fw_flush_system_based_opp_chains(void)
 {

=== modified file 'firewall/user_ipsec_api.c'
--- firewall/user_ipsec_api.c   2010-02-17 17:38:08 +0000
+++ firewall/user_ipsec_api.c   2010-03-19 09:53:35 +0000
@@ -21,6 +21,7 @@
 #include "esp_prot_api.h"
 #include "lib/core/ife.h"
 #include "lib/core/debug.h"
+#include "lsi.h"
 
 #define USER_IPSEC_INACTIVE 0
 #define USER_IPSEC_ACTIVE 1

=== modified file 'firewall/user_ipsec_api.h'
--- firewall/user_ipsec_api.h   2010-02-17 17:38:08 +0000
+++ firewall/user_ipsec_api.h   2010-03-19 09:53:35 +0000
@@ -14,9 +14,11 @@
 #ifndef HIP_FIREWALL_USER_IPSEC_API_H
 #define HIP_FIREWALL_USER_IPSEC_API_H
 
+#define _BSD_SOURCE
+
 #include <netinet/udp.h>
 #include <openssl/evp.h>
-#include "lib/core/misc.h"
+
 #include "firewall_defines.h"
 
 /* this is the maximum buffer-size needed for an userspace ipsec esp packet

=== modified file 'firewall/user_ipsec_esp.c'
--- firewall/user_ipsec_esp.c   2010-03-03 13:16:18 +0000
+++ firewall/user_ipsec_esp.c   2010-03-19 09:53:35 +0000
@@ -32,49 +32,13 @@
 #include "user_ipsec_esp.h"
 #include "esp_prot_api.h"
 #include "lib/core/prefix.h"
-#include "lib/core/misc.h"
+
+#include "lib/tool/checksum.h"
+#include "lib/core/keylen.h"
 
 /* for some reason the ICV for ESP authentication is truncated to 12 bytes */
 #define ICV_LENGTH 12
 
-/** calculates the IP-checksum
- *
- * @param ip_hdr    packet to be checksumed
- * @param ip_hl     header length field inside the header
- * @return          the IP checksum
- */
-static uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl)
-{
-    uint16_t checksum = 0;
-    unsigned long sum = 0;
-    int count         = ip_hl * 4;
-    unsigned short *p = (unsigned short *) ip_hdr;
-
-    /*
-     * this checksum algorithm can be found
-     * in RFC 1071 section 4.1
-     */
-
-    /* one's complement sum 16-bit words of data */
-    while (count > 1) {
-        sum   += *p++;
-        count -= 2;
-    }
-    /* add left-over byte, if any */
-    if (count > 0) {
-        sum += (unsigned char) *p;
-    }
-
-    /*  Fold 32-bit sum to 16 bits */
-    while (sum >> 16) {
-        sum = (sum & 0xffff) + (sum >> 16);
-    }
-    /* take the one's complement of the sum */
-    checksum = (uint16_t) (~sum);
-
-    return checksum;
-}
-
 /** adds an UDP-header to the packet
  *
  * @param udp_hdr       location of the udp_hdr

=== modified file 'firewall/user_ipsec_esp.h'
--- firewall/user_ipsec_esp.h   2010-02-17 17:38:08 +0000
+++ firewall/user_ipsec_esp.h   2010-03-19 09:53:35 +0000
@@ -24,6 +24,8 @@
 #ifndef HIP_FIREWALL_USER_IPSEC_ESP_H
 #define HIP_FIREWALL_USER_IPSEC_ESP_H
 
+#define _BSD_SOURCE
+
 #include "user_ipsec_sadb.h"
 #include "firewall_defines.h"
 

=== modified file 'firewall/user_ipsec_fw_msg.c'
--- firewall/user_ipsec_fw_msg.c        2010-02-17 17:38:08 +0000
+++ firewall/user_ipsec_fw_msg.c        2010-03-19 09:53:35 +0000
@@ -16,6 +16,7 @@
 #include "esp_prot_fw_msg.h"
 #include "firewall.h"
 #include "lib/core/builder.h"
+#include "lib/core/message.h"
 
 #define DEFAULT_LIFETIME 0 /* place holder as timeout not implemented yet */
 

=== modified file 'firewall/user_ipsec_sadb.c'
--- firewall/user_ipsec_sadb.c  2010-02-17 17:38:08 +0000
+++ firewall/user_ipsec_sadb.c  2010-03-19 09:53:35 +0000
@@ -17,12 +17,16 @@
 
 #include <pthread.h>
 #include <openssl/sha.h>
+#include <string.h>
 
 #include "user_ipsec_sadb.h"
 #include "esp_prot_api.h"
 #include "firewall.h"
 #include "lib/core/ife.h"
-#include "lib/core/misc.h"
+#include "lib/core/keylen.h"
+#include "lib/core/debug.h"
+#include "lib/core/state.h"
+#include "lib/core/builder.h"
 
 /* hash functions used for calculating the entries' hashes
  *

=== modified file 'firewall/user_ipsec_sadb.h'
--- firewall/user_ipsec_sadb.h  2010-02-17 17:38:08 +0000
+++ firewall/user_ipsec_sadb.h  2010-03-19 09:53:35 +0000
@@ -20,6 +20,7 @@
 #ifndef ANDROID_CHANGES
 #include <openssl/blowfish.h>   /* bf_key */
 #endif
+#include <sys/time.h>
 #include <pthread.h>
 #include <inttypes.h>
 #include "lib/core/hashchain.h"

=== modified file 'hipd/accessor.c'
--- hipd/accessor.c     2010-03-19 09:20:44 +0000
+++ hipd/accessor.c     2010-03-19 09:53:35 +0000
@@ -12,18 +12,16 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "accessor.h"
-
+#include "hipd.h"
 
 unsigned int hipd_state         = HIPD_STATE_CLOSED;
 #ifdef CONFIG_HIP_OPPORTUNISTIC
 unsigned int opportunistic_mode = 1;
+extern int hip_use_opptcp;
 #endif // CONFIG_HIP_OPPORTUNISTIC
-
+extern int hip_use_hi3;
 
 /**
  * Set global daemon state.
@@ -67,7 +65,7 @@
  *
  * @return non-zero, if agent is alive.
  */
-int hip_agent_is_alive()
+int hip_agent_is_alive(void)
 {
 #ifdef CONFIG_HIP_AGENT
     return hip_agent_status;
@@ -78,6 +76,67 @@
 
 #ifdef CONFIG_HIP_OPPORTUNISTIC
 /**
+ * Set opportunistic TCP status on or off
+ *
+ * @param msg a message with message type as SO_HIP_SET_OPPTCP_ON
+ *            or SO_HIP_SET_OPPTCP_OFF
+ */
+void hip_set_opportunistic_tcp_status(struct hip_common *msg)
+{
+    struct sockaddr_in6 sock_addr;
+    int retry, type, n;
+
+    type = hip_get_msg_type(msg);
+
+    _HIP_DEBUG("type=%d\n", type);
+
+    memset(&sock_addr, 0, sizeof(sock_addr));
+    sock_addr.sin6_family = AF_INET6;
+    sock_addr.sin6_port   = htons(HIP_FIREWALL_PORT);
+    sock_addr.sin6_addr   = in6addr_loopback;
+
+    for (retry = 0; retry < 3; retry++) {
+        /* Switched from hip_sendto() to hip_sendto_user() due to
+         * namespace collision. Both message.h and user.c had functions
+         * hip_sendto(). Introducing a prototype hip_sendto() to user.h
+         * led to compiler errors --> user.c hip_sendto() renamed to
+         * hip_sendto_user().
+         *
+         * Lesson learned: use function prototypes unless functions are
+         * ment only for local (inside the same file where defined) use.
+         * -Lauri 11.07.2008 */
+        n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr);
+        if (n <= 0) {
+            HIP_ERROR("hipconf opptcp failed (round %d)\n", retry);
+            HIP_DEBUG("Sleeping few seconds to wait for fw\n");
+            sleep(2);
+        } else {
+            HIP_DEBUG("hipconf opptcp ok (sent %d bytes)\n", n);
+            break;
+        }
+    }
+
+    if (type == SO_HIP_SET_OPPTCP_ON) {
+        hip_use_opptcp = 1;
+    } else {
+        hip_use_opptcp = 0;
+    }
+
+    HIP_DEBUG("Opportunistic tcp set %s\n",
+              (hip_use_opptcp ? "on" : "off"));
+}
+
+/**
+ * query status for the opportunistic TCP extensions
+ *
+ * @return 1 if it is enabled or 0 otherwise
+ */
+int hip_get_opportunistic_tcp_status(void)
+{
+    return hip_use_opptcp;
+}
+
+/**
  * Set opportunistic mode
  *
  * @param msg A message containing a HIP_PARAM_UINT parameter.
@@ -144,6 +203,64 @@
 out_err:
     return err;
 }
+#endif /* CONFIG_HIP_OPPORTUNISTIC */
+
+#ifdef CONFIG_HIP_I3
+/**
+ * turn hi3 support on or off
+ *
+ * @param msg a message with type SO_HIP_SET_HI3_ON or SO_HIP_SET_HI3_OFF
+ */
+void hip_set_hi3_status(struct hip_common *msg)
+{
+    struct sockaddr_in6 sock_addr;
+    int retry, type, n;
+
+    type = hip_get_msg_type(msg);
+
+    _HIP_DEBUG("type=%d\n", type);
+
+    bzero(&sock_addr, sizeof(sock_addr));
+    sock_addr.sin6_family = AF_INET6;
+    sock_addr.sin6_port   = htons(HIP_FIREWALL_PORT);
+    sock_addr.sin6_addr   = in6addr_loopback;
+
+    for (retry = 0; retry < 3; retry++) {
+        n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr);
+        if (n <= 0) {
+            HIP_ERROR("hipconf hi3 failed (round %d)\n", retry);
+            HIP_DEBUG("Sleeping few seconds to wait for fw\n");
+            sleep(2);
+        } else {
+            HIP_DEBUG("hipconf hi3 ok (sent %d bytes)\n", n);
+            break;
+        }
+    }
+
+    if (type == SO_HIP_SET_HI3_ON) {
+        hip_i3_init();
+        hip_use_hi3        = 1;
+        hip_locator_status = SO_HIP_SET_LOCATOR_ON;
+    } else {
+        hip_locator_status = SO_HIP_SET_LOCATOR_OFF;
+        hip_hi3_clean();
+        hip_use_hi3        = 0;
+    }
+
+    HIP_DEBUG("hi3 set %s\n",
+              (hip_use_hi3 ? "on" : "off"));
+}
+
+/**
+ * query if Hi3 is enabled or not
+ *
+ * @return 1 if it is enabled or 0 otherwise
+ */
+int hip_get_hi3_status(void)
+{
+    return hip_use_hi3;
+}
+#endif /* CONFIG_HIP_I3 */
 
 /**
  * Query if a pseudo HIT is stored in the host association
@@ -186,8 +303,6 @@
     return err;
 }
 
-#endif // CONFIG_HIP_OPPORTUNISTIC
-
 /**
  * Query status of client-side HIP proxy
  *

=== modified file 'hipd/accessor.h'
--- hipd/accessor.h     2010-02-17 17:38:08 +0000
+++ hipd/accessor.h     2010-03-19 09:53:35 +0000
@@ -1,16 +1,13 @@
 #ifndef HIP_HIPD_ACCESSOR_H
 #define HIP_HIPD_ACCESSOR_H
 
-#include "hipd.h" /* @todo: header recursion: hipd.h calls accessor.h */
-
-#include "lib/core/hashtable.h"
-
-#include <sys/time.h>
-
-
 #include <openssl/sha.h>
 #include <openssl/md5.h>
 #include <openssl/des.h>
+#include <sys/time.h>
+
+#include "config.h"
+#include "lib/core/hashtable.h"
 
 /** @addtogroup daemon_states
  * @{
@@ -35,14 +32,30 @@
 
 #define INDEX_HASH_FN           HIP_DIGEST_SHA1
 
+/** Specifies the NAT status of the daemon. This value indicates if the current
+ *  machine is behind a NAT. Defined in hipd.c */
+extern int hipproxy;
+
+extern unsigned int opportunistic_mode;
+
 unsigned int hipd_get_state(void);
 void hipd_set_state(unsigned int);
 int hipd_get_flag(unsigned int);
 void hipd_set_flag(unsigned int);
 int hip_agent_is_alive(void);
+
+#ifdef CONFIG_HIP_OPPORTUNISTIC
+int hip_get_opportunistic_tcp_status(void);
 int hip_set_opportunistic_mode(struct hip_common *msg);
 int hip_query_opportunistic_mode(struct hip_common *msg);
 int hip_query_ip_hit_mapping(struct hip_common *msg);
+#endif /* CONFIG_HIP_OPPORTUNISTIC */
+
+#ifdef CONFIG_HIP_I3
+int hip_get_hi3_status(void);
+void hip_set_hi3_status(struct hip_common *msg);
+#endif /* CONFIG_HIP_I3 */
+
 int hip_get_hip_proxy_status(void);
 int hip_set_hip_proxy_on(void);
 int hip_set_hip_proxy_off(void);

=== modified file 'hipd/blind.c'
--- hipd/blind.c        2010-03-19 09:24:10 +0000
+++ hipd/blind.c        2010-03-19 09:53:35 +0000
@@ -1,17 +1,29 @@
 /** @file
  * This file defines tools of  blind extension for the Host Identity Protocol
+ * See <a 
href="http://lib.tkk.fi/Diss/2008/isbn9789512295319/article6.pdf";>Ylitalo et 
al, BLIND: a Complete Identity Protection Framework for End-hosts, April 
2004</a> and the corresponding IETF draft <a 
href="http://tools.ietf.org/html/draft-zhang-hip-privacy-protection";>Zhang et 
al,
+An Extension of HIP Base Exchange to Support Identity Privacy, IETF draft, 
Work in Progress, March 2010</a>.
  *
  * @author  Laura Takkinen
- * @note    Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
+ * @note Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
  */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
 #include "blind.h"
+#include "lib/core/hostid.h"
 
 static int hip_blind_fingerprints(hip_ha_t *entry);
 
+/**
+ * test whether we should use blind or not based on an inbound packet
+ *
+ * @param msg a HIP control message
+ * @param entry related host association
+ * @param use_blind An output argument where the result will be written
+ *                  One if blind should be used or zero otherwise.
+ * @return zero on success or negative on error
+o */
 int hip_check_whether_to_use_blind(hip_common_t *msg, hip_ha_t *entry,  int 
*use_blind)
 {
     /* Check for error conditions. */
@@ -47,7 +59,13 @@
     }
 }
 
-/* For internal use only */
+/**
+ * enable blind for a given host assocation
+ *
+ * @param entry a host association
+ * @param not_used not used
+ * @return zero
+ */
 static int hip_set_blind_on_sa(hip_ha_t *entry, void *not_used)
 {
     int err = 0;
@@ -59,7 +77,13 @@
     return err;
 }
 
-/* For internal use only */
+/**
+ * disable blind for a given host assocation
+ *
+ * @param entry a host association
+ * @param not_used not used
+ * @return zero
+ */
 static int hip_set_blind_off_sa(hip_ha_t *entry, void *not_used)
 {
     int err = 0;
@@ -71,9 +95,12 @@
     return err;
 }
 
-/* This functions is used to set the blind on.
- * "blind" entry of all existing associations is set to 1
- * and hip_blind_status is set to 1.
+/**
+ * Enable blind globally for all host associations
+ *
+ * @return zero
+ * @note this function has no effect if host association
+ *       is in established state
  */
 int hip_set_blind_on(void)
 {
@@ -87,9 +114,12 @@
     return err;
 }
 
-/* This functions is used to set the blind off.
- * "blind" entry of all existing associations is set to 0
- * and hip_blind_status is set to 0.
+/**
+ * Disable blind globally for all host associations
+ *
+ * @return zero
+ * @note this function has no effect if host association
+ *       is in established state
  */
 int hip_set_blind_off(void)
 {
@@ -104,7 +134,7 @@
 }
 
 /**
- * @brief This functions is used to query if the blind is in use.
+ * This functions is used to query if the blind is in use.
  *
  * @return Zero if blind is off and 1 if blind is on.
  */
@@ -113,10 +143,12 @@
     return hip_blind_status;
 }
 
-/* Extracts the uint16_t type nonce from the message.
- * @msg Message from where the nonce is extracted
- * @msg_nonce The nonce that the message included
- * Returns 0 in success, otherwise returns -1.
+/**
+ * Extract uint16_t type blind nonce from HIP control message
+ *
+ * @param msg message the message from where the nonce is extracted
+ * @param msg_nonce the nonce will be written here
+ * @return zero on success or negative on error
  */
 int hip_blind_get_nonce(struct hip_common *msg, uint16_t *msg_nonce)
 {
@@ -132,12 +164,12 @@
 }
 
 /**
- * @brief Forms a plain HIT from a blinded one.
+ * Forms a plain HIT from a blinded one.
  *
  * @param  nonce     Nonce that is used to calculate the plain HIT.
  * @param  blind_hit Blinded HIT from where the plain HIT is formed.
  * @param  plain_hit Calculated plain HIT
- * @return           Zero in success, otherwise -1.
+ * @return zero on success or negative on error
  */
 int hip_plain_fingerprint(uint16_t *nonce,  struct in6_addr *blind_hit,
                           struct in6_addr *plain_hit)
@@ -152,12 +184,13 @@
     return err;
 }
 
-/* Forms the blinded HIT from the key (SHA1 hash from the key).
- * For internal purposes.
- * @key Key from where the hash is calculated
- * @key_len Length of the key
- * @blind_hit Calculated blind HIT (hash)
- * Returns 0 in success, otherwise returns -1.
+/**
+ * Form the blinded HIT from the key (SHA1 hash from the key).
+ *
+ * @param key Key from where the hash is calculated
+ * @param key_len Length of the key
+ * @param blind_hit Calculated blind HIT (hash)
+ * @return zero on success or negative on error
  */
 int hip_do_blind(char *key, unsigned int key_len, struct in6_addr *blind_hit)
 {
@@ -185,10 +218,11 @@
     return err;
 }
 
-/* Sets nonce and calculates the blinded
- * fingerprints for the hip_ha_t entry.
- * @entry hip_ha_t entry which blind fields are adjusted
- * Returns 0 in success, otherwise returns -1.
+/**
+ * Sets nonce and calculates the blinded fingerprints for the hip_ha_t entry.
+ *
+ * @param entry hip_ha_t entry which blind fields are adjusted
+ * @return zero on success or negative on error
  */
 static int hip_blind_fingerprints(hip_ha_t *entry)
 {
@@ -223,7 +257,15 @@
     return err;
 }
 
-/* Tests if @plain_hit blinded with nonce is same as @blind_hit*/
+/**
+ * Tests if plain_hit blinded with nonce is same as @blind_hit
+ *
+ * @param nonce the nonce used for blinding the hit
+ * @param plain_hit the plain HIT to be tested
+ * @param blind_hit the blinded HIT
+ *
+ * @return zero on success or negative on error
+ */
 int hip_blind_verify(uint16_t *nonce, struct in6_addr *plain_hit,
                      struct in6_addr *blind_hit)
 {
@@ -268,7 +310,12 @@
     }
     return ret == 0;
 }
-
+/**
+ * build a blinded i1 message
+ *
+ * @param entry the related host association
+ * @param mask a mask template for I1 packet without blind
+ */
 struct hip_common *hip_blind_build_i1(hip_ha_t *entry, uint16_t *mask)
 {
     struct hip_common *i1;
@@ -306,7 +353,16 @@
     return i1;
 }
 
-/* Fills the r2 message with required blind parameters*/
+/**
+ * Fill in the r2 message with required blind parameters
+ *
+ * @param i2 the receive I2 message
+ * @param r2 message to be sent
+ * @param entry the related host association
+ * @param the default control flags mask template
+ *
+ * @return zero on success or negative on error
+ */
 int hip_blind_build_r2(struct hip_common *i2, struct hip_common *r2, hip_ha_t 
*entry, uint16_t *mask)
 {
     int err           = 0, host_id_in_enc_len = 0;
@@ -385,6 +441,14 @@
     return err;
 }
 
+/**
+ * verify a blinded R2 message
+ *
+ * @param r2 the R2 control message
+ * @param entry the related host association
+ *
+ * @return zero if the message was ok or negative otherwise
+ */
 int hip_blind_verify_r2(struct hip_common *r2, hip_ha_t *entry)
 {
     int err                            = 0;
@@ -475,7 +539,7 @@
 }
 
 /**
- * Constructs a new R1 packet payload.
+ * Constructs a new blinde R1 packet payload
  *
  * @param src_hit      a pointer to the source host identity tag used in the
  *                     packet.
@@ -659,6 +723,16 @@
     return NULL;
 }
 
+/**
+ * recreate a blind spool of R1 messages
+ *
+ * @param r1table the R1 table to fill
+ * @param hit the local HIT
+ * @param sign the signature function pointer
+ * @param privkey the private key for signing
+ * @param pubkey the corresponding public key
+ * @return zero on success or negative on error
+ */
 int hip_blind_precreate_r1(struct hip_r1entry *r1table, struct in6_addr *hit,
                            int (*sign)(void *key, struct hip_common *m),
                            void *privkey, struct hip_host_id *pubkey)

=== modified file 'hipd/bos.c'
--- hipd/bos.c  2010-02-17 17:38:08 +0000
+++ hipd/bos.c  2010-03-19 09:53:35 +0000
@@ -1,7 +1,25 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * BOS packet was defined in
+ * <a 
href="http://tools.ietf.org/html/draft-ietf-hip-base-00";>draft-ietf-hip-base-00
+ * </a> but it was removed in later revisions. It can be used to broadcast your
+ * own identity (and IP address) to the local network. Privacy proponents 
beware!
+ *
+ * @brief BOS packet sending and receiving functionality
+ *
+ * @author Anthony D. Joseph
+ *
+ */
+
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
 #include "bos.h"
+#include "lib/core/hostid.h"
+#include "lib/core/hip_udp.h"
 
 /**
  * hip_create_signature - Calculate SHA1 hash over the data and sign it.
@@ -33,7 +51,8 @@
     return err;
 }
 
-/** hip_socket_send_bos - send a BOS packet
+/**
+ * hip_socket_send_bos - send a BOS packet
  * @param msg input message (should be empty)
  *
  * Generate a signed HIP BOS packet containing our HIT, and send

=== modified file 'hipd/bos.h'
--- hipd/bos.h  2010-02-17 17:38:08 +0000
+++ hipd/bos.h  2010-03-19 09:53:35 +0000
@@ -13,9 +13,6 @@
 #include "lib/core/state.h"
 
 int hip_send_bos(const struct hip_common *msg);
-int hip_verify_packet_signature(struct hip_common *bos,
-                                struct hip_host_id *peer_host_id);
-
 int hip_handle_bos(struct hip_common *bos,
                    struct in6_addr *bos_saddr,
                    struct in6_addr *bos_daddr,

=== modified file 'hipd/cert.h'
--- hipd/cert.h 2010-02-17 17:38:08 +0000
+++ hipd/cert.h 2010-03-19 09:53:35 +0000
@@ -23,13 +23,10 @@
 #include <openssl/err.h>
 #include <openssl/pem.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
-#include "lib/core/misc.h"
+
 #include "hidb.h"
 #include "lib/core/hashtable.h"
 

=== modified file 'hipd/close.c'
--- hipd/close.c        2010-02-17 17:38:08 +0000
+++ hipd/close.c        2010-03-19 09:53:35 +0000
@@ -1,19 +1,30 @@
-/* TODO: Doxygen documentation incomplete. Please fix
-**/
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Processing for CLOSE control packets
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "close.h"
 #ifdef CONFIG_HIP_PERFORMANCE
 #include "lib/performance/performance.h"
 #endif
-
-
+#include "lib/core/hip_udp.h"
+
+/**
+ * send a HIP close packet to a peer
+ *
+ * @param entry the host association with the peer
+ * @param opaque a nonce to be included in the CLOSE
+ * @return zero on success or negative on error
+ */
 static int hip_xmit_close(hip_ha_t *entry, void *opaque)
 {
 #ifdef CONFIG_HIP_PERFORMANCE
@@ -109,6 +120,13 @@
     return err;
 }
 
+/**
+ * a wrapper to send a close message to a peer
+ *
+ * @param msg a message containing a peer HIT to which to send close
+ * @param delete_ha_info a nonce parameter for the CLOSE message
+ * @return zero on success or negative on error
+ */
 int hip_send_close(struct hip_common *msg,
                    int delete_ha_info)
 {
@@ -174,6 +192,13 @@
     return err;
 }
 
+/**
+ * process a CLOSE message
+ *
+ * @param close the CLOSE message process
+ * @param entry the corresponding host association
+ * @return zero on success or negative on error
+ */
 int hip_handle_close(struct hip_common *close, hip_ha_t *entry)
 {
 #ifdef CONFIG_HIP_PERFORMANCE
@@ -264,6 +289,13 @@
     return err;
 }
 
+/**
+ * preprocess a CLOSE message
+ *
+ * @param close the CLOSE message preprocess
+ * @param entry the corresponding host association
+ * @return zero on success or negative on error
+ */
 int hip_receive_close(struct hip_common *close,
                       hip_ha_t          *entry)
 {
@@ -310,6 +342,13 @@
     return err;
 }
 
+/**
+ * process a CLOSE ACK message
+ *
+ * @param close_ack the CLOSE ACK message process
+ * @param entry the corresponding host association
+ * @return zero on success or negative on error
+ */
 int hip_handle_close_ack(struct hip_common *close_ack, hip_ha_t *entry)
 {
 #ifdef CONFIG_HIP_PERFORMANCE
@@ -373,6 +412,13 @@
     return err;
 }
 
+/**
+ * preprocess a CLOSE ACK message
+ *
+ * @param close the CLOSE ACK message process
+ * @param entry the corresponding host association
+ * @return zero on success or negative on error
+ */
 int hip_receive_close_ack(struct hip_common *close_ack,
                           hip_ha_t *entry)
 {
@@ -418,6 +464,13 @@
     return err;
 }
 
+/**
+ * tear down a host association after close procedure
+ *
+ * @param ha the corresponding host association
+ * @param notused not used
+ * @return zero on success or negative on error
+ */
 int hip_purge_closing_ha(hip_ha_t *ha, void *notused)
 {
     int err = 0;

=== modified file 'hipd/close.h'
--- hipd/close.h        2010-02-17 17:38:08 +0000
+++ hipd/close.h        2010-03-19 09:53:35 +0000
@@ -2,7 +2,7 @@
 #define HIP_HIPD_CLOSE_H
 
 #include "hadb.h"
-#include "lib/core/misc.h"
+
 #include "hidb.h"
 #include "lib/core/builder.h"
 #include "cookie.h"
@@ -10,7 +10,7 @@
 #include "lib/core/debug.h"
 #include "keymat.h"
 #include "lib/core/crypto.h"
-#include "lib/core/misc.h"
+
 #include "lib/tool/pk.h"
 
 int hip_send_close(struct hip_common *msg, int delete_ha_info);

=== modified file 'hipd/configfilereader.c'
--- hipd/configfilereader.c     2010-02-17 17:38:08 +0000
+++ hipd/configfilereader.c     2010-03-19 09:53:35 +0000
@@ -10,6 +10,7 @@
 #define _BSD_SOURCE
 
 #include "configfilereader.h"
+#include "lib/core/debug.h"
 
 /** Error value for generic config file error. (Everything but -EIO and EOF are
  *  acceptable here.) */

=== modified file 'hipd/configfilereader.h'
--- hipd/configfilereader.h     2010-02-17 17:38:08 +0000
+++ hipd/configfilereader.h     2010-03-19 09:53:35 +0000
@@ -63,7 +63,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <errno.h>
-#include "lib/core/misc.h" /* For debuging macros. */
+ /* For debuging macros. */
 
 /** Maximum number of characters per line in HIP relay config file. */
 #define HIP_RELAY_MAX_LINE_LEN 2048

=== modified file 'hipd/cookie.c'
--- hipd/cookie.c       2010-03-19 09:24:10 +0000
+++ hipd/cookie.c       2010-03-19 09:53:35 +0000
@@ -1,29 +1,34 @@
 /**
  * @file
- * HIP cookie handling. Licence: GNU/GPL
+ * HIP cookie handling
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
  *
  * @author Kristian Slavov <ksl#iki.fi>
  * @author Miika Komu <miika#iki.fi>
  *
- * TODO: Doxygen documentation incomplete. Please fix this.
- *
  */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "cookie.h"
+#include "lib/core/solve.h"
 
 #define HIP_PUZZLE_MAX_LIFETIME 60 /* in seconds */
 #define HIP_DEFAULT_COOKIE_K    1ULL /* a difficulty of i leads to approx. 
2^(i-1) hash computations during BEX */
 
 int hip_cookie_difficulty = HIP_DEFAULT_COOKIE_K;
 
-//get the puzzle difficulty and return result to hipconf
+/**
+ * get the puzzle difficulty and return result (for hipconf)
+ *
+ * @param msg A message containing a HIT for which to query for
+ *            the difficulty. The difficulty will be written
+ *            into the message as a HIP_PARAM_INT parameter.
+ * @return zero on success and negative on error
+ */
 int hip_get_puzzle_difficulty_msg(struct hip_common *msg)
 {
     int err            = 0, diff = 0;
@@ -31,18 +36,10 @@
     hip_hit_t all_zero_hit;
     bzero(&all_zero_hit, sizeof(all_zero_hit));
 
-    //obtain the hit
+    /* obtain the hit */
     dst_hit = hip_get_param_contents(msg, HIP_PARAM_HIT);
 
-#ifdef CONFIG_HIP_COOKIE
-    if (ipv6_addr_cmp(&all_zero_hit, dst_hit) != 0) {
-        diff = hip_get_cookie_difficulty(dst_hit);
-    } else {
-#endif
     diff = hip_get_cookie_difficulty(NULL);
-#ifdef CONFIG_HIP_COOKIE
-}
-#endif
 
     _HIP_DEBUG("Puzzle difficulty is %d\n", diff);
     hip_build_param_contents(msg, &diff, HIP_PARAM_INT, sizeof(diff));
@@ -51,47 +48,50 @@
 }
 
 
-/* TODO: This function has no error handling at all! Check if this is right-*/
-//set the puzzle difficulty acc to msg sent by hipconf
+/**
+ * set the puzzle difficulty according to the msg sent by hipconf
+ *
+ * @param msg An input/output message. Should contain the target
+ *            HIT and the required puzzle difficulty.
+ * @return zero on success and negative on error
+ */
 int hip_set_puzzle_difficulty_msg(struct hip_common *msg)
 {
-    int err            = 0, *newVal = NULL;
+    int err = 0, *newVal = NULL;
     hip_hit_t *dst_hit = NULL;
     hip_hit_t all_zero_hit;
     bzero(&all_zero_hit, sizeof(all_zero_hit));
 
-    dst_hit = hip_get_param_contents(msg, HIP_PARAM_HIT);
-    newVal  = hip_get_param_contents(msg, HIP_PARAM_INT);
-
-#ifdef CONFIG_HIP_COOKIE
-    if (ipv6_addr_cmp(&all_zero_hit, dst_hit) != 0) {
-        hip_set_cookie_difficulty(dst_hit, *newVal);
-    } else {
-#endif
-    hip_set_cookie_difficulty(NULL, *newVal);
-#ifdef CONFIG_HIP_COOKIE
-}
-
-#endif
+    HIP_IFEL(!(dst_hit = hip_get_param_contents(msg, HIP_PARAM_HIT)),
+             -1, "No HIT set\n");
+    HIP_IFEL(!(newVal = hip_get_param_contents(msg, HIP_PARAM_INT)),
+             -1, "No difficulty set\n");
+
+    HIP_IFEL(hip_set_cookie_difficulty(NULL, *newVal), -1,
+             "Setting difficulty failed\n");
+ out_err:
     return err;
 }
 
-#ifndef CONFIG_HIP_ICOOKIE /* see also spam.c for overriding functions */
-
-#if 0
-void hip_init_puzzle_defaults()
-{
-    return;
-}
-
-#endif
-
+/**
+ * query for current puzzle difficulty
+ *
+ * @param not_used not used
+ * @return the puzzle difficulty
+ */
 int hip_get_cookie_difficulty(hip_hit_t *not_used)
 {
     /* Note: we could return a higher value if we detect DoS */
     return hip_cookie_difficulty;
 }
 
+/**
+ * set puzzle difficulty
+ *
+ * @param not_used not used
+ * @param k the new puzzle difficulty
+ * @return the k value on success or negative on error
+ */
 int hip_set_cookie_difficulty(hip_hit_t *not_used, int k)
 {
     if (k > HIP_PUZZLE_MAX_K || k < 1) {
@@ -104,12 +104,24 @@
     return k;
 }
 
+/**
+ * increase cookie difficulty by one
+ *
+ * @param not_used not used
+ * @return the new cookie difficulty
+ */
 int hip_inc_cookie_difficulty(hip_hit_t *not_used)
 {
     int k = hip_get_cookie_difficulty(NULL) + 1;
     return hip_set_cookie_difficulty(NULL, k);
 }
 
+/**
+ * decrease cookie difficulty by one
+ *
+ * @param not_used not used
+ * @return the new cookie difficulty
+ */
 int hip_dec_cookie_difficulty(hip_hit_t *not_used)
 {
     int k = hip_get_cookie_difficulty(NULL) - 1;
@@ -117,7 +129,8 @@
 }
 
 /**
- * hip_calc_cookie_idx - get an index
+ * calculate the index of a cookie
+ *
  * @param ip_i Initiator's IPv6 address
  * @param ip_r Responder's IPv6 address
  * @param hit_i Initiators HIT
@@ -144,14 +157,13 @@
     return (base) % HIP_R1TABLESIZE;
 }
 
-#endif /* !CONFIG_HIP_ICOOKIE */
-
 /**
- * hip_fetch_cookie_entry - Get a copy of R1entry structure
+ * get a copy of R1entry structure
+ *
  * @param ip_i Initiator's IPv6
  * @param ip_r Responder's IPv6
  *
- * Comments for the if 0 code are inlined below.
+ * @note Comments for the if 0 code are inlined below.
  *
  * Returns NULL if error.
  */
@@ -233,6 +245,11 @@
     return err;
 }
 
+/**
+ * initialize an R1 entry structure
+ *
+ * @return The allocated R1 entry structure. Caller deallocates.
+ */
 struct hip_r1entry *hip_init_r1(void)
 {
     struct hip_r1entry *err;
@@ -245,9 +262,15 @@
     return err;
 }
 
-#ifndef CONFIG_HIP_ICOOKIE
-/*
- * @sign the signing function to use
+/**
+ * precreate an R1 packet
+ *
+ * @param r1table a pointer to R1 table structure
+ * @param hit the local HIT
+ * @param sign a signing callback function
+ * @param privkey the private key to use for signing
+ * @param pubkey the host id (public key)
+ * @return zero on success and non-zero on error
  */
 int hip_precreate_r1(struct hip_r1entry *r1table, struct in6_addr *hit,
                      int (*sign)(void *key, struct hip_common *m),
@@ -275,8 +298,11 @@
     return 0;
 }
 
-#endif /* !CONFIG_HIP_ICOOKIE */
-
+/**
+ * uninitialize R1 table
+ *
+ * @param hip_r1table R1 table
+ */
 void hip_uninit_r1(struct hip_r1entry *hip_r1table)
 {
     int i;
@@ -407,6 +433,13 @@
     return err;
 }
 
+/**
+ * recreate R1 packets corresponding to one HI
+ *
+ * @param entry the host id entry
+ * @param new_hash unused
+ * @return zero on success or negative on error
+ */
 static int hip_recreate_r1s_for_entry_move(struct hip_host_id_entry *entry,
                                            void *new_hash)
 {
@@ -432,6 +465,11 @@
     return err;
 }
 
+/**
+ * precreate all R1 packets
+ *
+ * @return zero on success or negative on error
+ */
 int hip_recreate_all_precreated_r1_packets()
 {
     HIP_HASHTABLE *ht = hip_ht_init(hip_hidb_hash, hip_hidb_match);

=== modified file 'hipd/cookie.h'
--- hipd/cookie.h       2010-02-17 17:38:08 +0000
+++ hipd/cookie.h       2010-03-19 09:53:35 +0000
@@ -16,7 +16,6 @@
 };
 
 #define HIP_R1TABLESIZE         3 /* precreate only this many R1s */
-#define HIP_PUZZLE_MAX_K        28
 struct hip_common *hip_get_r1(struct in6_addr *ip_i,
                               struct in6_addr *ip_r,
                               struct in6_addr *src_hit,

=== modified file 'hipd/dh.c'
--- hipd/dh.c   2010-03-19 09:24:10 +0000
+++ hipd/dh.c   2010-03-19 09:53:35 +0000
@@ -1,12 +1,13 @@
-/*
- * HIPL security related functions
- *
- * Licence: GNU/GPL
- *
- * Authors:
- * - Mika Kousa <mkousa@xxxxxx>
- * - Kristian Slavov <ksl@xxxxxx>
- * - Tobias Heer <heer@xxxxxxxxxx>
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Diffie-Hellman wrappers for HIP
+ *
+ * @author Mika Kousa <mkousa@xxxxxx>
+ * @author Kristian Slavov <ksl@xxxxxx>
+ * @author Tobias Heer <heer@xxxxxxxxxx>
  */
 
 /* required for s6_addr32 */
@@ -19,7 +20,7 @@
 static void hip_regen_dh_keys(uint32_t bitmask);
 
 /**
- * hip_insert_dh - Insert the current DH-key into the buffer
+ * insert the current DH-key into the buffer
  *
  * If a DH-key does not exist, we will create one.
  * @return >0 if ok, -1 if errors
@@ -62,9 +63,9 @@
 }
 
 /**
- * hip_calculate_shared_secret - Creates a shared secret based on the
- * public key of the peer (passed as an argument) and own DH private key
- * (created beforehand).
+ * create a shared secret based on the public key of the peer
+ * (passed as an argument) and own DH private key (created beforehand).
+ *
  * @param public_value Peer's Diffie-Hellman public key
  * @param group_id the Diffie-Hellman group ID
  * @param len the length of the public value
@@ -113,10 +114,10 @@
 }
 
 /**
- * hip_regen_dh_keys - Regenerate Diffie-Hellman keys for HIP
+ * regenerate Diffie-Hellman keys for HIP
  * @param bitmask Mask of groups to generate.
  *
- * Use only this function to generate DH keys.
+ * @note Use only this function to generate DH keys.
  */
 static void hip_regen_dh_keys(uint32_t bitmask)
 {
@@ -149,6 +150,9 @@
     HIP_DEBUG("%d keys generated\n", cnt);
 }
 
+/**
+ * uninitialize precreated DH structures
+ */
 void hip_dh_uninit(void)
 {
     int i;
@@ -160,6 +164,9 @@
     }
 }
 
+/**
+ * initialize D-H cipher structures
+ */
 int hip_init_cipher(void)
 {
     uint32_t supported_groups;

=== modified file 'hipd/dht.c'
--- hipd/dht.c  2010-02-17 17:38:08 +0000
+++ hipd/dht.c  2010-03-19 09:53:35 +0000
@@ -15,6 +15,8 @@
 
 #include "dht.h"
 #include "hipd.h"
+#include "lib/core/hostid.h"
+#include "lib/core/hit.h"
 
 static void hip_publish_hit(char *, char *);
 static int hip_publish_addr(char *);
@@ -35,10 +37,11 @@
  * @param *socket socket to be initialized
  * @param *socket_status updates the status of the socket after every socket 
operation
  *
- * @return void
+ * @return 0 on success negative otherwise
  */
-void hip_init_dht_sockets(int *socket, int *socket_status)
+int hip_init_dht_sockets(int *socket, int *socket_status)
 {
+    int err = 0;
     if (hip_opendht_inuse == SO_HIP_DHT_ON) {
         if (*socket_status == STATE_OPENDHT_IDLE) {
             HIP_DEBUG("Connecting to the DHT with socket no: %d \n", *socket);
@@ -46,18 +49,18 @@
                 *socket = init_dht_gateway_socket_gw(*socket,
                                                      opendht_serving_gateway);
             }
-            opendht_error = 0;
-            opendht_error = connect_dht_gateway(*socket,
-                                                opendht_serving_gateway, 0);
+            err = connect_dht_gateway(*socket,
+                                      opendht_serving_gateway, 0);
         }
-        if (opendht_error == EINPROGRESS) {
+        if (err == EINPROGRESS) {
             *socket_status = STATE_OPENDHT_WAITING_CONNECT;
             /* connect not ready */
             HIP_DEBUG("OpenDHT connect unfinished. Socket No: %d \n", *socket);
-        } else if (opendht_error > -1 && opendht_error != EINPROGRESS)   {
+        } else if (err > -1 && err != EINPROGRESS)   {
             *socket_status = STATE_OPENDHT_START_SEND;
         }
     }
+    return err;
 }
 
 /**

=== modified file 'hipd/dht.h'
--- hipd/dht.h  2010-02-17 17:38:08 +0000
+++ hipd/dht.h  2010-03-19 09:53:35 +0000
@@ -18,7 +18,7 @@
 #include "lib/dht/libhipdht.h"
 #include "lib/dht/libhipdhtxml.h"
 
-void hip_init_dht_sockets(int *, int *);
+int hip_init_dht_sockets(int *, int *);
 void hip_register_to_dht(void);
 
 int hip_publish_certificates(void);

=== modified file 'hipd/dhtqueue.c'
--- hipd/dhtqueue.c     2010-02-17 17:38:08 +0000
+++ hipd/dhtqueue.c     2010-03-19 09:53:35 +0000
@@ -9,11 +9,13 @@
 #define _BSD_SOURCE
 
 #include <stdlib.h>
+#include "dhtqueue.h"
+#include "hipd.h"
 #include "lib/core/hashtable.h"
 #include "lib/core/debug.h"
-
-#include "dhtqueue.h"
-#include "lib/core/misc.h"
+#include "lib/core/builder.h"
+
+
 
 struct hip_queue {
     void *data;

=== modified file 'hipd/esp_prot_anchordb.c'
--- hipd/esp_prot_anchordb.c    2010-02-17 17:38:08 +0000
+++ hipd/esp_prot_anchordb.c    2010-03-19 09:53:35 +0000
@@ -1,7 +1,7 @@
 /**
  * @file firewall/esp_prot_anchordb.c
  *
- * <LICENSE TEMLPATE LINE - LEAVE THIS LINE INTACT>
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
  *
  * This implementation stores anchor elements to be used as references to
  * the hash structures stored in the BEX store of the hipfw. The elements
@@ -20,7 +20,8 @@
 #include "lib/core/esp_prot_common.h"
 #include "lib/core/builder.h"
 #include "esp_prot_anchordb.h"
-
+#include "hipd.h"
+#include "init.h"
 
 /* defines the structure storing the anchors */
 typedef struct anchor_db {

=== modified file 'hipd/esp_prot_hipd_msg.c'
--- hipd/esp_prot_hipd_msg.c    2010-02-17 17:38:08 +0000
+++ hipd/esp_prot_hipd_msg.c    2010-03-19 09:53:35 +0000
@@ -1,7 +1,7 @@
 /**
  * @file firewall/esp_prot_hipd_msg.c
  *
- * <LICENSE TEMLPATE LINE - LEAVE THIS LINE INTACT>
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
  *
  * hipd messages to the hipfw and additional parameters for BEX and
  * UPDATE messages.
@@ -20,6 +20,7 @@
 #include "esp_prot_light_update.h"
 #include "lib/core/esp_prot_common.h"
 #include "lib/core/builder.h"
+#include "lib/core/hip_udp.h"
 #include "hipd.h"
 
 /**

=== modified file 'hipd/esp_prot_light_update.c'
--- hipd/esp_prot_light_update.c        2010-02-17 17:38:08 +0000
+++ hipd/esp_prot_light_update.c        2010-03-19 09:53:35 +0000
@@ -1,7 +1,7 @@
 /**
  * @file firewall/esp_prot_light_update.h
  *
- * <LICENSE TEMLPATE LINE - LEAVE THIS LINE INTACT>
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
  *
  * Provides messaging functionality required for HHL-based anchor
  * element updates.
@@ -17,7 +17,9 @@
 
 #include "esp_prot_light_update.h"
 #include "esp_prot_anchordb.h"
+#include "hipd.h"
 #include "lib/core/builder.h"
+#include "lib/core/hip_udp.h"
 
 /**
  * sends an ack for a received HHL-based update message

=== modified file 'hipd/hadb.c'
--- hipd/hadb.c 2010-03-03 13:16:18 +0000
+++ hipd/hadb.c 2010-03-19 09:53:35 +0000
@@ -1,16 +1,55 @@
-// FIXME: whenever something that is replicated in beet db is
-// modified, the modifications must be written there too.
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * Host Association Database (HADB) is the heart of the hipd and it
+ * contains state information about HIP connectivity with remote
+ * hosts. It shouldn't be confused with Host Identity Data Base (HIDB)
+ * which contains just the local host identities. The Host Association
+ * is an implementation-speficic synonym for HIP association (RFC
+ * terminology).
+ *
+ * HADB is a hash table. It is indexed by a local and remote HIT. For
+ * opportunistic connections, the remote HIT is actually a "pseudo
+ * HIT" at the Initiator side when sending I1. The pseudo HIT consists
+ * of a HIT prefix and a part of the IP address (to avoid demuxing
+ * problems with multiple simultaneous opportunistic connections at
+ * the Initiator side. The Initiator deletes the "pseudo HA" and
+ * creates a new one upon receiving the R1. At the Responder side,
+ * this pseudo trick is not needed because the Responder can just
+ * choose a real HIT when it receives the opportunistic I1.
+ *
+ * The hash table structure is located in lib/core/state.h and it is
+ * called hip_hadb_state. As the structure contains sensitive
+ * information (symmetric key material for IPsec), it should not be
+ * exposed outside of hipd (use hip_hadb_user_info_state instead).
+ *
+ * You can use HADB to store information about negotiated extensions,
+ * local or peer host capabilities, etc. Do not store there
+ * information that is needed to process a single HIP packet, but
+ * instead use the hip_context structure and pass in in function
+ * arguments.
+ *
+ * @brief Host Association Database (HADB) for HIP
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "hadb.h"
 #include "hipd.h"
+#include "accessor.h"
 #include "lib/core/list.h"
+#include "lib/core/hostsfiles.h"
+#include "lib/core/hostid.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/solve.h"
+#include "lib/core/keylen.h"
+#include "lib/core/hostsfiles.h"
 
 #define HIP_HADB_SIZE 53
 #define HIP_MAX_HAS 100
@@ -74,6 +113,14 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_HASH_FN(hip_ha, hip_ha_t)
 
+/**
+ * a comparison function for the hash table algorithm to distinguish
+ * two HAs from each other
+ *
+ * @param ha1 a HA to compare for equality
+ * @param ha2 a HA to compare for equality
+ * @return zero if the HAs match or non-zero otherwise
+ */
 static int hip_ha_cmp(const hip_ha_t *ha1, const hip_ha_t *ha2)
 {
     if (ha1 == NULL || &(ha1->hit_our) == NULL || &(ha1->hit_peer) == NULL ||
@@ -87,6 +134,12 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_COMP_FN(hip_ha, hip_ha_t)
 
+/**
+ * build a digest of a peer address
+ *
+ * @param ptr a pointer to hip_peer_addr_list_item structure
+ * @return a digest of the address in the hip_peer_addr_list_item structure
+ */
 static unsigned long hip_hash_peer_addr(const void *ptr)
 {
     struct in6_addr *addr = &((struct hip_peer_addr_list_item *) ptr)->address;
@@ -97,39 +150,25 @@
     return *((unsigned long *) (void *) hash);
 }
 
+/**
+ * test if two peer addresses match
+ *
+ * @param ptr1 a pointer to a hip_peer_addr_list_item
+ * @param ptr2 a pointer to a hip_peer_addr_list_item
+ * @return zero if the addresses match or non-zero otherwise
+ */
 static int hip_match_peer_addr(const void *ptr1, const void *ptr2)
 {
     return hip_hash_peer_addr(ptr1) != hip_hash_peer_addr(ptr2);
 }
 
-/*
- * Support for multiple inbound IPsec SAs:
- *
- * We need a separate hashtable containing elements HIT and SPI, which
- * tells which HIT has the inbound SPI. When an ESP packet is received,
- * we first get the SPI from it and perform a lookup on the HIT-SPI
- * hashtable to get the mapping. Then we perform another lookup from
- * the HIT hashtable using the HIT we got from the previous
- * lookup. This way we get the HA belonging to the connection.
- *
- * hs = HIT-SPI (struct hip_hit_spi)
- *
- * (functions hip_ .. _hs)
- */
-
-
-/*
- *
- * All the primitive functions up to this point are static, to force
- * some information hiding. The construct functions can access these
- * functions directly.
- *
- *
- */
-
-
 /* PRIMITIVES */
 
+/**
+ * assign local and peer LSI to the given host association
+ *
+ * @param entry the host association
+ */
 void hip_hadb_set_lsi_pair(hip_ha_t *entry)
 {
     hip_lsi_t aux;
@@ -148,7 +187,11 @@
 
 /**
  * This function searches for a hip_ha_t entry from the hip_hadb_hit
- * by a HIT pair (local,peer).
+ * by a HIT pair (local,peer)
+ *
+ * @param hit local HIT
+ * @param hit2 peer HIT
+ * @return the corresponding host association or NULL if not found
  */
 hip_ha_t *hip_hadb_find_byhits(const hip_hit_t *hit, const hip_hit_t *hit2)
 {
@@ -177,6 +220,10 @@
  * to find a HADB entry that matches the current HI and
  * the given peer hit. First matching HADB entry is then returned.
  *
+ * @param hit the peer HIT
+ * @return the host association that matches the peer HIT or NULL if
+ *         not found
+ *
  * @todo Find a better solution, see the text below:
  * This function is needed because we index the HADB now by
  * key values calculated from <peer_hit,local_hit> pairs. Unfortunately, in
@@ -304,6 +351,19 @@
     return st;
 }
 
+/**
+ * display debug information on information in host association
+ *
+ * @param local_addr local address
+ * @param peer_addr peer address
+ * @param local_hit local HIT
+ * @param peer_hit peer HIT
+ * @param peer_lsi peer LSI
+ * @param peer_hostname peer host name
+ * @param local_nat_udp_port local UDP port
+ * @param peer_nat_udp_port peer UDP port
+ *
+ */
 static void hip_print_debug_info(const struct in6_addr *local_addr,
                                  const struct in6_addr *peer_addr,
                                  const hip_hit_t  *local_hit,
@@ -344,17 +404,12 @@
 /**
  * Practically called only by when adding a HIT-IP mapping before base 
exchange.
  *
- * @param  local_hit  a pointer to...
- * @param  peer_hit   a pointer to...
- * @param  local_addr a pointer to...
- * @param  peer_addr  a pointer to...
- * @param  peer_lsi   a pointer to...
- * @return
- * @todo   Allow multiple mappings; base exchange should be initiated to allow
- *         of them in order to prevent local DoS.
- * @todo   Create a security policy for triggering base exchange.
- * @todo   Multiple identities support: alternative a) make generic HIT prefix
- *         based policy to work alternative b) add SP pair for all local HITs.
+ * @param  local_hit local HIT
+ * @param  peer_hit peer HIT
+ * @param  local_addr local address
+ * @param  peer_addr peer address
+ * @param  peer_lsi optional peer LSI (automatically generated if NULL)x
+ * @return zero on success or negative on error
  */
 int hip_hadb_add_peer_info_complete(const hip_hit_t *local_hit,
                                     const hip_hit_t *peer_hit,
@@ -460,7 +515,9 @@
         entry->is_loopback = 1;
     }
 
+#ifdef CONFIG_HIP_OPPORTUNISTIC
     entry->hip_is_opptcp_on = hip_get_opportunistic_tcp_status();
+#endif /* CONFIG_HIP_OPPORTUNISTIC */
 #ifdef CONFIG_HIP_I3
     entry->hip_is_hi3_on    =    hip_get_hi3_status();
 #endif
@@ -488,11 +545,11 @@
 }
 
 /**
- * .
+ * a wrapper to create a host association
  *
- * @param  entry         a pointer to...
- * @param  peer_map_void a pointer to...
- * @return               ...
+ * @param  entry a pointer to a preallocated host association
+ * @param  peer_map_void a pointer to hip_peer_map_info
+ * @return zero on success or negative on error
  */
 static int hip_hadb_add_peer_info_wrapper(struct hip_host_id_entry *entry,
                                           void *peer_map_void)
@@ -514,6 +571,15 @@
     return err;
 }
 
+/**
+ * create a host association
+ *
+ * @param peer_hit the HIT of the remote host
+ * @param peer_addr the address of the remote host
+ * @param peer_lsi an optional LSI for the remote host
+ * @param peer_hostname an optional host name for the remote host
+ * @return zero on success or negative on error
+ */
 int hip_hadb_add_peer_info(hip_hit_t *peer_hit, struct in6_addr *peer_addr,
                            hip_lsi_t *peer_lsi, const char *peer_hostname)
 {
@@ -563,6 +629,13 @@
     return err;
 }
 
+/**
+ * create a host association based on the parameter in a user message
+ *
+ * @param input an user message containing a HIT, optional LSI and hostname for
+ *              the remote host
+ * @return zero on success or negative on error
+ */
 int hip_add_peer_map(const struct hip_common *input)
 {
     struct in6_addr *hit = NULL, *ip = NULL;
@@ -613,7 +686,7 @@
 }
 
 /**
- * Sets function pointer set for an hadb record. Pointer values will not be
+ * set "misc" function pointer set for an hadb record. Pointer values will not 
be
  * copied!
  *
  * @param entry        pointer to the hadb record.
@@ -631,6 +704,14 @@
     return -1;
 }
 
+/**
+ * change the network delivery function pointer set of a host association
+ *
+ * @param entry the host association
+ * @param new_func_set the new function pointer set
+ * @return zero on success and negative on error
+ *
+ */
 int hip_hadb_set_xmit_function_set(hip_ha_t *entry,
                                    hip_xmit_func_set_t *new_func_set)
 {
@@ -641,6 +722,14 @@
     return -1;
 }
 
+/**
+ * change the input filter function pointer set of a host association
+ *
+ * @param entry the host association
+ * @param new_func_set the new function pointer set
+ * @return zero on success and negative on error
+ *
+ */
 static int hip_hadb_set_input_filter_function_set(hip_ha_t *entry,
                                                   hip_input_filter_func_set_t 
*new_func_set)
 {
@@ -651,6 +740,14 @@
     return -1;
 }
 
+/**
+ * change the output handler function pointer set of a host association
+ *
+ * @param entry the host association
+ * @param new_func_set the new function pointer set
+ * @return zero on success and negative on error
+ *
+ */
 static int hip_hadb_set_output_filter_function_set(hip_ha_t *entry,
                                                    
hip_output_filter_func_set_t *new_func_set)
 {
@@ -738,7 +835,7 @@
 }
 
 /**
- * Allocates and initializes a new HA structure.
+ * Allocate and initialize a new HA structure.
  *
  * @param  gfpmask a mask passed directly to HIP_MALLOC().
  * @return NULL if memory allocation failed, otherwise the HA.
@@ -762,8 +859,13 @@
 /* END OF PRIMITIVE FUNCTIONS */
 
 /**
- * Selects the preferred address within the addresses of the given SPI.
- * The selected address is copied to @c addr, it is is non-NULL.
+ * Select the preferred address within the addresses of the given SPI.
+ * The selected address is copied to @c addr, if it is non-NULL.
+ *
+ * @param entry the host association
+ * @param spi_out hip_spi_out_item a pointer to the structure containing 
outbound SPI information
+ * @param addr the resulting outbound address will be copied here if found
+ * @return zero on success and negative on error
  */
 int hip_hadb_select_spi_addr(hip_ha_t *entry, struct hip_spi_out_item 
*spi_out, struct in6_addr *addr)
 {
@@ -844,8 +946,7 @@
  * @param lifetime address lifetime of the address
  * @param state address state
  *
- * @return if @c new_addr already exists, 0 is returned. If address was
- * added successfully 0 is returned, else < 0.
+ * @return zero on success and negative on error
  */
 int hip_hadb_add_peer_addr(hip_ha_t *entry, const struct in6_addr *new_addr,
                            uint32_t spi, uint32_t lifetime, int state,
@@ -913,6 +1014,12 @@
     return err;
 }
 
+/**
+ * delete a host association
+ *
+ * @param ha the ha to deinitiliaze and deallocate
+ * @return zero on success and negative on error
+ */
 int hip_del_peer_info_entry(hip_ha_t *ha)
 {
 #ifdef CONFIG_HIP_OPPORTUNISTIC
@@ -942,7 +1049,12 @@
 }
 
 /**
- * Currently deletes the whole entry...
+ * Search and delete a host association based on HITs
+ *
+ * @param our_hit the local HIT
+ * @param peer_hit the remote HIT
+ *
+ * @return zero on success and negative on error
  */
 int hip_del_peer_info(hip_hit_t *our_hit, hip_hit_t *peer_hit)
 {
@@ -1022,12 +1134,12 @@
 }
 
 /**
- * .
+ * store a remote host identifier to a host association
  *
- * @param entry ...
- * @param msg for future purposes (KeyNote)
- * @param peer ...
- * @return     ...
+ * @param entry the host association
+ * @param msg unused
+ * @param peer the remote host identifier
+ * @return zero on success and negative on error
  */
 int hip_init_peer(hip_ha_t *entry, struct hip_common *msg,
                   struct hip_host_id *peer)
@@ -1071,9 +1183,7 @@
 }
 
 /**
- * Initializes a HIP association.
- *
- * Initializes a new allocated HIP association @c entry.
+ * Initializes a host association
  *
  * @param  a pointer to a HIP association to be initialized.
  * @param  a pointer to a HIT value that is to be bound with the HIP 
association
@@ -1132,6 +1242,9 @@
 
 /* ----------------- */
 
+/**
+ * initialize the host association database
+ */
 void hip_init_hadb(void)
 {
     /** @todo Check for errors. */
@@ -1238,40 +1351,75 @@
     }
 }
 
+/**
+ * receive a pointer to the default network delivery function pointer
+ * set of a host association
+ *
+ * @return the default function pointer set
+ */
 hip_xmit_func_set_t *hip_get_xmit_default_func_set(void)
 {
     return &default_xmit_func_set;
 }
 
+/**
+ * receive a pointer to the default "misc" function pointer
+ * set of a host association
+ *
+ * @return the default function pointer set
+ */
 hip_misc_func_set_t *hip_get_misc_default_func_set(void)
 {
     return &default_misc_func_set;
 }
 
+/**
+ * receive a pointer to the default input filter function
+ * pointer set of a host association
+ *
+ * @return the default function pointer set
+ */
 hip_input_filter_func_set_t *hip_get_input_filter_default_func_set(void)
 {
     return &default_input_filter_func_set;
 }
 
+/**
+ * receive a pointer to the default output filter function pointer
+ * set of a host association
+ *
+ * @return the default function pointer set
+ */
 hip_output_filter_func_set_t *hip_get_output_filter_default_func_set(void)
 {
     return &default_output_filter_func_set;
 }
 
+/**
+ * receive a pointer to the default preprocessing function pointer
+ * set of a host association
+ *
+ * @return the default function pointer set
+ */
 hip_rcv_func_set_t *hip_get_rcv_default_func_set(void)
 {
     return &default_rcv_func_set;
 }
 
+/**
+ * receive a pointer to the default postprocessing function pointer
+ * set of a host association
+ *
+ * @param entry the host association
+ * @param new_func_set the new function pointer set
+ * @return zero on success and negative on error
+ *
+ */
 hip_handle_func_set_t *hip_get_handle_default_func_set(void)
 {
     return &default_handle_func_set;
 }
 
-/*hip_update_func_set_t *hip_get_update_default_func_set() {
- *      return &default_update_func_set;
- * }*/
-
 /**
  * Sets function pointer set for an hadb record. Pointer values will not be
  * copied!
@@ -1330,15 +1478,15 @@
     return -1;
 }
 
-/* NOTE! When modifying this function, remember that some control values may
- * not be allowed to co-exist. Therefore the logical OR might not be enough
- * for all controls. */
 /**
  * Switches on a local control bit for a host assosiation entry.
  *
  * @param entry a pointer to a host assosiation.
  * @param mask  a bit mask representing the control value.
  * @note  mask is a single mask, not a logical AND or OR mask.
+ * @note When modifying this function, remember that some control values may
+ *       not be allowed to co-exist. Therefore the logical OR might not be 
enough
+ *       for all controls.
  */
 void hip_hadb_set_local_controls(hip_ha_t *entry, hip_controls_t mask)
 {
@@ -1366,15 +1514,15 @@
     }
 }
 
-/* NOTE! When modifying this function, remember that some control values may
- * not be allowed to co-exist. Therefore the logical OR might not be enough
- * for all controls. */
 /**
  * Switches on a peer control bit for a host assosiation entry.
  *
  * @param entry a pointer to a host assosiation.
  * @param mask  a bit mask representing the control value.
  * @note  mask is a single mask, not a logical AND or OR mask
+ * @note When modifying this function, remember that some control values may
+ *       not be allowed to co-exist. Therefore the logical OR might not be 
enough
+ *       for all controls.
  */
 void hip_hadb_set_peer_controls(hip_ha_t *entry, hip_controls_t mask)
 {
@@ -1397,12 +1545,6 @@
         case HIP_HA_CTRL_PEER_REFUSED_RVS:
         case HIP_HA_CTRL_PEER_REFUSED_SAVAH:
         case HIP_HA_CTRL_PEER_REFUSED_FULLRELAY:
-#if 0
-            if (mask == HIP_HA_CTRL_PEER_GRANTED_RELAY) {
-                hip_nat_set_control(entry, 1);
-                HIP_DEBUG("nat control has been reset to 1\n");
-            }
-#endif
             entry->peer_controls |= mask;
             break;
         default:
@@ -1444,26 +1586,23 @@
     hadb_hit = NULL;
 }
 
+/**
+ * flush all security policies
+ *
+ * @todo currently this function is a no-op
+ */
 void hip_delete_all_sp()
 {
-    //struct hip_hit_spi *hs, *tmp_hs;
     HIP_DEBUG("\n");
 
     HIP_DEBUG("DEBUG: DUMP SPI LISTS\n");
 
-    /* I think this is not very safe deallocation.
-     * Locking the hadb_spi and hadb_hit could be one option, but I'm not
-     * very sure that it will work, as they are locked later in
-     * hip_hadb_remove_state() for a while.
-     *
-     * The list traversing is not safe in smp way :(
-     */
     HIP_DEBUG("DELETING HA HT\n");
 }
 
 /**
- * Removes all the addresses from the addresses_to_send_echo_request list
- * and deallocates them.
+ * Remove all the addresses from the addresses_to_send_echo_request list
+ * and deallocate them.
  * @param ha pointer to a host association
  */
 void hip_remove_addresses_to_send_echo_request(hip_ha_t *ha)
@@ -1480,8 +1619,8 @@
 }
 
 /**
- * Deletes a HA state (and deallocate memory) Deletes all associates IPSEC SAs
- * and frees the memory occupied by the HA state.
+ * Delete a HA state (and deallocate memory), all associated IPSEC SAs
+ * and free the memory occupied by the HA state.
  *
  * @param ha HA
  * @note     ASSERT: The HA must be unlinked from the global hadb hash tables
@@ -1557,7 +1696,7 @@
 }
 
 /**
- * Maps function @c func to every HA in HIT hash table. The hash table is
+ * Map function @c func to every HA in HIT hash table. The hash table is
  * LOCKED while we process all the entries. This means that the mapper function
  * MUST be very short and _NOT_ do any operations that might sleep!
  *
@@ -1597,7 +1736,13 @@
     return fail;
 }
 
-/** Enumeration for hip_count_open_connections */
+/**
+ * Enumeration for hip_count_open_connections
+ *
+ * @param entry a host association
+ * @param cntr a counter used for counting open host associations
+ * @return zero
+ */
 static int hip_count_one_entry(hip_ha_t *entry, void *cntr)
 {
     int *counter = cntr;
@@ -1609,7 +1754,9 @@
 }
 
 /**
- * Return number of open connections by calculating hadb entrys.
+ * Return number of open host associations by calculating hadb entrys.
+ *
+ * @return the number of open host associations
  */
 int hip_count_open_connections(void)
 {
@@ -1620,6 +1767,14 @@
     return n;
 }
 
+/**
+ * an enumerator to find information on host associations
+ *
+ * @param entry the host association
+ * @param opaq a preallocated HIP message where information on the given
+ *             host association will be written
+ * @return zero on success and negative on error
+ */
 int hip_handle_get_ha_info(hip_ha_t *entry, void *opaq)
 {
     int err                = 0;
@@ -1656,8 +1811,6 @@
     // HIP_ASSERT(duration != NULL);
     // memcpy(&hid.bex_duration,  duration, sizeof(struct timeval));
 
-
-
     _HIP_HEXDUMP("HEXHID ", &hid, sizeof(struct hip_hadb_user_info_state));
 
     hid.nat_udp_port_peer  = entry->peer_udp_port;
@@ -1685,7 +1838,14 @@
 }
 
 /**
+ * an iterator to map an IP address to a HIT
+ *
+ * @param entry the host association to check for match
+ * @param id2 a HIT of a remote host
+ * @return -1 on match or zero otherwise
+ *
  * @todo We could scan through all of the alternative locators as well
+ * @todo this fails in NATted environments
  */
 int hip_hadb_map_ip_to_hit(hip_ha_t *entry, void *id2)
 {
@@ -1722,7 +1882,6 @@
  * @return           a pointer to a matching host association or NULL if
  *                   a matching host association was not found.
  * @author           Miika Komu
- * @date             31.08.2006
  */
 hip_ha_t *hip_hadb_find_rvs_candidate_entry(hip_hit_t *local_hit,
                                             hip_hit_t *rvs_ip)
@@ -1754,7 +1913,12 @@
 
 #ifdef CONFIG_HIP_BLIND
 /**
- * Defunct
+ * Defunctional. Find a host association based on blinded HITs
+ *
+ * @param local_blind_hit local blinded HIT
+ * @param peer_blind_hit remote blinded HIT
+ * @return the corresponding host association or NULL if not found
+ *
  * @date 22.07.2008
  */
 hip_ha_t *hip_hadb_find_by_blind_hits(hip_hit_t *local_blind_hit,
@@ -1798,23 +1962,15 @@
 
 #endif
 
-static int hip_host_file_info_exists_lsi(hip_lsi_t *lsi)
-{
-    uint8_t hostname[HOST_NAME_MAX];
-    struct in6_addr mapped_lsi;
-
-    memset(hostname, 0, sizeof(hostname));
-
-    IPV4_TO_IPV6_MAP(lsi, &mapped_lsi);
-
-    return !(hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
-                                          
hip_map_first_id_to_hostname_from_hosts,
-                                          &mapped_lsi, hostname) &&
-             hip_for_each_hosts_file_line(HOSTS_FILE,
-                                          
hip_map_first_id_to_hostname_from_hosts,
-                                          &mapped_lsi, hostname));
-}
-
+
+/**
+ * An iterator to find a matching remote LSI from HADB.
+ *
+ * @param entry the host association
+ * @param lsi The LSI to match. Set to zero if a match was found.
+ * @return zero
+ * @note this function overwrites @c lsi, beware!
+ */
 static int hip_hadb_find_lsi(hip_ha_t *entry, void *lsi)
 {
     int exist_lsi;
@@ -1825,6 +1981,12 @@
     return 0;
 }
 
+/**
+ * check if a remote LSI exists in the HADB
+ *
+ * @param lsi the LSI to check
+ * @return one if it exists or zero otherwise
+ */
 static int hip_hadb_exists_lsi(hip_lsi_t *lsi)
 {
     int res = 0;
@@ -1840,19 +2002,32 @@
     return res;
 }
 
-static int lsi_assigned(struct in_addr add)
+/**
+ * check if a remote LSI has been already assigned from
+ * HADB and hosts files
+ *
+ * @param addr the LSI to check
+ * @return one if the LSI exists or zero otherwise
+ */
+static int lsi_assigned(struct in_addr addr)
 {
     int exist = 0;
-    exist = hip_hidb_exists_lsi(&add);
+    exist = hip_hidb_exists_lsi(&addr);
     if (!exist) {
-        exist = hip_hadb_exists_lsi(&add);
+        exist = hip_hadb_exists_lsi(&addr);
     }
     if (!exist) {
-        exist = hip_host_file_info_exists_lsi(&add);
+        exist = hip_host_file_info_exists_lsi(&addr);
     }
     return exist;
 }
 
+/**
+ * allocate a free remote LSI
+ *
+ * @param lsi the LSI will be written here
+ * @return zero
+ */
 int hip_generate_peer_lsi(hip_lsi_t *lsi)
 {
     struct in_addr lsi_prefix;
@@ -1874,11 +2049,14 @@
  * This function simply goes through all HADB to find an entry that
  * matches the given lsi pair. First matching HADB entry is then returned.
  *
+ * @param lsi_src the source LSI
+ * @param lsi_dst the destination LSI
+ * @return the host association corresponding to the LSIs
+ *
  * @note This way of finding HA entries doesn't work properly if we have
  * multiple entries with the same tuple <lsi_src,lsi_dst>. Currently, that's 
not the case.
  * Our implementation doesn't allow repeated lsi tuples.
  */
-
 hip_ha_t *hip_hadb_try_to_find_by_pair_lsi(hip_lsi_t *lsi_src, hip_lsi_t 
*lsi_dst)
 {
     hip_list_t *item, *aux;
@@ -1899,6 +2077,12 @@
     return NULL;
 }
 
+/**
+ * find a remote LSI from from the HADB
+ *
+ * @param lsi_dst the remote LSI
+ * @return the HADB entry or NULL if not found
+ */
 hip_ha_t *hip_hadb_try_to_find_by_peer_lsi(hip_lsi_t *lsi_dst)
 {
     hip_list_t *item, *aux;
@@ -1915,46 +2099,52 @@
     return NULL;
 }
 
+/**
+ * search for the local address used by the host association denoted
+ * by source and destination HITs in a user message
+ *
+ * @param msg a user message containing source and destination HITs
+ * @return zero on success and negative on error
+ */
 int hip_get_local_addr(struct hip_common *msg)
 {
     hip_ha_t *entry;
-    int err;
+    int err = 0;
     struct in6_addr local_address;
     hip_hit_t *src_hit;
     hip_hit_t *dst_hit;
 
-    src_hit = (hip_hit_t *) hip_get_param_contents(msg, HIP_PARAM_HIT);
-    dst_hit = (hip_hit_t *) hip_get_param_contents(msg, HIP_PARAM_IPV6_ADDR);
+    HIP_IFEL(!(src_hit = (hip_hit_t *) hip_get_param_contents(msg, 
HIP_PARAM_HIT)),
+             -1, "No src HIT\n");
+    /** @todo why is this a HIP_PARAM_IPV6_ADDR instead of HIP_PARAM_HIT ? */
+    HIP_IFEL(!(dst_hit = (hip_hit_t *) hip_get_param_contents(msg, 
HIP_PARAM_IPV6_ADDR)),
+             -1, "No dst HIT\n");
     HIP_DEBUG_HIT("src_hit from local address request: ", src_hit);
     HIP_DEBUG_HIT("dst_hit from local address request: ", dst_hit);
-/*if (ptr) {
- *              memcpy(peer_hit, ptr, sizeof(hip_hit_t));
- *              HIP_DEBUG_HIT("peer_hit", peer_hit);
- *fallback = 0;
- *      }
- */
+
     memset(&local_address, 0, sizeof(struct in6_addr));
-    entry = hip_hadb_find_byhits(src_hit, dst_hit);
+    HIP_IFEL(!(entry = hip_hadb_find_byhits(src_hit, dst_hit)),
+             -1, "No HA\n");
 
     hip_msg_init(msg);
-    //HIP_DEBUG_IN6ADDR(" local address: ", &entry->our_addr);
-
-    if (!entry) {
-        HIP_DEBUG("Can't find local address because of no entry in hadb!\n");
-    }
 
     ipv6_addr_copy(&local_address, &entry->our_addr);
 
     //hip_build_user_hdr(msg, HIP_HIPPROXY_LOCAL_ADDRESS, 0);
-    err = hip_build_param_contents(msg, &local_address, HIP_PARAM_IPV6_ADDR,
-                                   sizeof(struct in6_addr));
-    if (err) {
-        HIP_ERROR("Building local address info failed\n");
-    }
-
-    return 0;
+    HIP_IFEL(hip_build_param_contents(msg, &local_address, HIP_PARAM_IPV6_ADDR,
+                                      sizeof(struct in6_addr)), -1,
+                                      "Building local address info failed\n");
+
+ out_err:
+
+    return err;
 }
 
+/**
+ * delete all security policies and associations related to the HA
+ *
+ * @param ha the host association
+ */
 void hip_delete_security_associations_and_sp(struct hip_hadb_state *ha)
 {
     int prev_spi_out = ha->spi_outbound_current;
@@ -1981,6 +2171,14 @@
     return;
 };
 
+/**
+ * recreate the security policies and associations related to a HA
+ *
+ * @param ha the host association
+ * @param src_addr the new source address for the SAs
+ * @param dst_addr the new destination address for the SAs
+ * @return zero on success and negative on error
+ */
 int hip_recreate_security_associations_and_sp(struct hip_hadb_state *ha, 
in6_addr_t *src_addr,
                                               in6_addr_t *dst_addr)
 {

=== modified file 'hipd/hadb.h'
--- hipd/hadb.h 2010-03-19 09:24:10 +0000
+++ hipd/hadb.h 2010-03-19 09:53:35 +0000
@@ -1,18 +1,16 @@
 #ifndef HIP_HIPD_HADB_H
 #define HIP_HIPD_HADB_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "keymat.h"
 #include "lib/tool/pk.h"
 #include "lib/core/debug.h"
-#include "lib/core/misc.h"
+
 #include "hidb.h"
 #include "lib/core/hashtable.h"
 #include "lib/core/state.h"
 #include "lib/core/builder.h"
+#include "lib/core/straddr.h"
 #include "input.h"      // required for declaration of receive functions
 #include "update.h"     // required for declaration of update function
 #include "user_ipsec_sadb_api.h"

=== modified file 'hipd/hadb_legacy.c'
--- hipd/hadb_legacy.c  2010-02-17 17:38:08 +0000
+++ hipd/hadb_legacy.c  2010-03-19 09:53:35 +0000
@@ -1,7 +1,14 @@
 /**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
  * This file contains legacy functions for mobility that should be rewritten 
for modularity.
  * They are still included in the code base due to locator dependencies with 
DHT and
- * base exchange code.
+ * base exchange code. See bugzilla item 926 and 927.
+ *
+ * @author Baris Boyvat
+ * @author Miika Komu <miika@xxxxxx>
  */
 
 /* required for s6_addr32 */

=== modified file 'hipd/hi3.c'
--- hipd/hi3.c  2010-02-17 17:38:08 +0000
+++ hipd/hi3.c  2010-03-19 09:53:35 +0000
@@ -1,3 +1,17 @@
+/** @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * HIP-based Internet Indirection Infrastructure (Hi3) code. This code
+ * can be used to relay HIP-based traffic over i3 infrastructure.
+ * See <a href="http://www.tml.tkk.fi/~pnr/publications/sncnw2004.pdf";>
+ * Nikander et al, Host Identity Indirection Infrastructure (Hi3), Nov 2004</a>
+ * or <a href="http://tools.ietf.org/html/draft-nikander-hiprg-hi3";>
+ * Nikander et al, Host Identity Indirection Infrastructure (Hi3),
+ * June 2004, expired Internet draft</a>.
+ *
+ * @author Andrey Lukyanenko
+ */
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
@@ -20,9 +34,9 @@
 /**
  * The callback for i3 "no matching id" callback.
  *
- * @param ctx_data a pointer to...
- * @param data     a pointer to...
- * @param fun_ctx  a pointer to...
+ * @param ctx_data a pointer to hi3 ID
+ * @param data     a pointer to additional data
+ * @param fun_ctx  a pointer to function's context information (not used)
  * @todo           tkoponen: should this somehow trigger the timeout for 
waiting
  *                 outbound traffic (state machine)?
  */
@@ -34,6 +48,12 @@
     HIP_ERROR("Following ID not found: %s\n", id);
 }
 
+
+/**
+ * hi3 initializing function for hip (called from main module)
+ *
+ * @return 0 on success, terminates program on i3 error
+ */
 int hip_i3_init()
 {
     if (cl_init(HIPL_HI3_FILE) != CL_RET_OK) {
@@ -49,12 +69,19 @@
     return 0;
 }
 
+/**
+ * Adds trigger from defined hip_host_id_entry structure to the list of the 
available triggers hi3_pub_id
+ *
+ * @param entry    a pointer to hip_host_id_entry structure
+ * @param count    a pointer to the number of triggers in hi3_pub_id array
+ * @return 0 on success, negative on the trigger number exceeded
+ */
 static int hip_hi3_add_pub_trigger_id(struct hip_host_id_entry *entry, void 
*count)
 {
     int i = *(int *) count;
     if (i > HI3_TRIGGER_MAX) {
         HIP_ERROR("Trigger number exceeded");
-        return 0;
+        return -1;
     }
 
     bzero(&hi3_pub_id[i], ID_LEN);
@@ -66,6 +93,10 @@
 
 /**
  * This is the i3 callback to process received data.
+ *
+ * @param t  a pointer to cl_trigger (not used right now)
+ * @param data a pointer to data received (including padding in the start and 
end, headers, payload).
+ * @param fun_ctx  a pointer to function's context information (not used)
  */
 static void hip_hi3_receive_payload(void *t, void *data, void *fun_ctx)
 {
@@ -120,8 +151,12 @@
     ;
 }
 
-/*
- * i3 callbacks for trigger management
+/**
+ * i3 callbacks for trigger management (information output)
+ *
+ * @param t a pointer to cl_trigger struct
+ * @param data     a pointer to additional data
+ * @param fun_ctx  a pointer to function's context
  */
 static void hip_hi3_constraint_failed(void *t, void *data, void *fun_ctx)
 {
@@ -129,6 +164,13 @@
     HIP_ERROR("Trigger constraint failed\n");
 }
 
+/**
+ * i3 callbacks for trigger insertion success
+ *
+ * @param t a pointer to cl_trigger struct
+ * @param data     a pointer to additional data
+ * @param fun_ctx  a pointer to function's context
+ */
 static void hip_hi3_trigger_inserted(void *t, void *data, void *fun_ctx)
 {
     char id[100];
@@ -136,9 +178,17 @@
 
     sprintf_i3_id(id, &type->t->id);
 
+    // it should not be error -> info?
     HIP_ERROR("Trigger inserted: %s\n", id);
 }
 
+/**
+ * i3 callbacks for trigger insert failure
+ *
+ * @param t a pointer to cl_trigger struct
+ * @param data     a pointer to additional data
+ * @param fun_ctx  a pointer to function's context
+ */
 static void hip_hi3_trigger_failure(void *t, void *data, void *fun_ctx)
 {
     cl_trigger *type = (cl_trigger *) t;
@@ -150,6 +200,12 @@
     cl_insert_trigger(type, 0);
 }
 
+/**
+ * The function to insert hi3 specific triggers into i3 network. It defines 
all callback functions for every new trigger.
+ * All triggers IDs are selected from array hi3_pri_id and hi3_pub_id.
+ *
+ * @return 0 always
+ */
 static int hip_hi3_insert_trigger(void)
 {
     Key key[HI3_TRIGGER_MAX];
@@ -204,6 +260,12 @@
     return 0;
 }
 
+/**
+ * The function cleans the triggers before exit. It destroys all triggers 
inserted into i3 network
+ * and cleans i3 context information through cl_exit()
+ *
+ * @return 0 always
+ */
 int hip_hi3_clean()
 {
     int i = 0;
@@ -218,6 +280,21 @@
     return 0;
 }
 
+/**
+ * The function makes sure that "right" locators are inserted into HIP i2 
packet, because
+ * the hi3 packets goes indirectly through i3 network, both initiator and 
reponder do not know
+ * about any locators of the other station (use IPv4 or IPv6?). This function 
ensures that the
+ * IPs are used in the right order (priority to IPv6) and that they are used 
correctly (without
+ * it HIP assumes that IP addresses already exist on previous stages I1, R1, 
and it puts address
+ * from database which are zeros).
+ *
+ * @param locator a pointer to hip_locator struct (null if I2 packet missed 
the field).
+ * @param i2_info     a poinjter to info field of I2 packet
+ * @param i2_saddr     a pointer to I2 source address
+ * @param i2_daddr     a pointer to I2 destination address
+ *
+ * @return 0 always
+ */
 int hip_do_i3_stuff_for_i2(struct hip_locator *locator, hip_portpair_t 
*i2_info,
                            in6_addr_t *i2_saddr, in6_addr_t *i2_daddr)
 {

=== modified file 'hipd/hi3.h'
--- hipd/hi3.h  2010-02-17 17:38:08 +0000
+++ hipd/hi3.h  2010-03-19 09:53:35 +0000
@@ -1,10 +1,7 @@
 #ifndef HIP_HIPD_HI3_H
 #define HIP_HIPD_HI3_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "user.h"
 #include "hipd.h"
 #include "lib/core/protodefs.h"

=== modified file 'hipd/hidb.c'
--- hipd/hidb.c 2010-03-19 09:24:10 +0000
+++ hipd/hidb.c 2010-03-19 09:53:35 +0000
@@ -1,6 +1,9 @@
 /**
  * @file
- * HIP host id database and accessors.
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief A database to local Host Identifiers and the related accessor 
functions.
  *
  * @author Janne Lundberg <jlu#tcs.hut.fi>
  * @author Miika Komu <miika#iki.fi>
@@ -12,11 +15,10 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "hidb.h"
+#include "lib/core/hostid.h"
+#include "lib/core/hit.h"
 
 HIP_HASHTABLE *hip_local_hostid_db = NULL;
 #define HIP_MAX_HOST_ID_LEN 1600
@@ -47,6 +49,13 @@
  */
 
 /* Do not access these databases directly: use the accessors in this file. */
+
+/**
+ * hashing function required by hashtable/linked list implementation
+ *
+ * @param ptr a pointer to a hip_host_id_entry structure
+ * @return the calculated hash value
+ */
 unsigned long hip_hidb_hash(const void *ptr)
 {
     hip_hit_t *hit = &(((struct hip_host_id_entry *) ptr)->lhi.hit);
@@ -57,11 +66,23 @@
     return *((unsigned long *) (void *) hash);
 }
 
+/**
+ * matching function required by hashtable/linked list implementation
+ *
+ * @param ptr1 a pointer to hip_host_id_entry
+ * @param ptr2 a pointer to hip_host_id_entry
+ * @return zero on match or non-zero on unmatch
+ */
 int hip_hidb_match(const void *ptr1, const void *ptr2)
 {
     return hip_hidb_hash(ptr1) != hip_hidb_hash(ptr2);
 }
 
+/**
+ * initialize host identity database
+ *
+ * @param db A double pointer to a hip_db_struct_t. Caller deallocates.
+ */
 void hip_init_hostid_db(hip_db_struct_t **db)
 {
     hip_local_hostid_db = hip_ht_init(hip_hidb_hash, hip_hidb_match);
@@ -188,12 +209,26 @@
     return NULL;
 }
 
+
+/**
+ * test if a given HIT belongs to the local host
+ *
+ * @param our the hit to be tested
+ * @return one if the HIT belongs to the local host or zero otherwise
+ */
 int hip_hidb_hit_is_our(const hip_hit_t *our)
 {
     return hip_get_hostid_entry_by_lhi_and_algo(hip_local_hostid_db, our,
                                                 HIP_ANY_ALGO, -1) != NULL;
 }
 
+/**
+ * map a local HIT to a local LSI from the local host identifier database
+ *
+ * @param our a local HIT
+ * @param our_lsi the mapped LSI
+ * @return zero on success or non-zero on failure
+ */
 int hip_hidb_get_lsi_by_hit(const hip_hit_t *our, hip_lsi_t *our_lsi)
 {
     struct hip_host_id_entry *id_entry;
@@ -228,7 +263,7 @@
  */
 
 /**
- * Deletes both host id databases
+ * Delete host id databases
  */
 void hip_uninit_host_id_dbs(void)
 {
@@ -487,56 +522,11 @@
     return err;
 }
 
-#if 0
 /**
- * Returns pointer to newly allocated area that contains a localhost HI. NULL
- * is returned if problems are encountered.
+ * Strips a public key out of DSA a host id with private key component
  *
- * @param db   a pointer to a database.
- * @param lhi  HIT to match, if null, any.
- * @param algo algorithm to match, if HIP_ANY_ALGO, any.
- * @note       Remember to free the host id structure after use.
- */
-static struct hip_host_id *hip_get_host_id(hip_db_struct_t *db,
-                                           struct in6_addr *hit, int algo)
-{
-    struct hip_host_id_entry *tmp = NULL;
-    struct hip_host_id *result    = NULL;
-    int t                         = 0;
-
-    HIP_READ_LOCK_DB(db);
-
-    tmp = hip_get_hostid_entry_by_lhi_and_algo(db, hit, algo, -1);
-    if (!tmp) {
-        HIP_READ_UNLOCK_DB(db);
-        HIP_ERROR("No host ID found.\n");
-        return NULL;
-    }
-
-    t = hip_get_param_total_len(tmp->host_id);
-    _HIP_DEBUG("Host ID length is %d bytes.\n", t);
-    if (t > HIP_MAX_HOST_ID_LEN) {
-        HIP_READ_UNLOCK_DB(db);
-        return NULL;
-    }
-
-    result = HIP_MALLOC(t, GFP_ATOMIC);
-    if (!result) {
-        HIP_READ_UNLOCK_DB(db);
-        HIP_ERROR("Out of memory.\n");
-        return NULL;
-    }
-
-    memcpy(result, tmp->host_id, t);
-    HIP_READ_UNLOCK_DB(db);
-
-    return result;
-}
-
-#endif
-
-/**
- * Resolves a public key out of DSA a host id.
+ * @param hi the host identifier with its private key component
+ * @return An allocated hip_host_id structure. Caller must deallocate.
  */
 static struct hip_host_id *hip_get_dsa_public_key(const struct 
hip_host_id_priv *hi)
 {
@@ -569,33 +559,12 @@
     return ret;
 }
 
-#if 0
-/**
- * .
- *
- * @return a newly allocated area that contains the public key part of the
- * localhost host identity. NULL is returned if errors detected.
- * @note Remember to free the return value.
- */
-static struct hip_host_id *hip_get_any_localhost_dsa_public_key(void)
-{
-    struct hip_host_id *res;
-
-    res = hip_get_host_id(hip_local_hostid_db, NULL, HIP_HI_DSA);
-    if (!res) {
-        HIP_ERROR("No host id for localhost\n");
-    }
-
-    return res;
-}
-
-#endif
-
-/**
- * Gets the RSA public key from a Host Identity
+/**
+ * Strips the RSA public key from a Host Identity
  *
  * @param tmp a pointer to a Host Identity.
- * @return    a pointer to a newly allocated host identity with only the 
public key
+ * @return    A pointer to a newly allocated host identity with only the 
public key.
+ *            Caller deallocates.
  */
 static struct hip_host_id *hip_get_rsa_public_key(const struct 
hip_host_id_priv *tmp)
 {
@@ -621,28 +590,6 @@
     return ret;
 }
 
-#if 0
-/**
- * .
- *
- * @return a newly allocated area that contains the public key part of the
- *         localhost host identity. %NULL is returned if errors detected.
- * @note   Remember to free the return value.
- */
-static struct hip_host_id *hip_get_any_localhost_rsa_public_key(void)
-{
-    struct hip_host_id *res;
-
-    res = hip_get_host_id(hip_local_hostid_db, NULL, HIP_HI_RSA);
-    if (!res) {
-        HIP_ERROR("No host id for localhost\n");
-    }
-
-    return res;
-}
-
-#endif
-
 /**
  * Transforms a private/public key pair to a public key, private key is 
deleted.
  *
@@ -665,7 +612,7 @@
 }
 
 /**
- * Adds a free lsi to the entry
+ * Assign a free LSI to a host id entry
  *
  * @param db database structure
  * @param id_entry contains an entry to the db, will contain an unsigned lsi
@@ -701,9 +648,9 @@
 }
 
 /**
- * Search if the lsi exists already in the hidb
+ * Search if a local lsi exists already in the hidb
  *
- * @param lsi lsi we are searching
+ * @param lsi the local lsi we are searching
  * @return 0 if it's not in the hidb, 1 if it is
  */
 int hip_hidb_exists_lsi(hip_lsi_t *lsi)
@@ -722,7 +669,7 @@
 }
 
 /**
- * Lists every hit in the database.
+ * Lists every local hit in the database.
  *
  * @param func   a mapper function.
  * @param opaque opaque data for the mapper function.
@@ -755,6 +702,13 @@
     return err;
 }
 
+/**
+ * find the local host identifier corresponding to the local LSI
+ *
+ * @param db the local host identifier database to be searched for
+ * @param lsi the local LSI to be matched
+ * @return the local host identifier structure
+ */
 static struct hip_host_id_entry *hip_hidb_get_entry_by_lsi(hip_db_struct_t *db,
                                                            const struct 
in_addr *lsi)
 {
@@ -771,6 +725,13 @@
     return NULL;
 }
 
+/**
+ * associate the given local LSI to the local host identifier denoted by the 
given HIT
+ *
+ * @param default_hit the HIT to be searched for
+ * @param the LSI to associate with
+ * @return zero on success or negative on error
+ */
 int hip_hidb_associate_default_hit_lsi(hip_hit_t *default_hit, hip_lsi_t 
*default_lsi)
 {
     int err = 0;
@@ -801,6 +762,15 @@
 }
 
 //#ifdef CONFIG_HIP_BLIND
+
+/**
+ * find the blinded local host identifier from the HIDB
+ *
+ * @param nonce the nonce used to blind the HIT
+ * @param test_hit the blinded HIT
+ * @param local_hit the unblinded HIT will be copied here
+ * @return zero on success or negative on error
+ */
 int hip_blind_find_local_hi(uint16_t *nonce,  struct in6_addr *test_hit,
                             struct in6_addr *local_hit)
 {
@@ -855,6 +825,16 @@
 
 //#endif
 
+/**
+ * find a host identifier from the database
+ *
+ * @param db the host identifier databased
+ * @param hit the HIT to be searched for
+ * @param algo the algorithm for the HI
+ * @param host_id A copy of the host is stored here. Caller deallocates.
+ * @param key a pointer to the private key (caller should not deallocate)
+ * @return zero on success or negative on error
+ */
 int hip_get_host_id_and_priv_key(hip_db_struct_t *db, struct in6_addr *hit,
                                  int algo, struct hip_host_id **host_id, void 
**key)
 {
@@ -882,6 +862,13 @@
     return err;
 }
 
+/**
+ * append a HOST id parameter and signature into the message to be sent on the 
wire
+ *
+ * @param msg the msg where the host id and signature should be appended
+ * @param hit the local HIT corresding to the host id
+ * @return zero on success or negative on error
+ */
 int hip_build_host_id_and_signature(struct hip_common *msg,  hip_hit_t *hit)
 {
     struct hip_host_id *hi_public = NULL;
@@ -934,28 +921,50 @@
     return err;
 }
 
+/**
+ * get the default HIT of the local host
+ *
+ * @param hit the local default HIT will be written here
+ * @return zero on success or negative on error
+ */
 int hip_get_default_hit(struct in6_addr *hit)
 {
     return hip_get_any_localhost_hit(hit, HIP_HI_RSA, 0);
 }
 
-/* TDOD; This function has no error handling at all. Check if this is ok */
+/**
+ * get the default HIT of the local host and write into a
+ * user message
+ *
+ * @param msg the message where the HIT will be written
+ * @return zero on success or negative on error
+ */
 int hip_get_default_hit_msg(struct hip_common *msg)
 {
     int err = 0;
     hip_hit_t hit;
     hip_lsi_t lsi;
 
-    hip_get_default_hit(&hit);
-    hip_get_default_lsi(&lsi);
+    HIP_IFE(hip_get_default_hit(&hit), -1);
+    HIP_IFE(hip_get_default_lsi(&lsi), -1);
     HIP_DEBUG_HIT("Default hit is ", &hit);
     HIP_DEBUG_LSI("Default lsi is ", &lsi);
-    hip_build_param_contents(msg, &hit, HIP_PARAM_HIT, sizeof(hit));
-    hip_build_param_contents(msg, &lsi, HIP_PARAM_LSI, sizeof(lsi));
+    HIP_IFE(hip_build_param_contents(msg, &hit, HIP_PARAM_HIT, sizeof(hit)),
+            -1);
+    HIP_IFE(hip_build_param_contents(msg, &lsi, HIP_PARAM_LSI, sizeof(lsi)),
+            -1);
+
+ out_err:
 
     return err;
 }
 
+/**
+ * get the default LSI of the local host
+ *
+ * @param lsi the default LSI will be written here
+ * @return zero on success or negative on error
+ */
 int hip_get_default_lsi(struct in_addr *lsi)
 {
     int err                       = 0, family = AF_INET;

=== modified file 'hipd/hipd.c'
--- hipd/hipd.c 2010-03-03 13:16:18 +0000
+++ hipd/hipd.c 2010-03-19 09:53:35 +0000
@@ -10,12 +10,11 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "hipd.h"
 #include "lib/dht/libhipdht.h"
+#include "lib/core/filemanip.h"
+#include "lib/core/straddr.h"
 #include "heartbeat.h"
 
 #ifdef CONFIG_HIP_PERFORMANCE
@@ -178,105 +177,10 @@
 
 HIP_HASHTABLE *bex_timestamp_db = NULL;
 
-void hip_set_opportunistic_tcp_status(struct hip_common *msg)
-{
-    struct sockaddr_in6 sock_addr;
-    int retry, type, n;
-
-    type = hip_get_msg_type(msg);
-
-    _HIP_DEBUG("type=%d\n", type);
-
-    memset(&sock_addr, 0, sizeof(sock_addr));
-    sock_addr.sin6_family = AF_INET6;
-    sock_addr.sin6_port   = htons(HIP_FIREWALL_PORT);
-    sock_addr.sin6_addr   = in6addr_loopback;
-
-    for (retry = 0; retry < 3; retry++) {
-        /* Switched from hip_sendto() to hip_sendto_user() due to
-         * namespace collision. Both message.h and user.c had functions
-         * hip_sendto(). Introducing a prototype hip_sendto() to user.h
-         * led to compiler errors --> user.c hip_sendto() renamed to
-         * hip_sendto_user().
-         *
-         * Lesson learned: use function prototypes unless functions are
-         * ment only for local (inside the same file where defined) use.
-         * -Lauri 11.07.2008 */
-        n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr);
-        if (n <= 0) {
-            HIP_ERROR("hipconf opptcp failed (round %d)\n", retry);
-            HIP_DEBUG("Sleeping few seconds to wait for fw\n");
-            sleep(2);
-        } else {
-            HIP_DEBUG("hipconf opptcp ok (sent %d bytes)\n", n);
-            break;
-        }
-    }
-
-    if (type == SO_HIP_SET_OPPTCP_ON) {
-        hip_use_opptcp = 1;
-    } else {
-        hip_use_opptcp = 0;
-    }
-
-    HIP_DEBUG("Opportunistic tcp set %s\n",
-              (hip_use_opptcp ? "on" : "off"));
-}
-
-int hip_get_opportunistic_tcp_status()
-{
-    return hip_use_opptcp;
-}
-
-/* hi3 */
-#ifdef CONFIG_HIP_I3
-void hip_set_hi3_status(struct hip_common *msg)
-{
-    struct sockaddr_in6 sock_addr;
-    int retry, type, n;
-
-    type = hip_get_msg_type(msg);
-
-    _HIP_DEBUG("type=%d\n", type);
-
-    bzero(&sock_addr, sizeof(sock_addr));
-    sock_addr.sin6_family = AF_INET6;
-    sock_addr.sin6_port   = htons(HIP_FIREWALL_PORT);
-    sock_addr.sin6_addr   = in6addr_loopback;
-
-    for (retry = 0; retry < 3; retry++) {
-        n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr);
-        if (n <= 0) {
-            HIP_ERROR("hipconf hi3 failed (round %d)\n", retry);
-            HIP_DEBUG("Sleeping few seconds to wait for fw\n");
-            sleep(2);
-        } else {
-            HIP_DEBUG("hipconf hi3 ok (sent %d bytes)\n", n);
-            break;
-        }
-    }
-
-    if (type == SO_HIP_SET_HI3_ON) {
-        hip_i3_init();
-        hip_use_hi3        = 1;
-        hip_locator_status = SO_HIP_SET_LOCATOR_ON;
-    } else {
-        hip_locator_status = SO_HIP_SET_LOCATOR_OFF;
-        hip_hi3_clean();
-        hip_use_hi3        = 0;
-    }
-
-    HIP_DEBUG("hi3 set %s\n",
-              (hip_use_hi3 ? "on" : "off"));
-}
-
-int hip_get_hi3_status()
-{
-    return hip_use_hi3;
-}
-
-#endif
-
+
+/**
+ * print hipd usage instructions on stderr
+ */
 static void usage(void)
 {
     fprintf(stderr, "Usage: hipd [options]\n\n");
@@ -289,6 +193,12 @@
     fprintf(stderr, "\n");
 }
 
+/**
+ * a function for passing a message to the HIP graphical user agent
+ *
+ * @param msg the message to send
+ * @return zero on success or negative on error
+ */
 int hip_send_agent(struct hip_common *msg)
 {
     struct sockaddr_in6 hip_agent_addr;
@@ -336,6 +246,9 @@
 
 /**
  * Receive message from agent socket.
+ *
+ * @param msg the received message will be stored here
+ * @return zero on success or negative on error
  */
 int hip_recv_agent(struct hip_common *msg)
 {
@@ -406,6 +319,12 @@
     return err;
 }
 
+/**
+ * send a message to the HIP firewall
+ *
+ * @param msg the message to send
+ * @return zero on success or negative on error
+ */
 int hip_sendto_firewall(const struct hip_common *msg)
 {
 #ifdef CONFIG_HIP_FIREWALL
@@ -433,7 +352,11 @@
 }
 
 /**
- * Daemon main function.
+ * Daemon "main" function.
+ *
+ * @param argc number of command line arguments
+ * @param argv the command line arguments
+ * @return zero on success or negative on error
  */
 static int hipd_main(int argc, char *argv[])
 {
@@ -802,10 +725,13 @@
             if (FD_ISSET(hip_opendht_sock_fqdn, &read_fdset) &&
                 FD_ISSET(hip_opendht_sock_fqdn, &write_fdset) &&
                 (hip_opendht_inuse == SO_HIP_DHT_ON)) {
-                /* Error with the connect */
-                HIP_ERROR("Error OpenDHT socket is readable and writable\n");
+                HIP_DEBUG("DHT socket waiting for connect (readable and 
writable)\n");
             } else if (FD_ISSET(hip_opendht_sock_fqdn, &write_fdset)) {
-                hip_opendht_fqdn_sent = STATE_OPENDHT_START_SEND;
+                if (address_count == 0) {
+                    HIP_DEBUG("No addresses do not go to the next state\n");
+                } else {
+                    hip_opendht_fqdn_sent = STATE_OPENDHT_START_SEND;
+                }
             }
             if (FD_ISSET(hip_opendht_sock_fqdn, &read_fdset) &&
                 (hip_opendht_inuse == SO_HIP_DHT_ON)) {
@@ -834,10 +760,13 @@
             if (FD_ISSET(hip_opendht_sock_hit, &read_fdset) &&
                 FD_ISSET(hip_opendht_sock_hit, &write_fdset) &&
                 (hip_opendht_inuse == SO_HIP_DHT_ON)) {
-                /* Error with the connect */
-                HIP_ERROR("Error OpenDHT socket is readable and writable\n");
+                HIP_ERROR("DHT socket waiting for connect (readable and 
writable)\n\n");
             } else if (FD_ISSET(hip_opendht_sock_hit, &write_fdset)) {
-                hip_opendht_hit_sent = STATE_OPENDHT_START_SEND;
+                if (address_count == 0) {
+                    HIP_DEBUG("No addresses do not go to the next state\n");
+                } else {
+                    hip_opendht_hit_sent = STATE_OPENDHT_START_SEND;
+                }
             }
             if ((FD_ISSET(hip_opendht_sock_hit, &read_fdset)) &&
                 (hip_opendht_inuse == SO_HIP_DHT_ON)) {
@@ -904,6 +833,13 @@
     return err;
 }
 
+/**
+ * the main function for hipd
+ *
+ * @param argc number of command line arguments
+ * @param argv the command line arguments
+ * @return zero on success or negative on error
+ */
 int main(int argc, char *argv[])
 {
     int err = 0;

=== modified file 'hipd/hipd.h'
--- hipd/hipd.h 2010-02-17 17:38:08 +0000
+++ hipd/hipd.h 2010-03-19 09:53:35 +0000
@@ -13,10 +13,7 @@
 #include <netinet/udp.h>
 #include <sys/socket.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/crypto.h"
 #include "cookie.h"
 #include "user.h"
@@ -76,8 +73,6 @@
 #define HIP_SIMULATE_PACKET_LOSS_PROBABILITY 0
 #define HIP_SIMULATE_PACKET_IS_LOST() (random() < ((uint64_t) 
HIP_SIMULATE_PACKET_LOSS_PROBABILITY * RAND_MAX) / 100)
 
-#define HIP_NETLINK_TALK_ACK 0 /* see netlink_talk */
-
 #define HIP_ADDRESS_CHANGE_WAIT_INTERVAL 6 /* seconds */
 #define HIP_ADDRESS_CHANGE_HB_COUNT_TRIGGER 2
 
@@ -182,19 +177,10 @@
 
 //int hip_sendto(const struct hip_common *msg, const struct sockaddr_in6 *dst);
 
-#ifdef CONFIG_HIP_I3
-int hip_get_hi3_status( void );
-void hip_set_hi3_status(struct hip_common *msg);
-#endif /* CONFIG_HIP_I3 */
-
-void hip_set_opportunistic_tcp_status(struct hip_common *msg);
-int hip_get_opportunistic_tcp_status(void);
 int hip_send_agent(struct hip_common *msg);
 int hip_recv_agent(struct hip_common *msg);
 
 /* Functions for handling outgoing packets. */
 int hip_sendto_firewall(const struct hip_common *msg);
 
-#define IPV4_HDR_SIZE 20
-
 #endif /* HIP_HIPD_HIPD_H */

=== modified file 'hipd/hiprelay.c'
--- hipd/hiprelay.c     2010-03-03 13:16:18 +0000
+++ hipd/hiprelay.c     2010-03-19 09:53:35 +0000
@@ -1,8 +1,67 @@
 /** @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
  * This file defines the rendezvous extension and the UDP relay for HIP packets
  * for the Host Identity Protocol (HIP). See header file for usage
- * instructions. Version 1.1 added support for white list and configuration
- * file.
+ * instructions. Supports access control in the form in white lists in
+ * the /etc/hip/relay_config file.
+ *
+ * The HIP relay combines the functionalites of an rendezvous server (RVS) and
+ * a HIP UDP relay. The HIP relay consists of a hashtable for storing IP 
address
+ * to HIT mappings and of functions that do the actual relaying action. The
+ * hashtable is based on lhash library and its functionalites are the same
+ * except that the HIP relay stores data (allocated memory for relay records)
+ * instead of pointers.
+ *
+ * A few simple rules apply:
+ * <ul>
+ * <li>Allocate memory for relay records that are to be put into the hashtable
+ * only with hip_relrec_alloc().</li>
+ * <li>Once a relay record is <b>successfully</b> put into the hashtable, the
+ * only way delete it is to call hip_relht_rec_free(). This will remove the
+ * entry from the hashtable and free the memory allocated for the relay record.
+ * </li>
+ * </ul>
+ *
+ * Usage:
+ * <ul>
+ * <li>Inserting a new relay record:
+ * <pre>
+ * hip_relrec_t rr = hip_relrec_alloc(...);
+ * hip_relht_put(rr);
+ * if(hip_relht_get(rr) == NULL) // The put was unsuccessful.
+ * {
+ *   if(rr != NULL)
+ *     free(rr);
+ * }
+ * </pre>
+ * </li>
+ * <li>Fetching a relay record. We do not need (but can use) a fully populated
+ * relay record as a search key. A dummy record with hit_r field populated
+ * is sufficient. Note that there is no need to re-put the relay record into 
the
+ * hashtable once it has been succesfully inserted into the hashtable - except
+ * if we change the hit_r field of the relay record. If a relay record with 
same
+ * HIT is put into the hashtable, the existing element is deleted.
+ *
+ * <pre>
+ * hip_relrec_t dummy, *fetch_record = NULL;
+ * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit));
+ * fetch_record = hip_relht_get(&dummy);
+ * if(fetch_record != NULL)
+ * {
+ * // Do something with the record.
+ * }
+ * </pre>
+ * </li>
+ * <li>Deleting a relay record. A dummy record can be used:
+ * <pre>
+ * hip_relrec_t dummy;
+ * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit));
+ * hip_relht_rec_free(&dummy);
+ * </pre>
+ * </li>
+ * </ul>
  *
  * @author  Lauri Silvennoinen
  * @note    Related RFC: <a href="http://www.rfc-editor.org/rfc/rfc5204.txt";>
@@ -11,17 +70,17 @@
  *          <a 
href="http://www.ietf.org/internet-drafts/draft-ietf-hip-nat-traversal-03.txt";>
  *          draft-ietf-hip-nat-traversal-03</a>
  * @note    Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
- * @see     hiprelay.h
+ * @note    Related RFC: <a href="http://www.rfc-editor.org/rfc/rfc5204.txt";>
+ *          Host Identity Protocol (HIP) Rendezvous Extension</a>
  */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "hiprelay.h"
+#include "output.h"
+#include "lib/core/hip_udp.h"
 
 /** HIP relay config file default content. If the file @c HIP_RELAY_CONFIG_FILE
  *  cannot be opened for reading, we write a new config file from scratch using
@@ -88,125 +147,25 @@
  */
 hip_relay_wl_status_t whitelist_enabled = HIP_RELAY_WL_ON;
 
-/**
- * Initializes the global HIP relay hashtable. Allocates memory for
- * @c hiprelay_ht.
- *
- * @return zero on success, -1 otherwise.
- * @note   do not call this function directly, instead call hip_relay_init().
- */
+/* forward declarations */
 static int hip_relht_init(void);
-
-/**
- * Uninitializes the HIP relay record hashtable @c hiprelay_ht. Frees the 
memory
- * allocated for the hashtable and for the relay records. Thus, after calling
- * this function, all memory allocated from the heap related to the relay 
record
- * hashtable is free.
- *
- * @note do not call this function directly, instead call hip_relay_uninit().
- */
 static void hip_relht_uninit(void);
-
-/**
- * Deletes a single entry from the relay record hashtable and frees the memory
- * allocated for the record, if the record has expired. The relay record is
- * deleted if it has been last contacted more than @c hiprelay_lifetime seconds
- * ago. If the parameter relay record is the same record that is being deleted
- * (i.e. is located in the same memory location) then the parameter @c rec
- * itself is freed. If a dummy record is used (i.e. is located in a different
- * memory location thatn the hashtable entry), then @c rec is left untouched.
- *
- * @param rec a pointer to a relay record.
- */
 static void hip_relht_rec_free_expired_doall(hip_relrec_t *rec);
-
-/**
- * Initializes the global HIP relay whitelist. Allocates memory for
- * @c hiprelay_wl.
- *
- * @return zero on success, -1 otherwise.
- * @note   do not call this function directly, instead call hip_relay_init().
- */
 static int hip_relwl_init(void);
-
-/**
- * Uninitializes the HIP relay whitelist hashtable @c hiprelay_wl. Frees the
- * memory allocated for the hashtable and for the HITs. Thus, after calling
- * this function, all memory allocated from the heap related to the whitelist
- * is free.
- *
- * @note do not call this function directly, instead call hip_relay_uninit().
- */
 static void hip_relwl_uninit(void);
-
-
-/**
- * Puts a HIT into the whitelist. Puts the HIT pointed by @c hit into the
- * whitelist hashtable @c hiprelay_wl. If there already is an entry with the
- * same HIT, the old value is replaced, and <b>the memory allocated for the
- * existing element is freed</b>. Note that we store pointers here, the data 
are
- * not copied.
- *
- * @param hit a pointer to a HIT to be inserted into the whitelist.
- * @return    -1 if there was a hash collision i.e. a duplicate HIT is 
inserted,
- *            zero otherwise.
- * @note      <b style="color: #f00;">Do not put HITs allocated from the stack
- *            into the whitelist.</b> Instead put only HITs created with
- *            malloc().
- * @note      In case of a hash collision, the existing HIT is freed. If you
- *            store references to HITs that are in the whitelist elsewhere
- *            outside the whitelist, NULL pointers can result.
- */
 static int hip_relwl_put(hip_hit_t *hit);
-
-/**
- * Deletes a single entry from the whitelist hashtable and frees the memory
- * allocated for the element. The parameter HIT is itself left untouched, it is
- * only used as an search key.
- *
- * @param hit a pointer to a HIT.
- */
 static void hip_relwl_hit_free_doall(hip_hit_t *hit);
-
-/**
- * Reads RVS / HIP Relay configuration from a file. Reads configuration
- * information from @c HIP_RELAY_CONFIG_FILE.
- *
- * @return zero on success, -ENOENT if the file could not be opened for 
reading.
- * @note   The white list @c hiprelay_wl must be initialized before this
- *         function is called.
- */
 static int hip_relay_read_config(void);
-
-/**
- * Writes RVS / HIP Relay configuration file with default content. Writes a RVS
- * / HIP Relay configuration file to @c HIP_RELAY_CONFIG_FILE. The file is
- * opened with "w" argument mode, which means that a possibly existing file is
- * truncated to zero length.
- *
- * @return zero on success, -ENOENT if the file could not be opened for 
writing.
- * @note   Truncates existing file to zero length.
- */
 static int hip_relay_write_config(void);
-
-/**
- * The hash function of the @c hiprelay_ht hashtable. Calculates a hash from
- * parameter relay record HIT.
- *
- * @param rec a pointer to a relay record.
- * @return    the calculated hash or zero if @c rec or hit_r is NULL.
- */
 static unsigned long hip_relht_hash(const hip_relrec_t *rec);
-
-/**
- * The hash function of the @c hiprelay_wl hashtable. Calculates a hash from
- * parameter HIT.
- *
- * @param hit a pointer to a HIT.
- * @return    the calculated hash or zero if @c hit is NULL.
- */
 static unsigned long hip_relwl_hash(const hip_hit_t *hit);
-
+static int hip_relay_forward_response(const hip_common_t *r,
+                                      const uint8_t type_hdr,
+                                      const in6_addr_t *r_saddr,
+                                      const in6_addr_t *r_daddr,
+                                      const hip_portpair_t *r_info,
+                                      const in6_addr_t *relay_to_addr,
+                                      const in_port_t relay_to_port);
 /**
  * Returns a hash calculated over a HIT.
  *
@@ -244,15 +203,19 @@
     return hash;
 }
 
-static int hip_relay_forward_response(const hip_common_t *r,
-                                      const uint8_t type_hdr,
-                                      const in6_addr_t *r_saddr,
-                                      const in6_addr_t *r_daddr,
-                                      const hip_portpair_t *r_info,
-                                      const in6_addr_t *relay_to_addr,
-                                      const in_port_t relay_to_port);
-
-
+/**
+ * Deletes a single entry from the relay record hashtable and frees the memory
+ * allocated for the element if the matching element's type is of @c type. The
+ * deletion is based on the hash calculated from the relay fecord
+ * @c hit_r field, and therefore the parameter record does not need to be fully
+ * populated. If the parameter relay record is the same record that is being
+ * deleted (i.e. is located in the same memory location) then the parameter
+ * @c rec itself is freed. If a dummy record is used (i.e. is located in a
+ * different memory location thatn the hashtable entry), then @c rec is left
+ * untouched.
+ *
+ * @param rec a pointer to a relay record.
+ */
 static void hip_relht_rec_free_type_doall_arg(hip_relrec_t *rec, const 
hip_relrec_type_t *type)
 {
     hip_relrec_t *fetch_record = hip_relht_get(rec);
@@ -265,16 +228,34 @@
 /** A callback wrapper of the prototype required by @c lh_doall_arg(). */
 static IMPLEMENT_LHASH_DOALL_ARG_FN(hip_relht_rec_free_type, hip_relrec_t, 
hip_relrec_type_t)
 
+/**
+ * Returns relay status.
+ *
+ * @return HIP_RELAY_ON if the RVS / relay is "on", HIP_RELAY_OFF otherwise.
+ */
 hip_relay_status_t hip_relay_get_status()
 {
     return relay_enabled;
 }
 
+/**
+ * Sets the status of the RVS / relay. Sets the relay "on" or "off".
+ *
+ * @param status zero if the relay is to be disabled, anything else to enable
+ *               the relay.
+ */
 void hip_relay_set_status(hip_relay_status_t status)
 {
     relay_enabled = status;
 }
 
+/**
+ * The hash function of the @c hiprelay_ht hashtable. Calculates a hash from
+ * parameter relay record HIT.
+ *
+ * @param rec a pointer to a relay record.
+ * @return    the calculated hash or zero if @c rec or hit_r is NULL.
+ */
 static unsigned long hip_relht_hash(const hip_relrec_t *rec)
 {
     if (rec == NULL || &(rec->hit_r) == NULL) {
@@ -287,6 +268,13 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_HASH_FN(hip_relht, const hip_relrec_t)
 
+/**
+ * relay hash table comparison function
+ *
+ * @param rec1 a hip_relrec_t structure
+ * @param rec2 a hip_relrec_t structure
+ * @return zero if the structures are equal or one otherwise
+ */
 static int hip_relht_cmp(const hip_relrec_t *rec1, const hip_relrec_t *rec2)
 {
     if (rec1 == NULL || &(rec1->hit_r) == NULL ||
@@ -300,6 +288,26 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_COMP_FN(hip_relht, const hip_relrec_t)
 
+/**
+ * Puts a relay record into the hashtable. Puts the relay record pointed by
+ * @c rec into the hashtable @c hiprelay_ht. If there already is an entry with
+ * the same key the old value is replaced, and <b>the memory allocated for the
+ * existing element is freed</b>. Note that we store pointers here, the data 
are
+ * not copied. There should be no need to put a relay record more than once 
into
+ * the hashtable. If the fields of an individual relay record need to be
+ * changed, just retrieve the record with @c hip_relht_get() and alter the
+ * fields of it, but do not re-put it into the hashtable.
+ *
+ * @param rec a pointer to a relay record to be inserted into the hashtable.
+ * @return    -1 if there was a hash collision i.e. an entry with duplicate HIT
+ *            is inserted, zero otherwise.
+ * @note      <b style="color: #f00;">Do not put records allocated from stack
+ *            into the hashtable.</b> Instead put only records created with
+ *            hip_relrec_alloc().
+ * @note      In case of a hash collision, the existing relay record is freed.
+ *            If you store references to relay records that are in the 
hashtable
+ *            elsewhere outside the hashtable, NULL pointers can result.
+ */
 int hip_relht_put(hip_relrec_t *rec)
 {
     hip_relrec_t key, *match;
@@ -325,6 +333,14 @@
     }
 }
 
+/**
+ * Retrieves a relay record from the hashtable @c hiprelay_ht. The parameter
+ * record @c rec only needs to have field @c hit_r populated.
+ *
+ * @param rec a pointer to a relay record.
+ * @return    a pointer to a fully populated relay record if found, NULL
+ *            otherwise.
+ */
 hip_relrec_t *hip_relht_get(const hip_relrec_t *rec)
 {
     if (hiprelay_ht == NULL || rec == NULL) {
@@ -334,6 +350,18 @@
     return (hip_relrec_t *) list_find(rec, hiprelay_ht);
 }
 
+/**
+ * Deletes a single entry from the relay record hashtable and frees the memory
+ * allocated for the element. The deletion is based on the hash calculated from
+ * the relay fecord @c hit_r field, and therefore the parameter record does not
+ * need to be fully populated. If the parameter relay record is the same record
+ * that is being deleted (i.e. is located in the same memory location) then
+ * the parameter @c rec itself is freed. If a dummy record is used (i.e. is
+ * located in a different memory location thatn the hashtable entry), then
+ * @c rec is left untouched.
+ *
+ * @param rec a pointer to a relay record.
+ */
 void hip_relht_rec_free_doall(hip_relrec_t *rec)
 {
     if (hiprelay_ht == NULL || rec == NULL) {
@@ -356,6 +384,17 @@
 /** A callback wrapper of the prototype required by @c lh_doall(). */
 static IMPLEMENT_LHASH_DOALL_FN(hip_relht_rec_free, hip_relrec_t)
 
+/**
+ * Deletes a single entry from the relay record hashtable and frees the memory
+ * allocated for the record, if the record has expired. The relay record is
+ * deleted if it has been last contacted more than @c hiprelay_lifetime seconds
+ * ago. If the parameter relay record is the same record that is being deleted
+ * (i.e. is located in the same memory location) then the parameter @c rec
+ * itself is freed. If a dummy record is used (i.e. is located in a different
+ * memory location thatn the hashtable entry), then @c rec is left untouched.
+ *
+ * @param rec a pointer to a relay record.
+ */
 static void hip_relht_rec_free_expired_doall(hip_relrec_t *rec)
 {
     if (rec == NULL) {  // No need to check hiprelay_ht
@@ -371,6 +410,11 @@
 /** A callback wrapper of the prototype required by @c lh_doall(). */
 static IMPLEMENT_LHASH_DOALL_FN(hip_relht_rec_free_expired, hip_relrec_t)
 
+/**
+ * Returns the number of relay records in the hashtable @c hiprelay_ht.
+ *
+ * @return  number of relay records in the hashtable.
+ */
 unsigned long hip_relht_size()
 {
     if (hiprelay_ht == NULL) {
@@ -380,6 +424,14 @@
     return ((struct lhash_st *) hiprelay_ht)->num_items;
 }
 
+/**
+ * Periodic maintenance function of the hip relay. This function should be
+ * called once in every maintenance cycle of the hip daemon. It clears the
+ * expired relay records by calling @c hip_relht_rec_free_expired() for every
+ * element in the hashtable.
+ * @todo a REG_RESPONSE with zero lifetime should be sent to each client whose
+ *       registration is cancelled.
+ */
 void hip_relht_maintenance()
 {
     if (hiprelay_ht == NULL) {
@@ -392,6 +444,12 @@
     ((struct lhash_st *) hiprelay_ht)->down_load = tmp;
 }
 
+/**
+ * Deletes all entries of @c type from the relay record hashtable and frees the
+ * memory allocated for the deleted elements.
+ *
+ * @param type the type of the records to be deleted.
+ */
 void hip_relht_free_all_of_type(const hip_relrec_type_t type)
 {
     if (hiprelay_ht == NULL) {
@@ -405,6 +463,21 @@
     ((struct lhash_st *) hiprelay_ht)->down_load = tmp;
 }
 
+/**
+ * Allocates a new relay record.
+ *
+ * @param type     the type of this relay record (HIP_FULLRELAY or
+ *                 HIP_RVSRELAY).
+ * @param lifetime the lifetime of this relayrecord as defined in registration
+ *                 draft.
+ * @param hit_r    a pointer to Responder (relay client) HIT.
+ * @param ip_r     a pointer to Responder (relay client) IP address.
+ * @param port     responder's UDP port.
+ * @return         a pointer to a new relay record, or NULL if failed to
+ *                 allocate.
+ * @note           All records to be put in the hashtable should be created 
with
+ *                 this function.
+ */
 hip_relrec_t *hip_relrec_alloc(const hip_relrec_type_t type,
                                const uint8_t lifetime,
                                const in6_addr_t *hit_r, const hip_hit_t *ip_r,
@@ -434,6 +507,19 @@
     return rec;
 }
 
+/**
+ * Sets the mode of a relay record. This function sets the @c flags field of a
+ * relay record.
+ *
+ * @param rec  a pointer to a relay record.
+ * @param mode the mode to be set for the parameter record. One of the 
following:
+ *             <ul>
+ *             <li>HIP_REL_NONE</li>
+ *             <li>HIP_REL_UDP</li>
+ *             <li>HIP_REL_TCP</li>
+ *             </ul>
+ * @see        hip_relrec_t for a bitmap.
+ */
 void hip_relrec_set_mode(hip_relrec_t *rec, const hip_relrec_type_t type)
 {
     if (rec != NULL) {
@@ -441,6 +527,13 @@
     }
 }
 
+/**
+ * Sets the lifetime of a relay record.
+ * The service lifetime is set to 2^((lifetime - 64)/8) seconds.
+ *
+ * @param rec      a pointer to a relay record.
+ * @param lifetime the lifetime of the above formula.
+ */
 void hip_relrec_set_lifetime(hip_relrec_t *rec, const uint8_t lifetime)
 {
     if (rec != NULL) {
@@ -448,6 +541,12 @@
     }
 }
 
+/**
+ * Sets the UDP port number of a relay record.
+ *
+ * @param rec  a pointer to a relay record.
+ * @param port UDP port number.
+ */
 void hip_relrec_set_udpport(hip_relrec_t *rec, const in_port_t port)
 {
     if (rec != NULL) {
@@ -455,6 +554,11 @@
     }
 }
 
+/**
+ * Prints info of the parameter relay record using @c HIP_INFO() macro.
+ *
+ * @param rec a pointer to a relay record.
+ */
 void hip_relrec_info(const hip_relrec_t *rec)
 {
     if (rec == NULL) {
@@ -500,6 +604,13 @@
     HIP_DEBUG("\n%s", status);
 }
 
+/**
+ * The hash function of the @c hiprelay_wl hashtable. Calculates a hash from
+ * parameter HIT.
+ *
+ * @param hit a pointer to a HIT.
+ * @return    the calculated hash or zero if @c hit is NULL.
+ */
 static unsigned long hip_relwl_hash(const hip_hit_t *hit)
 {
     if (hit == NULL) {
@@ -512,6 +623,14 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_HASH_FN(hip_relwl, const hip_hit_t)
 
+/**
+ * The compare function of the @c hiprelay_wl hashtable. Compares the hash
+ * values calculated from parameter @c hit1 and @c hit2.
+ *
+ * @param hit1 a pointer to a HIT.
+ * @param hit2 a pointer to a HIT.
+ * @return     0 if keys are equal and neither is NULL, non-zero otherwise.
+ */
 static int hip_relwl_cmp(const hip_hit_t *hit1, const hip_hit_t *hit2)
 {
     if (hit1 == NULL || hit2 == NULL) {
@@ -524,6 +643,23 @@
 /** A callback wrapper of the prototype required by @c lh_new(). */
 static IMPLEMENT_LHASH_COMP_FN(hip_relwl, const hip_hit_t)
 
+/**
+ * Puts a HIT into the whitelist. Puts the HIT pointed by @c hit into the
+ * whitelist hashtable @c hiprelay_wl. If there already is an entry with the
+ * same HIT, the old value is replaced, and <b>the memory allocated for the
+ * existing element is freed</b>. Note that we store pointers here, the data 
are
+ * not copied.
+ *
+ * @param hit a pointer to a HIT to be inserted into the whitelist.
+ * @return    -1 if there was a hash collision i.e. a duplicate HIT is 
inserted,
+ *            zero otherwise.
+ * @note      <b style="color: #f00;">Do not put HITs allocated from the stack
+ *            into the whitelist.</b> Instead put only HITs created with
+ *            malloc().
+ * @note      In case of a hash collision, the existing HIT is freed. If you
+ *            store references to HITs that are in the whitelist elsewhere
+ *            outside the whitelist, NULL pointers can result.
+ */
 static int hip_relwl_put(hip_hit_t *hit)
 {
     if (hiprelay_wl == NULL || hit == NULL) {
@@ -545,6 +681,12 @@
     }
 }
 
+/**
+ * Retrieves a HIT from the hashtable @c hiprelay_wl.
+ *
+ * @param hit a pointer to a HIT.
+ * @return    a pointer to a matching HIT, NULL otherwise.
+ */
 hip_hit_t *hip_relwl_get(const hip_hit_t *hit)
 {
     if (hiprelay_wl == NULL || hit == NULL) {
@@ -571,6 +713,13 @@
 
 #endif /* CONFIG_HIP_DEBUG */
 
+/**
+ * Deletes a single entry from the whitelist hashtable and frees the memory
+ * allocated for the element. The parameter HIT is itself left untouched, it is
+ * only used as an search key.
+ *
+ * @param hit a pointer to a HIT.
+ */
 static void hip_relwl_hit_free_doall(hip_hit_t *hit)
 {
     if (hiprelay_wl == NULL || hit == NULL) {
@@ -593,11 +742,32 @@
 /** A callback wrapper of the prototype required by @c lh_doall(). */
 static IMPLEMENT_LHASH_DOALL_FN(hip_relwl_hit_free, hip_hit_t)
 
+/**
+ * Returns the whitelist status.
+ *
+ * @return HIP_RELAY_ON if the RVS / relay whitelist is "on", HIP_RELAY_OFF
+ *         otherwise.
+ */
 hip_relay_wl_status_t hip_relwl_get_status()
 {
     return whitelist_enabled;
 }
 
+/**
+ * Validates a requested RVS service lifetime. If
+ * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then
+ * @c granted_lifetime is set to @c hiprelay_min_lifetime. If
+ * @c requested_lifetime is greater than @c hiprelay_max_lifetime then
+ * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else
+ * @c granted_lifetime is set to @c requested_lifetime.
+ *
+ * @param  requested_lifetime the lifetime that is to be validated.
+ * @param  granted_lifetime   a target buffer for the validated lifetime.
+ * @return                    -1 if @c requested_lifetime is outside 
boundaries,
+ *                            i.e. is smaller than @c hiprelay_min_lifetime or
+ *                            is greater than @c hiprelay_max_lifetime. Zero
+ *                            otherwise.
+ */
 int hip_rvs_validate_lifetime(uint8_t requested_lifetime,
                               uint8_t *granted_lifetime)
 {
@@ -613,6 +783,45 @@
     }
 }
 
+#if 0
+/**
+ * Validates a requested HIP relay service lifetime. If
+ * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then
+ * @c granted_lifetime is set to @c hiprelay_min_lifetime. If
+ * @c requested_lifetime is greater than @c hiprelay_max_lifetime then
+ * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else
+ * @c granted_lifetime is set to @c requested_lifetime.
+ *
+ * @param  requested_lifetime the lifetime that is to be validated.
+ * @param  granted_lifetime   a target buffer for the validated lifetime.
+ * @return                    -1 if @c requested_lifetime is outside 
boundaries,
+ *                            i.e. is smaller than @c hiprelay_min_lifetime or
+ *                            is greater than @c hiprelay_max_lifetime. Zero
+ *                            otherwise.
+ * @note                      Currently this is just a call back wrapper for
+ *                            hip_rvs_validate_lifetime() because RVS and relay
+ *                            services share the same lifetimes.
+ */
+static int hip_relay_validate_lifetime(uint8_t requested_lifetime,
+                                              uint8_t *granted_lifetime)
+{
+    return hip_rvs_validate_lifetime(requested_lifetime,
+                                     granted_lifetime);
+}
+#endif
+
+/**
+ * forward a control packet in relay or rvs mode
+ *
+ * @param msg the HIP control message to be forwarded
+ * @param saddr source address of the message
+ * @param daddr destination address of the message
+ * @param rec the relay record corresponding to the packet
+ * @param info transport port number information
+ * @param type_hdr message type
+ * @param relay_type rvs vs. relay
+ * @return zero on success and negative on failure
+ */
 int hip_relay_forward(const hip_common_t *msg, const in6_addr_t *saddr,
                       const in6_addr_t *daddr, hip_relrec_t *rec,
                       const hip_portpair_t *info, const uint8_t type_hdr,
@@ -748,6 +957,14 @@
     return err;
 }
 
+/**
+ * Reads RVS / HIP Relay configuration from a file. Reads configuration
+ * information from @c HIP_RELAY_CONFIG_FILE.
+ *
+ * @return zero on success, -ENOENT if the file could not be opened for 
reading.
+ * @note   The white list @c hiprelay_wl must be initialized before this
+ *         function is called.
+ */
 static int hip_relay_read_config()
 {
     FILE *fp    = NULL;
@@ -849,6 +1066,15 @@
     return err;
 }
 
+/**
+ * Writes RVS / HIP Relay configuration file with default content. Writes a RVS
+ * / HIP Relay configuration file to @c HIP_RELAY_CONFIG_FILE. The file is
+ * opened with "w" argument mode, which means that a possibly existing file is
+ * truncated to zero length.
+ *
+ * @return zero on success, -ENOENT if the file could not be opened for 
writing.
+ * @note   Truncates existing file to zero length.
+ */
 static int hip_relay_write_config()
 {
     int err  = 0;
@@ -869,10 +1095,14 @@
 }
 
 /**
- * @todo     Xiang! Please, add decent Doxygen comments, check the doxy syntax
- *           from doc/HACKING. Stick to C-coding style using LINUX indendation.
- *           No lines over 80 characters. No capital letters in funcion names
- *           (C-style). Function commmends should be in header file.
+ * handle a HIP control message with relay_to parameter
+ *
+ * @param msg the message with the relay_to parameter
+ * @param msg_type the type of the message
+ * @param src_addr the source address of the message
+ * @param dst_addr the destination address of the message
+ * @param msg_info transport port numbers
+ * @return zero on success or negative on error
  */
 int hip_relay_handle_relay_to(struct hip_common *msg,
                               int msg_type,
@@ -936,10 +1166,15 @@
 }
 
 /**
- * @todo     Xiang! Please, add decent Doxygen comments, check the doxy syntax
- *           from doc/HACKING. Stick to C-coding style using LINUX indendation.
- *           No lines over 80 characters. No capital letters in funcion names
- *           (C-style). Function commmends should be in header file.
+ * forward a HIP control packet with relay_to parameter
+ *
+ * @param r the HIP control message to be relayed
+ * @param r_saddr the original source address
+ * @param r_daddr the original destination address
+ * @param r_info the transport layer ports
+ * @param relay_to_addr the address where to relay the packet
+ * @param relay_to_port the port where to relay the packet
+ * @return zero on success or negative on error
  */
 static int hip_relay_forward_response(const hip_common_t *r,
                                       const uint8_t type_hdr,
@@ -992,6 +1227,15 @@
     return err;
 }
 
+/**
+ * store the address of a peer's rendezvous server to the host association
+ *
+ * @param source_msg the I1 message
+ * @param entry the host association
+ * @return zero on success or negative on error
+ *
+ * @todo handle also the relay case
+ */
 int hip_relay_add_rvs_to_ha(hip_common_t *source_msg, hip_ha_t *entry)
 {
     struct hip_via_rvs *via_rvs = NULL;
@@ -1024,14 +1268,23 @@
 }
 
 /**
- * function return -1 means error
- * return 0, means parameter not found
- * return 1, means parameter found and verified
- * @todo     Xiang! Please, add decent Doxygen comments, check the doxy syntax
- *           from doc/HACKING. Stick to C-coding style using LINUX indendation.
- *           No lines over 80 characters. No capital letters in funcion names
- *           (C-style). Function commmends should be in header file.
- *
+ * Handles a FROM/RELAY_FROM parameter.
+ *
+ * Checks if the parameter @c source_msg message has a FROM/RELAY_FROM
+ * parameter. If a parameter is found, the values are copied to target buffers
+ * @c dest_ip and @c dest_port. Next the hmac in RVS_HMAC is verified using
+ * the host association created during registration. This host association
+ * is searched using hitr from @c source_msg and @c rvs_ip as search keys.
+ *
+ * @param  source_msg a pointer to the I1 HIP packet common header with source
+ *                    and destination HITs.
+ * @param rvs_ip      a pointer to the source address from where the I1 packet
+ *                    was received.
+ * @param dest_ip     a target buffer for the IP address in the FROM/RELAY_FROM
+ *                    parameter.
+ * @param dest_port   a target buffer for the port number in RELAY_FROM
+ *                    parameter.
+ * @return            zero
  */
 int hip_relay_handle_from(hip_common_t *source_msg,
                           in6_addr_t *rvs_ip,
@@ -1103,13 +1356,12 @@
 }
 
 /**
- * function return -1 means error
- * return 0, means parameter not found
- * return 1, means parameter found and verified
- * @todo     Xiang! Please, add decent Doxygen comments, check the doxy syntax
- *           from doc/HACKING. Stick to C-coding style using LINUX indendation.
- *           No lines over 80 characters. No capital letters in funcion names
- *           (C-style). Function commmends should be in header file.
+ * handle relay_from parameter in a HIP control message
+ *
+ * @param source_msg the HIP control message
+ * @param relay_ip the source IP address of the message
+ * @param dest_ip the relayed destination will be written here
+ * @param dest_port the relayed destination port will be written here
  */
 int hip_relay_handle_relay_from(hip_common_t *source_msg,
                                 in6_addr_t *relay_ip,
@@ -1188,6 +1440,17 @@
     return 1;
 }
 
+/**
+ * handle the relay_to parameter at the Initiator
+ *
+ * @param msg the HIP control packet with relay_to parameter
+ * @param msg_type the type of the HIP control message
+ * @param src_addr source address of the message
+ * @param dst_addr destination address of the message
+ * @param msg_info transport layer port information
+ * @param entry the host association
+ * @return zero on success or negative on error
+ */
 int hip_relay_handle_relay_to_in_client(struct hip_common *msg,
                                         int msg_type,
                                         struct in6_addr *src_addr,
@@ -1239,6 +1502,13 @@
     return err;
 }
 
+/**
+ * Initializes the global HIP relay hashtable. Allocates memory for
+ * @c hiprelay_ht.
+ *
+ * @return zero on success, -1 otherwise.
+ * @note   do not call this function directly, instead call hip_relay_init().
+ */
 static int hip_relht_init()
 {
     /* Check that the relay hashtable is not already initialized. */
@@ -1256,6 +1526,14 @@
     return 0;
 }
 
+/**
+ * Uninitializes the HIP relay record hashtable @c hiprelay_ht. Frees the 
memory
+ * allocated for the hashtable and for the relay records. Thus, after calling
+ * this function, all memory allocated from the heap related to the relay 
record
+ * hashtable is free.
+ *
+ * @note do not call this function directly, instead call hip_relay_uninit().
+ */
 static void hip_relht_uninit()
 {
     if (hiprelay_ht == NULL) {
@@ -1267,6 +1545,10 @@
     hiprelay_ht = NULL;
 }
 
+/**
+ * Initializes the HIP relay / RVS. Initializes the HIP relay hashtable and
+ * whitelist.
+ */
 int hip_relay_init()
 {
     int err = 0;
@@ -1300,12 +1582,28 @@
     return err;
 }
 
+/**
+ * Uninitializes the HIP relay / RVS. Uninitializes the HIP relay hashtable and
+ * whitelist.
+ */
 void hip_relay_uninit()
 {
     hip_relht_uninit();
     hip_relwl_uninit();
 }
 
+/**
+ * Reinitializes the HIP relay / RVS. Deletes the old values from the relay
+ * whitelist and reads new values from the configuration file
+ * @c HIP_RELAY_CONFIG_FILE. Besides the whitelist values also every other
+ * value read from the configuration file is reinitialized. These include the
+ * lifetime values etc. However, the existing relay records are left as they
+ * were. This means that the relay / RVS clients that have already registered
+ * continue to be served as before - even if their HIT nomore exists in the
+ * whitelist.
+ *
+ * @return zero if the configuration file was read succesfully, -1 otherwise.
+ */
 int hip_relay_reinit()
 {
     int err = 0;
@@ -1320,6 +1618,13 @@
     return err;
 }
 
+/**
+ * Initializes the global HIP relay whitelist. Allocates memory for
+ * @c hiprelay_wl.
+ *
+ * @return zero on success, -1 otherwise.
+ * @note   do not call this function directly, instead call hip_relay_init().
+ */
 static int hip_relwl_init()
 {
     /* Check that the relay whitelist is not already initialized. */
@@ -1337,6 +1642,14 @@
     return 0;
 }
 
+/**
+ * Uninitializes the HIP relay whitelist hashtable @c hiprelay_wl. Frees the
+ * memory allocated for the hashtable and for the HITs. Thus, after calling
+ * this function, all memory allocated from the heap related to the whitelist
+ * is free.
+ *
+ * @note do not call this function directly, instead call hip_relay_uninit().
+ */
 static void hip_relwl_uninit()
 {
     if (hiprelay_wl == NULL) {

=== modified file 'hipd/hiprelay.h'
--- hipd/hiprelay.h     2010-02-17 17:38:08 +0000
+++ hipd/hiprelay.h     2010-03-19 09:53:35 +0000
@@ -1,71 +1,13 @@
 /** @file
+ *
+ * Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
+ *
  * A header file for hiprelay.c.
  *
- * The HIP relay combines the functionalites of an rendezvous server (RVS) and
- * a HIP UDP relay. The HIP relay consists of a hashtable for storing IP 
address
- * to HIT mappings and of functions that do the actual relaying action. The
- * hashtable is based on lhash library and its functionalites are the same
- * except that the HIP relay stores data (allocated memory for relay records)
- * instead of pointers.
- *
- * A few simple rules apply:
- * <ul>
- * <li>Allocate memory for relay records that are to be put into the hashtable
- * only with hip_relrec_alloc().</li>
- * <li>Once a relay record is <b>successfully</b> put into the hashtable, the
- * only way delete it is to call hip_relht_rec_free(). This will remove the
- * entry from the hashtable and free the memory allocated for the relay record.
- * </li>
- * </ul>
- *
- * Usage:
- * <ul>
- * <li>Inserting a new relay record:
- * <pre>
- * hip_relrec_t rr = hip_relrec_alloc(...);
- * hip_relht_put(rr);
- * if(hip_relht_get(rr) == NULL) // The put was unsuccessful.
- * {
- *   if(rr != NULL)
- *     free(rr);
- * }
- * </pre>
- * </li>
- * <li>Fetching a relay record. We do not need (but can use) a fully populated
- * relay record as a search key. A dummy record with hit_r field populated
- * is sufficient. Note that there is no need to re-put the relay record into 
the
- * hashtable once it has been succesfully inserted into the hashtable - except
- * if we change the hit_r field of the relay record. If a relay record with 
same
- * HIT is put into the hashtable, the existing element is deleted.
- *
- * <pre>
- * hip_relrec_t dummy, *fetch_record = NULL;
- * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit));
- * fetch_record = hip_relht_get(&dummy);
- * if(fetch_record != NULL)
- * {
- * // Do something with the record.
- * }
- * </pre>
- * </li>
- * <li>Deleting a relay record. A dummy record can be used:
- * <pre>
- * hip_relrec_t dummy;
- * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit));
- * hip_relht_rec_free(&dummy);
- * </pre>
- * </li>
- * </ul>
- *
  * @author  Lauri Silvennoinen
- * @version 1.1
- * @date    31.03.2008
- * @note    Related RFC: <a href="http://www.rfc-editor.org/rfc/rfc5204.txt";>
- *          Host Identity Protocol (HIP) Rendezvous Extension</a>
  * @note    Related draft:
  *          <a 
href="http://www.ietf.org/internet-drafts/draft-ietf-hip-nat-traversal-03.txt";>
  *          draft-ietf-hip-nat-traversal-03</a>
- * @note    Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
  */
 #ifndef HIP_HIPD_HIPRELAY_H
 #define HIP_HIPD_HIPRELAY_H
@@ -76,11 +18,8 @@
 #include <arpa/inet.h> /* For nthos() */
 #include <math.h> /* For pow() */
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include "lib/core/misc.h" /* For debuging macros. */
+#include "config.h"
+ /* For debuging macros. */
 #include "registration.h" /* For lifetime conversions. */
 #include "configfilereader.h"
 #include "lib/core/state.h"
@@ -136,366 +75,54 @@
 /** Possible states of the whitelist. */
 typedef enum { HIP_RELAY_WL_OFF = 0, HIP_RELAY_WL_ON = 1 } 
hip_relay_wl_status_t;
 
-/**
- * Returns relay status.
- *
- * @return HIP_RELAY_ON if the RVS / relay is "on", HIP_RELAY_OFF otherwise.
- */
 hip_relay_status_t hip_relay_get_status(void);
-
-/**
- * Sets the status of the RVS / relay. Sets the relay "on" or "off".
- *
- * @param status zero if the relay is to be disabled, anything else to enable
- *               the relay.
- */
 void hip_relay_set_status(hip_relay_status_t status);
-
-/**
- * Initializes the HIP relay / RVS. Initializes the HIP relay hashtable and
- * whitelist.
- */
 int hip_relay_init(void);
-
-/**
- * Uninitializes the HIP relay / RVS. Uninitializes the HIP relay hashtable and
- * whitelist.
- */
 void hip_relay_uninit(void);
-
-/**
- * Reinitializes the HIP relay / RVS. Deletes the old values from the relay
- * whitelist and reads new values from the configuration file
- * @c HIP_RELAY_CONFIG_FILE. Besides the whitelist values also every other
- * value read from the configuration file is reinitialized. These include the
- * lifetime values etc. However, the existing relay records are left as they
- * were. This means that the relay / RVS clients that have already registered
- * continue to be served as before - even if their HIT nomore exists in the
- * whitelist.
- *
- * @return zero if the configuration file was read succesfully, -1 otherwise.
- */
 int hip_relay_reinit(void);
-
-/**
- * Sets the mode of a relay record. This function sets the @c flags field of a
- * relay record.
- *
- * @param rec  a pointer to a relay record.
- * @param mode the mode to be set for the parameter record. One of the 
following:
- *             <ul>
- *             <li>HIP_REL_NONE</li>
- *             <li>HIP_REL_UDP</li>
- *             <li>HIP_REL_TCP</li>
- *             </ul>
- * @see        hip_relrec_t for a bitmap.
- */
 void hip_relrec_set_mode(hip_relrec_t *rec, const hip_relrec_type_t type);
-
-/**
- * Sets the lifetime of a relay record.
- * The service lifetime is set to 2^((lifetime - 64)/8) seconds.
- *
- * @param rec      a pointer to a relay record.
- * @param lifetime the lifetime of the above formula.
- */
 void hip_relrec_set_lifetime(hip_relrec_t *rec, const uint8_t lifetime);
-
-/**
- * Sets the UDP port number of a relay record.
- *
- * @param rec  a pointer to a relay record.
- * @param port UDP port number.
- */
 void hip_relrec_set_udpport(hip_relrec_t *rec, const in_port_t port);
-
-/**
- * Prints info of the parameter relay record using @c HIP_INFO() macro.
- *
- * @param rec a pointer to a relay record.
- */
 void hip_relrec_info(const hip_relrec_t *rec);
-
-/**
- * The compare function of the @c hiprelay_ht hashtable. Compares the hash
- * values calculated from parameters @c rec1 and @c rec2.
- *
- * @param rec1 a pointer to a HIT.
- * @param rec2 a pointer to a HIT.
- * @return     0 if keys are equal and neither is NULL, non-zero otherwise.
- */
-int hip_relht_compare(const hip_relrec_t *rec1, const hip_relrec_t *rec2);
-
-/**
- * Puts a relay record into the hashtable. Puts the relay record pointed by
- * @c rec into the hashtable @c hiprelay_ht. If there already is an entry with
- * the same key the old value is replaced, and <b>the memory allocated for the
- * existing element is freed</b>. Note that we store pointers here, the data 
are
- * not copied. There should be no need to put a relay record more than once 
into
- * the hashtable. If the fields of an individual relay record need to be
- * changed, just retrieve the record with @c hip_relht_get() and alter the
- * fields of it, but do not re-put it into the hashtable.
- *
- * @param rec a pointer to a relay record to be inserted into the hashtable.
- * @return    -1 if there was a hash collision i.e. an entry with duplicate HIT
- *            is inserted, zero otherwise.
- * @note      <b style="color: #f00;">Do not put records allocated from stack
- *            into the hashtable.</b> Instead put only records created with
- *            hip_relrec_alloc().
- * @note      In case of a hash collision, the existing relay record is freed.
- *            If you store references to relay records that are in the 
hashtable
- *            elsewhere outside the hashtable, NULL pointers can result.
- */
 int hip_relht_put(hip_relrec_t *rec);
-
-/**
- * Retrieves a relay record from the hashtable @c hiprelay_ht. The parameter
- * record @c rec only needs to have field @c hit_r populated.
- *
- * @param rec a pointer to a relay record.
- * @return    a pointer to a fully populated relay record if found, NULL
- *            otherwise.
- */
 hip_relrec_t *hip_relht_get(const hip_relrec_t *rec);
-
-/**
- * Deletes a single entry from the relay record hashtable and frees the memory
- * allocated for the element. The deletion is based on the hash calculated from
- * the relay fecord @c hit_r field, and therefore the parameter record does not
- * need to be fully populated. If the parameter relay record is the same record
- * that is being deleted (i.e. is located in the same memory location) then
- * the parameter @c rec itself is freed. If a dummy record is used (i.e. is
- * located in a different memory location thatn the hashtable entry), then
- * @c rec is left untouched.
- *
- * @param rec a pointer to a relay record.
- */
 void hip_relht_rec_free_doall(hip_relrec_t *rec);
-
-/**
- * Deletes a single entry from the relay record hashtable and frees the memory
- * allocated for the element if the matching element's type is of @c type. The
- * deletion is based on the hash calculated from the relay fecord
- * @c hit_r field, and therefore the parameter record does not need to be fully
- * populated. If the parameter relay record is the same record that is being
- * deleted (i.e. is located in the same memory location) then the parameter
- * @c rec itself is freed. If a dummy record is used (i.e. is located in a
- * different memory location thatn the hashtable entry), then @c rec is left
- * untouched.
- *
- * @param rec a pointer to a relay record.
- */
 void hip_relht_rec_free_type_doall(hip_relrec_t *rec, const hip_relrec_type_t 
*type);
-
-/**
- * Returns the number of relay records in the hashtable @c hiprelay_ht.
- *
- * @return  number of relay records in the hashtable.
- */
 unsigned long hip_relht_size(void);
-
-/**
- * Periodic maintenance function of the hip relay. This function should be
- * called once in every maintenance cycle of the hip daemon. It clears the
- * expired relay records by calling @c hip_relht_rec_free_expired() for every
- * element in the hashtable.
- * @todo a REG_RESPONSE with zero lifetime should be sent to each client whose
- *       registration is cancelled.
- */
 void hip_relht_maintenance(void);
-
-/**
- * Allocates a new relay record.
- *
- * @param type     the type of this relay record (HIP_FULLRELAY or
- *                 HIP_RVSRELAY).
- * @param lifetime the lifetime of this relayrecord as defined in registration
- *                 draft.
- * @param hit_r    a pointer to Responder (relay client) HIT.
- * @param ip_r     a pointer to Responder (relay client) IP address.
- * @param port     responder's UDP port.
- * @return         a pointer to a new relay record, or NULL if failed to
- *                 allocate.
- * @note           All records to be put in the hashtable should be created 
with
- *                 this function.
- */
 hip_relrec_t *hip_relrec_alloc(const hip_relrec_type_t type,
                                const uint8_t lifetime,
                                const in6_addr_t *hit_r, const hip_hit_t *ip_r,
                                const in_port_t port,
                                const hip_crypto_key_t *hmac,
                                const hip_xmit_func_t func);
-
-/**
- * Deletes all entries of @c type from the relay record hashtable and frees the
- * memory allocated for the deleted elements.
- *
- * @param type the type of the records to be deleted.
- */
 void hip_relht_free_all_of_type(const hip_relrec_type_t type);
-
-/**
- * The compare function of the @c hiprelay_wl hashtable. Compares the hash
- * values calculated from parameter @c hit1 and @c hit2.
- *
- * @param hit1 a pointer to a HIT.
- * @param hit2 a pointer to a HIT.
- * @return     0 if keys are equal and neither is NULL, non-zero otherwise.
- */
 int hip_relwl_compare(const hip_hit_t *hit1, const hip_hit_t *hit2);
-
-/**
- * Retrieves a HIT from the hashtable @c hiprelay_wl.
- *
- * @param hit a pointer to a HIT.
- * @return    a pointer to a matching HIT, NULL otherwise.
- */
 hip_hit_t *hip_relwl_get(const hip_hit_t *hit);
-
-/**
- * Returns the whitelist status.
- *
- * @return HIP_RELAY_ON if the RVS / relay whitelist is "on", HIP_RELAY_OFF
- *         otherwise.
- */
 hip_relay_wl_status_t hip_relwl_get_status(void);
-
-/**
- * Validates a requested RVS service lifetime. If
- * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then
- * @c granted_lifetime is set to @c hiprelay_min_lifetime. If
- * @c requested_lifetime is greater than @c hiprelay_max_lifetime then
- * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else
- * @c granted_lifetime is set to @c requested_lifetime.
- *
- * @param  requested_lifetime the lifetime that is to be validated.
- * @param  granted_lifetime   a target buffer for the validated lifetime.
- * @return                    -1 if @c requested_lifetime is outside 
boundaries,
- *                            i.e. is smaller than @c hiprelay_min_lifetime or
- *                            is greater than @c hiprelay_max_lifetime. Zero
- *                            otherwise.
- */
 int hip_rvs_validate_lifetime(uint8_t requested_lifetime,
                               uint8_t *granted_lifetime);
-
 int hip_relay_forward(const hip_common_t *msg, const in6_addr_t *saddr,
                       const in6_addr_t *daddr, hip_relrec_t *rec,
                       const hip_portpair_t *info, const uint8_t type_hdr,
                       const hip_relrec_type_t relay_type);
-
-/**
- * Validates a requested HIP relay service lifetime. If
- * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then
- * @c granted_lifetime is set to @c hiprelay_min_lifetime. If
- * @c requested_lifetime is greater than @c hiprelay_max_lifetime then
- * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else
- * @c granted_lifetime is set to @c requested_lifetime.
- *
- * @param  requested_lifetime the lifetime that is to be validated.
- * @param  granted_lifetime   a target buffer for the validated lifetime.
- * @return                    -1 if @c requested_lifetime is outside 
boundaries,
- *                            i.e. is smaller than @c hiprelay_min_lifetime or
- *                            is greater than @c hiprelay_max_lifetime. Zero
- *                            otherwise.
- * @note                      Currently this is just a call back wrapper for
- *                            hip_rvs_validate_lifetime() because RVS and relay
- *                            services share the same lifetimes.
- */
-static inline int hip_relay_validate_lifetime(uint8_t requested_lifetime,
-                                              uint8_t *granted_lifetime)
-{
-    return hip_rvs_validate_lifetime(requested_lifetime,
-                                     granted_lifetime);
-}
-
-/**
- * Relays an incoming I1 packet.
- *
- * This function relays an incoming I1 packet to the next node on path
- * to receiver and inserts a @c FROM parameter encapsulating the source IP
- * address. In case there is a NAT between the sender (the initiator or 
previous
- * RVS) of the I1 packet, a @c RELAY_FROM parameter is inserted instead of a
- * @c FROM parameter. Next node on path is typically the responder, but if the
- * message is to travel multiple rendezvous servers en route to responder, next
- * node can also be another rendezvous server. In this case the @c FROM
- * (@c RELAY_FROM) parameter is appended after the existing ones. Thus current 
RVS
- * appends the address of previous RVS and the final RVS (n) in the RVS chain
- * sends @c FROM:I, @c FROM:RVS1, ... , <code>FROM:RVS(n-1)</code>. If 
initiator
- * is located behind a NAT, the first @c FROM parameter is replaced with a
- * @c RELAY_FROM parameter.
- *
- * @param i1       a pointer to the I1 HIP packet common header with source and
- *                 destination HITs.
- * @param i1_saddr a pointer to the source address from where the I1 packet was
- *                 received.
- * @param i1_daddr a pointer to the destination address where the I1 packet was
- *                 sent to (own address).
- * @param rec      a pointer to a relay record matching the HIT of Responder.
- * @param i1_info  a pointer to the source and destination ports (when NAT is
- *                 in use).
- * @return         zero on success, or negative error value on error.
- * @note           This code has not been tested thoroughly with multiple 
RVSes.
- * @note           This function is a copy-paste from the previous RVS
- *                 implementation
- */
-int hip_relay_rvs(const hip_common_t *i1,
-                  const in6_addr_t *i1_saddr,
-                  const in6_addr_t *i1_daddr, hip_relrec_t *rec,
-                  const hip_portpair_t *i1_info);
-
 int hip_relay_add_rvs_to_ha(hip_common_t *source_msg, hip_ha_t *entry);
-
-
-/**
- * Handles a FROM/RELAY_FROM parameter.
- *
- * Checks if the parameter @c source_msg message has a FROM/RELAY_FROM
- * parameter. If a parameter is found, the values are copied to target buffers
- * @c dest_ip and @c dest_port. Next the hmac in RVS_HMAC is verified using
- * the host association created during registration. This host association
- * is searched using hitr from @c source_msg and @c rvs_ip as search keys.
- *
- * @param  source_msg a pointer to the I1 HIP packet common header with source
- *                    and destination HITs.
- * @param rvs_ip      a pointer to the source address from where the I1 packet
- *                    was received.
- * @param dest_ip     a target buffer for the IP address in the FROM/RELAY_FROM
- *                    parameter.
- * @param dest_port   a target buffer for the port number in RELAY_FROM
- *                    parameter.
- * @return            zero
- */
-
 int hip_relay_handle_from(hip_common_t *source_msg,
                           in6_addr_t *rvs_ip,
                           in6_addr_t *dest_ip, in_port_t *dest_port);
-
 int hip_relay_handle_relay_from(hip_common_t *source_msg,
                                 in6_addr_t *relay_ip,
                                 in6_addr_t *dest_ip, in_port_t *dest_port);
-
 int hip_relay_handle_relay_to_in_client(struct hip_common *msg,
                                         int msg_type,
                                         struct in6_addr *src_addr,
                                         struct in6_addr *dst_addr,
                                         hip_portpair_t *msg_info,
                                         hip_ha_t *entry);
-
-
 int hip_relay_handle_relay_to(struct hip_common *msg,
                               int msg_type,
                               struct in6_addr *src_addr,
                               struct in6_addr *dst_addr,
                               hip_portpair_t *msg_info);
 
-/**
- * function for full relay service. from I to R
- *
- */
-int hip_relay_forward_I(const hip_common_t *i1,
-                        const in6_addr_t *i1_saddr,
-                        const in6_addr_t *i1_daddr, hip_relrec_t *rec,
-                        const hip_portpair_t *i1_info,
-                        const uint8_t);
-
 #endif /* HIP_HIPD_HIPRELAY_H */

=== modified file 'hipd/init.c'
--- hipd/init.c 2010-03-03 13:16:18 +0000
+++ hipd/init.c 2010-03-19 09:53:35 +0000
@@ -1,7 +1,9 @@
 /** @file
+ *
+ * Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
+ *
  * This file defines initialization functions for the HIP daemon.
  *
- * @note    Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
  * @note    HIPU: BSD platform needs to be autodetected in 
hip_set_lowcapability
  */
 
@@ -12,18 +14,19 @@
 #include <sys/types.h>
 #include <netinet/icmp6.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
+#include "init.h"
+#include "oppdb.h"
 #include "lib/core/common_defines.h"
 #include "lib/core/debug.h"
-#include "init.h"
 #include "lib/performance/performance.h"
 #include "lib/core/hip_capability.h"
+#include "lib/core/filemanip.h"
+#include "lib/core/hostid.h"
 #include "lib/tool/nlink.h"
-#include "oppdb.h"
 #include "lib/dht/libhipdht.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/hostsfiles.h"
 
 #ifdef CONFIG_HIP_AGENT
 #include "hipd.h"
@@ -80,7 +83,11 @@
 static struct hip_host_id_entry *hip_return_first_rsa(void);
 
 
/******************************************************************************/
-/** Catch SIGCHLD. */
+/**
+ * Catch SIGCHLD.
+ *
+ * @param signum the signal number to catch
+ */
 static void hip_sig_chld(int signum)
 {
 #ifdef ANDROID_CHANGES
@@ -100,6 +107,13 @@
     }
 }
 
+/**
+ * set or unset close-on-exec flag for a given file descriptor
+ *
+ * @param desc the file descriptor
+ * @param value 1 if to set or zero for unset
+ * @return the previous flags
+ */
 static int set_cloexec_flag(int desc, int value)
 {
     int oldflags = fcntl(desc, F_GETFD, 0);
@@ -120,6 +134,9 @@
 
 #ifndef CONFIG_HIP_OPENWRT
 #ifdef CONFIG_HIP_DEBUG
+/**
+ * print information about underlying the system for bug reports
+ */
 static void hip_print_sysinfo(void)
 {
     FILE *fp    = NULL;
@@ -227,8 +244,11 @@
 #endif
 #endif
 
-/*
+/**
  * Create a file with the given contents unless it already exists
+ *
+ * @param path the file with its path
+ * @param contents a string to write to the file
  */
 static void hip_create_file_unless_exists(const char *path, const char 
*contents)
 {
@@ -244,6 +264,9 @@
     fclose(fp);
 }
 
+/**
+ * load hipd configuration files
+ */
 static void hip_load_configuration(void)
 {
     const char *cfile = "default";
@@ -269,6 +292,9 @@
     hip_conf_handle_load(NULL, ACTION_LOAD, &cfile, 1, 1);
 }
 
+/**
+ * initialize OS-dependent variables
+ */
 static void hip_set_os_dep_variables(void)
 {
     struct utsname un;
@@ -306,8 +332,9 @@
 
 #ifdef CONFIG_HIP_AGENT
 /**
- * hip_init_daemon_hitdb - The function initializes the database at daemon
- * which receives the information from agent to be stored
+ * initialize the graphical agent database
+ *
+ * @return zero on success or negative on failure
  */
 static int hip_init_daemon_hitdb(void)
 {
@@ -325,7 +352,11 @@
 #endif  /* CONFIG_HIP_AGENT */
 
 /**
- * Initialize raw ipv4 socket.
+ * initialize a raw ipv4 socket
+ *
+ * @param hip_raw_sock_v4 the raw socket to initialize
+ * @param proto the protocol for the raw socket
+ * @return zero on success or negative on failure
  */
 static int hip_init_raw_sock_v4(int *hip_raw_sock_v4, int proto)
 {
@@ -351,7 +382,10 @@
 }
 
 /**
- * Initialize icmpv6 socket.
+ * initialize icmpv6 socket for heartbeats
+ *
+ * @param icmpsockfd the socket to initialize
+ * @return zero on success or negative on failure
  */
 static int hip_init_icmp_v6(int *icmpsockfd)
 {
@@ -379,12 +413,11 @@
     return err;
 }
 
+#ifndef CONFIG_HIP_OPENWRT
+#ifndef ANDROID_CHANGES
 /**
- * Probe kernel modules.
+ * probe for kernel modules (linux specific)
  */
-
-#ifndef CONFIG_HIP_OPENWRT
-#ifndef ANDROID_CHANGES
 static void hip_probe_kernel_modules(void)
 {
     int count, err, status;
@@ -430,6 +463,11 @@
 
 /**
  * Main initialization function for HIP daemon.
+ *
+ * @param flush_ipsec one if ipsec should be flushed or zero otherwise
+ * @param killold one if an existing hipd process should be killed or
+ *                zero otherwise
+ * @return zero on success or negative on failure
  */
 int hipd_init(int flush_ipsec, int killold)
 {
@@ -558,14 +596,12 @@
 
     HIP_IFEL(hip_init_raw_sock_v6(&hip_raw_sock_output_v6, IPPROTO_HIP), -1, 
"raw sock output v6\n");
     HIP_IFEL(hip_init_raw_sock_v4(&hip_raw_sock_output_v4, IPPROTO_HIP), -1, 
"raw sock output v4\n");
-    // Notice that hip_nat_sock_input should be initialized after 
hip_nat_sock_output
-    // because for the sockets bound to the same address/port, only the last 
socket seems
-    // to receive the packets.
-#if 0
-    HIP_IFEL(hip_create_nat_sock_udp(&hip_nat_sock_output_udp, 0), -1, "raw 
sock output udp\n");
-#else
+    /* hip_nat_sock_input should be initialized after hip_nat_sock_output
+       because for the sockets bound to the same address/port, only the last 
socket seems
+       to receive the packets. NAT input socket is a normal UDP socket where as
+       NAT output socket is a raw socket. A raw output socket support better 
the "shotgun"
+       extension (sending packets from multiple source addresses). */
     HIP_IFEL(hip_init_raw_sock_v4(&hip_nat_sock_output_udp, IPPROTO_UDP), -1, 
"raw sock output udp\n");
-#endif
     HIP_IFEL(hip_init_raw_sock_v6(&hip_raw_sock_input_v6, IPPROTO_HIP), -1, 
"raw sock input v6\n");
     HIP_IFEL(hip_init_raw_sock_v4(&hip_raw_sock_input_v4, IPPROTO_HIP), -1, 
"raw sock input v4\n");
     HIP_IFEL(hip_create_nat_sock_udp(&hip_nat_sock_input_udp, 0, 0), -1, "raw 
sock input udp\n");
@@ -687,9 +723,9 @@
 }
 
 /**
- * Function initializes needed variables for the OpenDHT
+ * initialize the needed variables for DHT
  *
- * Returns positive on success negative otherwise
+ * @return zero on success or negative on failure
  */
 int hip_init_dht()
 {
@@ -789,8 +825,18 @@
         HIP_DEBUG("gethostname failed\n");
     }
     hip_register_to_dht();
-    hip_init_dht_sockets(&hip_opendht_sock_fqdn, &hip_opendht_fqdn_sent);
-    hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent);
+    err = hip_init_dht_sockets(&hip_opendht_sock_fqdn, &hip_opendht_fqdn_sent);
+    if (err < 0) {
+        close(hip_opendht_sock_fqdn);
+        hip_opendht_sock_fqdn = -1;
+        /* Do not bother trying the other */
+        return err;
+    }
+    err = hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent);
+    if (err < 0) {
+        close(hip_opendht_sock_hit);
+        hip_opendht_sock_hit = -1;
+    }
 
 /* out_err only used by opendht code */
 out_err:
@@ -800,7 +846,9 @@
 }
 
 /**
- * Initialize host IDs.
+ * Initialize local host IDs.
+ *
+ * @return zero on success or negative on failure
  */
 static int hip_init_host_ids()
 {
@@ -893,7 +941,12 @@
 }
 
 /**
- * Init raw ipv6 socket.
+ * Init raw ipv6 socket
+ *
+ * @param hip_raw_sock_v6 the socket to initialize
+ * @param proto protocol for the socket
+ *
+ * @return zero on success or negative on failure
  */
 static int hip_init_raw_sock_v6(int *hip_raw_sock_v6, int proto)
 {
@@ -915,6 +968,16 @@
     return err;
 }
 
+/**
+ * create a socket to handle UDP encapsulation of HIP control
+ * packets
+ *
+ * @param hip_nat_sock_udp the socket to initialize
+ * @param addr the address to which the socket should be bound
+ * @param is_output one if the socket is to be used for output
+ *                  or zero for input
+ * @return zero on success or negative on failure
+ */
 int hip_create_nat_sock_udp(int *hip_nat_sock_udp,
                             struct sockaddr_in *addr,
                             int is_output)
@@ -986,7 +1049,9 @@
 }
 
 /**
- * Start closing HIP daemon.
+ * exit gracefully by sending CLOSE to all peers
+ *
+ * @param signal the signal hipd received from OS
  */
 void hip_close(int signal)
 {
@@ -1012,6 +1077,8 @@
 /**
  * Cleanup and signal handler to free userspace and kernel space
  * resource allocations.
+ *
+ * @param signal the signal hipd received
  */
 void hip_exit(int signal)
 {
@@ -1095,6 +1162,9 @@
         close(hip_nat_sock_output_udp_v6);
     }
 
+    hip_uninit_hadb();
+    hip_uninit_host_id_dbs();
+
     if (hip_user_sock) {
         HIP_INFO("hip_user_sock\n");
         close(hip_user_sock);
@@ -1108,9 +1178,6 @@
         rtnl_close(&hip_nl_route);
     }
 
-    hip_uninit_hadb();
-    hip_uninit_host_id_dbs();
-
     msg = hip_msg_alloc();
     if (msg) {
         hip_build_user_hdr(msg, SO_HIP_DAEMON_QUIT, 0);
@@ -1148,6 +1215,8 @@
 
 /**
  * Initialize random seed.
+ *
+ * @return zero on success or negative on failure
  */
 static int init_random_seed()
 {
@@ -1172,6 +1241,11 @@
     return err;
 }
 
+/**
+ * Initialize certificates for the local host
+ *
+ * @return zero on success or negative on failure
+ */
 static int hip_init_certs(void)
 {
     int err = 0;
@@ -1241,6 +1315,11 @@
     return err;
 }
 
+/**
+ * find the first RSA-based host id
+ *
+ * @return the host id or NULL if none found
+ */
 static struct hip_host_id_entry *hip_return_first_rsa(void)
 {
     hip_list_t *curr, *iter;

=== modified file 'hipd/input.c'
--- hipd/input.c        2010-03-19 09:24:10 +0000
+++ hipd/input.c        2010-03-19 09:53:35 +0000
@@ -17,10 +17,7 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "input.h"
 #include "hadb.h"
 #include "oppdb.h"
@@ -28,8 +25,12 @@
 #include "keymat.h"
 #include "lib/core/crypto.h"
 #include "lib/core/builder.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/solve.h"
+#include "lib/core/transform.h"
+#include "lib/core/keylen.h"
 #include "dh.h"
-#include "lib/core/misc.h"
+
 #include "hidb.h"
 #include "cookie.h"
 #include "output.h"
@@ -37,6 +38,7 @@
 #include "netdev.h"
 #include "lib/tool/lutil.h"
 #include "lib/core/state.h"
+#include "lib/core/hit.h"
 #include "oppdb.h"
 #include "registration.h"
 #include "esp_prot_hipd_msg.h"
@@ -54,6 +56,10 @@
 #include "lib/performance/performance.h"
 #endif
 
+#ifdef CONFIG_HIP_BLIND
+#include "lib/core/hostid.h"
+#endif
+
 /**
  * Verifies a HMAC.
  *
@@ -1413,9 +1419,9 @@
 
     hip_relay_add_rvs_to_ha(r1, entry);
 
-#ifdef HIP_USE_ICE
+#ifdef CONFIG_HIP_RVS
     hip_relay_handle_relay_to_in_client(r1, HIP_R1, r1_saddr, r1_daddr, 
r1_info, entry);
-#endif
+#endif /* CONFIG_HIP_RVS */
 
     /* According to the section 8.6 of the base draft, we must first check
      * signature. */
@@ -2857,9 +2863,9 @@
         HIP_ERROR("Couldn't get device ifindex of address\n");
     }
 
-#ifdef HIP_USE_ICE
+#ifdef CONFIG_HIP_RVS
     hip_relay_handle_relay_to_in_client(r2, HIP_R2, r2_saddr, r2_daddr, 
r2_info, entry);
-#endif
+#endif /* CONFIG_HIP_RVS */
     /* Copying address list from temp location in entry
      * "entry->peer_addr_list_to_be_added" */
     hip_copy_peer_addrlist_changed(entry);

=== modified file 'hipd/input.h'
--- hipd/input.h        2010-03-19 09:24:10 +0000
+++ hipd/input.h        2010-03-19 09:53:35 +0000
@@ -15,10 +15,7 @@
 #ifndef HIP_HIPD_INPUT_H
 #define HIP_HIPD_INPUT_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #ifdef CONFIG_HIP_RVS
   #include "hiprelay.h"
 #endif
@@ -37,22 +34,6 @@
     struct in6_addr sin6_addr;
 };
 
-struct pseudo_header6 {
-    unsigned char src_addr[16];
-    unsigned char dst_addr[16];
-    uint32_t           packet_length;
-    unsigned char zero[3];
-    uint8_t            next_hdr;
-};
-
-struct pseudo_header {
-    unsigned char src_addr[4];
-    unsigned char dst_addr[4];
-    uint8_t            zero;
-    uint8_t            protocol;
-    uint16_t           packet_length;
-};
-
 /**
  * Checks for illegal controls in a HIP packet Controls field.
  *

=== modified file 'hipd/keymat.c'
--- hipd/keymat.c       2010-03-19 09:24:10 +0000
+++ hipd/keymat.c       2010-03-19 09:53:35 +0000
@@ -1,9 +1,9 @@
 /**
  * @file
- * This file contains KEYMAT handling functions for HIPL.
- * Licence: GNU/GPL
- *
- * TODO: Doxygen documentation is incomplete
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * This file contains KEYMAT handling functions for HIPL
  *
  * @author Mika Kousa <mkousa#iki.fi>
  * @author Kristian Slavov <ksl#iki.fi>
@@ -14,7 +14,21 @@
 #define _BSD_SOURCE
 
 #include "keymat.h"
+#include "lib/core/hit.h"
 
+/**
+ * allocate and initialize a big enough key material buffer for
+ * drawing symmetric keys for HIP and ESP
+ *
+ * @param kij the diffie hellman session key
+ * @param kij_len the length of kij in bytes
+ * @param hash_len the length of the used hash
+ * @param smaller_hit smaller HIT
+ * @param bigger_hit bigger HIT
+ * @param I the I value from the puzzle
+ * @param J the J value from the puzzle
+ * @return the allocated buffer (caller deallocates) or NULL on failure
+ */
 static uint8_t *hip_create_keymat_buffer(char *kij, size_t kij_len, size_t 
hash_len,
                                     struct in6_addr *smaller_hit,
                                     struct in6_addr *bigger_hit,
@@ -57,6 +71,15 @@
     return buffer;
 }
 
+/**
+ * update keymat buffer and index after writing material to it
+ *
+ * @param keybuf a pointer to the key material
+ * @param Kold a the seed
+ * @param Kold_len length of Kold
+ * @param Kij_len length of the Kij
+ * @param cnt index value
+ */
 static void hip_update_keymat_buffer(uint8_t *keybuf, uint8_t *Kold, size_t 
Kold_len,
                                      size_t Kij_len, uint8_t cnt)
 {

=== modified file 'hipd/keymat.h'
--- hipd/keymat.h       2010-03-19 09:24:10 +0000
+++ hipd/keymat.h       2010-03-19 09:53:35 +0000
@@ -2,7 +2,7 @@
 #define HIP_HIPD_KEYMAT_H
 
 #include "lib/core/list.h"
-#include "lib/core/misc.h"
+
 #include "lib/core/crypto.h"
 #include "lib/core/state.h"
 

=== modified file 'hipd/maintenance.c'
--- hipd/maintenance.c  2010-03-03 13:16:18 +0000
+++ hipd/maintenance.c  2010-03-19 09:53:35 +0000
@@ -1,26 +1,30 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * Periodically handled "maintenance" actions are processed here by
+ * default roughly once in a second. These actions include
+ * retransmissions of lost HIP control packets, keepalives for NATs,
+ * heartbeats to detect connectivity problems, purging of opportunistic
+ * mode state, delaying of UPDATE triggering until addresses have stabilized
+ * and publishing of hostname/hit/ip mappings in a DHT.
+ *
+ * @brief Hipd maintenance loop
+ *
+ * @note When adding new functionality, make sure that the socket
+ *       calls do not block because hipd is single threaded.
  */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "maintenance.h"
 #include "update.h"
 #include "heartbeat.h"
 #include "hipd.h"
+#include "lib/core/hip_udp.h"
 
 #define FORCE_EXIT_COUNTER_START                5
 
@@ -45,7 +49,11 @@
 static int hip_agent_add_lhits(void);
 
 /**
- * Handle packet retransmissions.
+ * an iterator to handle packet retransmission for a given host association
+ *
+ * @param entry the host association which to handle
+ * @param current_time current time
+ * @return zero on success or negative on failure
  */
 static int hip_handle_retransmission(hip_ha_t *entry, void *current_time)
 {
@@ -115,6 +123,12 @@
 }
 
 #ifdef CONFIG_HIP_OPPORTUNISTIC
+/**
+ * scan for opportunistic connections that should time out
+ * and give up (fall back to normal TCP/IP)
+ *
+ * @return zero on success or negative on failure
+ */
 static int hip_scan_opp_fallback(void)
 {
     int err = 0;
@@ -130,7 +144,9 @@
 #endif
 
 /**
- * Find packets, that should be retransmitted.
+ * deliver pending retransmissions for all host associations
+ *
+ * @return zero on success or negative on failure
  */
 static int hip_scan_retransmissions(void)
 {
@@ -145,7 +161,9 @@
 
 #ifdef CONFIG_HIP_AGENT
 /**
- * Send one local HIT to agent, enumerative function.
+ * An enumerator to inform agent on a new local HIT
+ *
+ * @return zero on success or negative on failure
  */
 static int hip_agent_add_lhit(struct hip_host_id_entry *entry, void *msg)
 {
@@ -167,7 +185,9 @@
 
 
 /**
- * Send local HITs to agent.
+ * Send all local HITs to the GUI agent
+ *
+ * @return zero on success or negative on failure
  */
 static int hip_agent_add_lhits(void)
 {
@@ -216,7 +236,14 @@
 }
 
 /**
- * Filter packet trough agent.
+ * Filter packet trough agent
+ *
+ * @param msg the control packet to filter
+ * @param src_addr the source address of the packet
+ * @param dst_addr the destination ddress of the packet
+ * @param msg_info transport port information on the packet
+ *
+ * @return zero on success or negative on failure
  */
 int hip_agent_filter(struct hip_common *msg,
                      struct in6_addr *src_addr,
@@ -264,7 +291,14 @@
 }
 
 /**
- * Send new status of given state to agent.
+ * inform agent on changes of in HADB state
+ *
+ * @param msg_type the type of the message
+ * @param data any kind of data to encapsulate inside
+ *             a HIP parameter
+ * @param size the length of the @c data in bytes
+ *
+ * @return zero on success or negative on failure
  */
 int hip_agent_update_status(int msg_type, void *data, size_t size)
 {
@@ -299,7 +333,9 @@
 }
 
 /**
- * Update different items status to agent.
+ * Update agent on local HIT status
+ *
+ * @return zero on success or negative on failure
  */
 int hip_agent_update(void)
 {
@@ -311,7 +347,7 @@
 /**
  * Periodic maintenance.
  *
- * @return ...
+ * @return zero on success or negative on failure
  */
 int hip_periodic_maintenance()
 {
@@ -447,11 +483,23 @@
     return err;
 }
 
+/**
+ * get the current running status of firewall
+ *
+ * @return one if firewall is running or zero otherwise
+ * @todo this is redundant with hip_firewall_is_alive()
+ */
 int hip_get_firewall_status()
 {
     return hip_firewall_status;
 }
 
+/**
+ *
+ * get the current running status of firewall
+ *
+ * @return one if firewall is running or zero otherwise
+ */
 int hip_firewall_is_alive()
 {
 #ifdef CONFIG_HIP_FIREWALL
@@ -467,78 +515,17 @@
 #endif // CONFIG_HIP_FIREWALL
 }
 
-int hip_firewall_set_i2_data(int action,  hip_ha_t *entry,
-                             struct in6_addr *hit_s,
-                             struct in6_addr *hit_r,
-                             struct in6_addr *src,
-                             struct in6_addr *dst)
-{
-    struct hip_common *msg = NULL;
-    struct sockaddr_in6 hip_firewall_addr;
-    int err                = 0, n = 0;
-    HIP_IFEL(!(msg = HIP_MALLOC(HIP_MAX_PACKET, 0)), -1, "alloc\n");
-    hip_msg_init(msg);
-    HIP_IFEL(hip_build_user_hdr(msg, action, 0), -1,
-             "Build hdr failed\n");
-
-    HIP_IFEL(hip_build_param_contents(msg, (void *) hit_r, HIP_PARAM_HIT,
-                                      sizeof(struct in6_addr)), -1, "build 
param contents failed\n");
-    HIP_IFEL(hip_build_param_contents(msg, (void *) src, HIP_PARAM_HIT,
-                                      sizeof(struct in6_addr)), -1, "build 
param contents failed\n");
-
-    socklen_t alen = sizeof(hip_firewall_addr);
-
-    bzero(&hip_firewall_addr, alen);
-    hip_firewall_addr.sin6_family = AF_INET6;
-    hip_firewall_addr.sin6_port   = htons(HIP_FIREWALL_PORT);
-    hip_firewall_addr.sin6_addr   = in6addr_loopback;
-
-    // if (hip_get_firewall_status()) {
-    n                             = sendto(hip_firewall_sock_lsi_fd, (char *) 
msg, hip_get_msg_total_len(msg),
-                                           0, (struct sockaddr *) 
&hip_firewall_addr, alen);
-    //}
-
-    if (n < 0) {
-        HIP_DEBUG("Send to firewall failed str errno %s\n", strerror(errno));
-    }
-    HIP_IFEL( n < 0, -1, "Sendto firewall failed.\n");
-
-    HIP_DEBUG("Sendto firewall OK.\n");
-
-out_err:
-    if (msg) {
-        free(msg);
-    }
-
-    return err;
-}
-
-int hip_firewall_set_savah_status(int status)
-{
-    int n, err = 0;
-    struct sockaddr_in6 sock_addr;
-    struct hip_common *msg = NULL;
-    bzero(&sock_addr, sizeof(sock_addr));
-    sock_addr.sin6_family = AF_INET6;
-    sock_addr.sin6_port   = htons(HIP_FIREWALL_PORT);
-    sock_addr.sin6_addr   = in6addr_loopback;
-
-    HIP_IFEL(!(msg = HIP_MALLOC(HIP_MAX_PACKET, 0)), -1, "alloc\n");
-    hip_msg_init(msg);
-
-    hip_build_user_hdr(msg, status, 0);
-
-    n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr);
-
-    HIP_IFEL(n < 0, 0, "sendto() failed\n");
-
-    if (err == 0) {
-        HIP_DEBUG("SEND SAVAH SERVER STATUS OK.\n");
-    }
-out_err:
-    return err;
-}
-
+/**
+ * Update firewall on host association state. Currently used by the
+ * LSI and system-based opportunistic mode in the firewall.
+ *
+ * @param action SO_HIP_FW_UPDATE_DB or SO_HIP_FW_BEX_DONE
+ * @param entry the host association
+ * @param hit_s optional source HIT
+ * @param hit_r optional destination HIT
+ *
+ * @return zero on success or negative on failure
+ */
 int hip_firewall_set_bex_data(int action, hip_ha_t *entry, struct in6_addr 
*hit_s, struct in6_addr *hit_r)
 {
     struct hip_common *msg = NULL;
@@ -590,14 +577,14 @@
 }
 
 /**
- * This function calculates RTT and ... and then stores them to correct entry
+ * This function calculates RTT and then stores them to correct entry
  *
  * @param src HIT
  * @param dst HIT
  * @param time when sent
  * @param time when received
  *
- * @return 0 if success negative otherwise
+ * @return zero on success or negative on failure
  */
 int hip_icmp_statistics(struct in6_addr *src, struct in6_addr *dst,
                         struct timeval *stval, struct timeval *rtval)
@@ -641,6 +628,13 @@
     return err;
 }
 
+/**
+ * tell firewall to turn on or off the ESP relay mode
+ *
+ * @param action SO_HIP_OFFER_FULLRELAY or SO_HIP_CANCEL_FULLRELAY
+ *
+ * @return zero on success or negative on failure
+ */
 int hip_firewall_set_esp_relay(int action)
 {
     struct hip_common *msg = NULL;

=== modified file 'hipd/nat.c'
--- hipd/nat.c  2010-02-17 17:38:08 +0000
+++ hipd/nat.c  2010-03-19 09:53:35 +0000
@@ -254,9 +254,8 @@
  */
 hip_transform_suite_t hip_nat_set_control(hip_ha_t *entry, 
hip_transform_suite_t mode)
 {
-#ifdef HIP_USE_ICE
     hip_ha_set_nat_mode(entry, &mode);
-#endif
+
     return 0;
 }
 

=== modified file 'hipd/nat.h'
--- hipd/nat.h  2010-02-17 17:38:08 +0000
+++ hipd/nat.h  2010-03-19 09:53:35 +0000
@@ -27,15 +27,6 @@
  *  @todo Change this value. */
 #define HIP_NAT_KEEP_ALIVE_INTERVAL 20
 /** Port number for NAT traversal of hip control packets. */
-#define HIP_NAT_UDP_PORT 10500
-#define HIP_NAT_TURN_PORT 10500
-
-/** For setting socket to listen for beet-udp packets. */
-#define HIP_UDP_ENCAP 100
-/** UDP encapsulation type. */
-#define HIP_UDP_ENCAP_ESPINUDP 2
-/** UDP encapsulation type. */
-#define HIP_UDP_ENCAP_ESPINUDP_NONIKE 1
 
 extern HIP_HASHTABLE *hadb_hit;
 hip_transform_suite_t hip_get_nat_mode(hip_ha_t *entry);

=== modified file 'hipd/netdev.c'
--- hipd/netdev.c       2010-03-19 09:24:10 +0000
+++ hipd/netdev.c       2010-03-19 09:53:35 +0000
@@ -21,18 +21,21 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include <net/if.h>
 #include <netinet/in.h>
+
+#include "config.h"
 #include "lib/tool/nlink.h"
+#include "accessor.h"
 #include "netdev.h"
 #include "maintenance.h"
 #include "lib/dht/libhipdht.h"
 #include "lib/core/debug.h"
 #include "lib/tool/lutil.h"
 #include "lib/conf/hipconf.h"
+#include "lib/core/hostsfiles.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/hit.h"
 #include "hipd.h"
 
 /**
@@ -102,7 +105,7 @@
     int ret  = 0;
 
     ifr.ifr_ifindex = -1;
-    strncpy(ifr.ifr_name, device_name, (size_t) IFNAMSIZ);
+    strncpy(ifr.ifr_name, device_name, (size_t) IF_NAMESIZE);
     sock            = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
     if (ioctl(sock, SIOCGIFINDEX, &ifr) == 0) {
@@ -825,8 +828,6 @@
      * depending on dst_hit value.
      * If dst_hit is a HIT -> find LSI and hostname
      * If dst_hit is an LSI -> find HIT and hostname
-     * The natural place to handle this is either in the getaddrinfo or
-     * getendpointinfo function with AI_NUMERICHOST flag set.
      * We can fallback to e.g. DHT search if the mapping is not
      * found from local files.*/
 

=== modified file 'hipd/netdev.h'
--- hipd/netdev.h       2010-03-03 13:16:18 +0000
+++ hipd/netdev.h       2010-03-19 09:53:35 +0000
@@ -8,15 +8,12 @@
 #include <sys/socket.h>
 #include <netinet/ip6.h>
 #include <openssl/rand.h>
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/tool/nlink.h"
 #include "lib/core/list.h"
 #include "lib/core/debug.h"
 #include "lib/core/prefix.h"
-#include "lib/core/misc.h"
+
 #include "hit_to_ip.h"
 
 #ifdef CONFIG_HIP_MAEMO

=== modified file 'hipd/nsupdate.c'
--- hipd/nsupdate.c     2010-02-17 17:38:08 +0000
+++ hipd/nsupdate.c     2010-03-19 09:53:35 +0000
@@ -24,12 +24,10 @@
 #include <string.h>
 #include <sys/resource.h> // for getrlimit
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
+#include "config.h"
 #include "hidb.h"
 #include "nsupdate.h"
+#include "lib/core/hit.h"
 
 // parameters for nsupdate.pl
 #define VAR_IPS "HIPD_IPS"

=== modified file 'hipd/oppdb.c'
--- hipd/oppdb.c        2010-03-03 13:16:18 +0000
+++ hipd/oppdb.c        2010-03-19 09:53:35 +0000
@@ -1,24 +1,50 @@
-/*
- * hipd oppdb.c
- *
- * Licence: GNU/GPL
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * Opportunistic mode databases for lib/opphip and HIP registration. The 
system-based
+ * opportunistic mode in the firewall uses also this functionality to trigger 
an
+ * opportunistic base base exchange. See the following publication on the 
details:
+ *
+ * <a href="http://www.iki.fi/miika/docs/ccnc09.pdf";>
+ * Miika Komu and Janne Lindqvist, Leap-of-Faith Security is Enough
+ * for IP Mobility, 6th Annual IEEE Consumer
+ * Communications & Networking Conference IEEE CCNC 2009, Las Vegas,
+ * Nevada, January 2009</a>
+ *
+ * The pseudo HIT is mentioned on multiple places in this file. When hipd sends
+ * the opportunistic I1, the destination HIT is NULL. For this reason, we don't
+ * know the Responder HIT until receiving the R2. During this unawareness 
period,
+ * we use a "pseudo HIT" to denote the Responder. It is calculated by 
extracting
+ * part of the IP address of the Responder and prefixing it with HIT prefix 
and some
+ * additional zeroes. Once the R1 received, the opportunistic database entry 
can
+ * be removed and the pseudo HIT becomes unnecessary. Consequtive opportunistic
+ * mode connections with the same Responder are cached and the pseudo HIT is 
not needed.
+ *
+ * The opportunistic mode supports also "fallback" which occurs with
+ * peers that do not support HIP. When the peer does not support HIP,
+ * hipd notices it after a certain time out in maintenance.c loop
+ * because there was no R1 response. The handlers in this function
+ * then send a "reject" message to the blocked opportunistic library
+ * process which means that it should proceed without HIP. Consequtive
+ * rejects are faster because they are cached.
+ *
+ * See firewall/opptcp.c extension on how the initial timeout can be
+ * reduced to a single round-trip time.
+ *
  * Authors:
  * - Bing Zhou <bingzhou@xxxxxxxxx>
- *
  */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#ifdef CONFIG_HIP_OPPORTUNISTIC
-
+#include "config.h"
 #include "oppdb.h"
 #include "hadb.h"
 #include "accessor.h"
+#include "lib/core/hit.h"
 
 #define HIP_LOCK_OPP_INIT(entry)
 #define HIP_UNLOCK_OPP_INIT(entry)
@@ -54,6 +80,12 @@
                               hip_portpair_t *msg_info);
 static int hip_force_opptcp_fallback(hip_opp_block_t *entry, void *ips);
 
+/**
+ * hashing function for the hashtable implementation
+ *
+ * @param a pointer to a hip_opp_block_t structure
+ * @return the calculated hash
+ */
 static unsigned long hip_oppdb_hash_hit(const void *ptr)
 {
     hip_opp_block_t *entry = (hip_opp_block_t *) ptr;
@@ -66,17 +98,30 @@
     return *((unsigned long *) (void *) hash);
 }
 
+/**
+ * matching function for the hashtable implementation
+ *
+ * @param ptr1 a pointer to a hip_opp_block_t structure
+ * @param ptr2 a pointer to a hip_opp_block_t structure
+ * @return zero on match or non-zero otherwise
+ */
 static int hip_oppdb_match_hit(const void *ptr1, const void *ptr2)
 {
     return hip_hash_hit(ptr1) != hip_hash_hit(ptr2);
 }
 
+/**
+ * expire an opportunistic connection
+ *
+ * @param opp_entry the entry to be expired
+ * @return zero on success or negative on error
+ */
 int hip_oppdb_entry_clean_up(hip_opp_block_t *opp_entry)
 {
     int err = 0;
 
-    /* XX FIXME: this does not support multiple multiple opp
-     * connections: a better solution might be trash collection  */
+    /** @todo this does not support multiple multiple opp
+        connections: a better solution might be trash collection  */
 
     HIP_ASSERT(opp_entry);
     err = hip_del_peer_info(&opp_entry->peer_phit,
@@ -86,6 +131,13 @@
     return err;
 }
 
+/**
+ * a for-each iterator function for the opportunistic database
+ *
+ * @param func a callback iterator function
+ * @param opaque an extra parameter to be passed to the callback
+ * @return zero on success and non-zero on error
+ */
 int hip_for_each_opp(int (*func)(hip_opp_block_t *entry, void *opaq), void 
*opaque)
 {
     int i = 0, fail = 0;
@@ -113,7 +165,11 @@
     return fail;
 }
 
-//void hip_hadb_delete_hs(struct hip_hit_spi *hs)
+/**
+ * delete an opportunistic database entry
+ *
+ * @param entry the entry to be deleted
+ */
 static void hip_oppdb_del_entry_by_entry(hip_opp_block_t *entry)
 {
     hip_opp_block_t *deleted;
@@ -126,18 +182,38 @@
     //HIP_FREE(entry);
 }
 
+/**
+ * an iterator function for uninitializing the opportunistic database
+ *
+ * @param entry the entry to be uninitialized
+ * @param unused unused
+ * @return zero
+ */
 static int hip_oppdb_uninit_wrap(hip_opp_block_t *entry, void *unused)
 {
     hip_oppdb_del_entry_by_entry(entry);
     return 0;
 }
 
+/**
+ * uninitialize the whole opportunistic database
+ */
 void hip_oppdb_uninit(void)
 {
     hip_for_each_opp(hip_oppdb_uninit_wrap, NULL);
     hip_ht_uninit(oppdb);
+    oppdb = NULL;
 }
 
+/**
+ * Unblock a caller from the opportunistic library
+ *
+ * @param app_id the UDP port of the local library process
+ * @param opp_info information related to the opportunistic connection
+ * @param reject Zero if Responder supports HIP or one if Responder
+ *               did not respond within a certain timeout (should fallback to 
TCP/IP).
+ * @return zero on success or negative on failure
+ */
 static int hip_opp_unblock_app(const struct sockaddr_in6 *app_id, 
hip_opp_info_t *opp_info,
                                int reject)
 {
@@ -217,6 +293,13 @@
     return err;
 }
 
+/**
+ * unblock all opportunistic connections with a certain remote host
+ *
+ * @param entry the opportunistic mode connection
+ * @param ptr the pseudo HIT denoting the remote host
+ * @return zero on success or negative on error
+ */
 static int hip_oppdb_unblock_group(hip_opp_block_t *entry, void *ptr)
 {
     hip_opp_info_t *opp_info = (hip_opp_info_t *) ptr;
@@ -235,6 +318,11 @@
     return err;
 }
 
+/**
+ * create a opportunistic mode database entry
+ *
+ * @return the created databased entry (caller deallocates)
+ */
 static hip_opp_block_t *hip_create_opp_block_entry(void)
 {
     hip_opp_block_t *entry = NULL;
@@ -247,17 +335,23 @@
 
     memset(entry, 0, sizeof(*entry));
 
-//INIT_LIST_HEAD(&entry->next_entry);
-
     HIP_LOCK_OPP_INIT(entry);
-    //atomic_set(&entry->refcnt,0);
     time(&entry->creation_time);
     HIP_UNLOCK_OPP_INIT(entry);
 
     return entry;
 }
 
-//int hip_hadb_add_peer_info(hip_hit_t *peer_hit, struct in6_addr *peer_addr)
+/**
+ * add an opportunistic mode connection entry to the database
+ *
+ * @param phit_peer the pseudo HIT of peer
+ * @param hit_our local HIT
+ * @param ip_peer remote IP address
+ * @param ip_our local IP address
+ * @param caller the UDP port of the local library process
+ * @return zero on success or negative on failure
+ */
 static int hip_oppdb_add_entry(const hip_hit_t *phit_peer,
                                const hip_hit_t *hit_our,
                                const struct in6_addr *ip_peer,
@@ -292,11 +386,17 @@
     return err;
 }
 
+/**
+ * initialize the opportunistic database
+ */
 void hip_init_opp_db(void)
 {
     oppdb = hip_ht_init(hip_oppdb_hash_hit, hip_oppdb_match_hit);
 }
 
+/**
+ * dump the contents of the database
+ */
 static void hip_oppdb_dump(void)
 {
     int i;
@@ -321,6 +421,14 @@
     HIP_DEBUG("end oppdb dump\n");
 }
 
+/**
+ * fetch an hadb entry corresponding to a pseudo HIT
+ *
+ * @param init_hit the local HIT of the Initiator
+ * @param resp_addr the remote IP address of the Responder from
+ *                  which to calculate the pseudo HIT
+ * @return a host assocition or NULL if not found
+ */
 hip_ha_t *hip_oppdb_get_hadb_entry(hip_hit_t *init_hit,
                                    struct in6_addr *resp_addr)
 {
@@ -341,6 +449,15 @@
     return entry_tmp;
 }
 
+/**
+ * find a host association based on I1 or R1 message
+ *
+ * @param msg the I1 or R2 message
+ * @param src_addr the source address of the message
+ * @param dst_addr the destination address of the message
+ * @param msg_info the transport layer port numbers (UDP tunnel)
+ * @return the host association or NULL if not found
+ */
 hip_ha_t *hip_oppdb_get_hadb_entry_i1_r1(struct hip_common *msg,
                                          struct in6_addr *src_addr,
                                          struct in6_addr *dst_addr,
@@ -365,6 +482,16 @@
     return entry;
 }
 
+/**
+ * process an incoming R1 packet
+ *
+ * @param msg the R1 packet
+ * @param src_addr the source address of the message
+ * @param dst_addr the destination address of the message
+ * @param opp_entry the opportunistic database entry
+ * @param msg_info the transport layer port numbers (UDP tunnel)
+ * @return zero on success or negative on failure
+ */
 static int hip_receive_opp_r1(struct hip_common *msg,
                               struct in6_addr *src_addr,
                               struct in6_addr *dst_addr,
@@ -445,6 +572,15 @@
     return err;
 }
 
+/**
+ * add an entry to the opportunistic mode dabase and host association
+ * database (with pseudo HIT)
+ *
+ * @param dst_ip the remote IP address of the Responder
+ * @param hit_our the local HIT of the Initiator
+ * @param caller the UDP port of the local library process
+ * @return the created host association
+ */
 hip_ha_t *hip_opp_add_map(const struct in6_addr *dst_ip,
                           const struct in6_addr *hit_our,
                           const struct sockaddr_in6 *caller)
@@ -501,7 +637,13 @@
 }
 
 /**
- * No description.
+ * Trigger opportunistic I1 to obtain the HIT of the Responder.
+ * The TCP optimization may also be used if it is requested.
+ *
+ * @param msg contains information on the Responder's IP address
+ *            and on the use of the TCP optimization
+ * @param src the UDP port number of the calling library process
+ * @return zero on success or negative on failure
  */
 int hip_opp_get_peer_hit(struct hip_common *msg,
                          const struct sockaddr_in6 *src)
@@ -740,10 +882,14 @@
     return err;
 }
 
-/*
+/**
  * Used by opportunistic tcp option to force an application fallback
  * immediately (without timeout) to non-hip communications. This occurs
  * when the firewall detects that peer does not support HIP.
+ *
+ * @param entry the opportunistic mode connection entry
+ * @param data in6_addr the IP address of the Responder
+ * @return zero on success or negative on failure
  */
 static int hip_force_opptcp_fallback(hip_opp_block_t *entry, void *data)
 {
@@ -769,6 +915,14 @@
     return err;
 }
 
+/**
+ * check if it is time for an opportunistic connection to
+ * time out and make it happen when needed
+ *
+ * @param entry the database entry for the opportunistic connection
+ * @param current_time the current time
+ * @return zero on success or negative on failure
+ */
 int hip_handle_opp_fallback(hip_opp_block_t *entry,
                             void *current_time)
 {
@@ -777,7 +931,7 @@
     struct in6_addr *addr;
     //HIP_DEBUG("now=%d e=%d\n", *now, entry->creation_time);
 
-#if defined(CONFIG_HIP_AGENT) && defined(CONFIG_HIP_OPPORTUNISTIC)
+#ifdef CONFIG_HIP_AGENT
     /* If agent is prompting user, let's make sure that
     *  the death counter in maintenance does not expire */
     if (hip_agent_is_alive()) {
@@ -807,6 +961,13 @@
     return err;
 }
 
+/**
+ * reject an opportunistic mode connection
+ *
+ * @param entry the connection to reject
+ * @param data the remote IP address of the Responder
+ * @return zero on success or negative on failure
+ */
 int hip_handle_opp_reject(hip_opp_block_t *entry, void *data)
 {
     int err                  = 0;
@@ -828,13 +989,12 @@
 }
 
 /**
- * hip_oppdb_find_byip:
- * Seeks an ip within the oppdb hash table.
- * If the ip is found in the table, that host is not HIP capable.
+ * check if a remote host is not capable of HIP
  *
  * @param ip_peer: pointer to the ip of the host to check whether
- *                 it is HIP capable
- * @return pointer to the entry if the ip is found in the table; NULL otherwise
+ *                 it is HIP capable or not
+ * @return pointer to the entry if the remote host does not definitely support 
HIP or
+ *         NULL if it is potentially HIP capable
  */
 hip_opp_block_t *hip_oppdb_find_by_ip(const struct in6_addr *ip_peer)
 {
@@ -842,6 +1002,9 @@
     hip_opp_block_t *this, *ret = NULL;
     hip_list_t *item, *tmp;
 
+    if (oppdb == NULL)
+        return NULL;
+
     HIP_LOCK_HT(&opp_db);
     list_for_each_safe(item, tmp, oppdb, i)
     {
@@ -856,5 +1019,3 @@
     HIP_UNLOCK_HT(&opp_db);
     return ret;
 }
-
-#endif /* CONFIG_HIP_OPPORTUNISTIC */

=== modified file 'hipd/oppdb.h'
--- hipd/oppdb.h        2010-03-03 13:16:18 +0000
+++ hipd/oppdb.h        2010-03-19 09:53:35 +0000
@@ -13,7 +13,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include "lib/core/debug.h"
-#include "lib/core/misc.h"
+
 #include "hidb.h"
 #include "lib/core/hashtable.h"
 #include "lib/core/builder.h"
@@ -65,4 +65,5 @@
                      void *opaque);
 
 int hip_handle_opp_reject(hip_opp_block_t *entry, void *ips);
-#endif /* HIP_HADB_H */
+
+#endif /* HIP_HIPD_OPPDB_H */

=== modified file 'hipd/oppipdb.c'
--- hipd/oppipdb.c      2010-02-17 17:38:08 +0000
+++ hipd/oppipdb.c      2010-03-19 09:53:35 +0000
@@ -1,5 +1,7 @@
 /** @file
- * oppipdb.c:
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
  * This file defines handling functions for opportunistic mode to remember
  * IP's which are not HIP capable. This means faster communication in second
  * connection attempts to these hosts. Otherwise it would always take the same
@@ -8,16 +10,12 @@
  *
  * @author  Antti Partanen
  * @author  Alberto Garcia
- * @note    Distributed under <a 
href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>.
  */
 
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #ifdef CONFIG_HIP_OPPORTUNISTIC
 
 #include "oppipdb.h"
@@ -33,7 +31,6 @@
 static void hip_oppipdb_uninit_wrap(hip_oppip_t *entry, void *unused);
 
 /**
- * hip_oppipdb_hash_ip:
  * Generates the hash information that is used to index the table
  *
  * @param ptr: pointer to the ip address used to make the hash
@@ -65,7 +62,6 @@
 }
 
 /**
- * hip_for_each_oppip:
  * Map function @func to every entry in the oppipdb hash table
  *
  * @param func: mapper function to apply to all entries
@@ -101,7 +97,6 @@
 }
 
 /**
- * hip_oppipdb_del_entry_by_entry:
  * Deletes an entry that is present in oppipdb hash table
  *
  * @param entry: pointer to the entry to delete
@@ -115,7 +110,6 @@
 }
 
 /**
- * hip_oppipdb_uninit_wrap:
  * Wrap function for hip_oppipdb_del_entry_by_entry()
  *
  * @param entry: pointer to the entry to delete
@@ -129,7 +123,6 @@
 }
 
 /**
- * hip_oppipdb_uninit:
  * Deletes the whole oppipdb hash table
  */
 void hip_oppipdb_uninit(void)
@@ -138,7 +131,6 @@
 }
 
 /**
- * hip_create_oppip_entry:
  * Allocates and initilizes the node to store the information
  * in the oppipdb hash table
  *
@@ -160,7 +152,6 @@
 }
 
 /**
- * hip_oppipdb_add_entry:
  * Adds a new entry to the oppipdb hash table.
  * This table stores the ip addresses of the hosts that are not HIP capable.
  *
@@ -191,7 +182,6 @@
 }
 
 /**
- * hip_init_oppip_db:
  * Creates and initializes the oppipdb hash table
  *
  * @return 0 on success
@@ -204,7 +194,6 @@
 
 #if 0
 /**
- * hip_oppipdb_dump:
  * Dumps the whole oppipdb hash table for monitoring purposes
  */
 static void hip_oppipdb_dump(void)
@@ -229,7 +218,6 @@
 #endif
 
 /**
- * hip_oppipdb_find_byip:
  * Seeks an ip within the oppipdb hash table.
  * If the ip is found in the table, that host is not HIP capable.
  *
@@ -254,7 +242,6 @@
 }
 
 /**
- * hip_oppipdb_delentry:
  * This function should be called after receiving an R1 from the peer and after
  * a successful base exchange in the opportunistic mode. It checks whether an
  * address of a HIP capable host is found from database. If the address is

=== modified file 'hipd/output.c'
--- hipd/output.c       2010-03-19 09:24:10 +0000
+++ hipd/output.c       2010-03-19 09:53:35 +0000
@@ -16,10 +16,7 @@
 
 #include <netinet/icmp6.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "output.h"
 #ifdef CONFIG_HIP_PERFORMANCE
 #include "lib/performance/performance.h"
@@ -29,48 +26,14 @@
 #include "i3/i3_client/i3_client_id.h"
 #endif
 
+#include "lib/core/hip_udp.h"
+#include "lib/tool/checksum.h"
+
 enum number_dh_keys_t { ONE, TWO };
 
 enum number_dh_keys_t number_dh_keys = TWO;
 
 /**
- * Standard BSD internet checksum routine from nmap
- * for calculating the checksum field of the TCP header
- */
-unsigned short in_cksum(uint16_t *ptr, int nbytes)
-{
-    register uint32_t sum;
-    uint16_t oddbyte;
-    register uint16_t answer;
-
-    /*
-     * Our algorithm is simple, using a 32-bit accumulator (sum),
-     * we add sequential 16-bit words to it, and at the end, fold back
-     * all the carry bits from the top 16 bits into the lower 16 bits.
-     */
-    sum = 0;
-    while (nbytes > 1) {
-        sum    += *ptr++;
-        nbytes -= 2;
-    }
-
-    /* mop up an odd byte, if necessary */
-    if (nbytes == 1) {
-        oddbyte                = 0;     /* make sure top half is zero */
-        *((u_char *) &oddbyte) = *(u_char *) ptr;          /* one byte only */
-        sum                   += oddbyte;
-    }
-
-    /*
-     * Add back carry outs from top 16 bits to low 16 bits.
-     */
-    sum    = (sum >> 16) + (sum & 0xffff);      /* add high-16 to low-16 */
-    sum   += (sum >> 16);                       /* add carry */
-    answer = ~sum;              /* ones-complement, then truncate to 16 bits */
-    return answer;
-}
-
-/**
  * @brief Sends a TCP packet through a raw socket.
  *
  * @param  hdr
@@ -269,6 +232,7 @@
  *                  the peer. The src and dst ports are included in this 
parameter
  * @return          nothing
  */
+#ifdef CONFIG_HIP_OPPORTUNISTIC
 static void hip_send_opp_tcp_i1(hip_ha_t *entry)
 {
     int ipType = !IN6_IS_ADDR_V4MAPPED(&entry->peer_addr);
@@ -344,6 +308,7 @@
         send_tcp_packet(&bytes[0], hdr_size + 4 * tcphdr->doff, 6, 
hip_raw_sock_output_v6, 1, 0);
     }
 }
+#endif /* CONFIG_HIP_OPPORTUNISTIC */
 
 /**
  * Sends an I1 packet to the peer. Used internally by hip_send_i1
@@ -403,6 +368,7 @@
         err = 0;
     }
 
+#ifdef CONFIG_HIP_OPPORTUNISTIC
     /*send the TCP SYN_i1 packet*/
     if (hip_get_opportunistic_tcp_status() &&
         hit_is_opportunistic_hit(dst_hit)) {
@@ -410,6 +376,7 @@
         usleep(50);
         hip_send_opp_tcp_i1(entry);
     }
+#endif /* CONFIG_HIP_OPPORTUNISTIC */
 
     return err;
 }

=== modified file 'hipd/output.h'
--- hipd/output.h       2010-02-17 17:38:08 +0000
+++ hipd/output.h       2010-03-19 09:53:35 +0000
@@ -17,14 +17,11 @@
 #include <unistd.h>
 #include <string.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "dh.h"
 #include "hidb.h"
 #include "hadb.h"
-#include "lib/core/misc.h"
+
 #include "lib/core/builder.h"
 #include "cookie.h"
 #include "close.h"

=== modified file 'hipd/pfkeyapi.c'
--- hipd/pfkeyapi.c     2010-03-19 09:24:10 +0000
+++ hipd/pfkeyapi.c     2010-03-19 09:53:35 +0000
@@ -8,16 +8,11 @@
 /* required for caddr_t */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#ifdef CONFIG_HIP_PFKEY
-#include <libinet6/include/net/pfkeyv2.h>
-#include </usr/include/linux/pfkeyv2.h>
-#include </usr/include/linux/ipsec.h>
+#include "config.h"
 #include "lib/ipsec/libpfkey.h"
 #include "pfkeyapi.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/keylen.h"
 
 
 // FIXME: This must be turned to BEET when BEET will be supported by pfkey as 
well
@@ -441,5 +436,3 @@
     HIP_DEBUG("\n");
     return 0;
 }
-
-#endif /* CONFIG_HIP_PFKEY */

=== modified file 'hipd/pfkeyapi.h'
--- hipd/pfkeyapi.h     2010-02-17 13:08:39 +0000
+++ hipd/pfkeyapi.h     2010-03-19 09:53:35 +0000
@@ -1,10 +1,7 @@
 #ifndef HIP_HIPD_PFKEYAPI_H
 #define HIP_HIPD_PFKEYAPI_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/tool/xfrmapi.h"
 
 #endif /* HIP_HIPD_PFKEYAPI_H */

=== modified file 'hipd/registration.c'
--- hipd/registration.c 2010-02-17 17:38:08 +0000
+++ hipd/registration.c 2010-03-19 09:53:35 +0000
@@ -14,6 +14,7 @@
 #define _BSD_SOURCE
 
 #include "registration.h"
+#include "hadb.h"
 
 /**
  * Pending request lifetime. Pending requests are created when the requester

=== modified file 'hipd/registration.h'
--- hipd/registration.h 2010-02-17 17:38:08 +0000
+++ hipd/registration.h 2010-03-19 09:53:35 +0000
@@ -14,7 +14,6 @@
 #ifndef HIP_HIPD_REGISTRATION_H
 #define HIP_HIPD_REGISTRATION_H
 
-#include "lib/core/misc.h"
 #include "lib/core/builder.h" // For lifetime conversions.
 #include "lib/core/protodefs.h" // For service type values and hip_ha_t
 #ifndef __KERNEL__

=== modified file 'hipd/update.c'
--- hipd/update.c       2010-03-19 09:25:52 +0000
+++ hipd/update.c       2010-03-19 09:53:35 +0000
@@ -13,13 +13,12 @@
 /* requiread for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "update.h"
 
 #include "lib/core/protodefs.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/solve.h"
 #include "netdev.h"
 #include "lib/core/builder.h"
 #include "update_legacy.h"

=== modified file 'hipd/user.c'
--- hipd/user.c 2010-03-19 09:24:10 +0000
+++ hipd/user.c 2010-03-19 09:53:35 +0000
@@ -16,13 +16,13 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
+#include "accessor.h"
 #include "user.h"
 #include "esp_prot_anchordb.h"
 #include "lib/dht/libhipdht.h"
+#include "lib/core/hostid.h"
+#include "lib/core/hip_udp.h"
 #include "hipd.h"
 
 int hip_sendto_user(const struct hip_common *msg, const struct sockaddr *dst)
@@ -46,7 +46,6 @@
 int hip_handle_user_msg(hip_common_t *msg, struct sockaddr_in6 *src)
 {
     hip_hit_t *src_hit           = NULL, *dst_hit = NULL;
-    in6_addr_t *dst_ip           = NULL;
     hip_ha_t *entry              = NULL;
     int err                      = 0, msg_type = 0, n = 0, len = 0, reti = 0;
     int access_ok                = 0, is_root = 0;
@@ -353,8 +352,16 @@
                 hip_opendht_sock_hit = 
init_dht_gateway_socket_gw(hip_opendht_sock_hit, opendht_serving_gateway);
                 hip_opendht_hit_sent = STATE_OPENDHT_IDLE;
             }
-            hip_init_dht_sockets(&hip_opendht_sock_fqdn, 
&hip_opendht_fqdn_sent);
-            hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent);
+            ret = hip_init_dht_sockets(&hip_opendht_sock_fqdn, 
&hip_opendht_fqdn_sent);
+            if (ret < 0) {
+                close(hip_opendht_sock_fqdn);
+                hip_opendht_sock_fqdn = -1;
+            }
+            ret = hip_init_dht_sockets(&hip_opendht_sock_hit, 
&hip_opendht_hit_sent);
+            if (ret < 0) {
+                close(hip_opendht_sock_hit);
+                hip_opendht_sock_hit = -1;
+            }
         } else {
             HIP_DEBUG("Error in changing the serving gateway!");
         }
@@ -702,6 +709,7 @@
         struct hip_reg_request *reg_req    = NULL;
         hip_pending_request_t *pending_req = NULL;
         uint8_t *reg_types                 = NULL;
+        in6_addr_t *dst_ip                 = NULL;
         int i                              = 0, type_count = 0;
         int opp_mode                       = 0;
         int add_to_global                  = 0;
@@ -1257,12 +1265,10 @@
         if (nat_port) {
             HIP_DEBUG("Setting local NAT port\n");
             hip_set_local_nat_udp_port(nat_port->port);
-            // We need to recreate the NAT UDP sockets to bind to the new port.
-            close(hip_nat_sock_output_udp);
+            /* We need to recreate only the input socket to bind to the new
+               port. Output port must be left intact as it is a raw socket */
             close(hip_nat_sock_input_udp);
-            hip_nat_sock_output_udp = 0;
             hip_nat_sock_input_udp  = 0;
-            hip_create_nat_sock_udp(&hip_nat_sock_output_udp, 0, 1);
             hip_create_nat_sock_udp(&hip_nat_sock_input_udp, 0, 0);
         } else {
             HIP_DEBUG("Setting peer NAT port\n");

=== modified file 'hipd/user_ipsec_hipd_msg.c'
--- hipd/user_ipsec_hipd_msg.c  2010-02-17 14:11:29 +0000
+++ hipd/user_ipsec_hipd_msg.c  2010-03-19 09:53:35 +0000
@@ -14,6 +14,9 @@
 #define _BSD_SOURCE
 
 #include "user_ipsec_hipd_msg.h"
+#include "hipd.h"
+#include "init.h"
+#include "user_ipsec_sadb_api.h"
 #include "lib/core/builder.h"
 
 /**

=== modified file 'i3/i3_client/http.c'
--- i3/i3_client/http.c 2010-02-17 17:38:08 +0000
+++ i3/i3_client/http.c 2010-03-19 09:53:35 +0000
@@ -17,6 +17,7 @@
 #include <sys/types.h>
 #include <string.h>
 #include <errno.h>
+#include <arpa/inet.h>
 #ifndef _WIN32
         #include <unistd.h>
 #endif

=== modified file 'i3/i3_client/i3_client_context.c'
--- i3/i3_client/i3_client_context.c    2010-02-17 17:38:08 +0000
+++ i3/i3_client/i3_client_context.c    2010-03-19 09:53:35 +0000
@@ -15,6 +15,7 @@
 #include <string.h>
 #include <sys/types.h>   /* basic system data types */
 #include <time.h>        /* timespec{} for pselect() */
+#include <arpa/inet.h>
 #ifndef _WIN32
     #include <unistd.h>
     #include <sys/errno.h>

=== modified file 'i3/i3_client/i3_client_pkt.c'
--- i3/i3_client/i3_client_pkt.c        2010-02-17 17:38:08 +0000
+++ i3/i3_client/i3_client_pkt.c        2010-03-19 09:53:35 +0000
@@ -10,6 +10,7 @@
 #include <string.h>
 #include <sys/types.h>   /* basic system data types */
 #include <time.h>        /* timespec{} for pselect() */
+#include <arpa/inet.h>
 #ifndef _WIN32
     #include <sys/time.h>    /* timeval{} for select() */
     #include <sys/errno.h>

=== modified file 'i3/i3_client/i3_client_trigger.c'
--- i3/i3_client/i3_client_trigger.c    2010-02-17 17:38:08 +0000
+++ i3/i3_client/i3_client_trigger.c    2010-03-19 09:53:35 +0000
@@ -18,10 +18,7 @@
     #include <sys/time.h>
 #endif
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "../i3/i3.h"
 #include "../i3/i3_fun.h"
 

=== modified file 'i3/i3_client/i3server_list.c'
--- i3/i3_client/i3server_list.c        2010-02-17 17:38:08 +0000
+++ i3/i3_client/i3server_list.c        2010-03-19 09:53:35 +0000
@@ -13,6 +13,7 @@
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <arpa/inet.h>
 #ifndef _WIN32
         #include <pthread.h>
 #endif

=== modified file 'i3/i3_client/ping.c'
--- i3/i3_client/ping.c 2010-02-17 17:38:08 +0000
+++ i3/i3_client/ping.c 2010-03-19 09:53:35 +0000
@@ -3,6 +3,7 @@
 
 #include <sys/types.h>
 #include <string.h>
+#include <arpa/inet.h>
 #ifndef _WIN32
     #include <unistd.h>
 #endif

=== modified file 'i3/i3_client/ping_thread.c'
--- i3/i3_client/ping_thread.c  2010-02-17 17:38:08 +0000
+++ i3/i3_client/ping_thread.c  2010-03-19 09:53:35 +0000
@@ -11,6 +11,7 @@
 
 
 #include <stdio.h>
+#include <arpa/inet.h>
     #include <errno.h>
 #ifndef _WIN32
     #include <pthread.h>

=== modified file 'lib/android/regex.c'
--- lib/android/regex.c 2010-02-18 14:58:39 +0000
+++ lib/android/regex.c 2010-03-19 09:53:35 +0000
@@ -27,9 +27,7 @@
 #undef  _GNU_SOURCE
 #define _GNU_SOURCE
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "config.h"
 
 /* We need this for `regex.h', and perhaps for the Emacs include files.  */
 #include <sys/types.h>

=== modified file 'lib/conf/hipconf.c'
--- lib/conf/hipconf.c  2010-03-03 13:16:18 +0000
+++ lib/conf/hipconf.c  2010-03-19 09:53:35 +0000
@@ -35,15 +35,17 @@
 /* required for ifreq */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include <sys/ioctl.h>
+#include "config.h"
 #include "lib/core/builder.h"
 #include "lib/core/debug.h"
+#include "lib/core/straddr.h"
 #include "hipconf.h"
 #include "lib/core/prefix.h"
 #include "lib/dht/libhipdht.h"
+#include "lib/core/hostid.h"
+#include "lib/core/message.h"
+#include "lib/core/crypto.h"
 
 /**
  * TYPE_ constant list, as an index for each action_handler function.
@@ -117,13 +119,8 @@
     "new hi anon|pub rsa|dsa filebasename keylen\n"
     "new|add hi default (HI must be created as root)\n"
     "new hi default rsa_keybits dsa_keybits\n"
-#ifdef CONFIG_HIP_ICOOKIE
-    "get|inc|dec|new puzzle all|<hit>\n"
-    "set puzzle all|<hit> new_value\n"
-#else
     "get|inc|dec|new puzzle all\n"
     "set puzzle all new_value\n"
-#endif
     "bos all\n"
     "nat none|plain-udp\n"
     "nat port local <port>\n"

=== modified file 'lib/conf/hipconf.h'
--- lib/conf/hipconf.h  2010-02-17 17:38:08 +0000
+++ lib/conf/hipconf.h  2010-03-19 09:53:35 +0000
@@ -15,11 +15,9 @@
 #ifndef HIP_LIB_CONF_HIPCONF_H
 #define HIP_LIB_CONF_HIPCONF_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #include <stdlib.h>
+
+#include "config.h"
 #include "lib/core/protodefs.h"
 
 /*
@@ -84,6 +82,8 @@
 # opp normal|advanced|none\n\
 # transform order 213 # crypto preference order (1=AES, 2=3DES, 3=NULL)\n\
 nat plain-udp       # use UDP capsulation (for NATted environments)\n\
+#nat port local 11111 # change local default UDP port\n\
+#nat port peer 22222 # change local peer UDP port\n\
 debug medium        # debug verbosity: all, medium or none\n"
 
 #define HOSTS_FILE "/etc/hosts"

=== modified file 'lib/core/builder.c'
--- lib/core/builder.c  2010-03-19 09:24:10 +0000
+++ lib/core/builder.c  2010-03-19 09:53:35 +0000
@@ -68,13 +68,12 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include <config.h>
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "builder.h"
 #include "hipd/input.h"
 #include "lib/core/crypto.h"
+#include "lib/core/hostid.h"
+#include "lib/tool/checksum.h"
 
 /* Not needed, already defined in netinet/in.h */
 /* #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } */
@@ -2007,93 +2006,6 @@
 }
 
 /**
- * Calculates the checksum of a HIP packet with pseudo-header.
- *
- * @param data a pointer to a hip_common structure
- * @param src  The source address of the packet as a sockaddr_in or 
sockaddr_in6
- *             structure in network byte order. IPv6 mapped addresses are not 
supported.
- * @param dst  The destination address of the packet as a sockaddr_in or 
sockaddr_in6
- *             structure in network byte order. IPv6 mapped addresses are not 
supported.
- * @return     the checksum
- * @note       Checksumming is from Boeing's HIPD.
- */
-uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst)
-{
-    uint16_t checksum      = 0;
-    unsigned long sum = 0;
-    int count         = 0, length = 0;
-    unsigned short *p = NULL;     /* 16-bit */
-    struct pseudo_header pseudoh;
-    struct pseudo_header6 pseudoh6;
-    uint32_t src_network, dst_network;
-    struct in6_addr *src6, *dst6;
-    struct hip_common *hiph = (struct hip_common *) data;
-
-    if (src->sa_family == AF_INET) {
-        /* IPv4 checksum based on UDP-- Section 6.1.2 */
-        src_network = ((struct sockaddr_in *) src)->sin_addr.s_addr;
-        dst_network = ((struct sockaddr_in *) dst)->sin_addr.s_addr;
-
-        memset(&pseudoh, 0, sizeof(struct pseudo_header));
-        memcpy(&pseudoh.src_addr, &src_network, 4);
-        memcpy(&pseudoh.dst_addr, &dst_network, 4);
-        pseudoh.protocol      = IPPROTO_HIP;
-        length                = (hiph->payload_len + 1) * 8;
-        pseudoh.packet_length = htons(length);
-
-        count                 = sizeof(struct pseudo_header); /* count always 
even number */
-        p                     = (unsigned short *) &pseudoh;
-    } else {
-        /* IPv6 checksum based on IPv6 pseudo-header */
-        src6 = &((struct sockaddr_in6 *) src)->sin6_addr;
-        dst6 = &((struct sockaddr_in6 *) dst)->sin6_addr;
-
-        memset(&pseudoh6, 0, sizeof(struct pseudo_header6));
-        memcpy(&pseudoh6.src_addr[0], src6, 16);
-        memcpy(&pseudoh6.dst_addr[0], dst6, 16);
-        length                 = (hiph->payload_len + 1) * 8;
-        pseudoh6.packet_length = htonl(length);
-        pseudoh6.next_hdr      = IPPROTO_HIP;
-
-        count                  = sizeof(struct pseudo_header6); /* count 
always even number */
-        p                      = (unsigned short *) &pseudoh6;
-    }
-    /*
-     * this checksum algorithm can be found
-     * in RFC 1071 section 4.1
-     */
-
-    /* sum the pseudo-header */
-    /* count and p are initialized above per protocol */
-    while (count > 1) {
-        sum   += *p++;
-        count -= 2;
-    }
-
-    /* one's complement sum 16-bit words of data */
-    HIP_DEBUG("Checksumming %d bytes of data.\n", length);
-    count = length;
-    p     = (unsigned short *) data;
-    while (count > 1) {
-        sum   += *p++;
-        count -= 2;
-    }
-    /* add left-over byte, if any */
-    if (count > 0) {
-        sum += (unsigned char) *p;
-    }
-
-    /*  Fold 32-bit sum to 16 bits */
-    while (sum >> 16) {
-        sum = (sum & 0xffff) + (sum >> 16);
-    }
-    /* take the one's complement of the sum */
-    checksum = ~sum;
-
-    return checksum;
-}
-
-/**
  * sanity checking for a HIP control packet originating from the network
  *
  * @param src  The source address of the packet as a sockaddr_in or 
sockaddr_in6
@@ -2134,14 +2046,9 @@
     /** @todo handle the RVS case better. */
     if (ipv6_addr_any(&hip_common->hitr)) {
         /* Required for e.g. BOS */
-        HIP_DEBUG("Received opportunistic HIT\n");
+        HIP_DEBUG("Received a connection to opportunistic HIT\n");
     } else {
-#ifdef CONFIG_HIP_RVS
-        HIP_DEBUG("Received HIT is ours or we are RVS\n");
-#else
-        HIP_IFEL(!hip_hidb_hit_is_our(&hip_common->hitr), -EFAULT,
-                 "Receiver HIT is not ours\n");
-#endif /* CONFIG_HIP_RVS */
+        HIP_DEBUG_HIT("Received a connection to HIT", &hip_common->hitr);
     }
 
     /* Check checksum. */
@@ -4888,3 +4795,41 @@
 
     return err;
 }
+
+/**
+ * calculate a digest over given data
+ * @param type the type of digest, e.g. "sha1"
+ * @param in the beginning of the data to be digested
+ * @param in_len the length of data to be digested in octets
+ * @param out the digest
+ *
+ * @note out should be long enough to hold the digest. This cannot be
+ * checked!
+ *
+ * @return 0 on success and negative on error.
+ */
+int hip_build_digest(const int type, const void *in, int in_len, void *out)
+{
+    SHA_CTX sha;
+    MD5_CTX md5;
+
+    switch (type) {
+    case HIP_DIGEST_SHA1:
+        SHA1_Init(&sha);
+        SHA1_Update(&sha, in, in_len);
+        SHA1_Final(out, &sha);
+        break;
+
+    case HIP_DIGEST_MD5:
+        MD5_Init(&md5);
+        MD5_Update(&md5, in, in_len);
+        MD5_Final(out, &md5);
+        break;
+
+    default:
+        HIP_ERROR("Unknown digest: %x\n", type);
+        return -EFAULT;
+    }
+
+    return 0;
+}

=== modified file 'lib/core/builder.h'
--- lib/core/builder.h  2010-03-19 09:24:10 +0000
+++ lib/core/builder.h  2010-03-19 09:53:35 +0000
@@ -15,10 +15,6 @@
 #include <openssl/dsa.h>
 #endif
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif /* HAVE_CONFIG_H */
-
 #ifdef __KERNEL__
 #  include "usercompat.h"
 #  include "protodefs.h"
@@ -28,7 +24,9 @@
 #  include "misc.h"
 #  include "icomm.h"
 #  include "certtools.h"
+#  include "config.h"
 #endif
+#include "debug.h"
 #include "hipd/registration.h"
 #include "state.h"
 
@@ -191,7 +189,6 @@
                               struct sockaddr *src,
                               struct sockaddr *dst,
                               int len);
-uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst);
 int hip_check_userspace_msg(const struct hip_common *);
 int hip_check_userspace_msg_type(const struct hip_common *);
 void hip_dump_msg(const struct hip_common *);
@@ -310,5 +307,6 @@
                              const in_port_t port,
                              hip_tlv_type_t hipparam);
 struct in6_addr *hip_get_locator_item_address(void *item);
+int hip_build_digest(const int type, const void *in, int in_len, void *out);
 
 #endif /* HIP_LIB_CORE_BUILDER_H */

=== modified file 'lib/core/certtools.c'
--- lib/core/certtools.c        2010-03-03 13:16:18 +0000
+++ lib/core/certtools.c        2010-03-19 09:53:35 +0000
@@ -8,6 +8,8 @@
 #define _BSD_SOURCE
 
 #include "certtools.h"
+#include "straddr.h"
+#include "lib/core/crypto.h"
 
 
/*******************************************************************************
 * FUNCTIONS FOR SPKI                                                          *

=== modified file 'lib/core/certtools.h'
--- lib/core/certtools.h        2010-02-17 17:38:08 +0000
+++ lib/core/certtools.h        2010-03-19 09:53:35 +0000
@@ -22,13 +22,11 @@
 #include <openssl/conf.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
 
+#include "config.h"
 #include "debug.h"
 #include "ife.h"
-#include "misc.h"
+
 #include "hashtable.h"
 
 /** Defines */

=== modified file 'lib/core/crypto.c'
--- lib/core/crypto.c   2010-03-19 09:24:10 +0000
+++ lib/core/crypto.c   2010-03-19 09:53:35 +0000
@@ -31,11 +31,9 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "crypto.h"
+#include "keylen.h"
 
 #ifdef CONFIG_HIP_PERFORMANCE
 #include "lib/performance/performance.h"
@@ -1113,3 +1111,14 @@
 out_err:
     return err;
 }
+
+/**
+ * get random bytes
+ *
+ * @param buf a buffer where to write random bytes
+ * @param n write n bytes to @c buf
+ */
+void get_random_bytes(void *buf, int n)
+{
+    RAND_bytes(buf, n);
+}

=== modified file 'lib/core/crypto.h'
--- lib/core/crypto.h   2010-03-19 09:24:10 +0000
+++ lib/core/crypto.h   2010-03-19 09:53:35 +0000
@@ -1,10 +1,6 @@
 #ifndef HIP_LIB_CORE_CRYPTO_H
 #define HIP_LIB_CORE_CRYPTO_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #include <sys/time.h>
 #include <time.h>
 #include <openssl/dsa.h>
@@ -26,8 +22,10 @@
 #include <string.h>
 #include <netinet/in.h>
 
+#include "config.h"
 #include "hipd/hidb.h"
 #include "lib/core/debug.h"
+#include "lib/core/transform.h"
 #include "lib/core/ife.h"
 #include "hipd/hadb.h"
 #define HIP_DSA_SIG_SIZE 41 /* T(1) + R(20) + S(20)  from RFC 2536 */
@@ -103,5 +101,6 @@
 int hip_write_hmac(int type, const void *key, void *in, int in_len, void *out);
 int hip_crypto_encrypted(void *data, const void *iv, int enc_alg, int enc_len,
                          void *enc_key, int direction);
+void get_random_bytes(void *buf, int n);
 
 #endif /* HIP_LIB_CORE_CRYPTO_H */

=== modified file 'lib/core/debug.c'
--- lib/core/debug.c    2010-03-03 13:16:18 +0000
+++ lib/core/debug.c    2010-03-19 09:53:35 +0000
@@ -49,11 +49,9 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "debug.h"
+#include "straddr.h"
 #include "lib/tool/lutil.h"
 #include "lib/conf/hipconf.h"
 

=== modified file 'lib/core/debug.h'
--- lib/core/debug.h    2010-03-03 13:16:18 +0000
+++ lib/core/debug.h    2010-03-19 09:53:35 +0000
@@ -9,10 +9,7 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <netinet/in.h>
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "protodefs.h"
 #include "prefix.h"
 #include "ife.h"

=== added file 'lib/core/filemanip.c'
--- lib/core/filemanip.c        1970-01-01 00:00:00 +0000
+++ lib/core/filemanip.c        2010-03-19 09:53:35 +0000
@@ -0,0 +1,199 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief file manipulation tools
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#include "filemanip.h"
+
+#include <unistd.h>
+
+#include "config.h"
+#include "crypto.h"
+
+/**
+ * get rid of a lock file
+ *
+ * @param filename the file name of the lock file
+ * @return zero on success and negative on error
+ */
+int hip_remove_lock_file(char *filename)
+{
+    return unlink(filename);
+}
+
+/**
+ * create a new lock file
+ *
+ * @param filename the file name of the lock
+ * @param killold one if the function should steal the lock from
+ *        and existing process and kill it, or zero otherwise
+ * @return zero on success and negative on error
+ */
+int hip_create_lock_file(char *filename, int killold)
+{
+    int err     = 0, fd = 0, old_pid = 0, new_pid_str_len = 0;
+    char old_pid_str[64], new_pid_str[64];
+    int pid_set = 0;     /* the pid was read successfully */
+    memset(old_pid_str, 0, sizeof(old_pid_str));
+    memset(new_pid_str, 0, sizeof(new_pid_str));
+
+    /* New pid */
+    snprintf(new_pid_str, sizeof(new_pid_str) - 1, "%d\n", getpid());
+    new_pid_str_len = strlen(new_pid_str);
+    HIP_IFEL((new_pid_str_len <= 0), -1, "pID length error.\n");
+
+    /* Read old pid */
+    fd              = HIP_CREATE_FILE(filename);
+    HIP_IFEL((fd <= 0), -1, "opening lock file failed\n");
+
+    /** @todo This is possibly unsafe: the pid is read from the file without 
checking
+     * file permissions and the process with the number is simply killed.
+     * THIS COULD BE USED TO ATTACK THE SYSTEM
+     */
+    pid_set         = read(fd, old_pid_str, sizeof(old_pid_str) - 1);
+    old_pid         = atoi(old_pid_str);
+
+    if (lockf(fd, F_TLOCK, 0) < 0) {
+        HIP_IFEL(!killold, -12,
+                 "\nHIP daemon already running with pid %d\n"
+                 "Give: -k option to kill old daemon.\n", old_pid);
+
+        HIP_INFO("\nDaemon is already running with pid %d\n"
+                 "-k option given, terminating old one...\n", old_pid);
+        /* Erase the old lock file to avoid having multiple pids
+         * in the file */
+        if (lockf(fd, F_ULOCK, 0) == -1) {
+            HIP_ERROR("Cannot unlock pid lock.");
+        }
+
+        close(fd);
+        HIP_IFEL(hip_remove_lock_file(filename), -1,
+                 "Removing lock file failed.\n");
+
+        /* fd = open(filename, O_RDWR | O_CREAT, 0644); */
+        fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
+
+        /* Don't close file descriptor because new started process is
+         * running. */
+        HIP_IFEL((fd <= 0), -1, "Opening lock file failed.\n");
+        HIP_IFEL(lockf(fd, F_TLOCK, 0), -1, "Lock attempt failed.\n");
+        if (pid_set) {
+            err = kill(old_pid, SIGKILL);
+        }
+        if (err != 0) {
+            HIP_ERROR("\nError when trying to send signal SIGKILL " \
+                      "process identified by process identifier " \
+                      "%d.\n", old_pid);
+            HIP_PERROR("errno after kill() is: ");
+        }
+    }
+
+    lseek(fd, 0, SEEK_SET);
+
+    HIP_IFEL((write(fd, new_pid_str, new_pid_str_len) != new_pid_str_len),
+             -1, "Writing new process identifier failed.\n");
+
+out_err:
+    if (err == -12) {
+        exit(0);
+    }
+
+    return err;
+}
+
+/**
+ * check and create a directory
+ * @param dirname the name of the directory
+ * @param mode creation mode for the directory, if it does not exist
+ *
+ * @return 0 if successful, or negative on error.
+ */
+int check_and_create_dir(char *dirname, mode_t mode)
+{
+    int err = 0;
+    struct stat dir_stat;
+
+    HIP_INFO("dirname=%s mode=%o\n", dirname, mode);
+    err = stat(dirname, &dir_stat);
+    if (err && errno == ENOENT) {     /* no such file or directory */
+        err = mkdir(dirname, mode);
+        if (err) {
+            HIP_ERROR("mkdir %s failed: %s\n", dirname,
+                      strerror(errno));
+        }
+    } else if (err) {
+        HIP_ERROR("stat %s failed: %s\n", dirname,
+                  strerror(errno));
+    }
+
+    return err;
+}
+
+/**
+ * check and create a file
+ * @param file the name of the file
+ * @param mode creation mode for the file, if it does not exist
+ *
+ * @return file descriptor of the created file
+ */
+int check_and_create_file(char *filename, mode_t mode)
+{
+    int err = 0, fd = 0;
+    struct stat file_stat;
+
+    HIP_INFO("filename=%s mode=%o\n", filename, mode);
+    err = stat(filename, &file_stat);
+    if (err && errno == ENOENT) {     /* no such file or file */
+        fd = open(filename, O_RDWR | O_CREAT, 0644);
+        if (fd < 0) {
+            HIP_ERROR("creating file %s failed: %s\n", filename,
+                      strerror(errno));
+        }
+    } else {
+        fd = open(filename, O_RDWR);
+        if (fd < 0) {
+            HIP_ERROR("opening file %s failed: %s\n", filename,
+                      strerror(errno));
+        }
+    }
+
+    return fd;
+}
+
+/**
+ * make /etc/hip file permissions more secure
+ *
+ * @param filenamebase the file name based for keys
+ */
+void change_key_file_perms(char *filenamebase)
+{
+    char *pubfilename = NULL;
+    int pubfilename_len;
+
+    pubfilename_len =
+        strlen(filenamebase) + strlen(DEFAULT_PUB_FILE_SUFFIX) + 1;
+    pubfilename     = malloc(pubfilename_len);
+    if (!pubfilename) {
+        HIP_ERROR("malloc(%d) failed\n", pubfilename_len);
+        goto out_err;
+    }
+
+    /* check retval */
+    snprintf(pubfilename, pubfilename_len, "%s%s", filenamebase,
+             DEFAULT_PUB_FILE_SUFFIX);
+
+    chmod(filenamebase, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+    chmod(pubfilename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+
+out_err:
+    if (pubfilename) {
+        HIP_FREE(pubfilename);
+    }
+
+    return;
+}

=== added file 'lib/core/filemanip.h'
--- lib/core/filemanip.h        1970-01-01 00:00:00 +0000
+++ lib/core/filemanip.h        2010-03-19 09:53:35 +0000
@@ -0,0 +1,23 @@
+#ifndef HIP_LIB_CORE_FILEMANIP_H
+#define HIP_LIB_CORE_FILEMANIP_H
+
+#include <sys/types.h>
+
+#include "config.h"
+
+#ifdef CONFIG_HIP_OPENWRT
+# define HIP_CREATE_FILE(x)     check_and_create_file(x, 0644)
+#else
+# define HIP_CREATE_FILE(x)     open((x), O_RDWR | O_CREAT, 0644)
+#endif
+
+/* system/bin for Android */
+#define HIP_DEFAULT_EXEC_PATH 
"/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/system/bin"
+
+int hip_create_lock_file(char *filename, int killold);
+int hip_remove_lock_file(char *filename);
+int check_and_create_dir(char *dirname, mode_t mode);
+int check_and_create_file(char *filename, mode_t mode);
+void change_key_file_perms(char *filenamebase);
+
+#endif /* HIP_LIB_CORE_FILEMANIP_H */

=== modified file 'lib/core/hashtable.c'
--- lib/core/hashtable.c        2010-03-03 13:16:18 +0000
+++ lib/core/hashtable.c        2010-03-19 09:53:35 +0000
@@ -24,9 +24,43 @@
  */
 #include "hashtable.h"
 
+/**
+ * A generic object hashing function for lib/core/hashtable.c
+ *
+ * @param ptr an pointer to hash (must be at least 32 bits)
+ * @return a hash of the first 32-bits of the ptr's data
+ */
+unsigned long hip_hash_generic(const void *ptr)
+{
+    unsigned long hash = (unsigned long) (*((uint32_t *) ptr));
+    return hash % ULONG_MAX;
+}
+
+/**
+ * A generic matching function for lib/core/hashtable.c
+ *
+ * @param ptr1 a pointer to an item in the hash table
+ * @param ptr2 a pointer to an item in the hash table
+ * @return zero if the pointers match or one otherwise
+ */
+int hip_match_generic(const void *ptr1, const void *ptr2)
+{
+    return ptr1 != ptr2;
+}
+
 #ifdef HIPL_OPENSSL_100
 
 /**
+ * Returns a generic linked list based on the hash table implementation
+ *
+ * @return an allocated hash table which is caller is responsible to free
+ */
+LHASH_OF(HIP_HT) * hip_linked_list_init(void)
+{
+  return (LHASH_OF(HIP_HT) *) hip_ht_init(hip_hash_generic, hip_match_generic);
+}
+
+/**
  * Initialize hash table (or linked list)
  *
  * @param hashfunc hash function to calculated the hash
@@ -41,6 +75,11 @@
 
 #else /* not HIPL_OPENSSL_100 */
 
+HIP_HASHTABLE *hip_linked_list_init(void)
+{
+    return (HIP_HASHTABLE *) hip_ht_init(hip_hash_generic, hip_match_generic);
+}
+
 HIP_HASHTABLE *hip_ht_init(LHASH_HASH_FN_TYPE hashfunc,
                            LHASH_COMP_FN_TYPE cmpfunc)
 {

=== modified file 'lib/core/hashtable.h'
--- lib/core/hashtable.h        2010-02-17 17:38:08 +0000
+++ lib/core/hashtable.h        2010-03-19 09:53:35 +0000
@@ -4,6 +4,7 @@
 #include <openssl/bio.h>
 #include <openssl/crypto.h>
 #include <openssl/lhash.h>
+#include <limits.h>
 #include "debug.h"
 #include "list.h"
 
@@ -35,6 +36,7 @@
 typedef DECLARE_LHASH_OF (HIP_HT) hip_ht_common;
 typedef hip_ht_common HIP_HASHTABLE;
 
+LHASH_OF(HIP_HT) * hip_linked_list_init(void);
 LHASH_OF(HIP_HT) * hip_ht_init(LHASH_HASH_FN_TYPE hashfunc, LHASH_COMP_FN_TYPE 
cmpfunc);
 
 #else
@@ -70,6 +72,7 @@
 typedef DECLARE_LHASH_OF (HIP_HT) hip_ht_common;
 typedef LHASH HIP_HASHTABLE;
 
+HIP_HASHTABLE *hip_linked_list_init(void);
 HIP_HASHTABLE *hip_ht_init(LHASH_HASH_FN_TYPE hashfunc,
                            LHASH_COMP_FN_TYPE cmpfunc);
 #endif

=== modified file 'lib/core/hip_capability.c'
--- lib/core/hip_capability.c   2010-03-03 13:16:18 +0000
+++ lib/core/hip_capability.c   2010-03-19 09:53:35 +0000
@@ -19,10 +19,7 @@
 
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #ifdef CONFIG_HIP_PRIVSEP
 #ifdef CONFIG_HIP_ALTSEP
 /* Note: OpenWRT has to use <linux/capability.h> */

=== modified file 'lib/core/hip_statistics.c'
--- lib/core/hip_statistics.c   2010-03-03 16:51:18 +0000
+++ lib/core/hip_statistics.c   2010-03-19 09:53:35 +0000
@@ -91,8 +91,8 @@
     HIP_ASSERT(timeval_start != NULL);
     HIP_ASSERT(timeval_end != NULL);
 
-    // check that timeval_high really is higher
-    if ((timeval_end->tv_sec > timeval_start->tv_sec) &&
+    /* check that timeval_high really is higher */
+    if ((timeval_end->tv_sec >= timeval_start->tv_sec) &&
         (timeval_end->tv_usec > timeval_start->tv_usec))
     {
         rel_timeval.tv_sec  = timeval_end->tv_sec - timeval_start->tv_sec;

=== added file 'lib/core/hip_udp.c'
--- lib/core/hip_udp.c  1970-01-01 00:00:00 +0000
+++ lib/core/hip_udp.c  2010-03-19 09:53:35 +0000
@@ -0,0 +1,67 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief UDP-related functions
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#include "hip_udp.h"
+#include "debug.h"
+
+/** Port numbers for NAT traversal of hip control packets. */
+in_port_t hip_local_nat_udp_port = HIP_NAT_UDP_PORT;
+in_port_t hip_peer_nat_udp_port  = HIP_NAT_UDP_PORT;
+
+
+/**
+ * Retrieve the default local UDP port
+ *
+ * @return the default local UDP port
+ */
+in_port_t hip_get_local_nat_udp_port()
+{
+    return hip_local_nat_udp_port;
+}
+
+/**
+ * Retrieve the default remote UDP port
+ *
+ * @return the default remote UDP port
+ */
+in_port_t hip_get_peer_nat_udp_port()
+{
+    return hip_peer_nat_udp_port;
+}
+
+/**
+ * set the default local UDP port
+ *
+ * @param port the port to set as the default local UDP port
+ * @return zero
+ */
+int hip_set_local_nat_udp_port(in_port_t port)
+{
+    int err = 0;
+    HIP_DEBUG("set local nat udp port %d\n", port);
+    hip_local_nat_udp_port = port;
+
+    return err;
+}
+
+/**
+ * set the default remote UDP port
+ *
+ * @param port the port to set as the default remote UDP port
+ * @return zero
+ */
+int hip_set_peer_nat_udp_port(in_port_t port)
+{
+    int err = 0;
+
+    HIP_DEBUG("set peer nat udp port %d\n", port);
+    hip_peer_nat_udp_port = port;
+    return err;
+}

=== added file 'lib/core/hip_udp.h'
--- lib/core/hip_udp.h  1970-01-01 00:00:00 +0000
+++ lib/core/hip_udp.h  2010-03-19 09:53:35 +0000
@@ -0,0 +1,36 @@
+#ifndef HIP_LIB_CORE_HIP_UDP_H
+#define HIP_LIB_CORE_HIP_UDP_H
+
+#include <netinet/in.h>
+
+#define HIP_NAT_UDP_PORT 10500
+//#define HIP_NAT_TURN_PORT 10500
+
+/** For setting socket to listen for beet-udp packets. */
+#define HIP_UDP_ENCAP 100
+/** UDP encapsulation type. */
+#define HIP_UDP_ENCAP_ESPINUDP 2
+/** UDP encapsulation type. */
+#define HIP_UDP_ENCAP_ESPINUDP_NONIKE 1
+
+/**
+ * Get HIP local NAT UDP port.
+ */
+in_port_t hip_get_local_nat_udp_port(void);
+
+/**
+ * Get HIP peer NAT UDP port.
+ */
+in_port_t hip_get_peer_nat_udp_port(void);
+
+/**
+ * Set HIP local NAT UDP port.
+ */
+int hip_set_local_nat_udp_port(in_port_t port);
+
+/**
+ * Set HIP peer NAT UDP port.
+ */
+int hip_set_peer_nat_udp_port(in_port_t port);
+
+#endif /* HIP_LIB_CORE_HIP_UDP_H */

=== added file 'lib/core/hit.c'
--- lib/core/hit.c      1970-01-01 00:00:00 +0000
+++ lib/core/hit.c      2010-03-19 09:53:35 +0000
@@ -0,0 +1,100 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief HIT-related utility functions
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#define _BSD_SOURCE
+
+#include "config.h"
+#include "hit.h"
+#include "debug.h"
+#include "straddr.h"
+#include "builder.h"
+
+/**
+ * convert a binary HIT into a string
+ *
+ * @param hit a binary HIT
+ * @param prefix an optional HIT prefix as a string
+ * @param hit_str the HIT as a string with the given prefix
+ * @return zero on success and negative on error
+ */
+int hip_convert_hit_to_str(const hip_hit_t *hit,
+                           const char *prefix,
+                           char *hit_str)
+{
+    int err = 0;
+
+    HIP_ASSERT(hit);
+
+    memset(hit_str, 0, INET6_ADDRSTRLEN);
+    err = !hip_in6_ntop(hit, hit_str);
+
+    if (prefix) {
+        memcpy(hit_str + strlen(hit_str), prefix, strlen(prefix));
+    }
+
+    return err;
+}
+/**
+ * compare two HITs to check which HIT is "bigger"
+ *
+ * @param hit1 the first HIT to be compared
+ * @param hit2 the second HIT to be compared
+ *
+ * @return 1 if hit1 was bigger than hit2, or else 0
+ */
+int hip_hit_is_bigger(const struct in6_addr *hit1,
+                      const struct in6_addr *hit2)
+{
+    return ipv6_addr_cmp(hit1, hit2) > 0;
+}
+
+/**
+ * compare two HITs to check which if they are equal
+ *
+ * @param hit1 the first HIT to be compared
+ * @param hit2 the second HIT to be compared
+ *
+ * @return 1 if the HITs were equal and zero otherwise
+ */
+int hip_hit_are_equal(const struct in6_addr *hit1,
+                      const struct in6_addr *hit2)
+{
+    return ipv6_addr_cmp(hit1, hit2) == 0;
+}
+
+/**
+ * hip_hash_hit - calculate a hash from a HIT
+ *
+ * @param key pointer to a HIT
+ * @param range range of the hash
+ *
+ * Returns value in range: 0 <= x < range
+ */
+unsigned long hip_hash_hit(const void *ptr)
+{
+    uint8_t hash[HIP_AH_SHA_LEN];
+
+    hip_build_digest(HIP_DIGEST_SHA1, ptr + sizeof(uint16_t),
+                     7 * sizeof(uint16_t), hash);
+
+    return *((unsigned long *) hash);
+}
+
+/**
+ * Verify if if two HITs match based on hashing
+ *
+ * @param ptr1 a HIT
+ * @param ptr2 a HIT
+ * @return zero if the HITs match or one otherwise
+ */
+int hip_match_hit(const void *ptr1, const void *ptr2)
+{
+    return hip_hash_hit(ptr1) != hip_hash_hit(ptr2);
+}

=== added file 'lib/core/hit.h'
--- lib/core/hit.h      1970-01-01 00:00:00 +0000
+++ lib/core/hit.h      2010-03-19 09:53:35 +0000
@@ -0,0 +1,15 @@
+#ifndef HIP_LIB_CORE_HIT_H
+#define HIP_LIB_CORE_HIT_H
+
+#include <netinet/in.h>
+#include "protodefs.h"
+
+int hip_convert_hit_to_str(const hip_hit_t *hit, const char *prefix, char 
*str);
+int hip_hit_is_bigger(const struct in6_addr *hit1,
+                      const struct in6_addr *hit2);
+int hip_hit_are_equal(const struct in6_addr *hit1,
+                      const struct in6_addr *hit2);
+unsigned long hip_hash_hit(const void *hit);
+int hip_match_hit(const void *, const void *);
+
+#endif /* HIP_LIB_CORE_HIT_H */

=== added file 'lib/core/hostid.c'
--- lib/core/hostid.c   1970-01-01 00:00:00 +0000
+++ lib/core/hostid.c   2010-03-19 09:53:35 +0000
@@ -0,0 +1,1197 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Host identifier manipulation functions
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#include <netinet/in.h>
+#include <stdlib.h>
+#include "lib/core/ife.h"
+#include "lib/core/debug.h"
+#include "lib/core/protodefs.h"
+#include "lib/core/crypto.h"
+#include "lib/tool/pk.h"
+
+#include "config.h"
+#include "hostid.h"
+#include "filemanip.h"
+
+/* needed due to missing system inlcude for openWRT */
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX           64
+#endif
+
+#define HOST_ID_FILENAME_MAX_LEN 256
+
+
+/**
+ * calculate a HIT from a HI without the prefix
+ *
+ * @param orig a pointer to a host identity
+ * @param orig_len the length of the host identity in bits
+ * @param encoded an output argument where the HIT will be stored
+ * @param encoded_len the length of the encoded HIT in bits
+ * @return zero on success or negative on error
+ */
+int khi_encode(unsigned char *orig, int orig_len,
+               unsigned char *encoded,
+               int encoded_len)
+{
+    BIGNUM *bn = NULL;
+    int err    = 0, shift = (orig_len - encoded_len) / 2,
+        len    = encoded_len / 8 + ((encoded_len % 8) ? 1 : 0);
+
+    HIP_IFEL((encoded_len > orig_len), -1, "len mismatch\n");
+    HIP_IFEL((!(bn = BN_bin2bn(orig, orig_len / 8, NULL))), -1,
+             "BN_bin2bn\n");
+    HIP_IFEL(!BN_rshift(bn, bn, shift), -1, "BN_lshift\n");
+    HIP_IFEL(!BN_mask_bits(bn, encoded_len), -1,
+             "BN_mask_bits\n");
+    HIP_IFEL((bn2bin_safe(bn, encoded, len) != len), -1,
+             "BN_bn2bin_safe\n");
+
+    _HIP_HEXDUMP("encoded: ", encoded, len);
+
+out_err:
+    if (bn) {
+        BN_free(bn);
+    }
+    return err;
+}
+
+/**
+ * Calculates a Host Identity Tag (HIT) from a Host Identifier (HI) using DSA
+ * encryption.
+ *
+ * @param  host_id  a pointer to a Host Identifier
+ * @param  hit      a target buffer where to put the calculated HIT.
+ * @param  hit_type type of the HIT (must be HIP_HIT_TYPE_HASH100).
+ * @return          zero on success, negative otherwise.
+ */
+int hip_dsa_host_id_to_hit(const struct hip_host_id *host_id,
+                           struct in6_addr *hit, int hit_type)
+{
+    int err                 = 0;
+    uint8_t digest[HIP_AH_SHA_LEN];
+    uint8_t *key_rr              = (uint8_t *) host_id->key; /* skip the 
header */
+    /* hit excludes rdata but it is included in hi_length;
+       subtract rdata */
+    unsigned int key_rr_len = ntohs(host_id->hi_length) -
+                              sizeof(struct hip_host_id_key_rdata);
+    uint8_t *khi_data            = NULL;
+    uint8_t khi_context_id[]     = HIP_KHI_CONTEXT_ID_INIT;
+    int khi_data_len        = key_rr_len + sizeof(khi_context_id);
+    int khi_index           = 0;
+
+    _HIP_DEBUG("key_rr_len=%u\n", key_rr_len);
+    HIP_IFE(hit_type != HIP_HIT_TYPE_HASH100, -ENOSYS);
+    _HIP_HEXDUMP("key_rr", key_rr, key_rr_len);
+
+    /* Hash Input :=  Context ID | Input */
+    khi_data   = HIP_MALLOC(khi_data_len, 0);
+    khi_index  = 0;
+    memcpy(khi_data + khi_index, khi_context_id, sizeof(khi_context_id));
+    khi_index += sizeof(khi_context_id);
+    memcpy(khi_data + khi_index, key_rr, key_rr_len);
+    khi_index += key_rr_len;
+
+    HIP_ASSERT(khi_index == khi_data_len);
+
+    _HIP_HEXDUMP("khi data", khi_data, khi_data_len);
+
+    /* Hash :=  SHA1( Expand( Hash Input ) ) */
+    HIP_IFEL((err = hip_build_digest(HIP_DIGEST_SHA1, khi_data,
+                                     khi_data_len, digest)), err,
+             "Building of digest failed\n");
+
+    _HIP_HEXDUMP("digest", digest, sizeof(digest));
+
+    memset(hit, 0, sizeof(hip_hit_t));
+    HIP_IFEL(khi_encode(digest, sizeof(digest) * 8,
+                        ((uint8_t *) hit) + 3,
+                        sizeof(hip_hit_t) * 8 - HIP_HIT_PREFIX_LEN),
+             -1, "encoding failed\n");
+
+    _HIP_DEBUG_HIT("HIT before prefix: ", hit);
+    set_hit_prefix(hit);
+    _HIP_DEBUG_HIT("HIT after prefix: ", hit);
+
+out_err:
+    if (khi_data) {
+        HIP_FREE(khi_data);
+    }
+
+    return err;
+}
+
+/**
+ * convert DSA or RSA-based host id to a HIT
+ *
+ * @param host_id a host id
+ * @param hit output argument, the calculated HIT will stored here
+ * @param hit_type the type of the HIT
+ * @return zero on success or negative on error
+ */
+int hip_host_id_to_hit(const struct hip_host_id *host_id,
+                       struct in6_addr *hit,
+                       int hit_type)
+{
+    int algo = hip_get_host_id_algo(host_id);
+    int err  = 0;
+
+    if (algo == HIP_HI_DSA) {
+        err = hip_dsa_host_id_to_hit(host_id, hit, hit_type);
+    } else if (algo == HIP_HI_RSA) {
+        err = hip_rsa_host_id_to_hit(host_id, hit, hit_type);
+    } else {
+        err = -ENOSYS;
+    }
+
+    return err;
+}
+
+/**
+ * convert DSA-based private host id to a HIT
+ *
+ * @param host_id a host id
+ * @param hit output argument, the calculated HIT will stored here
+ * @param hit_type the type of the HIT
+ * @return zero on success or negative on error
+ */
+int hip_private_dsa_host_id_to_hit(const struct hip_host_id_priv *host_id,
+                                   struct in6_addr *hit,
+                                   int hit_type)
+{
+    int err                         = 0;
+    struct hip_host_id *host_id_pub = NULL;
+    int contents_len;
+    int total_len;
+
+    contents_len = hip_get_param_contents_len(host_id);
+    total_len    = hip_get_param_total_len(host_id);
+
+    /*! \todo add an extra check for the T val */
+
+    HIP_IFEL(contents_len <= 20, -EMSGSIZE, "Host id too short\n");
+
+    /* Allocate enough space for host id; there will be 20 bytes extra
+     * to avoid hassle with padding. */
+    host_id_pub = (struct hip_host_id *) HIP_MALLOC(total_len, 0);
+    HIP_IFE(!host_id_pub, -EFAULT);
+    memset(host_id_pub, 0, total_len);
+
+    memcpy(host_id_pub, host_id,
+           sizeof(struct hip_tlv_common) + contents_len - DSA_PRIV);
+
+    host_id_pub->hi_length = htons(ntohs(host_id_pub->hi_length) - DSA_PRIV);
+    hip_set_param_contents_len((struct hip_tlv_common *) host_id_pub,
+                               contents_len - DSA_PRIV);
+
+    _HIP_HEXDUMP("extracted pubkey", host_id_pub,
+                 hip_get_param_total_len(host_id_pub));
+
+    if ((err = hip_dsa_host_id_to_hit(host_id_pub, hit, hit_type))) {
+        HIP_ERROR("Failed to convert HI to HIT.\n");
+        goto out_err;
+    }
+
+out_err:
+
+    if (host_id_pub) {
+        HIP_FREE(host_id_pub);
+    }
+
+    return err;
+}
+
+/**
+ * convert RSA-based private host id to a HIT
+ *
+ * @param host_id a host id
+ * @param hit output argument, the calculated HIT will stored here
+ * @param hit_type the type of the HIT
+ * @return zero on success or negative on error
+ */
+int hip_private_rsa_host_id_to_hit(const struct hip_host_id_priv *host_id,
+                                   struct in6_addr *hit,
+                                   int hit_type)
+{
+    int err = 0;
+    struct hip_host_id host_id_pub;
+    int rsa_pub_len, rsa_priv_len;
+    struct hip_rsa_keylen keylen;
+
+    /* Length of the private part of the RSA key d + p + q
+     * is twice the length of the public modulus.
+     * dmp1 + dmq1 + iqmp is another 1.5 times */
+
+    hip_get_rsa_keylen(host_id, &keylen, 1);
+    rsa_pub_len  = keylen.e_len + keylen.e + keylen.n;
+    rsa_priv_len = keylen.n * 7 / 2;
+
+    memcpy(&host_id_pub, host_id, sizeof(host_id_pub)
+           - sizeof(host_id_pub.key) - sizeof(host_id_pub.hostname));
+
+    host_id_pub.hi_length =
+        htons(ntohs(host_id_pub.hi_length) - rsa_priv_len);
+    memcpy(host_id_pub.key, host_id->key, rsa_pub_len);
+
+    _HIP_HEXDUMP("extracted pubkey", &host_id_pub,
+                 hip_get_param_total_len(host_id_pub));
+
+    if ((err = hip_rsa_host_id_to_hit(&host_id_pub, hit, hit_type))) {
+        HIP_ERROR("Failed to convert HI to HIT.\n");
+        goto out_err;
+    }
+
+out_err:
+
+    return err;
+}
+
+/**
+ * convert RSA or DSA-based private host id to a HIT
+ *
+ * @param host_id a host id
+ * @param hit output argument, the calculated HIT will stored here
+ * @param hit_type the type of the HIT
+ * @return zero on success or negative on error
+ */
+int hip_private_host_id_to_hit(const struct hip_host_id_priv *host_id,
+                               struct in6_addr *hit,
+                               int hit_type)
+{
+    int algo = hip_get_host_id_algo((struct hip_host_id *) host_id);
+    int err  = 0;
+
+    if (algo == HIP_HI_DSA) {
+        err = hip_private_dsa_host_id_to_hit(host_id, hit,
+                                             hit_type);
+    } else if (algo == HIP_HI_RSA) {
+        err = hip_private_rsa_host_id_to_hit(host_id, hit,
+                                             hit_type);
+    } else {
+        err = -ENOSYS;
+    }
+
+    return err;
+}
+
+
+/**
+ * check if a given host id just contains a public key (i.e. can
+ * be sent on wire) or if it is piggypacked with the private component
+ *
+ * @param host_id the host id structure
+ * @return 1 if the host id contains the private component or 0 otherwise
+ */
+int hip_host_id_contains_private_key(struct hip_host_id *host_id)
+{
+    uint16_t len = hip_get_param_contents_len(host_id);
+    uint8_t *buf      = (uint8_t *) host_id->key;
+    uint8_t t         = *buf;
+
+    return len >= 3 * (64 + 8 * t) + 2 * 20;     /* PQGXY 3*(64+8*t) + 2*20 */
+}
+
+/**
+ * dig out RSA key length from an host id
+ *
+ * @param host_id the host id
+ * @param ret the RSA key component lengths will be stored here
+ * @param is_priv one if the host_id contains also the private key
+ *                component or zero otherwise
+ */
+void hip_get_rsa_keylen(const struct hip_host_id_priv *host_id,
+                        struct hip_rsa_keylen *ret,
+                        int is_priv)
+{
+    int bytes;
+    uint8_t *tmp    = (uint8_t *) host_id->key;
+    int offset = 0;
+    int e_len  = tmp[offset++];
+
+    /* Check for public exponent longer than 255 bytes (see RFC 3110) */
+    if (e_len == 0) {
+        e_len   = ntohs((uint16_t) tmp[offset]);
+        offset += 2;
+    }
+
+    /*
+     * hi_length is the total length of:
+     * rdata struct (4 bytes), length of e (1 byte for e < 255 bytes, 3 bytes 
otherwise),
+     * e (normally 3 bytes), followed by public n, private d, p, q, dmp1, 
dmq1, iqmp
+     * n_len == d_len == 2 * p_len == 2 * q_len == dmp1_len == dmq1_len == 
iqmp_len
+     * for 9/2 * n_len
+     */
+    if (is_priv) {
+        bytes = (ntohs(host_id->hi_length) - sizeof(struct 
hip_host_id_key_rdata) -
+                 offset - e_len) * 2 / 9;
+    } else {
+        bytes = (ntohs(host_id->hi_length) - sizeof(struct 
hip_host_id_key_rdata) -
+                 offset - e_len);
+    }
+
+    ret->e_len = offset;
+    ret->e     = e_len;
+    ret->n     = bytes;
+}
+
+/**
+ * convert a RSA-based host id into an OpenSSL structure
+ *
+ * @param host_id the host id
+ * @param is_priv one if the host_id contains also the private key
+ *                component or zero otherwise
+ * @return The OpenSSL formatted RSA key corresponding to @c host_id.
+ *         Caller is responsible of freeing.
+ */
+RSA *hip_key_rr_to_rsa(const struct hip_host_id_priv *host_id, int is_priv)
+{
+    int offset;
+    struct hip_rsa_keylen keylen;
+    RSA *rsa = NULL;
+
+    hip_get_rsa_keylen(host_id, &keylen, is_priv);
+
+    rsa = RSA_new();
+    if (!rsa) {
+        HIP_ERROR("Failed to allocate RSA\n");
+        return NULL;
+    }
+
+    offset  = keylen.e_len;
+    rsa->e  = BN_bin2bn(&host_id->key[offset], keylen.e, 0);
+    offset += keylen.e;
+    rsa->n  = BN_bin2bn(&host_id->key[offset], keylen.n, 0);
+
+    if (is_priv) {
+        offset   += keylen.n;
+        rsa->d    = BN_bin2bn(&host_id->key[offset], keylen.n, 0);
+        offset   += keylen.n;
+        rsa->p    = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0);
+        offset   += keylen.n / 2;
+        rsa->q    = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0);
+        offset   += keylen.n / 2;
+        rsa->dmp1 = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0);
+        offset   += keylen.n / 2;
+        rsa->dmq1 = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0);
+        offset   += keylen.n / 2;
+        rsa->iqmp = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0);
+    }
+
+    return rsa;
+}
+
+/**
+ * convert a DSA-based host id into an OpenSSL structure
+ *
+ * @param host_id the host id
+ * @param is_priv one if the host_id contains also the private key
+ *                component or zero otherwise
+ * @return The OpenSSL formatted DSA key corresponding to @c host_id.
+ *         Caller is responsible of freeing.
+ */
+DSA *hip_key_rr_to_dsa(const struct hip_host_id_priv *host_id, int is_priv)
+{
+    int offset  = 0;
+    DSA *dsa    = NULL;
+    uint8_t t        = host_id->key[offset++];
+    int key_len = 64 + (t * 8);
+
+    dsa = DSA_new();
+    if (!dsa) {
+        HIP_ERROR("Failed to allocate DSA\n");
+        return NULL;
+    }
+
+    dsa->q       = BN_bin2bn(&host_id->key[offset], DSA_PRIV, 0);
+    offset      += DSA_PRIV;
+    dsa->p       = BN_bin2bn(&host_id->key[offset], key_len, 0);
+    offset      += key_len;
+    dsa->g       = BN_bin2bn(&host_id->key[offset], key_len, 0);
+    offset      += key_len;
+    dsa->pub_key = BN_bin2bn(&host_id->key[offset], key_len, 0);
+
+    if (is_priv) {
+        offset       += key_len;
+        dsa->priv_key = BN_bin2bn(&host_id->key[offset], DSA_PRIV, 0);
+
+        /* Precompute values for faster signing */
+        DSA_sign_setup(dsa, NULL, &dsa->kinv, &dsa->r);
+    }
+
+    return dsa;
+}
+
+/**
+ * verify the signature in a HIP control packet
+ *
+ * @param pkt the hip packet
+ * @param peer_host_id peer host id
+ * @return zero on success, or negative error value on failure
+ */
+int hip_verify_packet_signature(struct hip_common *pkt,
+                                struct hip_host_id *peer_host_id)
+{
+    int err                      = 0;
+    struct hip_host_id *peer_pub = NULL;
+    int len                      = hip_get_param_total_len(peer_host_id);
+    char *key                    = NULL;
+
+    HIP_IFEL(!(peer_pub = HIP_MALLOC(len, 0)),
+             -ENOMEM, "Out of memory\n");
+
+    memcpy(peer_pub, peer_host_id, len);
+
+    if (peer_host_id->rdata.algorithm == HIP_HI_DSA) {
+        key = (char *) hip_key_rr_to_rsa(
+            (struct hip_host_id_priv *) peer_pub, 0);
+        err = hip_dsa_verify((DSA *) key, pkt);
+    } else if (peer_host_id->rdata.algorithm == HIP_HI_RSA) {
+        key = (char *) hip_key_rr_to_rsa(
+            (struct hip_host_id_priv *) peer_pub, 0);
+        err = hip_rsa_verify((RSA *) key, pkt);
+    } else {
+        HIP_ERROR("Unknown algorithm\n");
+        err = -1;
+    }
+
+out_err:
+    if (peer_pub) {
+        free(peer_pub);
+    }
+
+    return err;
+}
+
+/**
+ * Convert a local host id into LSI/HIT information and write the
+ * result into a HIP message as a HIP_PARAM_HIT_INFO parameter.
+ * Interprocess communications only.
+ *
+ * @param entry an hip_host_id_entry structure
+ * @param msg a HIP user message where the HIP_PARAM_HIT_INFO
+ *            parameter will be written
+ * @return zero on success and negative on error
+ */
+int hip_host_id_entry_to_hit_info(struct hip_host_id_entry *entry,
+                                  void *msg)
+{
+    struct hip_hit_info data;
+    int err = 0;
+
+    memcpy(&data.lhi, &entry->lhi, sizeof(struct hip_lhi));
+    /* FIXME: algo is 0 in entry->lhi */
+    data.lhi.algo = hip_get_host_id_algo(entry->host_id);
+    memcpy(&data.lsi, &entry->lsi, sizeof(hip_lsi_t));
+
+    HIP_IFEL(hip_build_param_contents(msg,
+                                      &data,
+                                      HIP_PARAM_HIT_INFO,
+                                      sizeof(data)),
+                                      -1,
+                                      "Error building parameter\n");
+
+out_err:
+    return err;
+}
+
+/**
+ * (Re)create new host identities or load existing ones, and append the
+ * private identities into a message. This functionality is used by hipd
+ * but can also be invoked with hipconf.
+ *
+ * @param msg an output argument where the identities will be appended
+ * @param action Currently ACTION_ADD and ACTION_NEW are supported. Warning,
+ *               ACTION_NEW will override the existing identities on disk!
+ * @param anon set to one when you want to process only anonymous (short-term)
+ *             identities or zero otherwise
+ * @param use_default One when dealing with default identities in /etc/hip.
+ *                    Zero when user supplies own identities denoted by
+ *                    @c hi_file argument.
+ * @param hi_fmt "dsa" or "rsa" currently supported
+ * @param hi_file an optional location for user-supplied host identities.
+ *                Argument @c use_default must be zero when used.
+ * @param rsa_key_bits size for RSA keys in bits
+ * @param dsa_key_bits size of DSA keys in bits
+ *
+ * @return zero on success and negative on error
+ */
+int hip_serialize_host_id_action(struct hip_common *msg,
+                                 int action,
+                                 int anon,
+                                 int use_default,
+                                 const char *hi_fmt,
+                                 const char *hi_file,
+                                 int rsa_key_bits,
+                                 int dsa_key_bits)
+{
+    int err = 0, dsa_key_rr_len = 0, rsa_key_rr_len = 0;
+    int dsa_pub_key_rr_len = 0, rsa_pub_key_rr_len = 0;
+    hip_hdr_type_t numeric_action             = 0;
+    char addrstr[INET6_ADDRSTRLEN], hostname[HIP_HOST_ID_HOSTNAME_LEN_MAX];
+    char *dsa_filenamebase                    = NULL, *rsa_filenamebase = NULL;
+    char *dsa_filenamebase_pub                = NULL, *rsa_filenamebase_pub = 
NULL;
+    unsigned char *dsa_key_rr                 = NULL, *rsa_key_rr = NULL;
+    unsigned char *dsa_pub_key_rr             = NULL, *rsa_pub_key_rr = NULL;
+    DSA *dsa_key                              = NULL, *dsa_pub_key = NULL;
+    RSA *rsa_key                              = NULL, *rsa_pub_key = NULL;
+    struct hip_lhi rsa_lhi, dsa_lhi, rsa_pub_lhi, dsa_pub_lhi;
+    struct hip_host_id *dsa_host_id           = NULL, *rsa_host_id = NULL;
+    struct hip_host_id *dsa_pub_host_id       = NULL, *rsa_pub_host_id = NULL;
+    struct endpoint_hip *endpoint_dsa_hip     = NULL;
+    struct endpoint_hip *endpoint_dsa_pub_hip = NULL;
+    struct endpoint_hip *endpoint_rsa_hip     = NULL;
+    struct endpoint_hip *endpoint_rsa_pub_hip = NULL;
+
+    if (action == ACTION_ADD) {
+        numeric_action = SO_HIP_ADD_LOCAL_HI;
+    }
+
+    if ((err = hip_build_user_hdr(msg, numeric_action, 0))) {
+        HIP_ERROR("build hdr error %d\n", err);
+        goto out_err;
+    }
+
+    memset(addrstr, '\0', INET6_ADDRSTRLEN);
+    memset(hostname, '\0', HIP_HOST_ID_HOSTNAME_LEN_MAX);
+
+    if ((err = -gethostname(hostname, HIP_HOST_ID_HOSTNAME_LEN_MAX - 1))) {
+        HIP_ERROR("Failed to get hostname. Err is (%d).\n", err);
+        goto out_err;
+    }
+
+    HIP_INFO("Using hostname: %s\n", hostname);
+
+    HIP_IFEL((!use_default && strcmp(hi_fmt, "rsa") && strcmp(hi_fmt, "dsa")),
+             -ENOSYS, "Only RSA and DSA keys are supported\n");
+
+    /* Set filenamebase (depending on whether the user supplied a
+     * filenamebase or not) */
+    if (!use_default) {
+        if (!strcmp(hi_fmt, "dsa")) {
+            dsa_filenamebase = malloc(strlen(hi_file) + 1);
+            HIP_IFEL(!dsa_filenamebase, -ENOMEM,
+                     "Could not allocate DSA filename.\n");
+            memcpy(dsa_filenamebase, hi_file, strlen(hi_file));
+        } else {       /*rsa*/
+            rsa_filenamebase = malloc(strlen(hi_file) + 1);
+            HIP_IFEL(!rsa_filenamebase, -ENOMEM,
+                     "Could not allocate RSA filename.\n");
+            memcpy(rsa_filenamebase, hi_file, strlen(hi_file));
+        }
+    } else {     /* create dynamically default filenamebase */
+        int rsa_filenamebase_len = 0, dsa_filenamebase_len = 0, ret = 0;
+
+        HIP_INFO("No key file given, using default.\n");
+
+        /* Default_config_dir/default_host_dsa_key_file_base/
+         * default_anon_hi_file_name_suffix\0 */
+        /* Creation of default keys is called with hi_fmt = NULL,
+         * adding is called separately for DSA, RSA anon and RSA pub */
+        if (hi_fmt == NULL || !strcmp(hi_fmt, "dsa")) {
+            dsa_filenamebase_len =
+                strlen(DEFAULT_CONFIG_DIR) + strlen("/") +
+                strlen(DEFAULT_HOST_DSA_KEY_FILE_BASE) + 1;
+            dsa_filenamebase     = malloc(HOST_ID_FILENAME_MAX_LEN);
+            HIP_IFEL(!dsa_filenamebase, -ENOMEM,
+                     "Could not allocate DSA filename.\n");
+
+            ret = snprintf(dsa_filenamebase,
+                           dsa_filenamebase_len +
+                           strlen(DEFAULT_ANON_HI_FILE_NAME_SUFFIX),
+                           "%s/%s%s",
+                           DEFAULT_CONFIG_DIR,
+                           DEFAULT_HOST_DSA_KEY_FILE_BASE,
+                           DEFAULT_ANON_HI_FILE_NAME_SUFFIX);
+
+            HIP_IFE(ret <= 0, -EINVAL);
+
+            dsa_filenamebase_pub = malloc(HOST_ID_FILENAME_MAX_LEN);
+            HIP_IFEL(!dsa_filenamebase_pub, -ENOMEM,
+                     "Could not allocate DSA (pub) filename.\n");
+
+            ret = snprintf(dsa_filenamebase_pub,
+                           HOST_ID_FILENAME_MAX_LEN, "%s/%s%s",
+                           DEFAULT_CONFIG_DIR,
+                           DEFAULT_HOST_DSA_KEY_FILE_BASE,
+                           DEFAULT_PUB_HI_FILE_NAME_SUFFIX);
+
+            HIP_IFE(ret <= 0, -EINVAL);
+
+            HIP_DEBUG("Using dsa (anon hi) filenamebase: %s\n",
+                      dsa_filenamebase);
+            HIP_DEBUG("Using dsa (pub hi) filenamebase: %s\n",
+                      dsa_filenamebase_pub);
+        }
+
+        if (hi_fmt == NULL || !strcmp(hi_fmt, "rsa")) {
+            rsa_filenamebase_len =
+                strlen(DEFAULT_CONFIG_DIR) + strlen("/") +
+                strlen(DEFAULT_HOST_RSA_KEY_FILE_BASE) + 1;
+
+            if (anon || hi_fmt == NULL) {
+                rsa_filenamebase =
+                    malloc(HOST_ID_FILENAME_MAX_LEN);
+                HIP_IFEL(!rsa_filenamebase, -ENOMEM,
+                         "Could not allocate RSA filename.\n");
+
+                ret = snprintf(
+                    rsa_filenamebase,
+                    HOST_ID_FILENAME_MAX_LEN, "%s/%s%s",
+                    DEFAULT_CONFIG_DIR,
+                    DEFAULT_HOST_RSA_KEY_FILE_BASE,
+                    DEFAULT_ANON_HI_FILE_NAME_SUFFIX);
+
+                HIP_IFE(ret <= 0, -EINVAL);
+
+                HIP_DEBUG("Using RSA (anon HI) filenamebase: " \
+                          "%s.\n", rsa_filenamebase);
+            }
+
+            if (!anon || hi_fmt == NULL) {
+                rsa_filenamebase_pub =
+                    malloc(HOST_ID_FILENAME_MAX_LEN);
+                HIP_IFEL(!rsa_filenamebase_pub, -ENOMEM,
+                         "Could not allocate RSA (pub) " \
+                         "filename.\n");
+
+                ret = snprintf(
+                    rsa_filenamebase_pub,
+                    rsa_filenamebase_len +
+                    strlen(DEFAULT_PUB_HI_FILE_NAME_SUFFIX),
+                    "%s/%s%s", DEFAULT_CONFIG_DIR,
+                    DEFAULT_HOST_RSA_KEY_FILE_BASE,
+                    DEFAULT_PUB_HI_FILE_NAME_SUFFIX);
+
+                HIP_IFE(ret <= 0, -EINVAL);
+
+                HIP_DEBUG("Using RSA (pub HI) filenamebase: " \
+                          "%s\n", rsa_filenamebase_pub);
+            }
+        }
+    }
+
+    switch (action) {
+    case ACTION_NEW:
+        /* Default directory is created only in "hipconf new default hi" */
+        if (use_default) {
+            if ((err = check_and_create_dir(DEFAULT_CONFIG_DIR,
+                                            DEFAULT_CONFIG_DIR_MODE))) {
+                HIP_ERROR("Could not create default directory.\n");
+                goto out_err;
+            }
+        } else if (!use_default) {
+            if (!strcmp(hi_fmt, "dsa")) {
+                dsa_key = create_dsa_key(dsa_key_bits);
+                HIP_IFEL(!dsa_key, -EINVAL,
+                         "Creation of DSA key failed.\n");
+                if ((err = save_dsa_private_key(dsa_filenamebase, dsa_key))) {
+                    HIP_ERROR("Saving of DSA key failed.\n");
+                    goto out_err;
+                }
+            } else {             /*RSA*/
+                rsa_key = create_rsa_key(rsa_key_bits);
+                HIP_IFEL(!rsa_key, -EINVAL,
+                         "Creation of RSA key failed.\n");
+                if ((err = save_rsa_private_key(rsa_filenamebase, rsa_key))) {
+                    HIP_ERROR("Saving of RSA key failed.\n");
+                    goto out_err;
+                }
+            }
+            HIP_DEBUG("Key saved.\n");
+            break;
+        }
+
+        /* Using default */
+        dsa_key     = create_dsa_key(dsa_key_bits);
+        HIP_IFEL(!dsa_key, -EINVAL,
+                 "Creation of DSA key failed.\n");
+
+        dsa_pub_key = create_dsa_key(dsa_key_bits);
+        HIP_IFEL(!dsa_pub_key, -EINVAL,
+                 "Creation of public DSA key failed.\n");
+
+        rsa_key     = create_rsa_key(rsa_key_bits);
+        HIP_IFEL(!rsa_key, -EINVAL,
+                 "Creation of RSA key failed.\n");
+
+        rsa_pub_key = create_rsa_key(rsa_key_bits);
+        HIP_IFEL(!dsa_pub_key, -EINVAL,
+                 "Creation of public RSA key failed.\n");
+
+        if ((err = save_dsa_private_key(dsa_filenamebase, dsa_key))) {
+            HIP_ERROR("Saving of DSA key failed.\n");
+            goto out_err;
+        }
+
+        if ((err = save_dsa_private_key(dsa_filenamebase_pub, dsa_pub_key))) {
+            HIP_ERROR("Saving of public DSA key failed.\n");
+            goto out_err;
+        }
+
+        if ((err = save_rsa_private_key(rsa_filenamebase, rsa_key))) {
+            HIP_ERROR("Saving of RSA key failed.\n");
+            goto out_err;
+        }
+
+        if ((err = save_rsa_private_key(rsa_filenamebase_pub, rsa_pub_key))) {
+            HIP_ERROR("Saving of public RSA key failed.\n");
+            goto out_err;
+        }
+
+        break;
+
+    case ACTION_ADD:
+        if (!use_default) {
+            if (!strcmp(hi_fmt, "dsa")) {
+                if ((err = load_dsa_private_key(dsa_filenamebase, &dsa_key))) {
+                    HIP_ERROR("Loading of the DSA key failed\n");
+                    goto out_err;
+                }
+                dsa_key_rr_len = dsa_to_dns_key_rr(dsa_key, &dsa_key_rr);
+                HIP_IFEL(dsa_key_rr_len <= 0, -EFAULT, "dsa_key_rr_len <= 
0\n");
+
+                if ((err = dsa_to_hip_endpoint(dsa_key, &endpoint_dsa_hip,
+                                               anon ? HIP_ENDPOINT_FLAG_ANON : 
0, hostname))) {
+                    HIP_ERROR("Failed to allocate and build DSA endpoint.\n");
+                    goto out_err;
+                }
+                if ((err = hip_build_param_eid_endpoint(msg, 
endpoint_dsa_hip))) {
+                    HIP_ERROR("Building of host id failed\n");
+                    goto out_err;
+                }
+            } else { /*RSA*/
+                if ((err = load_rsa_private_key(rsa_filenamebase, &rsa_key))) {
+                    HIP_ERROR("Loading of the RSA key failed\n");
+                    goto out_err;
+                }
+                rsa_key_rr_len = rsa_to_dns_key_rr(rsa_key, &rsa_key_rr);
+                HIP_IFEL(rsa_key_rr_len <= 0, -EFAULT, "rsa_key_rr_len <= 
0\n");
+
+                if ((err = rsa_to_hip_endpoint(rsa_key, &endpoint_rsa_hip,
+                                               anon ? HIP_ENDPOINT_FLAG_ANON : 
0, hostname))) {
+                    HIP_ERROR("Failed to allocate and build RSA endpoint.\n");
+                    goto out_err;
+                }
+                if ((err = hip_build_param_eid_endpoint(msg, 
endpoint_rsa_hip))) {
+                    HIP_ERROR("Building of host id failed\n");
+                    goto out_err;
+                }
+            }
+            goto skip_host_id;
+        }
+
+        /* using default */
+
+        HIP_IFEL(hi_fmt == NULL, -1, "Key type is null.\n");
+
+        if (!strcmp(hi_fmt, "dsa")) {
+            if ((err = load_dsa_private_key(dsa_filenamebase, &dsa_key))) {
+                HIP_ERROR("Loading of the DSA key failed\n");
+                goto out_err;
+            }
+
+            dsa_key_rr_len = dsa_to_dns_key_rr(dsa_key, &dsa_key_rr);
+            HIP_IFEL(dsa_key_rr_len <= 0, -EFAULT, "dsa_key_rr_len <= 0\n");
+
+            if ((err = dsa_to_hip_endpoint(dsa_key, &endpoint_dsa_hip,
+                                           HIP_ENDPOINT_FLAG_ANON, hostname))) 
{
+                HIP_ERROR("Failed to allocate and build DSA endpoint 
(anon).\n");
+                goto out_err;
+            }
+
+            if ((err = hip_private_dsa_to_hit(dsa_key, dsa_key_rr,
+                                              HIP_HIT_TYPE_HASH100, 
&dsa_lhi.hit))) {
+                HIP_ERROR("Conversion from DSA to HIT failed\n");
+                goto out_err;
+            }
+
+            if ((err = load_dsa_private_key(dsa_filenamebase_pub, 
&dsa_pub_key))) {
+                HIP_ERROR("Loading of the DSA key (pub) failed\n");
+                goto out_err;
+            }
+
+            dsa_pub_key_rr_len = dsa_to_dns_key_rr(dsa_pub_key, 
&dsa_pub_key_rr);
+            HIP_IFEL(dsa_pub_key_rr_len <= 0, -EFAULT, "dsa_pub_key_rr_len <= 
0\n");
+
+            HIP_DEBUG_HIT("DSA HIT", &dsa_lhi.hit);
+
+            if ((err = hip_private_dsa_to_hit(dsa_pub_key, dsa_pub_key_rr,
+                                              HIP_HIT_TYPE_HASH100, 
&dsa_pub_lhi.hit))) {
+                HIP_ERROR("Conversion from DSA to HIT failed\n");
+                goto out_err;
+            }
+            HIP_DEBUG_HIT("DSA HIT", &dsa_pub_lhi.hit);
+
+            if ((err = dsa_to_hip_endpoint(dsa_pub_key,
+                                           &endpoint_dsa_pub_hip, 0, 
hostname))) {
+                HIP_ERROR("Failed to allocate and build DSA endpoint 
(pub).\n");
+                goto out_err;
+            }
+        } else if (anon) { /* rsa anon */
+            if ((err = load_rsa_private_key(rsa_filenamebase, &rsa_key))) {
+                HIP_ERROR("Loading of the RSA key failed\n");
+                goto out_err;
+            }
+
+            rsa_key_rr_len = rsa_to_dns_key_rr(rsa_key, &rsa_key_rr);
+            HIP_IFEL(rsa_key_rr_len <= 0, -EFAULT, "rsa_key_rr_len <= 0\n");
+
+            if ((err = rsa_to_hip_endpoint(rsa_key, &endpoint_rsa_hip,
+                                           HIP_ENDPOINT_FLAG_ANON, hostname))) 
{
+                HIP_ERROR("Failed to allocate and build RSA endpoint 
(anon).\n");
+                goto out_err;
+            }
+
+            if ((err = hip_private_rsa_to_hit(rsa_key, rsa_key_rr,
+                                              HIP_HIT_TYPE_HASH100,  
&rsa_lhi.hit))) {
+                HIP_ERROR("Conversion from RSA to HIT failed\n");
+                goto out_err;
+            }
+            HIP_DEBUG_HIT("RSA HIT", &rsa_lhi.hit);
+        } else { /* rsa pub */
+            if ((err = load_rsa_private_key(rsa_filenamebase_pub, 
&rsa_pub_key))) {
+                HIP_ERROR("Loading of the RSA key (pub) failed\n");
+                goto out_err;
+            }
+
+            rsa_pub_key_rr_len = rsa_to_dns_key_rr(rsa_pub_key, 
&rsa_pub_key_rr);
+            HIP_IFEL(rsa_pub_key_rr_len <= 0, -EFAULT, "rsa_pub_key_rr_len <= 
0\n");
+
+            if ((err = rsa_to_hip_endpoint(rsa_pub_key,
+                                           &endpoint_rsa_pub_hip, 0, 
hostname))) {
+                HIP_ERROR("Failed to allocate and build RSA endpoint 
(pub).\n");
+                goto out_err;
+            }
+
+            if ((err = hip_private_rsa_to_hit(rsa_pub_key, rsa_pub_key_rr,
+                                              HIP_HIT_TYPE_HASH100, 
&rsa_pub_lhi.hit))) {
+                HIP_ERROR("Conversion from RSA to HIT failed\n");
+                goto out_err;
+            }
+            HIP_DEBUG_HIT("RSA HIT", &rsa_pub_lhi.hit);
+        }
+
+        break;
+    } /* end switch */
+
+    if (numeric_action == 0) {
+        goto skip_msg;
+    }
+
+    if (!strcmp(hi_fmt, "dsa")) {
+        if ((err = hip_build_param_eid_endpoint(msg, endpoint_dsa_hip))) {
+            HIP_ERROR("Building of host id failed\n");
+            goto out_err;
+        }
+        if ((err = hip_build_param_eid_endpoint(msg, endpoint_dsa_pub_hip))) {
+            HIP_ERROR("Building of host id failed\n");
+            goto out_err;
+        }
+    } else if (anon) {
+        if ((err = hip_build_param_eid_endpoint(msg, endpoint_rsa_hip))) {
+            HIP_ERROR("Building of host id failed\n");
+            goto out_err;
+        }
+    } else {
+        if ((err = hip_build_param_eid_endpoint(msg, endpoint_rsa_pub_hip))) {
+            HIP_ERROR("Building of host id failed\n");
+            goto out_err;
+        }
+    }
+
+skip_host_id:
+skip_msg:
+
+out_err:
+    if (dsa_filenamebase != NULL) {
+        change_key_file_perms(dsa_filenamebase);
+    }
+    if (rsa_filenamebase != NULL) {
+        change_key_file_perms(rsa_filenamebase);
+    }
+    if (dsa_filenamebase_pub != NULL) {
+        change_key_file_perms(dsa_filenamebase_pub);
+    }
+    if (rsa_filenamebase_pub != NULL) {
+        change_key_file_perms(rsa_filenamebase_pub);
+    }
+
+    if (dsa_host_id) {
+        free(dsa_host_id);
+    }
+    if (dsa_pub_host_id) {
+        free(dsa_pub_host_id);
+    }
+    if (rsa_host_id) {
+        free(rsa_host_id);
+    }
+    if (rsa_pub_host_id) {
+        free(rsa_pub_host_id);
+    }
+    if (dsa_key) {
+        DSA_free(dsa_key);
+    }
+    if (rsa_key) {
+        RSA_free(rsa_key);
+    }
+    if (dsa_pub_key) {
+        DSA_free(dsa_pub_key);
+    }
+    if (rsa_pub_key) {
+        RSA_free(rsa_pub_key);
+    }
+    if (dsa_key_rr) {
+        free(dsa_key_rr);
+    }
+    if (rsa_key_rr) {
+        free(rsa_key_rr);
+    }
+    if (dsa_pub_key_rr) {
+        free(dsa_pub_key_rr);
+    }
+    if (rsa_pub_key_rr) {
+        free(rsa_pub_key_rr);
+    }
+    if (dsa_filenamebase) {
+        free(dsa_filenamebase);
+    }
+    if (rsa_filenamebase) {
+        free(rsa_filenamebase);
+    }
+    if (dsa_filenamebase_pub) {
+        free(dsa_filenamebase_pub);
+    }
+    if (rsa_filenamebase_pub) {
+        free(rsa_filenamebase_pub);
+    }
+    if (endpoint_dsa_hip) {
+        free(endpoint_dsa_hip);
+    }
+    if (endpoint_rsa_hip) {
+        free(endpoint_rsa_hip);
+    }
+    if (endpoint_dsa_pub_hip) {
+        free(endpoint_dsa_pub_hip);
+    }
+    if (endpoint_rsa_pub_hip) {
+        free(endpoint_rsa_pub_hip);
+    }
+
+    return err;
+}
+
+/**
+ * create DNS KEY RR record from host DSA key
+ * @param dsa the DSA structure from where the KEY RR record is to be created
+ * @param dsa_key_rr where the resultin KEY RR is stored
+ *
+ * @note Caller must free dsa_key_rr when it is not used anymore.
+ *
+ * @return On successful operation, the length of the KEY RR buffer is
+ * returned (greater than zero) and pointer to the buffer containing
+ * DNS KEY RR is stored at dsa_key_rr. On error function returns negative
+ * and sets dsa_key_rr to NULL.
+ */
+int dsa_to_dns_key_rr(DSA *dsa, unsigned char **dsa_key_rr)
+{
+    int err            = 0;
+    int dsa_key_rr_len = -1;
+    signed char t; /* in units of 8 bytes */
+    unsigned char *p = NULL;
+    int key_len;
+
+    HIP_ASSERT(dsa != NULL); /* should not happen */
+
+    *dsa_key_rr = NULL;
+
+    _HIP_DEBUG("numbytes p=%d\n", BN_num_bytes(dsa->p));
+    _HIP_DEBUG("numbytes q=%d\n", BN_num_bytes(dsa->q));
+    _HIP_DEBUG("numbytes g=%d\n", BN_num_bytes(dsa->g));
+    // shouldn't this be NULL also?
+    _HIP_DEBUG("numbytes pubkey=%d\n", BN_num_bytes(dsa->pub_key));
+
+
+    /* notice that these functions allocate memory */
+    _HIP_DEBUG("p=%s\n", BN_bn2hex(dsa->p));
+    _HIP_DEBUG("q=%s\n", BN_bn2hex(dsa->q));
+    _HIP_DEBUG("g=%s\n", BN_bn2hex(dsa->g));
+    _HIP_DEBUG("pubkey=%s\n", BN_bn2hex(dsa->pub_key));
+
+    /* ***** is use of BN_num_bytes ok ? ***** */
+    t = (BN_num_bytes(dsa->p) - 64) / 8;
+    HIP_IFEL((t < 0 || t > 8), -EINVAL,
+             "Invalid RSA key length %d bits\n", (64 + t * 8) * 8);
+    _HIP_DEBUG("t=%d\n", t);
+
+    /* RFC 2536 section 2 */
+    /*
+     *       Field     Size
+     *       -----     ----
+     *        T         1  octet
+     *        Q        20  octets
+     *        P        64 + T*8  octets
+     *        G        64 + T*8  octets
+     *        Y        64 + T*8  octets
+     *      [ X        20 optional octets (private key hack) ]
+     *
+     */
+    key_len        = 64 + t * 8;
+    dsa_key_rr_len = 1 + DSA_PRIV + 3 * key_len;
+
+    if (dsa->priv_key) {
+        dsa_key_rr_len += DSA_PRIV; /* private key hack */
+        _HIP_DEBUG("Private key included\n");
+    } else {
+        _HIP_DEBUG("No private key\n");
+    }
+
+    _HIP_DEBUG("dsa key rr len = %d\n", dsa_key_rr_len);
+    *dsa_key_rr = malloc(dsa_key_rr_len);
+    HIP_IFEL(!*dsa_key_rr, -ENOMEM, "Malloc for *dsa_key_rr failed\n");
+    memset(*dsa_key_rr, 0, dsa_key_rr_len);
+
+    p           = *dsa_key_rr;
+
+    /* set T */
+    memset(p, t, 1); // XX FIX: WTF MEMSET?
+    p++;
+    _HIP_HEXDUMP("DSA KEY RR after T:", *dsa_key_rr, p - *dsa_key_rr);
+
+    /* add given dsa_param to the *dsa_key_rr */
+
+    bn2bin_safe(dsa->q, p, DSA_PRIV);
+    p += DSA_PRIV;
+    _HIP_HEXDUMP("DSA KEY RR after Q:", *dsa_key_rr, p - *dsa_key_rr);
+
+    bn2bin_safe(dsa->p, p, key_len);
+    p += key_len;
+    _HIP_HEXDUMP("DSA KEY RR after P:", *dsa_key_rr, p - *dsa_key_rr);
+
+    bn2bin_safe(dsa->g, p, key_len);
+    p += key_len;
+    _HIP_HEXDUMP("DSA KEY RR after G:", *dsa_key_rr, p - *dsa_key_rr);
+
+    bn2bin_safe(dsa->pub_key, p, key_len);
+    p += key_len;
+    _HIP_HEXDUMP("DSA KEY RR after Y:", *dsa_key_rr, p - *dsa_key_rr);
+
+    if (dsa->priv_key) {
+        bn2bin_safe(dsa->priv_key, p, DSA_PRIV);
+        _HIP_HEXDUMP("DSA KEY RR after X:", *dsa_key_rr, p - *dsa_key_rr);
+    }
+
+out_err:
+
+    if (err) {
+        if (*dsa_key_rr) {
+            free(*dsa_key_rr);
+        }
+        return err;
+    } else {
+        return dsa_key_rr_len;
+    }
+}
+
+/**
+ * create a DNS KEY RR record from a given host RSA public key
+ *
+ * @param rsa the RSA structure from where the KEY RR record is to be created
+ * @param rsa_key_rr where the resultin KEY RR is stored
+ * @return On successful operation, the length of the KEY RR buffer is
+ *         returned (greater than zero) and pointer to the buffer containing
+ *         DNS KEY RR is stored at rsa_key_rr. On error function returns
+ *         negative and sets rsa_key_rr to NULL.
+ * @note Caller must free rsa_key_rr when it is not used anymore.
+ * @note This function assumes that RSA given as a parameter is always public.
+ */
+int rsa_to_dns_key_rr(RSA *rsa, unsigned char **rsa_key_rr)
+{
+    int err            = 0;
+    int rsa_key_rr_len = -1;
+    unsigned char *c = NULL;
+    int public = -1;
+    int e_len_bytes    = 1;
+    int e_len, key_len;
+
+    HIP_ASSERT(rsa != NULL); /* should not happen */
+
+    *rsa_key_rr = NULL;
+
+    e_len       = BN_num_bytes(rsa->e);
+    key_len     = RSA_size(rsa);
+
+    /* RFC 3110 limits e to 4096 bits */
+    HIP_IFEL(e_len > 512, -EINVAL,  "Invalid rsa->e length %d bytes\n", e_len);
+    if (e_len > 255) {
+        e_len_bytes = 3;
+    }
+
+    /* let's check if the RSA key is public or private
+     * private exponent is NULL in public keys */
+    if (rsa->d == NULL) {
+        public         = 1;
+        rsa_key_rr_len = e_len_bytes + e_len + key_len;
+
+        /*
+         * See RFC 2537 for flags, protocol and algorithm and check RFC 3110 
for
+         * the RSA public key part ( 1-3 octets defining length of the 
exponent,
+         * exponent is as many octets as the length defines and the modulus is
+         * all the rest of the bytes).
+         */
+    } else {
+        public         = 0;
+        rsa_key_rr_len = e_len_bytes + e_len + key_len * 9 / 2;
+    }
+
+    *rsa_key_rr = malloc(rsa_key_rr_len);
+    HIP_IFEL(!*rsa_key_rr, -ENOMEM, "Malloc for *rsa_key_rr failed\n");
+    memset(*rsa_key_rr, 0, rsa_key_rr_len);
+
+    c           = *rsa_key_rr;
+
+    if (e_len_bytes == 1) {
+        *c = (unsigned char) e_len;
+    }
+    c++; /* If e_len is more than one byte, first byte is 0. */
+    if (e_len_bytes == 3) {
+        *c = htons((uint16_t) e_len);
+        c += 2;
+    }
+
+    bn2bin_safe(rsa->e, c, e_len);
+    c += e_len;
+    bn2bin_safe(rsa->n, c, key_len);
+    c += key_len;
+
+    if (!public) {
+        bn2bin_safe(rsa->d, c, key_len);
+        c += key_len;
+        bn2bin_safe(rsa->p, c, key_len / 2);
+        c += key_len / 2;
+        bn2bin_safe(rsa->q, c, key_len / 2);
+        c += key_len / 2;
+        bn2bin_safe(rsa->dmp1, c, key_len / 2);
+        c += key_len / 2;
+        bn2bin_safe(rsa->dmq1, c, key_len / 2);
+        c += key_len / 2;
+        bn2bin_safe(rsa->iqmp, c, key_len / 2);
+    }
+
+out_err:
+
+    if (err) {
+        if (*rsa_key_rr) {
+            free(*rsa_key_rr);
+        }
+        return err;
+    }
+
+    return rsa_key_rr_len;
+}

=== added file 'lib/core/hostid.h'
--- lib/core/hostid.h   1970-01-01 00:00:00 +0000
+++ lib/core/hostid.h   2010-03-19 09:53:35 +0000
@@ -0,0 +1,68 @@
+#ifndef HIP_LIB_CORE_HOSTID_H
+#define HIP_LIB_CORE_HOSTID_H
+
+#include "state.h"
+
+struct hip_rsa_keylen {
+    int e_len;
+    int e;
+    int n;
+};
+
+struct hip_hit_info {
+    struct hip_lhi lhi;
+    hip_lsi_t      lsi;
+};
+
+int hip_verify_packet_signature(struct hip_common *pkt,
+                                struct hip_host_id *peer_host_id);
+
+int hip_dsa_host_id_to_hit(const struct hip_host_id *host_id,
+                           struct in6_addr *hit, int hit_type);
+
+/* Useless abstraction, goes to the same function anyway -- SAMU
+ *
+ * True that. Let's make this a static inline function and move it to the 
header
+ * file. It still remains as useless abstraction, but at least we eliminate the
+ * need for a call and return sequence. -Lauri 06.08.2008
+ */
+static inline int hip_rsa_host_id_to_hit(const struct hip_host_id *host_id,
+                                         struct in6_addr *hit, int hit_type)
+{
+    return hip_dsa_host_id_to_hit(host_id, hit, hit_type);
+}
+
+int hip_host_id_to_hit(const struct hip_host_id *host_id,
+                       struct in6_addr *hit, int hit_type);
+int hip_private_dsa_host_id_to_hit(const struct hip_host_id_priv *host_id,
+                                   struct in6_addr *hit,
+                                   int hit_type);
+int hip_private_rsa_host_id_to_hit(const struct hip_host_id_priv *host_id,
+                                   struct in6_addr *hit,
+                                   int hit_type);
+int hip_private_host_id_to_hit(const struct hip_host_id_priv *host_id,
+                               struct in6_addr *hit, int hit_type);
+int hip_host_id_contains_private_key(struct hip_host_id *host_id);
+void hip_get_rsa_keylen(const struct hip_host_id_priv *host_id,
+                        struct hip_rsa_keylen *ret,
+                        int is_priv);
+
+RSA *hip_key_rr_to_rsa(const struct hip_host_id_priv *host_id, int is_priv);
+DSA *hip_key_rr_to_dsa(const struct hip_host_id_priv *host_id, int is_priv);
+int dsa_to_dns_key_rr(DSA *dsa, unsigned char **buf);
+int rsa_to_dns_key_rr(RSA *rsa, unsigned char **rsa_key_rr);
+int hip_host_id_entry_to_hit_info(struct hip_host_id_entry *entry,
+                                  void *msg);
+int hip_serialize_host_id_action(struct hip_common *msg,
+                                 int action,
+                                 int anon,
+                                 int use_default,
+                                 const char *hi_fmt,
+                                 const char *hi_file,
+                                 int rsa_key_bits,
+                                 int dsa_key_bits);
+int khi_encode(unsigned char *orig, int orig_len,
+               unsigned char *encoded,
+               int encoded_len);
+
+#endif /* HIP_LIB_CORE_HOSTID_H */

=== added file 'lib/core/hostsfiles.c'
--- lib/core/hostsfiles.c       1970-01-01 00:00:00 +0000
+++ lib/core/hostsfiles.c       2010-03-19 09:53:35 +0000
@@ -0,0 +1,624 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * This file contains iterator functions to access and parse
+ * /etc/hosts and /etc/hip/hosts files. Also, this file contains a
+ * number of predefined functions that support mapping between
+ * hostnames, HITs, LSIs and routable IP addresses.
+ *
+ * @brief parser for /etc/hosts and /etc/hip/hosts
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ *
+ * @todo is there a standard API for accessing hosts files?
+ */
+
+/* required for s6_addr32 */
+#define _BSD_SOURCE
+
+#include <arpa/inet.h>
+#include <time.h>
+#include <netinet/in.h>
+
+#include "config.h"
+
+#include "hostsfiles.h"
+#include "lib/tool/lutil.h"
+
+/**
+ * A "for-each" iterator function for hosts files that returns the first
+ * hostname that matches the given address
+ *
+ * @param entry a hosts file line entry
+ * @param arg the IPv6 or IPv6-mapped IPv4 address to match
+ * @param result An output argument where the matching hostname will be
+ *        written. Minimum buffer length is HOST_NAME_MAX chars.
+ * @return zero on match or one otherwise
+ */
+int hip_map_first_id_to_hostname_from_hosts(const struct hosts_file_line 
*entry,
+                                            const void *arg,
+                                            void *result)
+{
+    int err = 1;
+
+    if (!ipv6_addr_cmp((struct in6_addr *) arg, &entry->id)) {
+        _HIP_DEBUG("Match on line %d\n", entry->lineno);
+        memcpy(result, entry->hostname, strlen(entry->hostname));
+        err = 0; /* Stop at the first match */
+    }
+
+    return err;
+}
+
+/**
+ * A "for-each" iterator function for hosts files that returns the first
+ * hostname that matches the given LSI
+ *
+ * @param entry a hosts file line entry
+ * @param arg an IPv6-mapped LSI to match
+ * @param result An output argument where the matching hostname will be
+ *        written. Minimum buffer length is HOST_NAME_MAX chars.
+ * @return zero on match or one otherwise
+ */
+int hip_map_first_lsi_to_hostname_from_hosts(const struct hosts_file_line 
*entry,
+                                             const void *arg,
+                                             void *result)
+{
+    int err    = 1;
+    int is_lsi = hip_id_type_match(&entry->id, 2);
+
+    if (!ipv6_addr_cmp((struct in6_addr *) arg, &entry->id) && is_lsi) {
+        _HIP_DEBUG("Match on line %d\n", entry->lineno);
+        memcpy(result, entry->hostname, strlen(entry->hostname));
+        err = 0; /* Stop at the first match */
+    }
+
+    return err;
+}
+
+/**
+ * find the hostname matching the given LSI from /etc/hip/hosts and
+ * /etc/hosts (in this particular order)
+ *
+ * @param lsi the LSI to match
+ * @param hostname An output argument where the matching hostname
+ *                 will be written. Minimum buffer length is
+ *                 HOST_NAME_MAX chars.
+ * @return zero on successful match or non-zero otherwise
+ */
+int hip_map_lsi_to_hostname_from_hosts(hip_lsi_t *lsi, char *hostname)
+{
+    return hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                        
hip_map_first_lsi_to_hostname_from_hosts,
+                                        lsi, hostname) &&
+           hip_for_each_hosts_file_line(HOSTS_FILE,
+                                        
hip_map_first_lsi_to_hostname_from_hosts,
+                                        lsi, hostname);
+}
+
+/**
+ * A "for-each" iterator function for hosts files that returns the first
+ * HIT that matches the hostname
+ *
+ * @param entry a hosts file line entry
+ * @param arg a hostname as a string
+ * @param result An output argument where the matching matching HIT will be
+ *        written. Minimum buffer length is sizeof(struct hip_hit_t)
+ * @return zero on match or one otherwise
+ */
+int hip_map_first_hostname_to_hit_from_hosts(const struct hosts_file_line 
*entry,
+                                             const void *arg,
+                                             void *result)
+{
+    int err = 1;
+    int is_hit;
+
+    /* test if hostname/alias matches and the type is hit */
+    if (!strncmp(arg, entry->hostname, HOST_NAME_MAX) ||
+        (entry->alias && !strncmp(arg, entry->alias, HOST_NAME_MAX)) ||
+        (entry->alias2 && !strncmp(arg, entry->alias2, HOST_NAME_MAX))) {
+        is_hit = hip_id_type_match(&entry->id, 1);
+
+        HIP_IFE(!is_hit, 1);
+
+        _HIP_DEBUG("Match on line %d\n", entry->lineno);
+        ipv6_addr_copy(result, &entry->id);
+        err = 0; /* Stop at the first match */
+    }
+
+out_err:
+
+    return err;
+}
+
+/**
+ * A "for-each" iterator function for hosts files that returns the first
+ * LSI that matches the hostname
+ *
+ * @param entry a hosts file line entry
+ * @param arg a hostname as a string
+ * @param result An output argument where the matching matching LSI will be
+ *        written in IPv6 mapped format. Minimum buffer length is
+ *        sizeof(struct in6_addr)
+ * @return zero on match or one otherwise
+ */
+int hip_map_first_hostname_to_lsi_from_hosts(const struct hosts_file_line 
*entry,
+                                             const void *arg,
+                                             void *result)
+{
+    int err = 1;
+    int is_lsi;
+
+    /* test if hostname/alias matches and the type is lsi */
+    if (!strncmp(arg, entry->hostname, HOST_NAME_MAX) ||
+        (entry->alias && !strncmp(arg, entry->alias, HOST_NAME_MAX)) ||
+        (entry->alias2 && !strncmp(arg, entry->alias2, HOST_NAME_MAX))) {
+        is_lsi = hip_id_type_match(&entry->id, 2);
+
+        HIP_IFE(!is_lsi, 1);
+
+        _HIP_DEBUG("Match on line %d\n", entry->lineno);
+        ipv6_addr_copy(result, &entry->id);
+        err = 0; /* Stop at the first match */
+    }
+
+out_err:
+
+    return err;
+}
+
+/**
+ * A "for-each" iterator function for hosts files that returns the first
+ * routable IP address that matches the hostname
+ *
+ * @param entry a hosts file line entry
+ * @param arg a hostname as a string
+ * @param result An output argument where the matching matching IP address 
will be
+ *        written. IPv4 addresses are written in IPv6 mapped format and
+ *        the minimum buffer length is sizeof(struct in6_addr)
+ * @return zero on match or one otherwise
+ */
+int hip_map_first_hostname_to_ip_from_hosts(const struct hosts_file_line 
*entry,
+                                            const void *arg,
+                                            void *result)
+{
+    int err = 1;
+    int is_lsi, is_hit;
+
+    /* test if hostname/alias matches and the type is routable ip */
+    if (!strncmp(arg, entry->hostname, HOST_NAME_MAX) ||
+        (entry->alias && !strncmp(arg, entry->alias, HOST_NAME_MAX)) ||
+        (entry->alias2 && !strncmp(arg, entry->alias2, HOST_NAME_MAX))) {
+        is_hit = hip_id_type_match(&entry->id, 1);
+        is_lsi = hip_id_type_match(&entry->id, 2);
+
+        HIP_IFE((is_hit || is_lsi), 1);
+
+        _HIP_DEBUG("Match on line %d\n", entry->lineno);
+        ipv6_addr_copy(result, &entry->id);
+        err = 0; /* Stop at the first match */
+    }
+
+out_err:
+
+    return err;
+}
+
+/**
+ * A "for-each" iterator function for hosts files to calculate
+ * the number of non-commented lines
+ *
+ * @param entry a hosts file line entry
+ * @param arg unused, but required by the API
+ * @param result an int pointer where the number of lines
+ *               will be calculated
+ * @return always one
+ */
+int hip_calc_lines_in_hosts(const struct hosts_file_line *entry,
+                            const void *arg,
+                            void *result)
+{
+    int *res = (int *) result;
+    (*res)++;
+    return 1;
+}
+
+/**
+ * A "for-each" iterator function for hosts files that returns the Nth
+ * identifier (address, LSI or HIT) from a hosts file
+ *
+ * @param entry a hosts file line entry
+ * @param arg the N as an int pointer
+ * @param result An output argument where the matching matching address will be
+ *        written. IPv4 addresses are written in IPv6 mapped format and
+ *        the minimum buffer length is sizeof(struct in6_addr).
+ * @return zero on match or one otherwise
+ */
+int hip_get_nth_id_from_hosts(const struct hosts_file_line *entry,
+                              const void *arg,
+                              void *result)
+{
+    int err         = 1;
+    const int *nth  = (const int *) arg;
+    int *total_past = (int *) result;
+
+    if (*nth == *total_past) {
+        ipv6_addr_copy(result, &entry->id);
+        err = 0;
+    } else {
+        (*total_past)++;
+    }
+    return err;
+}
+
+/**
+ * "For-each" loop to iterate through /etc/hosts or /etc/hip/hosts file, line
+ * by line.
+ *
+ * @param hosts_file the path and name to the hosts file
+ * @param func the iterator function pointer
+ * @param arg an input argument for the function pointer
+ * @param an output argument for the function pointer
+ * @return zero on success or non-zero on failure
+ */
+int hip_for_each_hosts_file_line(const char *hosts_file,
+                                 int(*func)(const struct hosts_file_line *line,
+                                            const void *arg,
+                                            void *result),
+                                 void *arg,
+                                 void *result)
+{
+    FILE *hip_hosts = NULL;
+    List mylist;
+    char line[500];
+    int err         = 0, lineno = 0;
+    struct in_addr in_addr;
+    struct hosts_file_line entry;
+    char *hostname  = NULL, *alias = NULL, *alias2 = NULL, *addr_ptr = NULL;
+
+    initlist(&mylist);
+    memset(line, 0, sizeof(line));
+
+    /* check whether  given hit_str is actually a HIT */
+
+    hip_hosts = fopen(hosts_file, "r");
+
+    HIP_IFEL(!hip_hosts, -1, "Failed to open hosts file\n");
+
+    /* For each line in the given hosts file, convert the line into binary 
format and
+     * call the given the handler  */
+
+    err = 1;
+    while (fgets(line, sizeof(line) - 1, hip_hosts) != NULL) {
+        char *eofline, *c, *comment;
+        int len;
+
+        lineno++;
+        c = line;
+
+        /* Remove whitespace */
+        while (*c == ' ' || *c == '\t') {
+            c++;
+        }
+
+        /* Line is a comment or empty */
+        if (*c == '#' || *c == '\n' || *c == '\0') {
+            continue;
+        }
+
+        eofline = strchr(c, '\n');
+        if (eofline) {
+            *eofline = '\0';
+        }
+
+        /* Terminate before (the first) trailing comment */
+        comment = strchr(c, '#');
+        if (comment) {
+            *comment = '\0';
+        }
+
+        /* shortest hostname: ":: a" = 4 */
+        if ((len = strlen(c)) < 4) {
+            HIP_DEBUG("skip line\n");
+            continue;
+        }
+
+        _HIP_DEBUG("lineno=%d, str=%s\n", lineno, c);
+
+        /* Split line into list */
+        extractsubstrings(c, &mylist);
+
+        len = length(&mylist);
+        if (len < 2 || len > 4) {
+            HIP_ERROR("Bad number of items on line %d in %s, skipping\n",
+                      lineno, hosts_file);
+            continue;
+        }
+
+        /* The list contains hosts line in reverse order. Let's sort it. */
+        switch (len) {
+        case (2):
+            alias    = NULL;
+            hostname = getitem(&mylist, 0);
+            addr_ptr = getitem(&mylist, 1);
+            break;
+        case (3):
+            alias    = getitem(&mylist, 0);
+            hostname = getitem(&mylist, 1);
+            addr_ptr = getitem(&mylist, 2);
+            break;
+        case (4):
+            alias2   = getitem(&mylist, 0);
+            alias    = getitem(&mylist, 1);
+            hostname = getitem(&mylist, 2);
+            addr_ptr = getitem(&mylist, 3);
+            break;
+        }
+
+        /* Initialize entry */
+
+        memset(&entry, 0, sizeof(entry));
+
+        HIP_ASSERT(addr_ptr);
+        err = inet_pton(AF_INET6, addr_ptr, &entry.id);
+        if (err <= 0) {
+            err = inet_pton(AF_INET, addr_ptr, &in_addr);
+            if (err <= 0) {
+                HIP_ERROR("Bad address %s on line %d in %s, skipping\n",
+                          addr_ptr, lineno, hosts_file);
+                continue;
+            }
+            IPV4_TO_IPV6_MAP(&in_addr, &entry.id);
+        }
+
+        entry.hostname = hostname;
+        HIP_ASSERT(entry.hostname)
+
+        entry.alias2   = alias2;
+        entry.alias    = alias;
+        entry.lineno   = lineno;
+
+        /* Finally, call the handler function to handle the line */
+
+        if (func(&entry, arg, result) == 0) {
+            _HIP_DEBUG("Match on line %d in %s\n", lineno, hosts_file);
+            err = 0;
+            break;
+        }
+
+        memset(line, 0, sizeof(line));
+        destroy(&mylist);
+    }
+
+out_err:
+
+    destroy(&mylist);
+
+    if (hip_hosts) {
+        fclose(hip_hosts);
+    }
+
+    return err;
+}
+
+/**
+ * find the HIT matching to the given LSI from /etc/hip/hosts and
+ * /etc/hosts (in this particular order)
+ *
+ * @param lsi the LSI to match
+ * @param hit An output argument where the matching matching HIT will be
+ *            written. Minimum buffer length is sizeof(struct hip_hit_t)
+ * @return zero on successful match or non-zero otherwise
+ */
+int hip_map_lsi_to_hit_from_hosts_files(hip_lsi_t *lsi, hip_hit_t *hit)
+{
+    int err = 0;
+    uint8_t hostname[HOST_NAME_MAX];
+    struct in6_addr mapped_lsi;
+
+    memset(hostname, 0, sizeof(hostname));
+    HIP_ASSERT(lsi && hit);
+
+    IPV4_TO_IPV6_MAP(lsi, &mapped_lsi);
+
+    err = hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                       hip_map_first_id_to_hostname_from_hosts,
+                                       &mapped_lsi, hostname);
+    if (err) {
+        err = hip_for_each_hosts_file_line(HOSTS_FILE,
+                                           
hip_map_first_id_to_hostname_from_hosts,
+                                           &mapped_lsi, hostname);
+    }
+
+    HIP_IFEL(err, -1, "Failed to map id to hostname\n");
+
+    err = hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                       
hip_map_first_hostname_to_hit_from_hosts,
+                                       hostname, hit);
+    if (err) {
+        err = hip_for_each_hosts_file_line(HOSTS_FILE,
+                                           
hip_map_first_hostname_to_hit_from_hosts,
+                                           hostname, hit);
+    }
+
+    HIP_IFEL(err, -1, "Failed to map id to hostname\n");
+
+    HIP_DEBUG_HIT("Found hit: ", hit);
+
+out_err:
+
+    return err;
+}
+
+/**
+ * find the LSI matching to the given HIT from /etc/hip/hosts and
+ * /etc/hosts (in this particular order)
+ *
+ * @param hit the HIT to match
+ * @param lsi An output argument where the matching matching LSI will
+ *            will be written
+ * @return zero on successful match or non-zero otherwise
+ */
+int hip_map_hit_to_lsi_from_hosts_files(const hip_hit_t *hit, hip_lsi_t *lsi)
+{
+    int err = 0;
+    uint8_t hostname[HOST_NAME_MAX];
+    struct in6_addr mapped_lsi;
+
+    memset(hostname, 0, sizeof(hostname));
+    HIP_ASSERT(lsi && hit);
+
+    err = (hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                        
hip_map_first_id_to_hostname_from_hosts,
+                                        (hip_hit_t *) hit, hostname) &&
+           hip_for_each_hosts_file_line(HOSTS_FILE,
+                                        
hip_map_first_id_to_hostname_from_hosts,
+                                        (hip_hit_t *) hit, hostname));
+    HIP_IFEL(err, -1, "Failed to map id to hostname\n");
+
+    err = (hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                        
hip_map_first_hostname_to_lsi_from_hosts,
+                                        hostname, &mapped_lsi) &&
+           hip_for_each_hosts_file_line(HOSTS_FILE,
+                                        
hip_map_first_hostname_to_lsi_from_hosts,
+                                        hostname, &mapped_lsi));
+    HIP_IFEL(err, -1, "Failed to map hostname to lsi\n");
+
+    IPV6_TO_IPV4_MAP(&mapped_lsi, lsi);
+
+    HIP_DEBUG_LSI("Found lsi: ", lsi);
+
+out_err:
+
+    return err;
+}
+
+/**
+ * Fetch a random host name from a hosts file. Currently this
+ * is used for selecting a random DHT node for load balancing.
+ *
+ * @param filename the hosts file path and file name
+ * @param hostname the hostname will be written here
+ * @param id_str The address, LSI or HIT corresponding to the
+ *               the hostname will be written here as a string.
+ * @return zero on successful match or non-zero on failure
+ */
+int hip_get_random_hostname_id_from_hosts(char *filename,
+                                          char *hostname,
+                                          char *id_str)
+{
+    int lines = 0, err = 0, nth;
+    struct in6_addr id;
+
+    memset(&id, 0, sizeof(struct in6_addr));
+
+    /* ignore return value, returns always error */
+    hip_for_each_hosts_file_line(filename,
+                                 hip_calc_lines_in_hosts,
+                                 NULL,
+                                 &lines);
+    HIP_IFEL((lines == 0), -1,
+             "No lines in host file %s\n", filename);
+
+    srand(time(NULL));
+    nth = rand() % lines;
+
+    err = hip_for_each_hosts_file_line(filename,
+                                       hip_get_nth_id_from_hosts,
+                                       &nth,
+                                       &id);
+    HIP_IFEL(err, -1, "Failed to get random id\n");
+
+    err = hip_for_each_hosts_file_line(filename,
+                                       hip_map_first_id_to_hostname_from_hosts,
+                                       &id,
+                                       hostname);
+    HIP_IFEL(err, -1, "Failed to map to hostname\n");
+
+    if (IN6_IS_ADDR_V4MAPPED(&id)) {
+        struct in_addr id4;
+        IPV6_TO_IPV4_MAP(&id, &id4);
+        HIP_IFEL(!inet_ntop(AF_INET, &id4, id_str,
+                            INET_ADDRSTRLEN), -1,
+                 "inet_ntop failed\n");
+    } else {
+        HIP_IFEL(!inet_ntop(AF_INET6, &id, id_str,
+                            INET6_ADDRSTRLEN), -1,
+                 "inet_ntop failed\n");
+    }
+
+out_err:
+    return err;
+}
+
+/**
+ * This function maps a HIT or a LSI (nodename) to an IP address using the two 
hosts files.
+ * The function implements this in two steps. First, it maps the HIT or LSI to 
an hostname
+ * from /etc/hip/hosts or /etc/hosts. Second, it maps the hostname to a IP 
address from
+ * /etc/hosts. The IP address is returned in the res argument.
+ *
+ * @param hit a HIT to be mapped
+ * @param lsi an LSI to be mapped
+ * @param ip the resulting routable IP address if found
+ * @return zero on successful match or non-zero otherwise
+ */
+int hip_map_id_to_ip_from_hosts_files(hip_hit_t *hit, hip_lsi_t *lsi, struct 
in6_addr *ip)
+{
+    int err = 0;
+    uint8_t hostname[HOST_NAME_MAX];
+
+    HIP_ASSERT((hit || lsi) && ip);
+
+    memset(hostname, 0, sizeof(hostname));
+
+    if (hit && !ipv6_addr_any(hit)) {
+        err = hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                           
hip_map_first_id_to_hostname_from_hosts,
+                                           hit, hostname);
+    } else {
+        struct in6_addr mapped_lsi;
+        IPV4_TO_IPV6_MAP(lsi, &mapped_lsi);
+        err = (hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                            
hip_map_first_id_to_hostname_from_hosts,
+                                            &mapped_lsi, hostname) &&
+               hip_for_each_hosts_file_line(HOSTS_FILE,
+                                            
hip_map_first_id_to_hostname_from_hosts,
+                                            &mapped_lsi, hostname));
+    }
+
+    HIP_IFEL(err, -1, "Failed to map id to hostname\n");
+
+    err = hip_for_each_hosts_file_line(HOSTS_FILE,
+                                       hip_map_first_hostname_to_ip_from_hosts,
+                                       hostname, ip);
+    HIP_IFEL(err, -1, "Failed to map id to ip\n");
+
+out_err:
+    return err;
+}
+
+/**
+ * check if the given LSI is in the hosts files
+ *
+ * @param lsi the LSI to be searched for
+ * @return one if the LSI exists or zero otherwise
+ *
+ */
+int hip_host_file_info_exists_lsi(hip_lsi_t *lsi)
+{
+    uint8_t hostname[HOST_NAME_MAX];
+    struct in6_addr mapped_lsi;
+
+    memset(hostname, 0, sizeof(hostname));
+
+    IPV4_TO_IPV6_MAP(lsi, &mapped_lsi);
+
+    return !(hip_for_each_hosts_file_line(HIPL_HOSTS_FILE,
+                                          
hip_map_first_id_to_hostname_from_hosts,
+                                          &mapped_lsi, hostname) &&
+             hip_for_each_hosts_file_line(HOSTS_FILE,
+                                          
hip_map_first_id_to_hostname_from_hosts,
+                                          &mapped_lsi, hostname));
+}

=== added file 'lib/core/hostsfiles.h'
--- lib/core/hostsfiles.h       1970-01-01 00:00:00 +0000
+++ lib/core/hostsfiles.h       2010-03-19 09:53:35 +0000
@@ -0,0 +1,40 @@
+#ifndef HIP_LIB_CORE_HOSTSFILES_H
+#define HIP_LIB_CORE_HOSTSFILES_H
+
+#include "prefix.h"
+#include "lib/conf/hipconf.h"
+
+#ifndef HOST_NAME_MAX
+#  define HOST_NAME_MAX 64
+#endif /* HOST_NAME_MAX */
+
+int hip_map_first_id_to_hostname_from_hosts(const struct hosts_file_line 
*entry,
+                                            const void *arg,
+                                            void *result);
+int hip_map_first_hostname_to_hit_from_hosts(const struct hosts_file_line 
*entry,
+                                             const void *arg,
+                                             void *result);
+int hip_map_first_hostname_to_lsi_from_hosts(const struct hosts_file_line 
*entry,
+                                             const void *arg,
+                                             void *result);
+int hip_map_first_hostname_to_ip_from_hosts(const struct hosts_file_line 
*entry,
+                                            const void *arg,
+                                            void *result);
+int hip_for_each_hosts_file_line(const char *hosts_file,
+                                 int(*func)(const struct hosts_file_line *line,
+                                            const void *arg,
+                                            void *result),
+                                 void *arg,
+                                 void *result);
+int hip_map_lsi_to_hit_from_hosts_files(hip_lsi_t *lsi, hip_hit_t *hit);
+int hip_map_hit_to_lsi_from_hosts_files(const hip_hit_t *hit, hip_lsi_t *lsi);
+int hip_map_id_to_ip_from_hosts_files(hip_hit_t *hit,
+                                      hip_lsi_t *lsi,
+                                      struct in6_addr *ip);
+int hip_map_lsi_to_hostname_from_hosts(hip_lsi_t *lsi, char *hostname);
+int hip_get_random_hostname_id_from_hosts(char *filename,
+                                          char *hostname,
+                                          char *id_str);
+int hip_host_file_info_exists_lsi(hip_lsi_t *lsi);
+
+#endif /* HIP_LIB_CORE_HOSTSFILES_H */

=== added file 'lib/core/keylen.c'
--- lib/core/keylen.c   1970-01-01 00:00:00 +0000
+++ lib/core/keylen.c   2010-03-19 09:53:35 +0000
@@ -0,0 +1,103 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Various key length calculation functions
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#include "keylen.h"
+#include "protodefs.h"
+#include "debug.h"
+
+/**
+ * get encryption key length for a transform
+ *
+ * @param tid transform
+ * @return the encryption key length of the chosen transform,
+ *         or negative  on error.
+ */
+int hip_enc_key_length(int tid)
+{
+    int ret = -1;
+
+    switch (tid) {
+    case HIP_ESP_AES_SHA1:
+        ret = 16;
+        break;
+    case HIP_ESP_3DES_SHA1:
+        ret = 24;
+        break;
+    case HIP_ESP_NULL_SHA1:
+    case HIP_ESP_NULL_NULL:
+        ret = 0;
+        break;
+    default:
+        HIP_ERROR("unknown tid=%d\n", tid);
+        HIP_ASSERT(0);
+        break;
+    }
+
+    return ret;
+}
+
+/**
+ * get hmac key length of a transform
+ *
+ * @param tid transform
+ * @return the encryption key length based of the chosen transform,
+ *         or negative  on error.
+ */
+int hip_hmac_key_length(int tid)
+{
+    int ret = -1;
+    switch (tid) {
+    case HIP_ESP_AES_SHA1:
+    case HIP_ESP_3DES_SHA1:
+    case HIP_ESP_NULL_SHA1:
+        ret = 20;
+        break;
+    case HIP_ESP_NULL_NULL:
+        ret = 0;
+        break;
+    default:
+        HIP_ERROR("unknown tid=%d\n", tid);
+        HIP_ASSERT(0);
+        break;
+    }
+
+    return ret;
+}
+
+
+/**
+ * get authentication key length for an ESP transform
+ *
+ * @param tid transform
+ * @return the authentication key length for the chosen transform.
+ * or negative on error
+ */
+int hip_auth_key_length_esp(int tid)
+{
+    int ret = -1;
+
+    switch (tid) {
+    case HIP_ESP_AES_SHA1:
+    case HIP_ESP_NULL_SHA1:
+    case HIP_ESP_3DES_SHA1:
+        ret = 20;
+        break;
+    case HIP_ESP_NULL_NULL:
+        ret = 0;
+        break;
+    default:
+        HIP_ERROR("unknown tid=%d\n", tid);
+        HIP_ASSERT(0);
+        break;
+    }
+
+    return ret;
+}
+

=== added file 'lib/core/keylen.h'
--- lib/core/keylen.h   1970-01-01 00:00:00 +0000
+++ lib/core/keylen.h   2010-03-19 09:53:35 +0000
@@ -0,0 +1,8 @@
+#ifndef HIP_LIB_CORE_KEYLEN_H
+#define HIP_LIB_CORE_KEYLEN_H
+
+int hip_auth_key_length_esp(int tid);
+int hip_hmac_key_length(int tid);
+int hip_enc_key_length(int tid);
+
+#endif /* HIP_LIB_CORE_KEYLEN_H */

=== modified file 'lib/core/message.c'
--- lib/core/message.c  2010-03-19 09:32:05 +0000
+++ lib/core/message.c  2010-03-19 09:53:35 +0000
@@ -67,7 +67,9 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <unistd.h>
 #include "message.h"
+#include "hip_udp.h"
 
 /**
  * Finds out how much data is coming from a socket
@@ -309,9 +311,6 @@
  * @return zero on success and negative on failure
  * @note currently the only SOCK_DGRAM and AF_INET6 are supported
  */
-/*
- * Don't call this function directly. Use hip_send_recv_daemon_info instead
- */
 static int hip_send_recv_daemon_info_internal(struct hip_common *msg, int 
opt_socket)
 {
     int hip_user_sock = 0, err = 0, n = 0, len = 0;

=== modified file 'lib/core/message.h'
--- lib/core/message.h  2010-03-03 13:16:18 +0000
+++ lib/core/message.h  2010-03-19 09:53:35 +0000
@@ -9,17 +9,10 @@
 #ifndef HIP_LIB_CORE_MESSAGE_H
 #define HIP_LIB_CORE_MESSAGE_H
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <errno.h>
 #include <netinet/in.h>
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/tool/nlink.h"
 #include "debug.h"
 #include "icomm.h"

=== modified file 'lib/core/prefix.c'
--- lib/core/prefix.c   2010-03-03 13:16:18 +0000
+++ lib/core/prefix.c   2010-03-19 09:53:35 +0000
@@ -15,6 +15,11 @@
 #define _BSD_SOURCE
 
 #include "prefix.h"
+#include "builder.h"
+
+/* Definitions */
+#define HIP_ID_TYPE_HIT     1
+#define HIP_ID_TYPE_LSI     2
 
 /**
  * Test if the given IPv6 address has HIT prefix (RFC4843 ORCHID prefix)
@@ -111,3 +116,289 @@
     lsi_begin |= htonl(HIP_LSI_PREFIX);
     memcpy(lsi, &lsi_begin, sizeof(hip_closest_prefix_type_t));
 }
+
+/**
+ * compare two LSIs for equality
+ *
+ * @param lsi1 an LSI
+ * @param lsi2 an LSI
+ * @return one if the LSIs are equal or zero otherwise
+ */
+int hip_lsi_are_equal(const hip_lsi_t *lsi1,
+                      const hip_lsi_t *lsi2)
+{
+    return ipv4_addr_cmp(lsi1, lsi2) == 0;
+}
+
+/**
+ * check the type of an IPv6 addresses
+ *
+ * @param id an IPv6 address, possibly in IPv6 mapped format
+ * @param type HIP_ID_TYPE_HIT or HIP_ID_TYPE_LSI
+ *
+ * @return zero for type match, greater than zero for mismatch or
+ * negative on error
+ */
+int hip_id_type_match(const struct in6_addr *id, int id_type)
+{
+    int ret = 0, is_lsi = 0, is_hit = 0;
+    hip_lsi_t lsi;
+
+    if (ipv6_addr_is_hit(id)) {
+        is_hit = 1;
+    } else if (IN6_IS_ADDR_V4MAPPED(id)) {
+        IPV6_TO_IPV4_MAP(id, &lsi);
+        if (IS_LSI32(lsi.s_addr)) {
+            is_lsi = 1;
+        }
+    }
+
+    HIP_ASSERT(!(is_lsi && is_hit));
+
+    if (id_type == HIP_ID_TYPE_HIT) {
+        ret = (is_hit ? 1 : 0);
+    } else if (id_type == HIP_ID_TYPE_LSI) {
+        ret = (is_lsi ? 1 : 0);
+    } else {
+        ret = ((is_hit || is_lsi) ? 0 : 1);
+    }
+
+    return ret;
+}
+
+#ifdef CONFIG_HIP_OPPORTUNISTIC
+/**
+ * Convert a given IP address into a pseudo HIT
+ *
+ * @param ip an IPv4 or IPv6 address address
+ * @param hit a pseudo HIT generated from the IP address
+ * @param hit_type the type of the HIT
+ * @return zero on success and non-zero on failure
+ * @see  <a
+ * href="http://hipl.hiit.fi/hipl/thesis_teresa_finez.pdf";>T. Finez,
+ * Backwards Compatibility Experimentation with Host Identity Protocol
+ * and Legacy Software and Networks , final project, December 2008</a>
+ *
+ */
+int hip_opportunistic_ipv6_to_hit(const struct in6_addr *ip,
+                                  struct in6_addr *hit,
+                                  int hit_type)
+{
+    int err              = 0;
+    uint8_t digest[HIP_AH_SHA_LEN];
+    char *key            = (char *) (ip);
+    unsigned int key_len = sizeof(struct in6_addr);
+
+    HIP_IFE(hit_type != HIP_HIT_TYPE_HASH100, -ENOSYS);
+    _HIP_HEXDUMP("key", key, key_len);
+    HIP_IFEL((err = hip_build_digest(HIP_DIGEST_SHA1, key, key_len, digest)),
+             err,
+             "Building of digest failed\n");
+
+    memcpy(hit, digest + (HIP_AH_SHA_LEN - sizeof(struct in6_addr)),
+           sizeof(struct in6_addr));
+
+    hit->s6_addr32[3] = 0; // this separates phit from normal hit
+
+    set_hit_prefix(hit);
+
+out_err:
+
+    return err;
+}
+
+#endif /* CONFIG_HIP_OPPORTUNISTIC */
+
+/**
+ * cast a socket address to an IPv4 or IPv6 address.
+ *
+ * @note The parameter @c sockaddr is first cast to a struct sockaddr
+ * and the IP address cast is then done based on the value of the
+ * sa_family field in the struct sockaddr. If sa_family is neither
+ * AF_INET nor AF_INET6, the cast fails.
+ *
+ * @param  sockaddr a pointer to a socket address that holds the IP address.
+ * @return          a pointer to an IPv4 or IPv6 address inside @c sockaddr or
+ *                  NULL if the cast fails.
+ */
+
+void *hip_cast_sa_addr(const struct sockaddr *sa)
+{
+    if (sa == NULL) {
+        HIP_ERROR("sockaddr is NULL, skipping type conversion\n");
+
+        return NULL;
+    }
+
+    switch (sa->sa_family) {
+    case AF_INET:
+        return &(((struct sockaddr_in *) sa)->sin_addr);
+    case AF_INET6:
+        return &(((struct sockaddr_in6 *) sa)->sin6_addr);
+    default:
+        HIP_ERROR("unhandled type: %i, skipping cast\n", sa->sa_family);
+        return NULL;
+    }
+}
+
+/**
+ * Test if a sockaddr_in6 structure is in IPv6 mapped format (i.e.
+ * contains an IPv4 address)
+ *
+ * @param sa socket address structure
+ * @return one if the structure is in IPv6 mapped format or zero otherwise
+ */
+int hip_sockaddr_is_v6_mapped(struct sockaddr *sa)
+{
+    int family = sa->sa_family;
+
+    HIP_ASSERT(family == AF_INET || family == AF_INET6);
+    if (family != AF_INET6) {
+        return 0;
+    } else {
+        return IN6_IS_ADDR_V4MAPPED((struct in6_addr *) hip_cast_sa_addr(sa));
+    }
+}
+
+/**
+ * Calculate the actual length of any sockaddr structure
+ *
+ * @param sockaddr the sockaddr structure
+ * @return the length of the actual sockaddr structure in bytes
+ */
+int hip_sockaddr_len(const void *sockaddr)
+{
+    struct sockaddr *sa = (struct sockaddr *) sockaddr;
+    int len;
+
+    switch (sa->sa_family) {
+    case AF_INET:
+        len = sizeof(struct sockaddr_in);
+        break;
+    case AF_INET6:
+        len = sizeof(struct sockaddr_in6);
+        break;
+    case AF_UNIX:
+        len = sizeof(struct sockaddr_un);
+        break;
+    default:
+        len = 0;
+    }
+    return len;
+}
+
+/**
+ * Calculate the address field length of any sockaddr structure
+ *
+ * @param sockaddr the sockaddr structure
+ * @return the length of the address field in the @c sockaddr structure
+ */
+int hip_sa_addr_len(void *sockaddr)
+{
+    struct sockaddr *sa = (struct sockaddr *) sockaddr;
+    int len;
+
+    switch (sa->sa_family) {
+    case AF_INET:
+        len = 4;
+        break;
+    case AF_INET6:
+        len = 16;
+        break;
+    default:
+        len = 0;
+    }
+    return len;
+}
+
+/**
+ * converts an in6_addr structure to sockaddr_storage
+ *
+ * @param addr the in6_addr to convert
+ * @param sa a sockaddr_storage structure where the result is stored
+ * @note remember to fill in the port number by yourself
+ *       if necessary
+ */
+void hip_addr_to_sockaddr(struct in6_addr *addr, struct sockaddr_storage *sa)
+{
+    memset(sa, 0, sizeof(struct sockaddr_storage));
+
+    if (IN6_IS_ADDR_V4MAPPED(addr)) {
+        struct sockaddr_in *in = (struct sockaddr_in *) sa;
+        in->sin_family = AF_INET;
+        IPV6_TO_IPV4_MAP(addr, &in->sin_addr);
+    } else {
+        struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) sa;
+        in6->sin6_family = AF_INET6;
+        ipv6_addr_copy(&in6->sin6_addr, addr);
+    }
+}
+
+/**
+ * verify if a given IPv6 address or IPv6 mapped IPv4 address
+ * is a loopback
+ *
+ * @param addr the address to verify
+ * @return one if the address if loopback or zero otherwise
+ */
+int hip_addr_is_loopback(struct in6_addr *addr)
+{
+    struct in_addr addr_in;
+
+    if (!IN6_IS_ADDR_V4MAPPED(addr)) {
+        return IN6_IS_ADDR_LOOPBACK(addr);
+    }
+    IPV6_TO_IPV4_MAP(addr, &addr_in);
+    return IS_IPV4_LOOPBACK(addr_in.s_addr);
+}
+
+int ipv4_addr_cmp(const struct in_addr *a1,
+                                const struct in_addr *a2) {
+    return memcmp((const char *) a1, (const char *) a2,
+                  sizeof(struct in_addr));
+}
+
+void ipv4_addr_copy(struct in_addr *a1,
+                                  const struct in_addr *a2) {
+    memcpy((char *) a1, (const char *) a2, sizeof(struct in_addr));
+}
+
+int ipv6_addr_cmp(const struct in6_addr *a1,
+                  const struct in6_addr *a2) {
+    return memcmp((const char *) a1, (const char *) a2,
+                  sizeof(struct in6_addr));
+}
+
+void ipv6_addr_copy(struct in6_addr *a1,
+               const struct in6_addr *a2) {
+    memcpy((char *) a1, (const char *) a2, sizeof(struct in6_addr));
+}
+
+int ipv6_addr_any(const struct in6_addr *a) {
+    return (a->s6_addr[0] | a->s6_addr[1] | a->s6_addr[2] | a->s6_addr[3] |
+            a->s6_addr[4] |a->s6_addr[5] |a->s6_addr[6] |a->s6_addr[7] |
+            a->s6_addr[8] |a->s6_addr[9] |a->s6_addr[10] |a->s6_addr[11] |
+            a->s6_addr[12] |a->s6_addr[13] |a->s6_addr[14] |a->s6_addr[15]) == 
0;
+}
+
+void hip_copy_in6addr_null_check(struct in6_addr *to,
+                                 struct in6_addr *from) {
+    HIP_ASSERT(to);
+    if (from) {
+        ipv6_addr_copy(to, from);
+    } else {
+        memset(to, 0, sizeof(*to));
+    }
+}
+
+void hip_copy_inaddr_null_check(struct in_addr *to,
+                                struct in_addr *from) {
+    HIP_ASSERT(to);
+    if (from) {
+        memcpy(to, from, sizeof(*to));
+    } else {
+        memset(to, 0, sizeof(*to));
+    }
+}
+
+

=== modified file 'lib/core/prefix.h'
--- lib/core/prefix.h   2010-03-03 13:16:18 +0000
+++ lib/core/prefix.h   2010-03-19 09:53:35 +0000
@@ -1,10 +1,6 @@
 #ifndef HIP_LIB_CORE_UTILS_H
 #define HIP_LIB_CORE_UTILS_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #ifdef __KERNEL__
 #  include <linux/un.h>
 #  include <linux/in6.h>
@@ -41,6 +37,31 @@
 int hit_is_opportunistic_hit(const struct in6_addr *hit);
 void set_hit_prefix(struct in6_addr *hit);
 void set_lsi_prefix(hip_lsi_t *lsi);
+int hip_id_type_match(const struct in6_addr *id, int id_type);
+int hip_opportunistic_ipv6_to_hit(const struct in6_addr *ip,
+                                  struct in6_addr *hit, int hit_type);
+void *hip_cast_sa_addr(const struct sockaddr *sa);
+int hip_sockaddr_len(const void *sockaddr);
+int hip_sa_addr_len(void *sockaddr);
+void hip_addr_to_sockaddr(struct in6_addr *addr, struct sockaddr_storage *sa);
+int hip_sockaddr_is_v6_mapped(struct sockaddr *sa);
+int hip_addr_is_loopback(struct in6_addr *addr);
+int hip_lsi_are_equal(const hip_lsi_t *lsi1,
+                      const hip_lsi_t *lsi2);
+
+int ipv4_addr_cmp(const struct in_addr *a1,
+                  const struct in_addr *a2);
+void ipv4_addr_copy(struct in_addr *a1,
+                    const struct in_addr *a2);
+int ipv6_addr_cmp(const struct in6_addr *a1,
+                  const struct in6_addr *a2);
+void ipv6_addr_copy(struct in6_addr *a1,
+                    const struct in6_addr *a2);
+int ipv6_addr_any(const struct in6_addr *a);
+void hip_copy_in6addr_null_check(struct in6_addr *to,
+                                 struct in6_addr *from);
+void hip_copy_inaddr_null_check(struct in_addr *to,
+                                struct in_addr *from);
 
 /* IN6_IS_ADDR_V4MAPPED(a) is defined in /usr/include/netinet/in.h */
 

=== modified file 'lib/core/protodefs.h'
--- lib/core/protodefs.h        2010-02-17 17:38:08 +0000
+++ lib/core/protodefs.h        2010-03-19 09:53:35 +0000
@@ -22,6 +22,8 @@
 #endif
 #endif
 
+#define IPV4_HDR_SIZE 20
+
 #define HIP_MAX_PACKET 4096
 #define HIP_MAX_NETWORK_PACKET 2048
 /** @addtogroup hip_msg

=== added file 'lib/core/solve.c'
--- lib/core/solve.c    1970-01-01 00:00:00 +0000
+++ lib/core/solve.c    2010-03-19 09:53:35 +0000
@@ -0,0 +1,177 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief HIP computation puzzle solving algorithms
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#include "solve.h"
+
+/**
+ * solve a computational puzzle for HIP
+ *
+ * @param puzzle_or_solution Either a pointer to hip_puzzle or hip_solution 
structure
+ * @param hdr The incoming R1/I2 packet header.
+ * @param mode Either HIP_VERIFY_PUZZLE of HIP_SOLVE_PUZZLE
+ *
+ * @note The K and I is read from the @c puzzle_or_solution.
+ * @note Regarding to return value of zero, I don't see why 0 couldn't solve 
the
+ *       puzzle too, but since the odds are 1/2^64 to try 0, I don't see the 
point
+ *       in improving this now.
+ * @return The J that solves the puzzle is returned, or 0 to indicate an error.
+ */
+uint64_t hip_solve_puzzle(void *puzzle_or_solution,
+                          struct hip_common *hdr,
+                          int mode)
+{
+    uint64_t mask     = 0;
+    uint64_t randval  = 0;
+    uint64_t maxtries = 0;
+    uint64_t digest   = 0;
+    uint8_t cookie[48];
+    int err           = 0;
+    union {
+        struct hip_puzzle   pz;
+        struct hip_solution sl;
+    } *u;
+
+    HIP_HEXDUMP("puzzle", puzzle_or_solution,
+                (mode == HIP_VERIFY_PUZZLE ? sizeof(struct hip_solution) :
+                                             sizeof(struct hip_puzzle)));
+
+    _HIP_DEBUG("\n");
+    /* pre-create cookie */
+    u = puzzle_or_solution;
+
+    _HIP_DEBUG("current hip_cookie_max_k_r1=%d\n", max_k);
+    HIP_IFEL(u->pz.K > HIP_PUZZLE_MAX_K, 0,
+             "Cookie K %u is higher than we are willing to calculate"
+             " (current max K=%d)\n", u->pz.K, HIP_PUZZLE_MAX_K);
+
+    mask = hton64((1ULL << u->pz.K) - 1);
+    memcpy(cookie, (uint8_t *) &(u->pz.I), sizeof(uint64_t));
+
+    HIP_DEBUG("(u->pz.I: 0x%llx\n", u->pz.I);
+
+    if (mode == HIP_VERIFY_PUZZLE) {
+        ipv6_addr_copy((hip_hit_t *) (cookie + 8), &hdr->hits);
+        ipv6_addr_copy((hip_hit_t *) (cookie + 24), &hdr->hitr);
+        //randval = ntoh64(u->sl.J);
+        randval  = u->sl.J;
+        _HIP_DEBUG("u->sl.J: 0x%llx\n", randval);
+        maxtries = 1;
+    } else if (mode == HIP_SOLVE_PUZZLE) {
+        ipv6_addr_copy((hip_hit_t *) (cookie + 8), &hdr->hitr);
+        ipv6_addr_copy((hip_hit_t *) (cookie + 24), &hdr->hits);
+        maxtries = 1ULL << (u->pz.K + 3);
+        get_random_bytes(&randval, sizeof(u_int64_t));
+    } else {
+        HIP_IFEL(1, 0, "Unknown mode: %d\n", mode);
+    }
+
+    HIP_DEBUG("K=%u, maxtries (with k+2)=%llu\n", u->pz.K, maxtries);
+    /* while loops should work even if the maxtries is unsigned
+     * if maxtries = 1 ---> while(1 > 0) [maxtries == 0 now]...
+     * the next round while (0 > 0) [maxtries > 0 now]
+     */
+    while (maxtries-- > 0) {
+        uint8_t sha_digest[HIP_AH_SHA_LEN];
+
+        /* must be 8 */
+        memcpy(cookie + 40, (uint8_t *) &randval, sizeof(uint64_t));
+
+        hip_build_digest(HIP_DIGEST_SHA1, cookie, 48, sha_digest);
+
+        /* copy the last 8 bytes for checking */
+        memcpy(&digest, sha_digest + 12, sizeof(uint64_t));
+
+        /* now, in order to be able to do correctly the bitwise
+         * AND-operation we have to remember that little endian
+         * processors will interpret the digest and mask reversely.
+         * digest is the last 64 bits of the sha1-digest.. how that is
+         * ordered in processors registers etc.. does not matter to us.
+         * If the last 64 bits of the sha1-digest is
+         * 0x12345678DEADBEEF, whether we have 0xEFBEADDE78563412
+         * doesn't matter because the mask matters... if the mask is
+         * 0x000000000000FFFF (or in other endianness
+         * 0xFFFF000000000000). Either ways... the result is
+         * 0x000000000000BEEF or 0xEFBE000000000000, which the cpu
+         * interprets as 0xBEEF. The mask is converted to network byte
+         * order (above).
+         */
+        if ((digest & mask) == 0) {
+            _HIP_DEBUG("*** Puzzle solved ***: 0x%llx\n", randval);
+            _HIP_HEXDUMP("digest", sha_digest, HIP_AH_SHA_LEN);
+            _HIP_HEXDUMP("cookie", cookie, sizeof(cookie));
+            return randval;
+        }
+
+        /* It seems like the puzzle was not correctly solved */
+        HIP_IFEL(mode == HIP_VERIFY_PUZZLE, 0, "Puzzle incorrect\n");
+        randval++;
+    }
+
+    HIP_ERROR("Could not solve the puzzle, no solution found\n");
+out_err:
+    return err;
+}
+
+#ifdef CONFIG_HIP_MIDAUTH
+/**
+ * solve a midauth puzzle which is essentially a normal HIP cookie
+ * with some extra whipped cream on the top
+ *
+ * @param out the received R1 message
+ * @param in an I2 message where the solution will be written
+ * @param entry the related host association
+ * @return zero on success and negative on error
+ * @see <a
+ * href="http://tools.ietf.org/id/draft-heer-hip-middle-auth";>Heer et
+ * al, End-Host Authentication for HIP Middleboxes, Internet draft,
+ * work in progress, February 2009</a>
+ */
+int hip_solve_puzzle_m(struct hip_common *out,
+                       struct hip_common *in,
+                       hip_ha_t *entry)
+{
+    struct hip_challenge_request *pz;
+    struct hip_puzzle tmp;
+    uint64_t solution;
+    int err = 0;
+    uint8_t digist[HIP_AH_SHA_LEN];
+
+
+    pz = hip_get_param(in, HIP_PARAM_CHALLENGE_REQUEST);
+    while (pz) {
+        if (hip_get_param_type(pz) != HIP_PARAM_CHALLENGE_REQUEST) {
+            break;
+        }
+
+        HIP_IFEL(hip_build_digest(HIP_DIGEST_SHA1, pz->opaque, 24, digist) < 0,
+                 -1, "Building of SHA1 Random seed I failed\n");
+        tmp.type      = pz->type;
+        tmp.length    = pz->length;
+        tmp.K         = pz->K;
+        tmp.lifetime  = pz->lifetime;
+        tmp.opaque[0] = tmp.opaque[1] = 0;
+        tmp.I         = *digist & 0x40; //truncate I to 8 byte length
+
+        HIP_IFEL((solution = entry->hadb_misc_func->hip_solve_puzzle(
+                      &tmp, in, HIP_SOLVE_PUZZLE)) == 0,
+                 -EINVAL, "Solving of puzzle failed\n");
+
+        HIP_IFEL(hip_build_param_challenge_response(out, pz, ntoh64(solution)) 
< 0,
+                 -1,
+                 "Error while creating solution_m reply parameter\n");
+        pz = (struct hip_challenge_request *) hip_get_next_param(in,
+                                                                 (struct 
hip_tlv_common *) pz);
+    }
+
+out_err:
+    return err;
+}
+#endif /* CONFIG_HIP_MIDAUTH */
+

=== added file 'lib/core/solve.h'
--- lib/core/solve.h    1970-01-01 00:00:00 +0000
+++ lib/core/solve.h    2010-03-19 09:53:35 +0000
@@ -0,0 +1,19 @@
+#ifndef HIP_LIB_CORE_SOLVE_H
+#define HIP_LIB_CORE_SOLVE_H
+
+#include <sys/types.h>
+
+#include "config.h"
+#include "lib/core/crypto.h"
+#include "protodefs.h"
+#include "state.h"
+
+
+#define HIP_PUZZLE_MAX_K        28
+
+uint64_t hip_solve_puzzle(void *puzzle, struct hip_common *hdr, int mode);
+int hip_solve_puzzle_m(struct hip_common *out,
+                       struct hip_common *in,
+                       hip_ha_t *entry);
+
+#endif /* HIP_LIB_CORE_SOLVE_H */

=== modified file 'lib/core/sqlitedbapi.c'
--- lib/core/sqlitedbapi.c      2010-02-17 17:38:08 +0000
+++ lib/core/sqlitedbapi.c      2010-03-19 09:53:35 +0000
@@ -5,10 +5,7 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #ifdef CONFIG_HIP_AGENT
 
 #include "sqlitedbapi.h"

=== modified file 'lib/core/sqlitedbapi.h'
--- lib/core/sqlitedbapi.h      2010-02-17 17:38:08 +0000
+++ lib/core/sqlitedbapi.h      2010-03-19 09:53:35 +0000
@@ -15,10 +15,8 @@
 
 #include <stdio.h>
 #include <sqlite3.h>
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
 
+#include "config.h"
 #include "debug.h"
 #include "ife.h"
 

=== modified file 'lib/core/state.h'
--- lib/core/state.h    2010-03-19 09:24:10 +0000
+++ lib/core/state.h    2010-03-19 09:53:35 +0000
@@ -7,15 +7,10 @@
 #ifndef HIP_LIB_CORE_STATE_H
 #define HIP_LIB_CORE_STATE_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #ifndef __KERNEL__
 #include "hashtable.h"
 #include "esp_prot_common.h"
 #include "hip_statistics.h"
-
 #endif
 
 #define HIP_ENDPOINT_FLAG_PUBKEY           0

=== added file 'lib/core/straddr.c'
--- lib/core/straddr.c  1970-01-01 00:00:00 +0000
+++ lib/core/straddr.c  2010-03-19 09:53:35 +0000
@@ -0,0 +1,177 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Conversion functions from string to address and vice versa
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+/* required for s6_addr32 */
+#define _BSD_SOURCE
+
+#include <errno.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <openssl/evp.h>
+#include "config.h"
+#include "straddr.h"
+#include "debug.h"
+
+/**
+ * convert a binary IPv6 address to a string
+ *
+ * @param in6 the IPv6 address to convert
+ * @param buf a preallocated buffer where the string will be stored
+ * @return a pointer to the buf
+ */
+char *hip_in6_ntop(const struct in6_addr *in6, char *buf)
+{
+    if (!buf) {
+        return NULL;
+    }
+    sprintf(buf,
+            "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+            ntohs(in6->s6_addr16[0]), ntohs(in6->s6_addr16[1]),
+            ntohs(in6->s6_addr16[2]), ntohs(in6->s6_addr16[3]),
+            ntohs(in6->s6_addr16[4]), ntohs(in6->s6_addr16[5]),
+            ntohs(in6->s6_addr16[6]), ntohs(in6->s6_addr16[7]));
+    return buf;
+}
+
+/**
+ * convert a string into a binary IPv4 address (a wrapper for inet_pton())
+ *
+ * @param str the string to convert
+ * @param ip an output argument that will contain a binary IPv4 calculated
+ *        from the @c str
+ * @return zero on success and negative on error
+ */
+int convert_string_to_address_v4(const char *str, struct in_addr *ip)
+{
+    int ret = 0, err = 0;
+
+    ret = inet_pton(AF_INET, str, ip);
+    HIP_IFEL((ret < 0 && errno == EAFNOSUPPORT), -1,
+             "inet_pton: not a valid address family\n");
+    HIP_IFEL((ret == 0), -1,
+             "inet_pton: %s: not a valid network address\n", str);
+out_err:
+    return err;
+}
+
+/**
+ * Convert a string to an IPv6 address. This function can handle
+ * also IPv6 mapped addresses.
+ *
+ * @param str the string to convert
+ * @param ip6 An output argument that will contain a binary IPv4 calculated
+ *        from the @c str. Possibly in IPv6 mapped format.
+ * @return zero on success or negative on error
+ */
+int convert_string_to_address(const char *str,
+                              struct in6_addr *ip6)
+{
+    int ret = 0, err = 0;
+    struct in_addr ip4;
+
+    ret = inet_pton(AF_INET6, str, ip6);
+    HIP_IFEL((ret < 0 && errno == EAFNOSUPPORT), -1,
+             "\"%s\" is not of valid address family.\n", str);
+    if (ret > 0) {
+        /* IPv6 address conversion was ok */
+        _HIP_DEBUG_IN6ADDR("Converted IPv6", ip6);
+        goto out_err;
+    }
+
+    /* Might be an ipv4 address (ret == 0). Lets catch it here. */
+    err = convert_string_to_address_v4(str, &ip4);
+    if (err) {
+        goto out_err;
+    }
+
+    IPV4_TO_IPV6_MAP(&ip4, ip6);
+    HIP_DEBUG("Mapped v4 to v6.\n");
+    HIP_DEBUG_IN6ADDR("mapped v6", ip6);
+
+out_err:
+    return err;
+}
+
+/**
+ * convert a string containing upper case characters to lower case
+ *
+ * @param to the result of the conversion (minimum length @c count)
+ * @param from a string possibly containing upper case characters
+ * @return zero on success or negative on failure
+ */
+int hip_string_to_lowercase(char *to, const char *from, const size_t count)
+{
+    if (to == NULL || from == NULL || count == 0) {
+        return -1;
+    }
+
+    int i = 0;
+
+    for (; i < count; i++) {
+        if (isalpha(from[i])) {
+            to[i] = tolower(from[i]);
+        } else {
+            to[i] = from[i];
+        }
+    }
+    return 0;
+}
+
+/**
+ * test if a given string contains a positive integer
+ *
+ * @param string the string to test
+ * @return zero if the string is digit or negative otherwise
+ */
+int hip_string_is_digit(const char *string)
+{
+    if (string == NULL) {
+        return -1;
+    }
+
+    int i = 0;
+
+    while (string[i] != '\0') {
+        if (!isdigit(string[i])) {
+            return -1;
+        }
+        i++;
+    }
+    return 0;
+}
+
+
+/**
+ * encode the given content to Base64
+ *
+ * @param buf Pointer to contents to be encoded
+ * @param len How long is the first parameter in bytes
+ *
+ * @return Returns a pointer to encoded content or NULL on error
+ */
+unsigned char *base64_encode(unsigned char *buf, unsigned int len)
+{
+    unsigned char *ret;
+    unsigned int b64_len;
+
+    b64_len = (((len + 2) / 3) * 4) + 1;
+    ret     = (unsigned char *) malloc(b64_len);
+    if (ret == NULL) {
+        goto out_err;
+    }
+    EVP_EncodeBlock(ret, buf, len);
+    return ret;
+out_err:
+    if (ret) {
+        free(ret);
+    }
+    return NULL;
+}
+

=== added file 'lib/core/straddr.h'
--- lib/core/straddr.h  1970-01-01 00:00:00 +0000
+++ lib/core/straddr.h  2010-03-19 09:53:35 +0000
@@ -0,0 +1,14 @@
+#ifndef HIP_LIB_CORE_STRADDR_H
+#define HIP_LIB_CORE_STRADDR_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+int convert_string_to_address_v4(const char *str, struct in_addr *ip);
+int convert_string_to_address(const char *str, struct in6_addr *ip6);
+char *hip_in6_ntop(const struct in6_addr *in6, char *buf);
+int hip_string_to_lowercase(char *to, const char *from, const size_t count);
+int hip_string_is_digit(const char *string);
+unsigned char *base64_encode(unsigned char *, unsigned int);
+
+#endif /* HIP_LIB_CORE_STRADDR_H */

=== added file 'lib/core/transform.c'
--- lib/core/transform.c        1970-01-01 00:00:00 +0000
+++ lib/core/transform.c        2010-03-19 09:53:35 +0000
@@ -0,0 +1,148 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Transform related functions for HIP
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ */
+
+#include "debug.h"
+#include "builder.h"
+#include "transform.h"
+
+/**
+ * select a HIP transform
+ *
+ * @param ht HIP_TRANSFORM payload where the transform is selected from
+ * @return the first acceptable Transform-ID or negative if no
+ * acceptable transform was found. The return value is in host byte order.
+ */
+hip_transform_suite_t hip_select_hip_transform(struct hip_hip_transform *ht)
+{
+    hip_transform_suite_t tid = 0;
+    int i;
+    int length;
+    hip_transform_suite_t *suggestion;
+
+    length     = ntohs(ht->length);
+    suggestion = (hip_transform_suite_t *) &ht->suite_id[0];
+
+    if ((length >> 1) > 6) {
+        HIP_ERROR("Too many transforms (%d)\n", length >> 1);
+        goto out;
+    }
+
+    for (i = 0; i < length; i++) {
+        switch (ntohs(*suggestion)) {
+        case HIP_HIP_AES_SHA1:
+        case HIP_HIP_3DES_SHA1:
+        case HIP_HIP_NULL_SHA1:
+            tid = ntohs(*suggestion);
+            goto out;
+            break;
+
+        default:
+            /* Specs don't say what to do when unknown are found.
+             * We ignore.
+             */
+            HIP_ERROR("Unknown HIP suite id suggestion (%u)\n",
+                      ntohs(*suggestion));
+            break;
+        }
+        suggestion++;
+    }
+
+out:
+    if (tid == 0) {
+        HIP_ERROR("None HIP transforms accepted\n");
+    } else {
+        HIP_DEBUG("Chose HIP transform: %d\n", tid);
+    }
+
+    return tid;
+}
+
+/**
+ * select an ESP transform to use
+ * @param ht ESP_TRANSFORM payload where the transform is selected from
+ *
+ * @return the first acceptable Suite-ID or negative if no
+ * acceptable Suite-ID was found.
+ */
+hip_transform_suite_t hip_select_esp_transform(struct hip_esp_transform *ht)
+{
+    hip_transform_suite_t tid = 0;
+    int i;
+    int length;
+    hip_transform_suite_t *suggestion;
+
+    length     = hip_get_param_contents_len(ht);
+    suggestion = (uint16_t *) &ht->suite_id[0];
+
+    if (length > sizeof(struct hip_esp_transform) -
+        sizeof(struct hip_common)) {
+        HIP_ERROR("Too many transforms\n");
+        goto out;
+    }
+
+    for (i = 0; i < length; i++) {
+        switch (ntohs(*suggestion)) {
+        case HIP_ESP_AES_SHA1:
+        case HIP_ESP_NULL_NULL:
+        case HIP_ESP_3DES_SHA1:
+        case HIP_ESP_NULL_SHA1:
+            tid = ntohs(*suggestion);
+            goto out;
+            break;
+        default:
+            /* Specs don't say what to do when unknowns are found.
+             * We ignore.
+             */
+            HIP_ERROR("Unknown ESP suite id suggestion (%u)\n",
+                      ntohs(*suggestion));
+            break;
+        }
+        suggestion++;
+    }
+
+out:
+    HIP_DEBUG("Took ESP transform %d\n", tid);
+
+    if (tid == 0) {
+        HIP_ERROR("Faulty ESP transform\n");
+    }
+
+    return tid;
+}
+
+/**
+ * get transform key length for a transform
+ * @param tid transform
+ *
+ * @return the transform key length based for the chosen transform,
+ * or negative on error.
+ */
+int hip_transform_key_length(int tid)
+{
+    int ret = -1;
+
+    switch (tid) {
+    case HIP_HIP_AES_SHA1:
+        ret = 16;
+        break;
+    case HIP_HIP_3DES_SHA1:
+        ret = 24;
+        break;
+    case HIP_HIP_NULL_SHA1:     // XX FIXME: SHOULD BE NULL_SHA1?
+        ret = 0;
+        break;
+    default:
+        HIP_ERROR("unknown tid=%d\n", tid);
+        HIP_ASSERT(0);
+        break;
+    }
+
+    return ret;
+}

=== added file 'lib/core/transform.h'
--- lib/core/transform.h        1970-01-01 00:00:00 +0000
+++ lib/core/transform.h        2010-03-19 09:53:35 +0000
@@ -0,0 +1,11 @@
+#ifndef HIP_LIB_CORE_TRANSFORM_H
+#define HIP_LIB_CORE_TRANSFORM_H
+
+#include "config.h"
+#include "protodefs.h"
+
+hip_transform_suite_t hip_select_esp_transform(struct hip_esp_transform *ht);
+hip_transform_suite_t hip_select_hip_transform(struct hip_hip_transform *ht);
+int hip_transform_key_length(int tid);
+
+#endif /* HIP_LIB_CORE_TRANSFORM_H */

=== modified file 'lib/dht/libhipdht.c'
--- lib/dht/libhipdht.c 2010-03-03 13:16:18 +0000
+++ lib/dht/libhipdht.c 2010-03-19 09:53:35 +0000
@@ -18,6 +18,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include <netdb.h>
+#include <unistd.h>
+#include <ctype.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
@@ -31,7 +33,10 @@
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
 #include "lib/core/icomm.h"
-#include "lib/core/misc.h"
+#include "lib/core/builder.h"
+#include "lib/core/straddr.h"
+#include "lib/core/message.h"
+
 #include "libhipdht.h"
 #include "libhipdhtxml.h"
 

=== modified file 'lib/dht/libhipdht.h'
--- lib/dht/libhipdht.h 2010-02-17 17:38:08 +0000
+++ lib/dht/libhipdht.h 2010-03-19 09:53:35 +0000
@@ -1,11 +1,11 @@
 #ifndef HIP_LIB_DHT_LIBHIPDHT_H
 #define HIP_LIB_DHT_LIBHIPDHT_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include "config.h"
 #include "lib/core/protodefs.h"
 
 /* Resolve the gateway address using opendht.nyuld.net */

=== modified file 'lib/dht/libhipdhtxml.c'
--- lib/dht/libhipdhtxml.c      2010-02-17 17:38:08 +0000
+++ lib/dht/libhipdhtxml.c      2010-03-19 09:53:35 +0000
@@ -8,6 +8,7 @@
 #include <libxml2/libxml/tree.h>
 #include "libhipdhtxml.h"
 #include "lib/core/debug.h"
+#include "lib/core/straddr.h"
 #include "hipd/netdev.h"
 
 xmlNodePtr xml_new_param(xmlNodePtr node_parent, char *type, char *value);

=== modified file 'lib/ipsec/ipsec_strerror.c'
--- lib/ipsec/ipsec_strerror.c  2010-03-03 13:16:18 +0000
+++ lib/ipsec/ipsec_strerror.c  2010-03-19 09:53:35 +0000
@@ -31,16 +31,13 @@
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <sys/types.h>
 #include <sys/param.h>
-
 #include <string.h>
 #include <inttypes.h>
 #include <linux/ipsec.h>
+
+#include "config.h"
 #include "ipsec_strerror.h"
 
 int __ipsec_errcode;

=== modified file 'lib/ipsec/pfkey.c'
--- lib/ipsec/pfkey.c   2010-03-03 13:16:18 +0000
+++ lib/ipsec/pfkey.c   2010-03-19 09:53:35 +0000
@@ -34,10 +34,6 @@
 /* required for caddr_t */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -51,9 +47,10 @@
 #include <errno.h>
 #include <stdio.h>
 
+#include "config.h"
 #include "ipsec_strerror.h"
 #include "libpfkey.h"
-#include "libinet6/include/net/pfkeyv2.h"
+#include "pfkeyv2.h"
 
 #define CALLOC(size, cast) (cast) calloc(1, (size))
 

=== added file 'lib/ipsec/pfkeyv2.h'
--- lib/ipsec/pfkeyv2.h 1970-01-01 00:00:00 +0000
+++ lib/ipsec/pfkeyv2.h 2010-03-19 09:53:35 +0000
@@ -0,0 +1,71 @@
+/*    $NetBSD: pfkeyv2.h,v 1.4 2006/09/09 16:22:08 manu Exp $    */
+
+#ifndef __NET_PFKEYV2_H_
+#define __NET_PFKEYV2_H_ 1
+
+#include <stdint.h>
+#include <linux/pfkeyv2.h>
+
+/* Private allocations for authentication algorithms */
+#define SADB_AALG_SHA2_256        SADB_X_AALG_SHA2_256HMAC
+#define SADB_X_AALG_SHA2_256        SADB_X_AALG_SHA2_256HMAC
+#define SADB_AALG_SHA2_384        SADB_X_AALG_SHA2_384HMAC
+#define SADB_X_AALG_SHA2_384        SADB_X_AALG_SHA2_384HMAC
+#define SADB_AALG_SHA2_512        SADB_X_AALG_SHA2_512HMAC
+#define SADB_X_AALG_SHA2_512        SADB_X_AALG_SHA2_512HMAC
+#define SADB_AALG_RIPEMD160HMAC        SADB_X_AALG_RIPEMD160HMAC
+#define SADB_X_AALG_MD5              249
+#define SADB_X_AALG_SHA              250
+
+/* private allocations - based on RFC2407/IANA assignment */
+#define SADB_X_EALG_CAST128CBC    5    /* SADB_X_EALG_CASTCBC? == 6 */
+#define SADB_X_EALG_RIJNDAELCBC        SADB_X_EALG_AESCBC
+#define SADB_X_EALG_AES            SADB_X_EALG_AESCBC
+
+
+#define SADB_X_CALG_NONE    0
+#define SADB_X_CALG_OUI        1
+#define SADB_X_CALG_DEFLATE    2
+#define SADB_X_CALG_LZS        3
+#define SADB_X_CALG_MAX        4
+
+
+#define SADB_X_EXT_NONE        0x0000    /* i.e. new format. */
+#define SADB_X_EXT_OLD        0x0001    /* old format. */
+
+#define SADB_X_EXT_IV4B        0x0010    /* IV length of 4 bytes in use */
+#define SADB_X_EXT_DERIV    0x0020    /* DES derived */
+#define SADB_X_EXT_CYCSEQ    0x0040    /* allowing to cyclic sequence. */
+
+    /* three of followings are exclusive flags each them */
+#define SADB_X_EXT_PSEQ        0x0000    /* sequencial padding for ESP */
+#define SADB_X_EXT_PRAND    0x0100    /* random padding for ESP */
+#define SADB_X_EXT_PZERO    0x0200    /* zero padding for ESP */
+#define SADB_X_EXT_PMASK    0x0300    /* mask for padding flag */
+
+#define SADB_X_EXT_RAWCPI    0x0080    /* use well known CPI (IPComp) */
+
+
+#define PFKEY_SOFT_LIFETIME_RATE    80
+
+#define SADB_X_LIFETIME_ALLOCATIONS    0
+#define SADB_X_LIFETIME_BYTES        1
+#define SADB_X_LIFETIME_ADDTIME        2
+#define SADB_X_LIFETIME_USETIME        3
+
+
+#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1)))
+#define    PFKEY_EXTLEN(msg) \
+    PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len)
+#define PFKEY_ADDR_PREFIX(ext) \
+    (((struct sadb_address *)(ext))->sadb_address_prefixlen)
+#define PFKEY_ADDR_PROTO(ext) \
+    (((struct sadb_address *)(ext))->sadb_address_proto)
+#define PFKEY_ADDR_SADDR(ext) \
+    ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address)))
+
+/* in 64bits */
+#define    PFKEY_UNUNIT64(a)    ((a) << 3)
+#define    PFKEY_UNIT64(a)        ((a) >> 3)
+
+#endif

=== modified file 'lib/ipsec/policy_parse.c'
--- lib/ipsec/policy_parse.c    2010-03-03 13:16:18 +0000
+++ lib/ipsec/policy_parse.c    2010-03-19 09:53:35 +0000
@@ -44,10 +44,6 @@
 #define YYPREFIX "__libipsec"
 #line 64 "policy_parse.y"
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -62,6 +58,7 @@
 
 #include <errno.h>
 
+#include "config.h"
 #include "ipsec_strerror.h"
 #include "libpfkey.h"
 

=== modified file 'lib/ipsec/policy_parse.y'
--- lib/ipsec/policy_parse.y    2010-03-03 13:16:18 +0000
+++ lib/ipsec/policy_parse.y    2010-03-19 09:53:35 +0000
@@ -64,10 +64,6 @@
 
 %{
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>
@@ -82,11 +78,10 @@
 
 #include <errno.h>
 
-//#include "config.h"
-
+#include "config.h"
 #include "ipsec_strerror.h"
 #include "libpfkey.h"
-#include "libinet6/include/net/pfkeyv2.h"
+#include "pfkeyv2.h"
 
 #ifndef INT32_MAX
 #define INT32_MAX       (0xffffffff)

=== modified file 'lib/ipsec/policy_token.l'
--- lib/ipsec/policy_token.l    2010-03-03 13:16:18 +0000
+++ lib/ipsec/policy_token.l    2010-03-19 09:53:35 +0000
@@ -32,12 +32,10 @@
  */
 
 %{
+#include "config.h"
+
 #ifdef CONFIG_HIP_PFKEY
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/socket.h>

=== modified file 'lib/opphip/wrap.c'
--- lib/opphip/wrap.c   2010-02-17 17:38:08 +0000
+++ lib/opphip/wrap.c   2010-03-19 09:53:35 +0000
@@ -15,10 +15,6 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #include <sys/types.h>
 #include <unistd.h>
 #include <errno.h>
@@ -27,7 +23,9 @@
 #include <pthread.h>
 #include <poll.h>
 
+#include "config.h"
 #include "lib/core/debug.h"
+#include "lib/core/message.h"
 #include "hipd/hadb.h"
 #include "lib/core/hashtable.h"
 #include "lib/tool/lutil.h"

=== modified file 'lib/opphip/wrap_db.c'
--- lib/opphip/wrap_db.c        2010-02-17 17:38:08 +0000
+++ lib/opphip/wrap_db.c        2010-03-19 09:53:35 +0000
@@ -11,10 +11,6 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #include <sys/types.h>
 #include <unistd.h>
 #include <errno.h>
@@ -22,6 +18,7 @@
 #include <sys/socket.h>
 #include <pthread.h>
 
+#include "config.h"
 #include "lib/core/hashtable.h"
 #include "hipd/hadb.h"
 #include "wrap_db.h"

=== modified file 'lib/performance/performance.c'
--- lib/performance/performance.c       2010-03-19 09:32:05 +0000
+++ lib/performance/performance.c       2010-03-19 09:53:35 +0000
@@ -4,7 +4,8 @@
  * \brief Primitive performance measurement library.
  * \author Tobias Heer
  *
- * This file provides a set of functions to mneasure execution time.
+ * This file provides a set of functions to measure execution time.
+ * The measurement unit is second.
  *
  * \note Distributed under
  * <a href="http://www.gnu.org/licenses/gpl.txt";>GNU/GPL</a>.
@@ -17,12 +18,6 @@
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
 
-int hip_perf_enabled()
-{
-    printf("PERF ENABLED");
-    return 1;
-}
-
 /*!
  * \brief Create a set of performance slots. Each performance measurement type
  * needs a slot.

=== added file 'lib/tool/checksum.c'
--- lib/tool/checksum.c 1970-01-01 00:00:00 +0000
+++ lib/tool/checksum.c 2010-03-19 09:53:35 +0000
@@ -0,0 +1,332 @@
+/**
+ * @file
+ *
+ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
+ *
+ * @brief Checksum functions
+ *
+ * @author Miika Komu <miika@xxxxxx>
+ * @note check if some of the checksum algos are redundant
+ */
+
+/* required for s6_addr */
+#define _BSD_SOURCE
+
+#include <netinet/ip.h>
+#include <sys/types.h>
+#include <string.h>
+#include "config.h"
+#include "checksum.h"
+#include "lib/core/debug.h"
+
+struct pseudo_header {
+    unsigned char src_addr[4];
+    unsigned char dst_addr[4];
+    uint8_t            zero;
+    uint8_t            protocol;
+    uint16_t           packet_length;
+};
+typedef struct pseudo_v6 {
+    struct  in6_addr src;
+    struct in6_addr  dst;
+    uint16_t         length;
+    uint16_t         zero1;
+    uint8_t          zero2;
+    uint8_t          next;
+} pseudo_v6;
+
+/** @todo this is redundant with pseudo_v6 */
+struct pseudo_header6 {
+    unsigned char src_addr[16];
+    unsigned char dst_addr[16];
+    uint32_t           packet_length;
+    unsigned char zero[3];
+    uint8_t            next_hdr;
+};
+
+/**
+ * Generate the IPv4 header checksum
+ *
+ * @param s     source address
+ * @param d     destination address
+ * @param c     data
+ * @return the calculated IPv4 header checksum
+ */
+uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t 
len)
+{
+    uint8_t *src   = s;
+    uint8_t *dst   = d;
+    uint8_t *data  = c;
+    uint16_t word16;
+    uint32_t sum;
+    uint16_t i;
+
+    /* initialize sum to zero */
+    sum = 0;
+
+    /* make 16 bit words out of every two adjacent 8 bit words and */
+    /* calculate the sum of all 16 vit words */
+    for (i = 0; i < len; i = i + 2) {
+        word16 = ((((uint16_t) (data[i] << 8))) & 0xFF00) + (((uint16_t) 
data[i + 1]) & 0xFF);
+        sum    = sum + (unsigned long) word16;
+    }
+    /* add the TCP pseudo header which contains:
+       the IP source and destination addresses, */
+    for (i = 0; i < 4; i = i + 2) {
+        word16 = ((src[i] << 8) & 0xFF00) + (src[i + 1] & 0xFF);
+        sum    = sum + word16;
+    }
+    for (i = 0; i < 4; i = i + 2) {
+        word16 = ((dst[i] << 8) & 0xFF00) + (dst[i + 1] & 0xFF);
+        sum    = sum + word16;
+    }
+    /* the protocol number and the length of the TCP packet */
+    sum = sum + protocol + len;
+
+    /* keep only the last 16 bits of the 32 bit calculated sum
+       and add the carries */
+    while (sum >> 16) {
+        sum = (sum & 0xFFFF) + (sum >> 16);
+    }
+
+    /* Take the one's complement of sum */
+    sum = ~sum;
+    return htons((unsigned short) sum);
+}
+
+/**
+ * calculate IPv6 checksum
+ *
+ * @param protocol the protocol
+ * @param src source address
+ * @param dst destination address
+ * @param data the data to checksum
+ * @param len the length of the data
+ * @return the calculated checksum
+ */
+uint16_t ipv6_checksum(uint8_t protocol,
+                       struct in6_addr *src,
+                       struct in6_addr *dst,
+                       void *data, uint16_t len)
+{
+    uint32_t chksum = 0;
+    pseudo_v6 pseudo;
+    memset(&pseudo, 0, sizeof(pseudo_v6));
+
+    pseudo.src    = *src;
+    pseudo.dst    = *dst;
+    pseudo.length = htons(len);
+    pseudo.next   = protocol;
+
+    chksum        = inchksum(&pseudo, sizeof(pseudo_v6));
+    chksum       += inchksum(data, len);
+
+    chksum        = (chksum >> 16) + (chksum & 0xffff);
+    chksum       += (chksum >> 16);
+
+    chksum        = (uint16_t) (~chksum);
+    if (chksum == 0) {
+        chksum = 0xffff;
+    }
+
+    return chksum;
+}
+
+/** calculate an IP checksum
+ *
+ * @param ip_hdr    packet to be checksumed
+ * @param ip_hl     header length field inside the header
+ * @return          the IP checksum
+ * @note taken from  RFC 1071 section 4.1
+ */
+uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl)
+{
+    uint16_t checksum = 0;
+    unsigned long sum = 0;
+    int count         = ip_hl * 4;
+    unsigned short *p = (unsigned short *) ip_hdr;
+
+    /*
+     * this checksum algorithm can be found
+     * in RFC 1071 section 4.1
+     */
+
+    /* one's complement sum 16-bit words of data */
+    while (count > 1) {
+        sum   += *p++;
+        count -= 2;
+    }
+    /* add left-over byte, if any */
+    if (count > 0) {
+        sum += (unsigned char) *p;
+    }
+
+    /*  Fold 32-bit sum to 16 bits */
+    while (sum >> 16) {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+    /* take the one's complement of the sum */
+    checksum = (uint16_t) (~sum);
+
+    return checksum;
+}
+
+/**
+ * yet another checksummer
+ *
+ * @param data the data to checksum
+ * @param length the length of the data
+ * @return the calculated checksum
+ */
+uint16_t inchksum(const void *data, uint32_t length)
+{
+    long sum            = 0;
+    const uint16_t *wrd =  (uint16_t *) data;
+    long slen           = (long) length;
+
+    while (slen > 1) {
+        sum  += *wrd++;
+        slen -= 2;
+    }
+
+    if (slen > 0) {
+        sum += *((uint8_t *) wrd);
+    }
+
+    while (sum >> 16) {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+
+    return (uint16_t) sum;
+}
+
+/**
+ * Standard BSD internet checksum routine from nmap
+ * for calculating the checksum field of the TCP header.
+ *
+ * @param ptr the data to checksum
+ * @param nbytes the length of data
+ * @return the checksum
+ *
+ * @note borrowed from Steven's network programming manual
+ */
+unsigned short in_cksum(uint16_t *ptr, int nbytes)
+{
+    register uint32_t sum;
+    uint16_t oddbyte;
+    register uint16_t answer;
+
+    /*
+     * Our algorithm is simple, using a 32-bit accumulator (sum),
+     * we add sequential 16-bit words to it, and at the end, fold back
+     * all the carry bits from the top 16 bits into the lower 16 bits.
+     */
+    sum = 0;
+    while (nbytes > 1) {
+        sum    += *ptr++;
+        nbytes -= 2;
+    }
+
+    /* mop up an odd byte, if necessary */
+    if (nbytes == 1) {
+        oddbyte                = 0;     /* make sure top half is zero */
+        *((u_char *) &oddbyte) = *(u_char *) ptr;          /* one byte only */
+        sum                   += oddbyte;
+    }
+
+    /*
+     * Add back carry outs from top 16 bits to low 16 bits.
+     */
+    sum    = (sum >> 16) + (sum & 0xffff);      /* add high-16 to low-16 */
+    sum   += (sum >> 16);                       /* add carry */
+    answer = ~sum;              /* ones-complement, then truncate to 16 bits */
+    return answer;
+}
+
+/**
+ * Calculates the checksum of a HIP packet with pseudo-header.
+ *
+ * @param data a pointer to a hip_common structure
+ * @param src  The source address of the packet as a sockaddr_in or 
sockaddr_in6
+ *             structure in network byte order. IPv6 mapped addresses are not 
supported.
+ * @param dst  The destination address of the packet as a sockaddr_in or 
sockaddr_in6
+ *             structure in network byte order. IPv6 mapped addresses are not 
supported.
+ * @return     the checksum
+ * @note       Checksumming is from Boeing's HIPD.
+ */
+uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst)
+{
+    uint16_t checksum      = 0;
+    unsigned long sum = 0;
+    int count         = 0, length = 0;
+    unsigned short *p = NULL;     /* 16-bit */
+    struct pseudo_header pseudoh;
+    struct pseudo_header6 pseudoh6;
+    uint32_t src_network, dst_network;
+    struct in6_addr *src6, *dst6;
+    struct hip_common *hiph = (struct hip_common *) data;
+
+    if (src->sa_family == AF_INET) {
+        /* IPv4 checksum based on UDP-- Section 6.1.2 */
+        src_network = ((struct sockaddr_in *) src)->sin_addr.s_addr;
+        dst_network = ((struct sockaddr_in *) dst)->sin_addr.s_addr;
+
+        memset(&pseudoh, 0, sizeof(struct pseudo_header));
+        memcpy(&pseudoh.src_addr, &src_network, 4);
+        memcpy(&pseudoh.dst_addr, &dst_network, 4);
+        pseudoh.protocol      = IPPROTO_HIP;
+        length                = (hiph->payload_len + 1) * 8;
+        pseudoh.packet_length = htons(length);
+
+        count                 = sizeof(struct pseudo_header); /* count always 
even number */
+        p                     = (unsigned short *) &pseudoh;
+    } else {
+        /* IPv6 checksum based on IPv6 pseudo-header */
+        src6 = &((struct sockaddr_in6 *) src)->sin6_addr;
+        dst6 = &((struct sockaddr_in6 *) dst)->sin6_addr;
+
+        memset(&pseudoh6, 0, sizeof(struct pseudo_header6));
+        memcpy(&pseudoh6.src_addr[0], src6, 16);
+        memcpy(&pseudoh6.dst_addr[0], dst6, 16);
+        length                 = (hiph->payload_len + 1) * 8;
+        pseudoh6.packet_length = htonl(length);
+        pseudoh6.next_hdr      = IPPROTO_HIP;
+
+        count                  = sizeof(struct pseudo_header6); /* count 
always even number */
+        p                      = (unsigned short *) &pseudoh6;
+    }
+    /*
+     * this checksum algorithm can be found
+     * in RFC 1071 section 4.1
+     */
+
+    /* sum the pseudo-header */
+    /* count and p are initialized above per protocol */
+    while (count > 1) {
+        sum   += *p++;
+        count -= 2;
+    }
+
+    /* one's complement sum 16-bit words of data */
+    HIP_DEBUG("Checksumming %d bytes of data.\n", length);
+    count = length;
+    p     = (unsigned short *) data;
+    while (count > 1) {
+        sum   += *p++;
+        count -= 2;
+    }
+    /* add left-over byte, if any */
+    if (count > 0) {
+        sum += (unsigned char) *p;
+    }
+
+    /*  Fold 32-bit sum to 16 bits */
+    while (sum >> 16) {
+        sum = (sum & 0xffff) + (sum >> 16);
+    }
+    /* take the one's complement of the sum */
+    checksum = ~sum;
+
+    return checksum;
+}
+

=== added file 'lib/tool/checksum.h'
--- lib/tool/checksum.h 1970-01-01 00:00:00 +0000
+++ lib/tool/checksum.h 2010-03-19 09:53:35 +0000
@@ -0,0 +1,18 @@
+#ifndef HIP_LIB_CORE_CHECKSUM_H
+#define HIP_LIB_CORE_CHECKSUM_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include "lib/core/protodefs.h"
+
+uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t 
len);
+uint16_t ipv6_checksum(uint8_t protocol,
+                       struct in6_addr *src,
+                       struct in6_addr *dst,
+                       void *data, uint16_t len);
+uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl);
+unsigned short in_cksum(uint16_t *ptr, int nbytes);
+uint16_t inchksum(const void *data, uint32_t length);
+uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr 
*dst);
+
+#endif /* HIP_LIB_CORE_CHECKSUM_H */

=== modified file 'lib/tool/lutil.c'
--- lib/tool/lutil.c    2010-02-17 17:38:08 +0000
+++ lib/tool/lutil.c    2010-03-19 09:53:35 +0000
@@ -4,7 +4,8 @@
  * Distributed under
  * <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>
  *
- * @brief String-related and linked list utilities borrowed from libinet6.
+ * @brief Utilities borrowed from libinet6. Function hip_timeval_diff()
+ * is borrowed from glibc project.
  */
 
 /* required for s6_addr32 */
@@ -224,3 +225,66 @@
     }
     return NULL;
 }
+
+/**
+ * calculate difference between two timevalues
+ *
+ * @param t1 timevalue 1
+ * @param t2 timevalue 2
+ * @param result where the result is stored
+ *
+ * ** CHECK comments **
+ * result = t1 - t2
+ *
+ * Code taken from 
http://www.gnu.org/manual/glibc-2.2.5/html_node/Elapsed-Time.html
+ *
+ * @return 1 if t1 is equal or later than t2, else 0.
+ */
+int hip_timeval_diff(const struct timeval *t1,
+                     const struct timeval *t2,
+                     struct timeval *result)
+{
+    struct timeval _t1, _t2;
+    _t1 = *t1;
+    _t2 = *t2;
+
+    if (_t1.tv_usec < _t2.tv_usec) {
+        int nsec = (_t2.tv_usec - _t1.tv_usec) / 1000000 + 1;
+        _t2.tv_usec -= 1000000 * nsec;
+        _t2.tv_sec  += nsec;
+    }
+    if (_t1.tv_usec - _t2.tv_usec > 1000000) {
+        int nsec = (_t1.tv_usec - _t2.tv_usec) / 1000000;
+        _t2.tv_usec += 1000000 * nsec;
+        _t2.tv_sec  -= nsec;
+    }
+
+    result->tv_sec  = _t2.tv_sec - _t1.tv_sec;
+    result->tv_usec = _t2.tv_usec - _t1.tv_usec;
+
+    return _t1.tv_sec >= _t2.tv_sec;
+}
+
+/**
+ * find the maximum value from a variable list of integers
+ *
+ * @param num_args number of list items
+ * @param ... the integers from which to find maximum
+ * @return the integer with the largest value from the
+ *         list provided
+ */
+int maxof(int num_args, ...)
+{
+    int max, i, a;
+    va_list ap;
+
+    va_start(ap, num_args);
+    max = va_arg(ap, int);
+    for (i = 2; i <= num_args; i++) {
+        if ((a = va_arg(ap, int)) > max) {
+            max = a;
+        }
+    }
+    va_end(ap);
+    return max;
+}

=== modified file 'lib/tool/lutil.h'
--- lib/tool/lutil.h    2010-03-03 16:51:18 +0000
+++ lib/tool/lutil.h    2010-03-19 09:53:35 +0000
@@ -7,10 +7,6 @@
 #ifndef HIP_LIB_TOOL_LUTIL_H
 #define HIP_LIB_TOOL_LUTIL_H
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
 #include <dirent.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -20,6 +16,7 @@
 #include <stdlib.h>
 #include <malloc.h>
 
+#include "config.h"
 #include "lib/core/builder.h"
 #include "lib/core/debug.h"
 
@@ -54,6 +51,8 @@
 void insert(List *, char *data);
 void destroy(List *);
 int length(List *);
+int hip_timeval_diff(const struct timeval *t1, const struct timeval *t2,
+                     struct timeval *result);
 
 /**
  * Gets an item from a linked list. Gets <code>n</code>th item from a linked
@@ -78,4 +77,6 @@
  */
 void extractsubstrings(char *string, List *list);
 
+int maxof(int num_args, ...);
+
 #endif /* HIP_LIB_TOOL_LUTIL_H */

=== modified file 'lib/tool/nlink.c'
--- lib/tool/nlink.c    2010-03-19 09:24:10 +0000
+++ lib/tool/nlink.c    2010-03-19 09:53:35 +0000
@@ -30,10 +30,11 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include "config.h"
+#include "lib/core/hip_udp.h"
 #include "nlink.h"
 
 /* New one to prevent netlink overrun */
@@ -1362,7 +1363,7 @@
     int fd;
     int err;
 
-    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+    strncpy(ifr.ifr_name, dev, IF_NAMESIZE);
     fd  = get_ctl_fd();
     if (fd < 0) {
         return -1;

=== modified file 'lib/tool/nlink.h'
--- lib/tool/nlink.h    2010-03-19 09:24:10 +0000
+++ lib/tool/nlink.h    2010-03-19 09:53:35 +0000
@@ -18,6 +18,9 @@
 #include "lib/core/builder.h"
 #include "lib/core/debug.h"
 
+#define HIP_OPTION_KIND 30
+#define HIP_NETLINK_TALK_ACK 0 /* see netlink_talk */
+
 
 struct pseudo_hdr {
     uint32_t s_addr;
@@ -35,8 +38,6 @@
     uint16_t             length;
 };
 
-#define HIP_OPTION_KIND 30
-
 struct netdev_address {
     //hip_list_t next;
     struct sockaddr_storage addr;

=== modified file 'lib/tool/pk.c'
--- lib/tool/pk.c       2010-03-19 09:24:10 +0000
+++ lib/tool/pk.c       2010-03-19 09:53:35 +0000
@@ -13,10 +13,7 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "pk.h"
 
 #ifdef CONFIG_HIP_PERFORMANCE

=== modified file 'lib/tool/xfrmapi.c'
--- lib/tool/xfrmapi.c  2010-03-19 09:24:10 +0000
+++ lib/tool/xfrmapi.c  2010-03-19 09:53:35 +0000
@@ -16,11 +16,10 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/tool/nlink.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/keylen.h"
 
 #include "xfrmapi.h"
 

=== modified file 'lib/tool/xfrmapi.h'
--- lib/tool/xfrmapi.h  2010-03-19 09:24:10 +0000
+++ lib/tool/xfrmapi.h  2010-03-19 09:53:35 +0000
@@ -15,7 +15,7 @@
 #include "lib/core/hashtable.h"
 #include "hipd/hadb.h"
 #include "hipd/user.h"
-#include "lib/core/misc.h"
+
 #include "lib/core/state.h"
 #include "nlink.h"
 

=== added directory 'patches/kernel/2.6.20'
=== added file 'patches/kernel/2.6.20/beet-2.6.20.21.patch'
--- patches/kernel/2.6.20/beet-2.6.20.21.patch  1970-01-01 00:00:00 +0000
+++ patches/kernel/2.6.20/beet-2.6.20.21.patch  2010-03-19 09:53:35 +0000
@@ -0,0 +1,1555 @@
+diff -urN linux-2.6.20.21/include/net/route.h 
linux-2.6.20.21-hipl/include/net/route.h
+--- linux-2.6.20.21/include/net/route.h        2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/include/net/route.h   2010-03-12 17:41:05.000000000 
+0200
+@@ -146,7 +146,8 @@
+ 
+ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
+                                  __be32 src, u32 tos, int oif, u8 protocol,
+-                                 __be16 sport, __be16 dport, struct sock *sk)
++                                 __be16 sport, __be16 dport, struct sock *sk,
++                                 int flags)
+ {
+       struct flowi fl = { .oif = oif,
+                           .nl_u = { .ip4_u = { .daddr = dst,
+@@ -168,7 +169,7 @@
+               *rp = NULL;
+       }
+       security_sk_classify_flow(sk, &fl);
+-      return ip_route_output_flow(rp, &fl, sk, 0);
++      return ip_route_output_flow(rp, &fl, sk, flags);
+ }
+ 
+ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
+diff -urN linux-2.6.20.21/include/net/xfrm.h 
linux-2.6.20.21-hipl/include/net/xfrm.h
+--- linux-2.6.20.21/include/net/xfrm.h 2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/include/net/xfrm.h    2010-03-12 17:41:05.000000000 
+0200
+@@ -237,7 +237,7 @@
+ extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+ extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event 
*c);
+ extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
+-#define XFRM_ACQ_EXPIRES      30
++#define XFRM_ACQ_EXPIRES      3
+ 
+ struct xfrm_tmpl;
+ extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct 
xfrm_policy *pol);
+@@ -928,14 +928,14 @@
+ extern int xfrm_init_state(struct xfrm_state *x);
+ extern int xfrm4_rcv(struct sk_buff *skb);
+ extern int xfrm4_output(struct sk_buff *skb);
+-extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
+-extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
++extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short 
family);
++extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned 
short family);
+ extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
+ extern int xfrm6_rcv(struct sk_buff **pskb);
+ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+                           xfrm_address_t *saddr, u8 proto);
+-extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
+-extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
++extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short 
family);
++extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned 
short family);
+ extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
+ extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
+ extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
+diff -urN linux-2.6.20.21/net/dccp/ipv4.c linux-2.6.20.21-hipl/net/dccp/ipv4.c
+--- linux-2.6.20.21/net/dccp/ipv4.c    2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/dccp/ipv4.c       2010-03-12 17:41:05.000000000 
+0200
+@@ -72,7 +72,7 @@
+       tmp = ip_route_connect(&rt, nexthop, inet->saddr,
+                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+                              IPPROTO_DCCP,
+-                             inet->sport, usin->sin_port, sk);
++                             inet->sport, usin->sin_port, sk, 1);
+       if (tmp < 0)
+               return tmp;
+ 
+diff -urN linux-2.6.20.21/net/dccp/ipv6.c linux-2.6.20.21-hipl/net/dccp/ipv6.c
+--- linux-2.6.20.21/net/dccp/ipv6.c    2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/dccp/ipv6.c       2010-03-12 17:41:05.000000000 
+0200
+@@ -1041,7 +1041,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      err = xfrm_lookup(&dst, &fl, sk, 0);
++      err = xfrm_lookup(&dst, &fl, sk, 1);
+       if (err < 0)
+               goto failure;
+ 
+diff -urN linux-2.6.20.21/net/ipv4/af_inet.c 
linux-2.6.20.21-hipl/net/ipv4/af_inet.c
+--- linux-2.6.20.21/net/ipv4/af_inet.c 2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/af_inet.c    2010-03-12 17:41:05.000000000 
+0200
+@@ -1007,7 +1007,7 @@
+                              RT_CONN_FLAGS(sk),
+                              sk->sk_bound_dev_if,
+                              sk->sk_protocol,
+-                             inet->sport, inet->dport, sk);
++                             inet->sport, inet->dport, sk, 0);
+       if (err)
+               return err;
+ 
+diff -urN linux-2.6.20.21/net/ipv4/datagram.c 
linux-2.6.20.21-hipl/net/ipv4/datagram.c
+--- linux-2.6.20.21/net/ipv4/datagram.c        2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv4/datagram.c   2010-03-12 17:41:05.000000000 
+0200
+@@ -49,7 +49,7 @@
+       err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
+                              RT_CONN_FLAGS(sk), oif,
+                              sk->sk_protocol,
+-                             inet->sport, usin->sin_port, sk);
++                             inet->sport, usin->sin_port, sk, 1);
+       if (err)
+               return err;
+       if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
+diff -urN linux-2.6.20.21/net/ipv4/esp4.c linux-2.6.20.21-hipl/net/ipv4/esp4.c
+--- linux-2.6.20.21/net/ipv4/esp4.c    2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/esp4.c       2010-03-12 17:41:05.000000000 
+0200
+@@ -402,6 +402,8 @@
+       x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               x->props.header_len += sizeof(struct iphdr);
++      else if (x->props.mode == XFRM_MODE_BEET)
++              x->props.header_len += IPV4_BEET_PHMAXLEN;
+       if (x->encap) {
+               struct xfrm_encap_tmpl *encap = x->encap;
+ 
+diff -urN linux-2.6.20.21/net/ipv4/ipip.c linux-2.6.20.21-hipl/net/ipv4/ipip.c
+--- linux-2.6.20.21/net/ipv4/ipip.c    2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/ipip.c       2010-03-12 17:41:05.000000000 
+0200
+@@ -870,7 +870,7 @@
+ 
+       printk(banner);
+ 
+-      if (xfrm4_tunnel_register(&ipip_handler)) {
++      if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
+               printk(KERN_INFO "ipip init: can't register tunnel\n");
+               return -EAGAIN;
+       }
+@@ -892,7 +892,7 @@
+  err2:
+       free_netdev(ipip_fb_tunnel_dev);
+  err1:
+-      xfrm4_tunnel_deregister(&ipip_handler);
++      xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+       goto out;
+ }
+ 
+@@ -912,7 +912,7 @@
+ 
+ static void __exit ipip_fini(void)
+ {
+-      if (xfrm4_tunnel_deregister(&ipip_handler))
++      if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
+               printk(KERN_INFO "ipip close: can't deregister tunnel\n");
+ 
+       rtnl_lock();
+diff -urN linux-2.6.20.21/net/ipv4/raw.c linux-2.6.20.21-hipl/net/ipv4/raw.c
+--- linux-2.6.20.21/net/ipv4/raw.c     2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/raw.c        2010-03-12 17:41:05.000000000 
+0200
+@@ -489,7 +489,7 @@
+               }
+ 
+               security_sk_classify_flow(sk, &fl);
+-              err = ip_route_output_flow(&rt, &fl, sk, 
!(msg->msg_flags&MSG_DONTWAIT));
++              err = ip_route_output_flow(&rt, &fl, sk, 1);
+       }
+       if (err)
+               goto done;
+diff -urN linux-2.6.20.21/net/ipv4/route.c 
linux-2.6.20.21-hipl/net/ipv4/route.c
+--- linux-2.6.20.21/net/ipv4/route.c   2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/route.c      2010-03-12 17:41:05.000000000 
+0200
+@@ -108,6 +108,7 @@
+ #ifdef CONFIG_SYSCTL
+ #include <linux/sysctl.h>
+ #endif
++#include <linux/xfrm.h>
+ 
+ #define RT_FL_TOS(oldflp) \
+     ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
+diff -urN linux-2.6.20.21/net/ipv4/tcp_ipv4.c 
linux-2.6.20.21-hipl/net/ipv4/tcp_ipv4.c
+--- linux-2.6.20.21/net/ipv4/tcp_ipv4.c        2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv4/tcp_ipv4.c   2010-03-12 17:41:05.000000000 
+0200
+@@ -191,7 +191,7 @@
+       tmp = ip_route_connect(&rt, nexthop, inet->saddr,
+                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+                              IPPROTO_TCP,
+-                             inet->sport, usin->sin_port, sk);
++                             inet->sport, usin->sin_port, sk, 1);
+       if (tmp < 0)
+               return tmp;
+ 
+diff -urN linux-2.6.20.21/net/ipv4/tunnel4.c 
linux-2.6.20.21-hipl/net/ipv4/tunnel4.c
+--- linux-2.6.20.21/net/ipv4/tunnel4.c 2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/tunnel4.c    2010-03-12 17:41:05.000000000 
+0200
+@@ -14,9 +14,10 @@
+ #include <net/xfrm.h>
+ 
+ static struct xfrm_tunnel *tunnel4_handlers;
++static struct xfrm_tunnel *tunnel64_handlers;
+ static DEFINE_MUTEX(tunnel4_mutex);
+ 
+-int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
++int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
+ {
+       struct xfrm_tunnel **pprev;
+       int ret = -EEXIST;
+@@ -24,7 +25,8 @@
+ 
+       mutex_lock(&tunnel4_mutex);
+ 
+-      for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET) ? &tunnel4_handlers : 
&tunnel64_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if ((*pprev)->priority > priority)
+                       break;
+               if ((*pprev)->priority == priority)
+@@ -44,14 +46,15 @@
+ 
+ EXPORT_SYMBOL(xfrm4_tunnel_register);
+ 
+-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
++int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short 
family)
+ {
+       struct xfrm_tunnel **pprev;
+       int ret = -ENOENT;
+ 
+       mutex_lock(&tunnel4_mutex);
+ 
+-      for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET) ? &tunnel4_handlers : 
&tunnel64_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if (*pprev == handler) {
+                       *pprev = handler->next;
+                       ret = 0;
+@@ -86,6 +89,26 @@
+       return 0;
+ }
+ 
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++static int tunnel64_rcv(struct sk_buff *skb)
++{
++      struct xfrm_tunnel *handler;
++
++      if (!pskb_may_pull(skb, sizeof(struct iphdr)))
++              goto drop;
++
++      for (handler = tunnel64_handlers; handler; handler = handler->next)
++              if (!handler->handler(skb))
++                      return 0;
++
++      icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
++
++drop:
++      kfree_skb(skb);
++      return 0;
++}
++#endif
++
+ static void tunnel4_err(struct sk_buff *skb, u32 info)
+ {
+       struct xfrm_tunnel *handler;
+@@ -101,17 +124,36 @@
+       .no_policy      =       1,
+ };
+ 
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++static struct net_protocol tunnel64_protocol = {
++      .handler        =       tunnel64_rcv,
++      .err_handler    =       tunnel4_err,
++      .no_policy      =       1,
++};
++#endif
++
+ static int __init tunnel4_init(void)
+ {
+       if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
+               printk(KERN_ERR "tunnel4 init: can't add protocol\n");
+               return -EAGAIN;
+       }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
++              printk(KERN_ERR "tunnel64 init: can't add protocol\n");
++              inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
++              return -EAGAIN;
++      }
++#endif
+       return 0;
+ }
+ 
+ static void __exit tunnel4_fini(void)
+ {
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
++              printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
++#endif
+       if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+               printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
+ }
+diff -urN linux-2.6.20.21/net/ipv4/udp.c linux-2.6.20.21-hipl/net/ipv4/udp.c
+--- linux-2.6.20.21/net/ipv4/udp.c     2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv4/udp.c        2010-03-12 17:41:05.000000000 
+0200
+@@ -629,7 +629,7 @@
+                                              { .sport = inet->sport,
+                                                .dport = dport } } };
+               security_sk_classify_flow(sk, &fl);
+-              err = ip_route_output_flow(&rt, &fl, sk, 
!(msg->msg_flags&MSG_DONTWAIT));
++              err = ip_route_output_flow(&rt, &fl, sk, 1);
+               if (err)
+                       goto out;
+ 
+diff -urN linux-2.6.20.21/net/ipv4/xfrm4_input.c 
linux-2.6.20.21-hipl/net/ipv4/xfrm4_input.c
+--- linux-2.6.20.21/net/ipv4/xfrm4_input.c     2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_input.c        2010-03-12 
17:41:05.000000000 +0200
+@@ -106,7 +106,7 @@
+               if (x->mode->input(x, skb))
+                       goto drop;
+ 
+-              if (x->props.mode == XFRM_MODE_TUNNEL) {
++              if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == 
XFRM_MODE_BEET) {
+                       decaps = 1;
+                       break;
+               }
+diff -urN linux-2.6.20.21/net/ipv4/xfrm4_mode_beet.c 
linux-2.6.20.21-hipl/net/ipv4/xfrm4_mode_beet.c
+--- linux-2.6.20.21/net/ipv4/xfrm4_mode_beet.c 2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_mode_beet.c    2010-03-12 
17:41:05.000000000 +0200
+@@ -6,6 +6,7 @@
+  *                    Herbert Xu     <herbert@xxxxxxxxxxxxxxxxxxx>
+  *                    Abhinav Pathak <abhinav.pathak@xxxxxxx>
+  *                    Jeff Ahrenholz <ahrenholz@xxxxxxxxx>
++ *                    Joakim Koskela <jookos@xxxxxxxxx>
+  */
+ 
+ #include <linux/init.h>
+@@ -14,54 +15,97 @@
+ #include <linux/skbuff.h>
+ #include <linux/stringify.h>
+ #include <net/dst.h>
++#include <net/dsfield.h>
+ #include <net/ip.h>
++#include <net/inet_ecn.h>
+ #include <net/xfrm.h>
+ 
+-/* Add encapsulation header.
+- *
+- * The top IP header will be constructed per 
draft-nikander-esp-beet-mode-06.txt.
+- * The following fields in it shall be filled in by x->type->output:
+- *      tot_len
+- *      check
+- *
+- * On exit, skb->h will be set to the start of the payload to be processed
+- * by x->type->output and skb->nh will be set to the top IP header.
+- */
+ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+-      struct iphdr *iph, *top_iph = NULL;
+-      int hdrlen, optlen;
++      struct dst_entry *dst = skb->dst;
++      int hdrlen;
++      struct iphdr *iphv4, *top_iphv4;
++      struct ipv6hdr *iphv6, *top_iphv6;
+ 
+-      iph = skb->nh.iph;
+-      skb->h.ipiph = iph;
++      if (skb->nh.iph->version == 4) {
+ 
+-      hdrlen = 0;
+-      optlen = iph->ihl * 4 - sizeof(*iph);
+-      if (unlikely(optlen))
+-              hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
+-
+-      skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
+-      top_iph = skb->nh.iph;
+-      hdrlen = iph->ihl * 4 - optlen;
+-      skb->h.raw += hdrlen;
+-
+-      memmove(top_iph, iph, hdrlen);
+-      if (unlikely(optlen)) {
+-              struct ip_beet_phdr *ph;
+-
+-              BUG_ON(optlen < 0);
+-
+-              ph = (struct ip_beet_phdr *)skb->h.raw;
+-              ph->padlen = 4 - (optlen & 4);
+-              ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
+-              ph->nexthdr = top_iph->protocol;
++              int optlen;
+ 
+-              top_iph->protocol = IPPROTO_BEETPH;
+-              top_iph->ihl = sizeof(struct iphdr) / 4;
+-      }
++              /* 4-4 */
++
++              iphv4 = skb->nh.iph;
++              skb->h.ipiph = iphv4;
++
++              hdrlen = x->props.header_len;
++
++              optlen = iphv4->ihl * 4 - sizeof(*iphv4);
++
++              if (!optlen) {
++                      hdrlen -= IPV4_BEET_PHMAXLEN;
++              } else {
++                      skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));
++                      hdrlen -= optlen & 4;
++              }
++
++              skb->nh.raw = skb_push(skb, hdrlen);
++
++              top_iphv4 = skb->nh.iph;
++              hdrlen = iphv4->ihl * 4 - optlen;
++              skb->h.raw += hdrlen;
++              memmove(top_iphv4, iphv4, hdrlen);
++
++              if (unlikely(optlen)) {
++                      struct ip_beet_phdr *ph;
++
++                      BUG_ON(optlen < 0);
++
++                      ph = (struct ip_beet_phdr *)skb->h.raw;
++                      ph->padlen = 4 - (optlen & 4);
++                      ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
++                      ph->nexthdr = iphv4->protocol;
++                      top_iphv4->protocol = IPPROTO_BEETPH;
++                      top_iphv4->ihl = sizeof(struct iphdr) / 4;
++              }
++
++              top_iphv4->saddr = x->props.saddr.a4;
++              top_iphv4->daddr = x->id.daddr.a4;
++
++              skb->protocol = htons(ETH_P_IP);
++
++      } else if (skb->nh.iph->version == 6) {
++
++              u8 protocol;
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++
++              /* Inner = 6, Outer = 4 : changing the external IP hdr
++               * to the outer addresses
++               */
++
++              hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;
++              skb_push(skb, hdrlen);
++              iphv6 = skb->nh.ipv6h;
++
++              skb->nh.raw = skb->data;
++              top_iphv6 = skb->nh.ipv6h;
++
++              protocol = iphv6->nexthdr;
++              skb->nh.raw = skb_pull(skb, delta);
++              top_iphv4 = skb->nh.iph;
++              skb->h.raw = skb->data + hdrlen;
++              top_iphv4->ihl = (sizeof(struct iphdr) >> 2);
++              top_iphv4->version = 4;
++              top_iphv4->id = 0;
++              top_iphv4->frag_off = htons(IP_DF);
++              top_iphv4->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
++              top_iphv4->saddr = x->props.saddr.a4;
++              top_iphv4->daddr = x->id.daddr.a4;
++              skb->h.raw += top_iphv4->ihl*4;
++              top_iphv4->protocol = protocol;
++
++              skb->protocol = htons(ETH_P_IP);
++      } else
++              BUG_ON(1);
+ 
+-      top_iph->saddr = x->props.saddr.a4;
+-      top_iph->daddr = x->id.daddr.a4;
+ 
+       return 0;
+ }
+@@ -69,45 +113,73 @@
+ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+       struct iphdr *iph = skb->nh.iph;
++      int hops = skb->nh.iph->ttl;
+       int phlen = 0;
+       int optlen = 0;
++      int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : 
sizeof(struct ipv6hdr);
++      int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
+       __u8 ph_nexthdr = 0, protocol = 0;
+       int err = -EINVAL;
+ 
+       protocol = iph->protocol;
+ 
+-      if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
+-              struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);
++      if (x->sel.family == AF_INET6) {
++              /* Here, the inner family is 6, therefore I have to
++               * substitute the IPhdr by enlarging it */
++              if (skb_tailroom(skb) <  delta){
++                      if (pskb_expand_head(skb, 0, delta, GFP_ATOMIC))
++                              goto out;
++              }
++              skb->nh.raw -= delta;
++      } else if (x->sel.family == AF_INET) {
++              if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
++                      struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 
1);
++
++                      if (!pskb_may_pull(skb, sizeof(*ph)))
++                              goto out;
++
++                      phlen = ph->hdrlen * 8;
++                      optlen = phlen - ph->padlen - sizeof(*ph);
++                      if (optlen < 0 || optlen & 3 || optlen > 250)
++                              goto out;
++
++                      if (!pskb_may_pull(skb, phlen))
++                              goto out;
++
++                      ph_nexthdr = ph->nexthdr;
++              }
++      } else
++              BUG_ON(1);
+ 
+-              if (!pskb_may_pull(skb, sizeof(*ph)))
+-                      goto out;
+-
+-              phlen = ph->hdrlen * 8;
+-              optlen = phlen - ph->padlen - sizeof(*ph);
+-              if (optlen < 0 || optlen & 3 || optlen > 250)
+-                      goto out;
+-
+-              if (!pskb_may_pull(skb, phlen))
+-                      goto out;
+-
+-              ph_nexthdr = ph->nexthdr;
+-      }
+-
+-      skb_push(skb, sizeof(*iph) - phlen + optlen);
++      size += (optlen - phlen);
++      skb_push(skb, size);
+       memmove(skb->data, skb->nh.raw, sizeof(*iph));
+       skb->nh.raw = skb->data;
+ 
+-      iph = skb->nh.iph;
+-      iph->ihl = (sizeof(*iph) + optlen) / 4;
+-      iph->tot_len = htons(skb->len);
+-      iph->daddr = x->sel.daddr.a4;
+-      iph->saddr = x->sel.saddr.a4;
+-      if (ph_nexthdr)
+-              iph->protocol = ph_nexthdr;
+-      else
+-              iph->protocol = protocol;
+-      iph->check = 0;
+-      iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
++      if (x->sel.family == AF_INET) {
++              iph = skb->nh.iph;
++              iph->ihl = (sizeof(*iph) + optlen) / 4;
++              iph->tot_len = htons(skb->len);
++              iph->daddr = x->sel.daddr.a4;
++              iph->saddr = x->sel.saddr.a4;
++              if (ph_nexthdr)
++                      iph->protocol = ph_nexthdr;
++              else
++                      iph->protocol = protocol;
++              iph->check = 0;
++              iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
++      } else if (x->sel.family == AF_INET6) {
++              struct ipv6hdr *ip6h = skb->nh.ipv6h;
++              memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl));
++              ip6h->version = 6;
++              ip6h->priority = 0;
++              ip6h->nexthdr = protocol;
++              ip6h->hop_limit = hops;
++              ip6h->payload_len = htons(skb->len - size);
++              ipv6_addr_copy(&ip6h->daddr, (struct in6_addr 
*)&x->sel.daddr.a6);
++              ipv6_addr_copy(&ip6h->saddr, (struct in6_addr 
*)&x->sel.saddr.a6);
++              skb->protocol = htons(ETH_P_IPV6);
++      }
+       err = 0;
+ out:
+       return err;
+diff -urN linux-2.6.20.21/net/ipv4/xfrm4_policy.c 
linux-2.6.20.21-hipl/net/ipv4/xfrm4_policy.c
+--- linux-2.6.20.21/net/ipv4/xfrm4_policy.c    2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_policy.c       2010-03-12 
17:42:24.000000000 +0200
+@@ -15,6 +15,7 @@
+ 
+ static struct dst_ops xfrm4_dst_ops;
+ static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
++static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu);
+ 
+ static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+ {
+@@ -72,17 +73,20 @@
+       struct dst_entry *dst, *dst_prev;
+       struct rtable *rt0 = (struct rtable*)(*dst_p);
+       struct rtable *rt = rt0;
+-      __be32 remote = fl->fl4_dst;
+-      __be32 local  = fl->fl4_src;
+       struct flowi fl_tunnel = {
+               .nl_u = {
+                       .ip4_u = {
+-                              .saddr = local,
+-                              .daddr = remote,
++                              .saddr = fl->fl4_src,
++                              .daddr = fl->fl4_dst,
+                               .tos = fl->fl4_tos
+                       }
+               }
+       };
++      union {
++              struct in6_addr *in6;
++              struct in_addr *in;
++      } remote, local;
++      unsigned short outer_family6 = 0;
+       int i;
+       int err;
+       int header_len = 0;
+@@ -94,7 +98,7 @@
+       for (i = 0; i < nx; i++) {
+               struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
+               struct xfrm_dst *xdst;
+-              int tunnel = 0;
++              unsigned short outer_family = 0;
+ 
+               if (unlikely(dst1 == NULL)) {
+                       err = -ENOBUFS;
+@@ -117,20 +121,41 @@
+               dst1->next = dst_prev;
+               dst_prev = dst1;
+               if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
+-                      remote = xfrm[i]->id.daddr.a4;
+-                      local  = xfrm[i]->props.saddr.a4;
+-                      tunnel = 1;
++                      outer_family = xfrm[i]->props.family;
++                      if(outer_family == AF_INET){
++                              remote.in = (struct 
in_addr*)&xfrm[i]->id.daddr.a4;
++                              local.in  = (struct 
in_addr*)&xfrm[i]->props.saddr.a4;
++                      } else if (outer_family == AF_INET6){
++                              outer_family6 = 1;
++                              remote.in6 = (struct 
in6_addr*)xfrm[i]->id.daddr.a6;
++                              local.in6 = (struct 
in6_addr*)xfrm[i]->props.saddr.a6;
++                      } else
++                                BUG_ON(1);
+               }
+               header_len += xfrm[i]->props.header_len;
+               trailer_len += xfrm[i]->props.trailer_len;
+ 
+-              if (tunnel) {
+-                      fl_tunnel.fl4_src = local;
+-                      fl_tunnel.fl4_dst = remote;
++              if (outer_family) {
++                      switch (outer_family) {
++                      default:
++                      case AF_INET:
++                              fl_tunnel.fl4_src = local.in->s_addr;
++                              fl_tunnel.fl4_dst = remote.in->s_addr;
++                              break;
++                      case AF_INET6:
++                              ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);
++                              ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);
++                              break;
++                      }
+                       err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
+-                                            &fl_tunnel, AF_INET);
++                                            &fl_tunnel, outer_family);
+                       if (err)
+                               goto error;
++                      /* Without this, the atomic inc below segfaults */
++                      if (outer_family == AF_INET6) {
++                              rt->peer = NULL;
++                              rt_bind_peer(rt,1);
++                      }
+               } else
+                       dst_hold(&rt->u.dst);
+       }
+@@ -181,6 +206,12 @@
+       }
+ 
+       xfrm_init_pmtu(dst);
++      if (outer_family6) {
++              /* The worst case */
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++              u32 mtu = dst_mtu(dst);
++              xfrm4_update_pmtu(dst, mtu - delta);
++      }
+       return 0;
+ 
+ error:
+diff -urN linux-2.6.20.21/net/ipv4/xfrm4_tunnel.c 
linux-2.6.20.21-hipl/net/ipv4/xfrm4_tunnel.c
+--- linux-2.6.20.21/net/ipv4/xfrm4_tunnel.c    2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_tunnel.c       2010-03-12 
17:42:24.000000000 +0200
+@@ -13,7 +13,7 @@
+ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+       struct iphdr *iph;
+-      
++
+       iph = skb->nh.iph;
+       iph->tot_len = htons(skb->len);
+       ip_send_check(iph);
+@@ -28,7 +28,7 @@
+ 
+ static int ipip_init_state(struct xfrm_state *x)
+ {
+-      if (x->props.mode != XFRM_MODE_TUNNEL)
++      if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != 
XFRM_MODE_BEET)
+               return -EINVAL;
+ 
+       if (x->encap)
+@@ -64,24 +64,45 @@
+       .priority       =       2,
+ };
+ 
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++static struct xfrm_tunnel xfrm64_tunnel_handler = {
++      .handler        =       xfrm4_rcv,
++      .err_handler    =       xfrm_tunnel_err,
++      .priority       =       2,
++};
++#endif
++
+ static int __init ipip_init(void)
+ {
+       if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
+               printk(KERN_INFO "ipip init: can't add xfrm type\n");
+               return -EAGAIN;
+       }
+-      if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
+-              printk(KERN_INFO "ipip init: can't add xfrm handler\n");
++
++      if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
++              printk(KERN_INFO "ipip init: can't add xfrm handler for 
AF_INET\n");
++              xfrm_unregister_type(&ipip_type, AF_INET);
++              return -EAGAIN;
++      }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
++              printk(KERN_INFO "ipip init: can't add xfrm handler for 
AF_INET6\n");
++              xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
+               xfrm_unregister_type(&ipip_type, AF_INET);
+               return -EAGAIN;
+       }
++#endif
+       return 0;
+ }
+ 
+ static void __exit ipip_fini(void)
+ {
+-      if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
+-              printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
++              printk(KERN_INFO "ipip close: can't remove xfrm handler for 
AF_INET6\n");
++#endif
++      if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
++              printk(KERN_INFO "ipip close: can't remove xfrm handler for 
AF_INET\n");
+       if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
+               printk(KERN_INFO "ipip close: can't remove xfrm type\n");
+ }
+diff -urN linux-2.6.20.21/net/ipv6/datagram.c 
linux-2.6.20.21-hipl/net/ipv6/datagram.c
+--- linux-2.6.20.21/net/ipv6/datagram.c        2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/datagram.c   2010-03-12 17:42:24.000000000 
+0200
+@@ -178,7 +178,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto out;
+ 
+       /* source address lookup done in ip6_dst_lookup */
+diff -urN linux-2.6.20.21/net/ipv6/esp6.c linux-2.6.20.21-hipl/net/ipv6/esp6.c
+--- linux-2.6.20.21/net/ipv6/esp6.c    2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv6/esp6.c       2010-03-12 17:42:24.000000000 
+0200
+@@ -240,9 +240,9 @@
+ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
+ {
+       struct esp_data *esp = x->data;
+-      u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
++      u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
+ 
+-      if (x->props.mode == XFRM_MODE_TUNNEL) {
++      if (x->props.mode) {
+               mtu = ALIGN(mtu + 2, blksize);
+       } else {
+               /* The worst case. */
+@@ -365,6 +365,8 @@
+       x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               x->props.header_len += sizeof(struct ipv6hdr);
++      else if (x->props.mode == XFRM_MODE_BEET)
++              x->props.header_len += IPV4_BEET_PHMAXLEN;
+       x->data = esp;
+       return 0;
+ 
+diff -urN linux-2.6.20.21/net/ipv6/icmp.c linux-2.6.20.21-hipl/net/ipv6/icmp.c
+--- linux-2.6.20.21/net/ipv6/icmp.c    2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv6/icmp.c       2010-03-12 17:42:24.000000000 
+0200
+@@ -64,6 +64,7 @@
+ #include <net/ip6_route.h>
+ #include <net/addrconf.h>
+ #include <net/icmp.h>
++#include <linux/xfrm.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+diff -urN linux-2.6.20.21/net/ipv6/ip6_tunnel.c 
linux-2.6.20.21-hipl/net/ipv6/ip6_tunnel.c
+--- linux-2.6.20.21/net/ipv6/ip6_tunnel.c      2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/ip6_tunnel.c 2010-03-12 17:42:24.000000000 
+0200
+@@ -1127,7 +1127,7 @@
+ {
+       int  err;
+ 
+-      if (xfrm6_tunnel_register(&ip6ip6_handler)) {
++      if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
+               printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
+               return -EAGAIN;
+       }
+@@ -1146,7 +1146,7 @@
+       }
+       return 0;
+ fail:
+-      xfrm6_tunnel_deregister(&ip6ip6_handler);
++      xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
+       return err;
+ }
+ 
+@@ -1170,7 +1170,7 @@
+ 
+ static void __exit ip6_tunnel_cleanup(void)
+ {
+-      if (xfrm6_tunnel_deregister(&ip6ip6_handler))
++      if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
+               printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
+ 
+       rtnl_lock();
+diff -urN linux-2.6.20.21/net/ipv6/raw.c linux-2.6.20.21-hipl/net/ipv6/raw.c
+--- linux-2.6.20.21/net/ipv6/raw.c     2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv6/raw.c        2010-03-12 17:42:24.000000000 
+0200
+@@ -815,7 +815,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto out;
+ 
+       if (hlimit < 0) {
+diff -urN linux-2.6.20.21/net/ipv6/tcp_ipv6.c 
linux-2.6.20.21-hipl/net/ipv6/tcp_ipv6.c
+--- linux-2.6.20.21/net/ipv6/tcp_ipv6.c        2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/tcp_ipv6.c   2010-03-12 17:42:24.000000000 
+0200
+@@ -265,7 +265,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto failure;
+ 
+       if (saddr == NULL) {
+diff -urN linux-2.6.20.21/net/ipv6/tunnel6.c 
linux-2.6.20.21-hipl/net/ipv6/tunnel6.c
+--- linux-2.6.20.21/net/ipv6/tunnel6.c 2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv6/tunnel6.c    2010-03-12 17:42:24.000000000 
+0200
+@@ -30,9 +30,10 @@
+ #include <net/xfrm.h>
+ 
+ static struct xfrm6_tunnel *tunnel6_handlers;
++static struct xfrm6_tunnel *tunnel46_handlers;
+ static DEFINE_MUTEX(tunnel6_mutex);
+ 
+-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
++int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
+ {
+       struct xfrm6_tunnel **pprev;
+       int ret = -EEXIST;
+@@ -40,7 +41,8 @@
+ 
+       mutex_lock(&tunnel6_mutex);
+ 
+-      for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET6) ? &tunnel6_handlers : 
&tunnel46_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if ((*pprev)->priority > priority)
+                       break;
+               if ((*pprev)->priority == priority)
+@@ -60,14 +62,15 @@
+ 
+ EXPORT_SYMBOL(xfrm6_tunnel_register);
+ 
+-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
++int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short 
family)
+ {
+       struct xfrm6_tunnel **pprev;
+       int ret = -ENOENT;
+ 
+       mutex_lock(&tunnel6_mutex);
+ 
+-      for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET6) ? &tunnel6_handlers : 
&tunnel46_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if (*pprev == handler) {
+                       *pprev = handler->next;
+                       ret = 0;
+@@ -103,6 +106,25 @@
+       return 0;
+ }
+ 
++static int tunnel46_rcv(struct sk_buff **pskb)
++{
++      struct sk_buff *skb = *pskb;
++      struct xfrm6_tunnel *handler;
++
++      if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
++              goto drop;
++
++      for (handler = tunnel46_handlers; handler; handler = handler->next)
++              if (!handler->handler(skb))
++                      return 0;
++
++      icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
++
++drop:
++      kfree_skb(skb);
++      return 0;
++}
++
+ static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                       int type, int code, int offset, __be32 info)
+ {
+@@ -119,17 +141,30 @@
+       .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ };
+ 
++static struct inet6_protocol tunnel46_protocol = {
++      .handler        = tunnel46_rcv,
++      .err_handler    = tunnel6_err,
++      .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
++};
++
+ static int __init tunnel6_init(void)
+ {
+       if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
+               printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
+               return -EAGAIN;
+       }
++      if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) {
++              printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
++              inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
++              return -EAGAIN;
++      }
+       return 0;
+ }
+ 
+ static void __exit tunnel6_fini(void)
+ {
++      if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
++              printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+       if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
+               printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+ }
+diff -urN linux-2.6.20.21/net/ipv6/udp.c linux-2.6.20.21-hipl/net/ipv6/udp.c
+--- linux-2.6.20.21/net/ipv6/udp.c     2007-10-17 22:31:14.000000000 +0300
++++ linux-2.6.20.21-hipl/net/ipv6/udp.c        2010-03-12 17:42:24.000000000 
+0200
+@@ -736,7 +736,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto out;
+ 
+       if (hlimit < 0) {
+diff -urN linux-2.6.20.21/net/ipv6/xfrm6_input.c 
linux-2.6.20.21-hipl/net/ipv6/xfrm6_input.c
+--- linux-2.6.20.21/net/ipv6/xfrm6_input.c     2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_input.c        2010-03-12 
17:42:24.000000000 +0200
+@@ -72,7 +72,7 @@
+               if (x->mode->input(x, skb))
+                       goto drop;
+ 
+-              if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
++              if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == 
XFRM_MODE_BEET) { /* XXX */
+                       decaps = 1;
+                       break;
+               }
+diff -urN linux-2.6.20.21/net/ipv6/xfrm6_mode_beet.c 
linux-2.6.20.21-hipl/net/ipv6/xfrm6_mode_beet.c
+--- linux-2.6.20.21/net/ipv6/xfrm6_mode_beet.c 2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_mode_beet.c    2010-03-12 
17:42:24.000000000 +0200
+@@ -6,6 +6,7 @@
+  *                    Herbert Xu     <herbert@xxxxxxxxxxxxxxxxxxx>
+  *                    Abhinav Pathak <abhinav.pathak@xxxxxxx>
+  *                    Jeff Ahrenholz <ahrenholz@xxxxxxxxx>
++ *                    Joakim Koskela <jookos@xxxxxxxxx>
+  */
+ 
+ #include <linux/init.h>
+@@ -16,6 +17,7 @@
+ #include <net/dsfield.h>
+ #include <net/dst.h>
+ #include <net/inet_ecn.h>
++#include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/xfrm.h>
+ 
+@@ -31,38 +33,165 @@
+  * its absence, that of the top IP header.  The value of skb->data will always
+  * point to the top IP header.
+  */
++/* Add encapsulation header.
++ *
++ * The top IP header will be constructed per 
draft-nikander-esp-beet-mode-06.txt.
++ * The following fields in it shall be filled in by x->type->output:
++ *      tot_len
++ *      check
++ *
++ * On exit, skb->h will be set to the start of the payload to be processed
++ * by x->type->output and skb->nh will be set to the top IP header.
++ */
+ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+-      struct ipv6hdr *iph, *top_iph;
+-      u8 *prevhdr;
+-      int hdr_len;
+-
+-      skb_push(skb, x->props.header_len);
+-      iph = skb->nh.ipv6h;
+-
+-      hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+-      skb->nh.raw = prevhdr - x->props.header_len;
+-      skb->h.raw = skb->data + hdr_len;
+-      memmove(skb->data, iph, hdr_len);
+ 
+-      skb->nh.raw = skb->data;
+-      top_iph = skb->nh.ipv6h;
+-      skb->nh.raw = &top_iph->nexthdr;
+-      skb->h.ipv6h = top_iph + 1;
+-
+-      ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+-      ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
++      struct dst_entry *dst = skb->dst;
++      int hdrlen;
++      struct iphdr *iphv4, *top_iphv4;
++      struct ipv6hdr *iphv6, *top_iphv6;
++
++      if (skb->nh.iph->version == 6) {
++
++              u8 *prevhdr;
++              int hdr_len;
++
++/* 6-6 */
++
++              hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;
++              skb_push(skb, hdrlen);
++              iphv6 = skb->nh.ipv6h;
++
++              hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
++              skb->nh.raw = prevhdr - hdrlen;
++              skb->h.raw = skb->data + hdr_len;
++              memmove(skb->data, iphv6, hdr_len);
++
++              skb->nh.raw = skb->data;
++              top_iphv6 = skb->nh.ipv6h;
++              skb->nh.raw = &top_iphv6->nexthdr;
++              skb->h.ipv6h = top_iphv6 + 1;
++              ipv6_addr_copy(&top_iphv6->saddr, (struct in6_addr 
*)&x->props.saddr);
++              ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr 
*)&x->id.daddr);
++
++              skb->protocol = htons(ETH_P_IPV6);
++
++      } else if (skb->nh.iph->version == 4) {
++
++              int flags;
++              int optlen;
++              int dsfield;
++              u8 protocol;
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++
++              /* Inner = 4, Outer = 6*/
++
++              iphv4 = skb->nh.iph;
++              skb->h.ipiph = iphv4;
++
++              hdrlen = x->props.header_len;
++
++              optlen = iphv4->ihl * 4 - sizeof(*iphv4);
++
++              if (!optlen) {
++                      hdrlen -= IPV4_BEET_PHMAXLEN;
++              } else {
++                      skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));
++                      hdrlen -= optlen & 4;
++              }
++
++              skb->nh.raw = skb_push(skb, hdrlen);
++
++              top_iphv4 = skb->nh.iph;
++              hdrlen = iphv4->ihl * 4 - optlen;
++              skb->h.raw += hdrlen;
++              if (unlikely(optlen)) {
++                      struct ip_beet_phdr *ph;
++
++                      BUG_ON(optlen < 0);
++
++                      ph = (struct ip_beet_phdr *)skb->h.raw;
++                      ph->padlen = 4 - (optlen & 4);
++                      ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
++                      ph->nexthdr = iphv4->protocol;
++                      top_iphv4->protocol = IPPROTO_BEETPH;
++                      top_iphv4->ihl = sizeof(struct iphdr) / 4;
++              }
++
++              if (unlikely(optlen))
++                      protocol = top_iphv4->protocol;
++              else
++                      protocol = iphv4->protocol;
++
++              if (skb_headroom(skb) <=  2*delta){
++                      if (pskb_expand_head(skb, delta,0, GFP_ATOMIC))
++                              return -ENOMEM;
++              }
++
++              skb->nh.raw = skb_push(skb, delta);
++
++              top_iphv6 = skb->nh.ipv6h;
++              skb->h.ipv6h = top_iphv6 + 1;
++              /* DS disclosed */
++              top_iphv6->version = 6;
++              top_iphv6->priority = 0;
++              top_iphv6->flow_lbl[0] = 0;
++              top_iphv6->flow_lbl[1] = 0;
++              top_iphv6->flow_lbl[2] = 0;
++              dsfield = ipv6_get_dsfield(top_iphv6);
++              dsfield = INET_ECN_encapsulate(dsfield, dsfield);
++              flags = x->props.flags;
++              if (flags & XFRM_STATE_NOECN)
++                      dsfield &= ~INET_ECN_MASK;
++              ipv6_change_dsfield(top_iphv6, 0, dsfield);
++
++              top_iphv6->nexthdr = protocol;
++              top_iphv6->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
++              top_iphv6->payload_len = htons(skb->len - sizeof(struct 
ipv6hdr));
++              ipv6_addr_copy(&top_iphv6->saddr,(struct in6_addr 
*)&x->props.saddr);
++              ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr 
*)&x->id.daddr);
++              skb->nh.raw = &top_iphv6->nexthdr;
++
++              skb->protocol = htons(ETH_P_IPV6);
++      } else
++              BUG_ON(1);
+ 
+       return 0;
+ }
+ 
+ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+-      struct ipv6hdr *ip6h;
+-      int size = sizeof(struct ipv6hdr);
++      struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->h.raw);
++      int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : 
sizeof(struct ipv6hdr);
++      int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++      __u8 proto = skb->nh.ipv6h->nexthdr, hops = skb->nh.ipv6h->hop_limit;
++      __u8 ph_nexthdr = 0;
++      int phlen = 0;
++      int optlen = 0;
++
+       int err = -EINVAL;
+ 
+-      if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
++      if (x->sel.family == AF_INET) {
++              /* Inner = IPv4, therefore the IPhdr must be shrunk */
++              /* Inner = 4, Outer = 6 */
++              if (unlikely(proto == IPPROTO_BEETPH)) {
++                      if (!pskb_may_pull(skb, sizeof(*ph)))
++                              goto out;
++                      phlen = ph->hdrlen * 8;
++                      optlen = phlen - ph->padlen - sizeof(*ph);
++
++                      if (optlen < 0 || optlen & 3 || optlen > 250)
++                              goto out;
++                      if (!pskb_may_pull(skb, phlen))
++                              goto out;
++
++                      proto = ph_nexthdr = ph->nexthdr;
++              }
++              skb->nh.raw += delta;
++      }
++
++      if (skb_cloned(skb) &&
++          pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+               goto out;
+ 
+       skb_push(skb, size);
+@@ -71,11 +200,36 @@
+ 
+       skb->mac.raw = memmove(skb->data - skb->mac_len,
+                              skb->mac.raw, skb->mac_len);
+-
+-      ip6h = skb->nh.ipv6h;
+-      ip6h->payload_len = htons(skb->len - size);
+-      ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);
+-      ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6);
++      if (unlikely(phlen)) {
++              skb_pull(skb, phlen - optlen);
++              skb->nh.raw = skb->data;
++      }
++      if (x->sel.family == AF_INET6) {
++              struct ipv6hdr *ip6h = skb->nh.ipv6h;
++              ip6h->payload_len = htons(skb->len - size);
++              ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) 
&x->sel.daddr.a6);
++              ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) 
&x->sel.saddr.a6);
++      } else if (x->sel.family == AF_INET) {
++              struct iphdr *iph = skb->nh.iph;
++              iph->ihl = (sizeof(*iph) + optlen) / 4;
++              iph->version = 4;
++              iph->tos = 0;
++              iph->id = 0;
++              iph->frag_off = 0;
++              iph->ttl = hops;
++              iph->protocol = proto;
++              iph->daddr = x->sel.daddr.a4;
++              iph->saddr = x->sel.saddr.a4;
++              iph->tot_len = htons(skb->len);
++              ip_send_check(iph);
++              skb->protocol = htons(ETH_P_IP);
++              if (unlikely(!optlen)) {
++                      skb->h.raw = skb->nh.raw;
++              }
++              dst_release(skb->dst);
++              skb->dst = NULL;
++      } else
++              BUG_ON(1);
+       err = 0;
+ out:
+       return err;
+diff -urN linux-2.6.20.21/net/ipv6/xfrm6_policy.c 
linux-2.6.20.21-hipl/net/ipv6/xfrm6_policy.c
+--- linux-2.6.20.21/net/ipv6/xfrm6_policy.c    2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_policy.c       2010-03-12 
17:42:24.000000000 +0200
+@@ -24,6 +24,7 @@
+ 
+ static struct dst_ops xfrm6_dst_ops;
+ static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
++static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu);
+ 
+ static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
+ {
+@@ -89,7 +90,7 @@
+ static inline struct in6_addr*
+ __xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr)
+ {
+-      return (x->type->remote_addr) ?
++      return (x->type && x->type->remote_addr) ?
+               (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t 
*)addr) :
+               (struct in6_addr*)&x->id.daddr;
+ }
+@@ -97,7 +98,7 @@
+ static inline struct in6_addr*
+ __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
+ {
+-      return (x->type->local_addr) ?
++      return (x->type && x->type->local_addr) ?
+               (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t 
*)addr) :
+               (struct in6_addr*)&x->props.saddr;
+ }
+@@ -105,7 +106,7 @@
+ static inline void
+ __xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
+ {
+-      if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
++      if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT)
+               *nflen += x->props.header_len;
+       else
+               *len += x->props.header_len;
+@@ -114,7 +115,7 @@
+ static inline void
+ __xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
+ {
+-      if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
++      if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT)
+               *nflen -= x->props.header_len;
+       else
+               *len -= x->props.header_len;
+@@ -131,16 +132,19 @@
+       struct dst_entry *dst, *dst_prev;
+       struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+       struct rt6_info *rt  = rt0;
+-      struct in6_addr *remote = &fl->fl6_dst;
+-      struct in6_addr *local  = &fl->fl6_src;
++      unsigned short outer_family = 0, beet = 0;
+       struct flowi fl_tunnel = {
+               .nl_u = {
+                       .ip6_u = {
+-                              .saddr = *local,
+-                              .daddr = *remote
++                              .saddr = fl->fl6_src,
++                              .daddr = fl->fl6_dst
+                       }
+               }
+       };
++      union {
++              struct in6_addr *in6;
++              struct in_addr *in;
++      } remote, local;
+       int i;
+       int err = 0;
+       int header_len = 0;
+@@ -153,7 +157,6 @@
+       for (i = 0; i < nx; i++) {
+               struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+               struct xfrm_dst *xdst;
+-              int tunnel = 0;
+ 
+               if (unlikely(dst1 == NULL)) {
+                       err = -ENOBUFS;
+@@ -178,18 +181,38 @@
+               dst1->next = dst_prev;
+               dst_prev = dst1;
+               if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
+-                      remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
+-                      local  = __xfrm6_bundle_addr_local(xfrm[i], local);
+-                      tunnel = 1;
++                      outer_family = xfrm[i]->props.family;
++                      beet = (xfrm[i]->props.mode == XFRM_MODE_BEET);
++                      if (outer_family == AF_INET6) {
++                              remote.in6 = 
__xfrm6_bundle_addr_remote(xfrm[i], remote.in6);
++                              local.in6  = __xfrm6_bundle_addr_local(xfrm[i], 
local.in6);
++                      } else if (outer_family == AF_INET) {
++                              remote.in = (struct 
in_addr*)&xfrm[i]->id.daddr.a4;
++                              local.in = (struct 
in_addr*)&xfrm[i]->props.saddr.a4;
++                      } else {
++                              BUG_ON(1);
++                      }
+               }
++
+               __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
+               trailer_len += xfrm[i]->props.trailer_len;
+ 
+-              if (tunnel) {
+-                      ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
+-                      ipv6_addr_copy(&fl_tunnel.fl6_src, local);
++              if (outer_family) {
++                      switch (outer_family) {
++                      default:
++                      case AF_INET6:
++                              ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);
++                              ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);
++                              break;
++                      case AF_INET:
++                              fl_tunnel.fl4_dst = remote.in->s_addr;
++                              fl_tunnel.fl4_src = local.in->s_addr;
++                              fl_tunnel.fl4_tos = 0;
++                              fl_tunnel.fl4_scope = 0;
++                              break;
++                      }
+                       err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
+-                                            &fl_tunnel, AF_INET6);
++                                            &fl_tunnel, outer_family);
+                       if (err)
+                               goto error;
+               } else
+@@ -241,6 +264,12 @@
+       }
+ 
+       xfrm_init_pmtu(dst);
++      if (beet && outer_family == AF_INET) {
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++              u32 mtu = dst_mtu(dst);
++              xfrm6_update_pmtu(dst, mtu + delta);
++      }
++
+       return 0;
+ 
+ error:
+diff -urN linux-2.6.20.21/net/ipv6/xfrm6_state.c 
linux-2.6.20.21-hipl/net/ipv6/xfrm6_state.c
+--- linux-2.6.20.21/net/ipv6/xfrm6_state.c     2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_state.c        2010-03-12 
17:42:24.000000000 +0200
+@@ -98,6 +98,18 @@
+                       src[i] = NULL;
+               }
+       }
++      if (j == n)
++              goto end;
++
++      /* Rule 5: select IPsec BEET */
++      for (i = 0; i < n; i++) {
++              if (src[i] &&
++                  src[i]->props.mode == XFRM_MODE_BEET) {
++                      dst[j++] = src[i];
++                      src[i] = NULL;
++              }
++      }
++
+       if (likely(j == n))
+               goto end;
+ 
+diff -urN linux-2.6.20.21/net/ipv6/xfrm6_tunnel.c 
linux-2.6.20.21-hipl/net/ipv6/xfrm6_tunnel.c
+--- linux-2.6.20.21/net/ipv6/xfrm6_tunnel.c    2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_tunnel.c       2010-03-12 
17:42:24.000000000 +0200
+@@ -5,12 +5,12 @@
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * (at your option) any later version.
+- * 
++ *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+- * 
++ *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+@@ -32,7 +32,7 @@
+ #include <linux/mutex.h>
+ 
+ /*
+- * xfrm_tunnel_spi things are for allocating unique id ("spi") 
++ * xfrm_tunnel_spi things are for allocating unique id ("spi")
+  * per xfrm_address_t.
+  */
+ struct xfrm6_tunnel_spi {
+@@ -70,7 +70,7 @@
+       return h;
+ }
+ 
+-static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi)
++static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi)
+ {
+       return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE;
+ }
+@@ -155,8 +155,8 @@
+ 
+       for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
+               index = xfrm6_tunnel_spi_hash_byspi(spi);
+-              hlist_for_each_entry(x6spi, pos, 
+-                                   &xfrm6_tunnel_spi_byspi[index], 
++              hlist_for_each_entry(x6spi, pos,
++                                   &xfrm6_tunnel_spi_byspi[index],
+                                    list_byspi) {
+                       if (x6spi->spi == spi)
+                               goto try_next_1;
+@@ -167,8 +167,8 @@
+       }
+       for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
+               index = xfrm6_tunnel_spi_hash_byspi(spi);
+-              hlist_for_each_entry(x6spi, pos, 
+-                                   &xfrm6_tunnel_spi_byspi[index], 
++              hlist_for_each_entry(x6spi, pos,
++                                   &xfrm6_tunnel_spi_byspi[index],
+                                    list_byspi) {
+                       if (x6spi->spi == spi)
+                               goto try_next_2;
+@@ -222,7 +222,7 @@
+ 
+       write_lock_bh(&xfrm6_tunnel_spi_lock);
+ 
+-      hlist_for_each_entry_safe(x6spi, pos, n, 
++      hlist_for_each_entry_safe(x6spi, pos, n,
+                                 
&xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
+                                 list_byaddr)
+       {
+@@ -269,9 +269,9 @@
+ {
+       /* xfrm6_tunnel native err handling */
+       switch (type) {
+-      case ICMPV6_DEST_UNREACH: 
++      case ICMPV6_DEST_UNREACH:
+               switch (code) {
+-              case ICMPV6_NOROUTE: 
++              case ICMPV6_NOROUTE:
+               case ICMPV6_ADM_PROHIBITED:
+               case ICMPV6_NOT_NEIGHBOUR:
+               case ICMPV6_ADDR_UNREACH:
+@@ -287,7 +287,7 @@
+               case ICMPV6_EXC_HOPLIMIT:
+                       break;
+               case ICMPV6_EXC_FRAGTIME:
+-              default: 
++              default:
+                       break;
+               }
+               break;
+@@ -307,7 +307,7 @@
+ 
+ static int xfrm6_tunnel_init_state(struct xfrm_state *x)
+ {
+-      if (x->props.mode != XFRM_MODE_TUNNEL)
++      if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != 
XFRM_MODE_BEET)
+               return -EINVAL;
+ 
+       if (x->encap)
+@@ -339,17 +339,29 @@
+       .priority       = 2,
+ };
+ 
++static struct xfrm6_tunnel xfrm46_tunnel_handler = {
++      .handler        = xfrm6_tunnel_rcv,
++      .err_handler    = xfrm6_tunnel_err,
++      .priority       = 2,
++};
++
+ static int __init xfrm6_tunnel_init(void)
+ {
+       if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
+               return -EAGAIN;
+ 
+-      if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
++      if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
++              xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
++              return -EAGAIN;
++      }
++      if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
++              xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+               xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+               return -EAGAIN;
+       }
+       if (xfrm6_tunnel_spi_init() < 0) {
+-              xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
++              xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
++              xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+               xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+               return -EAGAIN;
+       }
+@@ -359,7 +371,8 @@
+ static void __exit xfrm6_tunnel_fini(void)
+ {
+       xfrm6_tunnel_spi_fini();
+-      xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
++      xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
++      xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+       xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+ }
+ 
+diff -urN linux-2.6.20.21/net/xfrm/xfrm_policy.c 
linux-2.6.20.21-hipl/net/xfrm/xfrm_policy.c
+--- linux-2.6.20.21/net/xfrm/xfrm_policy.c     2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/xfrm/xfrm_policy.c        2010-03-12 
17:42:24.000000000 +0200
+@@ -1206,7 +1206,7 @@
+               xfrm_address_t *local  = saddr;
+               struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
+ 
+-              if (tmpl->mode == XFRM_MODE_TUNNEL) {
++              if (tmpl->mode == XFRM_MODE_TUNNEL || tmpl->mode == 
XFRM_MODE_BEET) {
+                       remote = &tmpl->id.daddr;
+                       local = &tmpl->saddr;
+                       family = tmpl->encap_family;
+@@ -1550,7 +1550,7 @@
+             unsigned short family)
+ {
+       if (xfrm_state_kern(x))
+-              return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family);
++              return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, 
tmpl->encap_family);
+       return  x->id.proto == tmpl->id.proto &&
+               (x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
+               (x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
+diff -urN linux-2.6.20.21/net/xfrm/xfrm_state.c 
linux-2.6.20.21-hipl/net/xfrm/xfrm_state.c
+--- linux-2.6.20.21/net/xfrm/xfrm_state.c      2007-10-17 22:31:14.000000000 
+0300
++++ linux-2.6.20.21-hipl/net/xfrm/xfrm_state.c 2010-03-12 17:42:24.000000000 
+0200
+@@ -561,7 +561,7 @@
+                             selector.
+                        */
+                       if (x->km.state == XFRM_STATE_VALID) {
+-                              if (!xfrm_selector_match(&x->sel, fl, family) ||
++                              if (!xfrm_selector_match(&x->sel, fl, 
x->sel.family) ||
+                                   !security_xfrm_state_pol_flow_match(x, pol, 
fl))
+                                       continue;
+                               if (!best ||
+@@ -573,9 +573,10 @@
+                               acquire_in_progress = 1;
+                       } else if (x->km.state == XFRM_STATE_ERROR ||
+                                  x->km.state == XFRM_STATE_EXPIRED) {
+-                              if (xfrm_selector_match(&x->sel, fl, family) &&
+-                                  security_xfrm_state_pol_flow_match(x, pol, 
fl))
++                              if (xfrm_selector_match(&x->sel, fl, 
x->sel.family) &&
++                                  security_xfrm_state_pol_flow_match(x, pol, 
fl)) {
+                                       error = -ESRCH;
++                              }
+                       }
+               }
+       }

=== added file 'patches/kernel/2.6.20/beet-2.6.20.patch'
--- patches/kernel/2.6.20/beet-2.6.20.patch     1970-01-01 00:00:00 +0000
+++ patches/kernel/2.6.20/beet-2.6.20.patch     2010-03-19 09:53:35 +0000
@@ -0,0 +1,1605 @@
+diff -urN linux-2.6.20/include/net/route.h 
linux-2.6.20-hipl/include/net/route.h
+--- linux-2.6.20/include/net/route.h   2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/include/net/route.h      2010-03-12 14:20:22.000000000 
+0200
+@@ -146,7 +146,8 @@
+ 
+ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
+                                  __be32 src, u32 tos, int oif, u8 protocol,
+-                                 __be16 sport, __be16 dport, struct sock *sk)
++                                 __be16 sport, __be16 dport, struct sock *sk,
++                                 int flags)
+ {
+       struct flowi fl = { .oif = oif,
+                           .nl_u = { .ip4_u = { .daddr = dst,
+@@ -168,7 +169,7 @@
+               *rp = NULL;
+       }
+       security_sk_classify_flow(sk, &fl);
+-      return ip_route_output_flow(rp, &fl, sk, 0);
++      return ip_route_output_flow(rp, &fl, sk, flags);
+ }
+ 
+ static inline int ip_route_newports(struct rtable **rp, u8 protocol,
+diff -urN linux-2.6.20/include/net/xfrm.h linux-2.6.20-hipl/include/net/xfrm.h
+--- linux-2.6.20/include/net/xfrm.h    2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/include/net/xfrm.h       2010-03-12 14:20:22.000000000 
+0200
+@@ -237,7 +237,7 @@
+ extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+ extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event 
*c);
+ extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
+-#define XFRM_ACQ_EXPIRES      30
++#define XFRM_ACQ_EXPIRES      3
+ 
+ struct xfrm_tmpl;
+ extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct 
xfrm_policy *pol);
+@@ -929,14 +929,14 @@
+ extern int xfrm_init_state(struct xfrm_state *x);
+ extern int xfrm4_rcv(struct sk_buff *skb);
+ extern int xfrm4_output(struct sk_buff *skb);
+-extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
+-extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
++extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short 
family);
++extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned 
short family);
+ extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi);
+ extern int xfrm6_rcv(struct sk_buff **pskb);
+ extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
+                           xfrm_address_t *saddr, u8 proto);
+-extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler);
+-extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
++extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short 
family);
++extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned 
short family);
+ extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
+ extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
+ extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
+diff -urN linux-2.6.20/net/dccp/ipv4.c linux-2.6.20-hipl/net/dccp/ipv4.c
+--- linux-2.6.20/net/dccp/ipv4.c       2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/dccp/ipv4.c  2010-03-12 14:20:22.000000000 +0200
+@@ -72,7 +72,7 @@
+       tmp = ip_route_connect(&rt, nexthop, inet->saddr,
+                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+                              IPPROTO_DCCP,
+-                             inet->sport, usin->sin_port, sk);
++                             inet->sport, usin->sin_port, sk, 1);
+       if (tmp < 0)
+               return tmp;
+ 
+diff -urN linux-2.6.20/net/dccp/ipv6.c linux-2.6.20-hipl/net/dccp/ipv6.c
+--- linux-2.6.20/net/dccp/ipv6.c       2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/dccp/ipv6.c  2010-03-12 14:20:22.000000000 +0200
+@@ -1041,7 +1041,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      err = xfrm_lookup(&dst, &fl, sk, 0);
++      err = xfrm_lookup(&dst, &fl, sk, 1);
+       if (err < 0)
+               goto failure;
+ 
+diff -urN linux-2.6.20/net/ipv4/af_inet.c linux-2.6.20-hipl/net/ipv4/af_inet.c
+--- linux-2.6.20/net/ipv4/af_inet.c    2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/af_inet.c       2010-03-12 14:20:22.000000000 
+0200
+@@ -1007,7 +1007,7 @@
+                              RT_CONN_FLAGS(sk),
+                              sk->sk_bound_dev_if,
+                              sk->sk_protocol,
+-                             inet->sport, inet->dport, sk);
++                             inet->sport, inet->dport, sk, 0);
+       if (err)
+               return err;
+ 
+diff -urN linux-2.6.20/net/ipv4/datagram.c 
linux-2.6.20-hipl/net/ipv4/datagram.c
+--- linux-2.6.20/net/ipv4/datagram.c   2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/datagram.c      2010-03-12 14:20:22.000000000 
+0200
+@@ -49,7 +49,7 @@
+       err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
+                              RT_CONN_FLAGS(sk), oif,
+                              sk->sk_protocol,
+-                             inet->sport, usin->sin_port, sk);
++                             inet->sport, usin->sin_port, sk, 1);
+       if (err)
+               return err;
+       if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
+diff -urN linux-2.6.20/net/ipv4/esp4.c linux-2.6.20-hipl/net/ipv4/esp4.c
+--- linux-2.6.20/net/ipv4/esp4.c       2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/esp4.c  2010-03-12 14:20:22.000000000 +0200
+@@ -402,6 +402,8 @@
+       x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               x->props.header_len += sizeof(struct iphdr);
++      else if (x->props.mode == XFRM_MODE_BEET)
++              x->props.header_len += IPV4_BEET_PHMAXLEN;
+       if (x->encap) {
+               struct xfrm_encap_tmpl *encap = x->encap;
+ 
+diff -urN linux-2.6.20/net/ipv4/ipip.c linux-2.6.20-hipl/net/ipv4/ipip.c
+--- linux-2.6.20/net/ipv4/ipip.c       2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/ipip.c  2010-03-12 14:20:22.000000000 +0200
+@@ -870,7 +870,7 @@
+ 
+       printk(banner);
+ 
+-      if (xfrm4_tunnel_register(&ipip_handler)) {
++      if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) {
+               printk(KERN_INFO "ipip init: can't register tunnel\n");
+               return -EAGAIN;
+       }
+@@ -892,7 +892,7 @@
+  err2:
+       free_netdev(ipip_fb_tunnel_dev);
+  err1:
+-      xfrm4_tunnel_deregister(&ipip_handler);
++      xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+       goto out;
+ }
+ 
+@@ -912,7 +912,7 @@
+ 
+ static void __exit ipip_fini(void)
+ {
+-      if (xfrm4_tunnel_deregister(&ipip_handler))
++      if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
+               printk(KERN_INFO "ipip close: can't deregister tunnel\n");
+ 
+       rtnl_lock();
+diff -urN linux-2.6.20/net/ipv4/raw.c linux-2.6.20-hipl/net/ipv4/raw.c
+--- linux-2.6.20/net/ipv4/raw.c        2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/raw.c   2010-03-12 14:20:22.000000000 +0200
+@@ -489,7 +489,7 @@
+               }
+ 
+               security_sk_classify_flow(sk, &fl);
+-              err = ip_route_output_flow(&rt, &fl, sk, 
!(msg->msg_flags&MSG_DONTWAIT));
++              err = ip_route_output_flow(&rt, &fl, sk, 1);
+       }
+       if (err)
+               goto done;
+diff -urN linux-2.6.20/net/ipv4/route.c linux-2.6.20-hipl/net/ipv4/route.c
+--- linux-2.6.20/net/ipv4/route.c      2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/route.c 2010-03-12 14:20:22.000000000 +0200
+@@ -108,6 +108,7 @@
+ #ifdef CONFIG_SYSCTL
+ #include <linux/sysctl.h>
+ #endif
++#include <linux/xfrm.h>
+ 
+ #define RT_FL_TOS(oldflp) \
+     ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
+diff -urN linux-2.6.20/net/ipv4/tcp_ipv4.c 
linux-2.6.20-hipl/net/ipv4/tcp_ipv4.c
+--- linux-2.6.20/net/ipv4/tcp_ipv4.c   2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/tcp_ipv4.c      2010-03-12 14:20:22.000000000 
+0200
+@@ -191,7 +191,7 @@
+       tmp = ip_route_connect(&rt, nexthop, inet->saddr,
+                              RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+                              IPPROTO_TCP,
+-                             inet->sport, usin->sin_port, sk);
++                             inet->sport, usin->sin_port, sk, 1);
+       if (tmp < 0)
+               return tmp;
+ 
+diff -urN linux-2.6.20/net/ipv4/tunnel4.c linux-2.6.20-hipl/net/ipv4/tunnel4.c
+--- linux-2.6.20/net/ipv4/tunnel4.c    2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/tunnel4.c       2010-03-12 14:20:22.000000000 
+0200
+@@ -14,9 +14,10 @@
+ #include <net/xfrm.h>
+ 
+ static struct xfrm_tunnel *tunnel4_handlers;
++static struct xfrm_tunnel *tunnel64_handlers;
+ static DEFINE_MUTEX(tunnel4_mutex);
+ 
+-int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
++int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family)
+ {
+       struct xfrm_tunnel **pprev;
+       int ret = -EEXIST;
+@@ -24,7 +25,8 @@
+ 
+       mutex_lock(&tunnel4_mutex);
+ 
+-      for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET) ? &tunnel4_handlers : 
&tunnel64_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if ((*pprev)->priority > priority)
+                       break;
+               if ((*pprev)->priority == priority)
+@@ -44,14 +46,15 @@
+ 
+ EXPORT_SYMBOL(xfrm4_tunnel_register);
+ 
+-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
++int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short 
family)
+ {
+       struct xfrm_tunnel **pprev;
+       int ret = -ENOENT;
+ 
+       mutex_lock(&tunnel4_mutex);
+ 
+-      for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET) ? &tunnel4_handlers : 
&tunnel64_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if (*pprev == handler) {
+                       *pprev = handler->next;
+                       ret = 0;
+@@ -86,6 +89,26 @@
+       return 0;
+ }
+ 
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++static int tunnel64_rcv(struct sk_buff *skb)
++{
++      struct xfrm_tunnel *handler;
++
++      if (!pskb_may_pull(skb, sizeof(struct iphdr)))
++              goto drop;
++
++      for (handler = tunnel64_handlers; handler; handler = handler->next)
++              if (!handler->handler(skb))
++                      return 0;
++
++      icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
++
++drop:
++      kfree_skb(skb);
++      return 0;
++}
++#endif
++
+ static void tunnel4_err(struct sk_buff *skb, u32 info)
+ {
+       struct xfrm_tunnel *handler;
+@@ -101,17 +124,36 @@
+       .no_policy      =       1,
+ };
+ 
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++static struct net_protocol tunnel64_protocol = {
++      .handler        =       tunnel64_rcv,
++      .err_handler    =       tunnel4_err,
++      .no_policy      =       1,
++};
++#endif
++
+ static int __init tunnel4_init(void)
+ {
+       if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) {
+               printk(KERN_ERR "tunnel4 init: can't add protocol\n");
+               return -EAGAIN;
+       }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) {
++              printk(KERN_ERR "tunnel64 init: can't add protocol\n");
++              inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP);
++              return -EAGAIN;
++      }
++#endif
+       return 0;
+ }
+ 
+ static void __exit tunnel4_fini(void)
+ {
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6))
++              printk(KERN_ERR "tunnel64 close: can't remove protocol\n");
++#endif
+       if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP))
+               printk(KERN_ERR "tunnel4 close: can't remove protocol\n");
+ }
+diff -urN linux-2.6.20/net/ipv4/udp.c linux-2.6.20-hipl/net/ipv4/udp.c
+--- linux-2.6.20/net/ipv4/udp.c        2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv4/udp.c   2010-03-12 14:20:22.000000000 +0200
+@@ -629,7 +629,7 @@
+                                              { .sport = inet->sport,
+                                                .dport = dport } } };
+               security_sk_classify_flow(sk, &fl);
+-              err = ip_route_output_flow(&rt, &fl, sk, 
!(msg->msg_flags&MSG_DONTWAIT));
++              err = ip_route_output_flow(&rt, &fl, sk, 1);
+               if (err)
+                       goto out;
+ 
+diff -urN linux-2.6.20/net/ipv4/xfrm4_input.c 
linux-2.6.20-hipl/net/ipv4/xfrm4_input.c
+--- linux-2.6.20/net/ipv4/xfrm4_input.c        2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv4/xfrm4_input.c   2010-03-12 14:26:28.000000000 
+0200
+@@ -106,7 +106,7 @@
+               if (x->mode->input(x, skb))
+                       goto drop;
+ 
+-              if (x->props.mode == XFRM_MODE_TUNNEL) {
++              if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == 
XFRM_MODE_BEET) {
+                       decaps = 1;
+                       break;
+               }
+@@ -136,10 +136,8 @@
+       nf_reset(skb);
+ 
+       if (decaps) {
+-              if (!(skb->dev->flags&IFF_LOOPBACK)) {
+-                      dst_release(skb->dst);
+-                      skb->dst = NULL;
+-              }
++              dst_release(skb->dst);
++              skb->dst = NULL;
+               netif_rx(skb);
+               return 0;
+       } else {
+diff -urN linux-2.6.20/net/ipv4/xfrm4_mode_beet.c 
linux-2.6.20-hipl/net/ipv4/xfrm4_mode_beet.c
+--- linux-2.6.20/net/ipv4/xfrm4_mode_beet.c    2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv4/xfrm4_mode_beet.c       2010-03-12 
14:45:37.000000000 +0200
+@@ -6,6 +6,7 @@
+  *                    Herbert Xu     <herbert@xxxxxxxxxxxxxxxxxxx>
+  *                    Abhinav Pathak <abhinav.pathak@xxxxxxx>
+  *                    Jeff Ahrenholz <ahrenholz@xxxxxxxxx>
++ *                    Joakim Koskela <jookos@xxxxxxxxx>
+  */
+ 
+ #include <linux/init.h>
+@@ -14,54 +15,97 @@
+ #include <linux/skbuff.h>
+ #include <linux/stringify.h>
+ #include <net/dst.h>
++#include <net/dsfield.h>
+ #include <net/ip.h>
++#include <net/inet_ecn.h>
+ #include <net/xfrm.h>
+ 
+-/* Add encapsulation header.
+- *
+- * The top IP header will be constructed per 
draft-nikander-esp-beet-mode-06.txt.
+- * The following fields in it shall be filled in by x->type->output:
+- *      tot_len
+- *      check
+- *
+- * On exit, skb->h will be set to the start of the payload to be processed
+- * by x->type->output and skb->nh will be set to the top IP header.
+- */
+ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+-      struct iphdr *iph, *top_iph = NULL;
+-      int hdrlen, optlen;
++      struct dst_entry *dst = skb->dst;
++      int hdrlen;
++      struct iphdr *iphv4, *top_iphv4;
++      struct ipv6hdr *iphv6, *top_iphv6;
+ 
+-      iph = skb->nh.iph;
+-      skb->h.ipiph = iph;
++      if (skb->nh.iph->version == 4) {
+ 
+-      hdrlen = 0;
+-      optlen = iph->ihl * 4 - sizeof(*iph);
+-      if (unlikely(optlen))
+-              hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
+-
+-      skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen);
+-      top_iph = skb->nh.iph;
+-      hdrlen = iph->ihl * 4 - optlen;
+-      skb->h.raw += hdrlen;
+-
+-      memmove(top_iph, iph, hdrlen);
+-      if (unlikely(optlen)) {
+-              struct ip_beet_phdr *ph;
+-
+-              BUG_ON(optlen < 0);
+-
+-              ph = (struct ip_beet_phdr *)skb->h.raw;
+-              ph->padlen = 4 - (optlen & 4);
+-              ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
+-              ph->nexthdr = top_iph->protocol;
++              int optlen;
+ 
+-              top_iph->protocol = IPPROTO_BEETPH;
+-              top_iph->ihl = sizeof(struct iphdr) / 4;
+-      }
++              /* 4-4 */
++
++              iphv4 = skb->nh.iph;
++              skb->h.ipiph = iphv4;
++
++              hdrlen = x->props.header_len;
++
++              optlen = iphv4->ihl * 4 - sizeof(*iphv4);
++
++              if (!optlen) {
++                      hdrlen -= IPV4_BEET_PHMAXLEN;
++              } else {
++                      skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));
++                      hdrlen -= optlen & 4;
++              }
++
++              skb->nh.raw = skb_push(skb, hdrlen);
++
++              top_iphv4 = skb->nh.iph;
++              hdrlen = iphv4->ihl * 4 - optlen;
++              skb->h.raw += hdrlen;
++              memmove(top_iphv4, iphv4, hdrlen);
++
++              if (unlikely(optlen)) {
++                      struct ip_beet_phdr *ph;
++
++                      BUG_ON(optlen < 0);
++
++                      ph = (struct ip_beet_phdr *)skb->h.raw;
++                      ph->padlen = 4 - (optlen & 4);
++                      ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
++                      ph->nexthdr = iphv4->protocol;
++                      top_iphv4->protocol = IPPROTO_BEETPH;
++                      top_iphv4->ihl = sizeof(struct iphdr) / 4;
++              }
++
++              top_iphv4->saddr = x->props.saddr.a4;
++              top_iphv4->daddr = x->id.daddr.a4;
++
++              skb->protocol = htons(ETH_P_IP);
++
++      } else if (skb->nh.iph->version == 6) {
++
++              u8 protocol;
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++
++              /* Inner = 6, Outer = 4 : changing the external IP hdr
++               * to the outer addresses
++               */
++
++              hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;
++              skb_push(skb, hdrlen);
++              iphv6 = skb->nh.ipv6h;
++
++              skb->nh.raw = skb->data;
++              top_iphv6 = skb->nh.ipv6h;
++
++              protocol = iphv6->nexthdr;
++              skb->nh.raw = skb_pull(skb, delta);
++              top_iphv4 = skb->nh.iph;
++              skb->h.raw = skb->data + hdrlen;
++              top_iphv4->ihl = (sizeof(struct iphdr) >> 2);
++              top_iphv4->version = 4;
++              top_iphv4->id = 0;
++              top_iphv4->frag_off = htons(IP_DF);
++              top_iphv4->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
++              top_iphv4->saddr = x->props.saddr.a4;
++              top_iphv4->daddr = x->id.daddr.a4;
++              skb->h.raw += top_iphv4->ihl*4;
++              top_iphv4->protocol = protocol;
++
++              skb->protocol = htons(ETH_P_IP);
++      } else
++              BUG_ON(1);
+ 
+-      top_iph->saddr = x->props.saddr.a4;
+-      top_iph->daddr = x->id.daddr.a4;
+ 
+       return 0;
+ }
+@@ -69,45 +113,73 @@
+ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+       struct iphdr *iph = skb->nh.iph;
++      int hops = skb->nh.iph->ttl;
+       int phlen = 0;
+       int optlen = 0;
++      int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : 
sizeof(struct ipv6hdr);
++      int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
+       __u8 ph_nexthdr = 0, protocol = 0;
+       int err = -EINVAL;
+ 
+       protocol = iph->protocol;
+ 
+-      if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
+-              struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1);
++      if (x->sel.family == AF_INET6) {
++              /* Here, the inner family is 6, therefore I have to
++               * substitute the IPhdr by enlarging it */
++              if (skb_tailroom(skb) <  delta){
++                      if (pskb_expand_head(skb, 0, delta, GFP_ATOMIC))
++                              goto out;
++              }
++              skb->nh.raw -= delta;
++      } else if (x->sel.family == AF_INET) {
++              if (unlikely(iph->protocol == IPPROTO_BEETPH)) {
++                      struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 
1);
++
++                      if (!pskb_may_pull(skb, sizeof(*ph)))
++                              goto out;
++
++                      phlen = ph->hdrlen * 8;
++                      optlen = phlen - ph->padlen - sizeof(*ph);
++                      if (optlen < 0 || optlen & 3 || optlen > 250)
++                              goto out;
++
++                      if (!pskb_may_pull(skb, phlen))
++                              goto out;
++
++                      ph_nexthdr = ph->nexthdr;
++              }
++      } else
++              BUG_ON(1);
+ 
+-              if (!pskb_may_pull(skb, sizeof(*ph)))
+-                      goto out;
+-
+-              phlen = ph->hdrlen * 8;
+-              optlen = phlen - ph->padlen - sizeof(*ph);
+-              if (optlen < 0 || optlen & 3 || optlen > 250)
+-                      goto out;
+-
+-              if (!pskb_may_pull(skb, phlen))
+-                      goto out;
+-
+-              ph_nexthdr = ph->nexthdr;
+-      }
+-
+-      skb_push(skb, sizeof(*iph) - phlen + optlen);
++      size += (optlen - phlen);
++      skb_push(skb, size);
+       memmove(skb->data, skb->nh.raw, sizeof(*iph));
+       skb->nh.raw = skb->data;
+ 
+-      iph = skb->nh.iph;
+-      iph->ihl = (sizeof(*iph) + optlen) / 4;
+-      iph->tot_len = htons(skb->len);
+-      iph->daddr = x->sel.daddr.a4;
+-      iph->saddr = x->sel.saddr.a4;
+-      if (ph_nexthdr)
+-              iph->protocol = ph_nexthdr;
+-      else
+-              iph->protocol = protocol;
+-      iph->check = 0;
+-      iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
++      if (x->sel.family == AF_INET) {
++              iph = skb->nh.iph;
++              iph->ihl = (sizeof(*iph) + optlen) / 4;
++              iph->tot_len = htons(skb->len);
++              iph->daddr = x->sel.daddr.a4;
++              iph->saddr = x->sel.saddr.a4;
++              if (ph_nexthdr)
++                      iph->protocol = ph_nexthdr;
++              else
++                      iph->protocol = protocol;
++              iph->check = 0;
++              iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
++      } else if (x->sel.family == AF_INET6) {
++              struct ipv6hdr *ip6h = skb->nh.ipv6h;
++              memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl));
++              ip6h->version = 6;
++              ip6h->priority = 0;
++              ip6h->nexthdr = protocol;
++              ip6h->hop_limit = hops;
++              ip6h->payload_len = htons(skb->len - size);
++              ipv6_addr_copy(&ip6h->daddr, (struct in6_addr 
*)&x->sel.daddr.a6);
++              ipv6_addr_copy(&ip6h->saddr, (struct in6_addr 
*)&x->sel.saddr.a6);
++              skb->protocol = htons(ETH_P_IPV6);
++      }
+       err = 0;
+ out:
+       return err;
+diff -urN linux-2.6.20/net/ipv4/xfrm4_mode_tunnel.c 
linux-2.6.20-hipl/net/ipv4/xfrm4_mode_tunnel.c
+--- linux-2.6.20/net/ipv4/xfrm4_mode_tunnel.c  2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv4/xfrm4_mode_tunnel.c     2010-03-12 
14:32:11.000000000 +0200
+@@ -66,6 +66,8 @@
+       top_iph->daddr = x->id.daddr.a4;
+       top_iph->protocol = IPPROTO_IPIP;
+ 
++      skb->protocol = htons(ETH_P_IP);
++
+       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+       return 0;
+ }
+diff -urN linux-2.6.20/net/ipv4/xfrm4_policy.c 
linux-2.6.20-hipl/net/ipv4/xfrm4_policy.c
+--- linux-2.6.20/net/ipv4/xfrm4_policy.c       2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv4/xfrm4_policy.c  2010-03-12 14:32:35.000000000 
+0200
+@@ -15,6 +15,7 @@
+ 
+ static struct dst_ops xfrm4_dst_ops;
+ static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
++static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu);
+ 
+ static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
+ {
+@@ -72,17 +73,20 @@
+       struct dst_entry *dst, *dst_prev;
+       struct rtable *rt0 = (struct rtable*)(*dst_p);
+       struct rtable *rt = rt0;
+-      __be32 remote = fl->fl4_dst;
+-      __be32 local  = fl->fl4_src;
+       struct flowi fl_tunnel = {
+               .nl_u = {
+                       .ip4_u = {
+-                              .saddr = local,
+-                              .daddr = remote,
++                              .saddr = fl->fl4_src,
++                              .daddr = fl->fl4_dst,
+                               .tos = fl->fl4_tos
+                       }
+               }
+       };
++      union {
++              struct in6_addr *in6;
++              struct in_addr *in;
++      } remote, local;
++      unsigned short outer_family6 = 0;
+       int i;
+       int err;
+       int header_len = 0;
+@@ -94,7 +98,7 @@
+       for (i = 0; i < nx; i++) {
+               struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
+               struct xfrm_dst *xdst;
+-              int tunnel = 0;
++              unsigned short outer_family = 0;
+ 
+               if (unlikely(dst1 == NULL)) {
+                       err = -ENOBUFS;
+@@ -117,20 +121,41 @@
+               dst1->next = dst_prev;
+               dst_prev = dst1;
+               if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
+-                      remote = xfrm[i]->id.daddr.a4;
+-                      local  = xfrm[i]->props.saddr.a4;
+-                      tunnel = 1;
++                      outer_family = xfrm[i]->props.family;
++                      if(outer_family == AF_INET){
++                              remote.in = (struct 
in_addr*)&xfrm[i]->id.daddr.a4;
++                              local.in  = (struct 
in_addr*)&xfrm[i]->props.saddr.a4;
++                      } else if (outer_family == AF_INET6){
++                              outer_family6 = 1;
++                              remote.in6 = (struct 
in6_addr*)xfrm[i]->id.daddr.a6;
++                              local.in6 = (struct 
in6_addr*)xfrm[i]->props.saddr.a6;
++                      } else
++                                BUG_ON(1);
+               }
+               header_len += xfrm[i]->props.header_len;
+               trailer_len += xfrm[i]->props.trailer_len;
+ 
+-              if (tunnel) {
+-                      fl_tunnel.fl4_src = local;
+-                      fl_tunnel.fl4_dst = remote;
++              if (outer_family) {
++                      switch (outer_family) {
++                      default:
++                      case AF_INET:
++                              fl_tunnel.fl4_src = local.in->s_addr;
++                              fl_tunnel.fl4_dst = remote.in->s_addr;
++                              break;
++                      case AF_INET6:
++                              ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);
++                              ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);
++                              break;
++                      }
+                       err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
+-                                            &fl_tunnel, AF_INET);
++                                            &fl_tunnel, outer_family);
+                       if (err)
+                               goto error;
++                      /* Without this, the atomic inc below segfaults */
++                      if (outer_family == AF_INET6) {
++                              rt->peer = NULL;
++                              rt_bind_peer(rt,1);
++                      }
+               } else
+                       dst_hold(&rt->u.dst);
+       }
+@@ -181,6 +206,12 @@
+       }
+ 
+       xfrm_init_pmtu(dst);
++      if (outer_family6) {
++              /* The worst case */
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++              u32 mtu = dst_mtu(dst);
++              xfrm4_update_pmtu(dst, mtu - delta);
++      }
+       return 0;
+ 
+ error:
+diff -urN linux-2.6.20/net/ipv4/xfrm4_tunnel.c 
linux-2.6.20-hipl/net/ipv4/xfrm4_tunnel.c
+--- linux-2.6.20/net/ipv4/xfrm4_tunnel.c       2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv4/xfrm4_tunnel.c  2010-03-12 14:33:28.000000000 
+0200
+@@ -13,7 +13,7 @@
+ static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+       struct iphdr *iph;
+-      
++
+       iph = skb->nh.iph;
+       iph->tot_len = htons(skb->len);
+       ip_send_check(iph);
+@@ -28,7 +28,7 @@
+ 
+ static int ipip_init_state(struct xfrm_state *x)
+ {
+-      if (x->props.mode != XFRM_MODE_TUNNEL)
++      if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != 
XFRM_MODE_BEET)
+               return -EINVAL;
+ 
+       if (x->encap)
+@@ -64,24 +64,45 @@
+       .priority       =       2,
+ };
+ 
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++static struct xfrm_tunnel xfrm64_tunnel_handler = {
++      .handler        =       xfrm4_rcv,
++      .err_handler    =       xfrm_tunnel_err,
++      .priority       =       2,
++};
++#endif
++
+ static int __init ipip_init(void)
+ {
+       if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
+               printk(KERN_INFO "ipip init: can't add xfrm type\n");
+               return -EAGAIN;
+       }
+-      if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) {
+-              printk(KERN_INFO "ipip init: can't add xfrm handler\n");
++
++      if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) {
++              printk(KERN_INFO "ipip init: can't add xfrm handler for 
AF_INET\n");
++              xfrm_unregister_type(&ipip_type, AF_INET);
++              return -EAGAIN;
++      }
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) {
++              printk(KERN_INFO "ipip init: can't add xfrm handler for 
AF_INET6\n");
++              xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET);
+               xfrm_unregister_type(&ipip_type, AF_INET);
+               return -EAGAIN;
+       }
++#endif
+       return 0;
+ }
+ 
+ static void __exit ipip_fini(void)
+ {
+-      if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler))
+-              printk(KERN_INFO "ipip close: can't remove xfrm handler\n");
++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
++      if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6))
++              printk(KERN_INFO "ipip close: can't remove xfrm handler for 
AF_INET6\n");
++#endif
++      if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET))
++              printk(KERN_INFO "ipip close: can't remove xfrm handler for 
AF_INET\n");
+       if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
+               printk(KERN_INFO "ipip close: can't remove xfrm type\n");
+ }
+diff -urN linux-2.6.20/net/ipv6/datagram.c 
linux-2.6.20-hipl/net/ipv6/datagram.c
+--- linux-2.6.20/net/ipv6/datagram.c   2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/datagram.c      2010-03-12 14:20:22.000000000 
+0200
+@@ -178,7 +178,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto out;
+ 
+       /* source address lookup done in ip6_dst_lookup */
+diff -urN linux-2.6.20/net/ipv6/esp6.c linux-2.6.20-hipl/net/ipv6/esp6.c
+--- linux-2.6.20/net/ipv6/esp6.c       2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/esp6.c  2010-03-12 14:20:22.000000000 +0200
+@@ -240,9 +240,9 @@
+ static u32 esp6_get_max_size(struct xfrm_state *x, int mtu)
+ {
+       struct esp_data *esp = x->data;
+-      u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4);
++      u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4);
+ 
+-      if (x->props.mode == XFRM_MODE_TUNNEL) {
++      if (x->props.mode) {
+               mtu = ALIGN(mtu + 2, blksize);
+       } else {
+               /* The worst case. */
+@@ -365,6 +365,8 @@
+       x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
+       if (x->props.mode == XFRM_MODE_TUNNEL)
+               x->props.header_len += sizeof(struct ipv6hdr);
++      else if (x->props.mode == XFRM_MODE_BEET)
++              x->props.header_len += IPV4_BEET_PHMAXLEN;
+       x->data = esp;
+       return 0;
+ 
+diff -urN linux-2.6.20/net/ipv6/icmp.c linux-2.6.20-hipl/net/ipv6/icmp.c
+--- linux-2.6.20/net/ipv6/icmp.c       2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/icmp.c  2010-03-12 14:20:22.000000000 +0200
+@@ -64,6 +64,7 @@
+ #include <net/ip6_route.h>
+ #include <net/addrconf.h>
+ #include <net/icmp.h>
++#include <linux/xfrm.h>
+ 
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+diff -urN linux-2.6.20/net/ipv6/ip6_tunnel.c 
linux-2.6.20-hipl/net/ipv6/ip6_tunnel.c
+--- linux-2.6.20/net/ipv6/ip6_tunnel.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/ip6_tunnel.c    2010-03-12 14:20:22.000000000 
+0200
+@@ -1127,7 +1127,7 @@
+ {
+       int  err;
+ 
+-      if (xfrm6_tunnel_register(&ip6ip6_handler)) {
++      if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) {
+               printk(KERN_ERR "ip6ip6 init: can't register tunnel\n");
+               return -EAGAIN;
+       }
+@@ -1146,7 +1146,7 @@
+       }
+       return 0;
+ fail:
+-      xfrm6_tunnel_deregister(&ip6ip6_handler);
++      xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
+       return err;
+ }
+ 
+@@ -1170,7 +1170,7 @@
+ 
+ static void __exit ip6_tunnel_cleanup(void)
+ {
+-      if (xfrm6_tunnel_deregister(&ip6ip6_handler))
++      if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6))
+               printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n");
+ 
+       rtnl_lock();
+diff -urN linux-2.6.20/net/ipv6/raw.c linux-2.6.20-hipl/net/ipv6/raw.c
+--- linux-2.6.20/net/ipv6/raw.c        2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/raw.c   2010-03-12 14:20:22.000000000 +0200
+@@ -815,7 +815,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto out;
+ 
+       if (hlimit < 0) {
+diff -urN linux-2.6.20/net/ipv6/tcp_ipv6.c 
linux-2.6.20-hipl/net/ipv6/tcp_ipv6.c
+--- linux-2.6.20/net/ipv6/tcp_ipv6.c   2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/tcp_ipv6.c      2010-03-12 14:20:22.000000000 
+0200
+@@ -265,7 +265,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto failure;
+ 
+       if (saddr == NULL) {
+diff -urN linux-2.6.20/net/ipv6/tunnel6.c linux-2.6.20-hipl/net/ipv6/tunnel6.c
+--- linux-2.6.20/net/ipv6/tunnel6.c    2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/tunnel6.c       2010-03-12 14:20:22.000000000 
+0200
+@@ -30,9 +30,10 @@
+ #include <net/xfrm.h>
+ 
+ static struct xfrm6_tunnel *tunnel6_handlers;
++static struct xfrm6_tunnel *tunnel46_handlers;
+ static DEFINE_MUTEX(tunnel6_mutex);
+ 
+-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler)
++int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family)
+ {
+       struct xfrm6_tunnel **pprev;
+       int ret = -EEXIST;
+@@ -40,7 +41,8 @@
+ 
+       mutex_lock(&tunnel6_mutex);
+ 
+-      for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET6) ? &tunnel6_handlers : 
&tunnel46_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if ((*pprev)->priority > priority)
+                       break;
+               if ((*pprev)->priority == priority)
+@@ -60,14 +62,15 @@
+ 
+ EXPORT_SYMBOL(xfrm6_tunnel_register);
+ 
+-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler)
++int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short 
family)
+ {
+       struct xfrm6_tunnel **pprev;
+       int ret = -ENOENT;
+ 
+       mutex_lock(&tunnel6_mutex);
+ 
+-      for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) {
++      for (pprev = (family == AF_INET6) ? &tunnel6_handlers : 
&tunnel46_handlers;
++           *pprev; pprev = &(*pprev)->next) {
+               if (*pprev == handler) {
+                       *pprev = handler->next;
+                       ret = 0;
+@@ -103,6 +106,25 @@
+       return 0;
+ }
+ 
++static int tunnel46_rcv(struct sk_buff **pskb)
++{
++      struct sk_buff *skb = *pskb;
++      struct xfrm6_tunnel *handler;
++
++      if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
++              goto drop;
++
++      for (handler = tunnel46_handlers; handler; handler = handler->next)
++              if (!handler->handler(skb))
++                      return 0;
++
++      icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev);
++
++drop:
++      kfree_skb(skb);
++      return 0;
++}
++
+ static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+                       int type, int code, int offset, __be32 info)
+ {
+@@ -119,17 +141,30 @@
+       .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
+ };
+ 
++static struct inet6_protocol tunnel46_protocol = {
++      .handler        = tunnel46_rcv,
++      .err_handler    = tunnel6_err,
++      .flags          = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
++};
++
+ static int __init tunnel6_init(void)
+ {
+       if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) {
+               printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
+               return -EAGAIN;
+       }
++      if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) {
++              printk(KERN_ERR "tunnel6 init(): can't add protocol\n");
++              inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6);
++              return -EAGAIN;
++      }
+       return 0;
+ }
+ 
+ static void __exit tunnel6_fini(void)
+ {
++      if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP))
++              printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+       if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6))
+               printk(KERN_ERR "tunnel6 close: can't remove protocol\n");
+ }
+diff -urN linux-2.6.20/net/ipv6/udp.c linux-2.6.20-hipl/net/ipv6/udp.c
+--- linux-2.6.20/net/ipv6/udp.c        2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/ipv6/udp.c   2010-03-12 14:20:22.000000000 +0200
+@@ -736,7 +736,7 @@
+       if (final_p)
+               ipv6_addr_copy(&fl.fl6_dst, final_p);
+ 
+-      if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
++      if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0)
+               goto out;
+ 
+       if (hlimit < 0) {
+diff -urN linux-2.6.20/net/ipv6/xfrm6_input.c 
linux-2.6.20-hipl/net/ipv6/xfrm6_input.c
+--- linux-2.6.20/net/ipv6/xfrm6_input.c        2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv6/xfrm6_input.c   2010-03-12 14:34:37.000000000 
+0200
+@@ -72,7 +72,7 @@
+               if (x->mode->input(x, skb))
+                       goto drop;
+ 
+-              if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */
++              if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == 
XFRM_MODE_BEET) { /* XXX */
+                       decaps = 1;
+                       break;
+               }
+@@ -103,10 +103,8 @@
+       nf_reset(skb);
+ 
+       if (decaps) {
+-              if (!(skb->dev->flags&IFF_LOOPBACK)) {
+-                      dst_release(skb->dst);
+-                      skb->dst = NULL;
+-              }
++              dst_release(skb->dst);
++              skb->dst = NULL;
+               netif_rx(skb);
+               return -1;
+       } else {
+diff -urN linux-2.6.20/net/ipv6/xfrm6_mode_beet.c 
linux-2.6.20-hipl/net/ipv6/xfrm6_mode_beet.c
+--- linux-2.6.20/net/ipv6/xfrm6_mode_beet.c    2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv6/xfrm6_mode_beet.c       2010-03-12 
14:46:23.000000000 +0200
+@@ -6,6 +6,7 @@
+  *                    Herbert Xu     <herbert@xxxxxxxxxxxxxxxxxxx>
+  *                    Abhinav Pathak <abhinav.pathak@xxxxxxx>
+  *                    Jeff Ahrenholz <ahrenholz@xxxxxxxxx>
++ *                    Joakim Koskela <jookos@xxxxxxxxx>
+  */
+ 
+ #include <linux/init.h>
+@@ -16,6 +17,7 @@
+ #include <net/dsfield.h>
+ #include <net/dst.h>
+ #include <net/inet_ecn.h>
++#include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/xfrm.h>
+ 
+@@ -31,38 +33,165 @@
+  * its absence, that of the top IP header.  The value of skb->data will always
+  * point to the top IP header.
+  */
++/* Add encapsulation header.
++ *
++ * The top IP header will be constructed per 
draft-nikander-esp-beet-mode-06.txt.
++ * The following fields in it shall be filled in by x->type->output:
++ *      tot_len
++ *      check
++ *
++ * On exit, skb->h will be set to the start of the payload to be processed
++ * by x->type->output and skb->nh will be set to the top IP header.
++ */
+ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+-      struct ipv6hdr *iph, *top_iph;
+-      u8 *prevhdr;
+-      int hdr_len;
+-
+-      skb_push(skb, x->props.header_len);
+-      iph = skb->nh.ipv6h;
+-
+-      hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+-      skb->nh.raw = prevhdr - x->props.header_len;
+-      skb->h.raw = skb->data + hdr_len;
+-      memmove(skb->data, iph, hdr_len);
+ 
+-      skb->nh.raw = skb->data;
+-      top_iph = skb->nh.ipv6h;
+-      skb->nh.raw = &top_iph->nexthdr;
+-      skb->h.ipv6h = top_iph + 1;
+-
+-      ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+-      ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
++      struct dst_entry *dst = skb->dst;
++      int hdrlen;
++      struct iphdr *iphv4, *top_iphv4;
++      struct ipv6hdr *iphv6, *top_iphv6;
++
++      if (skb->nh.iph->version == 6) {
++
++              u8 *prevhdr;
++              int hdr_len;
++
++/* 6-6 */
++
++              hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN;
++              skb_push(skb, hdrlen);
++              iphv6 = skb->nh.ipv6h;
++
++              hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
++              skb->nh.raw = prevhdr - hdrlen;
++              skb->h.raw = skb->data + hdr_len;
++              memmove(skb->data, iphv6, hdr_len);
++
++              skb->nh.raw = skb->data;
++              top_iphv6 = skb->nh.ipv6h;
++              skb->nh.raw = &top_iphv6->nexthdr;
++              skb->h.ipv6h = top_iphv6 + 1;
++              ipv6_addr_copy(&top_iphv6->saddr, (struct in6_addr 
*)&x->props.saddr);
++              ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr 
*)&x->id.daddr);
++
++              skb->protocol = htons(ETH_P_IPV6);
++
++      } else if (skb->nh.iph->version == 4) {
++
++              int flags;
++              int optlen;
++              int dsfield;
++              u8 protocol;
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++
++              /* Inner = 4, Outer = 6*/
++
++              iphv4 = skb->nh.iph;
++              skb->h.ipiph = iphv4;
++
++              hdrlen = x->props.header_len;
++
++              optlen = iphv4->ihl * 4 - sizeof(*iphv4);
++
++              if (!optlen) {
++                      hdrlen -= IPV4_BEET_PHMAXLEN;
++              } else {
++                      skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4));
++                      hdrlen -= optlen & 4;
++              }
++
++              skb->nh.raw = skb_push(skb, hdrlen);
++
++              top_iphv4 = skb->nh.iph;
++              hdrlen = iphv4->ihl * 4 - optlen;
++              skb->h.raw += hdrlen;
++              if (unlikely(optlen)) {
++                      struct ip_beet_phdr *ph;
++
++                      BUG_ON(optlen < 0);
++
++                      ph = (struct ip_beet_phdr *)skb->h.raw;
++                      ph->padlen = 4 - (optlen & 4);
++                      ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8;
++                      ph->nexthdr = iphv4->protocol;
++                      top_iphv4->protocol = IPPROTO_BEETPH;
++                      top_iphv4->ihl = sizeof(struct iphdr) / 4;
++              }
++
++              if (unlikely(optlen))
++                      protocol = top_iphv4->protocol;
++              else
++                      protocol = iphv4->protocol;
++
++              if (skb_headroom(skb) <=  2*delta){
++                      if (pskb_expand_head(skb, delta,0, GFP_ATOMIC))
++                              return -ENOMEM;
++              }
++
++              skb->nh.raw = skb_push(skb, delta);
++
++              top_iphv6 = skb->nh.ipv6h;
++              skb->h.ipv6h = top_iphv6 + 1;
++              /* DS disclosed */
++              top_iphv6->version = 6;
++              top_iphv6->priority = 0;
++              top_iphv6->flow_lbl[0] = 0;
++              top_iphv6->flow_lbl[1] = 0;
++              top_iphv6->flow_lbl[2] = 0;
++              dsfield = ipv6_get_dsfield(top_iphv6);
++              dsfield = INET_ECN_encapsulate(dsfield, dsfield);
++              flags = x->props.flags;
++              if (flags & XFRM_STATE_NOECN)
++                      dsfield &= ~INET_ECN_MASK;
++              ipv6_change_dsfield(top_iphv6, 0, dsfield);
++
++              top_iphv6->nexthdr = protocol;
++              top_iphv6->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
++              top_iphv6->payload_len = htons(skb->len - sizeof(struct 
ipv6hdr));
++              ipv6_addr_copy(&top_iphv6->saddr,(struct in6_addr 
*)&x->props.saddr);
++              ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr 
*)&x->id.daddr);
++              skb->nh.raw = &top_iphv6->nexthdr;
++
++              skb->protocol = htons(ETH_P_IPV6);
++      } else
++              BUG_ON(1);
+ 
+       return 0;
+ }
+ 
+ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+-      struct ipv6hdr *ip6h;
+-      int size = sizeof(struct ipv6hdr);
++      struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->h.raw);
++      int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : 
sizeof(struct ipv6hdr);
++      int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++      __u8 proto = skb->nh.ipv6h->nexthdr, hops = skb->nh.ipv6h->hop_limit;
++      __u8 ph_nexthdr = 0;
++      int phlen = 0;
++      int optlen = 0;
++
+       int err = -EINVAL;
+ 
+-      if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
++      if (x->sel.family == AF_INET) {
++              /* Inner = IPv4, therefore the IPhdr must be shrunk */
++              /* Inner = 4, Outer = 6 */
++              if (unlikely(proto == IPPROTO_BEETPH)) {
++                      if (!pskb_may_pull(skb, sizeof(*ph)))
++                              goto out;
++                      phlen = ph->hdrlen * 8;
++                      optlen = phlen - ph->padlen - sizeof(*ph);
++
++                      if (optlen < 0 || optlen & 3 || optlen > 250)
++                              goto out;
++                      if (!pskb_may_pull(skb, phlen))
++                              goto out;
++
++                      proto = ph_nexthdr = ph->nexthdr;
++              }
++              skb->nh.raw += delta;
++      }
++
++      if (skb_cloned(skb) &&
++          pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+               goto out;
+ 
+       skb_push(skb, size);
+@@ -71,11 +200,36 @@
+ 
+       skb->mac.raw = memmove(skb->data - skb->mac_len,
+                              skb->mac.raw, skb->mac_len);
+-
+-      ip6h = skb->nh.ipv6h;
+-      ip6h->payload_len = htons(skb->len - size);
+-      ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6);
+-      ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6);
++      if (unlikely(phlen)) {
++              skb_pull(skb, phlen - optlen);
++              skb->nh.raw = skb->data;
++      }
++      if (x->sel.family == AF_INET6) {
++              struct ipv6hdr *ip6h = skb->nh.ipv6h;
++              ip6h->payload_len = htons(skb->len - size);
++              ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) 
&x->sel.daddr.a6);
++              ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) 
&x->sel.saddr.a6);
++      } else if (x->sel.family == AF_INET) {
++              struct iphdr *iph = skb->nh.iph;
++              iph->ihl = (sizeof(*iph) + optlen) / 4;
++              iph->version = 4;
++              iph->tos = 0;
++              iph->id = 0;
++              iph->frag_off = 0;
++              iph->ttl = hops;
++              iph->protocol = proto;
++              iph->daddr = x->sel.daddr.a4;
++              iph->saddr = x->sel.saddr.a4;
++              iph->tot_len = htons(skb->len);
++              ip_send_check(iph);
++              skb->protocol = htons(ETH_P_IP);
++              if (unlikely(!optlen)) {
++                      skb->h.raw = skb->nh.raw;
++              }
++              dst_release(skb->dst);
++              skb->dst = NULL;
++      } else
++              BUG_ON(1);
+       err = 0;
+ out:
+       return err;
+diff -urN linux-2.6.20/net/ipv6/xfrm6_mode_tunnel.c 
linux-2.6.20-hipl/net/ipv6/xfrm6_mode_tunnel.c
+--- linux-2.6.20/net/ipv6/xfrm6_mode_tunnel.c  2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv6/xfrm6_mode_tunnel.c     2010-03-12 
14:36:47.000000000 +0200
+@@ -65,6 +65,8 @@
+       top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
+       ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+       ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
++      skb->protocol = htons(ETH_P_IPV6);
++
+       return 0;
+ }
+ 
+diff -urN linux-2.6.20/net/ipv6/xfrm6_policy.c 
linux-2.6.20-hipl/net/ipv6/xfrm6_policy.c
+--- linux-2.6.20/net/ipv6/xfrm6_policy.c       2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv6/xfrm6_policy.c  2010-03-12 14:38:03.000000000 
+0200
+@@ -24,6 +24,7 @@
+ 
+ static struct dst_ops xfrm6_dst_ops;
+ static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
++static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu);
+ 
+ static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl)
+ {
+@@ -89,7 +90,7 @@
+ static inline struct in6_addr*
+ __xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr)
+ {
+-      return (x->type->remote_addr) ?
++      return (x->type && x->type->remote_addr) ?
+               (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t 
*)addr) :
+               (struct in6_addr*)&x->id.daddr;
+ }
+@@ -97,7 +98,7 @@
+ static inline struct in6_addr*
+ __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr)
+ {
+-      return (x->type->local_addr) ?
++      return (x->type && x->type->local_addr) ?
+               (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t 
*)addr) :
+               (struct in6_addr*)&x->props.saddr;
+ }
+@@ -105,7 +106,7 @@
+ static inline void
+ __xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x)
+ {
+-      if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
++      if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT)
+               *nflen += x->props.header_len;
+       else
+               *len += x->props.header_len;
+@@ -114,7 +115,7 @@
+ static inline void
+ __xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x)
+ {
+-      if (x->type->flags & XFRM_TYPE_NON_FRAGMENT)
++      if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT)
+               *nflen -= x->props.header_len;
+       else
+               *len -= x->props.header_len;
+@@ -131,16 +132,19 @@
+       struct dst_entry *dst, *dst_prev;
+       struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
+       struct rt6_info *rt  = rt0;
+-      struct in6_addr *remote = &fl->fl6_dst;
+-      struct in6_addr *local  = &fl->fl6_src;
++      unsigned short outer_family = 0, beet = 0;
+       struct flowi fl_tunnel = {
+               .nl_u = {
+                       .ip6_u = {
+-                              .saddr = *local,
+-                              .daddr = *remote
++                              .saddr = fl->fl6_src,
++                              .daddr = fl->fl6_dst
+                       }
+               }
+       };
++      union {
++              struct in6_addr *in6;
++              struct in_addr *in;
++      } remote, local;
+       int i;
+       int err = 0;
+       int header_len = 0;
+@@ -153,7 +157,6 @@
+       for (i = 0; i < nx; i++) {
+               struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+               struct xfrm_dst *xdst;
+-              int tunnel = 0;
+ 
+               if (unlikely(dst1 == NULL)) {
+                       err = -ENOBUFS;
+@@ -178,18 +181,38 @@
+               dst1->next = dst_prev;
+               dst_prev = dst1;
+               if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
+-                      remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
+-                      local  = __xfrm6_bundle_addr_local(xfrm[i], local);
+-                      tunnel = 1;
++                      outer_family = xfrm[i]->props.family;
++                      beet = (xfrm[i]->props.mode == XFRM_MODE_BEET);
++                      if (outer_family == AF_INET6) {
++                              remote.in6 = 
__xfrm6_bundle_addr_remote(xfrm[i], remote.in6);
++                              local.in6  = __xfrm6_bundle_addr_local(xfrm[i], 
local.in6);
++                      } else if (outer_family == AF_INET) {
++                              remote.in = (struct 
in_addr*)&xfrm[i]->id.daddr.a4;
++                              local.in = (struct 
in_addr*)&xfrm[i]->props.saddr.a4;
++                      } else {
++                              BUG_ON(1);
++                      }
+               }
++
+               __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
+               trailer_len += xfrm[i]->props.trailer_len;
+ 
+-              if (tunnel) {
+-                      ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
+-                      ipv6_addr_copy(&fl_tunnel.fl6_src, local);
++              if (outer_family) {
++                      switch (outer_family) {
++                      default:
++                      case AF_INET6:
++                              ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6);
++                              ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6);
++                              break;
++                      case AF_INET:
++                              fl_tunnel.fl4_dst = remote.in->s_addr;
++                              fl_tunnel.fl4_src = local.in->s_addr;
++                              fl_tunnel.fl4_tos = 0;
++                              fl_tunnel.fl4_scope = 0;
++                              break;
++                      }
+                       err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
+-                                            &fl_tunnel, AF_INET6);
++                                            &fl_tunnel, outer_family);
+                       if (err)
+                               goto error;
+               } else
+@@ -241,6 +264,12 @@
+       }
+ 
+       xfrm_init_pmtu(dst);
++      if (beet && outer_family == AF_INET) {
++              int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr);
++              u32 mtu = dst_mtu(dst);
++              xfrm6_update_pmtu(dst, mtu + delta);
++      }
++
+       return 0;
+ 
+ error:
+diff -urN linux-2.6.20/net/ipv6/xfrm6_state.c 
linux-2.6.20-hipl/net/ipv6/xfrm6_state.c
+--- linux-2.6.20/net/ipv6/xfrm6_state.c        2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv6/xfrm6_state.c   2010-03-12 14:20:22.000000000 
+0200
+@@ -98,6 +98,18 @@
+                       src[i] = NULL;
+               }
+       }
++      if (j == n)
++              goto end;
++
++      /* Rule 5: select IPsec BEET */
++      for (i = 0; i < n; i++) {
++              if (src[i] &&
++                  src[i]->props.mode == XFRM_MODE_BEET) {
++                      dst[j++] = src[i];
++                      src[i] = NULL;
++              }
++      }
++
+       if (likely(j == n))
+               goto end;
+ 
+diff -urN linux-2.6.20/net/ipv6/xfrm6_tunnel.c 
linux-2.6.20-hipl/net/ipv6/xfrm6_tunnel.c
+--- linux-2.6.20/net/ipv6/xfrm6_tunnel.c       2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/ipv6/xfrm6_tunnel.c  2010-03-12 14:20:22.000000000 
+0200
+@@ -5,12 +5,12 @@
+  * it under the terms of the GNU General Public License as published by
+  * the Free Software Foundation; either version 2 of the License, or
+  * (at your option) any later version.
+- * 
++ *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+- * 
++ *
+  * You should have received a copy of the GNU General Public License
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+@@ -32,7 +32,7 @@
+ #include <linux/mutex.h>
+ 
+ /*
+- * xfrm_tunnel_spi things are for allocating unique id ("spi") 
++ * xfrm_tunnel_spi things are for allocating unique id ("spi")
+  * per xfrm_address_t.
+  */
+ struct xfrm6_tunnel_spi {
+@@ -70,7 +70,7 @@
+       return h;
+ }
+ 
+-static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi)
++static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi)
+ {
+       return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE;
+ }
+@@ -155,8 +155,8 @@
+ 
+       for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) {
+               index = xfrm6_tunnel_spi_hash_byspi(spi);
+-              hlist_for_each_entry(x6spi, pos, 
+-                                   &xfrm6_tunnel_spi_byspi[index], 
++              hlist_for_each_entry(x6spi, pos,
++                                   &xfrm6_tunnel_spi_byspi[index],
+                                    list_byspi) {
+                       if (x6spi->spi == spi)
+                               goto try_next_1;
+@@ -167,8 +167,8 @@
+       }
+       for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) {
+               index = xfrm6_tunnel_spi_hash_byspi(spi);
+-              hlist_for_each_entry(x6spi, pos, 
+-                                   &xfrm6_tunnel_spi_byspi[index], 
++              hlist_for_each_entry(x6spi, pos,
++                                   &xfrm6_tunnel_spi_byspi[index],
+                                    list_byspi) {
+                       if (x6spi->spi == spi)
+                               goto try_next_2;
+@@ -222,7 +222,7 @@
+ 
+       write_lock_bh(&xfrm6_tunnel_spi_lock);
+ 
+-      hlist_for_each_entry_safe(x6spi, pos, n, 
++      hlist_for_each_entry_safe(x6spi, pos, n,
+                                 
&xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)],
+                                 list_byaddr)
+       {
+@@ -269,9 +269,9 @@
+ {
+       /* xfrm6_tunnel native err handling */
+       switch (type) {
+-      case ICMPV6_DEST_UNREACH: 
++      case ICMPV6_DEST_UNREACH:
+               switch (code) {
+-              case ICMPV6_NOROUTE: 
++              case ICMPV6_NOROUTE:
+               case ICMPV6_ADM_PROHIBITED:
+               case ICMPV6_NOT_NEIGHBOUR:
+               case ICMPV6_ADDR_UNREACH:
+@@ -287,7 +287,7 @@
+               case ICMPV6_EXC_HOPLIMIT:
+                       break;
+               case ICMPV6_EXC_FRAGTIME:
+-              default: 
++              default:
+                       break;
+               }
+               break;
+@@ -307,7 +307,7 @@
+ 
+ static int xfrm6_tunnel_init_state(struct xfrm_state *x)
+ {
+-      if (x->props.mode != XFRM_MODE_TUNNEL)
++      if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != 
XFRM_MODE_BEET)
+               return -EINVAL;
+ 
+       if (x->encap)
+@@ -339,17 +339,29 @@
+       .priority       = 2,
+ };
+ 
++static struct xfrm6_tunnel xfrm46_tunnel_handler = {
++      .handler        = xfrm6_tunnel_rcv,
++      .err_handler    = xfrm6_tunnel_err,
++      .priority       = 2,
++};
++
+ static int __init xfrm6_tunnel_init(void)
+ {
+       if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0)
+               return -EAGAIN;
+ 
+-      if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) {
++      if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) {
++              xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
++              return -EAGAIN;
++      }
++      if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) {
++              xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+               xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+               return -EAGAIN;
+       }
+       if (xfrm6_tunnel_spi_init() < 0) {
+-              xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
++              xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
++              xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+               xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+               return -EAGAIN;
+       }
+@@ -359,7 +371,8 @@
+ static void __exit xfrm6_tunnel_fini(void)
+ {
+       xfrm6_tunnel_spi_fini();
+-      xfrm6_tunnel_deregister(&xfrm6_tunnel_handler);
++      xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET);
++      xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6);
+       xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6);
+ }
+ 
+diff -urN linux-2.6.20/net/xfrm/xfrm_policy.c 
linux-2.6.20-hipl/net/xfrm/xfrm_policy.c
+--- linux-2.6.20/net/xfrm/xfrm_policy.c        2007-02-04 20:44:54.000000000 
+0200
++++ linux-2.6.20-hipl/net/xfrm/xfrm_policy.c   2010-03-12 14:48:34.000000000 
+0200
+@@ -1206,7 +1206,7 @@
+               xfrm_address_t *local  = saddr;
+               struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
+ 
+-              if (tmpl->mode == XFRM_MODE_TUNNEL) {
++              if (tmpl->mode == XFRM_MODE_TUNNEL || tmpl->mode == 
XFRM_MODE_BEET) {
+                       remote = &tmpl->id.daddr;
+                       local = &tmpl->saddr;
+                       family = tmpl->encap_family;
+@@ -1550,7 +1550,7 @@
+             unsigned short family)
+ {
+       if (xfrm_state_kern(x))
+-              return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family);
++              return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, 
tmpl->encap_family);
+       return  x->id.proto == tmpl->id.proto &&
+               (x->id.spi == tmpl->id.spi || !tmpl->id.spi) &&
+               (x->props.reqid == tmpl->reqid || !tmpl->reqid) &&
+diff -urN linux-2.6.20/net/xfrm/xfrm_state.c 
linux-2.6.20-hipl/net/xfrm/xfrm_state.c
+--- linux-2.6.20/net/xfrm/xfrm_state.c 2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-hipl/net/xfrm/xfrm_state.c    2010-03-12 14:48:35.000000000 
+0200
+@@ -561,7 +561,7 @@
+                             selector.
+                        */
+                       if (x->km.state == XFRM_STATE_VALID) {
+-                              if (!xfrm_selector_match(&x->sel, fl, family) ||
++                              if (!xfrm_selector_match(&x->sel, fl, 
x->sel.family) ||
+                                   !security_xfrm_state_pol_flow_match(x, pol, 
fl))
+                                       continue;
+                               if (!best ||
+@@ -573,9 +573,10 @@
+                               acquire_in_progress = 1;
+                       } else if (x->km.state == XFRM_STATE_ERROR ||
+                                  x->km.state == XFRM_STATE_EXPIRED) {
+-                              if (xfrm_selector_match(&x->sel, fl, family) &&
+-                                  security_xfrm_state_pol_flow_match(x, pol, 
fl))
++                              if (xfrm_selector_match(&x->sel, fl, 
x->sel.family) &&
++                                  security_xfrm_state_pol_flow_match(x, pol, 
fl)) {
+                                       error = -ESRCH;
++                              }
+                       }
+               }
+       }

=== added file 'patches/kernel/2.6.20/notes.txt'
--- patches/kernel/2.6.20/notes.txt     1970-01-01 00:00:00 +0000
+++ patches/kernel/2.6.20/notes.txt     2010-03-19 09:53:35 +0000
@@ -0,0 +1,14 @@
+HIPL 2.6.20 kernel patch notes 12.3.2010
+========================================
+
+This patch adds support for interfamily xfrm (beet, tunnel) as well as
+the sleep-thingy and everything else needed to run HIP(L).
+
+Note:
+
+This patch has NOT been tested thoroughly and is considered
+experimental, only for the brave (or desperate) enough stuck with the
+2.6.20 kernel.
+
+
+- joakim.koskela@xxxxxxx

=== modified file 'patches/openwrt/package/Makefile'
--- patches/openwrt/package/Makefile    2010-03-03 17:48:34 +0000
+++ patches/openwrt/package/Makefile    2010-03-19 09:53:35 +0000
@@ -17,7 +17,7 @@
 define Package/hipl-hipd
     SECTION:=net
     CATEGORY:=Network
-    DEPENDS:=+hipl-common +genl +ip +kmod-ipsec +kmod-ipsec4 +kmod-ipsec6 
+kmod-loop +kmod-nbd +kmod-tun +libpthread +libuuid +losetup +kmod-dummy 
+kmod-ipip +kmod-crypto-authenc
+    DEPENDS:=+hipl-common +genl +ip +kmod-ipsec +kmod-ipsec4 +kmod-ipsec6 
+kmod-loop +kmod-nbd +kmod-tun +libpthread +libuuid +losetup +kmod-dummy 
+kmod-ipip +kmod-crypto-authenc +kmod-ip6-tunnel
              # TODO: probably not needed:
              #+kmod-capi +libpcap +udevtrigger +ipsec-tools +isakmpd
     TITLE:=HIPL deamon
@@ -104,10 +104,6 @@
 define Build/Configure
        (cd $(PKG_BUILD_DIR); rm -rf config.{cache,status}; ./autogen.sh 
--host=$(GNU_TARGET_NAME) --target=$(GNU_TARGET_NAME));
 
-#      (cd  $(PKG_BUILD_DIR)/libinet6; test -L include || ln -v -s 
include_glibc23 include;);
-
-#      (cp $(PKG_BUILD_DIR)/libinet6/include/ifaddrs.h 
$(STAGING_DIR)/include/);
-
        (cd ..;);
 
        $(CONFIGURE_VARS);
@@ -180,12 +176,8 @@
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhipconf.la $(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhiptool.so* $(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhiptool.la $(1)/usr/lib/
-#      $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libinet6.so* $(1)/usr/lib/
-#      $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libinet6.la $(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libopphip.so* $(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libopphip.la $(1)/usr/lib/
-       $(INSTALL_BIN)  $(PKG_INSTALL_DIR)/usr/bin/hipsetup $(1)/usr/bin/
-#      $(INSTALL_BIN)  $(PKG_INSTALL_DIR)/usr/bin/listifaces $(1)/usr/bin/
 endef
 
 $(eval $(call BuildPackage,hipl-common))

=== modified file 'release.version'
--- release.version     2010-03-19 09:32:05 +0000
+++ release.version     2010-03-19 09:53:35 +0000
@@ -1,2 +1,2 @@
 Version: 1.0.6
-Release: 2
+Release: 5

=== modified file 'test/auth_performance.c'
--- test/auth_performance.c     2010-02-18 13:36:05 +0000
+++ test/auth_performance.c     2010-03-19 09:53:35 +0000
@@ -16,15 +16,16 @@
 #include <stdio.h>              /* printf & co */
 #include <stdlib.h>             /* exit & co */
 #include <unistd.h>
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
 
+#include "config.h"
 #include "lib/core/hip_statistics.h"
+#include "lib/core/keylen.h"
 #include "lib/core/crypto.h"
-#ifdef CONFIG_HIP_ECDSA
+
+// only use ecdsa when available
+#ifdef HAVE_EC_CRYPTO
 #include <openssl/ecdsa.h>
-#endif /* CONFIG_HIP_ECDSA  */
+#endif
 
 #define PACKET_LENGTH 1280
 
@@ -97,10 +98,10 @@
     DSA *dsa_key_pool[key_pool_size];
     DSA_SIG *dsa_sig_pool[num_measurements];
 
-#ifdef CONFIG_HIP_ECDSA
+#ifdef HAVE_EC_CRYPTO
     EC_KEY *ecdsa_key_pool[key_pool_size];
     ECDSA_SIG *ecdsa_sig_pool[num_measurements];
-#endif /* CONFIG_HIP_ECDSA  */
+#endif
 
     hip_set_logdebug(LOGDEBUG_NONE);
 
@@ -440,7 +441,7 @@
 #endif
 
 
-#ifdef CONFIG_HIP_ECDSA
+#ifdef HAVE_EC_CRYPTO
     printf("\n-------------------------------\n"
            "ECDSA performance test\n"
            "-------------------------------\n");
@@ -486,7 +487,8 @@
             printf("%i. ecdsa signature: %.3f ms\n", i + 1, timediff / 1000.0);
         }
     }
-#endif /* CONFIG_HIP_ECDSA  */
+#endif
+
 #if 0
     calc_statistics(&creation_stats, &num_items, &min, &max, &avg, &std_dev,
                     STATS_IN_MSECS);

=== modified file 'test/certteststub.c'
--- test/certteststub.c 2010-02-17 17:38:08 +0000
+++ test/certteststub.c 2010-03-19 09:53:35 +0000
@@ -13,6 +13,7 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
+#include <arpa/inet.h>
 #include <sys/time.h>
 #include <time.h>
 #include <zlib.h>

=== modified file 'test/conntest-client-hip.c'
--- test/conntest-client-hip.c  2010-02-17 17:38:08 +0000
+++ test/conntest-client-hip.c  2010-03-19 09:53:35 +0000
@@ -9,10 +9,6 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -25,6 +21,8 @@
 #include <netdb.h>
 #include <sys/time.h>
 #include <time.h>
+
+#include "config.h"
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
 #include "conntest.h"

=== modified file 'test/conntest-client-native.c'
--- test/conntest-client-native.c       2010-02-17 17:38:08 +0000
+++ test/conntest-client-native.c       2010-03-19 09:53:35 +0000
@@ -18,10 +18,6 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -36,9 +32,10 @@
 #include <time.h>
 #include <arpa/inet.h>
 #include <net/if.h>
+
+#include "config.h"
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
-
 #include "conntest.h"
 
 int main(int argc, char *argv[])

=== modified file 'test/conntest-client-opp.c'
--- test/conntest-client-opp.c  2010-02-17 17:38:08 +0000
+++ test/conntest-client-opp.c  2010-03-19 09:53:35 +0000
@@ -7,10 +7,6 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -23,6 +19,8 @@
 #include <netdb.h>
 #include <sys/time.h>
 #include <time.h>
+
+#include "config.h"
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
 #include "conntest.h"

=== modified file 'test/conntest-server.c'
--- test/conntest-server.c      2010-02-17 17:38:08 +0000
+++ test/conntest-server.c      2010-03-19 09:53:35 +0000
@@ -12,10 +12,6 @@
 /* required for s6_addr32 */
 #define _BSD_SOURCE
 
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -31,6 +27,8 @@
 #  define __user
 #endif
 #include <signal.h>
+
+#include "config.h"
 #include "conntest.h"
 
 static void sig_handler(int signo)

=== modified file 'test/conntest.c'
--- test/conntest.c     2010-03-19 09:09:25 +0000
+++ test/conntest.c     2010-03-19 09:53:35 +0000
@@ -2,6 +2,8 @@
 #define _BSD_SOURCE
 
 #include "conntest.h"
+#include "lib/tool/nlink.h"
+#include "lib/tool/lutil.h"
 
 /**
  * create_serversocket - given the port and the protocol

=== modified file 'test/conntest.h'
--- test/conntest.h     2010-02-17 17:38:08 +0000
+++ test/conntest.h     2010-03-19 09:53:35 +0000
@@ -16,7 +16,7 @@
 #include <sys/uio.h>
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"
-#include "lib/core/misc.h"
+
 
 int create_socket(int proto);
 int create_serversocket(int type, in_port_t port);

=== modified file 'test/cookietest.c'
--- test/cookietest.c   2010-02-17 17:38:08 +0000
+++ test/cookietest.c   2010-03-19 09:53:35 +0000
@@ -2,7 +2,8 @@
 #define _BSD_SOURCE
 
 #include "lib/core/debug.h"
-#include "lib/core/misc.h"
+
+#include "lib/core/solve.h"
 #include <sys/time.h>
 #include <time.h>
 

=== modified file 'test/dh_performance.c'
--- test/dh_performance.c       2010-03-19 09:24:10 +0000
+++ test/dh_performance.c       2010-03-19 09:53:35 +0000
@@ -19,11 +19,9 @@
 #include <openssl/sha.h>        /* open ssl library for SHA operations */
 #include <openssl/dsa.h>        /* open ssl library for DSA operations */
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #include "lib/core/crypto.h"
+#include "lib/core/filemanip.h"
 #include "lib/core/hashchain.h"
 
 #include "lib/performance/performance.h"

=== modified file 'test/dhtteststub.c'
--- test/dhtteststub.c  2010-02-17 17:38:08 +0000
+++ test/dhtteststub.c  2010-03-19 09:53:35 +0000
@@ -23,9 +23,10 @@
 #include <netinet/ip.h>
 #include <errno.h>
 #include <time.h>
+#include <sys/time.h>
 #include "lib/dht/libhipdht.h"
 #include "lib/core/debug.h"
-#include "lib/core/misc.h"
+#include "lib/core/straddr.h"
 
 int main(int argc, char *argv[])
 {

=== modified file 'test/keygentest.c'
--- test/keygentest.c   2010-02-17 17:38:08 +0000
+++ test/keygentest.c   2010-03-19 09:53:35 +0000
@@ -13,7 +13,8 @@
 #include <time.h>
 
 #include "lib/core/debug.h"
-#include "lib/core/misc.h"
+#include "lib/core/crypto.h"
+#include "lib/tool/lutil.h"
 
 int main(int argc, char *argv[])
 {

=== modified file 'test/performance/perf_measure.sh'
--- test/performance/perf_measure.sh    2010-03-19 09:20:44 +0000
+++ test/performance/perf_measure.sh    2010-03-19 09:53:35 +0000
@@ -20,15 +20,17 @@
 RTT_POSTFIX=
 TCP_POSTFIX=
 UDP_POSTFIX=
+INTERVAL=10
 
 # get the command line options
 if [ $# -eq 0 ]
 then
-  echo "Usage: `basename $0` options: -a <family> [-n <value>] [-p <prefix>] 
-s|-c <dst> -r|-t <type> [-b <value>] [-l <length>]"
+  echo "Usage: `basename $0` options: -a <family> [-n <value>] [-i <interval> 
] [-p <prefix>] -s|-c <dst> -r|-t <type> [-b <value>] [-l <length>]"
   echo
   echo "  -a <family>  = address family (4 - IPv4, 6 - IPv6)"
   echo "  -b <value>   = bandwith to be used for UDP measurements (append K or 
M)"
   echo "  -c <dst>     = client mode with destination ip address"
+  echo "  -i <value>   = time interval between runs (in sec)"
   echo "  -l <value>   = maximum packet length"
   echo "  -n <value>   = number of sequential measurements"
   echo "  -p <prefix>  = output file prefix (including absolut path)"
@@ -39,7 +41,7 @@
   exit 0
 fi
 
-set -- `getopt a:b:c:l:n:p:rst: "$@"`
+set -- `getopt a:b:c:i:l:n:p:rst: "$@"`
 [ $# -lt 1 ] && exit 1    # getopt failed
 
 while [ $# -gt 0 ]
@@ -49,6 +51,7 @@
     -b) BANDWIDTH=$2; shift;;
     -c) RUN_MODE=1
         REMOTE_ADDRESS=$2; shift;;
+    -i) INTERVAL=$2; shift;;
     -l) PACKET_LENGTH=$2; shift;;
     -n) MEASUREMENT_COUNT=$2; shift;;
     -p) FILE=$2; shift;;
@@ -128,7 +131,7 @@
     then
       while [ $i -lt $MEASUREMENT_COUNT ]
       do
-        iperf -c $REMOTE_ADDRESS $TCP_LENGTH | $OUTPUT$TCP_POSTFIX
+        iperf -c $REMOTE_ADDRESS $TCP_LENGTH -t $INTERVAL -i 2 | 
$OUTPUT$TCP_POSTFIX
         i=`expr $i + 1`
         sleep 2
       done
@@ -136,7 +139,7 @@
     then
       while [ $i -lt $MEASUREMENT_COUNT ]
       do
-        iperf -V -c $REMOTE_ADDRESS $TCP_LENGTH | $OUTPUT$TCP_POSTFIX
+        iperf -V -c $REMOTE_ADDRESS $TCP_LENGTH -t $INTERVAL -i 2 | 
$OUTPUT$TCP_POSTFIX
         i=`expr $i + 1`
         sleep 2
       done
@@ -185,7 +188,7 @@
     then
       while [ $i -lt $MEASUREMENT_COUNT ]
       do
-        iperf -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth 
$BANDWIDTH | $OUTPUT$UDP_POSTFIX
+        iperf -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth 
$BANDWIDTH -t $INTERVAL | $OUTPUT$UDP_POSTFIX
         i=`expr $i + 1`
         sleep 2
       done
@@ -193,7 +196,7 @@
     then
       while [ $i -lt $MEASUREMENT_COUNT ]
       do
-        iperf -V -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth 
$BANDWIDTH | $OUTPUT$UDP_POSTFIX
+        iperf -V -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth 
$BANDWIDTH -t $INTERVAL | $OUTPUT$UDP_POSTFIX
         i=`expr $i + 1`
         sleep 2
       done

=== modified file 'test/sqliteteststub.c'
--- test/sqliteteststub.c       2010-03-03 13:16:18 +0000
+++ test/sqliteteststub.c       2010-03-19 09:53:35 +0000
@@ -10,10 +10,7 @@
  *
  */
 
-#ifdef HAVE_CONFIG_H
-  #include "config.h"
-#endif /* HAVE_CONFIG_H */
-
+#include "config.h"
 #ifdef CONFIG_HIP_AGENT
 
 #include "lib/core/prefix.h"

=== modified file 'tools/hipl_autobuild'
--- tools/hipl_autobuild        2010-03-19 09:20:44 +0000
+++ tools/hipl_autobuild        2010-03-19 09:53:35 +0000
@@ -2,14 +2,17 @@
 # HIPL autobuild script for periodic compilation tests.
 # The name of the branch to test needs to be passed as the first parameter.
 #
+# This script relies on the following home directory layout:
+# - $HOME/src/hipl/           - location for HIPL shared repository
+# - $HOME/src/hipl/<branch>   - location for HIPL <branch> to be tested
+# - $HOME/tmp/hipl_autobuild/ - temporary build directory
+#
 # If the HIPL_NOTIFICATION_EMAIL environment variable is set to a suitable 
value
 # for the user running this script, then email will be sent in case of failure.
 
 BRANCH_NAME=$1
-BRANCH_LOCATION=$2
-
 BUILD_DIR=$HOME/tmp/hipl_autobuild
-BRANCH_URL=http://hipl.hiit.fi/hipl/hipl-bzr/$BRANCH_LOCATION
+BRANCH_URL=$HOME/src/hipl/$BRANCH_NAME
 CHECKOUT_DIR=$BUILD_DIR/$(date +"%Y-%m-%d-%H%M")_$BRANCH_NAME
 BRANCH_REVISION=$(bzr revno -q $BRANCH_URL)
 BRANCH_REVISION_FILE=$BUILD_DIR/HIPL_REVISION_$BRANCH_NAME
@@ -23,13 +26,27 @@
         rm -f log.txt
         return 0
     else
-        SUBJECT="[$BRANCH_NAME] [autobuild] failing command: $@"
-        test $HIPL_NOTIFICATION_EMAIL &&
-            mailx -s "$SUBJECT" $HIPL_NOTIFICATION_EMAIL < log.txt
+        test $HIPL_NOTIFICATION_EMAIL && mail_notify "$1"
         cleanup 1
     fi
 }
 
+mail_notify()
+{
+    COMMAND="$1"
+    cat > msg.txt <<EOF
+branch: $BRANCH_NAME
+revision: $BRANCH_REVISION
+configuration: $CONFIGURATION
+command: $COMMAND
+compiler output:
+
+EOF
+    cat log.txt >> msg.txt
+    SUBJECT="[autobuild] [$BRANCH_NAME] revision $BRANCH_REVISION"
+    mailx -s "$SUBJECT" $HIPL_NOTIFICATION_EMAIL < msg.txt
+}
+
 cleanup()
 {
     chmod -R u+rwx "$CHECKOUT_DIR"
@@ -40,24 +57,29 @@
 
 compile()
 {
-    run_program ./autogen.sh &&
-        run_program ./configure --prefix=$(pwd)/local_install $@ &&
-        run_program make -j16 &&
-        run_program make -j16 distcheck &&
-        run_program make install
+    CONFIGURATION="--prefix=$(pwd)/local_install $@"
+    run_program "./autogen.sh" &&
+        run_program "./configure" $CONFIGURATION &&
+        run_program "make -j17" &&
+        run_program "make -j17 distcheck" &&
+        run_program "make install"
 }
 
 test $BRANCH_REVISION = $AUTOBUILD_REVISION && exit 0
 
-bzr checkout -q --lightweight $BRANCH_URL $CHECKOUT_DIR
+bzr checkout -q --lightweight $BRANCH_URL $CHECKOUT_DIR || exit 1
 
-cd "$CHECKOUT_DIR"
+cd "$CHECKOUT_DIR" || exit 1
 
 # Compile HIPL in different configurations
+# vanilla configuration
 compile
-# The following configuration is commented out until HIPL is fixed
-#compile --disable-rvs --disable-ice --disable-hipproxy 
--disable-opportunistic --disable-savaipopt
-#compile --enable-agent --enable-cookie --enable-pfkey --enable-cert 
--disable-rvs --disable-ice --disable-hipproxy --enable-openwrt --enable-altsep 
--enable-i3 --disable-privsep --disable-opportunistic --disable-savaipopt 
--disable-dht --enable-blind --enable-libinet6 --enable-profiling 
--enable-ecdsa --disable-debug --enable-midauth --enable-performance 
--enable-demo
+
+# PISA configuration
+compile --enable-firewall --disable-agent --disable-pfkey --disable-rvs 
--disable-hipproxy --disable-altsep --enable-privsep --disable-i3 
--disable-opportunistic --disable-dht --disable-blind --disable-profiling 
--enable-debug --enable-midauth --disable-performance --disable-demo
+
+# Alternative path to vanilla
+compile --enable-firewall --enable-agent --enable-pfkey --disable-rvs 
--disable-hipproxy --enable-openwrt --enable-altsep --disable-privsep 
--enable-i3 --disable-opportunistic --disable-dht --enable-blind 
--enable-profiling --disable-debug --enable-midauth --enable-performance 
--enable-demo
 
 
 cleanup 0

=== modified file 'tools/pisacert.c'
--- tools/pisacert.c    2010-02-17 17:38:08 +0000
+++ tools/pisacert.c    2010-03-19 09:53:35 +0000
@@ -10,10 +10,14 @@
 #include <sys/time.h>
 #include <time.h>
 #include <zlib.h>
+#include <unistd.h>
+#include <sys/types.h>
 #include "lib/core/ife.h"
 #include "lib/core/icomm.h"
 #include "lib/core/debug.h"
 #include "lib/core/certtools.h"
+#include "lib/core/builder.h"
+#include "lib/core/message.h"
 
 /**
  * Get the default hit of the local HIPD.

Other related posts:

  • » [hipl-commit] [release-1.0.5] Rev 3802: Syncronized to trunk revisions 3833..4000 - Miika Komu