[hipl-dev] [Branch ~toxedvirus/hipl/hipfw-modules] Rev 5013: Merged trunk.

  • From: noreply@xxxxxxxxxxxxx
  • To: HIPL core team <hipl-dev@xxxxxxxxxxxxx>
  • Date: Mon, 15 Nov 2010 17:10:57 -0000

Merge authors:
  Diego Biurrun (diego-biurrun)
  goetz <goetz@goetz>
  Miika Komu (miika-iki)
  Stefan Götz (stefan.goetz)
------------------------------------------------------------
revno: 5013 [merge]
committer: Andrius Bentkus <andrius.bentkus@xxxxxxxxxxxxxx>
branch nick: hipfw-modules
timestamp: Mon 2010-11-15 18:08:02 +0100
message:
  Merged trunk.
removed:
  lib/modularization/
added:
  firewall/file_buffer.c
  firewall/file_buffer.h
  firewall/file_buffer_inline.h
  firewall/line_parser.c
  firewall/line_parser.h
  firewall/line_parser_inline.h
  firewall/mem_area.h
  test/check_firewall.c
  test/firewall/
  test/firewall/file_buffer.c
  test/firewall/line_parser.c
  test/firewall/port_bindings.c
  test/fw_port_bindings_performance.c
renamed:
  firewall/cache_port.c => firewall/port_bindings.c
  firewall/cache_port.h => firewall/port_bindings.h
  lib/core/lmod.c => lib/core/modularization.c
  lib/core/lmod.h => lib/core/modularization.h
modified:
  .bzrignore
  COPYING
  Makefile.am
  configure.ac
  firewall/cache.c
  firewall/esp_prot_conntrack.c
  firewall/firewall.c
  firewall/lsi.c
  hipd/esp_prot_light_update.h
  hipd/hiprelay.c
  hipd/init.c
  hipd/maintenance.c
  hipd/pkt_handling.c
  hipd/registration.c
  hipd/user.c
  lib/core/builder.c
  lib/core/debug.h
  lib/core/hashchain_store.c
  lib/core/icomm.h
  lib/core/options.c
  lib/core/prefix.c
  lib/core/state.h
  lib/tool/pk.c
  modules/heartbeat/hipd/heartbeat.c
  modules/update/hipd/update.c
  packaging/openwrt/package/Makefile
  tools/hipl_autobuild.sh
  firewall/port_bindings.c
  firewall/port_bindings.h
  lib/core/modularization.c
  lib/core/modularization.h


--
lp:~toxedvirus/hipl/hipfw-modules
https://code.launchpad.net/~toxedvirus/hipl/hipfw-modules

Your team HIPL core team is subscribed to branch 
lp:~toxedvirus/hipl/hipfw-modules.
To unsubscribe from this branch go to 
https://code.launchpad.net/~toxedvirus/hipl/hipfw-modules/+edit-subscription
=== modified file '.bzrignore'
--- .bzrignore  2010-11-09 14:18:47 +0000
+++ .bzrignore  2010-11-15 17:08:02 +0000
@@ -48,6 +48,7 @@
 test/auth_performance
 test/certteststub
 test/dh_performance
+test/fw_port_bindings_performance
 test/hc_performance
 tools/hipconf
 tools/hipdnskeyparse

=== modified file 'COPYING'
--- COPYING     2010-08-18 13:12:07 +0000
+++ COPYING     2010-11-10 08:25:44 +0000
@@ -19,9 +19,11 @@
 and have their own licensing conditions (GPL):
 
   * firewall/user_ipsec_esp.c
-  * tools/hipdnsproxy/DNS
   * lib/tool
 
+(Note that tools/hipdnsproxy/DNS is from the pydns project and is covered 
+by the standard Python License)
+
 MIT (Expat) License
 ===================
 

=== modified file 'Makefile.am'
--- Makefile.am 2010-11-09 14:18:47 +0000
+++ Makefile.am 2010-11-15 17:08:02 +0000
@@ -1,3 +1,26 @@
+# Copyright (c) 2010 Aalto University and RWTH Aachen University.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
 ACLOCAL_AMFLAGS  = -I m4
 
 HIPL_HEADER_LIST = $(wildcard $(addprefix $(srcdir)/,firewall/*.h hipd/*.h 
lib/*/*.h modules/*/*/*.h))
@@ -33,6 +56,11 @@
 endif
 
 
+### test programs ###
+noinst_PROGRAMS = test/fw_port_bindings_performance
+
+
+
 ### libraries ###
 lib_LTLIBRARIES = lib/core/libhipcore.la
 
@@ -42,17 +70,23 @@
 check_PROGRAMS  =
 
 if HIP_UNITTESTS
-TESTS           += check_lib_core
-check_PROGRAMS  += check_lib_core
+TESTS           += check_firewall \
+                   check_lib_core
+check_PROGRAMS  += check_firewall \
+                   check_lib_core
 endif
 
 
 ### source declarations ###
 
-test_auth_performance_SOURCES = test/auth_performance.c
-test_certteststub_SOURCES     = test/certteststub.c
-test_dh_performance_SOURCES   = test/dh_performance.c
-test_hc_performance_SOURCES   = test/hc_performance.c
+test_auth_performance_SOURCES               = test/auth_performance.c
+test_certteststub_SOURCES                   = test/certteststub.c
+test_dh_performance_SOURCES                 = test/dh_performance.c
+test_fw_port_bindings_performance_SOURCES   = 
test/fw_port_bindings_performance.c \
+                                              firewall/file_buffer.c           
   \
+                                              firewall/line_parser.c           
   \
+                                              firewall/port_bindings.c
+test_hc_performance_SOURCES                 = test/hc_performance.c
 
 tools_hipconf_SOURCES  = tools/hipconf.c
 tools_pisacert_SOURCES = tools/pisacert.c
@@ -97,18 +131,20 @@
 endif
 
 firewall_hipfw_SOURCES = firewall/cache.c               \
-                         firewall/cache_port.c          \
                          firewall/conntrack.c           \
                          firewall/dlist.c               \
                          firewall/esp_prot_api.c        \
                          firewall/esp_prot_config.c     \
                          firewall/esp_prot_conntrack.c  \
                          firewall/esp_prot_fw_msg.c     \
+                         firewall/file_buffer.c         \
                          firewall/firewall.c            \
                          firewall/firewall_control.c    \
                          firewall/helpers.c             \
                          firewall/hslist.c              \
+                         firewall/line_parser.c         \
                          firewall/lsi.c                 \
+                         firewall/port_bindings.c       \
                          firewall/reinject.c            \
                          firewall/rule_management.c     \
                          firewall/sysopp.c              \
@@ -142,9 +178,9 @@
                                  lib/core/hostsfiles.c      \
                                  lib/core/keylen.c          \
                                  lib/core/linkedlist.c      \
-                                 lib/core/lmod.c            \
                                  lib/core/message.c         \
                                  lib/core/options.c         \
+                                 lib/core/modularization.c  \
                                  lib/core/prefix.c          \
                                  lib/core/solve.c           \
                                  lib/core/statistics.c      \
@@ -160,6 +196,16 @@
 lib_core_libhipcore_la_SOURCES += lib/core/performance.c
 endif
 
+
+check_lib_core_SOURCES =    test/check_lib_core.c          \
+                            test/lib/core/hit.c            \
+                            test/lib/core/straddr.c
+
+check_firewall_SOURCES =    test/check_firewall.c          \
+                            test/firewall/file_buffer.c    \
+                            test/firewall/line_parser.c    \
+                            test/firewall/port_bindings.c
+
 # Initialize LDADD lists empty, because modules might add entries to LDADD. The
 # module LDADDs need to be included before the standard LDADDs, because modules
 # can depend on the core code.
@@ -175,15 +221,17 @@
 
 ### library dependencies ###
 
-check_lib_core_LDADD           = lib/core/libhipcore.la
-firewall_hipfw_LDADD          += lib/core/libhipcore.la
-hipd_hipd_LDADD               += lib/core/libhipcore.la
-test_auth_performance_LDADD    = lib/core/libhipcore.la
-test_certteststub_LDADD        = lib/core/libhipcore.la
-test_dh_performance_LDADD      = lib/core/libhipcore.la
-test_hc_performance_LDADD      = lib/core/libhipcore.la
-tools_hipconf_LDADD           += lib/core/libhipcore.la
-tools_pisacert_LDADD           = lib/core/libhipcore.la
+check_lib_core_LDADD                     = lib/core/libhipcore.la
+check_firewall_LDADD                     = lib/core/libhipcore.la
+firewall_hipfw_LDADD                    += lib/core/libhipcore.la
+hipd_hipd_LDADD                         += lib/core/libhipcore.la
+test_auth_performance_LDADD              = lib/core/libhipcore.la
+test_certteststub_LDADD                  = lib/core/libhipcore.la
+test_dh_performance_LDADD                = lib/core/libhipcore.la
+test_fw_port_bindings_performance_LDADD  = lib/core/libhipcore.la
+test_hc_performance_LDADD                = lib/core/libhipcore.la
+tools_hipconf_LDADD                     += lib/core/libhipcore.la
+tools_pisacert_LDADD                     = lib/core/libhipcore.la
 
 dist_sbin_SCRIPTS = tools/hipdnskeyparse/hipdnskeyparse \
                     tools/hipdnsproxy/hipdnsproxy       \

=== modified file 'configure.ac'
--- configure.ac        2010-11-09 14:18:47 +0000
+++ configure.ac        2010-11-15 17:08:02 +0000
@@ -1,3 +1,26 @@
+# Copyright (c) 2010 Aalto University and RWTH Aachen University.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
 AC_PREREQ([2.53])
 AC_INIT([HIP for Linux], [1.0.6], [hipl-users@xxxxxxxxxxxxx], [hipl])
 AC_CONFIG_HEADERS([config.h])
@@ -12,11 +35,13 @@
 AC_DEFINE_UNQUOTED(HIPL_CONFIGURATION, "$@")
 AH_TEMPLATE(HIPL_CONFIGURATION, [options passed to configure])
 
-# Checks for programs.
+
+# program checks
+
 AC_PROG_CC
 AC_PROG_INSTALL
 # AC_PROG_LIBTOOL() could be replaced with LT_INIT(disable-shared) but
-# OpenWRT (Mar 2010) is running too old version of libtool
+# OpenWrt (Mar 2010) is running too old version of libtool
 # LT_INIT(disable-shared)
 AC_PROG_LIBTOOL(disable-shared)
 
@@ -28,22 +53,27 @@
 # Enable silent rules only when available (automake 1.11 or later).
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
 
-# Check for python for build-system and tools directory
-AM_PATH_PYTHON([2.4.3],, [AC_MSG_ERROR([min. required python version not 
found])])
-
-# Checks for libraries.
-AC_CHECK_LIB(crypto, DSA_generate_key,, AC_MSG_ERROR(openssl lib not found))
-# Check for ec crypto in openssl
+# Check for Python for build-system and tools directory
+AM_PATH_PYTHON([2.4.3],, [AC_MSG_ERROR([Minimum required Python version not 
found.])])
+
+
+
+# library checks
+
+AC_CHECK_LIB(crypto, DSA_generate_key,, AC_MSG_ERROR(OpenSSL not found.))
+# Check for ellyptic curve 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.]),)
+              AH_TEMPLATE(HAVE_EC_CRYPTO, [Defined to 1 if elliptic curve 
crypto is enabled.]))
 # We need the math lib in the registration extension.
-AC_CHECK_LIB(m, pow,, AC_MSG_ERROR(Math lib not found))
+AC_CHECK_LIB(m, pow,, AC_MSG_ERROR(Math library not found.))
 # The unit tests depend on 'check' (http://check.sourceforge.net/)
 AC_CHECK_LIB(check, suite_create,,
-             AC_MSG_WARN(libcheck (http://check.sourceforge.net/) not found: 
HIPL unit tests are not available),)
+             AC_MSG_WARN(libcheck (http://check.sourceforge.net/) not found: 
unit tests not available))
 AM_CONDITIONAL(HIP_UNITTESTS, test x"$ac_cv_lib_check_suite_create" = xyes)
 
+
+
 # If no --prefix option is passed to configure, $prefix is empty. But we want
 # to expand $sysconfdir, which defaults to ${prefix}/etc. So set $prefix.
 if test "x$prefix" = "xNONE"; then
@@ -73,9 +103,6 @@
 AH_TEMPLATE(HIPL_CONFIG_FILE, [default config file location])
 
 
-AC_ARG_WITH(nomodules,
-            AS_HELP_STRING([--with-nomodules=list],
-                           [comma-separated list of disabled modules]))
 
 # Set default AM_CFLAGS for the complete project.
 AC_SUBST(AM_CFLAGS, "-std=c99 -Wall -Wextra -Werror")
@@ -91,9 +118,13 @@
 # Set the preprocessor flags for the entire project
 AC_SUBST(AM_CPPFLAGS, "-D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=500")
 
+
+
+# configure options
+
 AC_ARG_ENABLE(firewall,
                AS_HELP_STRING([--enable-firewall],
-                              [HIP enabled firewall daemon (default is YES)]),
+                              [HIP firewall daemon (default is YES)]),
                [ac_cv_use_firewall=$enableval],
                [ac_cv_use_firewall=yes])
 AC_CACHE_CHECK([whether to use firewall],
@@ -110,7 +141,7 @@
 
 AC_ARG_ENABLE(rvs,
                AS_HELP_STRING([--enable-rvs],
-                              [HIP Rendezvous Extensions (default is YES)]),
+                              [HIP Rendezvous extensions (default is YES)]),
                [ac_cv_use_rvs=$enableval],
                [ac_cv_use_rvs=yes])
 AC_CACHE_CHECK([whether to use RVS],
@@ -180,7 +211,7 @@
 
 AC_ARG_ENABLE(performance,
                AS_HELP_STRING([--enable-performance],
-                              [Performace measurement support (default is 
NO)]),
+                              [Performance measurement support (default is 
NO)]),
                [ac_cv_use_performance=$enableval],
                [ac_cv_use_performance=no])
 AC_CACHE_CHECK([whether to use performance measurement],
@@ -193,18 +224,10 @@
 fi
 AM_CONDITIONAL(HIP_PERFORMANCE, test x"$ac_cv_use_performance" = x"yes")
 
-AC_ARG_ENABLE(demo,
-               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])
-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.])
-fi
+AC_ARG_WITH(nomodules,
+            AS_HELP_STRING([--with-nomodules=list],
+                           [comma-separated list of disabled modules]))
+
 
 
 # Parse modules directory
@@ -212,7 +235,7 @@
 echo "+-----------------------------------------------";
 echo "| processing modules...";
 echo "|";
-$PYTHON ${srcdir}/process_modules.py -s "${srcdir}" -d "${with_nomodules}" -m 
"modules/"
+$PYTHON "${srcdir}/process_modules.py" -s "${srcdir}" -d "${with_nomodules}" 
-m "modules/"
 if [[ "$?" != "0" ]]; then
     echo "configure: error: Module processing failed"
     exit 1
@@ -221,6 +244,8 @@
 echo "+-----------------------------------------------"
 echo ""
 
+
+
 AC_CONFIG_FILES([ Makefile doc/Doxyfile doc/HOWTO.xml tools/nsupdate.pl 
tools/hipdnsproxy/hipdnsproxy ])
 
 AC_OUTPUT

=== modified file 'firewall/cache.c'
--- firewall/cache.c    2010-10-15 15:29:14 +0000
+++ firewall/cache.c    2010-11-12 15:49:05 +0000
@@ -174,7 +174,7 @@
  * @param local local identifier or locator (optional)
  * @param peer peer identifier or locator
  * @param type whether the parameters are HITs, LSIs or IPs
- * @param query_daemon whether to query the demon for HA information
+ * @param query_daemon whether to query the daemon for HA information
  *        if no entry is found in the cache
  * @return the entry on match, NULL otherwise
  */

=== modified file 'firewall/esp_prot_conntrack.c'
--- firewall/esp_prot_conntrack.c       2010-10-15 15:29:14 +0000
+++ firewall/esp_prot_conntrack.c       2010-11-15 13:38:47 +0000
@@ -111,7 +111,7 @@
     long i;
 
     if (cache_item) {
-        anchor_item = (struct esp_anchor_item *) cache_item;
+        anchor_item = cache_item;
 
         for (i = 0; i < num_parallel_hchains; i++) {
             if (anchor_item->active_anchors[i]) {
@@ -399,8 +399,7 @@
         }
 
         // delete cached item from the list
-        HIP_IFEL(!(anchor_item = (struct esp_anchor_item *)
-                                 hip_ll_del(&esp_tuple->anchor_cache,
+        HIP_IFEL(!(anchor_item = hip_ll_del(&esp_tuple->anchor_cache,
                                             element_index, NULL)), -1,
                  "failed to remove anchor_item from list\n");
         free(anchor_item);

=== added file 'firewall/file_buffer.c'
--- firewall/file_buffer.c      1970-01-01 00:00:00 +0000
+++ firewall/file_buffer.c      2010-11-12 17:49:42 +0000
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lib/core/debug.h"
+#include "file_buffer.h"
+
+/**
+ * Always allocate this many more bytes for the memory buffer than is needed
+ * the actual file contents.
+ * This avoids having to re-allocate the buffer for very small increases in the
+ * file size.
+ */
+static const unsigned int HIP_FB_HEADROOM = 4096;
+
+/**
+ * Allocate at most this many bytes, i.e., the maximum supported file size.
+ * This is an arbitrary number used for sanity checking.
+ */
+static const unsigned long HIP_FB_MAX_SIZE = 1024 * 1024 * 1024;
+
+/**
+ * (Re-)allocates the file buffer so that it can hold a complete copy of its
+ * file in memory.
+ * After the function completes successfully, the memory area associated with
+ * the file buffer points to an allocated region of memory that is at least as
+ * large as the size of the file buffer's file at the time of invocation.
+ * The contents of the memory area are undefined.
+ *
+ * If the size of a file cannot be determined (lseek() does not work on proc
+ * files), the buffer size is increased incrementally.
+ *
+ * @param fb the file buffer to use.
+ * @return If the function completes successfully, it returns 0.
+ *  If fb is NULL, -1 is returned.
+ *  If internal errors occur, other negative values are returned.
+ */
+static int hip_fb_resize(struct hip_file_buffer *const fb)
+{
+    int err = 0;
+
+    if (fb) {
+        off_t file_size = 0;
+
+        free(fb->ma.start);
+        fb->ma.start = NULL;
+
+        /* First, we try to determine the current file size for the new buffer 
size.
+         * If that fails (it does, e.g., for proc files), we just increase the
+         * current buffer size. */
+        errno       = 0;
+        file_size   = lseek(fb->fd, 0, SEEK_END);
+        if (file_size != -1 || EINVAL == errno) {
+            if (file_size != -1) {
+                fb->buffer_size = file_size + HIP_FB_HEADROOM; // add a little 
head room
+            } else if (EINVAL == errno) {
+                if (fb->buffer_size < HIP_FB_HEADROOM) {
+                    fb->buffer_size = HIP_FB_HEADROOM;
+                } else {
+                    fb->buffer_size *= 2;
+                }
+            }
+
+            // fb->buffer_size is now adjusted, but maybe not positive or very 
large?
+            if (fb->buffer_size > 0 && fb->buffer_size <= HIP_FB_MAX_SIZE) {
+                // fb->buffer_size is now the size we want to allocate
+                fb->ma.start = malloc(fb->buffer_size);
+                if (fb->ma.start) {
+                    return 0;
+                } else {
+                    HIP_ERROR("Allocating %d bytes of memory for file data 
failed\n",
+                              fb->buffer_size);
+                    err = -4;
+                }
+            } else {
+                HIP_ERROR("The file buffer size %d is too large to be 
supported\n");
+                err = -3;
+            }
+        } else {
+            HIP_ERROR("Determining file size via lseek() failed: %s\n", 
strerror(errno));
+            err = -2;
+        }
+        fb->buffer_size = 0;
+    } else {
+        err = -1;
+    }
+
+    return err;
+}
+
+/**
+ * Initializes a file buffer that holds the specified file.
+ *
+ * A file buffer is used to load and hold the contents of a file in
+ * memory (for simplified access or improved performance).
+ * The memory buffer is allocated so that the whole file fits in it.
+ * Any changes to the memory buffer are not written back to the file and remain
+ * local to the memory buffer.
+ * Note that this is useful primarily with files that cannot be mapped into
+ * memory via mmap(), such as files in /proc.
+ * For regular files, using mmap() is vastly more efficient.
+ *
+ * This function allocates resources, in particular memory, for the returned
+ * object.
+ * To free these resources and to avoid memory leaks, it is imperative to call
+ * hip_fb_delete() when the object created here is no longer used.
+ *
+ * @param fb a pointer to a valid, allocated instance of struct 
hip_file_buffer.
+ *  Upon successful completion, the function writes file-specific context data
+ *  to the location referenced by fb.
+ * @param file_name the name of the file to open and load into memory.
+ * @return a 0 if the file could be opened and successfully buffered.
+ *  -1 is returned if fb is NULL or if file_name is NULL.
+ *  -2 is returned if the specified file cannot be opened for reading.
+ *  -3 is returned if an internal error occurs.
+ */
+int hip_fb_create(struct hip_file_buffer *const fb,
+                  const char *const file_name)
+{
+    int err = 0;
+
+    if (fb && file_name) {
+        memset(fb, 0, sizeof(*fb)); // set all fields to 0/NULL
+        fb->fd = open(file_name, O_RDONLY);
+        if (fb->fd != -1) {
+            if (hip_fb_reload(fb) == 0) {
+                return 0;
+            } else {
+                err = -3;
+            }
+        } else {
+            HIP_ERROR("Opening the file %s for reading via open() failed with 
the error %s\n",
+                      file_name, strerror(errno));
+            err = -2;
+        }
+        hip_fb_delete(fb);
+    } else {
+        err = -1;
+    }
+
+    return err;
+}
+
+/**
+ * De-allocates the resources associated with a file buffer object in
+ * hip_fb_create().
+ * This function does not de-allocated the memory pointed to by fb.
+ * After calling this function, the result of calling any other hip_fb_...()
+ * function on the file buffer fb is undefined.
+ *
+ * @param fb the file buffer to delete. If fb is NULL, this function has no
+ *  effect.
+ */
+void hip_fb_delete(struct hip_file_buffer *const fb)
+{
+    if (fb) {
+        if (fb->fd != -1) {
+            close(fb->fd);
+            fb->fd = -1;
+        }
+        free(fb->ma.start);
+        fb->ma.start    = NULL;
+        fb->ma.end      = NULL;
+    }
+}
+
+/**
+ * Make modifications to the file since the last invocation of hip_fb_create() 
or
+ * hip_fb_reload() visible in the buffer.
+ *
+ * @warning
+ * Note that this function may change the start and end pointers in the memory
+ * area returned by hip_fb_get_mem_area()!
+ *
+ * @param fb the file buffer to use.
+ * @return 0 when the function completes successfully.
+ *  If fb is NULL, -1 is returned.
+ *  If an internal error occurs, -2 is returned.
+ */
+int hip_fb_reload(struct hip_file_buffer *const fb)
+{
+    if (!fb) {
+        return -1;
+    }
+
+    while (1) {
+        ssize_t bytes;
+        off_t seek_offset;
+
+        // can we re-read the whole file into the memory buffer?
+        seek_offset = lseek(fb->fd, 0, SEEK_SET);
+        if (-1 == seek_offset) {
+            HIP_ERROR("Resetting the read position on file descriptor %d via 
lseek() failed with the error %s\n",
+                      fb->fd, errno, strerror(errno));
+            break;
+        }
+
+        bytes = read(fb->fd, fb->ma.start, fb->buffer_size);
+        if (bytes == -1) {
+            HIP_ERROR("Reading the contents of the file descriptor %d via 
read() into a memory buffer of size %d failed with the error %s\n",
+                      fb->fd, fb->buffer_size, strerror(errno));
+            break;
+        } else if ((size_t)bytes == fb->buffer_size) {
+            // we can't fit the file into the memory buffer -> resize it
+            if (hip_fb_resize(fb) == 0) {
+                // successful resize -> retry reading
+                continue;
+            } else {
+                // error resizing -> return error
+                break;
+            }
+        } else {
+            // successfully read the file contents into the buffer
+            fb->ma.end = fb->ma.start + bytes;
+            return 0;
+        }
+    }
+
+    fb->ma.end = NULL;
+
+    return -2;
+}

=== added file 'firewall/file_buffer.h'
--- firewall/file_buffer.h      1970-01-01 00:00:00 +0000
+++ firewall/file_buffer.h      2010-11-12 17:49:42 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef HIP_FIREWALL_FILE_BUFFER_H
+#define HIP_FIREWALL_FILE_BUFFER_H
+
+#include "mem_area.h"
+
+struct hip_file_buffer;
+
+int hip_fb_create(struct hip_file_buffer *const fb,
+                  const char *const file_name);
+void hip_fb_delete(struct hip_file_buffer *const fb);
+static inline const struct hip_mem_area *hip_fb_get_mem_area(const struct 
hip_file_buffer *const fb);
+int hip_fb_reload(struct hip_file_buffer *const fb);
+
+#include "firewall/file_buffer_inline.h"
+
+#endif /* HIP_FIREWALL_FILE_BUFFER_H */

=== added file 'firewall/file_buffer_inline.h'
--- firewall/file_buffer_inline.h       1970-01-01 00:00:00 +0000
+++ firewall/file_buffer_inline.h       2010-11-12 17:49:42 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef HIP_FIREWALL_FILE_BUFFER_INLINE_H
+#define HIP_FIREWALL_FILE_BUFFER_INLINE_H
+
+/* On the one hand, the contents of this file are part of the public interface
+ * and thus only their declaration should go into the public header file.
+ * On the other hand, these functions should be inlineable so their definitions
+ * have to appear in a header file.
+ * To achieve inlineability and still hide the implementation, we use this
+ * secondary header file that is not part of the public interface. */
+#ifndef HIP_FIREWALL_FILE_BUFFER_H
+#error This file must not be included directly because it contains 
implementation details. It may only be included by file_buffer.h.
+#endif
+
+#include <sys/types.h>
+#include <stddef.h>
+
+#include "mem_area.h"
+
+/**
+ * A file buffer object represents an open file and its associated memory
+ * buffer.
+ */
+struct hip_file_buffer {
+    /**
+     * The memory area holding the file contents.
+     * Its start field points to the first byte of file data and the beginning
+     * of the allocated memory buffer.
+     * Its end field points to the last byte of file data + 1.
+     */
+    struct hip_mem_area ma;
+    /*
+     * The number of bytes in the allocated buffer that ma.start points to.
+     * buffer_size is equal to or greater than (ma.end - ma.start).
+     */
+    size_t buffer_size;
+    /*
+     * The file descriptor for the file backing the buffer.
+     */
+    int fd;
+};
+
+/**
+ * Retrieve the memory area in which the file contents are stored.
+ *
+ * There is a 1:1 relationship between the passed in fb object and the returned
+ * pointer.
+ * That is, calling this function on the same fb object will always return the
+ * same struct hip_mem_area pointer.
+ * Thus, you may assume that the returned struct hip_mem_area pointer has the
+ * same life time as its associated struct hip_file_buffer object.
+ * However, hip_fb_reload() may change the start and end address in the
+ * returned struct hip_mem_area object!
+ *
+ * @param fb the file buffer object holding the memory area to retrieve.
+ * @return a pointer to the struct hip_mem_area object associated with the
+ *  given file buffer object.
+ *  If the passed in file buffer pointer is invalid, this function returns
+ *  NULL.
+ */
+static inline const struct hip_mem_area *hip_fb_get_mem_area(const struct 
hip_file_buffer *const fb)
+{
+    if (fb) {
+        return &fb->ma;
+    }
+    return NULL;
+}
+
+#endif /* HIP_FIREWALL_FILE_BUFFER_INLINE_H */

=== modified file 'firewall/firewall.c'
--- firewall/firewall.c 2010-11-09 13:04:44 +0000
+++ firewall/firewall.c 2010-11-15 17:08:02 +0000
@@ -74,7 +74,6 @@
 #include "lib/core/filemanip.h"
 #include "lib/core/hip_udp.h"
 #include "lib/core/ife.h"
-#include "lib/core/lmod.h"
 #include "lib/core/message.h"
 #include "lib/core/options.h"
 #include "lib/core/performance.h"
@@ -85,7 +84,6 @@
 #include "modules/firewall_modules.h"
 #include "config.h"
 #include "cache.h"
-#include "cache_port.h"
 #include "common_types.h"
 #include "conntrack.h"
 #include "esp_prot_api.h"
@@ -96,6 +94,7 @@
 #include "lsi.h"
 #include "midauth.h"
 #include "pisa.h"
+#include "port_bindings.h"
 #include "reinject.h"
 #include "rule_management.h"
 #include "user_ipsec_api.h"
@@ -640,7 +639,7 @@
     // Initializing local cache database
     hip_firewall_cache_init_hldb();
     // Initializing local port cache database
-    hip_firewall_port_cache_init_hldb();
+    hip_port_bindings_init(true);
     /* Initialize raw sockets for packet reinjection */
     hip_firewall_init_raw_sockets();
 
@@ -768,7 +767,7 @@
     }
 
     hip_firewall_cache_delete_hldb(1);
-    hip_firewall_port_cache_uninit_hldb();
+    hip_port_bindings_uninit();
     hip_fw_uninit_system_based_opp_mode();
     hip_fw_flush_iptables();
     /* rules have to be removed first, otherwise HIP packets won't pass through

=== added file 'firewall/line_parser.c'
--- firewall/line_parser.c      1970-01-01 00:00:00 +0000
+++ firewall/line_parser.c      2010-11-12 17:49:42 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#include <stdlib.h>
+
+#include "file_buffer.h"
+#include "line_parser.h"
+
+/**
+ * Initializes a parser that iterates over the lines of a given memory area.
+ *
+ * A line parser object is used to linearly iterate over the lines in a memory
+ * area that holds text.
+ * The memory area contents are not modified and the returned line pointers are
+ * terminated by newline characters, not null characters.
+ *
+ * When this function returns successfully, hip_lp_first() can be called
+ * immediately to start parsing.
+ * This function allocates resources, in particular memory, for the returned
+ * object.
+ * To free these resources and to avoid memory leaks, it is imperative to call
+ * hip_lp_delete() when the object created here is no longer used.
+ *
+ * @param lp a pointer to a valid, allocated instance of struct 
hip_line_parser.
+ *  Upon successful completion, the function writes parser-specific context
+ *  data to the location referenced by lp.
+ * @param ma the memory area to interpret as text and to parse by lines.
+ * @return 0 if the line parser lp was successfully initialized.
+ *  This function return -1 if lp is NULL or if ma is NULL.
+ */
+int hip_lp_create(struct hip_line_parser *const lp,
+                  const struct hip_mem_area *const ma)
+{
+    if (lp && ma) {
+        lp->ma  = ma;
+        lp->cur = NULL;
+        return 0;
+    }
+
+    return -1;
+}
+
+/**
+ * Releases the resources allocated for a line parser object in
+ * hip_lp_create().
+ * This does not include the memory pointed to by lp or the struct hip_mem_area
+ * object this parser was created with or the memory backing that memory area).
+ *
+ * @param lp the line parser object to delete.
+ *  If lp is NULL, calling this function has no effect.
+ */
+void hip_lp_delete(struct hip_line_parser *const lp)
+{
+    if (lp) {
+        lp->ma  = NULL;
+        lp->cur = NULL;
+    }
+}

=== added file 'firewall/line_parser.h'
--- firewall/line_parser.h      1970-01-01 00:00:00 +0000
+++ firewall/line_parser.h      2010-11-12 17:49:42 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef HIP_FIREWALL_LINE_PARSER_H
+#define HIP_FIREWALL_LINE_PARSER_H
+
+#include "mem_area.h"
+
+struct hip_line_parser;
+
+int hip_lp_create(struct hip_line_parser *const lp,
+                  const struct hip_mem_area *const ma);
+void hip_lp_delete(struct hip_line_parser *const lp);
+static inline char *hip_lp_first(struct hip_line_parser *const lp);
+static inline char *hip_lp_next(struct hip_line_parser *const lp);
+
+#include "firewall/line_parser_inline.h"
+
+#endif /* HIP_FIREWALL_LINE_PARSER_H */

=== added file 'firewall/line_parser_inline.h'
--- firewall/line_parser_inline.h       1970-01-01 00:00:00 +0000
+++ firewall/line_parser_inline.h       2010-11-12 17:49:42 +0000
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef HIP_FIREWALL_LINE_PARSER_INLINE_H
+#define HIP_FIREWALL_LINE_PARSER_INLINE_H
+
+/* On the one hand, the contents of this file are part of the public interface
+ * and thus only their declaration should go into the public header file.
+ * On the other hand, these functions should be inlineable so their definitions
+ * have to appear in a header file.
+ * To achieve inlineability and still hide the implementation, we use this
+ * secondary header file that is not part of the public interface. */
+#ifndef HIP_FIREWALL_LINE_PARSER_H
+#error This file must not be included directly because it contains 
implementation details. It may only be included by line_parser.h.
+#endif
+
+#include <string.h>
+
+#include "lib/core/debug.h"
+#include "file_buffer.h"
+
+/**
+ * Represents the parsing state on a memory area object.
+ */
+struct hip_line_parser {
+    /**
+     * The memory area this parser operates on.
+     */
+    const struct hip_mem_area *ma;
+    /**
+     * The current parsing position.
+     * If NULL, hip_lp_first() needs to be called.
+     * If != NULL, points to the start of line in the memory buffer.
+     */
+    char *cur;
+};
+
+/**
+ * Start a new parsing pass with a line parser and return the first line in the
+ * buffer.
+ * The buffer is not modified and the line is terminated by a newline
+ * character (not a null character).
+ *
+ * A parsing pass consists of starting it via hip_lp_first() and iterating over
+ * the lines in the file via hip_lp_next() until it returns NULL.
+ *
+ * @param lp the line parser to use.
+ * @return a pointer to the first line in the file or NULL if no line is
+ *  available.
+ */
+static inline char *hip_lp_first(struct hip_line_parser *const lp)
+{
+    if (!lp ||
+        !lp->ma) {
+        return NULL;
+    }
+
+    lp->cur = lp->ma->start;
+
+    return lp->cur;
+}
+
+/**
+ * Get the next line in a parsing pass with a line parser.
+ *
+ * Each invocation of this function returns a pointer to consecutive lines in
+ * the buffer to parse.
+ * After the last line has been reached, NULL is returned.
+ * In that case, parsing can restart by calling hip_lp_first().
+ *
+ * @param lp the line parser parser to use.
+ * @return a pointer to a line in the buffer or NULL if there are no more lines
+ *  available.
+ */
+static inline char *hip_lp_next(struct hip_line_parser *const lp)
+{
+    size_t remaining;
+
+    if (!lp ||
+        !lp->cur ||
+        !lp->ma ||
+        !lp->ma->start ||
+        !lp->ma->end ||
+        lp->cur < lp->ma->start ||
+        lp->cur >= lp->ma->end) {
+        return NULL;
+    }
+
+    remaining   = lp->ma->end - lp->cur;
+    lp->cur     = memchr(lp->cur, '\n', remaining);
+
+    // given the rest of the parsing code, we should always find a \n, but
+    // let's check to be sure
+    if (lp->cur) {
+        // cur should not point to the new-line character but to the next one:
+        lp->cur += 1;
+        // is there text on the line here or are we at the end?
+        if (lp->cur >= lp->ma->end) {
+            lp->cur = NULL;
+        }
+    }
+
+    return lp->cur;
+}
+
+#endif /* HIP_FIREWALL_LINE_PARSER_INLINE_H */

=== modified file 'firewall/lsi.c'
--- firewall/lsi.c      2010-10-15 15:29:14 +0000
+++ firewall/lsi.c      2010-10-24 22:20:24 +0000
@@ -64,7 +64,7 @@
 #include "lib/core/prefix.h"
 #include "lib/core/protodefs.h"
 #include "cache.h"
-#include "cache_port.h"
+#include "port_bindings.h"
 #include "firewall.h"
 #include "lsi.h"
 #include "reinject.h"
@@ -316,11 +316,9 @@
     int verdict                                           = 1;
     int ip_hdr_size                                       = 0;
     int portDest                                          = 0;
-    int process_as_lsi                                    = 0;
     fw_cache_hl_t *entry                                  = NULL;
-    const struct firewall_port_cache_hl *port_cache_entry = NULL;
+    enum hip_port_binding port_binding                    = 
HIP_PORT_INFO_UNKNOWN;
     const struct ip6_hdr *ip6_hdr                         = NULL;
-    char proto[PROTO_STRING_MAX];
     struct in6_addr src_addr, dst_addr;
 
     ip6_hdr = (const struct ip6_hdr *) m->payload;
@@ -329,11 +327,9 @@
     switch (ip6_hdr->ip6_nxt) {
     case IPPROTO_UDP:
         portDest = ((const struct udphdr *) ((m->payload) + 
ip_hdr_size))->dest;
-        strcpy(proto, "udp6");
         break;
     case IPPROTO_TCP:
         portDest = ((const struct tcphdr *) ((m->payload) + 
ip_hdr_size))->dest;
-        strcpy(proto, "tcp6");
         break;
     case IPPROTO_ICMPV6:
         HIP_DEBUG("ICMPv6 packet\n");
@@ -343,50 +339,45 @@
         break;
     }
 
-    /* port caching */
-    port_cache_entry = hip_firewall_port_cache_db_match(portDest,
-                                                        ip6_hdr->ip6_nxt);
+    port_binding = hip_port_bindings_get(ip6_hdr->ip6_nxt,
+                                         portDest);
 
-    if (port_cache_entry &&
-        (port_cache_entry->traffic_type ==
-         FIREWALL_PORT_CACHE_IPV6_TRAFFIC)) {
+    if (port_binding == HIP_PORT_INFO_IPV6BOUND) {
+        HIP_DEBUG("Port %d is bound to an IPv6 address -> accepting packet\n", 
portDest);
         verdict = 1;
-        HIP_DEBUG("Cached port, accepting\n");
-        goto out_err;
-    }
+    } else if (port_binding == HIP_PORT_INFO_IPV6UNBOUND) {
+        HIP_DEBUG("Port %d is unbound or bound to an IPv4 address -> looking 
up in cache\n", portDest);
+        HIP_IFEL(!(entry = hip_firewall_cache_db_match(ip_dst, ip_src,
+                                                       FW_CACHE_HIT, 1)),
+                 -1, "Failed to obtain from cache\n");
 
-    if (lsi_support) {
         /* Currently preferring LSIs over opp. connections */
-        process_as_lsi = 1;
-    }
-
-    HIP_IFEL(!(entry = hip_firewall_cache_db_match(ip_dst, ip_src,
-                                                   FW_CACHE_HIT, 1)),
-             -1, "Failed to obtain from cache\n");
-
-    if (process_as_lsi) {
-        HIP_DEBUG("Trying lsi transformation\n");
-        HIP_DEBUG_LSI("lsi_our: ", &entry->lsi_our);
-        HIP_DEBUG_LSI("lsi_peer: ", &entry->lsi_peer);
-        IPV4_TO_IPV6_MAP(&entry->lsi_our, &dst_addr);
-        IPV4_TO_IPV6_MAP(&entry->lsi_peer, &src_addr);
-        HIP_IFEL(hip_reinject_packet(&src_addr, &dst_addr, m, 6, 1), -1,
-                 "Failed to reinject with LSIs\n");
-        HIP_DEBUG("Successful LSI transformation.\n");
-
-        if (ip6_hdr->ip6_nxt == IPPROTO_ICMPV6) {
-            verdict = 1;             /* broadcast: dst may be ipv4 or ipv6 */
+        if (lsi_support) {
+            HIP_DEBUG("Trying lsi transformation\n");
+            HIP_DEBUG_LSI("lsi_our: ", &entry->lsi_our);
+            HIP_DEBUG_LSI("lsi_peer: ", &entry->lsi_peer);
+            IPV4_TO_IPV6_MAP(&entry->lsi_our, &dst_addr);
+            IPV4_TO_IPV6_MAP(&entry->lsi_peer, &src_addr);
+            HIP_IFEL(hip_reinject_packet(&src_addr, &dst_addr, m, 6, 1), -1,
+                     "Failed to reinject with LSIs\n");
+            HIP_DEBUG("Successful LSI transformation.\n");
+
+            if (ip6_hdr->ip6_nxt == IPPROTO_ICMPV6) {
+                verdict = 1;             /* broadcast: dst may be ipv4 or ipv6 
*/
+            } else {
+                verdict = 0;             /* drop original */
+            }
         } else {
-            verdict = 0;             /* drop original */
+            HIP_DEBUG("Trying sys opp transformation\n");
+            HIP_DEBUG_IN6ADDR("ip_src: ", &entry->ip_peer);
+            HIP_DEBUG_IN6ADDR("ip_dst: ", &entry->ip_our);
+            HIP_IFEL(hip_reinject_packet(&entry->ip_peer, &entry->ip_our, m, 
6, 1),
+                     -1, "Failed to reinject with IP addrs\n");
+            HIP_DEBUG("Successfull sysopp transformation. Drop orig\n");
+            verdict = 0;
         }
     } else {
-        HIP_DEBUG("Trying sys opp transformation\n");
-        HIP_DEBUG_IN6ADDR("ip_src: ", &entry->ip_peer);
-        HIP_DEBUG_IN6ADDR("ip_dst: ", &entry->ip_our);
-        HIP_IFEL(hip_reinject_packet(&entry->ip_peer, &entry->ip_our, m, 6, 1),
-                 -1, "Failed to reinject with IP addrs\n");
-        HIP_DEBUG("Successfull sysopp transformation. Drop orig\n");
-        verdict = 0;
+        HIP_DIE("hip_port_bindings_get() returned unknown return value %d\n", 
port_binding);
     }
 
 out_err:

=== added file 'firewall/mem_area.h'
--- firewall/mem_area.h 1970-01-01 00:00:00 +0000
+++ firewall/mem_area.h 2010-11-12 17:49:42 +0000
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef HIP_FIREWALL_MEM_AREA_H
+#define HIP_FIREWALL_MEM_AREA_H
+
+/**
+ * A range of memory with a defined start and end.
+ *
+ * This structure is useful where the information is needed about a specific
+ * memory area, e.g., for a file loaded into memory.
+ */
+struct hip_mem_area {
+    char *start;
+    char *end;
+};
+
+#endif

=== renamed file 'firewall/cache_port.c' => 'firewall/port_bindings.c'
--- firewall/cache_port.c       2010-10-15 15:29:14 +0000
+++ firewall/port_bindings.c    2010-11-12 17:49:42 +0000
@@ -25,277 +25,465 @@
 
 /**
  * @file
- * Cache TCP and UDP port information for incoming HIP-related connections for
- * LSIs. When hipfw sees an incoming HIT-based connection, it needs to figure 
out if
- * it needs to be translated to LSI or not. LSI translation is done only when 
there is
- * no IPv6 application bound the corresponding TCP or UDP port. The port 
information
- * can be read from /proc but consumes time. To avoid this overhead, hipfw 
caches
- * the port information after the first read. Notice that cache is static and 
hipfw
- * must be restarted if there are changes in the port numbers. This is 
described in
- * more detail in <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>.
- *
- * @brief Cache TCP and UDP port numbers for inbound HIP-related connections 
to optimize LSI translation
- *
- * @author Miika Komu <miika@xxxxxx>
+ * @brief Look up whether a port corresponds to a local bound socket, which 
influences LSI handling.
+ *
+ * @author Miika Komu <miika@xxxxxx>, Stefan Goetz 
<stefan.goetz@xxxxxxxxxxxxxxxxx>
  */
 
-#include <stdio.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <signal.h>
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
-#include <netinet/in.h>
+#include <time.h>
+#include <unistd.h>
 
-#include "lib/core/builder.h"
+#include "lib/core/common.h"
 #include "lib/core/debug.h"
-#include "lib/core/hashtable.h"
-#include "lib/core/icomm.h"
-#include "lib/core/list.h"
-#include "lib/core/prefix.h"
-#include "lib/tool/lutil.h"
-#include "cache.h"
-#include "cache_port.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
- */
-static 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)
- * @param value     the value for the hash key (LSI mode value)
- *
- * @return zero on success or non-zero on failure
- */
-static int hip_port_cache_add_new_entry(const char *key, int value)
-{
-    struct firewall_port_cache_hl *new_entry = NULL;
+#include "lib/core/ife.h"
+#include "line_parser.h"
+#include "port_bindings.h"
+
+/**
+ * The number of seconds after which hip_port_bindings_trigger_reload() is
+ * called periodically.
+ * The smaller this number, the more up-to-date information is returned by
+ * hip_port_bindings_get().
+ * At the same time, a small interval also causes the somewhat expensive
+ * hip_port_bindings_reload() to be called more frequently.
+ */
+const unsigned int INVALIDATION_INTERVAL = 1;
+
+/**
+ * Indicates whether the caches should be invalidated.
+ * This is periodically set to 1 by a timer and reset the next time a lookup is
+ * performed.
+ */
+volatile sig_atomic_t cache_invalidation_flag = 1;
+
+/**
+ * Pointer to the port bindings cache.
+ *
+ * The cache is a two-dimensional array.
+ * The first dimension is the transport protocol for which a port can be bound
+ * (supported are TCP and UDP).
+ * The second dimension is the port number itself.
+ * The value is a uint8_t representation of an enum hip_port_binding value
+ */
+static uint8_t *cache = NULL;
+
+static const unsigned int CACHE_SIZE_PROTOS = 2;
+static const unsigned int CACHE_SIZE_PORTS  = 1 << (sizeof(in_port_t) * 8);
+static unsigned int cache_size_entries      = 0;
+static unsigned int cache_size_bytes        = 0;
+
+/**
+ * Allocate and initializes the cache resources.
+ * If this function has not been called first, the results of calling
+ * cache_get() and cache_set() are undefined.
+ *
+ * @return 0 if the function completes successfully.
+ *  If the memory for the cache could not be allocated, this function returns
+ *  -1.
+ */
+static int init_cache(void)
+{
+    HIP_ASSERT(!cache);
+
+    cache_size_entries  = CACHE_SIZE_PROTOS * CACHE_SIZE_PORTS;
+    cache_size_bytes    = cache_size_entries * sizeof(*cache);
+
+    // check that the conversion used in the cache from enum hip_port_binding
+    // to uint8_t is consistent
+    HIP_ASSERT(HIP_PORT_INFO_IPV6UNBOUND == (enum 
hip_port_binding)(uint8_t)HIP_PORT_INFO_IPV6UNBOUND);
+    HIP_ASSERT(HIP_PORT_INFO_IPV6BOUND == (enum 
hip_port_binding)(uint8_t)HIP_PORT_INFO_IPV6BOUND);
+
+    /* We zero the cache on allocation assuming that HIP_PORT_INFO_UNKNOWN
+    is 0 and thus the whole cache initially has that value. */
+    HIP_ASSERT((uint8_t)HIP_PORT_INFO_UNKNOWN == 0);
+    cache = calloc(1, cache_size_bytes);
+    if (cache) {
+        return 0;
+    } else {
+        HIP_ERROR("Allocating the port bindings cache failed\n");
+        return -1;
+    }
+}
+
+/**
+ * Release the cache resources.
+ * After calling this function, the results of calling cache_get() and
+ * cache_set() are undefined.
+ */
+static void uninit_cache(void)
+{
+    free(cache);
+    cache = NULL;
+}
+
+/**
+ * Determines the index of a cache entry.
+ * The cache array should only be indexed via this function.
+ *
+ * The flat cache entry index can be used to access the cache as a
+ * one-dimensional array.
+ * Using it is not strictly necessary because it would be possible and more
+ * beautiful to behold to access the cache as a two-dimensional array, but the
+ * one-dimensional flat index determined here can also be used for bounds
+ * checking.
+ *
+ * @param protocol the protocol the specified port belongs to.
+ *  The value is the same as used in the IPv4 'protocol' and the IPv6 'Next
+ *  Header' fields.
+ *  The only supported values are 6 for TCP and 17 for UDP.
+ * @param port the port in host byte order to get the port binding for.
+ *  Valid values range from 0 to 2^16-1.
+ * @return the index of the cache entry for @a protocol and @a port.
+ */
+static inline unsigned int get_cache_index(const uint8_t protocol,
+                                           const uint16_t port)
+{
+    unsigned int index              = 0;
+    unsigned int protocol_offset    = 0;
+
+    // determine the offset into the first (protocol) dimension
+    if (IPPROTO_TCP == protocol) {
+        protocol_offset = 0;
+    } else if (IPPROTO_UDP == protocol) {
+        protocol_offset = 1;
+    } else {
+        HIP_DIE("Invalid protocol");
+    }
+
+    // calculate the index
+    index = (protocol_offset * CACHE_SIZE_PORTS) + port;
+
+    return index;
+}
+
+/**
+ * Cache binding state on the port of a given protocol.
+ *
+ * This function is called after looking up port binding status from the /proc
+ * file system.
+ * After it has been called, a call to hip_firewall_port_cache_set() with the
+ * same protocol and port returns the previously set port binding.
+ *
+ * @param protocol the protocol the specified port belongs to.
+ *  The value is the same as used in the IPv4 'protocol' and the IPv6 'Next
+ *  Header' fields.
+ *  The only supported values are 6 for TCP and 17 for UDP.
+ * @param port the port in host byte order to set the port binding for.
+ *  Valid values range from 0 to 2^16-1.
+ * @param binding the binding to store in the cache.
+ */
+static void set_cache_entry(const uint8_t protocol,
+                            const uint16_t port,
+                            const enum hip_port_binding binding)
+{
+    // fail gracefully if the cache is not allocated
+    if (cache) {
+        // calculate index of cache entry
+        const unsigned int index = get_cache_index(protocol, port);
+
+        // convert the port binding to the cache storage type
+        const uint8_t value = (uint8_t)binding;
+
+        cache[index] = value;
+    }
+}
+
+/**
+ * Retrieve port binding for a given protocol from the cache.
+ *
+ * Looking up the port binding from the /proc file systems is relatively
+ * expensive.
+ * Thus, we use this cache to speed up the lookup.
+ *
+ * This function is called before looking up the port binding from the /proc
+ * file system.
+ *
+ * @param protocol the protocol the specified port belongs to.
+ *  The value is the same as used in the IPv4 'protocol' and the IPv6 'Next
+ *  Header' fields.
+ *  The only supported values are 6 for TCP and 17 for UDP.
+ * @param port the port in host byte order to set the port binding for.
+ *  Valid values range from 0 to 2^16-1.
+ * @return If the port binding was previously stored, it is returned.
+ *  If the port binding was not previously stored or the cache is not
+ *  available, HIP_PORT_INFO_UNKNOWN is returned.
+ */
+static enum hip_port_binding get_cache_entry(const uint8_t protocol,
+                                             const uint16_t port)
+{
+    enum hip_port_binding binding = HIP_PORT_INFO_UNKNOWN;
+
+    // fail gracefully if cache is not available
+    if (cache) {
+        const unsigned int index = get_cache_index(protocol, port);
+
+        binding = (enum hip_port_binding)cache[index];
+    }
+
+    return binding;
+}
+
+/**
+ * Invalidate all cache entries.
+ *
+ * After calling this function, all valid invocations of get_cache_entry()
+ * return HIP_PORT_INFO_UNKNOWN.
+ */
+static void invalidate_cache(void)
+{
+    if (cache) {
+        memset(cache, HIP_PORT_INFO_UNKNOWN, cache_size_bytes);
+    }
+}
+
+
+
+
+
+
+static struct hip_file_buffer tcp6_file;
+static struct hip_file_buffer udp6_file;
+
+/**
+ * Handles ALRM signals and triggers caches to be reloaded.
+ * After this function has been called, the next call to
+ * hip_port_bindings_get() calls hip_port_bindings_reload() to invalidate the
+ * port and the file caches before performing a port lookup.
+ * This tries to strike a balance between the cost of
+ * hip_port_bindings_reload() and the freshness of the lookup information
+ * returned by hip_port_bindings_get().
+ * This function is called every INVALIDATION_INTERVAL seconds.
+ */
+static void hip_port_bindings_trigger_reload(UNUSED const int sig)
+{
+    cache_invalidation_flag = 1;
+}
+
+/**
+ * Load the latest information from /proc.
+ * This consists of handling two separate caching layers:
+ * a) re-reading the file contents in the tcp6/udp6 file buffer objects and
+ * b) invalidating the lookup cache.
+ * On the one hand, this operation should ideally be called for every call to
+ * hip_port_bindings_get() to retrieve up-to-date information from /proc
+ * about which ports are bound.
+ * On the other hand, this operation is about 300 times more expensive than
+ * parsing the /proc file and even more expensive compared to a cache lookup.
+ * hip_port_bindings_trigger_reload() tries to balance this conflict.
+ * After calling this function, the cache is empty and the file buffers contain
+ * the up-to-date file contents from /proc.
+ *
+ * @todo TODO efficiency could be increased by narrowing this down from
+ *  reloading the files and invalidating the caches of all protocols to
+ *  individual protocols.
+ *
+ * @return If this function completes successfully, it returns 0.
+ *  If one of the proc files could not be reloaded from the file system, this
+ *  function returns -1.
+ */
+static int hip_port_bindings_reload(void)
+{
     int err = 0;
 
-    HIP_DEBUG("\n");
-    new_entry = (struct firewall_port_cache_hl *) 
(hip_cache_create_hl_entry());
-    memcpy(new_entry->port_and_protocol, key, strlen(key));
-    new_entry->traffic_type = value;
-    hip_ht_add(firewall_port_cache_db, new_entry);
-
-    return err;
+    invalidate_cache();
+
+    err  = hip_fb_reload(&tcp6_file);
+    err |= hip_fb_reload(&udp6_file);
+
+    return (err == 0) ? 0 : -1;
 }
 
 /**
- * Search in the port cache database. The key composed of port and protocol
- *
- * @param port the TCP or UDP port to search for
- * @param proto the protocol (IPPROTO_UDP, IPPROTO_TCP or IPPROTO_ICMPV6)
- *
- * @return the cache entry if found or NULL otherwise
+ * Look up the port binding from the proc file system.
+ *
+ * @param protocol protocol type
+ * @param port the port number of the socket
+ * @return the traffic type associated with the given port.
  */
-struct firewall_port_cache_hl *hip_firewall_port_cache_db_match(in_port_t port,
-                                                                int proto)
+static enum hip_port_binding hip_port_bindings_get_from_proc(const uint8_t 
protocol,
+                                                             const uint16_t 
port)
 {
-    struct firewall_port_cache_hl *found_entry = NULL;
-    char key[FIREWALL_PORT_CACHE_KEY_LENGTH];
-    char protocol[10], proto_for_bind[10];
-    int bindto = FIREWALL_PORT_CACHE_IPV4_TRAFFIC; //3 - default to ipv4, 
non-LSI traffic
-
-    memset(protocol, 0, sizeof(protocol));
-    memset(proto_for_bind, 0, sizeof(proto_for_bind));
-    memset(key, 0, sizeof(key));
-
-    switch (proto) {
+    const unsigned int PORT_STR_OFFSET  = 39;
+    const unsigned int PORT_STR_LEN     = 4;
+    enum hip_port_binding result        = HIP_PORT_INFO_IPV6UNBOUND;
+    const struct hip_mem_area *ma;
+    char *line;
+    // the files /proc/net/{udp,tcp}6 are line-based and the line number of the
+    // port to look up is not known in advance
+    // -> use a parser that lets us iterate over the lines in the files
+    struct hip_line_parser lp;
+
+    switch (protocol) {
+    case IPPROTO_TCP:
+        ma = hip_fb_get_mem_area(&tcp6_file);
+        break;
     case IPPROTO_UDP:
-        strcpy(protocol, "udp");
-        strcpy(proto_for_bind, "udp6");
-        break;
-    case IPPROTO_TCP:
-        strcpy(protocol, "tcp");
-        strcpy(proto_for_bind, "tcp6");
-        break;
-    case IPPROTO_ICMPV6:
-        strcpy(protocol, "icmp");
-        break;
-    default:
-        goto out_err;
-        break;
-    }
-
-    //assemble the key
-    sprintf(key, "%i", (int) port);
-    memcpy(key + strlen(key), "_", 1);
-    memcpy(key + strlen(key), protocol, strlen(protocol));
-
-    found_entry = hip_ht_find(firewall_port_cache_db, key);
-
-    if (proto == IPPROTO_ICMPV6) {
-        goto out_err;
-    }
-
-    if (!found_entry) {
-        bindto      = hip_get_proto_info(ntohs(port), proto_for_bind);
-        hip_port_cache_add_new_entry(key, bindto);
-        found_entry = hip_ht_find(firewall_port_cache_db, key);
-    } else {
-        HIP_DEBUG("Matched port using hash\n");
-    }
+        ma = hip_fb_get_mem_area(&udp6_file);
+        break;
+    }
+    hip_lp_create(&lp, ma);
+
+    // Note that here we blindly parse whatever is in the file buffer.
+    // This may not be up-to-date compared to the actual /proc file.
+    // We rely on someone else calling hip_port_bindings_reload() to
+    // reload the file contents for us so that we return some at least roughly
+    // up-to-date information.
+    line = hip_lp_first(&lp);
+
+    // the first line only contains headers, no port information, skip it
+    line = hip_lp_next(&lp);
+
+    // is the current line valid and is it long enough to hold a port binding?
+    while (line && ma->end > (line + PORT_STR_OFFSET + PORT_STR_LEN)) {
+        const unsigned int PORT_BASE_HEX    = 16;
+        unsigned long proc_port             = 0;
+        // note that strtoul() is about 10 times faster than sscanf().
+        errno       = 0;
+        proc_port   = strtoul(line + PORT_STR_OFFSET, NULL, PORT_BASE_HEX);
+        if (0 == errno) {
+            if (proc_port == port) {
+                result = HIP_PORT_INFO_IPV6BOUND;
+                break;
+            }
+        } else {
+            HIP_ERROR("Unable to parse port number in line '%.*s' from 
/proc/net/%s6, errno = %d\n",
+                      PORT_STR_OFFSET + PORT_STR_LEN, line,
+                      IPPROTO_TCP == protocol ? "tcp" : "udp", errno);
+        }
+        line = hip_lp_next(&lp);
+    }
+
+    hip_lp_delete(&lp);
+    return result;
+}
+
+/**
+ * Initialize the port binding lookup and allocate any necessary resources.
+ *
+ * @param enable_cache if not 0, use an internal cache that is consulted on
+ *  lookups in favor of parsing the /proc file.
+ *  If this lookup cache is not enabled, every lookup results in parsing the
+ *  proc file.
+ *  Note however, that the /proc file itself is cached in memory and only
+ *  reloaded at a certain interval.
+ *  Within this interval, hip_port_bindings_get() might return a different
+ *  port binding status than the one in the actual /proc file.
+ * @return 0 if the function completes successfully.
+ *  If enable_cache is true but the cache could not be allocated or initialized
+ *  this function returns -1.
+ *  If one of the /proc files could not be opened or buffered in memory
+ *  successfully, this function returns -2.
+ */
+int hip_port_bindings_init(const bool enable_cache)
+{
+    int err;
+
+    // The cache is built such that it can be disabled just by not initializing
+    // it here.
+    if (enable_cache) {
+        HIP_IFEL(init_cache() != 0, -1,
+                 "Initializing the port bindings cache failed\n")
+    }
+
+    HIP_IFEL(hip_fb_create(&tcp6_file, "/proc/net/tcp6") != 0, -2,
+             "Buffering tcp6 proc file in memory failed\n");
+    HIP_IFEL(hip_fb_create(&udp6_file, "/proc/net/udp6") != 0, -2,
+             "Buffering udp6 proc file in memory failed\n");
+
+    return 0;
 
 out_err:
-    return found_entry;
-}
-
-/**
- * Generate the hash information that is used to index the table
- *
- * @param ptr pointer to the hit used to assemble the hash
- *
- * @return hash value
- */
-static unsigned long hip_firewall_port_hash_key(const void *ptr)
-{
-    const char *key;
-    uint8_t hash[HIP_AH_SHA_LEN];
-
-    key = (const char *)
-          &((const struct firewall_port_cache_hl *) ptr)->port_and_protocol;
-    hip_build_digest(HIP_DIGEST_SHA1, key, sizeof(*key), hash);
-    return *((unsigned long *) hash);
-}
-
-/**
- * Compare two keys for the hashtable
- *
- * Note that when this function is called, the hashes of the two hash table
- * entries provided as arguments are known to be equal.
- * The point of this function is to allow the hash table to determine whether
- * the entries (or rather the part used to calculate the hash) themselves are
- * equal or whether they are different and this is just a hash collision.
- *
- * @param ptr1 pointer to the first key
- * @param ptr2 pointer to the second key
- *
- * @return 0 if keys identical, otherwise != 0
- */
-static int hip_firewall_match_port_cache_key(const void *ptr1, const void 
*ptr2)
-{
-    return strncmp((const char *)ptr1, (const char *)ptr2, 
FIREWALL_PORT_CACHE_KEY_LENGTH);
-}
-
-/**
- * Initialize port cache database
- *
- */
-void hip_firewall_port_cache_init_hldb(void)
-{
-    firewall_port_cache_db = hip_ht_init(hip_firewall_port_hash_key,
-                                         hip_firewall_match_port_cache_key);
-}
-
-/**
- * Initialize port cache database
- *
- */
-void hip_firewall_port_cache_uninit_hldb(void)
-{
-    int i;
-    struct firewall_port_cache_hl *this = NULL;
-    hip_list_t *item                    = NULL;
-    hip_list_t *tmp                     = NULL;
-
-    HIP_DEBUG("Start hldb delete\n");
-    HIP_LOCK_HT(&firewall_port_cache_db);
-
-    list_for_each_safe(item, tmp, firewall_port_cache_db, i)
-    {
-      HIP_DEBUG("xx\n");
-        this = (struct firewall_port_cache_hl *) list_entry(item);
-        hip_ht_delete(firewall_port_cache_db, this);
-        free(this);
-      HIP_DEBUG("yy\n");
+    hip_port_bindings_uninit();
+    return err;
+}
+
+/**
+ * Release any resources allocated for port binding lookups.
+ */
+void hip_port_bindings_uninit(void)
+{
+    hip_fb_delete(&tcp6_file);
+    hip_fb_delete(&udp6_file);
+
+    uninit_cache();
+}
+
+/**
+ * Determine whether the given port is bound under the given protocol to an
+ * IPv6 address on the local host.
+ *
+ * For example, on a system with a running IPv6-capable web server, this
+ * function returns HIP_PORT_INFO_IPV6BOUND.
+ * If there is no web server or it only supports (or binds to) IPv4 addresses,
+ * this function returns HIP_PORT_INFO_IPV6UNBOUND.
+ *
+ * Note that due to internal caching, hip_port_bindings_get() might return for
+ * a certain caching interval a different port binding status than the one
+ * reported in the actual /proc file (see hip_port_bindings_trigger_reload()).
+ *
+ * The binary test/fw_port_bindings_performance benchmarks the elements that
+ * influence the performance of the hip_port_bindings_* code.
+ * Please have a look at the numbers it generates when changing this code under
+ * performance aspects.
+ *
+ * @param protocol the protocol to check the port binding for.
+ *  The values are equivalent to those found in the 'Protocol' field of the
+ *  IPv4 header and the 'Next Header' field of the IPv6 header.
+ *  The only supported values are those for TCP (6) and UDP (17).
+ * @param port the port to look up.
+ *  The value is expected in network byte order, as it is found in protocol
+ *  headers.
+ * @return HIP_PORT_INFO_IPV6BOUND if the given port is bound under the given
+ *  protocol to an IPv6 address.
+ *  HIP_PORT_INFO_IPV6UNBOUND if it is not.
+ */
+enum hip_port_binding hip_port_bindings_get(const uint8_t protocol,
+                                            const in_port_t port)
+{
+    enum hip_port_binding binding = HIP_PORT_INFO_IPV6UNBOUND;
+
+    // check input parameters
+    if (IPPROTO_TCP == protocol ||
+        IPPROTO_UDP == protocol) {
+        const uint16_t port_hbo = ntohs(port);
+
+        // Make sure we return (sort of) up-to-date information.
+        // This is the one potentially slow operation here.
+        // The others (hip_port_bindings_get_from_proc() and the cache access
+        // functions) are (intended to be) very fast.
+        if (cache_invalidation_flag) {
+            // prevent further cache invalidation
+            cache_invalidation_flag = 0;
+            // invalidate all caches and reload the /proc-file contents
+            hip_port_bindings_reload();
+            // start a timer that sets cache_invalidation_flag back to 1
+            signal(SIGALRM, hip_port_bindings_trigger_reload);
+            alarm(INVALIDATION_INTERVAL);
+        }
+
+        // check the cache before checking /proc
+        // note that the cache might be switched off (see
+        // hip_port_bindings_init()) or was just invalidated by
+        // hip_port_bindings_reload()
+        binding = get_cache_entry(protocol, port_hbo);
+
+        if (HIP_PORT_INFO_UNKNOWN == binding) {
+            binding = hip_port_bindings_get_from_proc(protocol, port_hbo);
+            set_cache_entry(protocol, port_hbo, binding);
+        }
+    } else {
+        HIP_ERROR("Protocol %d not supported\n", protocol);
     }
-    HIP_UNLOCK_HT(&firewall_port_cache_db);
-    hip_ht_uninit(firewall_port_cache_db);
-    HIP_DEBUG("End hldbdb delete\n");
+
+    // check return value
+    HIP_ASSERT(HIP_PORT_INFO_IPV6UNBOUND == binding ||
+               HIP_PORT_INFO_IPV6BOUND == binding);
+
+    return binding;
 }

=== renamed file 'firewall/cache_port.h' => 'firewall/port_bindings.h'
--- firewall/cache_port.h       2010-10-15 15:29:14 +0000
+++ firewall/port_bindings.h    2010-11-12 17:49:42 +0000
@@ -23,16 +23,51 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIP_FIREWALL_CACHE_PORT_H
-#define HIP_FIREWALL_CACHE_PORT_H
+/**
+ * @file
+ * The port binding says whether a port is locally bound to an IPv6
+ * application or not.
+ * This allows the firewall to determine whether an incoming HIT-based packet
+ * is meant to go to a local IPv6 port or not.
+ * If not, the packet needs to be converted to IPv4 and sent to an LSI.
+ * More details can be found in <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>.
+ *
+ * @author Miika Komu <miika@xxxxxx>, Stefan Goetz 
<stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef HIP_FIREWALL_PORT_BINDINGS_H
+#define HIP_FIREWALL_PORT_BINDINGS_H
 
 #include <netinet/in.h>
-
-#include "lib/core/icomm.h"
-
-void hip_firewall_port_cache_init_hldb(void);
-struct firewall_port_cache_hl *hip_firewall_port_cache_db_match(in_port_t port,
-                                                                int proto);
-void hip_firewall_port_cache_uninit_hldb(void);
-
-#endif /* HIP_CACHE_H */
+#include <stdbool.h>
+
+/**
+ * The binding state of a particular TCP or UDP port under IPv6 on the local
+ * host.
+ */
+enum hip_port_binding {
+    /**
+     * It is not known which network protocol the port is bound under.
+     */
+    HIP_PORT_INFO_UNKNOWN = 0,
+    /**
+     * The port is not bound to an IPv6 address (but potentially to an
+     * IPv4 address).
+     */
+    HIP_PORT_INFO_IPV6UNBOUND,
+    /**
+     * The port is bound to an IPv6 address (and potentially to an IPv4
+     * address)
+     */
+    HIP_PORT_INFO_IPV6BOUND,
+};
+
+int hip_port_bindings_init(const bool enable_cache);
+void hip_port_bindings_uninit(void);
+enum hip_port_binding hip_port_bindings_get(const uint8_t proto,
+                                            const in_port_t port);
+
+#endif /* HIP_FIREWALL_PORT_BINDINGS_H */

=== modified file 'hipd/esp_prot_light_update.h'
--- hipd/esp_prot_light_update.h        2010-10-20 16:11:23 +0000
+++ hipd/esp_prot_light_update.h        2010-11-15 17:08:02 +0000
@@ -36,8 +36,8 @@
 #ifndef HIP_HIPD_ESP_PROT_LIGHT_UPDATE_H
 #define HIP_HIPD_ESP_PROT_LIGHT_UPDATE_H
 
-#include "lib/core/lmod.h"
 #include "lib/core/protodefs.h"
+#include "lib/core/modularization.h"
 
 int esp_prot_send_light_update(hip_ha_t *entry,
                                const int anchor_offset[],

=== modified file 'hipd/hiprelay.c'
--- hipd/hiprelay.c     2010-10-20 03:38:26 +0000
+++ hipd/hiprelay.c     2010-11-15 13:39:24 +0000
@@ -69,7 +69,7 @@
  *
  * <pre>
  * hip_relrec_t dummy, *fetch_record = NULL;
- * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit));
+ * memcpy(&dummy.hit_r, hit, sizeof(hit));
  * fetch_record = hip_relht_get(&dummy);
  * if (fetch_record != NULL) {
  *     // Do something with the record.
@@ -79,7 +79,7 @@
  * <li>Deleting a relay record. A dummy record can be used:
  * <pre>
  * hip_relrec_t dummy;
- * memcpy((char *) &(dummy.hit_r), hit, sizeof(hit));
+ * memcpy(&dummy.hit_r, hit, sizeof(hit));
  * hip_relht_rec_free(&dummy);
  * </pre>
  * </li>

=== modified file 'hipd/init.c'
--- hipd/init.c 2010-11-09 13:04:44 +0000
+++ hipd/init.c 2010-11-15 17:08:02 +0000
@@ -62,7 +62,6 @@
 #include "lib/core/hostsfiles.h"
 #include "lib/core/ife.h"
 #include "lib/tool/nlink.h"
-#include "lib/core/lmod.h"
 #include "lib/core/performance.h"
 #include "lib/core/straddr.h"
 #include "lib/tool/xfrmapi.h"

=== modified file 'hipd/maintenance.c'
--- hipd/maintenance.c  2010-10-20 16:11:23 +0000
+++ hipd/maintenance.c  2010-11-15 17:08:02 +0000
@@ -49,8 +49,8 @@
 #include "lib/core/hip_udp.h"
 #include "lib/core/ife.h"
 #include "lib/core/linkedlist.h"
-#include "lib/core/lmod.h"
 #include "lib/core/protodefs.h"
+#include "lib/core/modularization.h"
 #include "config.h"
 #include "accessor.h"
 #include "close.h"

=== modified file 'hipd/pkt_handling.c'
--- hipd/pkt_handling.c 2010-10-20 16:11:23 +0000
+++ hipd/pkt_handling.c 2010-11-15 17:08:02 +0000
@@ -34,9 +34,9 @@
 
 #include "lib/core/ife.h"
 #include "lib/core/linkedlist.h"
-#include "lib/core/lmod.h"
 #include "lib/core/protodefs.h"
 #include "lib/core/state.h"
+#include "lib/core/modularization.h"
 #include "pkt_handling.h"
 
 

=== modified file 'hipd/registration.c'
--- hipd/registration.c 2010-10-27 11:11:20 +0000
+++ hipd/registration.c 2010-11-15 12:40:48 +0000
@@ -522,10 +522,8 @@
                     if (new_record != NULL) {
                         free(new_record);
                     }
-                    refused_requests[*refused_count] =
-                        reg_types[i];
-                    failure_types[*refused_count]    =
-                        HIP_REG_TRANSIENT_CONDITIONS;
+                    refused_requests[*refused_count] = reg_types[i];
+                    failure_types[*refused_count]    = 
HIP_REG_TRANSIENT_CONDITIONS;
                     (*refused_count)++;
                     HIP_ERROR("Unable to store new relay " \
                               "record. Registration " \

=== modified file 'hipd/user.c'
--- hipd/user.c 2010-10-20 16:11:23 +0000
+++ hipd/user.c 2010-11-15 17:08:02 +0000
@@ -65,9 +65,9 @@
 #include "lib/core/icomm.h"
 #include "lib/core/ife.h"
 #include "lib/core/linkedlist.h"
-#include "lib/core/lmod.h"
 #include "lib/core/prefix.h"
 #include "lib/core/protodefs.h"
+#include "lib/core/modularization.h"
 #include "lib/tool/nlink.h"
 #include "config.h"
 #include "accessor.h"

=== modified file 'lib/core/builder.c'
--- lib/core/builder.c  2010-10-18 20:24:43 +0000
+++ lib/core/builder.c  2010-11-15 12:40:48 +0000
@@ -3757,7 +3757,7 @@
                        hostname,
                        dsa_key_rr);
 
-    out_err:
+out_err:
 
     if (dsa_key_rr) {
         free(dsa_key_rr);
@@ -3815,7 +3815,7 @@
                        hostname,
                        rsa_key_rr);
 
-    out_err:
+out_err:
 
     if (rsa_key_rr) {
         free(rsa_key_rr);

=== modified file 'lib/core/debug.h'
--- lib/core/debug.h    2010-10-15 15:29:14 +0000
+++ lib/core/debug.h    2010-11-12 15:50:17 +0000
@@ -261,11 +261,6 @@
 #define HIP_DEBUG_GL(debug_group, debug_level, ...) do {} while (0)
 #endif
 
-#ifdef CONFIG_HIP_DEMO
-#define HIP_DEMO(...) printf(__VA_ARGS__);
-#else
-#define HIP_DEMO(...) do {} while (0)
-#endif
 /* @} */
 
 /* Debug groups define groups of debug messages which belong to the

=== modified file 'lib/core/hashchain_store.c'
--- lib/core/hashchain_store.c  2010-10-18 17:44:31 +0000
+++ lib/core/hashchain_store.c  2010-11-15 13:38:47 +0000
@@ -48,7 +48,7 @@
  */
 static void hcstore_free_hchain(void *hchain)
 {
-    hchain_free((hash_chain_t *) hchain);
+    hchain_free(hchain);
 }
 
 /** helper function to free a hash tree
@@ -57,7 +57,7 @@
  */
 static void hcstore_free_htree(void *htree)
 {
-    htree_free((hash_tree_t *) htree);
+    htree_free(htree);
 }
 
 /** initializes a new hash item store

=== modified file 'lib/core/icomm.h'
--- lib/core/icomm.h    2010-10-15 15:29:14 +0000
+++ lib/core/icomm.h    2010-10-15 22:56:42 +0000
@@ -197,18 +197,4 @@
 
 #define FLUSH_HA_INFO_DB                        1
 
-
-/****** FIREWALL ******/
-
-/*----Firewall cache----*/
-/*Values for the port cache of the firewall*/
-#define FIREWALL_PORT_CACHE_IPV6_TRAFFIC        1
-#define FIREWALL_PORT_CACHE_IPV4_TRAFFIC        3
-#define FIREWALL_PORT_CACHE_KEY_LENGTH          20
-
-struct firewall_port_cache_hl {
-    char port_and_protocol[FIREWALL_PORT_CACHE_KEY_LENGTH];     //key
-    int  traffic_type;                                          //value
-};
-
 #endif /* HIP_LIB_CORE_ICOMM_H */

=== renamed file 'lib/core/lmod.c' => 'lib/core/modularization.c'
--- lib/core/lmod.c     2010-11-09 14:18:47 +0000
+++ lib/core/modularization.c   2010-11-15 17:08:02 +0000
@@ -25,7 +25,7 @@
 
 /**
  * @file
- * @brief The main source file for libmodularization (lmod).
+ * @brief Allow modularized features that can be enabled as required.
  *
  * @author Tim Just <tim.just@xxxxxxxxxxxxxx>
  */
@@ -34,8 +34,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "modularization.h"
 #include "modules/modules.h"
-#include "lmod.h"
 #include "debug.h"
 #include "ife.h"
 
@@ -492,9 +492,9 @@
  */
 static void lmod_free_packet_entry(void *entry)
 {
-    struct packet_type *packte_type_entry = entry;
-    free(packte_type_entry->identifier);
-    free(packte_type_entry);
+    struct packet_type *packet_type_entry = entry;
+    free(packet_type_entry->identifier);
+    free(packet_type_entry);
 }
 
 /**

=== renamed file 'lib/core/lmod.h' => 'lib/core/modularization.h'
--- lib/core/lmod.h     2010-10-20 16:11:23 +0000
+++ lib/core/modularization.h   2010-11-15 17:08:02 +0000
@@ -27,8 +27,9 @@
  * @file
  * @author Tim Just <tim.just@xxxxxxxxxxxxxx>
  */
-#ifndef HIP_LIB_CORE_LMOD_H
-#define HIP_LIB_CORE_LMOD_H
+
+#ifndef HIP_LIB_CORE_MODULARIZATION_H
+#define HIP_LIB_CORE_MODULARIZATION_H
 
 #include <stdint.h>
 
@@ -75,4 +76,4 @@
 
 int hip_lmod_load_modules(const struct module_info *const modules, const 
unsigned int size);
 
-#endif /* HIP_LIB_CORE_LMOD_H */
+#endif /* HIP_LIB_CORE_MODULARIZATION_H */

=== modified file 'lib/core/options.c'
--- lib/core/options.c  2010-11-09 13:36:03 +0000
+++ lib/core/options.c  2010-11-15 17:08:02 +0000
@@ -54,9 +54,9 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "lmod.h"
 #include "common.h"
 #include "options.h"
+#include "modularization.h"
 #include "modules/modules.h"
 #include "lib/core/linkedlist.h"
 

=== modified file 'lib/core/prefix.c'
--- lib/core/prefix.c   2010-10-18 17:44:31 +0000
+++ lib/core/prefix.c   2010-11-15 13:39:24 +0000
@@ -383,24 +383,22 @@
 
 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));
+    return memcmp(a1, 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));
+    memcpy(a1, 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));
+    return memcmp(a1, 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));
+    memcpy(a1, a2, sizeof(struct in6_addr));
 }
 
 int ipv6_addr_any(const struct in6_addr *a) {

=== modified file 'lib/core/state.h'
--- lib/core/state.h    2010-10-20 16:11:23 +0000
+++ lib/core/state.h    2010-11-15 17:08:02 +0000
@@ -40,7 +40,7 @@
 #include "hipd/cookie.h"
 #include "config.h"
 #include "hashtable.h"
-#include "lmod.h"
+#include "modularization.h"
 #include "protodefs.h"
 #include "statistics.h"
 

=== removed directory 'lib/modularization'
=== modified file 'lib/tool/pk.c'
--- lib/tool/pk.c       2010-08-19 09:32:20 +0000
+++ lib/tool/pk.c       2010-11-15 13:38:47 +0000
@@ -41,7 +41,7 @@
  */
 int hip_rsa_sign(void *priv_key, struct hip_common *msg)
 {
-    RSA *rsa      = (RSA *) priv_key;
+    RSA *rsa      = priv_key;
     uint8_t sha1_digest[HIP_AH_SHA_LEN];
     uint8_t *signature = NULL;
     int err       = 0, len;

=== modified file 'modules/heartbeat/hipd/heartbeat.c'
--- modules/heartbeat/hipd/heartbeat.c  2010-10-20 00:28:19 +0000
+++ modules/heartbeat/hipd/heartbeat.c  2010-11-15 17:08:02 +0000
@@ -81,11 +81,11 @@
 #include "lib/core/debug.h"
 #include "lib/core/icomm.h"
 #include "lib/core/ife.h"
-#include "lib/core/lmod.h"
 #include "lib/core/prefix.h"
 #include "lib/core/protodefs.h"
 #include "lib/core/statistics.h"
 #include "lib/core/straddr.h"
+#include "lib/core/modularization.h"
 #include "lib/tool/nlink.h"
 #include "heartbeat.h"
 

=== modified file 'modules/update/hipd/update.c'
--- modules/update/hipd/update.c        2010-10-20 00:28:19 +0000
+++ modules/update/hipd/update.c        2010-11-15 17:08:02 +0000
@@ -56,12 +56,12 @@
 #include "lib/core/hashtable.h"
 #include "lib/core/hip_udp.h"
 #include "lib/core/ife.h"
-#include "lib/core/lmod.h"
 #include "lib/core/list.h"
 #include "lib/core/performance.h"
 #include "lib/core/prefix.h"
 #include "lib/core/protodefs.h"
 #include "lib/core/solve.h"
+#include "lib/core/modularization.h"
 #include "update_legacy.h"
 #include "update.h"
 

=== modified file 'packaging/openwrt/package/Makefile'
--- packaging/openwrt/package/Makefile  2010-10-29 11:31:40 +0000
+++ packaging/openwrt/package/Makefile  2010-11-12 16:31:19 +0000
@@ -97,7 +97,6 @@
 
        $(INSTALL_DATA) ./files/hipl.modules $(1)/etc/modules.d/35-hipl
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhipcore.so* $(1)/usr/lib/
-       $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libmod.so* $(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhipheartbeat.so* 
$(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhiphbupdate.so* 
$(1)/usr/lib/
        $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhipupdate.so* 
$(1)/usr/lib/

=== added file 'test/check_firewall.c'
--- test/check_firewall.c       1970-01-01 00:00:00 +0000
+++ test/check_firewall.c       2010-11-12 17:49:42 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <check.h>
+#include <stdlib.h>
+
+/* Import test suite functions from their respective C files via forward
+ * declarations.
+ * Since each test C file exports only one such function which is only used
+ * right here, a dedicated header file for each of them adds unnecessary file
+ * clutter in this particular case of unit tests.
+ * Do not adopt this HFAS (header-file-avoidance-scheme) (TM) in HIPL 
production
+ * code as header files are generally a good idea, just not here. */
+extern Suite *firewall_file_buffer(void);
+extern Suite *firewall_line_parser(void);
+extern Suite *firewall_port_bindings(void);
+
+int main(void)
+{
+    int number_failed;
+    SRunner *sr = srunner_create(firewall_file_buffer());
+    srunner_add_suite(sr, firewall_line_parser());
+    srunner_add_suite(sr, firewall_port_bindings());
+
+    srunner_run_all(sr, CK_NORMAL);
+    number_failed = srunner_ntests_failed(sr);
+    srunner_free(sr);
+    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}

=== added directory 'test/firewall'
=== added file 'test/firewall/file_buffer.c'
--- test/firewall/file_buffer.c 1970-01-01 00:00:00 +0000
+++ test/firewall/file_buffer.c 2010-11-12 17:49:42 +0000
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <check.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "firewall/file_buffer.h"
+#include "firewall/file_buffer.c"
+
+// these tests do not clean up after themselves because they assume that
+// check runs them in dedicated processes so the OS does the cleanup
+
+START_TEST(test_hip_fb_create_valid)
+{
+    struct hip_file_buffer fb;
+
+    fail_unless(hip_fb_create(&fb, "/etc/fstab") == 0,
+                "Opening the file '/etc/fstab' failed - does it exist?");
+}
+END_TEST
+
+START_TEST(test_hip_fb_create_null_buffer)
+{
+    fail_unless(hip_fb_create(NULL, "/etc/fstab") == -1, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_fb_create_null_file_name)
+{
+    struct hip_file_buffer fb;
+
+    fail_unless(hip_fb_create(&fb, NULL) == -1, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_fb_create_missing_file)
+{
+    struct hip_file_buffer fb;
+
+    fail_unless(hip_fb_create(&fb,
+                              
"XhUp8vH5sbye3izn25XbY3EVu9VcAsNC42WOCVYxAkMXiFo7cuh4Zsp2jHgfJ2OsBUTamYDuSyB9oSuAYEfBJA6EaEXBpNCp2l88Zo2yaWaLw6pB5mh61dlBDQZjaqlS")
 == -2,
+                NULL);
+}
+END_TEST
+
+START_TEST(test_hip_fb_create_check_file_integrity)
+{
+    struct hip_file_buffer fb;
+    const struct hip_mem_area *ma   = NULL;
+    int fd                          = -1;
+    const char FILE_NAME_PATTERN[]  = "XXXXXX";
+    char file_name[sizeof(FILE_NAME_PATTERN)];
+    const char file_contents[]      = 
"yfuCedywwPTVUJ0ego5HPQ34hCJgaDAElU3qDTniiRme0bdmjpo1YId9PX9Kkffsi1HOzzwBvnGikMuxJ5bSv8xRSUmBLsv31tfmvdcUDkTzzjoJErKCxnTRsccJdJYc4Y3o7P2dDkHFAokEY5lz79dEbUmfpKmdWuEx4Ory17tDoe2S30l1yhlDUnHF3Hg6FLELMymJDMDologVjohganwYN6j0p9zJfnOwm9pPzzqoEsNoNALA3XwNBG40jMOBb9KaulcHCS56fieRsakxmSUw9T5iM3T5Bn37FhBnMDfEu1AJ3SkTwNw2vrcCDYpN3zl2isC3lTfkRnMDmrTkBfwx9MZuxaPI8jqebZfXrFvl6Oc8TFdaLlUARshG0Ci0UUEa5QiwbCOKjcC1tc2IztYzGpOghvv4rBA7B5B7TGH4VJZJXekRx46xlnEvlw5qKzfDAKeFmeM0L5ym9zRzXmv9HYOD8krkLD2ubMQnaLL6d3LU0qI9NaQsi2PM2A1FIswVlQ5EtGpjf7l35pWsCEE08r7efzBjtYAtvytyzFmxI7mGd4pf9xWlmJJ8OFM6PAEwvSnJN0jEJIxaRZUMH93DfHGW3w2sQpFu3FyHzfzweQma2wf1dD7BjHYHJTXb3gsYqaNG8yweoJQ4RUtAMiEkal6HxzRgQYb87g7ESzuKCp1XjDXh3k0Rtsezjrd957rHO2F2xttHSP3GqBhsdTzTVgVEdPLiFj7G3iBol7t0I3QGbEcX2AkxoCkQGV1cRfRvxeuctnGpDczBM0gHjTcHScqhBfOpCmAzhFa9NNc0GNiihL37DJ3mgzwAw7qh49zbtgP0YqRWUNkHJgukisldvCFiHucXaRWc21AvdyIpYmIRN4gKfhPfBEKCdrX6Ykjxxq5lqnnitL00Ib3Am8gOaChB8r8FffiZ91PUvN5vMSZIc32fVQpAFw296GcXJZbVraJh4sHAONFMpNtoYj56YWDcKOwAHXiCFd58jlqHftot44DKk4dOSrORFeAUfu58zpbxoUu2LmqtORlp3AjRh5cHv1bjzpE6dRE09ksNTdrvdxyD2zdN4755gIGeIqMzO11gnwRQ6y19lFc9RI5TmFcEyVHpgKWvUEUAKqOMHc1Er6X8fX22awM1Ex7IF5DHpVTVPBGX4m6NUWu9JmUz2oEBOpU1ik5rXfp7aea1wwz1KS3IwdEHf4VMFVA2CAQ9cS3jrBYVb6Rm18uhDTAyAv9l0ZgBHR6c5s2Rnh6THT7WAGJ8Scf95OKQVNk8WEEagM5th09E07Cd4RYtck52alL7VfWSpaBgPgrDgSnjRf4419Qvbkbvbl0GnSNyXUPRR63eS9ZzWtq2gn0HnAz8mJoBMSgU6Lky5hoEgloDM1cpJgcxtFqLYsS2BII94BkDtb8tPUyOwGT6KfLOHy77Mx61eBHkLEM3dIjpOdwTA2YNZ5wK6vpUtUVsadoFKYMMQvnFFhc7kzilSNZPs5nvM6VzyUtrAP2FQvHCl1A6fHP9clmeWTEYqqYZO1D8LUKlhUCv2TYuqkSekP8pjmv4NYXA5IvWsbSigxyWpa15AmFg0f1GajKen6zHE9Yj88VW1GRAAjtohVsC1XrHRLfuRn1FDjxlMVZR2eRI9TTuWPy2sT93TyfsBwZNhdJ36d5CCj9aAdI1L2UI7qCunqVnC5ALnUTejRR8vJNswDOzU6sdI1op6sUSSUAtUshsoFANcvC6bLMGZyick4ckzrepnAGYWWutyqg7dJXwmsGJYCummuk6ppEixnWYs2N7IeaK0O0NXa4GXOgz4mGdUsDYD0kDsmNHjsHgzXDpLGoe76dQdfGZLbgaKWj0t2XaoMHEjTtPn4b4YAYD2XkOPh47s53EoIBUqBW7fmmPFwaEKO7voSGWJS20H9Ojjy0YQvSi5UiBMItJt8XwaH8a3QZSvp1XwwF0eUdjFWLmYN4UU9DM9hiDBfQwbuu6n5TDS9a9wpTDCwDJmOYwi04rGIUw9pKNHyCiZljZXe4cG35tduR6cISrEIEmYE3XU33LtvkMgDE4JaShmPIWEwMl4ahqIKFq42pLYEByRSWsEhw348VlUkN23Xjxi7q0TR0NWYIbWLa1NWlq4iu3J1j6DmtyqXrYKwMhhCnT7RVSZvoZi6pPyIsKSyC9cmd5aciPoPbHjXgUZTSBperj4JGPvRkwZuga6jh5yPdq5e2AEKEFarK9JcE7ohY29m411j7U9QpMzjkOocmTG2vKD077hRjdX4mmbK4Rj4fTWAVzjor2E9mYcjHIPjLPTzhmmawvIQ5sSH3ESezGm0FGqmnD5LNdIl94dlYQKVWKrjbi7QfJieOOOrXm0tNtNvRghx4DM4j988x1WSB8ppRb9M0KB4HHeEd5vvuEd8ERk3Tz6MvktPPlNvQIbwlE9GXFd46Id5ysCCHw9Qrplaf4CPul2jvuRkEMqYZZ6IZ9qiniJNDNHDcDejRafCKb0r8fDv7lUmyqCaxgKa4XqPYHqg2227wZQ8dM3FBUGPuJUyRnkuGxq5K9s56IPETosvzcEVGMhmlGFHoG4fBZBJxX32h0x0P5fksKM0mx8bN2ncezrFSQZMg1NbqMTWGCoVnA1tcvLQJtAXznlTBoeg5pYLhrS7ImK52pjEZNygJDjndeXHfTtJmZpinYnMnImkuw2yFHzC2erq43fMZVBofE3mjekzyekXRV4RhdxRFQeMAVmCKcbfL3Xo8sthxHFAQaPPmMUgWtNuRlb3SVjkZXWfIPTqBodsDL1AbS80fF91oDNCKUEZCEg0jFceiku3y63AIh3mCvgrpr2uF26t37ayx8aD9l2fzhS7gJniCl4qP4DgD7LtJBVVym4IwatvGM4hv3xaBOhjj8MOrA4cKUUh1BGEIIFE2Zs54TGlPAMt5zmOQlSWqrtqYPPpKBTaBlNOGmzu4CnQTUnHwK6OxczFFPPhBc3jXvSgn3RSzwjhlbf8nCaLHumKylknCKwitVNBNXhFCwGKU1nTNENt601AelsaplzbtjrI8j0sM3xGrsHiG8tM9Nf7lJDRbFlIKqXRcWAzhdD90em4swjzYCstTMOHFu9yh1M2Pj2BNuu9BIkkMb0n0NijwKWaggRNjTk98FsOeZpFrpPxuPSyeR8b2lW52Pik7r6BroNuTz6SvOyB7x2h5hHYLs7JATMlyZarWTWryPMJpd8217JuFDS6cJO1A1knzS3JKpM5C9UM2JGcZ5c3eR9ZXFmE1GbJSgNnPnzjHaXpbWXqglWM9OpIXIP9HQd75yk0jVa9b9HM3zvVtNKKtyNEpjS3MJYWvVhrzgNp1XL2qksEgAUUIcWEmUCOaT3PIt6SZVlOI8Ygj15IdzJgkwSCLZU8YeVmRxW0xRIti6AZbmtYOxoBFo0yVf7IyeexFtSkRc781FRwm3cihqPcNvcy0Hm4FINfzrzocbLA5TbOr3zIl3eNBKbQa2vxziGLOdyRlH33P3fyHADcpzzxciQ0xqcNGJyIzZu0GqqOwdp3nkjld6PV6FZHHS6zgYBHlTJNXntTAY51XRNVzWecyo2jMiVx4E94LeuerxTzl78Vtz2pC1McnsS8IRWkJ80VyHudAGxbh6U630iMnzKwdWTwzco2RJCoIqFIQRerolJtXIPlZxE4CchHG6r09MXIWAnSUjq3UvdfBp0NLgqln727sDcFKjQ4vmLfWrW6CyJLXs3p40yi5VId6JW3jUwu7o6DhotLW5WXjIJks2lLuAETYxgG2kEhxcCPBkry6UvfNnWarPhauNrQmS5hrCodMTnhhshmIJLx7NZWaKMw77sfxnM5pzdeJzwu81YEGEPVpW4qgovGXnMq7Qx7UrNceDSCiizL0XAORmKj4yQbq9AW35gf5VgZIuCwUdkG6FJqlipss1DBh8HfbxtWCfiGiPzb3P7Ua2oGLXpFWgXZucfVGffr93DjouvVYqste1kBLvxuoAJHVqAC0auC9cheh717MKUQkGUavqu7sNAWvKv0AhBddxzwkPIXBRYW6uoyhS7YY5tSoNYW9jFYAMfm9k53jzqyS8fZ3dhh8Qkf7PLXlhEqZ7R276Psdd";
+    size_t bytes_written            = 0;
+
+    strncpy(file_name, FILE_NAME_PATTERN, sizeof(file_name));
+
+    // create a file and write well-known data into it
+    fd = mkstemp(file_name);
+    assert(fd != -1);
+    bytes_written = write(fd, file_contents, sizeof(file_contents));
+    assert(sizeof(file_contents) == bytes_written);
+    close(fd);
+
+    fail_unless(hip_fb_create(&fb, file_name) == 0, NULL);
+    fail_unless((ma = hip_fb_get_mem_area(&fb)) != NULL, NULL);
+    fail_unless((ma->end - ma->start) == sizeof(file_contents));
+    fail_unless(memcmp(ma->start, file_contents, sizeof(file_contents)) == 0,
+                NULL);
+
+    fd = open(file_name, O_RDWR | O_APPEND);
+    assert(fd != -1);
+    bytes_written = write(fd, file_contents, sizeof(file_contents));
+    assert(sizeof(file_contents) == bytes_written);
+    close(fd);
+
+    fail_unless(hip_fb_reload(&fb) == 0, NULL);
+    fail_unless(ma == hip_fb_get_mem_area(&fb), NULL);
+    fail_unless((ma->end - ma->start) == sizeof(file_contents) * 2);
+    fail_unless(memcmp(ma->start, file_contents, sizeof(file_contents)) == 0,
+                NULL);
+    fail_unless(memcmp(ma->start + sizeof(file_contents), file_contents,
+                       sizeof(file_contents)) == 0, NULL);
+
+    remove(file_name);
+}
+END_TEST
+
+START_TEST(test_hip_fb_delete_valid)
+{
+    struct hip_file_buffer fb;
+    int err = 0;
+
+    err = hip_fb_create(&fb, "/etc/fstab");
+    assert(0 == err);
+    hip_fb_delete(&fb);
+}
+END_TEST
+
+START_TEST(test_hip_fb_delete_null_fb)
+{
+    hip_fb_delete(NULL);
+}
+END_TEST
+
+START_TEST(test_hip_fb_reload_null_fb)
+{
+    fail_unless(hip_fb_reload(NULL) == -1, NULL);
+}
+END_TEST
+
+// For unknown reasons, this file does not compile without the following,
+// seemingly useless forward declaration
+Suite *firewall_file_buffer(void);
+
+Suite *firewall_file_buffer(void)
+{
+    Suite *s = suite_create("firewall/file_buffer");
+
+    TCase *tc_core = tcase_create("Core");
+    tcase_add_test(tc_core, test_hip_fb_create_valid);
+    tcase_add_test(tc_core, test_hip_fb_create_null_buffer);
+    tcase_add_test(tc_core, test_hip_fb_create_null_file_name);
+    tcase_add_test(tc_core, test_hip_fb_create_missing_file);
+    tcase_add_test(tc_core, test_hip_fb_create_check_file_integrity);
+    tcase_add_test(tc_core, test_hip_fb_delete_valid);
+    tcase_add_test(tc_core, test_hip_fb_delete_null_fb);
+    tcase_add_test(tc_core, test_hip_fb_reload_null_fb);
+    suite_add_tcase(s, tc_core);
+
+    return s;
+}

=== added file 'test/firewall/line_parser.c'
--- test/firewall/line_parser.c 1970-01-01 00:00:00 +0000
+++ test/firewall/line_parser.c 2010-11-12 17:49:42 +0000
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <check.h>
+
+#include "firewall/line_parser.h"
+#include "firewall/line_parser.c"
+
+// four lines, each 50 characters long (including \n)
+char data[] = "I'm not knocking your want to carry that home    \n\
+Took it with you when you moved and got it broke \n\
+Found the pieces we counted them all alone       \n\
+Didn't add up forgot to carry a zero             ";
+// four pointers to the beginning of the lines
+char *const lines[4] = {
+    data,
+    data + 50,
+    data + 100,
+    data + 150
+};
+// the memory area describing data
+const struct hip_mem_area ma = { data, data + sizeof(data) };
+
+// these tests do not clean up after themselves because they assume that
+// check runs them in dedicated processes so the OS does the cleanup
+START_TEST(test_hip_lp_create_valid)
+{
+    struct hip_line_parser lp;
+
+    fail_unless(hip_lp_create(&lp, &ma) == 0, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_create_null_lp)
+{
+    fail_unless(hip_lp_create(NULL, &ma) == -1, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_create_null_ma)
+{
+    struct hip_line_parser lp;
+
+    fail_unless(hip_lp_create(&lp, NULL) == -1, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_delete_valid)
+{
+    struct hip_line_parser lp;
+    int err = 0;
+
+    err = hip_lp_create(&lp, &ma);
+    assert(0 == err);
+    hip_lp_delete(&lp);
+}
+END_TEST
+
+START_TEST(test_hip_lp_delete_null_lp)
+{
+    hip_lp_delete(NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_first_valid)
+{
+    struct hip_line_parser lp;
+    int err = 0;
+
+    err = hip_lp_create(&lp, &ma);
+    assert(0 == err);
+    fail_unless(hip_lp_first(&lp) == lines[0], NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_first_null_lp)
+{
+    fail_unless(hip_lp_first(NULL) == NULL, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_next_valid)
+{
+    struct hip_line_parser lp;
+    int err     = 0;
+    char *first = NULL;
+
+    err = hip_lp_create(&lp, &ma);
+    assert(0 == err);
+    first = hip_lp_first(&lp);
+    assert(first == lines[0]);
+
+    fail_unless(hip_lp_next(&lp) == lines[1], NULL);
+    fail_unless(hip_lp_next(&lp) == lines[2], NULL);
+    fail_unless(hip_lp_next(&lp) == lines[3], NULL);
+    fail_unless(hip_lp_next(&lp) == NULL, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_lp_next_null_lp)
+{
+    fail_unless(hip_lp_next(NULL) == NULL, NULL);
+}
+END_TEST
+
+// For unknown reasons, this file does not compile without the following,
+// seemingly useless forward declaration
+Suite *firewall_line_parser(void);
+
+Suite *firewall_line_parser(void)
+{
+    Suite *s = suite_create("firewall/line_parser");
+
+    TCase *tc_core = tcase_create("Core");
+    tcase_add_test(tc_core, test_hip_lp_create_valid);
+    tcase_add_test(tc_core, test_hip_lp_create_null_lp);
+    tcase_add_test(tc_core, test_hip_lp_create_null_ma);
+    tcase_add_test(tc_core, test_hip_lp_delete_valid);
+    tcase_add_test(tc_core, test_hip_lp_delete_null_lp);
+    tcase_add_test(tc_core, test_hip_lp_first_valid);
+    tcase_add_test(tc_core, test_hip_lp_first_null_lp);
+    tcase_add_test(tc_core, test_hip_lp_next_valid);
+    tcase_add_test(tc_core, test_hip_lp_next_null_lp);
+    suite_add_tcase(s, tc_core);
+
+    return s;
+}

=== added file 'test/firewall/port_bindings.c'
--- test/firewall/port_bindings.c       1970-01-01 00:00:00 +0000
+++ test/firewall/port_bindings.c       2010-11-12 17:49:42 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <netinet/in.h>
+#include <assert.h>
+#include <check.h>
+#include <stdio.h>
+
+#include "firewall/port_bindings.h"
+#include "firewall/port_bindings.c"
+
+// these tests do not clean up after themselves because they assume that
+// check runs them in dedicated processes so the OS does the cleanup.
+START_TEST(test_hip_port_bindings_init_with_cache)
+{
+    fail_unless(hip_port_bindings_init(true) == 0, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_port_bindings_init_without_cache)
+{
+    fail_unless(hip_port_bindings_init(false) == 0, NULL);
+}
+END_TEST
+
+START_TEST(test_hip_port_bindings_uninit_with_cache)
+{
+    int err = 0;
+
+    err = hip_port_bindings_init(true);
+    assert(0 == err);
+
+    hip_port_bindings_uninit();
+}
+END_TEST
+
+START_TEST(test_hip_port_bindings_uninit_without_cache)
+{
+    int err = 0;
+
+    err = hip_port_bindings_init(false);
+    assert(0 == err);
+
+    hip_port_bindings_uninit();
+}
+END_TEST
+
+static void test_hip_port_bindings_get(const bool enable_cache)
+{
+    int err = 0;
+    enum hip_port_binding binding;
+
+    err = hip_port_bindings_init(enable_cache);
+    assert(0 == err);
+
+    binding = hip_port_bindings_get(IPPROTO_TCP, htons(631));
+    fail_unless(HIP_PORT_INFO_IPV6UNBOUND == binding ||
+                HIP_PORT_INFO_IPV6BOUND == binding, NULL);
+    if (HIP_PORT_INFO_IPV6UNBOUND == binding) {
+        printf("hip_port_bindings_get() reports your CUPS port 631 to not be 
bound under IPv6.\n"
+               " This is only correct if you do not have CUPS installed or 
deliberately disabled\n"
+               " IPv6 support.\n");
+    } else {
+        printf("hip_port_bindings_get() reports your CUPS port 631 to be bound 
under IPv6. This\n"
+               " is only correct if you have CUPS running and IPv6 support 
enabled.\n");
+    }
+}
+
+START_TEST(test_hip_port_bindings_get_with_cache)
+{
+    test_hip_port_bindings_get(true);
+}
+END_TEST
+
+START_TEST(test_hip_port_bindings_get_without_cache)
+{
+    test_hip_port_bindings_get(false);
+}
+END_TEST
+
+// For unknown reasons, this file does not compile without the following,
+// seemingly useless forward declaration
+Suite *firewall_port_bindings(void);
+
+Suite *firewall_port_bindings(void)
+{
+    Suite *s = suite_create("firewall/port_bindings");
+
+    TCase *tc_core = tcase_create("Core");
+    tcase_add_test(tc_core, test_hip_port_bindings_init_with_cache);
+    tcase_add_test(tc_core, test_hip_port_bindings_init_without_cache);
+    tcase_add_test(tc_core, test_hip_port_bindings_uninit_with_cache);
+    tcase_add_test(tc_core, test_hip_port_bindings_uninit_without_cache);
+    tcase_add_test(tc_core, test_hip_port_bindings_get_with_cache);
+    tcase_add_test(tc_core, test_hip_port_bindings_get_without_cache);
+    suite_add_tcase(s, tc_core);
+
+    return s;
+}

=== added file 'test/fw_port_bindings_performance.c'
--- test/fw_port_bindings_performance.c 1970-01-01 00:00:00 +0000
+++ test/fw_port_bindings_performance.c 2010-11-12 17:49:42 +0000
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @author Stefan Goetz <stefan.goetz@xxxxxxxxxxxxxxxxx>
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "firewall/file_buffer.h"
+#include "firewall/line_parser.h"
+#include "firewall/port_bindings.h"
+
+static double time_clock(const unsigned int iterations)
+{
+    clock_t start, end, tmp;
+    unsigned int i;
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        tmp = clock();
+    }
+    end = clock();
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_fb_create_delete(const unsigned int iterations,
+                                        const char *file_name)
+{
+    clock_t start, end;
+    unsigned int i;
+    struct hip_file_buffer fb;
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        if (hip_fb_create(&fb, file_name) == 0) {
+            hip_fb_delete(&fb);
+        }
+    }
+    end = clock();
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_fb_reload(const unsigned int iterations,
+                                 const char *file_name)
+{
+    clock_t start, end;
+    unsigned int i;
+    struct hip_file_buffer fb;
+    int err;
+
+    err = hip_fb_create(&fb, file_name);
+    assert(0 == err);
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        err = hip_fb_reload(&fb);
+        assert(err == 0);
+    }
+    end = clock();
+
+    hip_fb_delete(&fb);
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_lp_create_delete(const unsigned int iterations)
+{
+    clock_t start, end;
+    unsigned int i;
+    struct hip_mem_area ma = { 0, 0 };
+    struct hip_line_parser lp;
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        if (hip_lp_create(&lp, &ma) == 0) {
+            hip_lp_delete(&lp);
+        }
+    }
+    end = clock();
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_lp_first(const unsigned int iterations)
+{
+    clock_t start, end;
+    unsigned int i;
+    struct hip_line_parser lp;
+    char *line;
+    struct hip_mem_area ma = { 0, 0 };
+    int err;
+
+    err = hip_lp_create(&lp, &ma);
+    assert(0 == err);
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        line = hip_lp_first(&lp);
+    }
+    end = clock();
+
+    hip_lp_delete(&lp);
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_lp_next(const unsigned int iterations,
+                               const char *file_name)
+{
+    clock_t start, end;
+    unsigned int i;
+    struct hip_file_buffer fb;
+    struct hip_line_parser lp;
+    char *line;
+    int err;
+
+    err = hip_fb_create(&fb, file_name);
+    assert(0 == err);
+    err = hip_lp_create(&lp, hip_fb_get_mem_area(&fb));
+    assert(0 == err);
+    line = hip_lp_first(&lp);
+    assert(line != NULL);
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        line = hip_lp_next(&lp);
+    }
+    end = clock();
+
+    hip_lp_delete(&lp);
+    hip_fb_delete(&fb);
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_lp_parse_file(const unsigned int iterations,
+                                     const char *file_name)
+{
+    clock_t start, end;
+    unsigned int i;
+    struct hip_file_buffer fb;
+    struct hip_line_parser lp;
+    char *line;
+    int err;
+
+    err = hip_fb_create(&fb, file_name);
+    assert(0 == err);
+    err = hip_lp_create(&lp, hip_fb_get_mem_area(&fb));
+    assert(0 == err);
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        line = hip_lp_first(&lp);
+        while (line != NULL) {
+            line = hip_lp_next(&lp);
+        }
+    }
+    end = clock();
+
+    hip_lp_delete(&lp);
+    hip_fb_delete(&fb);
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_port_binding_create_delete(const unsigned int 
iterations,
+                                                  const bool enable_cache)
+{
+    clock_t start, end;
+    unsigned int i;
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        hip_port_bindings_init(enable_cache);
+        hip_port_bindings_uninit();
+    }
+    end = clock();
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+static double time_hip_port_bindings_get(const unsigned int iterations,
+                                         const uint8_t proto,
+                                         const in_port_t port,
+                                         const bool enable_cache)
+{
+    clock_t start, end;
+    unsigned int i;
+    enum hip_port_binding pi;
+
+    hip_port_bindings_init(enable_cache);
+
+    start = clock();
+    for (i = 0; i < iterations; i += 1) {
+        pi = hip_port_bindings_get(proto, port);
+    }
+    end = clock();
+
+    hip_port_bindings_uninit();
+
+    return (((double) (end - start)) / CLOCKS_PER_SEC) / iterations;
+}
+
+int main(void)
+{
+    const unsigned int iterations = 10000;
+    const char *file_name = "/proc/net/tcp6";
+    const uint8_t proto = 6;
+    const in_port_t port = 0xFFFF;
+    bool enable_cache = false;
+
+    printf("Testing clock reading used for benchmarks:\n"
+           "  - call clock()\n"
+           "  ==> time_clock(%d): %fs\n\n", iterations,
+           time_clock(iterations));
+
+    printf("Testing file buffer allocation and de-allocation:\n"
+           "  - call hip_fb_create() to\n"
+           "    - zero the file buffer object\n"
+           "    - open the file\n"
+           "    - call hip_fb_reload() to\n"
+           "      - allocate a memory buffer for the file data (if new fb 
object)\n"
+           "      - read the file data into the memory buffer\n"
+           "  - call hip_fb_delete() to\n"
+           "    - de-allocate the file buffer object\n"
+           "  ==> time_hip_fb_create_delete(%d, %s): %fs\n\n", iterations,
+           file_name, time_hip_fb_create_delete(iterations, file_name));
+
+    printf("Testing file buffer file access:\n"
+           "  - call hip_fb_reload() to\n"
+           "    - allocate a memory buffer for the file data (if new fb 
object)\n"
+           "    - read the file data into the memory buffer\n"
+           "  ==> time_hip_fb_reload(%d, %s): %fs\n\n", iterations, file_name,
+           time_hip_fb_reload(iterations, file_name));
+
+    printf("Testing line parser allocation and de-allocation:\n"
+           "  - call hip_lp_create() to\n"
+           "    - allocate a line parser object\n"
+           "    - call hip_fb_create() (s.a.)\n"
+           "  - call hip_lp_delete() to\n"
+           "    - de-allocate the line parser object\n"
+           "  ==> time_hip_lp_create_delete(%d): %fs\n\n", iterations,
+           time_hip_lp_create_delete(iterations));
+
+    printf("Testing line parser parsing function:\n"
+           "  - call hip_lp_first() to\n"
+           "    - retrieve a pointer to the beginning of the file\n"
+           "  ==> time_hip_lp_first(%d): %fs\n\n", iterations,
+           time_hip_lp_first(iterations));
+
+    printf("Testing line parser parsing function:\n"
+           "  - call hip_lp_next() to\n"
+           "    - search for the next line\n"
+           "    - retrieve a pointer to the beginning of the line\n"
+           "  ==> time_hip_lp_next(%d, %s): %fs\n\n", iterations, file_name,
+           time_hip_lp_next(iterations, file_name));
+
+    printf("Testing line parser whole file parsing:\n"
+           "  - call hip_lp_first() (s.a.)\n"
+           "  - call hip_lp_next() (s.a.) until the end of the file\n"
+           "  ==> time_hip_lp_parse_file(%d, %s): %fs\n\n", iterations, 
file_name,
+           time_hip_lp_parse_file(iterations, file_name));
+
+    printf("Testing port binding allocation and de-allocation without cache:\n"
+           "  - call hip_port_bindings_init() to\n"
+           "    - create tcp6 and udp6 line parser objects\n"
+           "  - call hip_port_bindings_uninit() to\n"
+           "    - delete tcp6 and udp6 line parser objects\n"
+           "  ==> time_hip_port_binding_create_delete(%d, %d): %fs\n\n",
+           iterations, enable_cache,
+           time_hip_port_binding_create_delete(iterations, enable_cache));
+
+    printf("Testing port binding parsing without cache:\n"
+           "  - call hip_port_bindings_get() to\n"
+           "    - parse proc file\n"
+           "  ==> time_hip_port_bindings_get(%d, %d, 0x%X, %d): %fs\n\n",
+           iterations, proto, port, enable_cache,
+           time_hip_port_bindings_get(iterations, proto, port, enable_cache));
+
+    enable_cache = true;
+    printf("Testing port binding allocation and de-allocation with cache:\n"
+           "  - call hip_port_bindings_init() to\n"
+           "    - allocate and zero cache\n"
+           "    - create tcp6 and udp6 line parser objects\n"
+           "  - call hip_port_bindings_uninit() to\n"
+           "    - delete tcp6 and udp6 line parser objects\n"
+           "    - de-allocate cache\n"
+            "  ==> time_hip_port_binding_create_delete(%d, %d): %fs\n\n",
+            iterations, enable_cache,
+            time_hip_port_binding_create_delete(iterations, enable_cache));
+
+    printf("Testing port binding parsing with cache:\n"
+           "  - call hip_port_bindings_get() to\n"
+           "    - check cache for port binding\n"
+           "    - parse proc file if no cache entry\n"
+            "  ==> time_hip_port_bindings_get(%d, %d, 0x%X, %d): %fs\n\n",
+            iterations, proto, port, enable_cache,
+            time_hip_port_bindings_get(iterations, proto, port, enable_cache));
+
+    return 0;
+}

=== modified file 'tools/hipl_autobuild.sh'
--- tools/hipl_autobuild.sh     2010-11-05 08:46:43 +0000
+++ tools/hipl_autobuild.sh     2010-11-12 15:50:17 +0000
@@ -143,10 +143,10 @@
 run_program "make -j check"
 
 # PISA configuration
-compile --enable-firewall --disable-rvs --disable-opportunistic 
--disable-profiling --enable-debug --enable-midauth --disable-performance 
--disable-demo
+compile --enable-firewall --disable-rvs --disable-opportunistic 
--disable-profiling --enable-debug --enable-midauth --disable-performance
 
 # Max compile coverage configuration
-FEATURES_ALL="--enable-firewall --enable-rvs --enable-opportunistic 
--enable-profiling --disable-debug --enable-midauth --enable-performance 
--enable-demo"
+FEATURES_ALL="--enable-firewall --enable-rvs --enable-opportunistic 
--enable-profiling --disable-debug --enable-midauth --enable-performance"
 compile $FEATURES_ALL
 
 # Max compile coverage configuration without optimization

Other related posts:

  • » [hipl-dev] [Branch ~toxedvirus/hipl/hipfw-modules] Rev 5013: Merged trunk. - noreply