Committer: Miika Komu <miika@xxxxxx> Date: 19/03/2010 at 11:53:30 Revision: 3802 Revision-id: miika@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Branch nick: release-1.0.5 Log: Syncronized to trunk revisions 3833..4000 Modified: D debian/README.Debian D debian/cron.d.ex D debian/emacsen-install.ex D debian/emacsen-remove.ex D debian/emacsen-startup.ex D debian/manpage.1.ex D debian/manpage.sgml.ex D debian/manpage.xml.ex D debian/menu.ex D debian/watch.ex D firewall/proxy.c.doxyme D firewall/proxydb.c.doxyme D hipd/blind.c.doxyme D hipd/bos.c.doxyme D hipd/close.c.doxyme D hipd/cookie.c.doxyme D hipd/dh.c.doxyme D hipd/hadb.c.doxyme D hipd/hadb_legacy.c.doxyme D hipd/hi3.c.doxyme D hipd/hidb.c.doxyme D hipd/hipd.c.doxyme D hipd/hipqueue.c.doxyme D hipd/hipqueue.h.doxyme D hipd/hiprelay.c.doxyme D hipd/icookie.c D hipd/icookie.c.doxyme D hipd/icookie.h D hipd/icookie.h.doxyme D hipd/init.c.doxyme D hipd/keymat.c.doxyme D hipd/maintenance.c.doxyme D hipd/oppdb.c.doxyme D hipd/oppipdb.c.doxyme D lib/core/getendpointinfo.h.doxyme D lib/core/kerncompat.h.doxyme D lib/core/misc.c D lib/core/misc.c.doxyme D lib/core/misc.h D lib/core/misc.h.doxyme D lib/core/utils.h.doxyme D lib/tool/crypto.c.doxyme A lib/core/filemanip.c A lib/core/filemanip.h A lib/core/hip_udp.c A lib/core/hip_udp.h A lib/core/hit.c A lib/core/hit.h A lib/core/hostid.c A lib/core/hostid.h A lib/core/hostsfiles.c A lib/core/hostsfiles.h A lib/core/keylen.c A lib/core/keylen.h A lib/core/solve.c A lib/core/solve.h A lib/core/straddr.c A lib/core/straddr.h A lib/core/transform.c A lib/core/transform.h A lib/ipsec/pfkeyv2.h A lib/tool/checksum.c A lib/tool/checksum.h A patches/kernel/2.6.20/ A patches/kernel/2.6.20/beet-2.6.20.21.patch A patches/kernel/2.6.20/beet-2.6.20.patch A patches/kernel/2.6.20/notes.txt M .bzrignore M Android.mk M Makefile.am M agent/agent.c M agent/connhipd.c M autogen.sh M configure.ac M debian/changelog M debian/control M debian/copyright M debian/dirs M debian/docs M debian/rules M doc/HOWTO.xml M firewall/cache.c M firewall/cache_port.c M firewall/common_hipd_msg.c M firewall/conntrack.c M firewall/conntrack.h M firewall/datapkt.c M firewall/esp_prot_api.c M firewall/esp_prot_config.h M firewall/esp_prot_conntrack.c M firewall/esp_prot_conntrack.h M firewall/esp_prot_fw_msg.c M firewall/firewall.c M firewall/firewall.h M firewall/firewall_control.c M firewall/firewall_control.h M firewall/firewall_defines.h M firewall/firewalldb.c M firewall/lsi.c M firewall/lsi.h M firewall/midauth.c M firewall/midauth.h M firewall/opptcp.c M firewall/pisa.c M firewall/proxy.c M firewall/proxy.h M firewall/proxydb.c M firewall/rule_management.c M firewall/sysopp.c M firewall/user_ipsec_api.c M firewall/user_ipsec_api.h M firewall/user_ipsec_esp.c M firewall/user_ipsec_esp.h M firewall/user_ipsec_fw_msg.c M firewall/user_ipsec_sadb.c M firewall/user_ipsec_sadb.h M hipd/accessor.c M hipd/accessor.h M hipd/blind.c M hipd/bos.c M hipd/bos.h M hipd/cert.h M hipd/close.c M hipd/close.h M hipd/configfilereader.c M hipd/configfilereader.h M hipd/cookie.c M hipd/cookie.h M hipd/dh.c M hipd/dht.c M hipd/dht.h M hipd/dhtqueue.c M hipd/esp_prot_anchordb.c M hipd/esp_prot_hipd_msg.c M hipd/esp_prot_light_update.c M hipd/hadb.c M hipd/hadb.h M hipd/hadb_legacy.c M hipd/hi3.c M hipd/hi3.h M hipd/hidb.c M hipd/hipd.c M hipd/hipd.h M hipd/hiprelay.c M hipd/hiprelay.h M hipd/init.c M hipd/input.c M hipd/input.h M hipd/keymat.c M hipd/keymat.h M hipd/maintenance.c M hipd/nat.c M hipd/nat.h M hipd/netdev.c M hipd/netdev.h M hipd/nsupdate.c M hipd/oppdb.c M hipd/oppdb.h M hipd/oppipdb.c M hipd/output.c M hipd/output.h M hipd/pfkeyapi.c M hipd/pfkeyapi.h M hipd/registration.c M hipd/registration.h M hipd/update.c M hipd/user.c M hipd/user_ipsec_hipd_msg.c M i3/i3_client/http.c M i3/i3_client/i3_client_context.c M i3/i3_client/i3_client_pkt.c M i3/i3_client/i3_client_trigger.c M i3/i3_client/i3server_list.c M i3/i3_client/ping.c M i3/i3_client/ping_thread.c M lib/android/regex.c M lib/conf/hipconf.c M lib/conf/hipconf.h M lib/core/builder.c M lib/core/builder.h M lib/core/certtools.c M lib/core/certtools.h M lib/core/crypto.c M lib/core/crypto.h M lib/core/debug.c M lib/core/debug.h M lib/core/hashtable.c M lib/core/hashtable.h M lib/core/hip_capability.c M lib/core/hip_statistics.c M lib/core/message.c M lib/core/message.h M lib/core/prefix.c M lib/core/prefix.h M lib/core/protodefs.h M lib/core/sqlitedbapi.c M lib/core/sqlitedbapi.h M lib/core/state.h M lib/dht/libhipdht.c M lib/dht/libhipdht.h M lib/dht/libhipdhtxml.c M lib/ipsec/ipsec_strerror.c M lib/ipsec/pfkey.c M lib/ipsec/policy_parse.c M lib/ipsec/policy_parse.y M lib/ipsec/policy_token.l M lib/opphip/wrap.c M lib/opphip/wrap_db.c M lib/performance/performance.c M lib/tool/lutil.c M lib/tool/lutil.h M lib/tool/nlink.c M lib/tool/nlink.h M lib/tool/pk.c M lib/tool/xfrmapi.c M lib/tool/xfrmapi.h M patches/openwrt/package/Makefile M release.version M test/auth_performance.c M test/certteststub.c M test/conntest-client-hip.c M test/conntest-client-native.c M test/conntest-client-opp.c M test/conntest-server.c M test/conntest.c M test/conntest.h M test/cookietest.c M test/dh_performance.c M test/dhtteststub.c M test/keygentest.c M test/performance/perf_measure.sh M test/sqliteteststub.c M tools/hipl_autobuild M tools/pisacert.c === modified file '.bzrignore' --- .bzrignore 2010-03-01 12:17:31 +0000 +++ .bzrignore 2010-03-19 09:53:35 +0000 @@ -1,3 +1,4 @@ +*.ho *.la *.lo ./compile === modified file 'Android.mk' --- Android.mk 2010-02-01 13:24:34 +0000 +++ Android.mk 2010-03-19 09:53:35 +0000 @@ -34,7 +34,6 @@ netdev.c \ bos.c \ nat.c \ - icookie.c \ init.c \ maintenance.c \ accessor.c \ === modified file 'Makefile.am' --- Makefile.am 2010-03-19 09:32:05 +0000 +++ Makefile.am 2010-03-19 09:53:35 +0000 @@ -1,23 +1,20 @@ ACLOCAL_AMFLAGS = -I m4 +HIPL_HEADER_LIST = $(wildcard $(addprefix $(srcdir)/,agent/*.h firewall/*.h hipd/*.h i3/*/*.h lib/*/*.h test/*.h)) + # For "make dist" # # XX FIX: use dist_doc_DATA for all documentation (if you change this, # make sure the check the "make bin" still works) # -EXTRA_DIST = debian doc hipext hipfwmi patches test/packaging test/configs -EXTRA_DIST += Android.mk check_header_verbosity.sh tcp verbose-headers.txt +EXTRA_DIST = debian doc hipext hipfwmi lib/android patches EXTRA_DIST += hipsock jip -EXTRA_DIST += autogen.sh i3-cfg-PL.xml release.version -EXTRA_DIST += $(wildcard agent/*.h) -EXTRA_DIST += $(wildcard i3/*/*.h) -EXTRA_DIST += $(wildcard lib/android/*.c) -EXTRA_DIST += $(wildcard lib/*/*.h) -EXTRA_DIST += $(wildcard hipd/*.h) -EXTRA_DIST += $(wildcard firewall/*.h) -EXTRA_DIST += $(wildcard test/*.h) +EXTRA_DIST += test/packaging test/configs +EXTRA_DIST += Android.mk autogen.sh check_header_verbosity.sh i3-cfg-PL.xml +EXTRA_DIST += release.version tcp verbose-headers.txt EXTRA_DIST += tools/gen-python-starter.sh EXTRA_DIST += m4 # required for CentOS "make bin" target +EXTRA_DIST += $(HIPL_HEADER_LIST) # XX TODO: remove these when maemo building uses spec files EXTRA_DIST += libinet6/include @@ -167,7 +164,6 @@ hipd/registration.c \ hipd/user.c \ hipd/hadb.c \ - hipd/oppdb.c \ hipd/close.c \ hipd/configfilereader.c \ hipd/input.c \ @@ -177,7 +173,6 @@ hipd/netdev.c \ hipd/bos.c \ hipd/nat.c \ - hipd/icookie.c \ hipd/init.c \ hipd/maintenance.c \ hipd/accessor.c \ @@ -212,6 +207,10 @@ hipd_hipd_SOURCES += hipd/pisa.c endif +if HIP_OPPORTUNISTIC +hipd_hipd_SOURCES += hipd/oppdb.c +endif + firewall_hipfw_SOURCES = firewall/firewall.c \ firewall/conntrack.c \ firewall/rule_management.c \ @@ -279,8 +278,16 @@ lib/core/debug.c \ lib/core/message.c \ lib/core/esp_prot_common.c \ - lib/core/misc.c \ + lib/core/hostsfiles.c \ + lib/core/filemanip.c \ lib/core/hashchain.c \ + lib/core/hostid.c \ + lib/core/hip_udp.c \ + lib/core/solve.c \ + lib/core/transform.c \ + lib/core/keylen.c \ + lib/core/hit.c \ + lib/core/straddr.c \ lib/core/sqlitedbapi.c \ lib/core/hashchain_store.c \ lib/core/hip_statistics.c \ @@ -293,7 +300,8 @@ lib_tool_libhiptool_la_SOURCES = lib/tool/pk.c \ lib/tool/nlink.c \ - lib/tool/lutil.c + lib/tool/lutil.c \ + lib/tool/checksum.c ############################ NOTE ################################## # @@ -323,10 +331,8 @@ #DISTCLEANFILES = policy_parse.c policy_token.c policy_token.h DISTCLEANFILES = lib/ipsec/policy_token.h -if HIP_PFKEY -BUILT_SOURCES += lib/ipsec/policy_parse.h -else # don't use libipsec, but xfrmapi +if !HIP_PFKEY lib_tool_libhiptool_la_SOURCES += lib/tool/xfrmapi.c endif # HIPPFKEY @@ -418,13 +424,15 @@ ### *_LDADD ### -test_conntest_client_opp_LDADD = lib/core/libhipcore.la \ - lib/tool/libhiptool.la +test_conntest_client_opp_LDADD = if HIP_OPPORTUNISTIC test_conntest_client_opp_LDADD += lib/opphip/libopphip.la endif +test_conntest_client_opp_LDADD += lib/core/libhipcore.la \ + lib/tool/libhiptool.la + if HIP_PERFORMANCE test_conntest_client_opp_LDADD += lib/performance/libperformance.la endif @@ -506,9 +514,9 @@ if HIP_DHT -test_dhtteststub_LDADD = lib/core/libhipcore.la \ - lib/tool/libhiptool.la \ - lib/dht/libhipdht.la +test_dhtteststub_LDADD = lib/dht/libhipdht.la \ + lib/core/libhipcore.la \ + lib/tool/libhiptool.la if HIP_PERFORMANCE test_dhtteststub_LDADD += lib/performance/libperformance.la @@ -548,9 +556,9 @@ lib/performance/libperformance.la endif -tools_hipconf_LDADD = lib/core/libhipcore.la \ - lib/tool/libhiptool.la \ - lib/conf/libhipconf.la +tools_hipconf_LDADD = lib/conf/libhipconf.la \ + lib/core/libhipcore.la \ + lib/tool/libhiptool.la # required by libhipconf if HIP_PERFORMANCE @@ -708,4 +716,11 @@ rm -f aclocal.m4 compile config.* configure depcomp install-sh rm -f ltmain.sh m4/*.m4 Makefile.in missing py-compile -.PHONY: bin deb doxygen increl olddeb rpm syncrepo +HIPL_HEADER_OBJS = $(HIPL_HEADER_LIST:.h=.ho) +CLEANFILES += $(HIPL_HEADER_OBJS) + +checkheaders: $(HIPL_HEADER_OBJS) +%.ho: %.h + $(CC) -I$(srcdir) -I$(builddir) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -o $@ $< + +.PHONY: bin checkheaders deb doxygen increl olddeb rpm syncrepo === modified file 'agent/agent.c' --- agent/agent.c 2010-03-03 13:16:18 +0000 +++ agent/agent.c 2010-03-19 09:53:35 +0000 @@ -16,10 +16,6 @@ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #include <fcntl.h> #include <sys/un.h> #include <sys/types.h> @@ -32,6 +28,7 @@ #include <unistd.h> #include <time.h> +#include "config.h" #include "agent.h" #include "tools.h" #include "gui_interface.h" === modified file 'agent/connhipd.c' --- agent/connhipd.c 2010-03-19 09:25:52 +0000 +++ agent/connhipd.c 2010-03-19 09:53:35 +0000 @@ -18,6 +18,7 @@ #include <errno.h> #include <string.h> #include <fcntl.h> +#include <unistd.h> #include "connhipd.h" #include "agent.h" @@ -30,6 +31,7 @@ #include "lib/core/icomm.h" #include "lib/core/message.h" #include "lib/core/builder.h" +#include "lib/core/straddr.h" /* This socket is used for communication between agent and HIP daemon. */ int hip_agent_sock = 0; === modified file 'autogen.sh' --- autogen.sh 2010-03-19 09:32:05 +0000 +++ autogen.sh 2010-03-19 09:53:35 +0000 @@ -6,18 +6,18 @@ echo "The following packages are needed for building HIPL software bundle:" if test -e /etc/debian_version then - echo "apt-get install automake autoconf libtool gcc g++ libgtk2.0-dev libssl-dev libxml2-dev xmlto doxygen iproute netcat6 iptables-dev libcap-dev libsqlite3-dev libuuid1 libnet-ip-perl libnet-dns-perl libsocket6-perl libio-socket-inet6-perl" + echo "apt-get install automake autoconf libtool gcc libgtk2.0-dev libssl-dev libxml2-dev xmlto doxygen iproute netcat6 iptables-dev libcap-dev libsqlite3-dev libuuid1 libnet-ip-perl libnet-dns-perl libsocket6-perl libio-socket-inet6-perl" echo "Optional: apt-get install pax miredo bzr" elif test -e /etc/redhat-release then - echo "yum install gcc gcc-c++ openssl-devel libxml2-devel autoconf automake libtool iproute gtk2-devel xmlto doxygen iptables-devel libcap-devel sqlite-devel rpm-build perl-Net-IP perl-Net-DNS perl-Socket6 perl-IO-Socket-INET6" + echo "yum install gcc openssl-devel libxml2-devel autoconf automake libtool iproute gtk2-devel xmlto doxygen iptables-devel libcap-devel sqlite-devel rpm-build perl-Net-IP perl-Net-DNS perl-Socket6 perl-IO-Socket-INET6" echo "Optional: yum install uuid miredo bzr" echo "If yum does not find a package, try searching 'rpm.pbone.net' or 'rpmfind.net' or install from sources" else echo -n "Unknown linux system:" cat /etc/lsb-release echo "You should install the following software:" - echo "autoreconf, automake, autoconf, libtool, gcc, g++, xmlto, doxygen, iproute, netcat6, Socket6, IO::Socket::INET6, Net::IP and Net::DNS modules for perl" + echo "autoreconf, automake, autoconf, libtool, gcc, xmlto, doxygen, iproute, netcat6, Socket6, IO::Socket::INET6, Net::IP and Net::DNS modules for perl" echo "And the following packages with their development headers:" echo "libgtk2.0, openssl, libxml2, iptables, libcap, libsqlite3" echo "Optionally you can install also uuid, miredo, bzr" === modified file 'configure.ac' --- configure.ac 2010-03-19 09:32:05 +0000 +++ configure.ac 2010-03-19 09:53:35 +0000 @@ -11,11 +11,14 @@ AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign subdir-objects]) +# AC_PROG_LIBTOOL() could be replaced with LT_INIT(disable-shared) but +# OpenWRT (Mar 2010) is running too old version of libtool +# LT_INIT(disable-shared) +AC_PROG_LIBTOOL(disable-shared) # Checks for programs. AC_PROG_CC AC_PROG_INSTALL -AC_PROG_LIBTOOL(disable-shared) AM_PROG_CC_C_O # Required in CentOS # Check for python for tools directory @@ -24,11 +27,16 @@ # Checks for libraries. AC_CHECK_LIB(crypto, DSA_generate_key,, AC_MSG_ERROR(openssl lib not found)) +# Check for ec crypto in openssl +AC_CHECK_FUNC(EC_KEY_new, + AC_DEFINE(HAVE_EC_CRYPTO) + AH_TEMPLATE(HAVE_EC_CRYPTO, [Defined to 1 if ec is enabled.]),) # We need the math lib in the registration extension. AC_CHECK_LIB(m, pow,, AC_MSG_ERROR(Math lib not found)) # Checks for header files. -# libintl.h and alloca.h are only used in libhipandroid/regex.c - remove if possible +# libintl.h and alloca.h are only used in libhipandroid/regex.c +# REMOVE IF POSSIBLE AC_CHECK_HEADERS([alloca.h libintl.h]) case "$host" in @@ -90,197 +98,189 @@ usagi_libc=23 AC_SUBST(usagi_libc) + AC_ARG_ENABLE(firewall, - AC_HELP_STRING([--enable-firewall], - [HIP enabled firewall daemon (default is YES)]), - [ac_cv_use_firewall=$enableval], - [ac_cv_use_firewall=yes]) + AS_HELP_STRING([--enable-firewall], + [HIP enabled firewall daemon (default is YES)]), + [ac_cv_use_firewall=$enableval], + [ac_cv_use_firewall=yes]) AC_CACHE_CHECK([whether to use firewall], - [ac_cv_use_firewall], [ac_cv_use_firewall=yes]) + [ac_cv_use_firewall], + [ac_cv_use_firewall=yes]) if test x"$ac_cv_use_firewall" = x"yes"; then - AC_CHECK_LIB(ipq, ipq_create_handle,, [AC_MSG_ERROR([libipq not found])]) - AC_CHECK_LIB(config, config_setting_index,, [AC_MSG_WARN([libconfig not found, using default configuration of esp token extension])]) - AC_DEFINE(CONFIG_HIP_FIREWALL) - AH_TEMPLATE(CONFIG_HIP_FIREWALL, [Defined to 1 if firewall is enabled.]) + AC_CHECK_LIB(ipq, ipq_create_handle,, [AC_MSG_ERROR([libipq not found])]) + AC_CHECK_LIB(config, config_setting_index,, + [AC_MSG_WARN([libconfig not found, using default config])]) + AC_DEFINE(CONFIG_HIP_FIREWALL) + AH_TEMPLATE(CONFIG_HIP_FIREWALL, [Defined to 1 if firewall is enabled.]) fi AM_CONDITIONAL(HIP_FIREWALL, test x"$ac_cv_use_firewall" = x"yes") # Try to automatically detect GTK if not disabled or enabled by user -PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.10.0, ac_cv_use_agent=yes, ac_cv_use_agent=no) +PKG_CHECK_MODULES(GTK, + gtk+-2.0 >= 2.10.0, + ac_cv_use_agent=yes, + ac_cv_use_agent=no) if test x"$ac_cv_use_agent" = x"no"; then - PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, ac_cv_use_agent=yes, ac_cv_use_agent=no) - if test x"$ac_cv_use_agent" = x"yes"; then - AC_MSG_WARN(You are missing >= GTK 2.10, it is VERY recommended) - fi + PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, ac_cv_use_agent=yes, + ac_cv_use_agent=no) + if test x"$ac_cv_use_agent" = x"yes"; then + AC_MSG_WARN(You are missing >= GTK 2.10, it is VERY recommended) + fi fi AC_ARG_ENABLE(agent, - AC_HELP_STRING([--enable-agent], - [HIP enable user agent (default is YES)]), - [ac_cv_use_agent=$enableval],) + AS_HELP_STRING([--enable-agent], + [HIP enable user agent (default is YES)]), + [ac_cv_use_agent=$enableval], + [ac_cv_use_agent=yes]) AC_CACHE_CHECK([whether to use agent], - [ac_cv_use_agent], [ac_cv_use_agent=yes]) + [ac_cv_use_agent], + [ac_cv_use_agent=yes]) if test x"$ac_cv_use_agent" = x"yes"; then - AC_DEFINE(CONFIG_HIP_AGENT) + AC_CHECK_LIB(sqlite3, sqlite3_open,, + AC_MSG_ERROR(libsqlite3-dev not found)) + AC_DEFINE(CONFIG_HIP_AGENT) AH_TEMPLATE(CONFIG_HIP_AGENT, [Defined to 1 if agent is enabled.]) - AC_CHECK_LIB(sqlite3, sqlite3_open,, AC_MSG_ERROR(libsqlite3-dev not found)) fi AM_CONDITIONAL(HIP_AGENT, test x"$ac_cv_use_agent" = x"yes") -AC_ARG_ENABLE(cookie, - AC_HELP_STRING([--enable-cookie], - [HIP cookie extensions (default is NO)]), - [ac_cv_use_cookie=$enableval], [ac_cv_use_cookie=no]) -AC_CACHE_CHECK([whether to use cookie extensions], - [ac_cv_use_cookie], [ac_cv_use_cookie=no]) -if test x"$ac_cv_use_cookie" = x"yes"; then - AC_DEFINE(CONFIG_HIP_COOKIE) - AH_TEMPLATE(CONFIG_HIP_COOKIE, [Defined to 1 if cookie is enabled.]) -fi - AC_ARG_ENABLE(pfkey, - AC_HELP_STRING([--enable-pfkey], - [HIP pfkey extensions (default is NO)]), - [ac_cv_use_pfkey=$enableval], [ac_cv_use_pfkey=no]) + AS_HELP_STRING([--enable-pfkey], + [HIP pfkey extensions (default is NO)]), + [ac_cv_use_pfkey=$enableval], + [ac_cv_use_pfkey=no]) AC_CACHE_CHECK([whether to use pfkey extensions], - [ac_cv_use_pfkey], [ac_cv_use_pfkey=no]) + [ac_cv_use_pfkey], + [ac_cv_use_pfkey=no]) if test x"$ac_cv_use_pfkey" = x"yes"; then - AC_DEFINE(CONFIG_HIP_PFKEY) - AH_TEMPLATE(CONFIG_HIP_PFKEY, [Defined to 1 if pfkey is enabled.]) - AC_DEFINE(PATH_IPSEC_H, "netinet/ipsec.h") - AH_TEMPLATE(PATH_IPSEC_H, [Path to ipsec.h.]) - AM_PROG_LEX + AC_DEFINE(CONFIG_HIP_PFKEY) + AH_TEMPLATE(CONFIG_HIP_PFKEY, [Defined to 1 if pfkey is enabled.]) + AM_PROG_LEX fi AM_CONDITIONAL(HIP_PFKEY, test x"$ac_cv_use_pfkey" = x"yes") -AC_ARG_ENABLE(cert, - AC_HELP_STRING([--enable-cert], - [Samus cert extensions (default is NO)]), - [ac_cv_use_cert=$enableval], [ac_cv_use_cert=no]) -AC_CACHE_CHECK([whether to use cert extensions], - [ac_cv_use_cert], [ac_cv_use_cert=no]) -if test x"$ac_cv_use_cert" = x"yes"; then - AC_DEFINE(CONFIG_HIP_CERT) - AH_TEMPLATE(CONFIG_HIP_CERT, [Defined to 1 if certificates are enabled.]) -fi - AC_ARG_ENABLE(rvs, - AC_HELP_STRING([--enable-rvs], - [HIP Rendezvous Extensions (default is YES)]), - [ac_cv_use_rvs=$enableval], [ac_cv_use_rvs=yes]) + AS_HELP_STRING([--enable-rvs], + [HIP Rendezvous Extensions (default is YES)]), + [ac_cv_use_rvs=$enableval], + [ac_cv_use_rvs=yes]) AC_CACHE_CHECK([whether to use RVS], - [ac_cv_use_rvs], [ac_cv_use_rvs=yes]) + [ac_cv_use_rvs], + [ac_cv_use_rvs=yes]) if test x"$ac_cv_use_rvs" = x"yes"; then - AC_DEFINE(CONFIG_HIP_RVS) - AH_TEMPLATE(CONFIG_HIP_RVS, [Defined to 1 if RVS is enabled.]) + AC_DEFINE(CONFIG_HIP_RVS) + AH_TEMPLATE(CONFIG_HIP_RVS, [Defined to 1 if RVS is enabled.]) fi AC_ARG_ENABLE(hipproxy, - AC_HELP_STRING([--enable-hipproxy], - [HIP Proxy (default is YES)]), - [ac_cv_use_hipproxy=$enableval], [ac_cv_use_hipproxy=yes]) + AS_HELP_STRING([--enable-hipproxy], + [HIP Proxy (default is YES)]), + [ac_cv_use_hipproxy=$enableval], + [ac_cv_use_hipproxy=yes]) AC_CACHE_CHECK([whether to use HIP proxy], - [ac_cv_use_hipproxy], [ac_cv_use_hipproxy=yes]) + [ac_cv_use_hipproxy], + [ac_cv_use_hipproxy=yes]) if test x"$ac_cv_use_hipproxy" = x"yes"; then - AC_DEFINE(CONFIG_HIP_HIPPROXY) - AH_TEMPLATE(CONFIG_HIP_HIPPROXY, [Defined to 1 if the HIP Proxy is enabled.]) + AC_DEFINE(CONFIG_HIP_HIPPROXY) + AH_TEMPLATE(CONFIG_HIP_HIPPROXY, [Defined to 1 if HIP Proxy is enabled.]) fi AC_ARG_ENABLE(maemo, - AC_HELP_STRING([--enable-maemo], - [Maemo (default is NO)]), - [ac_cv_use_maemo=$enableval \ - ac_cv_use_altsep=yes \ - ac_cv_use_i3=no], [ac_cv_use_maemo=no]) + AS_HELP_STRING([--enable-maemo], + [Maemo (default is NO)]), + [ac_cv_use_maemo=$enableval], + [ac_cv_use_maemo=no]) AC_CACHE_CHECK([whether to use Maemo], - [ac_cv_use_maemo], [ac_cv_use_maemo=no]) + [ac_cv_use_maemo], + [ac_cv_use_maemo=no]) if test x"$ac_cv_use_maemo" = x"yes"; then - AC_DEFINE(CONFIG_HIP_MAEMO) - AC_SUBST(MAEMO_CFLAGS, "-O2 -g -fgnu89-inline") - AC_SUBST(MAEMO_CPPFLAGS, "-I/usr/include/libipq/") - AH_TEMPLATE(CONFIG_HIP_MAEMO, [Defined to 1 if maemo build is enabled.]) + AC_DEFINE(CONFIG_HIP_MAEMO) + AH_TEMPLATE(CONFIG_HIP_MAEMO, [Defined to 1 if Maemo build is enabled.]) + AC_SUBST(MAEMO_CFLAGS, "-O2 -g -fgnu89-inline") + AC_SUBST(MAEMO_CPPFLAGS, "-I/usr/include/libipq/") fi -AM_CONDITIONAL(HIP_MAEMO, test x"$ac_cv_use_maemo" = x"yes") AC_ARG_ENABLE(openwrt, - AC_HELP_STRING([--enable-openwrt], - [OpenWRT (default is NO)]), - [ac_cv_use_openwrt=$enableval \ - ac_cv_use_altsep=yes], [ac_cv_use_openwrt=no]) + AS_HELP_STRING([--enable-openwrt], + [OpenWRT (default is NO)]), + [ac_cv_use_openwrt=$enableval], + [ac_cv_use_openwrt=no]) AC_CACHE_CHECK([whether to use OpenWRT], - [ac_cv_use_openwrt], [ac_cv_use_openwrt=no]) + [ac_cv_use_openwrt], + [ac_cv_use_openwrt=no]) if test x"$ac_cv_use_openwrt" = x"yes"; then - AC_DEFINE(CONFIG_HIP_OPENWRT) - AC_SUBST(OPENWRT_CFLAGS, "-lc") - AH_TEMPLATE(CONFIG_HIP_OPENWRT, [Defined to 1 if openwrt support is enabled.]) - if test x"$TARGET" = x"MIPS_LINUX"; then - AC_DEFINE(CONFIG_HIP_OPENWRT_MIPSLINUX) - AH_TEMPLATE(CONFIG_HIP_OPENWRT_MIPSLINUX, [Defined to 1 if mipslinux is enabled.]) - fi + AC_DEFINE(CONFIG_HIP_OPENWRT) + AC_SUBST(OPENWRT_CFLAGS, "-lc") + AH_TEMPLATE(CONFIG_HIP_OPENWRT, + [Defined to 1 if openwrt support is enabled.]) + if test x"$TARGET" = x"MIPS_LINUX"; then + AC_DEFINE(CONFIG_HIP_OPENWRT_MIPSLINUX) + AH_TEMPLATE(CONFIG_HIP_OPENWRT_MIPSLINUX, + [Defined to 1 if mipslinux is enabled.]) + fi fi -AM_CONDITIONAL(HIP_OPENWRT, test x"$ac_cv_use_openwrt" = x"yes") -# if we already set altsep, then don't check the flags anymore -if test x"$ac_cv_use_altsep" != x"yes"; then AC_ARG_ENABLE(altsep, - AC_HELP_STRING([--enable-altsep], - [Alternative privilege separation (default is NO)]), - [ac_cv_use_altsep=$enableval], [ac_cv_use_altsep=no]) -fi + AS_HELP_STRING([--enable-altsep], + [Alternative privilege separation (default is NO)]), + [ac_cv_use_altsep=$enableval], + [ac_cv_use_altsep=no]) AC_CACHE_CHECK([whether to use Alternative privilege separation], - [ac_cv_use_altsep], [ac_cv_use_altsep=no]) + [ac_cv_use_altsep], + [ac_cv_use_altsep=no]) if test x"$ac_cv_use_altsep" = x"yes"; then - AC_DEFINE(CONFIG_HIP_ALTSEP) - AH_TEMPLATE(CONFIG_HIP_ALTSEP, [Defined to 1 if alternative privilege separation is enabled.]) -fi -AM_CONDITIONAL(HIP_ALTSEP, test x"$ac_cv_use_altsep" = x"yes") - -# define this iff we have uuid lib -AM_CONDITIONAL(HIP_UUIDLIB, test "$ac_has_uuid_lib" = "1") - -# if we already set i3, then don't check the flags anymore -if test x"$ac_cv_use_i3" != x"no"; then + AC_DEFINE(CONFIG_HIP_ALTSEP) + AH_TEMPLATE(CONFIG_HIP_ALTSEP, + [Defined to 1 if alternative privilege separation is enabled.]) +fi + +AC_ARG_ENABLE(privsep, + AS_HELP_STRING([--enable-privsep], + [Privilege separation (default is YES)]), + [ac_cv_use_privsep=$enableval], + [ac_cv_use_privsep=yes]) +AC_CACHE_CHECK([whether to use privsep], + [ac_cv_use_privsep], + [ac_cv_use_privsep=yes]) +if test x"$ac_cv_use_privsep" = x"yes"; then + if test x"$ac_cv_use_altsep" != x"yes"; then + AC_CHECK_LIB(cap, cap_get_proc,, + AC_MSG_ERROR(libcap-dev developer headers not found)) + fi + AC_DEFINE(CONFIG_HIP_PRIVSEP) + AH_TEMPLATE(CONFIG_HIP_PRIVSEP, + [Defined to 1 if privilege separation is enabled.]) +fi +AM_CONDITIONAL(HIP_PRIVSEP, test x"$ac_cv_use_privsep" = x"yes") + AC_ARG_ENABLE(i3, - AC_HELP_STRING([--enable-i3], - [HIP i3 (default is NO)]), - [ac_cv_use_i3=$enableval],) -fi + AS_HELP_STRING([--enable-i3], + [HIP i3 (default is NO)]), + [ac_cv_use_i3=$enableval],) AC_CACHE_CHECK([whether to use i3], - [ac_cv_use_i3], [ac_cv_use_i3=no]) + [ac_cv_use_i3], + [ac_cv_use_i3=no]) if test x"$ac_cv_use_i3" = x"yes"; then - AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found)) - AC_CHECK_LIB(pthread, pthread_create,, AC_MSG_ERROR(libpthread not found)) - AC_DEFINE(CONFIG_HIP_I3) - AH_TEMPLATE(CONFIG_HIP_I3, [Defined to 1 if i3 is enabled.]) - + AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found)) + AC_CHECK_LIB(pthread, pthread_create,, AC_MSG_ERROR(libpthread not found)) + AC_DEFINE(CONFIG_HIP_I3) + AH_TEMPLATE(CONFIG_HIP_I3, [Defined to 1 if i3 is enabled.]) fi AM_CONDITIONAL(HIP_I3, test x"$ac_cv_use_i3" = x"yes") -AM_CONDITIONAL(HIP_PRIVSEP, test x"$ac_cv_use_privsep" = x"yes") -AC_ARG_ENABLE(privsep, - AC_HELP_STRING([--enable-privsep], - [Privilege separation (default is YES)]), - [ac_cv_use_privsep=$enableval], [ac_cv_use_privsep=yes]) -AC_CACHE_CHECK([whether to use privsep], - [ac_cv_use_privsep], [ac_cv_use_privsep=yes]) -if test x"$ac_cv_use_privsep" = x"yes"; then - if test x"$ac_cv_use_altsep" != x"yes"; then - AC_CHECK_LIB(cap, cap_get_proc,, AC_MSG_ERROR(libcap-dev developer headers not found)) - fi - AC_DEFINE(CONFIG_HIP_PRIVSEP) - AH_TEMPLATE(CONFIG_HIP_PRIVSEP, [Defined to 1 if privilege separation is enabled.]) -fi -AM_CONDITIONAL(HIP_PRIVSEP, test x"$ac_cv_use_privsep" = x"yes") - AC_ARG_ENABLE(opportunistic, - AC_HELP_STRING([--enable-opportunistic], - [HIP opportunistic extensions (default is YES)]), - [ac_cv_use_opportunistic=$enableval], [ac_cv_use_opportunistic=yes]) + AS_HELP_STRING([--enable-opportunistic], + [HIP opportunistic mode (default is YES)]), + [ac_cv_use_opportunistic=$enableval], + [ac_cv_use_opportunistic=yes]) AC_CACHE_CHECK([whether to use opportunistic], - [ac_cv_use_opportunistic], [ac_cv_use_opportunistic=yes]) + [ac_cv_use_opportunistic], + [ac_cv_use_opportunistic=yes]) if test x"$ac_cv_use_opportunistic" = x"yes"; then - AC_DEFINE(CONFIG_HIP_OPPORTUNISTIC) - AH_TEMPLATE(CONFIG_HIP_OPPORTUNISTIC, [Defined to 1 if oppotunistic mode is enabled.]) + AC_DEFINE(CONFIG_HIP_OPPORTUNISTIC) + AH_TEMPLATE(CONFIG_HIP_OPPORTUNISTIC, + [Defined to 1 if opportunistic mode is enabled.]) fi AM_CONDITIONAL(HIP_OPPORTUNISTIC, test x"$ac_cv_use_opportunistic" = x"yes") @@ -297,27 +297,31 @@ AM_CONDITIONAL(SAVAH_IP_OPTION, test x"$ac_cv_use_savaipopt" = x"yes") AC_ARG_ENABLE(dht, - AC_HELP_STRING([--enable-dht], - [DHT support (default is YES)]), - [ac_cv_use_dht=$enableval], [ac_cv_use_dht=yes]) + AS_HELP_STRING([--enable-dht], + [DHT support (default is YES)]), + [ac_cv_use_dht=$enableval], + [ac_cv_use_dht=yes]) AC_CACHE_CHECK([whether to use dht], - [ac_cv_use_dht], [ac_cv_use_dht=yes]) + [ac_cv_use_dht], + [ac_cv_use_dht=yes]) if test x"$ac_cv_use_dht" = x"yes"; then - AC_DEFINE(CONFIG_HIP_DHT) - AH_TEMPLATE(CONFIG_HIP_DHT, [Defined to 1 if dht is enabled.]) - AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found)) + AC_DEFINE(CONFIG_HIP_DHT) + AH_TEMPLATE(CONFIG_HIP_DHT, [Defined to 1 if dht is enabled.]) + AC_CHECK_LIB(xml2, xmlFreeDoc,, AC_MSG_ERROR(libxml2 not found)) fi AM_CONDITIONAL(HIP_DHT, test x"$ac_cv_use_dht" = x"yes") AC_ARG_ENABLE(blind, - AC_HELP_STRING([--enable-blind], - [HIP BLIND extensions (default is NO)]), - [ac_cv_use_blind=$enableval], [ac_cv_use_blind=no]) + AS_HELP_STRING([--enable-blind], + [HIP BLIND extensions (default is NO)]), + [ac_cv_use_blind=$enableval], + [ac_cv_use_blind=no]) AC_CACHE_CHECK([whether to use BLIND], - [ac_cv_use_blind], [ac_cv_use_blind=no]) + [ac_cv_use_blind], + [ac_cv_use_blind=no]) if test x"$ac_cv_use_blind" = x"yes"; then - AC_DEFINE(CONFIG_HIP_BLIND) - AH_TEMPLATE(CONFIG_HIP_BLIND, [Defined to 1 if the blind extension is enabled.]) + AC_DEFINE(CONFIG_HIP_BLIND) + AH_TEMPLATE(CONFIG_HIP_BLIND, [Defined to 1 if blind is enabled.]) fi AC_ARG_ENABLE(libinet6, @@ -338,38 +342,25 @@ AM_CONDITIONAL(HIP_LIBINET6, test x"$ac_cv_use_libinet6" = x"yes") AC_ARG_ENABLE(profiling, - AC_HELP_STRING([--enable-profiling], - [compile in gprof profiling support (default is NO)]), - [ac_cv_use_profiling=$enableval], [ac_cv_use_profiling=no]) + AS_HELP_STRING([--enable-profiling], + [gprof profiling support (default is NO)]), + [ac_cv_use_profiling=$enableval], + [ac_cv_use_profiling=no]) AC_CACHE_CHECK([whether to use grof support], - [ac_cv_use_profiling], [ac_cv_use_profiling=no]) + [ac_cv_use_profiling], + [ac_cv_use_profiling=no]) if test x"$ac_cv_use_profiling" = x"yes"; then - AC_DEFINE(CONFIG_HIP_PROFILING) - AH_TEMPLATE(CONFIG_HIP_PROFILING, [Defined to 1 if profiling is enabled.]) - AC_SUBST(GPROF_CFLAGS, "-pg") -fi -AM_CONDITIONAL(HIP_PROFILING, test x"$ac_cv_use_profiling" = x"yes") - -AC_ARG_ENABLE(ecdsa, - AC_HELP_STRING([--enable-ecdsa], - [compile in ecdsa support (default is NO)]), - [ac_cv_use_ecdsa=$enableval], [ac_cv_use_ecdsa=no]) -AC_CACHE_CHECK([whether to use ecdsa support], - [ac_cv_use_ecdsa], [ac_cv_use_ecdsa=no]) -if test x"$ac_cv_use_ecdsa" = x"yes"; then - AC_DEFINE(CONFIG_HIP_ECDSA) - AH_TEMPLATE(CONFIG_HIP_ECDSA, [Defined to 1 if ECDSA support is enabled.]) - AC_SUBST(GPROF_CFLAGS, "-pg") -fi -AM_CONDITIONAL(HIP_ECDSA, test x"$ac_cv_use_ecdsa" = x"yes") + AC_SUBST(GPROF_CFLAGS, "-pg") +fi AC_ARG_ENABLE(debug, - AC_HELP_STRING([--enable-debug], - [Enable debug (default is YES)]), - [ac_cv_use_debug=$enableval], - [ac_cv_use_debug=yes]) + AS_HELP_STRING([--enable-debug], + [Enable debug (default is YES)]), + [ac_cv_use_debug=$enableval], + [ac_cv_use_debug=yes]) AC_CACHE_CHECK([whether to have verbose debug], - [ac_cv_use_debug], [ac_cv_use_debug=yes]) + [ac_cv_use_debug], + [ac_cv_use_debug=yes]) if test x"$ac_cv_use_debug" = x"yes"; then AC_DEFINE(HIP_LOGFMT_LONG) AH_TEMPLATE(HIP_LOGFMT_LONG, [Defined to 1 if long log format output is enabled.]) @@ -378,41 +369,47 @@ fi AC_ARG_ENABLE(midauth, - AC_HELP_STRING([--enable-midauth], - [Enable middlebox authentification (default is NO)]), - [ac_cv_use_midauth=$enableval], - [ac_cv_use_midauth=no]) + AS_HELP_STRING([--enable-midauth], + [Enable middlebox authentification (default is NO)]), + [ac_cv_use_midauth=$enableval], + [ac_cv_use_midauth=no]) AC_CACHE_CHECK([whether to have middlebox authentification], - [ac_cv_use_midauth], [ac_cv_use_midauth=no]) + [ac_cv_use_midauth], + [ac_cv_use_midauth=no]) if test x"$ac_cv_use_midauth" = x"yes"; then - AC_DEFINE(CONFIG_HIP_MIDAUTH) - AH_TEMPLATE(CONFIG_HIP_MIDAUTH, [Defined to 1 if midauth extensions are enabled.]) + AC_DEFINE(CONFIG_HIP_MIDAUTH) + AH_TEMPLATE(CONFIG_HIP_MIDAUTH, + [Defined to 1 if midauth extension is enabled.]) fi AM_CONDITIONAL(HIP_MIDAUTH, test x"$ac_cv_use_midauth" = x"yes") AC_ARG_ENABLE(performance, - AC_HELP_STRING([--enable-performance], - [Performace measurement support (default is NO)]), - [ac_cv_use_performance=$enableval], [ac_cv_use_performance=no]) + AS_HELP_STRING([--enable-performance], + [Performace measurement support (default is NO)]), + [ac_cv_use_performance=$enableval], + [ac_cv_use_performance=no]) AC_CACHE_CHECK([whether to use performance measurement], - [ac_cv_use_performance], [ac_cv_use_performance=no]) + [ac_cv_use_performance], + [ac_cv_use_performance=no]) if test x"$ac_cv_use_performance" = x"yes"; then - AC_DEFINE(CONFIG_HIP_PERFORMANCE) - AH_TEMPLATE(CONFIG_HIP_PERFORMANCE, [Defined to 1 if performance measurements are enabled.]) + AC_DEFINE(CONFIG_HIP_PERFORMANCE) + AH_TEMPLATE(CONFIG_HIP_PERFORMANCE, + [Defined to 1 if performance measurements are enabled.]) fi AM_CONDITIONAL(HIP_PERFORMANCE, test x"$ac_cv_use_performance" = x"yes") AC_ARG_ENABLE(demo, - AC_HELP_STRING([--enable-demo], - [Demo output (default is NO)]), - [ac_cv_use_demo=$enableval], [ac_cv_use_demo=no]) + AS_HELP_STRING([--enable-demo], + [Demo output (default is NO)]), + [ac_cv_use_demo=$enableval], + [ac_cv_use_demo=no]) AC_CACHE_CHECK([whether to print output for demos], - [ac_cv_use_demo], [ac_cv_use_demo=no]) + [ac_cv_use_demo], + [ac_cv_use_demo=no]) if test x"$ac_cv_use_demo" = x"yes"; then - AC_DEFINE(CONFIG_HIP_DEMO) - AH_TEMPLATE(CONFIG_HIP_DEMO, [Defined to 1 if demo is enabled.]) + AC_DEFINE(CONFIG_HIP_DEMO) + AH_TEMPLATE(CONFIG_HIP_DEMO, [Defined to 1 if demo is enabled.]) fi -AM_CONDITIONAL(HIP_DEMO, test x"$ac_cv_use_demo" = x"yes") # Set default AM_CFLAGS for the complete project. # -funit-at-a-time can be removed when libinet6 is removed. === modified file 'debian/changelog' --- debian/changelog 2010-02-10 15:28:54 +0000 +++ debian/changelog 2010-03-19 09:53:35 +0000 @@ -1,5 +1,5 @@ hipl (1.0.4-1) unstable; urgency=low - * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP> + * Initial release - -- hummen <rene.hummen@xxxxxxxxxxxxxxxxx> Wed, 10 Feb 2010 16:27:50 +0100 + -- Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx> Wed, 10 Feb 2010 16:27:50 +0100 === modified file 'debian/control' --- debian/control 2010-02-10 16:44:07 +0000 +++ debian/control 2010-03-19 09:53:35 +0000 @@ -1,7 +1,5 @@ Source: hipl -Section: networt -Priority: extra -Maintainer: hummen <rene.hummen@xxxxxxxxxxxxxxxxx> +Maintainer: Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx> Build-Depends: debhelper (>= 5), autotools-dev Standards-Version: 3.7.2 === modified file 'debian/copyright' --- debian/copyright 2010-02-18 13:55:51 +0000 +++ debian/copyright 2010-03-19 09:53:35 +0000 @@ -1,6 +1,8 @@ -This package was debianized by hummen <rene.hummen@xxxxxxxxxxxxxxxxx> on +This package was debianized by Rene Hummen <rene.hummen@xxxxxxxxxxxxxxxxx> on Wed, 10 Feb 2010 16:27:50 +0100. +# THIS FILE NEEDS TO BE TAKEN CARE OF + It was downloaded from <url://example.com> Upstream Author(s): === modified file 'debian/dirs' --- debian/dirs 2010-02-10 16:17:46 +0000 +++ debian/dirs 2010-03-19 09:53:35 +0000 @@ -1,5 +1,1 @@ -usr/bin -usr/sbin -usr/lib -usr/lib64 -usr/share +# This file specifies the directories which our package will create. === modified file 'debian/docs' --- debian/docs 2010-02-10 15:28:54 +0000 +++ debian/docs 2010-03-19 09:53:35 +0000 @@ -1,1 +1,2 @@ -verbose-headers.txt +# This file includes the files that will be copied to /usr/share/doc/package +# when the package is installed === modified file 'debian/rules' --- debian/rules 2010-03-01 17:34:58 +0000 +++ debian/rules 2010-03-19 09:53:35 +0000 @@ -31,7 +31,14 @@ ifneq "$(wildcard /usr/share/misc/config.guess)" "" cp -f /usr/share/misc/config.guess config.guess endif - ./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" --enable-maemo --disable-firewall --disable-privsep --enable-midauth --disable-agent --disable-opportunistic --disable-savaipopt --disable-dht + ./configure $(CROSS) --prefix=/usr \ + --enable-midauth \ + --enable-maemo \ + --disable-dht \ + --disable-agent \ + --disable-privsep \ + --disable-i3 \ + --disable-debug build: build-stamp @@ -75,26 +82,14 @@ dh_testdir dh_testroot dh_installchangelogs - dh_installdocs - dh_installexamples -# dh_install -# dh_installmenu -# dh_installdebconf -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime +# dh_installdocs # dh_python # dh_installinit -# dh_installcron -# dh_installinfo - dh_installman dh_link dh_strip dh_compress dh_fixperms # dh_perl -# dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol === modified file 'doc/HOWTO.xml' --- doc/HOWTO.xml 2010-03-19 09:09:25 +0000 +++ doc/HOWTO.xml 2010-03-19 09:53:35 +0000 @@ -2109,15 +2109,15 @@ /etc/hosts: </para></listitem> <listitem><para> + HIT_OF_OOPS oops + </para></listitem> + <listitem><para> + /etc/hosts: + </para></listitem> + <listitem><para> 3ffe::2 oops </para></listitem> <listitem><para> - /etc/hip/hosts: - </para></listitem> - <listitem><para> - HIT_OF_OOPS oops - </para></listitem> - <listitem><para> ifconfig eth0 inet6 add 3ffe::1/64 </para></listitem> <listitem><para> @@ -2257,7 +2257,7 @@ <itemizedlist> <listitem> <para> - Add the information in /etc/hip/hosts + Add the information in /etc/hosts <itemizedlist> <listitem><para>OOPS_HIT oops</para></listitem> <listitem><para>OOPS_LSI oops <emphasis>Optional!</emphasis> If it's not defined, @@ -2411,7 +2411,7 @@ <section id="sec_easy_methods"> <title>Easy Methods</title> <para> - 1. Run the dnshipproxy to handle mapping from hostnames to HITs from hosts files. + 1. Run the dnshipproxy to map hostnames transparently to HITs from hosts files and directory services (DNS, DHT). See <xref linkend="sec_dns_proxy" /> for more details. </para> <para> @@ -2706,7 +2706,7 @@ <para> The name can be something found from <emphasis>/etc/hosts</emphasis> - and <emphasis>/etc/hip/hosts</emphasis> or you can use DHT to + and <emphasis>/etc/hosts</emphasis> or you can use DHT to resolve names to HIT and address. Search can also be done directly with HIT by command </para> @@ -3065,9 +3065,10 @@ </para> <para> - Currently HIP daemon performs name resolution in the following order: + Currently HIP daemon performs HIP name resolution in the following order: <itemizedlist> <listitem><para>in /etc/hip/hosts</para></listitem> + <listitem><para>in /etc/hosts</para></listitem> <listitem><para>in hit-to-ip.infrahip.net zone</para></listitem> <listitem><para>in DHT</para></listitem> </itemizedlist> @@ -3345,13 +3346,23 @@ NATs are commonly referred to as "good" NATs. </para> <para> - The primary objective of the HIP relay extension, on the other hand, is - to improve reachability when HIP hosts are separated from each other - by a NAT device that performs address dependent mapping. Such NATs are - commonly referred to as "bad" NATs. In practice, the HIP relay servers - are used to relay the Interactive Connectivity Establishment (ICE) - address candidates that are encapsulated in HIP messages. - </para> + HIPL has two experimental relay modes serving NAT traversal + purposes. In the first mode, the HIP control plane relay + supports <ulink url="http://www.ietf.org/id/draft-keranen-hip-native-nat-traversal-00.txt";> + Native NAT Traversal Mode for HIP</ulink> which is only + partially supported at the moment. The core idea is that two + end-points are behind two different NAT boxes and use a HIP + control plane relay to be able to contact each other to + exchange their locators. Then the hosts "punch holes" to their + NAT boxes to establish direct end-to-end connectivity with + each other. The second mode, "full-relay" is supported + completely and it relays both HIP and ESP traffic. You should + use it carefully and whitelist your /etc/hip/relay_config + file. Otherwise you risk your host becoming an open HIP and + ESP relay. For additional security measure, you can also use + also /etc/hip/firewall_conf to further restrict the allowed + clients and servers by their HITs. + </para> <para> The main difference between the rendezvous server and the HIP relay server is that the RVS only relays I1 packet of the base exchange while @@ -5053,7 +5064,7 @@ </section> <section id="sys_based_opp_mode"> - <title>System-based opportunistic mode</title> + <title>System-based opportunistic mode (experimental)</title> <para> The system-based opportunistic mode enables HIP communication without the use of the opportunistic library. If the peer does === modified file 'firewall/cache.c' --- firewall/cache.c 2010-03-03 13:16:18 +0000 +++ firewall/cache.c 2010-03-19 09:53:35 +0000 @@ -16,7 +16,9 @@ #include "cache.h" #include "lib/core/debug.h" -#include "lib/core/misc.h" +#include "lib/core/builder.h" +#include "lib/core/message.h" + #include "firewall.h" #include "user_ipsec_api.h" === modified file 'firewall/cache_port.c' --- firewall/cache_port.c 2010-02-18 12:26:08 +0000 +++ firewall/cache_port.c 2010-03-19 09:53:35 +0000 @@ -23,13 +23,102 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <stdio.h> + #include "cache_port.h" #include "cache.h" -#include "lib/core/misc.h" + +#include <lib/tool/lutil.h> + + static HIP_HASHTABLE *firewall_port_cache_db = NULL; /** + * Check from the proc file system whether a local port is attached + * to an IPv4 or IPv6 address. This is required to determine whether + * incoming packets should be diverted to an LSI. + * + * @param port_dest the port number of the socket + * @param *proto protocol type + * @return 1 if it finds the required socket, 0 otherwise + * + * @note this is used only from the firewall, so move this there + */ +int hip_get_proto_info(in_port_t port_dest, char *proto) +{ + FILE *fd = NULL; + char line[500], sub_string_addr_hex[8], path[11 + sizeof(proto)]; + char *fqdn_str = NULL, *separator = NULL, *sub_string_port_hex = NULL; + int lineno = 0, index_addr_port = 0, exists = 0, result; + uint32_t result_addr; + struct in_addr addr; + List list; + + if (!proto) { + return 0; + } + + if (!strcmp(proto, "tcp6") || !strcmp(proto, "tcp")) { + index_addr_port = 15; + } else if (!strcmp(proto, "udp6") || !strcmp(proto, "udp")) { + index_addr_port = 10; + } else { + return 0; + } + + strcpy(path, "/proc/net/"); + strcat(path, proto); + fd = fopen(path, "r"); + + initlist(&list); + while (fd && getwithoutnewline(line, 500, fd) != NULL && !exists) { + lineno++; + + destroy(&list); + initlist(&list); + + if (lineno == 1 || strlen(line) <= 1) { + continue; + } + + extractsubstrings(line, &list); + + fqdn_str = getitem(&list, index_addr_port); + if (fqdn_str) { + separator = strrchr(fqdn_str, ':'); + } + + if (!separator) { + continue; + } + + sub_string_port_hex = strtok(separator, ":"); + sscanf(sub_string_port_hex, "%X", &result); + HIP_DEBUG("Result %i\n", result); + HIP_DEBUG("port dest %i\n", port_dest); + if (result == port_dest) { + strncpy(sub_string_addr_hex, fqdn_str, 8); + sscanf(sub_string_addr_hex, "%X", &result_addr); + addr.s_addr = result_addr; + if (IS_LSI32(addr.s_addr)) { + exists = 2; + break; + } else { + exists = 1; + break; + } + } + } /* end of while */ + if (fd) { + fclose(fd); + } + destroy(&list); + + return exists; +} + +/** * add a default entry in the firewall port cache. * * @param key the hash key (a string consisting of concatenation of the port, an underscore and the protocol) === modified file 'firewall/common_hipd_msg.c' --- firewall/common_hipd_msg.c 2010-02-17 17:38:08 +0000 +++ firewall/common_hipd_msg.c 2010-03-19 09:53:35 +0000 @@ -5,6 +5,7 @@ #include "lib/core/ife.h" #include "lib/core/debug.h" #include "lib/core/builder.h" +#include "lib/core/message.h" #include "firewall.h" /** === modified file 'firewall/conntrack.c' --- firewall/conntrack.c 2010-03-19 09:24:10 +0000 +++ firewall/conntrack.c 2010-03-19 09:53:35 +0000 @@ -20,16 +20,15 @@ #include <stdio.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "conntrack.h" #include "dlist.h" #include "hslist.h" #include "esp_prot_conntrack.h" #include "datapkt.h" -#include "lib/core/misc.h" + +#include "lib/core/hostid.h" +#include "lib/core/hip_udp.h" #include "hipd/hadb.h" #include "lib/tool/pk.h" #include "firewalldb.h" @@ -232,7 +231,7 @@ HIP_IFEL(data->verify(data->src_hi, common), -EINVAL, "Verification of signature failed\n"); - HIP_DEBUG("verfied BEX signature\n"); + HIP_DEBUG("verified BEX signature\n"); #endif _HIP_DEBUG("get_hip_data:\n"); @@ -395,7 +394,7 @@ * Find esp tuple from espList that matches the argument spi and contains the * argument ip address * - * @param dst_addr the destination address to be searched for + * @param dst_addr the optional destination address to be searched for * @param spi the SPI number to be searched for * @return a tuple matching to the address and SPI or NULL if not found */ @@ -409,17 +408,18 @@ while (list) { struct esp_tuple *tuple = (struct esp_tuple *) list->data; if (spi == tuple->spi) { - if (get_esp_address(tuple->dst_addr_list, dst_addr) != NULL) { + if (dst_addr && get_esp_address(tuple->dst_addr_list, dst_addr) != NULL) { HIP_DEBUG("connection found by esp\n"); return tuple->tuple; + } else if (!dst_addr) { + return tuple->tuple; } } list = list->next; } + HIP_DEBUG("get_tuple_by_esp: dst addr %s spi 0x%lx no connection found\n", - addr_to_numeric(dst_addr), spi); - - HIP_DEBUG_IN6ADDR("DST", dst_addr); + (dst_addr ? addr_to_numeric(dst_addr) : "NULL"), spi); return NULL; } @@ -854,6 +854,103 @@ } /** + * Hipfw has an experimental mode which allows it to act as an ESP + * Relay to pass e.g. p2p-unfriendly NAT boxes. The ESP relay mode + * assumes that the HIP relay (in hipd) and ESP relay (in hipfw) are + * running on the same middlehost in a public network. The responder + * has to register to the relay with "hipconf add server full-relay" + * which operates as defined in <a + * href="http://tools.ietf.org/html/draft-ietf-hip-nat-traversal";> NAT + * traversal for HIP</a>. Then the initiator can contact the responder + * through the IP address of the HIP/ESP relay. The relay acts as a two-way + * NAT and hides the addresses of the initiator and responder. This way, + * the the relay supports P2P-unfriendly NAT traversal with the cost of + * triangular routing. If the initiator and responder wish to communicate + * with each other directly, they can exchange locators either in base exchange + * or UPDATE. + * + * @todo implement the same handling for UPDATE + * + * @param common the R2 packet + * @param ctx packet context + * + * @return zero on success and non-zero on error + */ +static int hipfw_handle_relay_to_r2(const struct hip_common *common, + const hip_fw_context_t *ctx) +{ + struct iphdr *iph = (struct iphdr *) ctx->ipq_packet->payload; + struct hip_relay_to *relay_to = NULL; /* same format as relay_from */ + struct tuple *tuple, *reverse_tuple; + int err = 0; + uint32_t spi; + struct hip_esp_info *esp_info; + + HIP_DEBUG_IN6ADDR("ctx->src", &ctx->src); + HIP_DEBUG_IN6ADDR("ctx->dst", &ctx->dst); + + HIP_ASSERT((hip_get_msg_type(common) == HIP_R2)); + + HIP_IFEL(!(relay_to = hip_get_param(common, HIP_PARAM_RELAY_TO)), -1, + "No relay_to, skip\n"); + + HIP_DEBUG_IN6ADDR("relay_to_addr", &relay_to->address); + + HIP_IFEL(!((ctx->ip_version == 4) && + (iph->protocol == IPPROTO_UDP)), 0, + "Not a relay packet, ignore\n"); + + HIP_IFEL((ipv6_addr_cmp(&ctx->dst, &relay_to->address) == 0), 0, + "Reinjected control packet, passing it\n"); + + esp_info = hip_get_param(common, HIP_PARAM_ESP_INFO); + HIP_IFEL(!esp_info, 0, "No ESP_INFO, pass\n"); + spi = ntohl(esp_info->new_spi); + + HIP_DEBUG("SPI is 0x%lx\n", spi); + + HIP_IFEL(!(tuple = get_tuple_by_esp(NULL, spi)), 0, + "No tuple, skip\n"); + + HIP_IFEL(!(reverse_tuple = get_tuple_by_hits(&common->hits, &common->hitr)), 0, + "No reverse tuple, skip\n"); + + HIP_DEBUG("tuple src=%d dst=%d\n", tuple->src_port, tuple->dst_port); + HIP_DEBUG_IN6ADDR("tuple src ip", tuple->src_ip); + HIP_DEBUG_IN6ADDR("tuple dst ip", tuple->dst_ip); + HIP_DEBUG("tuple dir=%d, sport=%d, dport=%d, rel=%d\n", tuple->direction, + tuple->src_port, tuple->dst_port, tuple->esp_relay); + + HIP_DEBUG("reverse tuple src=%d dst=%d\n", reverse_tuple->src_port, + reverse_tuple->dst_port); + HIP_DEBUG_IN6ADDR("reverse tuple src ip", reverse_tuple->src_ip); + HIP_DEBUG_IN6ADDR("reverse tuple dst ip", reverse_tuple->dst_ip); + HIP_DEBUG("reverse tuple dir=%d, sport=%d, dport=%d, rel=%d\n", + reverse_tuple->direction, reverse_tuple->src_port, + reverse_tuple->dst_port, reverse_tuple->esp_relay); + + /* Store Responder's IP address and port */ + tuple->esp_relay = 1; + ipv6_addr_copy(&tuple->esp_relay_daddr, + &ctx->src); + tuple->esp_relay_dport = tuple->dst_port; + HIP_DEBUG("tuple relay port=%d\n", + tuple->esp_relay_dport); + HIP_DEBUG_IN6ADDR("tuple relay ip", + &tuple->esp_relay_daddr); + + /* Store Initiator's IP address and port */ + reverse_tuple->esp_relay = 1; + ipv6_addr_copy(&reverse_tuple->esp_relay_daddr, &relay_to->address); + reverse_tuple->esp_relay_dport = ntohs(relay_to->port); + HIP_DEBUG("reverse_tuple relay port=%d\n", reverse_tuple->esp_relay_dport); + HIP_DEBUG_IN6ADDR("reverse_tuple relay ip", &reverse_tuple->esp_relay_daddr); + +out_err: + return 0; +} + +/** * Process an R1 packet. This function also stores the HI of the Responder * to be able to verify signatures also later. The HI is stored only if the * signature in R1 was valid. @@ -867,7 +964,7 @@ // first check signature then store hi static int handle_r1(struct hip_common *common, struct tuple *tuple, - int verify_responder) + int verify_responder, const hip_fw_context_t *ctx) { struct in6_addr hit; struct hip_host_id *host_id = NULL; @@ -934,15 +1031,14 @@ * is re-established. In such a case, the old ESP tuples are not removed. If an * attacker spoofs an I2 or R2, the valid peers are still able to send data. * - * @param ip6_src the source address of the I2 packet - * @param ip6_dst the destination address of the I2 packet * @param common the I2 packet * @param tuple the connection tracking tuple corresponding to the I2 packet + * @param ctx packet context * * @return one on success or zero failure */ -static int handle_i2(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, - struct hip_common *common, struct tuple *tuple) +static int handle_i2(struct hip_common *common, struct tuple *tuple, + const hip_fw_context_t *ctx) { struct hip_esp_info *spi = NULL; struct tuple *other_dir = NULL; @@ -953,6 +1049,7 @@ // assume correct packet int err = 1; hip_tlv_len_t len = 0; + const struct in6_addr *ip6_src = &ctx->src; HIP_DEBUG("\n"); @@ -990,7 +1087,7 @@ HIP_IFEL(tuple->hip_tuple->data->verify(tuple->hip_tuple->data->src_pub_key, common), -EINVAL, "Verification of signature failed\n"); - HIP_DEBUG("verfied I2 signature\n"); + HIP_DEBUG("verified I2 signature\n"); } else { HIP_DEBUG("No HOST_ID found in control message\n"); } @@ -1048,104 +1145,26 @@ } /** - * Hipfw has an experimental mode which allows it to act as an ESP Relay to pass e.g. - * p2p-unfriendly NAT boxes. It is assumed that the same host is running - * also a HIP relay. This function adjusts the connection tracking so that - * the ESP relaying functionality works. As the end-hosts set up their IPsec - * SAs based on the IP address of the Relay, it must effectively implement - * source NATting to forward the ESP packets succesfully. At the moment, the relay - * adjusts connection tracking on based on the R2 packet. - * - * @todo implement the same handling for UPDATE - * @see http://hipl.hiit.fi/bugzilla/show_bug.cgi?id=871 - * - * @param ip6_src the source address of the R2 - * @param ip6_dst the destination address of the R2 - * @param common the R2 packet - * @param tuple the connection tracking tuple corresponding to the R2 packet - * @param esp_tuple the connection tracking ESP tuple corresponding to the R2 packet - * @param ctx packet context - * - * @return zero on success and non-zero on error - */ -static int hip_handle_esp_in_udp_relay_r2(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, - const struct hip_common *common, struct tuple *tuple, - struct esp_tuple *esp_tuple, hip_fw_context_t *ctx) -{ - struct hip_relay_to *relay_to; - struct iphdr *iph = (struct iphdr *) ctx->ipq_packet->payload; - struct udphdr *udph = (struct udphdr *) ((uint8_t *) iph + iph->ihl * 4); - int err = 0; - - relay_to = hip_get_param(common, HIP_PARAM_RELAY_TO); - - HIP_IFEL(!((ctx->ip_version == 4) && - (iph->protocol == IPPROTO_UDP)), 0, - "Not a relay packet, ignore\n"); - - if (!tuple->connection->original.src_ip && relay_to) { - HIP_IFE(!(tuple->connection->original.src_ip = - malloc(sizeof(struct in6_addr))), 0); - HIP_IFE(!(tuple->connection->reply.dst_ip = - malloc(sizeof(struct in6_addr))), 0); - HIP_IFE(!(tuple->connection->original.dst_ip = - malloc(sizeof(struct in6_addr))), 0); - HIP_IFE(!(tuple->connection->reply.src_ip = - malloc(sizeof(struct in6_addr))), 0); - - memcpy(tuple->connection->original.src_ip, - &relay_to->address, sizeof(struct in6_addr)); - memcpy(tuple->connection->reply.dst_ip, - &relay_to->address, sizeof(struct in6_addr)); - memcpy(tuple->connection->original.dst_ip, - ip6_src, sizeof(struct in6_addr)); - memcpy(tuple->connection->reply.src_ip, - ip6_src, sizeof(struct in6_addr)); - - HIP_DEBUG("%d %d\n", - htons(relay_to->port), - htons(udph->source)); - tuple->connection->original.relayed_src_port = relay_to->port; - tuple->connection->original.relayed_dst_port = udph->source; - tuple->connection->reply.relayed_src_port = udph->source; - tuple->connection->reply.relayed_dst_port = relay_to->port; - } else { /* Relayed R2: we are the source address */ - HIP_DEBUG_IN6ADDR("I", &tuple->connection->original.hip_tuple->data->src_hit); - HIP_DEBUG_IN6ADDR("I", tuple->connection->original.src_ip); - HIP_DEBUG_IN6ADDR("R", &tuple->connection->original.hip_tuple->data->dst_hit); - HIP_DEBUG_IN6ADDR("R", tuple->connection->original.dst_ip); - - esp_tuple->dst_addr_list = update_esp_address( - esp_tuple->dst_addr_list, ip6_src, NULL); - } - -out_err: - return 0; -} - -/** * Process an R2 packet. If connection already exists, the esp tuple is * just added to the existing connection. This occurs, for example, when * the connection is re-established. In such a case, the old esp * tuples are not removed. If an attacker spoofs an I2 or R2, the * valid peers are still able to send data. * - * @param ip6_src the source address of the R2 - * @param ip6_dst the destination address of the R2 * @param common the R2 packet * @param tuple the connection tracking tuple corresponding to the R2 packet * @param ctx packet context * * @return one if packet was processed successfully or zero otherwise */ -static int handle_r2(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, - const struct hip_common *common, struct tuple *tuple, - hip_fw_context_t *ctx) +static int handle_r2(const struct hip_common *common, struct tuple *tuple, + const hip_fw_context_t *ctx) { struct hip_esp_info *spi = NULL; struct tuple *other_dir = NULL; SList *other_dir_esps = NULL; struct esp_tuple *esp_tuple = NULL; + const struct in6_addr *ip6_src = &ctx->src; int err = 1; HIP_IFEL(!(spi = (struct hip_esp_info *) hip_get_param(common, HIP_PARAM_ESP_INFO)), @@ -1192,11 +1211,6 @@ HIP_DEBUG("ESP tuple already exists!\n"); } - if (esp_relay) { - HIP_IFEL(hip_handle_esp_in_udp_relay_r2(ip6_src, ip6_dst, common, tuple, esp_tuple, ctx), - -1, "ESP-in-UDP relay failed\n"); - } - /* check if the R2 contains ESP protection anchor and store state */ HIP_IFEL(esp_prot_conntrack_R2_anchor(common, tuple), -1, "failed to track esp protection extension state\n"); @@ -1208,6 +1222,11 @@ * else * other_dir = &tuple->connection->original;*/ + if (esp_relay && ctx->udp_encap_hdr) { + HIP_IFEL(hipfw_handle_relay_to_r2(common, ctx), + -1, "handling of relay_to failed\n"); + } + out_err: return err; } @@ -1341,26 +1360,23 @@ * @todo: SPI parameters did not work earlier and could not be used for creating * connection state for updates - check if the situation is still the same * - * @param ip6_src the source address of the R2 - * @param ip6_dst the destination address of the R2 * @param common the R2 packet * @param tuple the connection tracking tuple corresponding to the R2 packet + * @param ctx packet context * * @return one if packet was processed successfully or zero otherwise */ -static int handle_update(const struct in6_addr *ip6_src, - const struct in6_addr *ip6_dst, - const struct hip_common *common, - struct tuple *tuple) +static int handle_update(const struct hip_common *common, + struct tuple *tuple, + const hip_fw_context_t *ctx) { struct hip_seq *seq = NULL; struct hip_esp_info *esp_info = NULL; struct hip_ack *ack = NULL; struct hip_locator *locator = NULL; struct hip_spi *spi = NULL; - struct hip_echo_request *echo_req = NULL; - struct hip_echo_response *echo_res = NULL; struct tuple *other_dir_tuple = NULL; + const struct in6_addr *ip6_src = &ctx->src; int err = 0; _HIP_DEBUG("handle_update\n"); @@ -1371,10 +1387,6 @@ ack = (struct hip_ack *) hip_get_param(common, HIP_PARAM_ACK); locator = (struct hip_locator *) hip_get_param(common, HIP_PARAM_LOCATOR); spi = (struct hip_spi *) hip_get_param(common, HIP_PARAM_ESP_INFO); - echo_req = (struct hip_echo_request *) hip_get_param(common, - HIP_PARAM_ECHO_REQUEST); - echo_res = (struct hip_echo_response *) hip_get_param(common, - HIP_PARAM_ECHO_RESPONSE); if (spi) { _HIP_DEBUG("handle_update: spi param, spi: 0x%lx \n", ntohl(spi->spi)); @@ -1472,47 +1484,21 @@ _HIP_DEBUG("handle_update: esp_info and locator found\n"); - /* TODO check processing of SPI - * - * old_spi == 0, new_spi = x means that host is requesting a new SA - * old_spi == new_spi means only location update - * old_spi != new_spi means esp_tuple update */ - if (esp_info->old_spi != esp_info->new_spi) { //update existing - esp_tuple = find_esp_tuple(other_dir_esps, ntohl(esp_info->old_spi)); - - if (!esp_tuple) { - _HIP_DEBUG("No suitable esp_tuple found for updating\n"); - - err = 0; - goto out_err; - } - - if (!update_esp_tuple(esp_info, locator, seq, esp_tuple)) { - _HIP_DEBUG("failed to update the esp_tuple\n"); - - err = 0; - goto out_err; - } - } - -/* why would we want to do that? We already know this connection and this is a U1 */ -#if 0 - } else { /* create new esp_tuple */ - new_esp = esp_tuple_from_esp_info_locator(esp_info, locator, seq, - other_dir_tuple); - - if (new_esp == NULL) { - //locator must contain address for this spi - err = 0; - goto out_err; - } - - other_dir_tuple->esp_tuples = (SList *) append_to_slist((SList *) - other_dir_esps, (void *) new_esp); - - insert_esp_tuple(new_esp); - } -#endif + esp_tuple = find_esp_tuple(other_dir_esps, ntohl(esp_info->old_spi)); + + if (!esp_tuple) { + _HIP_DEBUG("No suitable esp_tuple found for updating\n"); + + err = 0; + goto out_err; + } + + if (!update_esp_tuple(esp_info, locator, seq, esp_tuple)) { + _HIP_DEBUG("failed to update the esp_tuple\n"); + + err = 0; + goto out_err; + } } else if (locator && seq) { /* Readdress without rekeying */ @@ -1660,13 +1646,6 @@ } #endif - if (echo_req) { - _HIP_DEBUG("handle_update: echo found req\n"); - } - - if (echo_res) { - _HIP_DEBUG("handle_update: echo found res\n"); - } } /* everything should be set now in order to process eventual anchor params */ @@ -1680,17 +1659,17 @@ /** * Process a CLOSE packet * - * @param ip6_src the source address of the CLOSE packet - * @param ip6_dst the destination address of the CLOSE packet * @param common the CLOSE packet * @param tuple the connection tracking tuple corresponding to the CLOSE packet + * @param ctx packet context * * @return one if packet was processed successfully or zero otherwise */ static int handle_close(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, const struct hip_common *common, - struct tuple *tuple) + struct tuple *tuple, + const hip_fw_context_t *ctx) { int err = 1; @@ -1724,17 +1703,17 @@ /** * Process CLOSE_ACK and remove the connection. * - * @param ip6_src the source address of the CLOSE_ACK - * @param ip6_dst the destination address of the CLOSE_ACK * @param common the CLOSE_ACK packet * @param tuple the connection tracking tuple corresponding to the CLOSE_ACK packet + * @param ctx packet context * * @return one if packet was processed successfully or zero otherwise */ int handle_close_ack(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, const struct hip_common *common, - struct tuple *tuple) + struct tuple *tuple, + const hip_fw_context_t *ctx) { int err = 1; @@ -1907,11 +1886,11 @@ goto out_err; } } else if (common->type_hdr == HIP_R1) { - err = handle_r1(common, tuple, verify_responder); + err = handle_r1(common, tuple, verify_responder, ctx); } else if (common->type_hdr == HIP_I2) { - err = handle_i2(ip6_src, ip6_dst, common, tuple); + err = handle_i2(common, tuple, ctx); } else if (common->type_hdr == HIP_R2) { - err = handle_r2(ip6_src, ip6_dst, common, tuple, ctx); + err = handle_r2(common, tuple, ctx); } else if (common->type_hdr == HIP_UPDATE) { if (!(tuple && tuple->hip_tuple->data->src_hi != NULL)) { HIP_DEBUG("signature was NOT verified\n"); @@ -1927,7 +1906,7 @@ } if (err) { - err = handle_update(ip6_src, ip6_dst, common, tuple); + err = handle_update(common, tuple, ctx); } } else if (common->type_hdr == HIP_NOTIFY) { // don't process and let pass through @@ -1936,12 +1915,12 @@ // don't process and let pass through err = 1; } else if (common->type_hdr == HIP_CLOSE) { - err = handle_close(ip6_src, ip6_dst, common, tuple); + err = handle_close(ip6_src, ip6_dst, common, tuple, ctx); } else if (common->type_hdr == HIP_CLOSE_ACK) { - err = handle_close_ack(ip6_src, ip6_dst, common, tuple); + err = handle_close_ack(ip6_src, ip6_dst, common, tuple, ctx); tuple = NULL; } else if (common->type_hdr == HIP_LUPDATE) { - err = esp_prot_conntrack_lupdate(ip6_src, ip6_dst, common, tuple); + err = esp_prot_conntrack_lupdate(common, tuple, ctx); } else { HIP_ERROR("unknown packet type\n"); err = 0; @@ -1958,6 +1937,16 @@ } } + HIP_DEBUG("udp_encap_hdr=%p tuple=%p err=%d\n", ctx->udp_encap_hdr, tuple, err); + + /* Cache UDP port numbers (at the moment, used only by the ESP relay) */ + if (ctx->udp_encap_hdr && (err == 1) && tuple) { + tuple->src_port = ntohs(ctx->udp_encap_hdr->source); + tuple->dst_port = ntohs(ctx->udp_encap_hdr->dest); + HIP_DEBUG("UDP src port %d\n", tuple->src_port); + HIP_DEBUG("UDP dst port %d\n", tuple->dst_port); + } + out_err: return err; } @@ -1969,48 +1958,77 @@ * * @param ctx context for the packet * @param tuple the tuple corresponding to the packet - * @return zero on success or non-zero on failure + * @return Zero means that a new relay packet was reinjected successfully + * and the original should be dropped. -1 means that the reinjected + * packet was processed again and should be just accepted without + * ESP filtering. 1 means that the packet was not related to relayin + * and should just proceed to ESP filtering. */ -static int relay_esp_in_udp(const hip_fw_context_t *ctx, - const struct tuple *tuple) +int hipfw_relay_esp(const hip_fw_context_t *ctx) { - struct iphdr *iph = (struct iphdr *) ctx->ipq_packet->payload; + struct iphdr *iph = (struct iphdr *) ctx->ipq_packet->payload; struct udphdr *udph = (struct udphdr *) ((uint8_t *) iph + iph->ihl * 4); - int len = ctx->ipq_packet->data_len - iph->ihl * 4; - int err = 0; - - if (iph->protocol != IPPROTO_UDP) { - HIP_DEBUG("Protocol is not UDP. Not relaying packet.\n"); - goto out_err; - } - - _HIP_DEBUG("%d %d %d %d %d %d %d %d %d\n", - htons(tuple->connection->original.relayed_src_port), - htons(tuple->connection->original.relayed_dst_port), - htons(tuple->connection->reply.relayed_src_port), - htons(tuple->connection->reply.relayed_dst_port), - htons(tuple->relayed_src_port), - htons(tuple->relayed_dst_port), - htons(udph->source), - htons(udph->dest), - tuple->direction); - - HIP_DEBUG_IN6ADDR("original src", tuple->src_ip); - - if (udph->source == tuple->connection->original.relayed_src_port) { - udph->dest = tuple->connection->original.relayed_src_port; - } else { - udph->dest = tuple->connection->original.relayed_dst_port; - } + int len = ctx->ipq_packet->data_len - iph->ihl * 4; + SList *list = (SList *) espList; + struct tuple *tuple = NULL; + struct hip_esp *esp = ctx->transport_hdr.esp; + int err = 0; + uint32_t spi; + + HIP_IFEL(!list, -1, "List is empty\n"); + HIP_IFEL((iph->protocol != IPPROTO_UDP), -1, + "Protocol is not UDP. Not relaying packet.\n\n"); + HIP_IFEL(!esp, -1, "No ESP header\n"); + + spi = ntohl(esp->esp_spi); + HIP_IFEL(!(tuple = get_tuple_by_esp(NULL, spi)), 0, + "No tuple, skip\n"); + + HIP_DEBUG("SPI is 0x%lx\n", spi); + + HIP_IFEL((tuple->esp_relay == 0), -1, "Relay is off for this tuple\n"); + + HIP_IFEL((ipv6_addr_cmp(&ctx->dst, &tuple->esp_relay_daddr) == 0), 1, + "Reinjected relayed packet, passing it\n"); + + HIP_IFEL(hip_fw_hit_is_our(&tuple->connection->original.hip_tuple->data->dst_hit), + 0, "Destination HIT belongs to us, no relaying\n"); + + HIP_DEBUG_IN6ADDR("I", &tuple->connection->original.hip_tuple->data->src_hit); + HIP_DEBUG_IN6ADDR("I", tuple->connection->original.src_ip); + HIP_DEBUG_IN6ADDR("R", &tuple->connection->original.hip_tuple->data->dst_hit); + HIP_DEBUG_IN6ADDR("R", tuple->connection->original.dst_ip); + + HIP_DEBUG("%d %d %d %d %d %d %d %d %d %d\n", + tuple->src_port, + tuple->dst_port, + tuple->connection->original.src_port, + tuple->connection->original.dst_port, + tuple->connection->reply.src_port, + tuple->connection->reply.dst_port, + ntohs(udph->source), + ntohs(udph->dest), + tuple->direction, + tuple->esp_relay_dport); + + HIP_DEBUG_IN6ADDR("src", tuple->src_ip); + HIP_DEBUG_IN6ADDR("dst", tuple->dst_ip); + HIP_DEBUG_IN6ADDR("esp_relay_addr", &tuple->esp_relay_daddr); + udph->source = htons(HIP_NAT_UDP_PORT); + udph->dest = htons(tuple->esp_relay_dport); udph->check = 0; HIP_DEBUG("Relaying packet\n"); - hip_firewall_send_outgoing_pkt(&ctx->dst, tuple->dst_ip, - (uint8_t *) iph + iph->ihl * 4, len, iph->protocol); + err = hip_firewall_send_outgoing_pkt(&ctx->dst, + &tuple->esp_relay_daddr, + (uint8_t *) iph + iph->ihl * 4, len, + iph->protocol); + out_err: - return err; + + return -err; } /** @@ -2060,13 +2078,6 @@ err = 1; } - if (esp_relay && !hip_fw_hit_is_our(&tuple->hip_tuple->data->dst_hit) && - !hip_fw_hit_is_our(&tuple->hip_tuple->data->src_hit) && - ipv6_addr_cmp(dst_addr, tuple->dst_ip) && - ctx->ip_version == 4) { - relay_esp_in_udp(ctx, tuple); - } - #ifdef CONFIG_HIP_MIDAUTH if (use_midauth && tuple->connection->pisa_state == PISA_STATE_DISALLOW) { HIP_DEBUG("PISA: ESP unauthorized -> dropped\n"); @@ -2202,13 +2213,14 @@ * @param buf the control packet * @param ctx context for the control packet */ -void conntrack(const struct in6_addr *ip6_src, +int conntrack(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, struct hip_common *buf, hip_fw_context_t *ctx) { struct hip_data *data = NULL; struct tuple *tuple = NULL; + int verdict = 0; _HIP_DEBUG("\n"); //g_mutex_lock(connectionTableMutex); @@ -2223,12 +2235,14 @@ // the accept_mobile parameter is true as packets // are not filtered here - check_packet(ip6_src, ip6_dst, buf, tuple, 0, 1, ctx); + verdict = check_packet(ip6_src, ip6_dst, buf, tuple, 0, 1, ctx); //g_mutex_unlock(connectionTableMutex); _HIP_DEBUG("unlocked mutex\n"); free(data); + + return verdict; } /** === modified file 'firewall/conntrack.h' --- firewall/conntrack.h 2010-02-17 17:38:08 +0000 +++ firewall/conntrack.h 2010-03-19 09:53:35 +0000 @@ -1,6 +1,8 @@ #ifndef HIP_FIREWALL_CONNTRACK_H #define HIP_FIREWALL_CONNTRACK_H +#define _BSD_SOURCE + #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip6.h> @@ -22,7 +24,7 @@ struct hip_common *buf, const struct state_option *option, const int accept, hip_fw_context_t *ctx); -void conntrack(const struct in6_addr *ip6_src, +int conntrack(const struct in6_addr *ip6_src, const struct in6_addr *ip6_dst, struct hip_common *buf, hip_fw_context_t *ctx); @@ -30,5 +32,6 @@ struct esp_tuple *find_esp_tuple(const SList *esp_list, const uint32_t spi); struct tuple *get_tuple_by_hits(const struct in6_addr *src_hit, const struct in6_addr *dst_hit); +int hipfw_relay_esp(const hip_fw_context_t *ctx); #endif === modified file 'firewall/datapkt.c' --- firewall/datapkt.c 2010-02-17 17:38:08 +0000 +++ firewall/datapkt.c 2010-03-19 09:53:35 +0000 @@ -27,10 +27,9 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ +#include <netinet/ip.h> +#include "config.h" #include "datapkt.h" #include "user_ipsec_api.h" #include "user_ipsec_esp.h" @@ -38,6 +37,8 @@ #include "lib/core/debug.h" #include "lib/core/ife.h" #include "lib/core/builder.h" +#include "lib/core/hostid.h" +#include "lib/core/message.h" static unsigned char *hip_data_packet = NULL; @@ -84,6 +85,49 @@ } /** + * ask hipd to sign a hiccups data packet + * + * @param src_hit the source HIT of the data packet + * @param dst_hit the destination HIT of the data packet + * @param payload the payload protocol value + * @param msg An input/output parameter. For input, contains the + * data packet with payload. For output, contains the + * same but including a signature from hipd. + * @return zero on success or negative on error + */ +int hip_get_data_packet_header(const struct in6_addr *src_hit, + const struct in6_addr *dst_hit, + int payload, + struct hip_common *msg) +{ + int err = 0; + + hip_build_network_hdr(msg, HIP_DATA, 0, src_hit, dst_hit); + msg->payload_proto = payload; + + HIP_DEBUG("PAYLOAD_PROTO in HIP DATA HEADER = %d ", payload ); + + /* @todo: this will assert */ + HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_BUILD_HOST_ID_SIGNATURE_DATAPACKET, 0), + -1, "build hdr failed\n"); + _HIP_DUMP_MSG(msg); + + /* send msg to hipd and receive corresponding reply */ + HIP_IFEL(hip_send_recv_daemon_info(msg, 0, 0), -1, "send_recv msg failed\n"); + + /* check error value */ + HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n"); + HIP_DEBUG("Send_recv msg succeed \n"); + +out_err: + msg->type_hdr = HIP_DATA; + /* this was overwritten by some mischief.. So reseting it */ + msg->payload_proto = payload; + + return err; +} + +/** * Process an inbound HICCUPS data packet and remove the HIP header. Caller * is responsible to reinjecting the decapsulated message back to the networking * stack. === modified file 'firewall/esp_prot_api.c' --- firewall/esp_prot_api.c 2010-02-18 13:36:05 +0000 +++ firewall/esp_prot_api.c 2010-03-19 09:53:35 +0000 @@ -18,9 +18,7 @@ #include <openssl/sha.h> #include <math.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ +#include "config.h" #include "lib/core/common_defines.h" #include "lib/core/debug.h" === modified file 'firewall/esp_prot_config.h' --- firewall/esp_prot_config.h 2010-02-17 17:38:08 +0000 +++ firewall/esp_prot_config.h 2010-03-19 09:53:35 +0000 @@ -16,9 +16,7 @@ #ifndef HIP_FIREWALL_ESP_PROT_CONFIG_H #define HIP_FIREWALL_ESP_PROT_CONFIG_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ +#include "config.h" /* WORKAROUND: some platforms don't support libconfig out of the box */ #ifdef HAVE_LIBCONFIG === modified file 'firewall/esp_prot_conntrack.c' --- firewall/esp_prot_conntrack.c 2010-02-17 17:38:08 +0000 +++ firewall/esp_prot_conntrack.c 2010-03-19 09:53:35 +0000 @@ -15,12 +15,9 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <netinet/udp.h> #include "lib/core/builder.h" - -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "esp_prot_conntrack.h" #include "esp_prot_api.h" #include "hslist.h" @@ -968,16 +965,14 @@ /** * Tracks an HHL-based update message * - * @param ip6_src the source address of the packet - * @param ip6_dst the destination address of the packet * @param common the HIP message * @param tuple state maintained for this connection + * @param ctx packet context * @return 0 on success, -1 in case of an error */ -int esp_prot_conntrack_lupdate(const struct in6_addr *ip6_src, - const struct in6_addr *ip6_dst, - const struct hip_common *common, - struct tuple *tuple) +int esp_prot_conntrack_lupdate(const struct hip_common *common, + struct tuple *tuple, + const hip_fw_context_t *ctx) { struct hip_seq *seq = NULL; struct hip_tlv_common *param = NULL; @@ -987,6 +982,8 @@ struct esp_prot_root *esp_roots[MAX_NUM_PARALLEL_HCHAINS]; struct hip_ack *ack = NULL; struct hip_esp_info *esp_info = NULL; + const struct in6_addr *ip6_src = &ctx->src; + const struct in6_addr *ip6_dst = &ctx->dst; int err = 0; long i; === modified file 'firewall/esp_prot_conntrack.h' --- firewall/esp_prot_conntrack.h 2010-02-17 17:38:08 +0000 +++ firewall/esp_prot_conntrack.h 2010-03-19 09:53:35 +0000 @@ -14,6 +14,8 @@ #ifndef HIP_FIREWALL_ESP_PROT_CONNTRACK_H #define HIP_FIREWALL_ESP_PROT_CONNTRACK_H +#define _BSD_SOURCE + #include "lib/core/protodefs.h" #include "conntrack.h" @@ -37,10 +39,9 @@ int esp_prot_conntrack_update(const hip_common_t *update, const struct tuple *tuple); int esp_prot_conntrack_remove_state(struct esp_tuple *esp_tuple); -int esp_prot_conntrack_lupdate(const struct in6_addr *ip6_src, - const struct in6_addr *ip6_dst, - const struct hip_common *common, - struct tuple *tuple); +int esp_prot_conntrack_lupdate(const struct hip_common *common, + struct tuple *tuple, + const hip_fw_context_t *ctx); int esp_prot_conntrack_verify(const hip_fw_context_t *ctx, struct esp_tuple *esp_tuple); === modified file 'firewall/esp_prot_fw_msg.c' --- firewall/esp_prot_fw_msg.c 2010-02-17 17:38:08 +0000 +++ firewall/esp_prot_fw_msg.c 2010-03-19 09:53:35 +0000 @@ -13,10 +13,13 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <netinet/udp.h> + #include "lib/core/debug.h" #include "lib/core/ife.h" #include "lib/core/kerncompat.h" #include "lib/core/builder.h" +#include "lib/core/message.h" #include "esp_prot_fw_msg.h" #include "esp_prot_api.h" === modified file 'firewall/firewall.c' --- firewall/firewall.c 2010-03-03 13:16:18 +0000 +++ firewall/firewall.c 2010-03-19 09:53:35 +0000 @@ -30,10 +30,7 @@ #include <netinet/in.h> /* in_addr, in6_addr */ #include <linux/netfilter_ipv4.h> /* NF_IP_LOCAL_IN, etc */ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "firewall.h" /* default include */ #include "conntrack.h" /* connection tracking */ #include "proxy.h" /* HIP Proxy */ @@ -43,6 +40,7 @@ #include "cache_port.h" /* required by opptcp */ #include "lsi.h" /* LSI */ #include "lib/core/hip_capability.h" /* Priviledge Separation */ +#include "lib/core/hip_udp.h" #include "user_ipsec_api.h" /* Userspace IPsec */ #include "esp_prot_conntrack.h" /* ESP Tokens */ #include "esp_prot_api.h" /* ESP Tokens */ @@ -58,6 +56,7 @@ #include "lib/performance/performance.h" /* Performance Analysis */ #endif #include "helpers.h" +#include "lib/core/filemanip.h" /* packet types handled by the firewall */ #define OTHER_PACKET 0 @@ -1122,16 +1121,28 @@ */ static int filter_esp(const hip_fw_context_t *ctx) { - // drop packet by default - int verdict = 0; + /* drop packet by default */ + int verdict = 0, ret; - if (filter_esp_state(ctx) > 0) { + if (esp_relay && ctx->udp_encap_hdr && + ((ret = hipfw_relay_esp(ctx)) <= 0)) { + /* 0: drop original and reinject new packet + -1: accept reinject packet and avoid filter_esp_state + 1: just let it pass => proceed to filter */ + if (ret == 0) { + HIP_DEBUG("Drop original and reinject relayed ESP packet\n"); + verdict = 0; + } else if (ret == -1) { + HIP_DEBUG("Accept reinjected packet\n"); + verdict = 1; + } else { + HIP_ASSERT(0); + } + } else if (filter_esp_state(ctx) > 0) { verdict = 1; - HIP_DEBUG("ESP packet successfully passed filtering\n"); } else { verdict = 0; - HIP_DEBUG("ESP packet NOT authed in ESP filtering\n"); } @@ -1355,13 +1366,8 @@ //release rule list read_rules_exit(0); - /* FIXME this actually verifies the packet and should be incorporated in the - * resulting verdict!!! */ - // if packet will be accepted and connection tracking is used - // but there is no state for the packet in the conntrack module - // yet -> show the packet to conntracking if (statefulFiltering && verdict && !conntracked) { - conntrack(ip6_src, ip6_dst, buf, ctx); + verdict = conntrack(ip6_src, ip6_dst, buf, ctx); } return verdict; @@ -1456,9 +1462,6 @@ verdict = ACCEPT; } - HIP_INFO("\n"); - -out_err: /* zero return value means that the packet should be dropped */ return verdict; } === modified file 'firewall/firewall.h' --- firewall/firewall.h 2010-02-17 17:38:08 +0000 +++ firewall/firewall.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,7 @@ #ifndef HIP_FIREWALL_FIREWALL_H #define HIP_FIREWALL_FIREWALL_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/protodefs.h" /** globally used variables defined in firewall.c */ === modified file 'firewall/firewall_control.c' --- firewall/firewall_control.c 2010-03-03 13:16:18 +0000 +++ firewall/firewall_control.c 2010-03-19 09:53:35 +0000 @@ -15,10 +15,7 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "firewall_control.h" #include "firewall.h" /* extern int esp_relay */ #include "proxy.h" === modified file 'firewall/firewall_control.h' --- firewall/firewall_control.h 2010-02-17 17:38:08 +0000 +++ firewall/firewall_control.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,7 @@ #ifndef HIP_FIREWALL_FIREWALL_CONTROL_H #define HIP_FIREWALL_FIREWALL_CONTROL_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/builder.h" #include "lib/core/protodefs.h" === modified file 'firewall/firewall_defines.h' --- firewall/firewall_defines.h 2010-02-17 17:38:08 +0000 +++ firewall/firewall_defines.h 2010-03-19 09:53:35 +0000 @@ -1,14 +1,14 @@ #ifndef HIP_FIREWALL_FIREWALL_DEFINES_H #define HIP_FIREWALL_FIREWALL_DEFINES_H +#define _BSD_SOURCE + +#include <net/if.h> #include <sys/time.h> #include <libipq.h> #include <string.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/linkedlist.h" #include "lib/core/common_defines.h" #include "lib/core/esp_prot_common.h" @@ -108,8 +108,8 @@ struct hip_tuple * hip_tuple; struct in6_addr * src_ip; struct in6_addr * dst_ip; - in_port_t relayed_src_port; - in_port_t relayed_dst_port; + in_port_t src_port; + in_port_t dst_port; SList * esp_tuples; int direction; struct connection *connection; @@ -118,6 +118,9 @@ #ifdef CONFIG_HIP_HIPPROXY int hipproxy; #endif + int esp_relay; + struct in6_addr esp_relay_daddr; + in_port_t esp_relay_dport; }; struct connection { @@ -139,63 +142,4 @@ struct hip_esp *esp_data; }; -typedef struct pseudo_v6 { - struct in6_addr src; - struct in6_addr dst; - uint16_t length; - uint16_t zero1; - uint8_t zero2; - uint8_t next; -} pseudo_v6; - -static inline uint16_t inchksum(const void *data, uint32_t length) -{ - long sum = 0; - const uint16_t *wrd = (uint16_t *) data; - long slen = (long) length; - - while (slen > 1) { - sum += *wrd++; - slen -= 2; - } - - if (slen > 0) { - sum += *((uint8_t *) wrd); - } - - while (sum >> 16) { - sum = (sum & 0xffff) + (sum >> 16); - } - - return (uint16_t) sum; -} - -static inline uint16_t ipv6_checksum(uint8_t protocol, - struct in6_addr *src, - struct in6_addr *dst, - void *data, uint16_t len) -{ - uint32_t chksum = 0; - pseudo_v6 pseudo; - memset(&pseudo, 0, sizeof(pseudo_v6)); - - pseudo.src = *src; - pseudo.dst = *dst; - pseudo.length = htons(len); - pseudo.next = protocol; - - chksum = inchksum(&pseudo, sizeof(pseudo_v6)); - chksum += inchksum(data, len); - - chksum = (chksum >> 16) + (chksum & 0xffff); - chksum += (chksum >> 16); - - chksum = (uint16_t) (~chksum); - if (chksum == 0) { - chksum = 0xffff; - } - - return chksum; -} - #endif /*HIP_FIREWALL_FIREWALL_DEFINES_H*/ === modified file 'firewall/firewalldb.c' --- firewall/firewalldb.c 2010-03-19 09:24:10 +0000 +++ firewall/firewalldb.c 2010-03-19 09:53:35 +0000 @@ -4,6 +4,7 @@ * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> * * @todo THIS DATABASE IS REDUDANT WITH CACHE.C AND CONTAINS ONLY A SUBSET OF IT. REWRITE AND TEST!!! + * @note this code is linked to the use of hip_firewall_set_bex_data() * @todo move the raw socket initialization to somewhere else * * @brief Write a short summary @@ -17,6 +18,8 @@ #include <netinet/ip_icmp.h> #include <netinet/icmp6.h> +#include <netinet/udp.h> +#include <netinet/tcp.h> #include "firewalldb.h" #include "cache.h" @@ -25,7 +28,9 @@ #include "lib/core/kerncompat.h" #include "lib/core/debug.h" #include "lib/core/hashtable.h" -#include "lib/core/misc.h" +#include "lib/core/builder.h" + +#include "lib/tool/checksum.h" #define DISABLE_hip_firewall_hldb_dump #define DISABLE_firewall_init_raw_sock_esp_v6 === modified file 'firewall/lsi.c' --- firewall/lsi.c 2010-03-19 09:24:10 +0000 +++ firewall/lsi.c 2010-03-19 09:53:35 +0000 @@ -25,16 +25,126 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <netinet/ip6.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> #include "cache.h" #include "cache_port.h" #include "firewall.h" #include "firewalldb.h" #include "lsi.h" #include "lib/core/builder.h" +#include "lib/core/message.h" #define BUFSIZE HIP_MAX_PACKET /** + * build a message for hipd to trigger a base exchange + * + * @param src_hit an optional source HIT for the I1 + * @param dst_hit a destination HIT for the I1 + * @param src_lsi an optional source LSI (corresponding to a local HIT) + * @param dst_lsi a destination LSI for the I1 + * @param src_ip an optional source IP address for the I1 + * @param dst_ip a destination IP for the I1 + * @return zero on success or negative on error + + * @note Many of the parameters are optional, but at least a + * destination LSI, HIT or IP (for opportunistic BEX) must to be + * provided + */ +int hip_trigger_bex(const struct in6_addr *src_hit, + const struct in6_addr *dst_hit, + struct in6_addr *src_lsi, + struct in6_addr *dst_lsi, + struct in6_addr *src_ip, + struct in6_addr *dst_ip) +{ + struct hip_common *msg = NULL; + int err = 0; + HIP_IFE(!(msg = hip_msg_alloc()), -1); + HIP_IFEL(!dst_hit && !dst_ip, -1, + "neither destination hit nor ip provided\n"); + + /* NOTE: we need this sequence in order to process the incoming + * message correctly */ + + /* build the message header */ + HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_TRIGGER_BEX, 0), + -1, "build hdr failed\n"); + + /* destination HIT, LSI or IP are obligatory */ + if (dst_hit) { + HIP_DEBUG_HIT("dst_hit: ", dst_hit); + HIP_IFEL(hip_build_param_contents(msg, (void *) (dst_hit), + HIP_PARAM_HIT, + sizeof(struct in6_addr)), + -1, "build param HIP_PARAM_HIT failed\n"); + } + + /* source HIT is optional */ + if (src_hit) { + HIP_DEBUG_HIT("src_hit: ", src_hit); + HIP_IFEL(hip_build_param_contents(msg, (void *) (src_hit), + HIP_PARAM_HIT, + sizeof(struct in6_addr)), + -1, "build param HIP_PARAM_HIT failed\n"); + } + + /* destination LSI is obligatory */ + if (dst_lsi) { + HIP_DEBUG_IN6ADDR("dst lsi: ", dst_lsi); + HIP_IFEL(hip_build_param_contents(msg, (void *) (dst_lsi), + HIP_PARAM_LSI, + sizeof(struct in6_addr)), + -1, "build param HIP_PARAM_LSI failed\n"); + } + + /* source LSI is optional */ + if (src_lsi) { + HIP_DEBUG_IN6ADDR("src lsi: ", src_lsi); + HIP_IFEL(hip_build_param_contents(msg, (void *) (src_lsi), + HIP_PARAM_LSI, + sizeof(struct in6_addr)), + -1, "build param HIP_PARAM_LSI failed\n"); + } + + /* if no destination HIT is provided, at least destination IP must + exist */ + if (dst_ip) { + HIP_DEBUG_IN6ADDR("dst_ip: ", dst_ip); + HIP_IFEL(hip_build_param_contents(msg, (void *) (dst_ip), + HIP_PARAM_IPV6_ADDR, + sizeof(struct in6_addr)), + -1, "build param HIP_PARAM_IPV6_ADDR failed\n"); + } + + /* this again is optional */ + if (src_ip) { + HIP_DEBUG_IN6ADDR("src_ip: ", src_ip); + HIP_IFEL(hip_build_param_contents(msg, (void *) (src_ip), + HIP_PARAM_IPV6_ADDR, + sizeof(struct in6_addr)), + -1, "build param HIP_PARAM_IPV6_ADDR failed\n"); + } + + HIP_DUMP_MSG(msg); + + /* send msg to hipd and receive corresponding reply */ + HIP_IFEL(hip_send_recv_daemon_info(msg, 0, 0), -1, "send_recv msg failed\n"); + + /* check error value */ + HIP_IFEL(hip_get_msg_err(msg), -1, "hipd returned error message!\n"); + HIP_DEBUG("Send_recv msg succeed \n"); + +out_err: + if (msg) { + HIP_FREE(msg); + } + return err; +} + +/** * Checks if the packet is a reinjection * * @param ip_src pointer to the source address @@ -59,6 +169,67 @@ } /** + * get the state of the bex for a pair of ip addresses. + * + * @param src_ip input for finding the correct entries + * @param dst_ip input for finding the correct entries + * @param src_hit output data of the correct entry + * @param dst_hit output data of the correct entry + * @param src_lsi output data of the correct entry + * @param dst_lsi output data of the correct entry + * @return the state of the bex if the entry is found + * otherwise returns -1 + */ +int hip_get_bex_state_from_LSIs(hip_lsi_t *src_lsi, + hip_lsi_t *dst_lsi, + struct in6_addr *src_ip, + struct in6_addr *dst_ip, + struct in6_addr *src_hit, + struct in6_addr *dst_hit) +{ + int err = 0, res = -1; + struct hip_tlv_common *current_param = NULL; + struct hip_common *msg = NULL; + struct hip_hadb_user_info_state *ha; + + HIP_ASSERT(src_ip != NULL && dst_ip != NULL); + + HIP_IFEL(!(msg = hip_msg_alloc()), -1, "malloc failed\n"); + hip_msg_init(msg); + HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_GET_HA_INFO, 0), + -1, "Building of daemon header failed\n"); + HIP_IFEL(hip_send_recv_daemon_info(msg, 0, 0), -1, "send recv daemon info\n"); + + while ((current_param = hip_get_next_param(msg, current_param)) != NULL) { + ha = hip_get_param_contents_direct(current_param); + + if ((ipv4_addr_cmp(dst_lsi, &ha->lsi_our) == 0) && + (ipv4_addr_cmp(src_lsi, &ha->lsi_peer) == 0)) { + *src_hit = ha->hit_peer; + *dst_hit = ha->hit_our; + *src_ip = ha->ip_peer; + *dst_ip = ha->ip_our; + res = ha->state; + break; + } else if ((ipv4_addr_cmp(src_lsi, &ha->lsi_our) == 0) && + (ipv4_addr_cmp(dst_lsi, &ha->lsi_peer) == 0)) { + *src_hit = ha->hit_our; + *dst_hit = ha->hit_peer; + *src_ip = ha->ip_our; + *dst_ip = ha->ip_peer; + res = ha->state; + break; + } + } + +out_err: + if (msg) { + HIP_FREE(msg); + } + return res; +} + +/** * Analyzes first whether the ipv6 packet belongs to an ipv6 socket. * If not, it then analyzes whether the packet belongs to an * ipv4 socket with an LSI as IP address. === modified file 'firewall/lsi.h' --- firewall/lsi.h 2010-03-03 13:16:18 +0000 +++ firewall/lsi.h 2010-03-19 09:53:35 +0000 @@ -1,11 +1,19 @@ #ifndef HIP_FIREWALL_LSI_H #define HIP_FIREWALL_LSI_H +#define _BSD_SOURCE + #include <libipq.h> #include <netinet/ip_icmp.h> #include <linux/netfilter_ipv4/ip_queue.h> #include "lib/core/protodefs.h" +int hip_trigger_bex(const struct in6_addr *src_hit, + const struct in6_addr *dst_hit, + struct in6_addr *src_lsi, + struct in6_addr *dst_lsi, + struct in6_addr *src_ip, + struct in6_addr *dst_ip); int hip_fw_handle_incoming_hit(const ipq_packet_msg_t *m, const struct in6_addr *ip_src, const struct in6_addr *ip_dst, === modified file 'firewall/midauth.c' --- firewall/midauth.c 2010-02-18 12:26:08 +0000 +++ firewall/midauth.c 2010-03-19 09:53:35 +0000 @@ -22,14 +22,13 @@ #include <string.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/ife.h" #include "midauth.h" #include "pisa.h" #include "lib/core/builder.h" +#include "lib/core/solve.h" +#include "lib/tool/checksum.h" #ifdef CONFIG_HIP_PERFORMANCE #include "lib/performance/performance.h" === modified file 'firewall/midauth.h' --- firewall/midauth.h 2010-02-18 12:26:08 +0000 +++ firewall/midauth.h 2010-03-19 09:53:35 +0000 @@ -12,10 +12,11 @@ #ifndef HIP_FIREWALL_MIDAUTH_H #define HIP_FIREWALL_MIDAUTH_H +#define _BSD_SOURCE + #include <netinet/ip6.h> #include <netinet/ip.h> #include <netinet/udp.h> -#include <libipq.h> #include <linux/netfilter.h> #include "lib/core/protodefs.h" #include "lib/core/debug.h" === modified file 'firewall/opptcp.c' --- firewall/opptcp.c 2010-02-17 17:38:08 +0000 +++ firewall/opptcp.c 2010-03-19 09:53:35 +0000 @@ -36,11 +36,13 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <netinet/tcp.h> #include "opptcp.h" #include "firewalldb.h" #include "lib/core/debug.h" #include "lib/core/protodefs.h" #include "lib/core/builder.h" +#include "lib/core/message.h" #include "common_hipd_msg.h" #include "firewall.h" === modified file 'firewall/pisa.c' --- firewall/pisa.c 2010-03-19 09:24:10 +0000 +++ firewall/pisa.c 2010-03-19 09:53:35 +0000 @@ -20,13 +20,11 @@ #include <time.h> #include <stdio.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/ife.h" +#include "lib/core/crypto.h" #include "midauth.h" -#include "lib/core/misc.h" + #include "pisa.h" #include "pisa_cert.h" #define PISA_RANDOM_LEN 16 === modified file 'firewall/proxy.c' --- firewall/proxy.c 2010-03-19 09:24:10 +0000 +++ firewall/proxy.c 2010-03-19 09:53:35 +0000 @@ -1,5 +1,11 @@ -/* - * HIP proxy +/** @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * HIP client-side proxy. Documented in detail in Weiwei's thesis when + * it's finished. + * + * @author Weiwei Hu */ /* required for s6_addr32 */ @@ -10,6 +16,7 @@ #include "firewall/proxy.h" #include "firewall/proxyconndb.h" #include "firewall/firewall_defines.h" +#include "lib/tool/checksum.h" int hip_proxy_raw_sock_tcp_v4 = 0; int hip_proxy_raw_sock_tcp_v6 = 0; @@ -21,12 +28,13 @@ const char hip_proxy_supported_proto[] = { IPPROTO_TCP, IPPROTO_ICMP, IPPROTO_UDP }; -/** - * - * - * @return zero on success, non-zero on error - */ + #ifdef CONFIG_HIP_HIPPROXY +/** + * Request the status of the HIP proxy + * + * @return zero on success, non-zero on error + */ int request_hipproxy_status(void) { struct hip_common *msg = NULL; @@ -56,6 +64,14 @@ #endif /* CONFIG_HIP_HIPPROXY */ + +/** + * Request the peer HIT from HIP Daemon + * + * @param peer_ip the address of the peer host (HIP Server) + * @param local_hit the HIT of the local HIP proxy + * @return zero on success, non-zero on error + */ int hip_proxy_request_peer_hit_from_hipd(const struct in6_addr *peer_ip, const struct in6_addr *local_hit) { @@ -94,6 +110,12 @@ return err; } +/** + * Get the local HIT from HIP Daemon + * + * @param hit the pointer used to store the local HIT + * @return zero on success, non-zero on error + */ int hip_get_local_hit_wrapper(hip_hit_t *hit) { int err = 0; @@ -117,6 +139,12 @@ return err; } +/** + * Set the peer HIT into the HIP Proxy Database + * + * @param msg the received message for the HIT request of the peer host + * @return zero on success, non-zero on error + */ int hip_fw_proxy_set_peer_hit(hip_common_t *msg) { int fallback = 1, reject = 0, addr_found = 0, err = 0; @@ -210,6 +238,12 @@ return err; } +/** + * Initialize the IPv6 socket for TCP connection + * + * @param hip_raw_sock_v6 the socket pointer used for TCP connection in IPv6 + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_tcp_v6(int *hip_raw_sock_v6) { int on = 1, off = 0, err = 0; @@ -232,6 +266,12 @@ return err; } +/** + * Initialize the IPv4 socket for TCP connection + * + * @param hip_raw_sock_v4 the socket pointer used for TCP connection in IPv4 + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_tcp_v4(int *hip_raw_sock_v4) { int on = 1, err = 0; @@ -258,6 +298,12 @@ return err; } +/** + * Initialize the IPv6 socket for UDP connection + * + * @param hip_raw_sock_v6 the socket pointer used for UDP connection in IPv6 + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_udp_v6(int *hip_raw_sock_v6) { int on = 1, off = 0, err = 0; @@ -280,6 +326,12 @@ return err; } +/** + * Initialize the IPv4 socket for UDP connection + * + * @param hip_raw_sock_v4 the socket pointer used for UDP connection in IPv4 + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_udp_v4(int *hip_raw_sock_v4) { int on = 1, err = 0; @@ -306,6 +358,12 @@ return err; } +/** + * Initialize the ICMPv6 socket + * + * @param hip_raw_sock_v6 the socket pointer used for ICMPv6 connection + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_icmp_v6(int *hip_raw_sock_v6) { int on = 1, off = 0, err = 0; @@ -329,6 +387,12 @@ return err; } +/** + * Initialize the ICMP socket + * + * @param hip_raw_sock_v4 the socket pointer used for ICMP + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_icmp_v4(int *hip_raw_sock_v4) { int on = 1, err = 0; @@ -356,6 +420,12 @@ return err; } +/** + * Initialize the ICMPV6 socket for Inbound connection + * + * @param hip_raw_sock_v6 the socket pointer used for ICMPv6 connection in IPv6 + * @return zero on success, non-zero on error + */ int hip_init_proxy_raw_sock_icmp_inbound(int *hip_raw_sock_v6) { int on = 1, off = 0, err = 0; @@ -378,6 +448,11 @@ return err; } +/** + * Initialize all the sockets + * + * @return zero on success, non-zero on error + */ int hip_proxy_init_raw_sockets(void) { hip_init_proxy_raw_sock_tcp_v6(&hip_proxy_raw_sock_tcp_v6); @@ -391,8 +466,11 @@ return 0; } -// TODO add hip_proxy_UNinit_raw_sockets() - +/** + * Initialize the HIP proxy + * + * @return zero on success, non-zero on error + */ int init_proxy(void) { int err = 0; @@ -404,6 +482,11 @@ return err; } +/** + * Uninitialize the HIP proxy + * + * @return zero on success, non-zero on error + */ int uninit_proxy(void) { int err = 0; @@ -415,6 +498,15 @@ return err; } +/** + * Send packets to the HIP server + * @param local_addr the HIT of the sender + * @param peer_addr the HIT of the receiver + * @param msg the payload of the packet + * @param len the len of the packet + * @param protocol the protocol of the connection + * @return zero on success, non-zero on error + */ static int hip_proxy_send_pkt(struct in6_addr *local_addr, struct in6_addr *peer_addr, uint8_t *msg, uint16_t len, int protocol) @@ -620,6 +712,14 @@ return err; } +/** + * Send packets to the legacy client + * @param local_addr the address of the sender + * @param peer_addr the address of the receiver + * @param buff the payload of the packet + * @param len the len of the packet + * @return zero on success, non-zero on error + */ static int hip_proxy_send_to_client_pkt(struct in6_addr *local_addr, struct in6_addr *peer_addr, uint8_t *buff, uint16_t len) @@ -915,6 +1015,12 @@ return err; } +/** + * Handle the proxy inbound traffic + * @param m the ipq packet captured by the hipfw + * @param src_addr the source address + * @return zero on success, non-zero on error + */ int handle_proxy_inbound_traffic(const ipq_packet_msg_t *m, const struct in6_addr *src_addr) { @@ -975,15 +1081,23 @@ return err; } -static int hip_proxy_send_inbound_icmp_pkt(struct in6_addr *src_addr, struct in6_addr *dst_addr, uint8_t *buff, uint16_t len) +/** + * Send the inbound ICMP packet + * @param src_addr the ipq packet captured by the hipfw + * @param dst_addr the source address inside the packet + * @param buff the payload of the packet + * @param len the length of the payload + * @return zero on success, non-zero on error + */ +static int hip_proxy_send_inbound_icmp_pkt(struct in6_addr *src_addr, struct in6_addr *dst_addr, const unsigned char *buff, uint16_t len) { struct sockaddr_in6 src6, dst6; - struct ip *ip; - struct ip6_hdr *ip6; - struct icmphdr *icmp; + struct ip *ip = NULL; + struct ip6_hdr *ip6 = NULL; + struct icmphdr *icmp = NULL; int sa_size, sent; int on = 1; - uint8_t *msg; + unsigned char *msg = NULL; ip = (struct ip *) buff; @@ -1000,7 +1114,7 @@ HIP_DEBUG_IN6ADDR("dst6", &dst6.sin6_addr); sa_size = sizeof(struct sockaddr_in6); - msg = (uint8_t *) HIP_MALLOC((len + sizeof(struct ip6_hdr) - ip->ip_hl), 0); + msg = HIP_MALLOC((len + sizeof(struct ip6_hdr) - ip->ip_hl), 0); memset(msg, 0, (len + sizeof(struct ip6_hdr) - ip->ip_hl)); ip6 = (struct ip6_hdr *) msg; @@ -1032,6 +1146,15 @@ return 0; } +/** + * Handle the proxy outbound traffic + * @param m the ipq packet captured by the hipfw + * @param src_addr the source address + * @param dst_addr the destination address + * @param hdr_size the header size + * @param ip_version the IP protocol version + * @return zero on success, non-zero on error + */ int handle_proxy_outbound_traffic(const ipq_packet_msg_t *m, const struct in6_addr *src_addr, const struct in6_addr *dst_addr, @@ -1141,7 +1264,7 @@ } if ((protocol == IPPROTO_ICMP) || (protocol == IPPROTO_ICMPV6)) { - hip_proxy_send_inbound_icmp_pkt(proxy_hit, &entry->hit_peer, (uint8_t *) m->payload, m->data_len); + hip_proxy_send_inbound_icmp_pkt(proxy_hit, &entry->hit_peer, m->payload, m->data_len); /* drop packet */ err = 0; } else { === modified file 'firewall/proxy.h' --- firewall/proxy.h 2010-02-17 17:38:08 +0000 +++ firewall/proxy.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,13 @@ #ifndef HIP_FIREWALL_PROXY_H #define HIP_FIREWALL_PROXY_H +#define _BSD_SOURCE + #include <libipq.h> #include "firewall.h" #include "proxydb.h" +#include "config.h" #ifdef CONFIG_HIP_HIPPROXY int request_hipproxy_status(void); === modified file 'firewall/proxydb.c' --- firewall/proxydb.c 2010-02-17 17:38:08 +0000 +++ firewall/proxydb.c 2010-03-19 09:53:35 +0000 @@ -1,3 +1,13 @@ +/** @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * HIP client-side proxy databases. Documented in detail in Weiwei's + * thesis when it's finished. + * + * @author Weiwei Hu + */ + /* required for s6_addr32 */ #define _BSD_SOURCE @@ -5,6 +15,13 @@ HIP_HASHTABLE *hip_proxy_db = NULL; + +/** + * Create a hash of the given entry for the hash table + * + * @param p the connection entry + * @return a hash calculated based on the given entry + */ unsigned long hip_proxy_db_hash(const hip_proxy_t *p) { hip_hit_t hitpair[2]; @@ -28,6 +45,14 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_HASH_FN(hip_proxy_db, const hip_proxy_t) + +/** + * Compare two hash keys + * + * @param ha1 first hash key + * @param ha2 second hash key + * @return zero if keys match or one otherwise + */ int hip_proxy_db_cmp(const hip_proxy_t *ha1, const hip_proxy_t *ha2) { if (ha1 == NULL @@ -45,12 +70,19 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_COMP_FN(hip_proxy_db, const hip_proxy_t) + +/** + * Initialize the proxy database + */ void hip_init_proxy_db(void) { hip_proxy_db = hip_ht_init(LHASH_HASH_FN(hip_proxy_db), LHASH_COMP_FN(hip_proxy_db)); } +/** + * Unitialize the proxy database + */ void hip_uninit_proxy_db() { int i = 0; @@ -64,6 +96,13 @@ } } +/** + * Add an entry to the database of the HIP proxy + * + * @param addr_client Addess of the legacy client + * @param addr_peer Address of the HIP server + * @return zero on success or non-zero on failure + */ int hip_proxy_add_entry(const struct in6_addr *addr_client, const struct in6_addr *addr_peer) { @@ -89,6 +128,13 @@ return err; } +/** + * Find the proxy database entry corresponding to addresses + * + * @param addr the address of the legacy client + * @param addr2 the address of the HIP server + * @return the database entry if found or otherwise NULL + */ hip_proxy_t *hip_proxy_find_by_addr(const struct in6_addr *addr, const struct in6_addr *addr2) { @@ -99,6 +145,19 @@ return hip_ht_find(hip_proxy_db, &p); } +/** + * Update the entry state in the proxy database + * Only for known clients + * + * @param entry the HIP database entry + * @param client_addr the IP address of the client + * @param peer_addr the IP address of the server + * @param proxy_addr the IP address of the HIP proxy + * @param proxy_hit the HIT of the HIP proxy + * @param peer_hit the HIT of the server + * @param state the state of the connection entry + * @return zero on success or non-zero on failure + */ int hip_proxy_update_entry_state(hip_proxy_t *entry, struct in6_addr *client_addr, struct in6_addr *peer_addr, @@ -132,6 +191,13 @@ * The firewall receives R1 and does not know which client to serve. * Updates all clients. * + * @param client_addr the IP address of the client + * @param peer_addr the IP address of the server + * @param proxy_addr the IP address of the HIP proxy + * @param proxy_hit the HIT of the HIP proxy + * @param peer_hit the HIT of the server + * @param state the state of the connection entry + * */ int hip_proxy_update_state_no_client(struct in6_addr *client_addr, struct in6_addr *peer_addr, @@ -159,6 +225,19 @@ return 0; } + +/** + * Update the entry state in the proxy database for all cases. + * Available for the known clients and unknow clients + * + * @param client_addr the IP address of the client + * @param peer_addr the IP address of the server + * @param proxy_addr the IP address of the HIP proxy + * @param proxy_hit the HIT of the HIP proxy + * @param peer_hit the HIT of the server + * @param state the state of the connection entry + * + */ int hip_proxy_update_state(struct in6_addr *client_addr, struct in6_addr *peer_addr, struct in6_addr *proxy_addr, === modified file 'firewall/rule_management.c' --- firewall/rule_management.c 2010-03-03 13:16:18 +0000 +++ firewall/rule_management.c 2010-03-19 09:53:35 +0000 @@ -16,6 +16,7 @@ #include <stdio.h> #include <string.h> +#include <net/if.h> #include <netinet/in.h> //#include <linux/types.h> #include <linux/netfilter.h> @@ -28,15 +29,13 @@ #include <limits.h> #include <linux/netfilter_ipv6.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "rule_management.h" #include "helpers.h" #include "lib/core/builder.h" #include "lib/core/crypto.h" #include "lib/core/debug.h" +#include "lib/core/hostid.h" /* string tokens for rule parsing */ #define SRC_HIT_STR "-src_hit" @@ -900,12 +899,12 @@ } else { option->boolean = 1; } - if (strlen(token) > IFNAMSIZ) { + if (strlen(token) > IF_NAMESIZE) { HIP_DEBUG("parse_if error: invalid length interface name\n"); free(option); return NULL; } else { - option->value = (char *) malloc(IFNAMSIZ); + option->value = (char *) malloc(IF_NAMESIZE); strcpy(option->value, token); } return option; === modified file 'firewall/sysopp.c' --- firewall/sysopp.c 2010-02-17 17:38:08 +0000 +++ firewall/sysopp.c 2010-03-19 09:53:35 +0000 @@ -1,14 +1,19 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <netinet/ip6.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> + #include "lib/core/debug.h" #include "lib/core/builder.h" - +#include "lib/core/message.h" #include "sysopp.h" #include "firewall.h" #include "firewalldb.h" #include "lsi.h" #include "common_hipd_msg.h" +#include "lib/core/hostid.h" void hip_fw_flush_system_based_opp_chains(void) { === modified file 'firewall/user_ipsec_api.c' --- firewall/user_ipsec_api.c 2010-02-17 17:38:08 +0000 +++ firewall/user_ipsec_api.c 2010-03-19 09:53:35 +0000 @@ -21,6 +21,7 @@ #include "esp_prot_api.h" #include "lib/core/ife.h" #include "lib/core/debug.h" +#include "lsi.h" #define USER_IPSEC_INACTIVE 0 #define USER_IPSEC_ACTIVE 1 === modified file 'firewall/user_ipsec_api.h' --- firewall/user_ipsec_api.h 2010-02-17 17:38:08 +0000 +++ firewall/user_ipsec_api.h 2010-03-19 09:53:35 +0000 @@ -14,9 +14,11 @@ #ifndef HIP_FIREWALL_USER_IPSEC_API_H #define HIP_FIREWALL_USER_IPSEC_API_H +#define _BSD_SOURCE + #include <netinet/udp.h> #include <openssl/evp.h> -#include "lib/core/misc.h" + #include "firewall_defines.h" /* this is the maximum buffer-size needed for an userspace ipsec esp packet === modified file 'firewall/user_ipsec_esp.c' --- firewall/user_ipsec_esp.c 2010-03-03 13:16:18 +0000 +++ firewall/user_ipsec_esp.c 2010-03-19 09:53:35 +0000 @@ -32,49 +32,13 @@ #include "user_ipsec_esp.h" #include "esp_prot_api.h" #include "lib/core/prefix.h" -#include "lib/core/misc.h" + +#include "lib/tool/checksum.h" +#include "lib/core/keylen.h" /* for some reason the ICV for ESP authentication is truncated to 12 bytes */ #define ICV_LENGTH 12 -/** calculates the IP-checksum - * - * @param ip_hdr packet to be checksumed - * @param ip_hl header length field inside the header - * @return the IP checksum - */ -static uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl) -{ - uint16_t checksum = 0; - unsigned long sum = 0; - int count = ip_hl * 4; - unsigned short *p = (unsigned short *) ip_hdr; - - /* - * this checksum algorithm can be found - * in RFC 1071 section 4.1 - */ - - /* one's complement sum 16-bit words of data */ - while (count > 1) { - sum += *p++; - count -= 2; - } - /* add left-over byte, if any */ - if (count > 0) { - sum += (unsigned char) *p; - } - - /* Fold 32-bit sum to 16 bits */ - while (sum >> 16) { - sum = (sum & 0xffff) + (sum >> 16); - } - /* take the one's complement of the sum */ - checksum = (uint16_t) (~sum); - - return checksum; -} - /** adds an UDP-header to the packet * * @param udp_hdr location of the udp_hdr === modified file 'firewall/user_ipsec_esp.h' --- firewall/user_ipsec_esp.h 2010-02-17 17:38:08 +0000 +++ firewall/user_ipsec_esp.h 2010-03-19 09:53:35 +0000 @@ -24,6 +24,8 @@ #ifndef HIP_FIREWALL_USER_IPSEC_ESP_H #define HIP_FIREWALL_USER_IPSEC_ESP_H +#define _BSD_SOURCE + #include "user_ipsec_sadb.h" #include "firewall_defines.h" === modified file 'firewall/user_ipsec_fw_msg.c' --- firewall/user_ipsec_fw_msg.c 2010-02-17 17:38:08 +0000 +++ firewall/user_ipsec_fw_msg.c 2010-03-19 09:53:35 +0000 @@ -16,6 +16,7 @@ #include "esp_prot_fw_msg.h" #include "firewall.h" #include "lib/core/builder.h" +#include "lib/core/message.h" #define DEFAULT_LIFETIME 0 /* place holder as timeout not implemented yet */ === modified file 'firewall/user_ipsec_sadb.c' --- firewall/user_ipsec_sadb.c 2010-02-17 17:38:08 +0000 +++ firewall/user_ipsec_sadb.c 2010-03-19 09:53:35 +0000 @@ -17,12 +17,16 @@ #include <pthread.h> #include <openssl/sha.h> +#include <string.h> #include "user_ipsec_sadb.h" #include "esp_prot_api.h" #include "firewall.h" #include "lib/core/ife.h" -#include "lib/core/misc.h" +#include "lib/core/keylen.h" +#include "lib/core/debug.h" +#include "lib/core/state.h" +#include "lib/core/builder.h" /* hash functions used for calculating the entries' hashes * === modified file 'firewall/user_ipsec_sadb.h' --- firewall/user_ipsec_sadb.h 2010-02-17 17:38:08 +0000 +++ firewall/user_ipsec_sadb.h 2010-03-19 09:53:35 +0000 @@ -20,6 +20,7 @@ #ifndef ANDROID_CHANGES #include <openssl/blowfish.h> /* bf_key */ #endif +#include <sys/time.h> #include <pthread.h> #include <inttypes.h> #include "lib/core/hashchain.h" === modified file 'hipd/accessor.c' --- hipd/accessor.c 2010-03-19 09:20:44 +0000 +++ hipd/accessor.c 2010-03-19 09:53:35 +0000 @@ -12,18 +12,16 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "accessor.h" - +#include "hipd.h" unsigned int hipd_state = HIPD_STATE_CLOSED; #ifdef CONFIG_HIP_OPPORTUNISTIC unsigned int opportunistic_mode = 1; +extern int hip_use_opptcp; #endif // CONFIG_HIP_OPPORTUNISTIC - +extern int hip_use_hi3; /** * Set global daemon state. @@ -67,7 +65,7 @@ * * @return non-zero, if agent is alive. */ -int hip_agent_is_alive() +int hip_agent_is_alive(void) { #ifdef CONFIG_HIP_AGENT return hip_agent_status; @@ -78,6 +76,67 @@ #ifdef CONFIG_HIP_OPPORTUNISTIC /** + * Set opportunistic TCP status on or off + * + * @param msg a message with message type as SO_HIP_SET_OPPTCP_ON + * or SO_HIP_SET_OPPTCP_OFF + */ +void hip_set_opportunistic_tcp_status(struct hip_common *msg) +{ + struct sockaddr_in6 sock_addr; + int retry, type, n; + + type = hip_get_msg_type(msg); + + _HIP_DEBUG("type=%d\n", type); + + memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin6_family = AF_INET6; + sock_addr.sin6_port = htons(HIP_FIREWALL_PORT); + sock_addr.sin6_addr = in6addr_loopback; + + for (retry = 0; retry < 3; retry++) { + /* Switched from hip_sendto() to hip_sendto_user() due to + * namespace collision. Both message.h and user.c had functions + * hip_sendto(). Introducing a prototype hip_sendto() to user.h + * led to compiler errors --> user.c hip_sendto() renamed to + * hip_sendto_user(). + * + * Lesson learned: use function prototypes unless functions are + * ment only for local (inside the same file where defined) use. + * -Lauri 11.07.2008 */ + n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr); + if (n <= 0) { + HIP_ERROR("hipconf opptcp failed (round %d)\n", retry); + HIP_DEBUG("Sleeping few seconds to wait for fw\n"); + sleep(2); + } else { + HIP_DEBUG("hipconf opptcp ok (sent %d bytes)\n", n); + break; + } + } + + if (type == SO_HIP_SET_OPPTCP_ON) { + hip_use_opptcp = 1; + } else { + hip_use_opptcp = 0; + } + + HIP_DEBUG("Opportunistic tcp set %s\n", + (hip_use_opptcp ? "on" : "off")); +} + +/** + * query status for the opportunistic TCP extensions + * + * @return 1 if it is enabled or 0 otherwise + */ +int hip_get_opportunistic_tcp_status(void) +{ + return hip_use_opptcp; +} + +/** * Set opportunistic mode * * @param msg A message containing a HIP_PARAM_UINT parameter. @@ -144,6 +203,64 @@ out_err: return err; } +#endif /* CONFIG_HIP_OPPORTUNISTIC */ + +#ifdef CONFIG_HIP_I3 +/** + * turn hi3 support on or off + * + * @param msg a message with type SO_HIP_SET_HI3_ON or SO_HIP_SET_HI3_OFF + */ +void hip_set_hi3_status(struct hip_common *msg) +{ + struct sockaddr_in6 sock_addr; + int retry, type, n; + + type = hip_get_msg_type(msg); + + _HIP_DEBUG("type=%d\n", type); + + bzero(&sock_addr, sizeof(sock_addr)); + sock_addr.sin6_family = AF_INET6; + sock_addr.sin6_port = htons(HIP_FIREWALL_PORT); + sock_addr.sin6_addr = in6addr_loopback; + + for (retry = 0; retry < 3; retry++) { + n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr); + if (n <= 0) { + HIP_ERROR("hipconf hi3 failed (round %d)\n", retry); + HIP_DEBUG("Sleeping few seconds to wait for fw\n"); + sleep(2); + } else { + HIP_DEBUG("hipconf hi3 ok (sent %d bytes)\n", n); + break; + } + } + + if (type == SO_HIP_SET_HI3_ON) { + hip_i3_init(); + hip_use_hi3 = 1; + hip_locator_status = SO_HIP_SET_LOCATOR_ON; + } else { + hip_locator_status = SO_HIP_SET_LOCATOR_OFF; + hip_hi3_clean(); + hip_use_hi3 = 0; + } + + HIP_DEBUG("hi3 set %s\n", + (hip_use_hi3 ? "on" : "off")); +} + +/** + * query if Hi3 is enabled or not + * + * @return 1 if it is enabled or 0 otherwise + */ +int hip_get_hi3_status(void) +{ + return hip_use_hi3; +} +#endif /* CONFIG_HIP_I3 */ /** * Query if a pseudo HIT is stored in the host association @@ -186,8 +303,6 @@ return err; } -#endif // CONFIG_HIP_OPPORTUNISTIC - /** * Query status of client-side HIP proxy * === modified file 'hipd/accessor.h' --- hipd/accessor.h 2010-02-17 17:38:08 +0000 +++ hipd/accessor.h 2010-03-19 09:53:35 +0000 @@ -1,16 +1,13 @@ #ifndef HIP_HIPD_ACCESSOR_H #define HIP_HIPD_ACCESSOR_H -#include "hipd.h" /* @todo: header recursion: hipd.h calls accessor.h */ - -#include "lib/core/hashtable.h" - -#include <sys/time.h> - - #include <openssl/sha.h> #include <openssl/md5.h> #include <openssl/des.h> +#include <sys/time.h> + +#include "config.h" +#include "lib/core/hashtable.h" /** @addtogroup daemon_states * @{ @@ -35,14 +32,30 @@ #define INDEX_HASH_FN HIP_DIGEST_SHA1 +/** Specifies the NAT status of the daemon. This value indicates if the current + * machine is behind a NAT. Defined in hipd.c */ +extern int hipproxy; + +extern unsigned int opportunistic_mode; + unsigned int hipd_get_state(void); void hipd_set_state(unsigned int); int hipd_get_flag(unsigned int); void hipd_set_flag(unsigned int); int hip_agent_is_alive(void); + +#ifdef CONFIG_HIP_OPPORTUNISTIC +int hip_get_opportunistic_tcp_status(void); int hip_set_opportunistic_mode(struct hip_common *msg); int hip_query_opportunistic_mode(struct hip_common *msg); int hip_query_ip_hit_mapping(struct hip_common *msg); +#endif /* CONFIG_HIP_OPPORTUNISTIC */ + +#ifdef CONFIG_HIP_I3 +int hip_get_hi3_status(void); +void hip_set_hi3_status(struct hip_common *msg); +#endif /* CONFIG_HIP_I3 */ + int hip_get_hip_proxy_status(void); int hip_set_hip_proxy_on(void); int hip_set_hip_proxy_off(void); === modified file 'hipd/blind.c' --- hipd/blind.c 2010-03-19 09:24:10 +0000 +++ hipd/blind.c 2010-03-19 09:53:35 +0000 @@ -1,17 +1,29 @@ /** @file * This file defines tools of blind extension for the Host Identity Protocol + * See <a href="http://lib.tkk.fi/Diss/2008/isbn9789512295319/article6.pdf";>Ylitalo et al, BLIND: a Complete Identity Protection Framework for End-hosts, April 2004</a> and the corresponding IETF draft <a href="http://tools.ietf.org/html/draft-zhang-hip-privacy-protection";>Zhang et al, +An Extension of HIP Base Exchange to Support Identity Privacy, IETF draft, Work in Progress, March 2010</a>. * * @author Laura Takkinen - * @note Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. + * @note Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. */ /* required for s6_addr32 */ #define _BSD_SOURCE #include "blind.h" +#include "lib/core/hostid.h" static int hip_blind_fingerprints(hip_ha_t *entry); +/** + * test whether we should use blind or not based on an inbound packet + * + * @param msg a HIP control message + * @param entry related host association + * @param use_blind An output argument where the result will be written + * One if blind should be used or zero otherwise. + * @return zero on success or negative on error +o */ int hip_check_whether_to_use_blind(hip_common_t *msg, hip_ha_t *entry, int *use_blind) { /* Check for error conditions. */ @@ -47,7 +59,13 @@ } } -/* For internal use only */ +/** + * enable blind for a given host assocation + * + * @param entry a host association + * @param not_used not used + * @return zero + */ static int hip_set_blind_on_sa(hip_ha_t *entry, void *not_used) { int err = 0; @@ -59,7 +77,13 @@ return err; } -/* For internal use only */ +/** + * disable blind for a given host assocation + * + * @param entry a host association + * @param not_used not used + * @return zero + */ static int hip_set_blind_off_sa(hip_ha_t *entry, void *not_used) { int err = 0; @@ -71,9 +95,12 @@ return err; } -/* This functions is used to set the blind on. - * "blind" entry of all existing associations is set to 1 - * and hip_blind_status is set to 1. +/** + * Enable blind globally for all host associations + * + * @return zero + * @note this function has no effect if host association + * is in established state */ int hip_set_blind_on(void) { @@ -87,9 +114,12 @@ return err; } -/* This functions is used to set the blind off. - * "blind" entry of all existing associations is set to 0 - * and hip_blind_status is set to 0. +/** + * Disable blind globally for all host associations + * + * @return zero + * @note this function has no effect if host association + * is in established state */ int hip_set_blind_off(void) { @@ -104,7 +134,7 @@ } /** - * @brief This functions is used to query if the blind is in use. + * This functions is used to query if the blind is in use. * * @return Zero if blind is off and 1 if blind is on. */ @@ -113,10 +143,12 @@ return hip_blind_status; } -/* Extracts the uint16_t type nonce from the message. - * @msg Message from where the nonce is extracted - * @msg_nonce The nonce that the message included - * Returns 0 in success, otherwise returns -1. +/** + * Extract uint16_t type blind nonce from HIP control message + * + * @param msg message the message from where the nonce is extracted + * @param msg_nonce the nonce will be written here + * @return zero on success or negative on error */ int hip_blind_get_nonce(struct hip_common *msg, uint16_t *msg_nonce) { @@ -132,12 +164,12 @@ } /** - * @brief Forms a plain HIT from a blinded one. + * Forms a plain HIT from a blinded one. * * @param nonce Nonce that is used to calculate the plain HIT. * @param blind_hit Blinded HIT from where the plain HIT is formed. * @param plain_hit Calculated plain HIT - * @return Zero in success, otherwise -1. + * @return zero on success or negative on error */ int hip_plain_fingerprint(uint16_t *nonce, struct in6_addr *blind_hit, struct in6_addr *plain_hit) @@ -152,12 +184,13 @@ return err; } -/* Forms the blinded HIT from the key (SHA1 hash from the key). - * For internal purposes. - * @key Key from where the hash is calculated - * @key_len Length of the key - * @blind_hit Calculated blind HIT (hash) - * Returns 0 in success, otherwise returns -1. +/** + * Form the blinded HIT from the key (SHA1 hash from the key). + * + * @param key Key from where the hash is calculated + * @param key_len Length of the key + * @param blind_hit Calculated blind HIT (hash) + * @return zero on success or negative on error */ int hip_do_blind(char *key, unsigned int key_len, struct in6_addr *blind_hit) { @@ -185,10 +218,11 @@ return err; } -/* Sets nonce and calculates the blinded - * fingerprints for the hip_ha_t entry. - * @entry hip_ha_t entry which blind fields are adjusted - * Returns 0 in success, otherwise returns -1. +/** + * Sets nonce and calculates the blinded fingerprints for the hip_ha_t entry. + * + * @param entry hip_ha_t entry which blind fields are adjusted + * @return zero on success or negative on error */ static int hip_blind_fingerprints(hip_ha_t *entry) { @@ -223,7 +257,15 @@ return err; } -/* Tests if @plain_hit blinded with nonce is same as @blind_hit*/ +/** + * Tests if plain_hit blinded with nonce is same as @blind_hit + * + * @param nonce the nonce used for blinding the hit + * @param plain_hit the plain HIT to be tested + * @param blind_hit the blinded HIT + * + * @return zero on success or negative on error + */ int hip_blind_verify(uint16_t *nonce, struct in6_addr *plain_hit, struct in6_addr *blind_hit) { @@ -268,7 +310,12 @@ } return ret == 0; } - +/** + * build a blinded i1 message + * + * @param entry the related host association + * @param mask a mask template for I1 packet without blind + */ struct hip_common *hip_blind_build_i1(hip_ha_t *entry, uint16_t *mask) { struct hip_common *i1; @@ -306,7 +353,16 @@ return i1; } -/* Fills the r2 message with required blind parameters*/ +/** + * Fill in the r2 message with required blind parameters + * + * @param i2 the receive I2 message + * @param r2 message to be sent + * @param entry the related host association + * @param the default control flags mask template + * + * @return zero on success or negative on error + */ int hip_blind_build_r2(struct hip_common *i2, struct hip_common *r2, hip_ha_t *entry, uint16_t *mask) { int err = 0, host_id_in_enc_len = 0; @@ -385,6 +441,14 @@ return err; } +/** + * verify a blinded R2 message + * + * @param r2 the R2 control message + * @param entry the related host association + * + * @return zero if the message was ok or negative otherwise + */ int hip_blind_verify_r2(struct hip_common *r2, hip_ha_t *entry) { int err = 0; @@ -475,7 +539,7 @@ } /** - * Constructs a new R1 packet payload. + * Constructs a new blinde R1 packet payload * * @param src_hit a pointer to the source host identity tag used in the * packet. @@ -659,6 +723,16 @@ return NULL; } +/** + * recreate a blind spool of R1 messages + * + * @param r1table the R1 table to fill + * @param hit the local HIT + * @param sign the signature function pointer + * @param privkey the private key for signing + * @param pubkey the corresponding public key + * @return zero on success or negative on error + */ int hip_blind_precreate_r1(struct hip_r1entry *r1table, struct in6_addr *hit, int (*sign)(void *key, struct hip_common *m), void *privkey, struct hip_host_id *pubkey) === modified file 'hipd/bos.c' --- hipd/bos.c 2010-02-17 17:38:08 +0000 +++ hipd/bos.c 2010-03-19 09:53:35 +0000 @@ -1,7 +1,25 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * BOS packet was defined in + * <a href="http://tools.ietf.org/html/draft-ietf-hip-base-00";>draft-ietf-hip-base-00 + * </a> but it was removed in later revisions. It can be used to broadcast your + * own identity (and IP address) to the local network. Privacy proponents beware! + * + * @brief BOS packet sending and receiving functionality + * + * @author Anthony D. Joseph + * + */ + /* required for s6_addr32 */ #define _BSD_SOURCE #include "bos.h" +#include "lib/core/hostid.h" +#include "lib/core/hip_udp.h" /** * hip_create_signature - Calculate SHA1 hash over the data and sign it. @@ -33,7 +51,8 @@ return err; } -/** hip_socket_send_bos - send a BOS packet +/** + * hip_socket_send_bos - send a BOS packet * @param msg input message (should be empty) * * Generate a signed HIP BOS packet containing our HIT, and send === modified file 'hipd/bos.h' --- hipd/bos.h 2010-02-17 17:38:08 +0000 +++ hipd/bos.h 2010-03-19 09:53:35 +0000 @@ -13,9 +13,6 @@ #include "lib/core/state.h" int hip_send_bos(const struct hip_common *msg); -int hip_verify_packet_signature(struct hip_common *bos, - struct hip_host_id *peer_host_id); - int hip_handle_bos(struct hip_common *bos, struct in6_addr *bos_saddr, struct in6_addr *bos_daddr, === modified file 'hipd/cert.h' --- hipd/cert.h 2010-02-17 17:38:08 +0000 +++ hipd/cert.h 2010-03-19 09:53:35 +0000 @@ -23,13 +23,10 @@ #include <openssl/err.h> #include <openssl/pem.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/debug.h" #include "lib/core/ife.h" -#include "lib/core/misc.h" + #include "hidb.h" #include "lib/core/hashtable.h" === modified file 'hipd/close.c' --- hipd/close.c 2010-02-17 17:38:08 +0000 +++ hipd/close.c 2010-03-19 09:53:35 +0000 @@ -1,19 +1,30 @@ -/* TODO: Doxygen documentation incomplete. Please fix -**/ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Processing for CLOSE control packets + * + * @author Miika Komu <miika@xxxxxx> + */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "close.h" #ifdef CONFIG_HIP_PERFORMANCE #include "lib/performance/performance.h" #endif - - +#include "lib/core/hip_udp.h" + +/** + * send a HIP close packet to a peer + * + * @param entry the host association with the peer + * @param opaque a nonce to be included in the CLOSE + * @return zero on success or negative on error + */ static int hip_xmit_close(hip_ha_t *entry, void *opaque) { #ifdef CONFIG_HIP_PERFORMANCE @@ -109,6 +120,13 @@ return err; } +/** + * a wrapper to send a close message to a peer + * + * @param msg a message containing a peer HIT to which to send close + * @param delete_ha_info a nonce parameter for the CLOSE message + * @return zero on success or negative on error + */ int hip_send_close(struct hip_common *msg, int delete_ha_info) { @@ -174,6 +192,13 @@ return err; } +/** + * process a CLOSE message + * + * @param close the CLOSE message process + * @param entry the corresponding host association + * @return zero on success or negative on error + */ int hip_handle_close(struct hip_common *close, hip_ha_t *entry) { #ifdef CONFIG_HIP_PERFORMANCE @@ -264,6 +289,13 @@ return err; } +/** + * preprocess a CLOSE message + * + * @param close the CLOSE message preprocess + * @param entry the corresponding host association + * @return zero on success or negative on error + */ int hip_receive_close(struct hip_common *close, hip_ha_t *entry) { @@ -310,6 +342,13 @@ return err; } +/** + * process a CLOSE ACK message + * + * @param close_ack the CLOSE ACK message process + * @param entry the corresponding host association + * @return zero on success or negative on error + */ int hip_handle_close_ack(struct hip_common *close_ack, hip_ha_t *entry) { #ifdef CONFIG_HIP_PERFORMANCE @@ -373,6 +412,13 @@ return err; } +/** + * preprocess a CLOSE ACK message + * + * @param close the CLOSE ACK message process + * @param entry the corresponding host association + * @return zero on success or negative on error + */ int hip_receive_close_ack(struct hip_common *close_ack, hip_ha_t *entry) { @@ -418,6 +464,13 @@ return err; } +/** + * tear down a host association after close procedure + * + * @param ha the corresponding host association + * @param notused not used + * @return zero on success or negative on error + */ int hip_purge_closing_ha(hip_ha_t *ha, void *notused) { int err = 0; === modified file 'hipd/close.h' --- hipd/close.h 2010-02-17 17:38:08 +0000 +++ hipd/close.h 2010-03-19 09:53:35 +0000 @@ -2,7 +2,7 @@ #define HIP_HIPD_CLOSE_H #include "hadb.h" -#include "lib/core/misc.h" + #include "hidb.h" #include "lib/core/builder.h" #include "cookie.h" @@ -10,7 +10,7 @@ #include "lib/core/debug.h" #include "keymat.h" #include "lib/core/crypto.h" -#include "lib/core/misc.h" + #include "lib/tool/pk.h" int hip_send_close(struct hip_common *msg, int delete_ha_info); === modified file 'hipd/configfilereader.c' --- hipd/configfilereader.c 2010-02-17 17:38:08 +0000 +++ hipd/configfilereader.c 2010-03-19 09:53:35 +0000 @@ -10,6 +10,7 @@ #define _BSD_SOURCE #include "configfilereader.h" +#include "lib/core/debug.h" /** Error value for generic config file error. (Everything but -EIO and EOF are * acceptable here.) */ === modified file 'hipd/configfilereader.h' --- hipd/configfilereader.h 2010-02-17 17:38:08 +0000 +++ hipd/configfilereader.h 2010-03-19 09:53:35 +0000 @@ -63,7 +63,7 @@ #include <string.h> #include <ctype.h> #include <errno.h> -#include "lib/core/misc.h" /* For debuging macros. */ + /* For debuging macros. */ /** Maximum number of characters per line in HIP relay config file. */ #define HIP_RELAY_MAX_LINE_LEN 2048 === modified file 'hipd/cookie.c' --- hipd/cookie.c 2010-03-19 09:24:10 +0000 +++ hipd/cookie.c 2010-03-19 09:53:35 +0000 @@ -1,29 +1,34 @@ /** * @file - * HIP cookie handling. Licence: GNU/GPL + * HIP cookie handling + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> * * @author Kristian Slavov <ksl#iki.fi> * @author Miika Komu <miika#iki.fi> * - * TODO: Doxygen documentation incomplete. Please fix this. - * */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "cookie.h" +#include "lib/core/solve.h" #define HIP_PUZZLE_MAX_LIFETIME 60 /* in seconds */ #define HIP_DEFAULT_COOKIE_K 1ULL /* a difficulty of i leads to approx. 2^(i-1) hash computations during BEX */ int hip_cookie_difficulty = HIP_DEFAULT_COOKIE_K; -//get the puzzle difficulty and return result to hipconf +/** + * get the puzzle difficulty and return result (for hipconf) + * + * @param msg A message containing a HIT for which to query for + * the difficulty. The difficulty will be written + * into the message as a HIP_PARAM_INT parameter. + * @return zero on success and negative on error + */ int hip_get_puzzle_difficulty_msg(struct hip_common *msg) { int err = 0, diff = 0; @@ -31,18 +36,10 @@ hip_hit_t all_zero_hit; bzero(&all_zero_hit, sizeof(all_zero_hit)); - //obtain the hit + /* obtain the hit */ dst_hit = hip_get_param_contents(msg, HIP_PARAM_HIT); -#ifdef CONFIG_HIP_COOKIE - if (ipv6_addr_cmp(&all_zero_hit, dst_hit) != 0) { - diff = hip_get_cookie_difficulty(dst_hit); - } else { -#endif diff = hip_get_cookie_difficulty(NULL); -#ifdef CONFIG_HIP_COOKIE -} -#endif _HIP_DEBUG("Puzzle difficulty is %d\n", diff); hip_build_param_contents(msg, &diff, HIP_PARAM_INT, sizeof(diff)); @@ -51,47 +48,50 @@ } -/* TODO: This function has no error handling at all! Check if this is right-*/ -//set the puzzle difficulty acc to msg sent by hipconf +/** + * set the puzzle difficulty according to the msg sent by hipconf + * + * @param msg An input/output message. Should contain the target + * HIT and the required puzzle difficulty. + * @return zero on success and negative on error + */ int hip_set_puzzle_difficulty_msg(struct hip_common *msg) { - int err = 0, *newVal = NULL; + int err = 0, *newVal = NULL; hip_hit_t *dst_hit = NULL; hip_hit_t all_zero_hit; bzero(&all_zero_hit, sizeof(all_zero_hit)); - dst_hit = hip_get_param_contents(msg, HIP_PARAM_HIT); - newVal = hip_get_param_contents(msg, HIP_PARAM_INT); - -#ifdef CONFIG_HIP_COOKIE - if (ipv6_addr_cmp(&all_zero_hit, dst_hit) != 0) { - hip_set_cookie_difficulty(dst_hit, *newVal); - } else { -#endif - hip_set_cookie_difficulty(NULL, *newVal); -#ifdef CONFIG_HIP_COOKIE -} - -#endif + HIP_IFEL(!(dst_hit = hip_get_param_contents(msg, HIP_PARAM_HIT)), + -1, "No HIT set\n"); + HIP_IFEL(!(newVal = hip_get_param_contents(msg, HIP_PARAM_INT)), + -1, "No difficulty set\n"); + + HIP_IFEL(hip_set_cookie_difficulty(NULL, *newVal), -1, + "Setting difficulty failed\n"); + out_err: return err; } -#ifndef CONFIG_HIP_ICOOKIE /* see also spam.c for overriding functions */ - -#if 0 -void hip_init_puzzle_defaults() -{ - return; -} - -#endif - +/** + * query for current puzzle difficulty + * + * @param not_used not used + * @return the puzzle difficulty + */ int hip_get_cookie_difficulty(hip_hit_t *not_used) { /* Note: we could return a higher value if we detect DoS */ return hip_cookie_difficulty; } +/** + * set puzzle difficulty + * + * @param not_used not used + * @param k the new puzzle difficulty + * @return the k value on success or negative on error + */ int hip_set_cookie_difficulty(hip_hit_t *not_used, int k) { if (k > HIP_PUZZLE_MAX_K || k < 1) { @@ -104,12 +104,24 @@ return k; } +/** + * increase cookie difficulty by one + * + * @param not_used not used + * @return the new cookie difficulty + */ int hip_inc_cookie_difficulty(hip_hit_t *not_used) { int k = hip_get_cookie_difficulty(NULL) + 1; return hip_set_cookie_difficulty(NULL, k); } +/** + * decrease cookie difficulty by one + * + * @param not_used not used + * @return the new cookie difficulty + */ int hip_dec_cookie_difficulty(hip_hit_t *not_used) { int k = hip_get_cookie_difficulty(NULL) - 1; @@ -117,7 +129,8 @@ } /** - * hip_calc_cookie_idx - get an index + * calculate the index of a cookie + * * @param ip_i Initiator's IPv6 address * @param ip_r Responder's IPv6 address * @param hit_i Initiators HIT @@ -144,14 +157,13 @@ return (base) % HIP_R1TABLESIZE; } -#endif /* !CONFIG_HIP_ICOOKIE */ - /** - * hip_fetch_cookie_entry - Get a copy of R1entry structure + * get a copy of R1entry structure + * * @param ip_i Initiator's IPv6 * @param ip_r Responder's IPv6 * - * Comments for the if 0 code are inlined below. + * @note Comments for the if 0 code are inlined below. * * Returns NULL if error. */ @@ -233,6 +245,11 @@ return err; } +/** + * initialize an R1 entry structure + * + * @return The allocated R1 entry structure. Caller deallocates. + */ struct hip_r1entry *hip_init_r1(void) { struct hip_r1entry *err; @@ -245,9 +262,15 @@ return err; } -#ifndef CONFIG_HIP_ICOOKIE -/* - * @sign the signing function to use +/** + * precreate an R1 packet + * + * @param r1table a pointer to R1 table structure + * @param hit the local HIT + * @param sign a signing callback function + * @param privkey the private key to use for signing + * @param pubkey the host id (public key) + * @return zero on success and non-zero on error */ int hip_precreate_r1(struct hip_r1entry *r1table, struct in6_addr *hit, int (*sign)(void *key, struct hip_common *m), @@ -275,8 +298,11 @@ return 0; } -#endif /* !CONFIG_HIP_ICOOKIE */ - +/** + * uninitialize R1 table + * + * @param hip_r1table R1 table + */ void hip_uninit_r1(struct hip_r1entry *hip_r1table) { int i; @@ -407,6 +433,13 @@ return err; } +/** + * recreate R1 packets corresponding to one HI + * + * @param entry the host id entry + * @param new_hash unused + * @return zero on success or negative on error + */ static int hip_recreate_r1s_for_entry_move(struct hip_host_id_entry *entry, void *new_hash) { @@ -432,6 +465,11 @@ return err; } +/** + * precreate all R1 packets + * + * @return zero on success or negative on error + */ int hip_recreate_all_precreated_r1_packets() { HIP_HASHTABLE *ht = hip_ht_init(hip_hidb_hash, hip_hidb_match); === modified file 'hipd/cookie.h' --- hipd/cookie.h 2010-02-17 17:38:08 +0000 +++ hipd/cookie.h 2010-03-19 09:53:35 +0000 @@ -16,7 +16,6 @@ }; #define HIP_R1TABLESIZE 3 /* precreate only this many R1s */ -#define HIP_PUZZLE_MAX_K 28 struct hip_common *hip_get_r1(struct in6_addr *ip_i, struct in6_addr *ip_r, struct in6_addr *src_hit, === modified file 'hipd/dh.c' --- hipd/dh.c 2010-03-19 09:24:10 +0000 +++ hipd/dh.c 2010-03-19 09:53:35 +0000 @@ -1,12 +1,13 @@ -/* - * HIPL security related functions - * - * Licence: GNU/GPL - * - * Authors: - * - Mika Kousa <mkousa@xxxxxx> - * - Kristian Slavov <ksl@xxxxxx> - * - Tobias Heer <heer@xxxxxxxxxx> +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Diffie-Hellman wrappers for HIP + * + * @author Mika Kousa <mkousa@xxxxxx> + * @author Kristian Slavov <ksl@xxxxxx> + * @author Tobias Heer <heer@xxxxxxxxxx> */ /* required for s6_addr32 */ @@ -19,7 +20,7 @@ static void hip_regen_dh_keys(uint32_t bitmask); /** - * hip_insert_dh - Insert the current DH-key into the buffer + * insert the current DH-key into the buffer * * If a DH-key does not exist, we will create one. * @return >0 if ok, -1 if errors @@ -62,9 +63,9 @@ } /** - * hip_calculate_shared_secret - Creates a shared secret based on the - * public key of the peer (passed as an argument) and own DH private key - * (created beforehand). + * create a shared secret based on the public key of the peer + * (passed as an argument) and own DH private key (created beforehand). + * * @param public_value Peer's Diffie-Hellman public key * @param group_id the Diffie-Hellman group ID * @param len the length of the public value @@ -113,10 +114,10 @@ } /** - * hip_regen_dh_keys - Regenerate Diffie-Hellman keys for HIP + * regenerate Diffie-Hellman keys for HIP * @param bitmask Mask of groups to generate. * - * Use only this function to generate DH keys. + * @note Use only this function to generate DH keys. */ static void hip_regen_dh_keys(uint32_t bitmask) { @@ -149,6 +150,9 @@ HIP_DEBUG("%d keys generated\n", cnt); } +/** + * uninitialize precreated DH structures + */ void hip_dh_uninit(void) { int i; @@ -160,6 +164,9 @@ } } +/** + * initialize D-H cipher structures + */ int hip_init_cipher(void) { uint32_t supported_groups; === modified file 'hipd/dht.c' --- hipd/dht.c 2010-02-17 17:38:08 +0000 +++ hipd/dht.c 2010-03-19 09:53:35 +0000 @@ -15,6 +15,8 @@ #include "dht.h" #include "hipd.h" +#include "lib/core/hostid.h" +#include "lib/core/hit.h" static void hip_publish_hit(char *, char *); static int hip_publish_addr(char *); @@ -35,10 +37,11 @@ * @param *socket socket to be initialized * @param *socket_status updates the status of the socket after every socket operation * - * @return void + * @return 0 on success negative otherwise */ -void hip_init_dht_sockets(int *socket, int *socket_status) +int hip_init_dht_sockets(int *socket, int *socket_status) { + int err = 0; if (hip_opendht_inuse == SO_HIP_DHT_ON) { if (*socket_status == STATE_OPENDHT_IDLE) { HIP_DEBUG("Connecting to the DHT with socket no: %d \n", *socket); @@ -46,18 +49,18 @@ *socket = init_dht_gateway_socket_gw(*socket, opendht_serving_gateway); } - opendht_error = 0; - opendht_error = connect_dht_gateway(*socket, - opendht_serving_gateway, 0); + err = connect_dht_gateway(*socket, + opendht_serving_gateway, 0); } - if (opendht_error == EINPROGRESS) { + if (err == EINPROGRESS) { *socket_status = STATE_OPENDHT_WAITING_CONNECT; /* connect not ready */ HIP_DEBUG("OpenDHT connect unfinished. Socket No: %d \n", *socket); - } else if (opendht_error > -1 && opendht_error != EINPROGRESS) { + } else if (err > -1 && err != EINPROGRESS) { *socket_status = STATE_OPENDHT_START_SEND; } } + return err; } /** === modified file 'hipd/dht.h' --- hipd/dht.h 2010-02-17 17:38:08 +0000 +++ hipd/dht.h 2010-03-19 09:53:35 +0000 @@ -18,7 +18,7 @@ #include "lib/dht/libhipdht.h" #include "lib/dht/libhipdhtxml.h" -void hip_init_dht_sockets(int *, int *); +int hip_init_dht_sockets(int *, int *); void hip_register_to_dht(void); int hip_publish_certificates(void); === modified file 'hipd/dhtqueue.c' --- hipd/dhtqueue.c 2010-02-17 17:38:08 +0000 +++ hipd/dhtqueue.c 2010-03-19 09:53:35 +0000 @@ -9,11 +9,13 @@ #define _BSD_SOURCE #include <stdlib.h> +#include "dhtqueue.h" +#include "hipd.h" #include "lib/core/hashtable.h" #include "lib/core/debug.h" - -#include "dhtqueue.h" -#include "lib/core/misc.h" +#include "lib/core/builder.h" + + struct hip_queue { void *data; === modified file 'hipd/esp_prot_anchordb.c' --- hipd/esp_prot_anchordb.c 2010-02-17 17:38:08 +0000 +++ hipd/esp_prot_anchordb.c 2010-03-19 09:53:35 +0000 @@ -1,7 +1,7 @@ /** * @file firewall/esp_prot_anchordb.c * - * <LICENSE TEMLPATE LINE - LEAVE THIS LINE INTACT> + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> * * This implementation stores anchor elements to be used as references to * the hash structures stored in the BEX store of the hipfw. The elements @@ -20,7 +20,8 @@ #include "lib/core/esp_prot_common.h" #include "lib/core/builder.h" #include "esp_prot_anchordb.h" - +#include "hipd.h" +#include "init.h" /* defines the structure storing the anchors */ typedef struct anchor_db { === modified file 'hipd/esp_prot_hipd_msg.c' --- hipd/esp_prot_hipd_msg.c 2010-02-17 17:38:08 +0000 +++ hipd/esp_prot_hipd_msg.c 2010-03-19 09:53:35 +0000 @@ -1,7 +1,7 @@ /** * @file firewall/esp_prot_hipd_msg.c * - * <LICENSE TEMLPATE LINE - LEAVE THIS LINE INTACT> + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> * * hipd messages to the hipfw and additional parameters for BEX and * UPDATE messages. @@ -20,6 +20,7 @@ #include "esp_prot_light_update.h" #include "lib/core/esp_prot_common.h" #include "lib/core/builder.h" +#include "lib/core/hip_udp.h" #include "hipd.h" /** === modified file 'hipd/esp_prot_light_update.c' --- hipd/esp_prot_light_update.c 2010-02-17 17:38:08 +0000 +++ hipd/esp_prot_light_update.c 2010-03-19 09:53:35 +0000 @@ -1,7 +1,7 @@ /** * @file firewall/esp_prot_light_update.h * - * <LICENSE TEMLPATE LINE - LEAVE THIS LINE INTACT> + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> * * Provides messaging functionality required for HHL-based anchor * element updates. @@ -17,7 +17,9 @@ #include "esp_prot_light_update.h" #include "esp_prot_anchordb.h" +#include "hipd.h" #include "lib/core/builder.h" +#include "lib/core/hip_udp.h" /** * sends an ack for a received HHL-based update message === modified file 'hipd/hadb.c' --- hipd/hadb.c 2010-03-03 13:16:18 +0000 +++ hipd/hadb.c 2010-03-19 09:53:35 +0000 @@ -1,16 +1,55 @@ -// FIXME: whenever something that is replicated in beet db is -// modified, the modifications must be written there too. +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * Host Association Database (HADB) is the heart of the hipd and it + * contains state information about HIP connectivity with remote + * hosts. It shouldn't be confused with Host Identity Data Base (HIDB) + * which contains just the local host identities. The Host Association + * is an implementation-speficic synonym for HIP association (RFC + * terminology). + * + * HADB is a hash table. It is indexed by a local and remote HIT. For + * opportunistic connections, the remote HIT is actually a "pseudo + * HIT" at the Initiator side when sending I1. The pseudo HIT consists + * of a HIT prefix and a part of the IP address (to avoid demuxing + * problems with multiple simultaneous opportunistic connections at + * the Initiator side. The Initiator deletes the "pseudo HA" and + * creates a new one upon receiving the R1. At the Responder side, + * this pseudo trick is not needed because the Responder can just + * choose a real HIT when it receives the opportunistic I1. + * + * The hash table structure is located in lib/core/state.h and it is + * called hip_hadb_state. As the structure contains sensitive + * information (symmetric key material for IPsec), it should not be + * exposed outside of hipd (use hip_hadb_user_info_state instead). + * + * You can use HADB to store information about negotiated extensions, + * local or peer host capabilities, etc. Do not store there + * information that is needed to process a single HIP packet, but + * instead use the hip_context structure and pass in in function + * arguments. + * + * @brief Host Association Database (HADB) for HIP + * + * @author Miika Komu <miika@xxxxxx> + */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "hadb.h" #include "hipd.h" +#include "accessor.h" #include "lib/core/list.h" +#include "lib/core/hostsfiles.h" +#include "lib/core/hostid.h" +#include "lib/core/hip_udp.h" +#include "lib/core/solve.h" +#include "lib/core/keylen.h" +#include "lib/core/hostsfiles.h" #define HIP_HADB_SIZE 53 #define HIP_MAX_HAS 100 @@ -74,6 +113,14 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_HASH_FN(hip_ha, hip_ha_t) +/** + * a comparison function for the hash table algorithm to distinguish + * two HAs from each other + * + * @param ha1 a HA to compare for equality + * @param ha2 a HA to compare for equality + * @return zero if the HAs match or non-zero otherwise + */ static int hip_ha_cmp(const hip_ha_t *ha1, const hip_ha_t *ha2) { if (ha1 == NULL || &(ha1->hit_our) == NULL || &(ha1->hit_peer) == NULL || @@ -87,6 +134,12 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_COMP_FN(hip_ha, hip_ha_t) +/** + * build a digest of a peer address + * + * @param ptr a pointer to hip_peer_addr_list_item structure + * @return a digest of the address in the hip_peer_addr_list_item structure + */ static unsigned long hip_hash_peer_addr(const void *ptr) { struct in6_addr *addr = &((struct hip_peer_addr_list_item *) ptr)->address; @@ -97,39 +150,25 @@ return *((unsigned long *) (void *) hash); } +/** + * test if two peer addresses match + * + * @param ptr1 a pointer to a hip_peer_addr_list_item + * @param ptr2 a pointer to a hip_peer_addr_list_item + * @return zero if the addresses match or non-zero otherwise + */ static int hip_match_peer_addr(const void *ptr1, const void *ptr2) { return hip_hash_peer_addr(ptr1) != hip_hash_peer_addr(ptr2); } -/* - * Support for multiple inbound IPsec SAs: - * - * We need a separate hashtable containing elements HIT and SPI, which - * tells which HIT has the inbound SPI. When an ESP packet is received, - * we first get the SPI from it and perform a lookup on the HIT-SPI - * hashtable to get the mapping. Then we perform another lookup from - * the HIT hashtable using the HIT we got from the previous - * lookup. This way we get the HA belonging to the connection. - * - * hs = HIT-SPI (struct hip_hit_spi) - * - * (functions hip_ .. _hs) - */ - - -/* - * - * All the primitive functions up to this point are static, to force - * some information hiding. The construct functions can access these - * functions directly. - * - * - */ - - /* PRIMITIVES */ +/** + * assign local and peer LSI to the given host association + * + * @param entry the host association + */ void hip_hadb_set_lsi_pair(hip_ha_t *entry) { hip_lsi_t aux; @@ -148,7 +187,11 @@ /** * This function searches for a hip_ha_t entry from the hip_hadb_hit - * by a HIT pair (local,peer). + * by a HIT pair (local,peer) + * + * @param hit local HIT + * @param hit2 peer HIT + * @return the corresponding host association or NULL if not found */ hip_ha_t *hip_hadb_find_byhits(const hip_hit_t *hit, const hip_hit_t *hit2) { @@ -177,6 +220,10 @@ * to find a HADB entry that matches the current HI and * the given peer hit. First matching HADB entry is then returned. * + * @param hit the peer HIT + * @return the host association that matches the peer HIT or NULL if + * not found + * * @todo Find a better solution, see the text below: * This function is needed because we index the HADB now by * key values calculated from <peer_hit,local_hit> pairs. Unfortunately, in @@ -304,6 +351,19 @@ return st; } +/** + * display debug information on information in host association + * + * @param local_addr local address + * @param peer_addr peer address + * @param local_hit local HIT + * @param peer_hit peer HIT + * @param peer_lsi peer LSI + * @param peer_hostname peer host name + * @param local_nat_udp_port local UDP port + * @param peer_nat_udp_port peer UDP port + * + */ static void hip_print_debug_info(const struct in6_addr *local_addr, const struct in6_addr *peer_addr, const hip_hit_t *local_hit, @@ -344,17 +404,12 @@ /** * Practically called only by when adding a HIT-IP mapping before base exchange. * - * @param local_hit a pointer to... - * @param peer_hit a pointer to... - * @param local_addr a pointer to... - * @param peer_addr a pointer to... - * @param peer_lsi a pointer to... - * @return - * @todo Allow multiple mappings; base exchange should be initiated to allow - * of them in order to prevent local DoS. - * @todo Create a security policy for triggering base exchange. - * @todo Multiple identities support: alternative a) make generic HIT prefix - * based policy to work alternative b) add SP pair for all local HITs. + * @param local_hit local HIT + * @param peer_hit peer HIT + * @param local_addr local address + * @param peer_addr peer address + * @param peer_lsi optional peer LSI (automatically generated if NULL)x + * @return zero on success or negative on error */ int hip_hadb_add_peer_info_complete(const hip_hit_t *local_hit, const hip_hit_t *peer_hit, @@ -460,7 +515,9 @@ entry->is_loopback = 1; } +#ifdef CONFIG_HIP_OPPORTUNISTIC entry->hip_is_opptcp_on = hip_get_opportunistic_tcp_status(); +#endif /* CONFIG_HIP_OPPORTUNISTIC */ #ifdef CONFIG_HIP_I3 entry->hip_is_hi3_on = hip_get_hi3_status(); #endif @@ -488,11 +545,11 @@ } /** - * . + * a wrapper to create a host association * - * @param entry a pointer to... - * @param peer_map_void a pointer to... - * @return ... + * @param entry a pointer to a preallocated host association + * @param peer_map_void a pointer to hip_peer_map_info + * @return zero on success or negative on error */ static int hip_hadb_add_peer_info_wrapper(struct hip_host_id_entry *entry, void *peer_map_void) @@ -514,6 +571,15 @@ return err; } +/** + * create a host association + * + * @param peer_hit the HIT of the remote host + * @param peer_addr the address of the remote host + * @param peer_lsi an optional LSI for the remote host + * @param peer_hostname an optional host name for the remote host + * @return zero on success or negative on error + */ int hip_hadb_add_peer_info(hip_hit_t *peer_hit, struct in6_addr *peer_addr, hip_lsi_t *peer_lsi, const char *peer_hostname) { @@ -563,6 +629,13 @@ return err; } +/** + * create a host association based on the parameter in a user message + * + * @param input an user message containing a HIT, optional LSI and hostname for + * the remote host + * @return zero on success or negative on error + */ int hip_add_peer_map(const struct hip_common *input) { struct in6_addr *hit = NULL, *ip = NULL; @@ -613,7 +686,7 @@ } /** - * Sets function pointer set for an hadb record. Pointer values will not be + * set "misc" function pointer set for an hadb record. Pointer values will not be * copied! * * @param entry pointer to the hadb record. @@ -631,6 +704,14 @@ return -1; } +/** + * change the network delivery function pointer set of a host association + * + * @param entry the host association + * @param new_func_set the new function pointer set + * @return zero on success and negative on error + * + */ int hip_hadb_set_xmit_function_set(hip_ha_t *entry, hip_xmit_func_set_t *new_func_set) { @@ -641,6 +722,14 @@ return -1; } +/** + * change the input filter function pointer set of a host association + * + * @param entry the host association + * @param new_func_set the new function pointer set + * @return zero on success and negative on error + * + */ static int hip_hadb_set_input_filter_function_set(hip_ha_t *entry, hip_input_filter_func_set_t *new_func_set) { @@ -651,6 +740,14 @@ return -1; } +/** + * change the output handler function pointer set of a host association + * + * @param entry the host association + * @param new_func_set the new function pointer set + * @return zero on success and negative on error + * + */ static int hip_hadb_set_output_filter_function_set(hip_ha_t *entry, hip_output_filter_func_set_t *new_func_set) { @@ -738,7 +835,7 @@ } /** - * Allocates and initializes a new HA structure. + * Allocate and initialize a new HA structure. * * @param gfpmask a mask passed directly to HIP_MALLOC(). * @return NULL if memory allocation failed, otherwise the HA. @@ -762,8 +859,13 @@ /* END OF PRIMITIVE FUNCTIONS */ /** - * Selects the preferred address within the addresses of the given SPI. - * The selected address is copied to @c addr, it is is non-NULL. + * Select the preferred address within the addresses of the given SPI. + * The selected address is copied to @c addr, if it is non-NULL. + * + * @param entry the host association + * @param spi_out hip_spi_out_item a pointer to the structure containing outbound SPI information + * @param addr the resulting outbound address will be copied here if found + * @return zero on success and negative on error */ int hip_hadb_select_spi_addr(hip_ha_t *entry, struct hip_spi_out_item *spi_out, struct in6_addr *addr) { @@ -844,8 +946,7 @@ * @param lifetime address lifetime of the address * @param state address state * - * @return if @c new_addr already exists, 0 is returned. If address was - * added successfully 0 is returned, else < 0. + * @return zero on success and negative on error */ int hip_hadb_add_peer_addr(hip_ha_t *entry, const struct in6_addr *new_addr, uint32_t spi, uint32_t lifetime, int state, @@ -913,6 +1014,12 @@ return err; } +/** + * delete a host association + * + * @param ha the ha to deinitiliaze and deallocate + * @return zero on success and negative on error + */ int hip_del_peer_info_entry(hip_ha_t *ha) { #ifdef CONFIG_HIP_OPPORTUNISTIC @@ -942,7 +1049,12 @@ } /** - * Currently deletes the whole entry... + * Search and delete a host association based on HITs + * + * @param our_hit the local HIT + * @param peer_hit the remote HIT + * + * @return zero on success and negative on error */ int hip_del_peer_info(hip_hit_t *our_hit, hip_hit_t *peer_hit) { @@ -1022,12 +1134,12 @@ } /** - * . + * store a remote host identifier to a host association * - * @param entry ... - * @param msg for future purposes (KeyNote) - * @param peer ... - * @return ... + * @param entry the host association + * @param msg unused + * @param peer the remote host identifier + * @return zero on success and negative on error */ int hip_init_peer(hip_ha_t *entry, struct hip_common *msg, struct hip_host_id *peer) @@ -1071,9 +1183,7 @@ } /** - * Initializes a HIP association. - * - * Initializes a new allocated HIP association @c entry. + * Initializes a host association * * @param a pointer to a HIP association to be initialized. * @param a pointer to a HIT value that is to be bound with the HIP association @@ -1132,6 +1242,9 @@ /* ----------------- */ +/** + * initialize the host association database + */ void hip_init_hadb(void) { /** @todo Check for errors. */ @@ -1238,40 +1351,75 @@ } } +/** + * receive a pointer to the default network delivery function pointer + * set of a host association + * + * @return the default function pointer set + */ hip_xmit_func_set_t *hip_get_xmit_default_func_set(void) { return &default_xmit_func_set; } +/** + * receive a pointer to the default "misc" function pointer + * set of a host association + * + * @return the default function pointer set + */ hip_misc_func_set_t *hip_get_misc_default_func_set(void) { return &default_misc_func_set; } +/** + * receive a pointer to the default input filter function + * pointer set of a host association + * + * @return the default function pointer set + */ hip_input_filter_func_set_t *hip_get_input_filter_default_func_set(void) { return &default_input_filter_func_set; } +/** + * receive a pointer to the default output filter function pointer + * set of a host association + * + * @return the default function pointer set + */ hip_output_filter_func_set_t *hip_get_output_filter_default_func_set(void) { return &default_output_filter_func_set; } +/** + * receive a pointer to the default preprocessing function pointer + * set of a host association + * + * @return the default function pointer set + */ hip_rcv_func_set_t *hip_get_rcv_default_func_set(void) { return &default_rcv_func_set; } +/** + * receive a pointer to the default postprocessing function pointer + * set of a host association + * + * @param entry the host association + * @param new_func_set the new function pointer set + * @return zero on success and negative on error + * + */ hip_handle_func_set_t *hip_get_handle_default_func_set(void) { return &default_handle_func_set; } -/*hip_update_func_set_t *hip_get_update_default_func_set() { - * return &default_update_func_set; - * }*/ - /** * Sets function pointer set for an hadb record. Pointer values will not be * copied! @@ -1330,15 +1478,15 @@ return -1; } -/* NOTE! When modifying this function, remember that some control values may - * not be allowed to co-exist. Therefore the logical OR might not be enough - * for all controls. */ /** * Switches on a local control bit for a host assosiation entry. * * @param entry a pointer to a host assosiation. * @param mask a bit mask representing the control value. * @note mask is a single mask, not a logical AND or OR mask. + * @note When modifying this function, remember that some control values may + * not be allowed to co-exist. Therefore the logical OR might not be enough + * for all controls. */ void hip_hadb_set_local_controls(hip_ha_t *entry, hip_controls_t mask) { @@ -1366,15 +1514,15 @@ } } -/* NOTE! When modifying this function, remember that some control values may - * not be allowed to co-exist. Therefore the logical OR might not be enough - * for all controls. */ /** * Switches on a peer control bit for a host assosiation entry. * * @param entry a pointer to a host assosiation. * @param mask a bit mask representing the control value. * @note mask is a single mask, not a logical AND or OR mask + * @note When modifying this function, remember that some control values may + * not be allowed to co-exist. Therefore the logical OR might not be enough + * for all controls. */ void hip_hadb_set_peer_controls(hip_ha_t *entry, hip_controls_t mask) { @@ -1397,12 +1545,6 @@ case HIP_HA_CTRL_PEER_REFUSED_RVS: case HIP_HA_CTRL_PEER_REFUSED_SAVAH: case HIP_HA_CTRL_PEER_REFUSED_FULLRELAY: -#if 0 - if (mask == HIP_HA_CTRL_PEER_GRANTED_RELAY) { - hip_nat_set_control(entry, 1); - HIP_DEBUG("nat control has been reset to 1\n"); - } -#endif entry->peer_controls |= mask; break; default: @@ -1444,26 +1586,23 @@ hadb_hit = NULL; } +/** + * flush all security policies + * + * @todo currently this function is a no-op + */ void hip_delete_all_sp() { - //struct hip_hit_spi *hs, *tmp_hs; HIP_DEBUG("\n"); HIP_DEBUG("DEBUG: DUMP SPI LISTS\n"); - /* I think this is not very safe deallocation. - * Locking the hadb_spi and hadb_hit could be one option, but I'm not - * very sure that it will work, as they are locked later in - * hip_hadb_remove_state() for a while. - * - * The list traversing is not safe in smp way :( - */ HIP_DEBUG("DELETING HA HT\n"); } /** - * Removes all the addresses from the addresses_to_send_echo_request list - * and deallocates them. + * Remove all the addresses from the addresses_to_send_echo_request list + * and deallocate them. * @param ha pointer to a host association */ void hip_remove_addresses_to_send_echo_request(hip_ha_t *ha) @@ -1480,8 +1619,8 @@ } /** - * Deletes a HA state (and deallocate memory) Deletes all associates IPSEC SAs - * and frees the memory occupied by the HA state. + * Delete a HA state (and deallocate memory), all associated IPSEC SAs + * and free the memory occupied by the HA state. * * @param ha HA * @note ASSERT: The HA must be unlinked from the global hadb hash tables @@ -1557,7 +1696,7 @@ } /** - * Maps function @c func to every HA in HIT hash table. The hash table is + * Map function @c func to every HA in HIT hash table. The hash table is * LOCKED while we process all the entries. This means that the mapper function * MUST be very short and _NOT_ do any operations that might sleep! * @@ -1597,7 +1736,13 @@ return fail; } -/** Enumeration for hip_count_open_connections */ +/** + * Enumeration for hip_count_open_connections + * + * @param entry a host association + * @param cntr a counter used for counting open host associations + * @return zero + */ static int hip_count_one_entry(hip_ha_t *entry, void *cntr) { int *counter = cntr; @@ -1609,7 +1754,9 @@ } /** - * Return number of open connections by calculating hadb entrys. + * Return number of open host associations by calculating hadb entrys. + * + * @return the number of open host associations */ int hip_count_open_connections(void) { @@ -1620,6 +1767,14 @@ return n; } +/** + * an enumerator to find information on host associations + * + * @param entry the host association + * @param opaq a preallocated HIP message where information on the given + * host association will be written + * @return zero on success and negative on error + */ int hip_handle_get_ha_info(hip_ha_t *entry, void *opaq) { int err = 0; @@ -1656,8 +1811,6 @@ // HIP_ASSERT(duration != NULL); // memcpy(&hid.bex_duration, duration, sizeof(struct timeval)); - - _HIP_HEXDUMP("HEXHID ", &hid, sizeof(struct hip_hadb_user_info_state)); hid.nat_udp_port_peer = entry->peer_udp_port; @@ -1685,7 +1838,14 @@ } /** + * an iterator to map an IP address to a HIT + * + * @param entry the host association to check for match + * @param id2 a HIT of a remote host + * @return -1 on match or zero otherwise + * * @todo We could scan through all of the alternative locators as well + * @todo this fails in NATted environments */ int hip_hadb_map_ip_to_hit(hip_ha_t *entry, void *id2) { @@ -1722,7 +1882,6 @@ * @return a pointer to a matching host association or NULL if * a matching host association was not found. * @author Miika Komu - * @date 31.08.2006 */ hip_ha_t *hip_hadb_find_rvs_candidate_entry(hip_hit_t *local_hit, hip_hit_t *rvs_ip) @@ -1754,7 +1913,12 @@ #ifdef CONFIG_HIP_BLIND /** - * Defunct + * Defunctional. Find a host association based on blinded HITs + * + * @param local_blind_hit local blinded HIT + * @param peer_blind_hit remote blinded HIT + * @return the corresponding host association or NULL if not found + * * @date 22.07.2008 */ hip_ha_t *hip_hadb_find_by_blind_hits(hip_hit_t *local_blind_hit, @@ -1798,23 +1962,15 @@ #endif -static int hip_host_file_info_exists_lsi(hip_lsi_t *lsi) -{ - uint8_t hostname[HOST_NAME_MAX]; - struct in6_addr mapped_lsi; - - memset(hostname, 0, sizeof(hostname)); - - IPV4_TO_IPV6_MAP(lsi, &mapped_lsi); - - return !(hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, - hip_map_first_id_to_hostname_from_hosts, - &mapped_lsi, hostname) && - hip_for_each_hosts_file_line(HOSTS_FILE, - hip_map_first_id_to_hostname_from_hosts, - &mapped_lsi, hostname)); -} - + +/** + * An iterator to find a matching remote LSI from HADB. + * + * @param entry the host association + * @param lsi The LSI to match. Set to zero if a match was found. + * @return zero + * @note this function overwrites @c lsi, beware! + */ static int hip_hadb_find_lsi(hip_ha_t *entry, void *lsi) { int exist_lsi; @@ -1825,6 +1981,12 @@ return 0; } +/** + * check if a remote LSI exists in the HADB + * + * @param lsi the LSI to check + * @return one if it exists or zero otherwise + */ static int hip_hadb_exists_lsi(hip_lsi_t *lsi) { int res = 0; @@ -1840,19 +2002,32 @@ return res; } -static int lsi_assigned(struct in_addr add) +/** + * check if a remote LSI has been already assigned from + * HADB and hosts files + * + * @param addr the LSI to check + * @return one if the LSI exists or zero otherwise + */ +static int lsi_assigned(struct in_addr addr) { int exist = 0; - exist = hip_hidb_exists_lsi(&add); + exist = hip_hidb_exists_lsi(&addr); if (!exist) { - exist = hip_hadb_exists_lsi(&add); + exist = hip_hadb_exists_lsi(&addr); } if (!exist) { - exist = hip_host_file_info_exists_lsi(&add); + exist = hip_host_file_info_exists_lsi(&addr); } return exist; } +/** + * allocate a free remote LSI + * + * @param lsi the LSI will be written here + * @return zero + */ int hip_generate_peer_lsi(hip_lsi_t *lsi) { struct in_addr lsi_prefix; @@ -1874,11 +2049,14 @@ * This function simply goes through all HADB to find an entry that * matches the given lsi pair. First matching HADB entry is then returned. * + * @param lsi_src the source LSI + * @param lsi_dst the destination LSI + * @return the host association corresponding to the LSIs + * * @note This way of finding HA entries doesn't work properly if we have * multiple entries with the same tuple <lsi_src,lsi_dst>. Currently, that's not the case. * Our implementation doesn't allow repeated lsi tuples. */ - hip_ha_t *hip_hadb_try_to_find_by_pair_lsi(hip_lsi_t *lsi_src, hip_lsi_t *lsi_dst) { hip_list_t *item, *aux; @@ -1899,6 +2077,12 @@ return NULL; } +/** + * find a remote LSI from from the HADB + * + * @param lsi_dst the remote LSI + * @return the HADB entry or NULL if not found + */ hip_ha_t *hip_hadb_try_to_find_by_peer_lsi(hip_lsi_t *lsi_dst) { hip_list_t *item, *aux; @@ -1915,46 +2099,52 @@ return NULL; } +/** + * search for the local address used by the host association denoted + * by source and destination HITs in a user message + * + * @param msg a user message containing source and destination HITs + * @return zero on success and negative on error + */ int hip_get_local_addr(struct hip_common *msg) { hip_ha_t *entry; - int err; + int err = 0; struct in6_addr local_address; hip_hit_t *src_hit; hip_hit_t *dst_hit; - src_hit = (hip_hit_t *) hip_get_param_contents(msg, HIP_PARAM_HIT); - dst_hit = (hip_hit_t *) hip_get_param_contents(msg, HIP_PARAM_IPV6_ADDR); + HIP_IFEL(!(src_hit = (hip_hit_t *) hip_get_param_contents(msg, HIP_PARAM_HIT)), + -1, "No src HIT\n"); + /** @todo why is this a HIP_PARAM_IPV6_ADDR instead of HIP_PARAM_HIT ? */ + HIP_IFEL(!(dst_hit = (hip_hit_t *) hip_get_param_contents(msg, HIP_PARAM_IPV6_ADDR)), + -1, "No dst HIT\n"); HIP_DEBUG_HIT("src_hit from local address request: ", src_hit); HIP_DEBUG_HIT("dst_hit from local address request: ", dst_hit); -/*if (ptr) { - * memcpy(peer_hit, ptr, sizeof(hip_hit_t)); - * HIP_DEBUG_HIT("peer_hit", peer_hit); - *fallback = 0; - * } - */ + memset(&local_address, 0, sizeof(struct in6_addr)); - entry = hip_hadb_find_byhits(src_hit, dst_hit); + HIP_IFEL(!(entry = hip_hadb_find_byhits(src_hit, dst_hit)), + -1, "No HA\n"); hip_msg_init(msg); - //HIP_DEBUG_IN6ADDR(" local address: ", &entry->our_addr); - - if (!entry) { - HIP_DEBUG("Can't find local address because of no entry in hadb!\n"); - } ipv6_addr_copy(&local_address, &entry->our_addr); //hip_build_user_hdr(msg, HIP_HIPPROXY_LOCAL_ADDRESS, 0); - err = hip_build_param_contents(msg, &local_address, HIP_PARAM_IPV6_ADDR, - sizeof(struct in6_addr)); - if (err) { - HIP_ERROR("Building local address info failed\n"); - } - - return 0; + HIP_IFEL(hip_build_param_contents(msg, &local_address, HIP_PARAM_IPV6_ADDR, + sizeof(struct in6_addr)), -1, + "Building local address info failed\n"); + + out_err: + + return err; } +/** + * delete all security policies and associations related to the HA + * + * @param ha the host association + */ void hip_delete_security_associations_and_sp(struct hip_hadb_state *ha) { int prev_spi_out = ha->spi_outbound_current; @@ -1981,6 +2171,14 @@ return; }; +/** + * recreate the security policies and associations related to a HA + * + * @param ha the host association + * @param src_addr the new source address for the SAs + * @param dst_addr the new destination address for the SAs + * @return zero on success and negative on error + */ int hip_recreate_security_associations_and_sp(struct hip_hadb_state *ha, in6_addr_t *src_addr, in6_addr_t *dst_addr) { === modified file 'hipd/hadb.h' --- hipd/hadb.h 2010-03-19 09:24:10 +0000 +++ hipd/hadb.h 2010-03-19 09:53:35 +0000 @@ -1,18 +1,16 @@ #ifndef HIP_HIPD_HADB_H #define HIP_HIPD_HADB_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "keymat.h" #include "lib/tool/pk.h" #include "lib/core/debug.h" -#include "lib/core/misc.h" + #include "hidb.h" #include "lib/core/hashtable.h" #include "lib/core/state.h" #include "lib/core/builder.h" +#include "lib/core/straddr.h" #include "input.h" // required for declaration of receive functions #include "update.h" // required for declaration of update function #include "user_ipsec_sadb_api.h" === modified file 'hipd/hadb_legacy.c' --- hipd/hadb_legacy.c 2010-02-17 17:38:08 +0000 +++ hipd/hadb_legacy.c 2010-03-19 09:53:35 +0000 @@ -1,7 +1,14 @@ /** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * * This file contains legacy functions for mobility that should be rewritten for modularity. * They are still included in the code base due to locator dependencies with DHT and - * base exchange code. + * base exchange code. See bugzilla item 926 and 927. + * + * @author Baris Boyvat + * @author Miika Komu <miika@xxxxxx> */ /* required for s6_addr32 */ === modified file 'hipd/hi3.c' --- hipd/hi3.c 2010-02-17 17:38:08 +0000 +++ hipd/hi3.c 2010-03-19 09:53:35 +0000 @@ -1,3 +1,17 @@ +/** @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * HIP-based Internet Indirection Infrastructure (Hi3) code. This code + * can be used to relay HIP-based traffic over i3 infrastructure. + * See <a href="http://www.tml.tkk.fi/~pnr/publications/sncnw2004.pdf";> + * Nikander et al, Host Identity Indirection Infrastructure (Hi3), Nov 2004</a> + * or <a href="http://tools.ietf.org/html/draft-nikander-hiprg-hi3";> + * Nikander et al, Host Identity Indirection Infrastructure (Hi3), + * June 2004, expired Internet draft</a>. + * + * @author Andrey Lukyanenko + */ /* required for s6_addr32 */ #define _BSD_SOURCE @@ -20,9 +34,9 @@ /** * The callback for i3 "no matching id" callback. * - * @param ctx_data a pointer to... - * @param data a pointer to... - * @param fun_ctx a pointer to... + * @param ctx_data a pointer to hi3 ID + * @param data a pointer to additional data + * @param fun_ctx a pointer to function's context information (not used) * @todo tkoponen: should this somehow trigger the timeout for waiting * outbound traffic (state machine)? */ @@ -34,6 +48,12 @@ HIP_ERROR("Following ID not found: %s\n", id); } + +/** + * hi3 initializing function for hip (called from main module) + * + * @return 0 on success, terminates program on i3 error + */ int hip_i3_init() { if (cl_init(HIPL_HI3_FILE) != CL_RET_OK) { @@ -49,12 +69,19 @@ return 0; } +/** + * Adds trigger from defined hip_host_id_entry structure to the list of the available triggers hi3_pub_id + * + * @param entry a pointer to hip_host_id_entry structure + * @param count a pointer to the number of triggers in hi3_pub_id array + * @return 0 on success, negative on the trigger number exceeded + */ static int hip_hi3_add_pub_trigger_id(struct hip_host_id_entry *entry, void *count) { int i = *(int *) count; if (i > HI3_TRIGGER_MAX) { HIP_ERROR("Trigger number exceeded"); - return 0; + return -1; } bzero(&hi3_pub_id[i], ID_LEN); @@ -66,6 +93,10 @@ /** * This is the i3 callback to process received data. + * + * @param t a pointer to cl_trigger (not used right now) + * @param data a pointer to data received (including padding in the start and end, headers, payload). + * @param fun_ctx a pointer to function's context information (not used) */ static void hip_hi3_receive_payload(void *t, void *data, void *fun_ctx) { @@ -120,8 +151,12 @@ ; } -/* - * i3 callbacks for trigger management +/** + * i3 callbacks for trigger management (information output) + * + * @param t a pointer to cl_trigger struct + * @param data a pointer to additional data + * @param fun_ctx a pointer to function's context */ static void hip_hi3_constraint_failed(void *t, void *data, void *fun_ctx) { @@ -129,6 +164,13 @@ HIP_ERROR("Trigger constraint failed\n"); } +/** + * i3 callbacks for trigger insertion success + * + * @param t a pointer to cl_trigger struct + * @param data a pointer to additional data + * @param fun_ctx a pointer to function's context + */ static void hip_hi3_trigger_inserted(void *t, void *data, void *fun_ctx) { char id[100]; @@ -136,9 +178,17 @@ sprintf_i3_id(id, &type->t->id); + // it should not be error -> info? HIP_ERROR("Trigger inserted: %s\n", id); } +/** + * i3 callbacks for trigger insert failure + * + * @param t a pointer to cl_trigger struct + * @param data a pointer to additional data + * @param fun_ctx a pointer to function's context + */ static void hip_hi3_trigger_failure(void *t, void *data, void *fun_ctx) { cl_trigger *type = (cl_trigger *) t; @@ -150,6 +200,12 @@ cl_insert_trigger(type, 0); } +/** + * The function to insert hi3 specific triggers into i3 network. It defines all callback functions for every new trigger. + * All triggers IDs are selected from array hi3_pri_id and hi3_pub_id. + * + * @return 0 always + */ static int hip_hi3_insert_trigger(void) { Key key[HI3_TRIGGER_MAX]; @@ -204,6 +260,12 @@ return 0; } +/** + * The function cleans the triggers before exit. It destroys all triggers inserted into i3 network + * and cleans i3 context information through cl_exit() + * + * @return 0 always + */ int hip_hi3_clean() { int i = 0; @@ -218,6 +280,21 @@ return 0; } +/** + * The function makes sure that "right" locators are inserted into HIP i2 packet, because + * the hi3 packets goes indirectly through i3 network, both initiator and reponder do not know + * about any locators of the other station (use IPv4 or IPv6?). This function ensures that the + * IPs are used in the right order (priority to IPv6) and that they are used correctly (without + * it HIP assumes that IP addresses already exist on previous stages I1, R1, and it puts address + * from database which are zeros). + * + * @param locator a pointer to hip_locator struct (null if I2 packet missed the field). + * @param i2_info a poinjter to info field of I2 packet + * @param i2_saddr a pointer to I2 source address + * @param i2_daddr a pointer to I2 destination address + * + * @return 0 always + */ int hip_do_i3_stuff_for_i2(struct hip_locator *locator, hip_portpair_t *i2_info, in6_addr_t *i2_saddr, in6_addr_t *i2_daddr) { === modified file 'hipd/hi3.h' --- hipd/hi3.h 2010-02-17 17:38:08 +0000 +++ hipd/hi3.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,7 @@ #ifndef HIP_HIPD_HI3_H #define HIP_HIPD_HI3_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "user.h" #include "hipd.h" #include "lib/core/protodefs.h" === modified file 'hipd/hidb.c' --- hipd/hidb.c 2010-03-19 09:24:10 +0000 +++ hipd/hidb.c 2010-03-19 09:53:35 +0000 @@ -1,6 +1,9 @@ /** * @file - * HIP host id database and accessors. + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief A database to local Host Identifiers and the related accessor functions. * * @author Janne Lundberg <jlu#tcs.hut.fi> * @author Miika Komu <miika#iki.fi> @@ -12,11 +15,10 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "hidb.h" +#include "lib/core/hostid.h" +#include "lib/core/hit.h" HIP_HASHTABLE *hip_local_hostid_db = NULL; #define HIP_MAX_HOST_ID_LEN 1600 @@ -47,6 +49,13 @@ */ /* Do not access these databases directly: use the accessors in this file. */ + +/** + * hashing function required by hashtable/linked list implementation + * + * @param ptr a pointer to a hip_host_id_entry structure + * @return the calculated hash value + */ unsigned long hip_hidb_hash(const void *ptr) { hip_hit_t *hit = &(((struct hip_host_id_entry *) ptr)->lhi.hit); @@ -57,11 +66,23 @@ return *((unsigned long *) (void *) hash); } +/** + * matching function required by hashtable/linked list implementation + * + * @param ptr1 a pointer to hip_host_id_entry + * @param ptr2 a pointer to hip_host_id_entry + * @return zero on match or non-zero on unmatch + */ int hip_hidb_match(const void *ptr1, const void *ptr2) { return hip_hidb_hash(ptr1) != hip_hidb_hash(ptr2); } +/** + * initialize host identity database + * + * @param db A double pointer to a hip_db_struct_t. Caller deallocates. + */ void hip_init_hostid_db(hip_db_struct_t **db) { hip_local_hostid_db = hip_ht_init(hip_hidb_hash, hip_hidb_match); @@ -188,12 +209,26 @@ return NULL; } + +/** + * test if a given HIT belongs to the local host + * + * @param our the hit to be tested + * @return one if the HIT belongs to the local host or zero otherwise + */ int hip_hidb_hit_is_our(const hip_hit_t *our) { return hip_get_hostid_entry_by_lhi_and_algo(hip_local_hostid_db, our, HIP_ANY_ALGO, -1) != NULL; } +/** + * map a local HIT to a local LSI from the local host identifier database + * + * @param our a local HIT + * @param our_lsi the mapped LSI + * @return zero on success or non-zero on failure + */ int hip_hidb_get_lsi_by_hit(const hip_hit_t *our, hip_lsi_t *our_lsi) { struct hip_host_id_entry *id_entry; @@ -228,7 +263,7 @@ */ /** - * Deletes both host id databases + * Delete host id databases */ void hip_uninit_host_id_dbs(void) { @@ -487,56 +522,11 @@ return err; } -#if 0 /** - * Returns pointer to newly allocated area that contains a localhost HI. NULL - * is returned if problems are encountered. + * Strips a public key out of DSA a host id with private key component * - * @param db a pointer to a database. - * @param lhi HIT to match, if null, any. - * @param algo algorithm to match, if HIP_ANY_ALGO, any. - * @note Remember to free the host id structure after use. - */ -static struct hip_host_id *hip_get_host_id(hip_db_struct_t *db, - struct in6_addr *hit, int algo) -{ - struct hip_host_id_entry *tmp = NULL; - struct hip_host_id *result = NULL; - int t = 0; - - HIP_READ_LOCK_DB(db); - - tmp = hip_get_hostid_entry_by_lhi_and_algo(db, hit, algo, -1); - if (!tmp) { - HIP_READ_UNLOCK_DB(db); - HIP_ERROR("No host ID found.\n"); - return NULL; - } - - t = hip_get_param_total_len(tmp->host_id); - _HIP_DEBUG("Host ID length is %d bytes.\n", t); - if (t > HIP_MAX_HOST_ID_LEN) { - HIP_READ_UNLOCK_DB(db); - return NULL; - } - - result = HIP_MALLOC(t, GFP_ATOMIC); - if (!result) { - HIP_READ_UNLOCK_DB(db); - HIP_ERROR("Out of memory.\n"); - return NULL; - } - - memcpy(result, tmp->host_id, t); - HIP_READ_UNLOCK_DB(db); - - return result; -} - -#endif - -/** - * Resolves a public key out of DSA a host id. + * @param hi the host identifier with its private key component + * @return An allocated hip_host_id structure. Caller must deallocate. */ static struct hip_host_id *hip_get_dsa_public_key(const struct hip_host_id_priv *hi) { @@ -569,33 +559,12 @@ return ret; } -#if 0 -/** - * . - * - * @return a newly allocated area that contains the public key part of the - * localhost host identity. NULL is returned if errors detected. - * @note Remember to free the return value. - */ -static struct hip_host_id *hip_get_any_localhost_dsa_public_key(void) -{ - struct hip_host_id *res; - - res = hip_get_host_id(hip_local_hostid_db, NULL, HIP_HI_DSA); - if (!res) { - HIP_ERROR("No host id for localhost\n"); - } - - return res; -} - -#endif - -/** - * Gets the RSA public key from a Host Identity +/** + * Strips the RSA public key from a Host Identity * * @param tmp a pointer to a Host Identity. - * @return a pointer to a newly allocated host identity with only the public key + * @return A pointer to a newly allocated host identity with only the public key. + * Caller deallocates. */ static struct hip_host_id *hip_get_rsa_public_key(const struct hip_host_id_priv *tmp) { @@ -621,28 +590,6 @@ return ret; } -#if 0 -/** - * . - * - * @return a newly allocated area that contains the public key part of the - * localhost host identity. %NULL is returned if errors detected. - * @note Remember to free the return value. - */ -static struct hip_host_id *hip_get_any_localhost_rsa_public_key(void) -{ - struct hip_host_id *res; - - res = hip_get_host_id(hip_local_hostid_db, NULL, HIP_HI_RSA); - if (!res) { - HIP_ERROR("No host id for localhost\n"); - } - - return res; -} - -#endif - /** * Transforms a private/public key pair to a public key, private key is deleted. * @@ -665,7 +612,7 @@ } /** - * Adds a free lsi to the entry + * Assign a free LSI to a host id entry * * @param db database structure * @param id_entry contains an entry to the db, will contain an unsigned lsi @@ -701,9 +648,9 @@ } /** - * Search if the lsi exists already in the hidb + * Search if a local lsi exists already in the hidb * - * @param lsi lsi we are searching + * @param lsi the local lsi we are searching * @return 0 if it's not in the hidb, 1 if it is */ int hip_hidb_exists_lsi(hip_lsi_t *lsi) @@ -722,7 +669,7 @@ } /** - * Lists every hit in the database. + * Lists every local hit in the database. * * @param func a mapper function. * @param opaque opaque data for the mapper function. @@ -755,6 +702,13 @@ return err; } +/** + * find the local host identifier corresponding to the local LSI + * + * @param db the local host identifier database to be searched for + * @param lsi the local LSI to be matched + * @return the local host identifier structure + */ static struct hip_host_id_entry *hip_hidb_get_entry_by_lsi(hip_db_struct_t *db, const struct in_addr *lsi) { @@ -771,6 +725,13 @@ return NULL; } +/** + * associate the given local LSI to the local host identifier denoted by the given HIT + * + * @param default_hit the HIT to be searched for + * @param the LSI to associate with + * @return zero on success or negative on error + */ int hip_hidb_associate_default_hit_lsi(hip_hit_t *default_hit, hip_lsi_t *default_lsi) { int err = 0; @@ -801,6 +762,15 @@ } //#ifdef CONFIG_HIP_BLIND + +/** + * find the blinded local host identifier from the HIDB + * + * @param nonce the nonce used to blind the HIT + * @param test_hit the blinded HIT + * @param local_hit the unblinded HIT will be copied here + * @return zero on success or negative on error + */ int hip_blind_find_local_hi(uint16_t *nonce, struct in6_addr *test_hit, struct in6_addr *local_hit) { @@ -855,6 +825,16 @@ //#endif +/** + * find a host identifier from the database + * + * @param db the host identifier databased + * @param hit the HIT to be searched for + * @param algo the algorithm for the HI + * @param host_id A copy of the host is stored here. Caller deallocates. + * @param key a pointer to the private key (caller should not deallocate) + * @return zero on success or negative on error + */ int hip_get_host_id_and_priv_key(hip_db_struct_t *db, struct in6_addr *hit, int algo, struct hip_host_id **host_id, void **key) { @@ -882,6 +862,13 @@ return err; } +/** + * append a HOST id parameter and signature into the message to be sent on the wire + * + * @param msg the msg where the host id and signature should be appended + * @param hit the local HIT corresding to the host id + * @return zero on success or negative on error + */ int hip_build_host_id_and_signature(struct hip_common *msg, hip_hit_t *hit) { struct hip_host_id *hi_public = NULL; @@ -934,28 +921,50 @@ return err; } +/** + * get the default HIT of the local host + * + * @param hit the local default HIT will be written here + * @return zero on success or negative on error + */ int hip_get_default_hit(struct in6_addr *hit) { return hip_get_any_localhost_hit(hit, HIP_HI_RSA, 0); } -/* TDOD; This function has no error handling at all. Check if this is ok */ +/** + * get the default HIT of the local host and write into a + * user message + * + * @param msg the message where the HIT will be written + * @return zero on success or negative on error + */ int hip_get_default_hit_msg(struct hip_common *msg) { int err = 0; hip_hit_t hit; hip_lsi_t lsi; - hip_get_default_hit(&hit); - hip_get_default_lsi(&lsi); + HIP_IFE(hip_get_default_hit(&hit), -1); + HIP_IFE(hip_get_default_lsi(&lsi), -1); HIP_DEBUG_HIT("Default hit is ", &hit); HIP_DEBUG_LSI("Default lsi is ", &lsi); - hip_build_param_contents(msg, &hit, HIP_PARAM_HIT, sizeof(hit)); - hip_build_param_contents(msg, &lsi, HIP_PARAM_LSI, sizeof(lsi)); + HIP_IFE(hip_build_param_contents(msg, &hit, HIP_PARAM_HIT, sizeof(hit)), + -1); + HIP_IFE(hip_build_param_contents(msg, &lsi, HIP_PARAM_LSI, sizeof(lsi)), + -1); + + out_err: return err; } +/** + * get the default LSI of the local host + * + * @param lsi the default LSI will be written here + * @return zero on success or negative on error + */ int hip_get_default_lsi(struct in_addr *lsi) { int err = 0, family = AF_INET; === modified file 'hipd/hipd.c' --- hipd/hipd.c 2010-03-03 13:16:18 +0000 +++ hipd/hipd.c 2010-03-19 09:53:35 +0000 @@ -10,12 +10,11 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "hipd.h" #include "lib/dht/libhipdht.h" +#include "lib/core/filemanip.h" +#include "lib/core/straddr.h" #include "heartbeat.h" #ifdef CONFIG_HIP_PERFORMANCE @@ -178,105 +177,10 @@ HIP_HASHTABLE *bex_timestamp_db = NULL; -void hip_set_opportunistic_tcp_status(struct hip_common *msg) -{ - struct sockaddr_in6 sock_addr; - int retry, type, n; - - type = hip_get_msg_type(msg); - - _HIP_DEBUG("type=%d\n", type); - - memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin6_family = AF_INET6; - sock_addr.sin6_port = htons(HIP_FIREWALL_PORT); - sock_addr.sin6_addr = in6addr_loopback; - - for (retry = 0; retry < 3; retry++) { - /* Switched from hip_sendto() to hip_sendto_user() due to - * namespace collision. Both message.h and user.c had functions - * hip_sendto(). Introducing a prototype hip_sendto() to user.h - * led to compiler errors --> user.c hip_sendto() renamed to - * hip_sendto_user(). - * - * Lesson learned: use function prototypes unless functions are - * ment only for local (inside the same file where defined) use. - * -Lauri 11.07.2008 */ - n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr); - if (n <= 0) { - HIP_ERROR("hipconf opptcp failed (round %d)\n", retry); - HIP_DEBUG("Sleeping few seconds to wait for fw\n"); - sleep(2); - } else { - HIP_DEBUG("hipconf opptcp ok (sent %d bytes)\n", n); - break; - } - } - - if (type == SO_HIP_SET_OPPTCP_ON) { - hip_use_opptcp = 1; - } else { - hip_use_opptcp = 0; - } - - HIP_DEBUG("Opportunistic tcp set %s\n", - (hip_use_opptcp ? "on" : "off")); -} - -int hip_get_opportunistic_tcp_status() -{ - return hip_use_opptcp; -} - -/* hi3 */ -#ifdef CONFIG_HIP_I3 -void hip_set_hi3_status(struct hip_common *msg) -{ - struct sockaddr_in6 sock_addr; - int retry, type, n; - - type = hip_get_msg_type(msg); - - _HIP_DEBUG("type=%d\n", type); - - bzero(&sock_addr, sizeof(sock_addr)); - sock_addr.sin6_family = AF_INET6; - sock_addr.sin6_port = htons(HIP_FIREWALL_PORT); - sock_addr.sin6_addr = in6addr_loopback; - - for (retry = 0; retry < 3; retry++) { - n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr); - if (n <= 0) { - HIP_ERROR("hipconf hi3 failed (round %d)\n", retry); - HIP_DEBUG("Sleeping few seconds to wait for fw\n"); - sleep(2); - } else { - HIP_DEBUG("hipconf hi3 ok (sent %d bytes)\n", n); - break; - } - } - - if (type == SO_HIP_SET_HI3_ON) { - hip_i3_init(); - hip_use_hi3 = 1; - hip_locator_status = SO_HIP_SET_LOCATOR_ON; - } else { - hip_locator_status = SO_HIP_SET_LOCATOR_OFF; - hip_hi3_clean(); - hip_use_hi3 = 0; - } - - HIP_DEBUG("hi3 set %s\n", - (hip_use_hi3 ? "on" : "off")); -} - -int hip_get_hi3_status() -{ - return hip_use_hi3; -} - -#endif - + +/** + * print hipd usage instructions on stderr + */ static void usage(void) { fprintf(stderr, "Usage: hipd [options]\n\n"); @@ -289,6 +193,12 @@ fprintf(stderr, "\n"); } +/** + * a function for passing a message to the HIP graphical user agent + * + * @param msg the message to send + * @return zero on success or negative on error + */ int hip_send_agent(struct hip_common *msg) { struct sockaddr_in6 hip_agent_addr; @@ -336,6 +246,9 @@ /** * Receive message from agent socket. + * + * @param msg the received message will be stored here + * @return zero on success or negative on error */ int hip_recv_agent(struct hip_common *msg) { @@ -406,6 +319,12 @@ return err; } +/** + * send a message to the HIP firewall + * + * @param msg the message to send + * @return zero on success or negative on error + */ int hip_sendto_firewall(const struct hip_common *msg) { #ifdef CONFIG_HIP_FIREWALL @@ -433,7 +352,11 @@ } /** - * Daemon main function. + * Daemon "main" function. + * + * @param argc number of command line arguments + * @param argv the command line arguments + * @return zero on success or negative on error */ static int hipd_main(int argc, char *argv[]) { @@ -802,10 +725,13 @@ if (FD_ISSET(hip_opendht_sock_fqdn, &read_fdset) && FD_ISSET(hip_opendht_sock_fqdn, &write_fdset) && (hip_opendht_inuse == SO_HIP_DHT_ON)) { - /* Error with the connect */ - HIP_ERROR("Error OpenDHT socket is readable and writable\n"); + HIP_DEBUG("DHT socket waiting for connect (readable and writable)\n"); } else if (FD_ISSET(hip_opendht_sock_fqdn, &write_fdset)) { - hip_opendht_fqdn_sent = STATE_OPENDHT_START_SEND; + if (address_count == 0) { + HIP_DEBUG("No addresses do not go to the next state\n"); + } else { + hip_opendht_fqdn_sent = STATE_OPENDHT_START_SEND; + } } if (FD_ISSET(hip_opendht_sock_fqdn, &read_fdset) && (hip_opendht_inuse == SO_HIP_DHT_ON)) { @@ -834,10 +760,13 @@ if (FD_ISSET(hip_opendht_sock_hit, &read_fdset) && FD_ISSET(hip_opendht_sock_hit, &write_fdset) && (hip_opendht_inuse == SO_HIP_DHT_ON)) { - /* Error with the connect */ - HIP_ERROR("Error OpenDHT socket is readable and writable\n"); + HIP_ERROR("DHT socket waiting for connect (readable and writable)\n\n"); } else if (FD_ISSET(hip_opendht_sock_hit, &write_fdset)) { - hip_opendht_hit_sent = STATE_OPENDHT_START_SEND; + if (address_count == 0) { + HIP_DEBUG("No addresses do not go to the next state\n"); + } else { + hip_opendht_hit_sent = STATE_OPENDHT_START_SEND; + } } if ((FD_ISSET(hip_opendht_sock_hit, &read_fdset)) && (hip_opendht_inuse == SO_HIP_DHT_ON)) { @@ -904,6 +833,13 @@ return err; } +/** + * the main function for hipd + * + * @param argc number of command line arguments + * @param argv the command line arguments + * @return zero on success or negative on error + */ int main(int argc, char *argv[]) { int err = 0; === modified file 'hipd/hipd.h' --- hipd/hipd.h 2010-02-17 17:38:08 +0000 +++ hipd/hipd.h 2010-03-19 09:53:35 +0000 @@ -13,10 +13,7 @@ #include <netinet/udp.h> #include <sys/socket.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/crypto.h" #include "cookie.h" #include "user.h" @@ -76,8 +73,6 @@ #define HIP_SIMULATE_PACKET_LOSS_PROBABILITY 0 #define HIP_SIMULATE_PACKET_IS_LOST() (random() < ((uint64_t) HIP_SIMULATE_PACKET_LOSS_PROBABILITY * RAND_MAX) / 100) -#define HIP_NETLINK_TALK_ACK 0 /* see netlink_talk */ - #define HIP_ADDRESS_CHANGE_WAIT_INTERVAL 6 /* seconds */ #define HIP_ADDRESS_CHANGE_HB_COUNT_TRIGGER 2 @@ -182,19 +177,10 @@ //int hip_sendto(const struct hip_common *msg, const struct sockaddr_in6 *dst); -#ifdef CONFIG_HIP_I3 -int hip_get_hi3_status( void ); -void hip_set_hi3_status(struct hip_common *msg); -#endif /* CONFIG_HIP_I3 */ - -void hip_set_opportunistic_tcp_status(struct hip_common *msg); -int hip_get_opportunistic_tcp_status(void); int hip_send_agent(struct hip_common *msg); int hip_recv_agent(struct hip_common *msg); /* Functions for handling outgoing packets. */ int hip_sendto_firewall(const struct hip_common *msg); -#define IPV4_HDR_SIZE 20 - #endif /* HIP_HIPD_HIPD_H */ === modified file 'hipd/hiprelay.c' --- hipd/hiprelay.c 2010-03-03 13:16:18 +0000 +++ hipd/hiprelay.c 2010-03-19 09:53:35 +0000 @@ -1,8 +1,67 @@ /** @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * * This file defines the rendezvous extension and the UDP relay for HIP packets * for the Host Identity Protocol (HIP). See header file for usage - * instructions. Version 1.1 added support for white list and configuration - * file. + * instructions. Supports access control in the form in white lists in + * the /etc/hip/relay_config file. + * + * The HIP relay combines the functionalites of an rendezvous server (RVS) and + * a HIP UDP relay. The HIP relay consists of a hashtable for storing IP address + * to HIT mappings and of functions that do the actual relaying action. The + * hashtable is based on lhash library and its functionalites are the same + * except that the HIP relay stores data (allocated memory for relay records) + * instead of pointers. + * + * A few simple rules apply: + * <ul> + * <li>Allocate memory for relay records that are to be put into the hashtable + * only with hip_relrec_alloc().</li> + * <li>Once a relay record is <b>successfully</b> put into the hashtable, the + * only way delete it is to call hip_relht_rec_free(). This will remove the + * entry from the hashtable and free the memory allocated for the relay record. + * </li> + * </ul> + * + * Usage: + * <ul> + * <li>Inserting a new relay record: + * <pre> + * hip_relrec_t rr = hip_relrec_alloc(...); + * hip_relht_put(rr); + * if(hip_relht_get(rr) == NULL) // The put was unsuccessful. + * { + * if(rr != NULL) + * free(rr); + * } + * </pre> + * </li> + * <li>Fetching a relay record. We do not need (but can use) a fully populated + * relay record as a search key. A dummy record with hit_r field populated + * is sufficient. Note that there is no need to re-put the relay record into the + * hashtable once it has been succesfully inserted into the hashtable - except + * if we change the hit_r field of the relay record. If a relay record with same + * HIT is put into the hashtable, the existing element is deleted. + * + * <pre> + * hip_relrec_t dummy, *fetch_record = NULL; + * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit)); + * fetch_record = hip_relht_get(&dummy); + * if(fetch_record != NULL) + * { + * // Do something with the record. + * } + * </pre> + * </li> + * <li>Deleting a relay record. A dummy record can be used: + * <pre> + * hip_relrec_t dummy; + * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit)); + * hip_relht_rec_free(&dummy); + * </pre> + * </li> + * </ul> * * @author Lauri Silvennoinen * @note Related RFC: <a href="http://www.rfc-editor.org/rfc/rfc5204.txt";> @@ -11,17 +70,17 @@ * <a href="http://www.ietf.org/internet-drafts/draft-ietf-hip-nat-traversal-03.txt";> * draft-ietf-hip-nat-traversal-03</a> * @note Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. - * @see hiprelay.h + * @note Related RFC: <a href="http://www.rfc-editor.org/rfc/rfc5204.txt";> + * Host Identity Protocol (HIP) Rendezvous Extension</a> */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "hiprelay.h" +#include "output.h" +#include "lib/core/hip_udp.h" /** HIP relay config file default content. If the file @c HIP_RELAY_CONFIG_FILE * cannot be opened for reading, we write a new config file from scratch using @@ -88,125 +147,25 @@ */ hip_relay_wl_status_t whitelist_enabled = HIP_RELAY_WL_ON; -/** - * Initializes the global HIP relay hashtable. Allocates memory for - * @c hiprelay_ht. - * - * @return zero on success, -1 otherwise. - * @note do not call this function directly, instead call hip_relay_init(). - */ +/* forward declarations */ static int hip_relht_init(void); - -/** - * Uninitializes the HIP relay record hashtable @c hiprelay_ht. Frees the memory - * allocated for the hashtable and for the relay records. Thus, after calling - * this function, all memory allocated from the heap related to the relay record - * hashtable is free. - * - * @note do not call this function directly, instead call hip_relay_uninit(). - */ static void hip_relht_uninit(void); - -/** - * Deletes a single entry from the relay record hashtable and frees the memory - * allocated for the record, if the record has expired. The relay record is - * deleted if it has been last contacted more than @c hiprelay_lifetime seconds - * ago. If the parameter relay record is the same record that is being deleted - * (i.e. is located in the same memory location) then the parameter @c rec - * itself is freed. If a dummy record is used (i.e. is located in a different - * memory location thatn the hashtable entry), then @c rec is left untouched. - * - * @param rec a pointer to a relay record. - */ static void hip_relht_rec_free_expired_doall(hip_relrec_t *rec); - -/** - * Initializes the global HIP relay whitelist. Allocates memory for - * @c hiprelay_wl. - * - * @return zero on success, -1 otherwise. - * @note do not call this function directly, instead call hip_relay_init(). - */ static int hip_relwl_init(void); - -/** - * Uninitializes the HIP relay whitelist hashtable @c hiprelay_wl. Frees the - * memory allocated for the hashtable and for the HITs. Thus, after calling - * this function, all memory allocated from the heap related to the whitelist - * is free. - * - * @note do not call this function directly, instead call hip_relay_uninit(). - */ static void hip_relwl_uninit(void); - - -/** - * Puts a HIT into the whitelist. Puts the HIT pointed by @c hit into the - * whitelist hashtable @c hiprelay_wl. If there already is an entry with the - * same HIT, the old value is replaced, and <b>the memory allocated for the - * existing element is freed</b>. Note that we store pointers here, the data are - * not copied. - * - * @param hit a pointer to a HIT to be inserted into the whitelist. - * @return -1 if there was a hash collision i.e. a duplicate HIT is inserted, - * zero otherwise. - * @note <b style="color: #f00;">Do not put HITs allocated from the stack - * into the whitelist.</b> Instead put only HITs created with - * malloc(). - * @note In case of a hash collision, the existing HIT is freed. If you - * store references to HITs that are in the whitelist elsewhere - * outside the whitelist, NULL pointers can result. - */ static int hip_relwl_put(hip_hit_t *hit); - -/** - * Deletes a single entry from the whitelist hashtable and frees the memory - * allocated for the element. The parameter HIT is itself left untouched, it is - * only used as an search key. - * - * @param hit a pointer to a HIT. - */ static void hip_relwl_hit_free_doall(hip_hit_t *hit); - -/** - * Reads RVS / HIP Relay configuration from a file. Reads configuration - * information from @c HIP_RELAY_CONFIG_FILE. - * - * @return zero on success, -ENOENT if the file could not be opened for reading. - * @note The white list @c hiprelay_wl must be initialized before this - * function is called. - */ static int hip_relay_read_config(void); - -/** - * Writes RVS / HIP Relay configuration file with default content. Writes a RVS - * / HIP Relay configuration file to @c HIP_RELAY_CONFIG_FILE. The file is - * opened with "w" argument mode, which means that a possibly existing file is - * truncated to zero length. - * - * @return zero on success, -ENOENT if the file could not be opened for writing. - * @note Truncates existing file to zero length. - */ static int hip_relay_write_config(void); - -/** - * The hash function of the @c hiprelay_ht hashtable. Calculates a hash from - * parameter relay record HIT. - * - * @param rec a pointer to a relay record. - * @return the calculated hash or zero if @c rec or hit_r is NULL. - */ static unsigned long hip_relht_hash(const hip_relrec_t *rec); - -/** - * The hash function of the @c hiprelay_wl hashtable. Calculates a hash from - * parameter HIT. - * - * @param hit a pointer to a HIT. - * @return the calculated hash or zero if @c hit is NULL. - */ static unsigned long hip_relwl_hash(const hip_hit_t *hit); - +static int hip_relay_forward_response(const hip_common_t *r, + const uint8_t type_hdr, + const in6_addr_t *r_saddr, + const in6_addr_t *r_daddr, + const hip_portpair_t *r_info, + const in6_addr_t *relay_to_addr, + const in_port_t relay_to_port); /** * Returns a hash calculated over a HIT. * @@ -244,15 +203,19 @@ return hash; } -static int hip_relay_forward_response(const hip_common_t *r, - const uint8_t type_hdr, - const in6_addr_t *r_saddr, - const in6_addr_t *r_daddr, - const hip_portpair_t *r_info, - const in6_addr_t *relay_to_addr, - const in_port_t relay_to_port); - - +/** + * Deletes a single entry from the relay record hashtable and frees the memory + * allocated for the element if the matching element's type is of @c type. The + * deletion is based on the hash calculated from the relay fecord + * @c hit_r field, and therefore the parameter record does not need to be fully + * populated. If the parameter relay record is the same record that is being + * deleted (i.e. is located in the same memory location) then the parameter + * @c rec itself is freed. If a dummy record is used (i.e. is located in a + * different memory location thatn the hashtable entry), then @c rec is left + * untouched. + * + * @param rec a pointer to a relay record. + */ static void hip_relht_rec_free_type_doall_arg(hip_relrec_t *rec, const hip_relrec_type_t *type) { hip_relrec_t *fetch_record = hip_relht_get(rec); @@ -265,16 +228,34 @@ /** A callback wrapper of the prototype required by @c lh_doall_arg(). */ static IMPLEMENT_LHASH_DOALL_ARG_FN(hip_relht_rec_free_type, hip_relrec_t, hip_relrec_type_t) +/** + * Returns relay status. + * + * @return HIP_RELAY_ON if the RVS / relay is "on", HIP_RELAY_OFF otherwise. + */ hip_relay_status_t hip_relay_get_status() { return relay_enabled; } +/** + * Sets the status of the RVS / relay. Sets the relay "on" or "off". + * + * @param status zero if the relay is to be disabled, anything else to enable + * the relay. + */ void hip_relay_set_status(hip_relay_status_t status) { relay_enabled = status; } +/** + * The hash function of the @c hiprelay_ht hashtable. Calculates a hash from + * parameter relay record HIT. + * + * @param rec a pointer to a relay record. + * @return the calculated hash or zero if @c rec or hit_r is NULL. + */ static unsigned long hip_relht_hash(const hip_relrec_t *rec) { if (rec == NULL || &(rec->hit_r) == NULL) { @@ -287,6 +268,13 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_HASH_FN(hip_relht, const hip_relrec_t) +/** + * relay hash table comparison function + * + * @param rec1 a hip_relrec_t structure + * @param rec2 a hip_relrec_t structure + * @return zero if the structures are equal or one otherwise + */ static int hip_relht_cmp(const hip_relrec_t *rec1, const hip_relrec_t *rec2) { if (rec1 == NULL || &(rec1->hit_r) == NULL || @@ -300,6 +288,26 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_COMP_FN(hip_relht, const hip_relrec_t) +/** + * Puts a relay record into the hashtable. Puts the relay record pointed by + * @c rec into the hashtable @c hiprelay_ht. If there already is an entry with + * the same key the old value is replaced, and <b>the memory allocated for the + * existing element is freed</b>. Note that we store pointers here, the data are + * not copied. There should be no need to put a relay record more than once into + * the hashtable. If the fields of an individual relay record need to be + * changed, just retrieve the record with @c hip_relht_get() and alter the + * fields of it, but do not re-put it into the hashtable. + * + * @param rec a pointer to a relay record to be inserted into the hashtable. + * @return -1 if there was a hash collision i.e. an entry with duplicate HIT + * is inserted, zero otherwise. + * @note <b style="color: #f00;">Do not put records allocated from stack + * into the hashtable.</b> Instead put only records created with + * hip_relrec_alloc(). + * @note In case of a hash collision, the existing relay record is freed. + * If you store references to relay records that are in the hashtable + * elsewhere outside the hashtable, NULL pointers can result. + */ int hip_relht_put(hip_relrec_t *rec) { hip_relrec_t key, *match; @@ -325,6 +333,14 @@ } } +/** + * Retrieves a relay record from the hashtable @c hiprelay_ht. The parameter + * record @c rec only needs to have field @c hit_r populated. + * + * @param rec a pointer to a relay record. + * @return a pointer to a fully populated relay record if found, NULL + * otherwise. + */ hip_relrec_t *hip_relht_get(const hip_relrec_t *rec) { if (hiprelay_ht == NULL || rec == NULL) { @@ -334,6 +350,18 @@ return (hip_relrec_t *) list_find(rec, hiprelay_ht); } +/** + * Deletes a single entry from the relay record hashtable and frees the memory + * allocated for the element. The deletion is based on the hash calculated from + * the relay fecord @c hit_r field, and therefore the parameter record does not + * need to be fully populated. If the parameter relay record is the same record + * that is being deleted (i.e. is located in the same memory location) then + * the parameter @c rec itself is freed. If a dummy record is used (i.e. is + * located in a different memory location thatn the hashtable entry), then + * @c rec is left untouched. + * + * @param rec a pointer to a relay record. + */ void hip_relht_rec_free_doall(hip_relrec_t *rec) { if (hiprelay_ht == NULL || rec == NULL) { @@ -356,6 +384,17 @@ /** A callback wrapper of the prototype required by @c lh_doall(). */ static IMPLEMENT_LHASH_DOALL_FN(hip_relht_rec_free, hip_relrec_t) +/** + * Deletes a single entry from the relay record hashtable and frees the memory + * allocated for the record, if the record has expired. The relay record is + * deleted if it has been last contacted more than @c hiprelay_lifetime seconds + * ago. If the parameter relay record is the same record that is being deleted + * (i.e. is located in the same memory location) then the parameter @c rec + * itself is freed. If a dummy record is used (i.e. is located in a different + * memory location thatn the hashtable entry), then @c rec is left untouched. + * + * @param rec a pointer to a relay record. + */ static void hip_relht_rec_free_expired_doall(hip_relrec_t *rec) { if (rec == NULL) { // No need to check hiprelay_ht @@ -371,6 +410,11 @@ /** A callback wrapper of the prototype required by @c lh_doall(). */ static IMPLEMENT_LHASH_DOALL_FN(hip_relht_rec_free_expired, hip_relrec_t) +/** + * Returns the number of relay records in the hashtable @c hiprelay_ht. + * + * @return number of relay records in the hashtable. + */ unsigned long hip_relht_size() { if (hiprelay_ht == NULL) { @@ -380,6 +424,14 @@ return ((struct lhash_st *) hiprelay_ht)->num_items; } +/** + * Periodic maintenance function of the hip relay. This function should be + * called once in every maintenance cycle of the hip daemon. It clears the + * expired relay records by calling @c hip_relht_rec_free_expired() for every + * element in the hashtable. + * @todo a REG_RESPONSE with zero lifetime should be sent to each client whose + * registration is cancelled. + */ void hip_relht_maintenance() { if (hiprelay_ht == NULL) { @@ -392,6 +444,12 @@ ((struct lhash_st *) hiprelay_ht)->down_load = tmp; } +/** + * Deletes all entries of @c type from the relay record hashtable and frees the + * memory allocated for the deleted elements. + * + * @param type the type of the records to be deleted. + */ void hip_relht_free_all_of_type(const hip_relrec_type_t type) { if (hiprelay_ht == NULL) { @@ -405,6 +463,21 @@ ((struct lhash_st *) hiprelay_ht)->down_load = tmp; } +/** + * Allocates a new relay record. + * + * @param type the type of this relay record (HIP_FULLRELAY or + * HIP_RVSRELAY). + * @param lifetime the lifetime of this relayrecord as defined in registration + * draft. + * @param hit_r a pointer to Responder (relay client) HIT. + * @param ip_r a pointer to Responder (relay client) IP address. + * @param port responder's UDP port. + * @return a pointer to a new relay record, or NULL if failed to + * allocate. + * @note All records to be put in the hashtable should be created with + * this function. + */ hip_relrec_t *hip_relrec_alloc(const hip_relrec_type_t type, const uint8_t lifetime, const in6_addr_t *hit_r, const hip_hit_t *ip_r, @@ -434,6 +507,19 @@ return rec; } +/** + * Sets the mode of a relay record. This function sets the @c flags field of a + * relay record. + * + * @param rec a pointer to a relay record. + * @param mode the mode to be set for the parameter record. One of the following: + * <ul> + * <li>HIP_REL_NONE</li> + * <li>HIP_REL_UDP</li> + * <li>HIP_REL_TCP</li> + * </ul> + * @see hip_relrec_t for a bitmap. + */ void hip_relrec_set_mode(hip_relrec_t *rec, const hip_relrec_type_t type) { if (rec != NULL) { @@ -441,6 +527,13 @@ } } +/** + * Sets the lifetime of a relay record. + * The service lifetime is set to 2^((lifetime - 64)/8) seconds. + * + * @param rec a pointer to a relay record. + * @param lifetime the lifetime of the above formula. + */ void hip_relrec_set_lifetime(hip_relrec_t *rec, const uint8_t lifetime) { if (rec != NULL) { @@ -448,6 +541,12 @@ } } +/** + * Sets the UDP port number of a relay record. + * + * @param rec a pointer to a relay record. + * @param port UDP port number. + */ void hip_relrec_set_udpport(hip_relrec_t *rec, const in_port_t port) { if (rec != NULL) { @@ -455,6 +554,11 @@ } } +/** + * Prints info of the parameter relay record using @c HIP_INFO() macro. + * + * @param rec a pointer to a relay record. + */ void hip_relrec_info(const hip_relrec_t *rec) { if (rec == NULL) { @@ -500,6 +604,13 @@ HIP_DEBUG("\n%s", status); } +/** + * The hash function of the @c hiprelay_wl hashtable. Calculates a hash from + * parameter HIT. + * + * @param hit a pointer to a HIT. + * @return the calculated hash or zero if @c hit is NULL. + */ static unsigned long hip_relwl_hash(const hip_hit_t *hit) { if (hit == NULL) { @@ -512,6 +623,14 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_HASH_FN(hip_relwl, const hip_hit_t) +/** + * The compare function of the @c hiprelay_wl hashtable. Compares the hash + * values calculated from parameter @c hit1 and @c hit2. + * + * @param hit1 a pointer to a HIT. + * @param hit2 a pointer to a HIT. + * @return 0 if keys are equal and neither is NULL, non-zero otherwise. + */ static int hip_relwl_cmp(const hip_hit_t *hit1, const hip_hit_t *hit2) { if (hit1 == NULL || hit2 == NULL) { @@ -524,6 +643,23 @@ /** A callback wrapper of the prototype required by @c lh_new(). */ static IMPLEMENT_LHASH_COMP_FN(hip_relwl, const hip_hit_t) +/** + * Puts a HIT into the whitelist. Puts the HIT pointed by @c hit into the + * whitelist hashtable @c hiprelay_wl. If there already is an entry with the + * same HIT, the old value is replaced, and <b>the memory allocated for the + * existing element is freed</b>. Note that we store pointers here, the data are + * not copied. + * + * @param hit a pointer to a HIT to be inserted into the whitelist. + * @return -1 if there was a hash collision i.e. a duplicate HIT is inserted, + * zero otherwise. + * @note <b style="color: #f00;">Do not put HITs allocated from the stack + * into the whitelist.</b> Instead put only HITs created with + * malloc(). + * @note In case of a hash collision, the existing HIT is freed. If you + * store references to HITs that are in the whitelist elsewhere + * outside the whitelist, NULL pointers can result. + */ static int hip_relwl_put(hip_hit_t *hit) { if (hiprelay_wl == NULL || hit == NULL) { @@ -545,6 +681,12 @@ } } +/** + * Retrieves a HIT from the hashtable @c hiprelay_wl. + * + * @param hit a pointer to a HIT. + * @return a pointer to a matching HIT, NULL otherwise. + */ hip_hit_t *hip_relwl_get(const hip_hit_t *hit) { if (hiprelay_wl == NULL || hit == NULL) { @@ -571,6 +713,13 @@ #endif /* CONFIG_HIP_DEBUG */ +/** + * Deletes a single entry from the whitelist hashtable and frees the memory + * allocated for the element. The parameter HIT is itself left untouched, it is + * only used as an search key. + * + * @param hit a pointer to a HIT. + */ static void hip_relwl_hit_free_doall(hip_hit_t *hit) { if (hiprelay_wl == NULL || hit == NULL) { @@ -593,11 +742,32 @@ /** A callback wrapper of the prototype required by @c lh_doall(). */ static IMPLEMENT_LHASH_DOALL_FN(hip_relwl_hit_free, hip_hit_t) +/** + * Returns the whitelist status. + * + * @return HIP_RELAY_ON if the RVS / relay whitelist is "on", HIP_RELAY_OFF + * otherwise. + */ hip_relay_wl_status_t hip_relwl_get_status() { return whitelist_enabled; } +/** + * Validates a requested RVS service lifetime. If + * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then + * @c granted_lifetime is set to @c hiprelay_min_lifetime. If + * @c requested_lifetime is greater than @c hiprelay_max_lifetime then + * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else + * @c granted_lifetime is set to @c requested_lifetime. + * + * @param requested_lifetime the lifetime that is to be validated. + * @param granted_lifetime a target buffer for the validated lifetime. + * @return -1 if @c requested_lifetime is outside boundaries, + * i.e. is smaller than @c hiprelay_min_lifetime or + * is greater than @c hiprelay_max_lifetime. Zero + * otherwise. + */ int hip_rvs_validate_lifetime(uint8_t requested_lifetime, uint8_t *granted_lifetime) { @@ -613,6 +783,45 @@ } } +#if 0 +/** + * Validates a requested HIP relay service lifetime. If + * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then + * @c granted_lifetime is set to @c hiprelay_min_lifetime. If + * @c requested_lifetime is greater than @c hiprelay_max_lifetime then + * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else + * @c granted_lifetime is set to @c requested_lifetime. + * + * @param requested_lifetime the lifetime that is to be validated. + * @param granted_lifetime a target buffer for the validated lifetime. + * @return -1 if @c requested_lifetime is outside boundaries, + * i.e. is smaller than @c hiprelay_min_lifetime or + * is greater than @c hiprelay_max_lifetime. Zero + * otherwise. + * @note Currently this is just a call back wrapper for + * hip_rvs_validate_lifetime() because RVS and relay + * services share the same lifetimes. + */ +static int hip_relay_validate_lifetime(uint8_t requested_lifetime, + uint8_t *granted_lifetime) +{ + return hip_rvs_validate_lifetime(requested_lifetime, + granted_lifetime); +} +#endif + +/** + * forward a control packet in relay or rvs mode + * + * @param msg the HIP control message to be forwarded + * @param saddr source address of the message + * @param daddr destination address of the message + * @param rec the relay record corresponding to the packet + * @param info transport port number information + * @param type_hdr message type + * @param relay_type rvs vs. relay + * @return zero on success and negative on failure + */ int hip_relay_forward(const hip_common_t *msg, const in6_addr_t *saddr, const in6_addr_t *daddr, hip_relrec_t *rec, const hip_portpair_t *info, const uint8_t type_hdr, @@ -748,6 +957,14 @@ return err; } +/** + * Reads RVS / HIP Relay configuration from a file. Reads configuration + * information from @c HIP_RELAY_CONFIG_FILE. + * + * @return zero on success, -ENOENT if the file could not be opened for reading. + * @note The white list @c hiprelay_wl must be initialized before this + * function is called. + */ static int hip_relay_read_config() { FILE *fp = NULL; @@ -849,6 +1066,15 @@ return err; } +/** + * Writes RVS / HIP Relay configuration file with default content. Writes a RVS + * / HIP Relay configuration file to @c HIP_RELAY_CONFIG_FILE. The file is + * opened with "w" argument mode, which means that a possibly existing file is + * truncated to zero length. + * + * @return zero on success, -ENOENT if the file could not be opened for writing. + * @note Truncates existing file to zero length. + */ static int hip_relay_write_config() { int err = 0; @@ -869,10 +1095,14 @@ } /** - * @todo Xiang! Please, add decent Doxygen comments, check the doxy syntax - * from doc/HACKING. Stick to C-coding style using LINUX indendation. - * No lines over 80 characters. No capital letters in funcion names - * (C-style). Function commmends should be in header file. + * handle a HIP control message with relay_to parameter + * + * @param msg the message with the relay_to parameter + * @param msg_type the type of the message + * @param src_addr the source address of the message + * @param dst_addr the destination address of the message + * @param msg_info transport port numbers + * @return zero on success or negative on error */ int hip_relay_handle_relay_to(struct hip_common *msg, int msg_type, @@ -936,10 +1166,15 @@ } /** - * @todo Xiang! Please, add decent Doxygen comments, check the doxy syntax - * from doc/HACKING. Stick to C-coding style using LINUX indendation. - * No lines over 80 characters. No capital letters in funcion names - * (C-style). Function commmends should be in header file. + * forward a HIP control packet with relay_to parameter + * + * @param r the HIP control message to be relayed + * @param r_saddr the original source address + * @param r_daddr the original destination address + * @param r_info the transport layer ports + * @param relay_to_addr the address where to relay the packet + * @param relay_to_port the port where to relay the packet + * @return zero on success or negative on error */ static int hip_relay_forward_response(const hip_common_t *r, const uint8_t type_hdr, @@ -992,6 +1227,15 @@ return err; } +/** + * store the address of a peer's rendezvous server to the host association + * + * @param source_msg the I1 message + * @param entry the host association + * @return zero on success or negative on error + * + * @todo handle also the relay case + */ int hip_relay_add_rvs_to_ha(hip_common_t *source_msg, hip_ha_t *entry) { struct hip_via_rvs *via_rvs = NULL; @@ -1024,14 +1268,23 @@ } /** - * function return -1 means error - * return 0, means parameter not found - * return 1, means parameter found and verified - * @todo Xiang! Please, add decent Doxygen comments, check the doxy syntax - * from doc/HACKING. Stick to C-coding style using LINUX indendation. - * No lines over 80 characters. No capital letters in funcion names - * (C-style). Function commmends should be in header file. - * + * Handles a FROM/RELAY_FROM parameter. + * + * Checks if the parameter @c source_msg message has a FROM/RELAY_FROM + * parameter. If a parameter is found, the values are copied to target buffers + * @c dest_ip and @c dest_port. Next the hmac in RVS_HMAC is verified using + * the host association created during registration. This host association + * is searched using hitr from @c source_msg and @c rvs_ip as search keys. + * + * @param source_msg a pointer to the I1 HIP packet common header with source + * and destination HITs. + * @param rvs_ip a pointer to the source address from where the I1 packet + * was received. + * @param dest_ip a target buffer for the IP address in the FROM/RELAY_FROM + * parameter. + * @param dest_port a target buffer for the port number in RELAY_FROM + * parameter. + * @return zero */ int hip_relay_handle_from(hip_common_t *source_msg, in6_addr_t *rvs_ip, @@ -1103,13 +1356,12 @@ } /** - * function return -1 means error - * return 0, means parameter not found - * return 1, means parameter found and verified - * @todo Xiang! Please, add decent Doxygen comments, check the doxy syntax - * from doc/HACKING. Stick to C-coding style using LINUX indendation. - * No lines over 80 characters. No capital letters in funcion names - * (C-style). Function commmends should be in header file. + * handle relay_from parameter in a HIP control message + * + * @param source_msg the HIP control message + * @param relay_ip the source IP address of the message + * @param dest_ip the relayed destination will be written here + * @param dest_port the relayed destination port will be written here */ int hip_relay_handle_relay_from(hip_common_t *source_msg, in6_addr_t *relay_ip, @@ -1188,6 +1440,17 @@ return 1; } +/** + * handle the relay_to parameter at the Initiator + * + * @param msg the HIP control packet with relay_to parameter + * @param msg_type the type of the HIP control message + * @param src_addr source address of the message + * @param dst_addr destination address of the message + * @param msg_info transport layer port information + * @param entry the host association + * @return zero on success or negative on error + */ int hip_relay_handle_relay_to_in_client(struct hip_common *msg, int msg_type, struct in6_addr *src_addr, @@ -1239,6 +1502,13 @@ return err; } +/** + * Initializes the global HIP relay hashtable. Allocates memory for + * @c hiprelay_ht. + * + * @return zero on success, -1 otherwise. + * @note do not call this function directly, instead call hip_relay_init(). + */ static int hip_relht_init() { /* Check that the relay hashtable is not already initialized. */ @@ -1256,6 +1526,14 @@ return 0; } +/** + * Uninitializes the HIP relay record hashtable @c hiprelay_ht. Frees the memory + * allocated for the hashtable and for the relay records. Thus, after calling + * this function, all memory allocated from the heap related to the relay record + * hashtable is free. + * + * @note do not call this function directly, instead call hip_relay_uninit(). + */ static void hip_relht_uninit() { if (hiprelay_ht == NULL) { @@ -1267,6 +1545,10 @@ hiprelay_ht = NULL; } +/** + * Initializes the HIP relay / RVS. Initializes the HIP relay hashtable and + * whitelist. + */ int hip_relay_init() { int err = 0; @@ -1300,12 +1582,28 @@ return err; } +/** + * Uninitializes the HIP relay / RVS. Uninitializes the HIP relay hashtable and + * whitelist. + */ void hip_relay_uninit() { hip_relht_uninit(); hip_relwl_uninit(); } +/** + * Reinitializes the HIP relay / RVS. Deletes the old values from the relay + * whitelist and reads new values from the configuration file + * @c HIP_RELAY_CONFIG_FILE. Besides the whitelist values also every other + * value read from the configuration file is reinitialized. These include the + * lifetime values etc. However, the existing relay records are left as they + * were. This means that the relay / RVS clients that have already registered + * continue to be served as before - even if their HIT nomore exists in the + * whitelist. + * + * @return zero if the configuration file was read succesfully, -1 otherwise. + */ int hip_relay_reinit() { int err = 0; @@ -1320,6 +1618,13 @@ return err; } +/** + * Initializes the global HIP relay whitelist. Allocates memory for + * @c hiprelay_wl. + * + * @return zero on success, -1 otherwise. + * @note do not call this function directly, instead call hip_relay_init(). + */ static int hip_relwl_init() { /* Check that the relay whitelist is not already initialized. */ @@ -1337,6 +1642,14 @@ return 0; } +/** + * Uninitializes the HIP relay whitelist hashtable @c hiprelay_wl. Frees the + * memory allocated for the hashtable and for the HITs. Thus, after calling + * this function, all memory allocated from the heap related to the whitelist + * is free. + * + * @note do not call this function directly, instead call hip_relay_uninit(). + */ static void hip_relwl_uninit() { if (hiprelay_wl == NULL) { === modified file 'hipd/hiprelay.h' --- hipd/hiprelay.h 2010-02-17 17:38:08 +0000 +++ hipd/hiprelay.h 2010-03-19 09:53:35 +0000 @@ -1,71 +1,13 @@ /** @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. + * * A header file for hiprelay.c. * - * The HIP relay combines the functionalites of an rendezvous server (RVS) and - * a HIP UDP relay. The HIP relay consists of a hashtable for storing IP address - * to HIT mappings and of functions that do the actual relaying action. The - * hashtable is based on lhash library and its functionalites are the same - * except that the HIP relay stores data (allocated memory for relay records) - * instead of pointers. - * - * A few simple rules apply: - * <ul> - * <li>Allocate memory for relay records that are to be put into the hashtable - * only with hip_relrec_alloc().</li> - * <li>Once a relay record is <b>successfully</b> put into the hashtable, the - * only way delete it is to call hip_relht_rec_free(). This will remove the - * entry from the hashtable and free the memory allocated for the relay record. - * </li> - * </ul> - * - * Usage: - * <ul> - * <li>Inserting a new relay record: - * <pre> - * hip_relrec_t rr = hip_relrec_alloc(...); - * hip_relht_put(rr); - * if(hip_relht_get(rr) == NULL) // The put was unsuccessful. - * { - * if(rr != NULL) - * free(rr); - * } - * </pre> - * </li> - * <li>Fetching a relay record. We do not need (but can use) a fully populated - * relay record as a search key. A dummy record with hit_r field populated - * is sufficient. Note that there is no need to re-put the relay record into the - * hashtable once it has been succesfully inserted into the hashtable - except - * if we change the hit_r field of the relay record. If a relay record with same - * HIT is put into the hashtable, the existing element is deleted. - * - * <pre> - * hip_relrec_t dummy, *fetch_record = NULL; - * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit)); - * fetch_record = hip_relht_get(&dummy); - * if(fetch_record != NULL) - * { - * // Do something with the record. - * } - * </pre> - * </li> - * <li>Deleting a relay record. A dummy record can be used: - * <pre> - * hip_relrec_t dummy; - * memcpy((char *)&(dummy.hit_r), hit, sizeof(hit)); - * hip_relht_rec_free(&dummy); - * </pre> - * </li> - * </ul> - * * @author Lauri Silvennoinen - * @version 1.1 - * @date 31.03.2008 - * @note Related RFC: <a href="http://www.rfc-editor.org/rfc/rfc5204.txt";> - * Host Identity Protocol (HIP) Rendezvous Extension</a> * @note Related draft: * <a href="http://www.ietf.org/internet-drafts/draft-ietf-hip-nat-traversal-03.txt";> * draft-ietf-hip-nat-traversal-03</a> - * @note Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. */ #ifndef HIP_HIPD_HIPRELAY_H #define HIP_HIPD_HIPRELAY_H @@ -76,11 +18,8 @@ #include <arpa/inet.h> /* For nthos() */ #include <math.h> /* For pow() */ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include "lib/core/misc.h" /* For debuging macros. */ +#include "config.h" + /* For debuging macros. */ #include "registration.h" /* For lifetime conversions. */ #include "configfilereader.h" #include "lib/core/state.h" @@ -136,366 +75,54 @@ /** Possible states of the whitelist. */ typedef enum { HIP_RELAY_WL_OFF = 0, HIP_RELAY_WL_ON = 1 } hip_relay_wl_status_t; -/** - * Returns relay status. - * - * @return HIP_RELAY_ON if the RVS / relay is "on", HIP_RELAY_OFF otherwise. - */ hip_relay_status_t hip_relay_get_status(void); - -/** - * Sets the status of the RVS / relay. Sets the relay "on" or "off". - * - * @param status zero if the relay is to be disabled, anything else to enable - * the relay. - */ void hip_relay_set_status(hip_relay_status_t status); - -/** - * Initializes the HIP relay / RVS. Initializes the HIP relay hashtable and - * whitelist. - */ int hip_relay_init(void); - -/** - * Uninitializes the HIP relay / RVS. Uninitializes the HIP relay hashtable and - * whitelist. - */ void hip_relay_uninit(void); - -/** - * Reinitializes the HIP relay / RVS. Deletes the old values from the relay - * whitelist and reads new values from the configuration file - * @c HIP_RELAY_CONFIG_FILE. Besides the whitelist values also every other - * value read from the configuration file is reinitialized. These include the - * lifetime values etc. However, the existing relay records are left as they - * were. This means that the relay / RVS clients that have already registered - * continue to be served as before - even if their HIT nomore exists in the - * whitelist. - * - * @return zero if the configuration file was read succesfully, -1 otherwise. - */ int hip_relay_reinit(void); - -/** - * Sets the mode of a relay record. This function sets the @c flags field of a - * relay record. - * - * @param rec a pointer to a relay record. - * @param mode the mode to be set for the parameter record. One of the following: - * <ul> - * <li>HIP_REL_NONE</li> - * <li>HIP_REL_UDP</li> - * <li>HIP_REL_TCP</li> - * </ul> - * @see hip_relrec_t for a bitmap. - */ void hip_relrec_set_mode(hip_relrec_t *rec, const hip_relrec_type_t type); - -/** - * Sets the lifetime of a relay record. - * The service lifetime is set to 2^((lifetime - 64)/8) seconds. - * - * @param rec a pointer to a relay record. - * @param lifetime the lifetime of the above formula. - */ void hip_relrec_set_lifetime(hip_relrec_t *rec, const uint8_t lifetime); - -/** - * Sets the UDP port number of a relay record. - * - * @param rec a pointer to a relay record. - * @param port UDP port number. - */ void hip_relrec_set_udpport(hip_relrec_t *rec, const in_port_t port); - -/** - * Prints info of the parameter relay record using @c HIP_INFO() macro. - * - * @param rec a pointer to a relay record. - */ void hip_relrec_info(const hip_relrec_t *rec); - -/** - * The compare function of the @c hiprelay_ht hashtable. Compares the hash - * values calculated from parameters @c rec1 and @c rec2. - * - * @param rec1 a pointer to a HIT. - * @param rec2 a pointer to a HIT. - * @return 0 if keys are equal and neither is NULL, non-zero otherwise. - */ -int hip_relht_compare(const hip_relrec_t *rec1, const hip_relrec_t *rec2); - -/** - * Puts a relay record into the hashtable. Puts the relay record pointed by - * @c rec into the hashtable @c hiprelay_ht. If there already is an entry with - * the same key the old value is replaced, and <b>the memory allocated for the - * existing element is freed</b>. Note that we store pointers here, the data are - * not copied. There should be no need to put a relay record more than once into - * the hashtable. If the fields of an individual relay record need to be - * changed, just retrieve the record with @c hip_relht_get() and alter the - * fields of it, but do not re-put it into the hashtable. - * - * @param rec a pointer to a relay record to be inserted into the hashtable. - * @return -1 if there was a hash collision i.e. an entry with duplicate HIT - * is inserted, zero otherwise. - * @note <b style="color: #f00;">Do not put records allocated from stack - * into the hashtable.</b> Instead put only records created with - * hip_relrec_alloc(). - * @note In case of a hash collision, the existing relay record is freed. - * If you store references to relay records that are in the hashtable - * elsewhere outside the hashtable, NULL pointers can result. - */ int hip_relht_put(hip_relrec_t *rec); - -/** - * Retrieves a relay record from the hashtable @c hiprelay_ht. The parameter - * record @c rec only needs to have field @c hit_r populated. - * - * @param rec a pointer to a relay record. - * @return a pointer to a fully populated relay record if found, NULL - * otherwise. - */ hip_relrec_t *hip_relht_get(const hip_relrec_t *rec); - -/** - * Deletes a single entry from the relay record hashtable and frees the memory - * allocated for the element. The deletion is based on the hash calculated from - * the relay fecord @c hit_r field, and therefore the parameter record does not - * need to be fully populated. If the parameter relay record is the same record - * that is being deleted (i.e. is located in the same memory location) then - * the parameter @c rec itself is freed. If a dummy record is used (i.e. is - * located in a different memory location thatn the hashtable entry), then - * @c rec is left untouched. - * - * @param rec a pointer to a relay record. - */ void hip_relht_rec_free_doall(hip_relrec_t *rec); - -/** - * Deletes a single entry from the relay record hashtable and frees the memory - * allocated for the element if the matching element's type is of @c type. The - * deletion is based on the hash calculated from the relay fecord - * @c hit_r field, and therefore the parameter record does not need to be fully - * populated. If the parameter relay record is the same record that is being - * deleted (i.e. is located in the same memory location) then the parameter - * @c rec itself is freed. If a dummy record is used (i.e. is located in a - * different memory location thatn the hashtable entry), then @c rec is left - * untouched. - * - * @param rec a pointer to a relay record. - */ void hip_relht_rec_free_type_doall(hip_relrec_t *rec, const hip_relrec_type_t *type); - -/** - * Returns the number of relay records in the hashtable @c hiprelay_ht. - * - * @return number of relay records in the hashtable. - */ unsigned long hip_relht_size(void); - -/** - * Periodic maintenance function of the hip relay. This function should be - * called once in every maintenance cycle of the hip daemon. It clears the - * expired relay records by calling @c hip_relht_rec_free_expired() for every - * element in the hashtable. - * @todo a REG_RESPONSE with zero lifetime should be sent to each client whose - * registration is cancelled. - */ void hip_relht_maintenance(void); - -/** - * Allocates a new relay record. - * - * @param type the type of this relay record (HIP_FULLRELAY or - * HIP_RVSRELAY). - * @param lifetime the lifetime of this relayrecord as defined in registration - * draft. - * @param hit_r a pointer to Responder (relay client) HIT. - * @param ip_r a pointer to Responder (relay client) IP address. - * @param port responder's UDP port. - * @return a pointer to a new relay record, or NULL if failed to - * allocate. - * @note All records to be put in the hashtable should be created with - * this function. - */ hip_relrec_t *hip_relrec_alloc(const hip_relrec_type_t type, const uint8_t lifetime, const in6_addr_t *hit_r, const hip_hit_t *ip_r, const in_port_t port, const hip_crypto_key_t *hmac, const hip_xmit_func_t func); - -/** - * Deletes all entries of @c type from the relay record hashtable and frees the - * memory allocated for the deleted elements. - * - * @param type the type of the records to be deleted. - */ void hip_relht_free_all_of_type(const hip_relrec_type_t type); - -/** - * The compare function of the @c hiprelay_wl hashtable. Compares the hash - * values calculated from parameter @c hit1 and @c hit2. - * - * @param hit1 a pointer to a HIT. - * @param hit2 a pointer to a HIT. - * @return 0 if keys are equal and neither is NULL, non-zero otherwise. - */ int hip_relwl_compare(const hip_hit_t *hit1, const hip_hit_t *hit2); - -/** - * Retrieves a HIT from the hashtable @c hiprelay_wl. - * - * @param hit a pointer to a HIT. - * @return a pointer to a matching HIT, NULL otherwise. - */ hip_hit_t *hip_relwl_get(const hip_hit_t *hit); - -/** - * Returns the whitelist status. - * - * @return HIP_RELAY_ON if the RVS / relay whitelist is "on", HIP_RELAY_OFF - * otherwise. - */ hip_relay_wl_status_t hip_relwl_get_status(void); - -/** - * Validates a requested RVS service lifetime. If - * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then - * @c granted_lifetime is set to @c hiprelay_min_lifetime. If - * @c requested_lifetime is greater than @c hiprelay_max_lifetime then - * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else - * @c granted_lifetime is set to @c requested_lifetime. - * - * @param requested_lifetime the lifetime that is to be validated. - * @param granted_lifetime a target buffer for the validated lifetime. - * @return -1 if @c requested_lifetime is outside boundaries, - * i.e. is smaller than @c hiprelay_min_lifetime or - * is greater than @c hiprelay_max_lifetime. Zero - * otherwise. - */ int hip_rvs_validate_lifetime(uint8_t requested_lifetime, uint8_t *granted_lifetime); - int hip_relay_forward(const hip_common_t *msg, const in6_addr_t *saddr, const in6_addr_t *daddr, hip_relrec_t *rec, const hip_portpair_t *info, const uint8_t type_hdr, const hip_relrec_type_t relay_type); - -/** - * Validates a requested HIP relay service lifetime. If - * @c requested_lifetime is smaller than @c hiprelay_min_lifetime then - * @c granted_lifetime is set to @c hiprelay_min_lifetime. If - * @c requested_lifetime is greater than @c hiprelay_max_lifetime then - * @c granted_lifetime is set to @c hiprelay_max_lifetime. Else - * @c granted_lifetime is set to @c requested_lifetime. - * - * @param requested_lifetime the lifetime that is to be validated. - * @param granted_lifetime a target buffer for the validated lifetime. - * @return -1 if @c requested_lifetime is outside boundaries, - * i.e. is smaller than @c hiprelay_min_lifetime or - * is greater than @c hiprelay_max_lifetime. Zero - * otherwise. - * @note Currently this is just a call back wrapper for - * hip_rvs_validate_lifetime() because RVS and relay - * services share the same lifetimes. - */ -static inline int hip_relay_validate_lifetime(uint8_t requested_lifetime, - uint8_t *granted_lifetime) -{ - return hip_rvs_validate_lifetime(requested_lifetime, - granted_lifetime); -} - -/** - * Relays an incoming I1 packet. - * - * This function relays an incoming I1 packet to the next node on path - * to receiver and inserts a @c FROM parameter encapsulating the source IP - * address. In case there is a NAT between the sender (the initiator or previous - * RVS) of the I1 packet, a @c RELAY_FROM parameter is inserted instead of a - * @c FROM parameter. Next node on path is typically the responder, but if the - * message is to travel multiple rendezvous servers en route to responder, next - * node can also be another rendezvous server. In this case the @c FROM - * (@c RELAY_FROM) parameter is appended after the existing ones. Thus current RVS - * appends the address of previous RVS and the final RVS (n) in the RVS chain - * sends @c FROM:I, @c FROM:RVS1, ... , <code>FROM:RVS(n-1)</code>. If initiator - * is located behind a NAT, the first @c FROM parameter is replaced with a - * @c RELAY_FROM parameter. - * - * @param i1 a pointer to the I1 HIP packet common header with source and - * destination HITs. - * @param i1_saddr a pointer to the source address from where the I1 packet was - * received. - * @param i1_daddr a pointer to the destination address where the I1 packet was - * sent to (own address). - * @param rec a pointer to a relay record matching the HIT of Responder. - * @param i1_info a pointer to the source and destination ports (when NAT is - * in use). - * @return zero on success, or negative error value on error. - * @note This code has not been tested thoroughly with multiple RVSes. - * @note This function is a copy-paste from the previous RVS - * implementation - */ -int hip_relay_rvs(const hip_common_t *i1, - const in6_addr_t *i1_saddr, - const in6_addr_t *i1_daddr, hip_relrec_t *rec, - const hip_portpair_t *i1_info); - int hip_relay_add_rvs_to_ha(hip_common_t *source_msg, hip_ha_t *entry); - - -/** - * Handles a FROM/RELAY_FROM parameter. - * - * Checks if the parameter @c source_msg message has a FROM/RELAY_FROM - * parameter. If a parameter is found, the values are copied to target buffers - * @c dest_ip and @c dest_port. Next the hmac in RVS_HMAC is verified using - * the host association created during registration. This host association - * is searched using hitr from @c source_msg and @c rvs_ip as search keys. - * - * @param source_msg a pointer to the I1 HIP packet common header with source - * and destination HITs. - * @param rvs_ip a pointer to the source address from where the I1 packet - * was received. - * @param dest_ip a target buffer for the IP address in the FROM/RELAY_FROM - * parameter. - * @param dest_port a target buffer for the port number in RELAY_FROM - * parameter. - * @return zero - */ - int hip_relay_handle_from(hip_common_t *source_msg, in6_addr_t *rvs_ip, in6_addr_t *dest_ip, in_port_t *dest_port); - int hip_relay_handle_relay_from(hip_common_t *source_msg, in6_addr_t *relay_ip, in6_addr_t *dest_ip, in_port_t *dest_port); - int hip_relay_handle_relay_to_in_client(struct hip_common *msg, int msg_type, struct in6_addr *src_addr, struct in6_addr *dst_addr, hip_portpair_t *msg_info, hip_ha_t *entry); - - int hip_relay_handle_relay_to(struct hip_common *msg, int msg_type, struct in6_addr *src_addr, struct in6_addr *dst_addr, hip_portpair_t *msg_info); -/** - * function for full relay service. from I to R - * - */ -int hip_relay_forward_I(const hip_common_t *i1, - const in6_addr_t *i1_saddr, - const in6_addr_t *i1_daddr, hip_relrec_t *rec, - const hip_portpair_t *i1_info, - const uint8_t); - #endif /* HIP_HIPD_HIPRELAY_H */ === modified file 'hipd/init.c' --- hipd/init.c 2010-03-03 13:16:18 +0000 +++ hipd/init.c 2010-03-19 09:53:35 +0000 @@ -1,7 +1,9 @@ /** @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. + * * This file defines initialization functions for the HIP daemon. * - * @note Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. * @note HIPU: BSD platform needs to be autodetected in hip_set_lowcapability */ @@ -12,18 +14,19 @@ #include <sys/types.h> #include <netinet/icmp6.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" +#include "init.h" +#include "oppdb.h" #include "lib/core/common_defines.h" #include "lib/core/debug.h" -#include "init.h" #include "lib/performance/performance.h" #include "lib/core/hip_capability.h" +#include "lib/core/filemanip.h" +#include "lib/core/hostid.h" #include "lib/tool/nlink.h" -#include "oppdb.h" #include "lib/dht/libhipdht.h" +#include "lib/core/hip_udp.h" +#include "lib/core/hostsfiles.h" #ifdef CONFIG_HIP_AGENT #include "hipd.h" @@ -80,7 +83,11 @@ static struct hip_host_id_entry *hip_return_first_rsa(void); /******************************************************************************/ -/** Catch SIGCHLD. */ +/** + * Catch SIGCHLD. + * + * @param signum the signal number to catch + */ static void hip_sig_chld(int signum) { #ifdef ANDROID_CHANGES @@ -100,6 +107,13 @@ } } +/** + * set or unset close-on-exec flag for a given file descriptor + * + * @param desc the file descriptor + * @param value 1 if to set or zero for unset + * @return the previous flags + */ static int set_cloexec_flag(int desc, int value) { int oldflags = fcntl(desc, F_GETFD, 0); @@ -120,6 +134,9 @@ #ifndef CONFIG_HIP_OPENWRT #ifdef CONFIG_HIP_DEBUG +/** + * print information about underlying the system for bug reports + */ static void hip_print_sysinfo(void) { FILE *fp = NULL; @@ -227,8 +244,11 @@ #endif #endif -/* +/** * Create a file with the given contents unless it already exists + * + * @param path the file with its path + * @param contents a string to write to the file */ static void hip_create_file_unless_exists(const char *path, const char *contents) { @@ -244,6 +264,9 @@ fclose(fp); } +/** + * load hipd configuration files + */ static void hip_load_configuration(void) { const char *cfile = "default"; @@ -269,6 +292,9 @@ hip_conf_handle_load(NULL, ACTION_LOAD, &cfile, 1, 1); } +/** + * initialize OS-dependent variables + */ static void hip_set_os_dep_variables(void) { struct utsname un; @@ -306,8 +332,9 @@ #ifdef CONFIG_HIP_AGENT /** - * hip_init_daemon_hitdb - The function initializes the database at daemon - * which receives the information from agent to be stored + * initialize the graphical agent database + * + * @return zero on success or negative on failure */ static int hip_init_daemon_hitdb(void) { @@ -325,7 +352,11 @@ #endif /* CONFIG_HIP_AGENT */ /** - * Initialize raw ipv4 socket. + * initialize a raw ipv4 socket + * + * @param hip_raw_sock_v4 the raw socket to initialize + * @param proto the protocol for the raw socket + * @return zero on success or negative on failure */ static int hip_init_raw_sock_v4(int *hip_raw_sock_v4, int proto) { @@ -351,7 +382,10 @@ } /** - * Initialize icmpv6 socket. + * initialize icmpv6 socket for heartbeats + * + * @param icmpsockfd the socket to initialize + * @return zero on success or negative on failure */ static int hip_init_icmp_v6(int *icmpsockfd) { @@ -379,12 +413,11 @@ return err; } +#ifndef CONFIG_HIP_OPENWRT +#ifndef ANDROID_CHANGES /** - * Probe kernel modules. + * probe for kernel modules (linux specific) */ - -#ifndef CONFIG_HIP_OPENWRT -#ifndef ANDROID_CHANGES static void hip_probe_kernel_modules(void) { int count, err, status; @@ -430,6 +463,11 @@ /** * Main initialization function for HIP daemon. + * + * @param flush_ipsec one if ipsec should be flushed or zero otherwise + * @param killold one if an existing hipd process should be killed or + * zero otherwise + * @return zero on success or negative on failure */ int hipd_init(int flush_ipsec, int killold) { @@ -558,14 +596,12 @@ HIP_IFEL(hip_init_raw_sock_v6(&hip_raw_sock_output_v6, IPPROTO_HIP), -1, "raw sock output v6\n"); HIP_IFEL(hip_init_raw_sock_v4(&hip_raw_sock_output_v4, IPPROTO_HIP), -1, "raw sock output v4\n"); - // Notice that hip_nat_sock_input should be initialized after hip_nat_sock_output - // because for the sockets bound to the same address/port, only the last socket seems - // to receive the packets. -#if 0 - HIP_IFEL(hip_create_nat_sock_udp(&hip_nat_sock_output_udp, 0), -1, "raw sock output udp\n"); -#else + /* hip_nat_sock_input should be initialized after hip_nat_sock_output + because for the sockets bound to the same address/port, only the last socket seems + to receive the packets. NAT input socket is a normal UDP socket where as + NAT output socket is a raw socket. A raw output socket support better the "shotgun" + extension (sending packets from multiple source addresses). */ HIP_IFEL(hip_init_raw_sock_v4(&hip_nat_sock_output_udp, IPPROTO_UDP), -1, "raw sock output udp\n"); -#endif HIP_IFEL(hip_init_raw_sock_v6(&hip_raw_sock_input_v6, IPPROTO_HIP), -1, "raw sock input v6\n"); HIP_IFEL(hip_init_raw_sock_v4(&hip_raw_sock_input_v4, IPPROTO_HIP), -1, "raw sock input v4\n"); HIP_IFEL(hip_create_nat_sock_udp(&hip_nat_sock_input_udp, 0, 0), -1, "raw sock input udp\n"); @@ -687,9 +723,9 @@ } /** - * Function initializes needed variables for the OpenDHT + * initialize the needed variables for DHT * - * Returns positive on success negative otherwise + * @return zero on success or negative on failure */ int hip_init_dht() { @@ -789,8 +825,18 @@ HIP_DEBUG("gethostname failed\n"); } hip_register_to_dht(); - hip_init_dht_sockets(&hip_opendht_sock_fqdn, &hip_opendht_fqdn_sent); - hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent); + err = hip_init_dht_sockets(&hip_opendht_sock_fqdn, &hip_opendht_fqdn_sent); + if (err < 0) { + close(hip_opendht_sock_fqdn); + hip_opendht_sock_fqdn = -1; + /* Do not bother trying the other */ + return err; + } + err = hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent); + if (err < 0) { + close(hip_opendht_sock_hit); + hip_opendht_sock_hit = -1; + } /* out_err only used by opendht code */ out_err: @@ -800,7 +846,9 @@ } /** - * Initialize host IDs. + * Initialize local host IDs. + * + * @return zero on success or negative on failure */ static int hip_init_host_ids() { @@ -893,7 +941,12 @@ } /** - * Init raw ipv6 socket. + * Init raw ipv6 socket + * + * @param hip_raw_sock_v6 the socket to initialize + * @param proto protocol for the socket + * + * @return zero on success or negative on failure */ static int hip_init_raw_sock_v6(int *hip_raw_sock_v6, int proto) { @@ -915,6 +968,16 @@ return err; } +/** + * create a socket to handle UDP encapsulation of HIP control + * packets + * + * @param hip_nat_sock_udp the socket to initialize + * @param addr the address to which the socket should be bound + * @param is_output one if the socket is to be used for output + * or zero for input + * @return zero on success or negative on failure + */ int hip_create_nat_sock_udp(int *hip_nat_sock_udp, struct sockaddr_in *addr, int is_output) @@ -986,7 +1049,9 @@ } /** - * Start closing HIP daemon. + * exit gracefully by sending CLOSE to all peers + * + * @param signal the signal hipd received from OS */ void hip_close(int signal) { @@ -1012,6 +1077,8 @@ /** * Cleanup and signal handler to free userspace and kernel space * resource allocations. + * + * @param signal the signal hipd received */ void hip_exit(int signal) { @@ -1095,6 +1162,9 @@ close(hip_nat_sock_output_udp_v6); } + hip_uninit_hadb(); + hip_uninit_host_id_dbs(); + if (hip_user_sock) { HIP_INFO("hip_user_sock\n"); close(hip_user_sock); @@ -1108,9 +1178,6 @@ rtnl_close(&hip_nl_route); } - hip_uninit_hadb(); - hip_uninit_host_id_dbs(); - msg = hip_msg_alloc(); if (msg) { hip_build_user_hdr(msg, SO_HIP_DAEMON_QUIT, 0); @@ -1148,6 +1215,8 @@ /** * Initialize random seed. + * + * @return zero on success or negative on failure */ static int init_random_seed() { @@ -1172,6 +1241,11 @@ return err; } +/** + * Initialize certificates for the local host + * + * @return zero on success or negative on failure + */ static int hip_init_certs(void) { int err = 0; @@ -1241,6 +1315,11 @@ return err; } +/** + * find the first RSA-based host id + * + * @return the host id or NULL if none found + */ static struct hip_host_id_entry *hip_return_first_rsa(void) { hip_list_t *curr, *iter; === modified file 'hipd/input.c' --- hipd/input.c 2010-03-19 09:24:10 +0000 +++ hipd/input.c 2010-03-19 09:53:35 +0000 @@ -17,10 +17,7 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "input.h" #include "hadb.h" #include "oppdb.h" @@ -28,8 +25,12 @@ #include "keymat.h" #include "lib/core/crypto.h" #include "lib/core/builder.h" +#include "lib/core/hip_udp.h" +#include "lib/core/solve.h" +#include "lib/core/transform.h" +#include "lib/core/keylen.h" #include "dh.h" -#include "lib/core/misc.h" + #include "hidb.h" #include "cookie.h" #include "output.h" @@ -37,6 +38,7 @@ #include "netdev.h" #include "lib/tool/lutil.h" #include "lib/core/state.h" +#include "lib/core/hit.h" #include "oppdb.h" #include "registration.h" #include "esp_prot_hipd_msg.h" @@ -54,6 +56,10 @@ #include "lib/performance/performance.h" #endif +#ifdef CONFIG_HIP_BLIND +#include "lib/core/hostid.h" +#endif + /** * Verifies a HMAC. * @@ -1413,9 +1419,9 @@ hip_relay_add_rvs_to_ha(r1, entry); -#ifdef HIP_USE_ICE +#ifdef CONFIG_HIP_RVS hip_relay_handle_relay_to_in_client(r1, HIP_R1, r1_saddr, r1_daddr, r1_info, entry); -#endif +#endif /* CONFIG_HIP_RVS */ /* According to the section 8.6 of the base draft, we must first check * signature. */ @@ -2857,9 +2863,9 @@ HIP_ERROR("Couldn't get device ifindex of address\n"); } -#ifdef HIP_USE_ICE +#ifdef CONFIG_HIP_RVS hip_relay_handle_relay_to_in_client(r2, HIP_R2, r2_saddr, r2_daddr, r2_info, entry); -#endif +#endif /* CONFIG_HIP_RVS */ /* Copying address list from temp location in entry * "entry->peer_addr_list_to_be_added" */ hip_copy_peer_addrlist_changed(entry); === modified file 'hipd/input.h' --- hipd/input.h 2010-03-19 09:24:10 +0000 +++ hipd/input.h 2010-03-19 09:53:35 +0000 @@ -15,10 +15,7 @@ #ifndef HIP_HIPD_INPUT_H #define HIP_HIPD_INPUT_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #ifdef CONFIG_HIP_RVS #include "hiprelay.h" #endif @@ -37,22 +34,6 @@ struct in6_addr sin6_addr; }; -struct pseudo_header6 { - unsigned char src_addr[16]; - unsigned char dst_addr[16]; - uint32_t packet_length; - unsigned char zero[3]; - uint8_t next_hdr; -}; - -struct pseudo_header { - unsigned char src_addr[4]; - unsigned char dst_addr[4]; - uint8_t zero; - uint8_t protocol; - uint16_t packet_length; -}; - /** * Checks for illegal controls in a HIP packet Controls field. * === modified file 'hipd/keymat.c' --- hipd/keymat.c 2010-03-19 09:24:10 +0000 +++ hipd/keymat.c 2010-03-19 09:53:35 +0000 @@ -1,9 +1,9 @@ /** * @file - * This file contains KEYMAT handling functions for HIPL. - * Licence: GNU/GPL - * - * TODO: Doxygen documentation is incomplete + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * This file contains KEYMAT handling functions for HIPL * * @author Mika Kousa <mkousa#iki.fi> * @author Kristian Slavov <ksl#iki.fi> @@ -14,7 +14,21 @@ #define _BSD_SOURCE #include "keymat.h" +#include "lib/core/hit.h" +/** + * allocate and initialize a big enough key material buffer for + * drawing symmetric keys for HIP and ESP + * + * @param kij the diffie hellman session key + * @param kij_len the length of kij in bytes + * @param hash_len the length of the used hash + * @param smaller_hit smaller HIT + * @param bigger_hit bigger HIT + * @param I the I value from the puzzle + * @param J the J value from the puzzle + * @return the allocated buffer (caller deallocates) or NULL on failure + */ static uint8_t *hip_create_keymat_buffer(char *kij, size_t kij_len, size_t hash_len, struct in6_addr *smaller_hit, struct in6_addr *bigger_hit, @@ -57,6 +71,15 @@ return buffer; } +/** + * update keymat buffer and index after writing material to it + * + * @param keybuf a pointer to the key material + * @param Kold a the seed + * @param Kold_len length of Kold + * @param Kij_len length of the Kij + * @param cnt index value + */ static void hip_update_keymat_buffer(uint8_t *keybuf, uint8_t *Kold, size_t Kold_len, size_t Kij_len, uint8_t cnt) { === modified file 'hipd/keymat.h' --- hipd/keymat.h 2010-03-19 09:24:10 +0000 +++ hipd/keymat.h 2010-03-19 09:53:35 +0000 @@ -2,7 +2,7 @@ #define HIP_HIPD_KEYMAT_H #include "lib/core/list.h" -#include "lib/core/misc.h" + #include "lib/core/crypto.h" #include "lib/core/state.h" === modified file 'hipd/maintenance.c' --- hipd/maintenance.c 2010-03-03 13:16:18 +0000 +++ hipd/maintenance.c 2010-03-19 09:53:35 +0000 @@ -1,26 +1,30 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * Periodically handled "maintenance" actions are processed here by + * default roughly once in a second. These actions include + * retransmissions of lost HIP control packets, keepalives for NATs, + * heartbeats to detect connectivity problems, purging of opportunistic + * mode state, delaying of UPDATE triggering until addresses have stabilized + * and publishing of hostname/hit/ip mappings in a DHT. + * + * @brief Hipd maintenance loop + * + * @note When adding new functionality, make sure that the socket + * calls do not block because hipd is single threaded. */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "maintenance.h" #include "update.h" #include "heartbeat.h" #include "hipd.h" +#include "lib/core/hip_udp.h" #define FORCE_EXIT_COUNTER_START 5 @@ -45,7 +49,11 @@ static int hip_agent_add_lhits(void); /** - * Handle packet retransmissions. + * an iterator to handle packet retransmission for a given host association + * + * @param entry the host association which to handle + * @param current_time current time + * @return zero on success or negative on failure */ static int hip_handle_retransmission(hip_ha_t *entry, void *current_time) { @@ -115,6 +123,12 @@ } #ifdef CONFIG_HIP_OPPORTUNISTIC +/** + * scan for opportunistic connections that should time out + * and give up (fall back to normal TCP/IP) + * + * @return zero on success or negative on failure + */ static int hip_scan_opp_fallback(void) { int err = 0; @@ -130,7 +144,9 @@ #endif /** - * Find packets, that should be retransmitted. + * deliver pending retransmissions for all host associations + * + * @return zero on success or negative on failure */ static int hip_scan_retransmissions(void) { @@ -145,7 +161,9 @@ #ifdef CONFIG_HIP_AGENT /** - * Send one local HIT to agent, enumerative function. + * An enumerator to inform agent on a new local HIT + * + * @return zero on success or negative on failure */ static int hip_agent_add_lhit(struct hip_host_id_entry *entry, void *msg) { @@ -167,7 +185,9 @@ /** - * Send local HITs to agent. + * Send all local HITs to the GUI agent + * + * @return zero on success or negative on failure */ static int hip_agent_add_lhits(void) { @@ -216,7 +236,14 @@ } /** - * Filter packet trough agent. + * Filter packet trough agent + * + * @param msg the control packet to filter + * @param src_addr the source address of the packet + * @param dst_addr the destination ddress of the packet + * @param msg_info transport port information on the packet + * + * @return zero on success or negative on failure */ int hip_agent_filter(struct hip_common *msg, struct in6_addr *src_addr, @@ -264,7 +291,14 @@ } /** - * Send new status of given state to agent. + * inform agent on changes of in HADB state + * + * @param msg_type the type of the message + * @param data any kind of data to encapsulate inside + * a HIP parameter + * @param size the length of the @c data in bytes + * + * @return zero on success or negative on failure */ int hip_agent_update_status(int msg_type, void *data, size_t size) { @@ -299,7 +333,9 @@ } /** - * Update different items status to agent. + * Update agent on local HIT status + * + * @return zero on success or negative on failure */ int hip_agent_update(void) { @@ -311,7 +347,7 @@ /** * Periodic maintenance. * - * @return ... + * @return zero on success or negative on failure */ int hip_periodic_maintenance() { @@ -447,11 +483,23 @@ return err; } +/** + * get the current running status of firewall + * + * @return one if firewall is running or zero otherwise + * @todo this is redundant with hip_firewall_is_alive() + */ int hip_get_firewall_status() { return hip_firewall_status; } +/** + * + * get the current running status of firewall + * + * @return one if firewall is running or zero otherwise + */ int hip_firewall_is_alive() { #ifdef CONFIG_HIP_FIREWALL @@ -467,78 +515,17 @@ #endif // CONFIG_HIP_FIREWALL } -int hip_firewall_set_i2_data(int action, hip_ha_t *entry, - struct in6_addr *hit_s, - struct in6_addr *hit_r, - struct in6_addr *src, - struct in6_addr *dst) -{ - struct hip_common *msg = NULL; - struct sockaddr_in6 hip_firewall_addr; - int err = 0, n = 0; - HIP_IFEL(!(msg = HIP_MALLOC(HIP_MAX_PACKET, 0)), -1, "alloc\n"); - hip_msg_init(msg); - HIP_IFEL(hip_build_user_hdr(msg, action, 0), -1, - "Build hdr failed\n"); - - HIP_IFEL(hip_build_param_contents(msg, (void *) hit_r, HIP_PARAM_HIT, - sizeof(struct in6_addr)), -1, "build param contents failed\n"); - HIP_IFEL(hip_build_param_contents(msg, (void *) src, HIP_PARAM_HIT, - sizeof(struct in6_addr)), -1, "build param contents failed\n"); - - socklen_t alen = sizeof(hip_firewall_addr); - - bzero(&hip_firewall_addr, alen); - hip_firewall_addr.sin6_family = AF_INET6; - hip_firewall_addr.sin6_port = htons(HIP_FIREWALL_PORT); - hip_firewall_addr.sin6_addr = in6addr_loopback; - - // if (hip_get_firewall_status()) { - n = sendto(hip_firewall_sock_lsi_fd, (char *) msg, hip_get_msg_total_len(msg), - 0, (struct sockaddr *) &hip_firewall_addr, alen); - //} - - if (n < 0) { - HIP_DEBUG("Send to firewall failed str errno %s\n", strerror(errno)); - } - HIP_IFEL( n < 0, -1, "Sendto firewall failed.\n"); - - HIP_DEBUG("Sendto firewall OK.\n"); - -out_err: - if (msg) { - free(msg); - } - - return err; -} - -int hip_firewall_set_savah_status(int status) -{ - int n, err = 0; - struct sockaddr_in6 sock_addr; - struct hip_common *msg = NULL; - bzero(&sock_addr, sizeof(sock_addr)); - sock_addr.sin6_family = AF_INET6; - sock_addr.sin6_port = htons(HIP_FIREWALL_PORT); - sock_addr.sin6_addr = in6addr_loopback; - - HIP_IFEL(!(msg = HIP_MALLOC(HIP_MAX_PACKET, 0)), -1, "alloc\n"); - hip_msg_init(msg); - - hip_build_user_hdr(msg, status, 0); - - n = hip_sendto_user(msg, (struct sockaddr *) &sock_addr); - - HIP_IFEL(n < 0, 0, "sendto() failed\n"); - - if (err == 0) { - HIP_DEBUG("SEND SAVAH SERVER STATUS OK.\n"); - } -out_err: - return err; -} - +/** + * Update firewall on host association state. Currently used by the + * LSI and system-based opportunistic mode in the firewall. + * + * @param action SO_HIP_FW_UPDATE_DB or SO_HIP_FW_BEX_DONE + * @param entry the host association + * @param hit_s optional source HIT + * @param hit_r optional destination HIT + * + * @return zero on success or negative on failure + */ int hip_firewall_set_bex_data(int action, hip_ha_t *entry, struct in6_addr *hit_s, struct in6_addr *hit_r) { struct hip_common *msg = NULL; @@ -590,14 +577,14 @@ } /** - * This function calculates RTT and ... and then stores them to correct entry + * This function calculates RTT and then stores them to correct entry * * @param src HIT * @param dst HIT * @param time when sent * @param time when received * - * @return 0 if success negative otherwise + * @return zero on success or negative on failure */ int hip_icmp_statistics(struct in6_addr *src, struct in6_addr *dst, struct timeval *stval, struct timeval *rtval) @@ -641,6 +628,13 @@ return err; } +/** + * tell firewall to turn on or off the ESP relay mode + * + * @param action SO_HIP_OFFER_FULLRELAY or SO_HIP_CANCEL_FULLRELAY + * + * @return zero on success or negative on failure + */ int hip_firewall_set_esp_relay(int action) { struct hip_common *msg = NULL; === modified file 'hipd/nat.c' --- hipd/nat.c 2010-02-17 17:38:08 +0000 +++ hipd/nat.c 2010-03-19 09:53:35 +0000 @@ -254,9 +254,8 @@ */ hip_transform_suite_t hip_nat_set_control(hip_ha_t *entry, hip_transform_suite_t mode) { -#ifdef HIP_USE_ICE hip_ha_set_nat_mode(entry, &mode); -#endif + return 0; } === modified file 'hipd/nat.h' --- hipd/nat.h 2010-02-17 17:38:08 +0000 +++ hipd/nat.h 2010-03-19 09:53:35 +0000 @@ -27,15 +27,6 @@ * @todo Change this value. */ #define HIP_NAT_KEEP_ALIVE_INTERVAL 20 /** Port number for NAT traversal of hip control packets. */ -#define HIP_NAT_UDP_PORT 10500 -#define HIP_NAT_TURN_PORT 10500 - -/** For setting socket to listen for beet-udp packets. */ -#define HIP_UDP_ENCAP 100 -/** UDP encapsulation type. */ -#define HIP_UDP_ENCAP_ESPINUDP 2 -/** UDP encapsulation type. */ -#define HIP_UDP_ENCAP_ESPINUDP_NONIKE 1 extern HIP_HASHTABLE *hadb_hit; hip_transform_suite_t hip_get_nat_mode(hip_ha_t *entry); === modified file 'hipd/netdev.c' --- hipd/netdev.c 2010-03-19 09:24:10 +0000 +++ hipd/netdev.c 2010-03-19 09:53:35 +0000 @@ -21,18 +21,21 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include <net/if.h> #include <netinet/in.h> + +#include "config.h" #include "lib/tool/nlink.h" +#include "accessor.h" #include "netdev.h" #include "maintenance.h" #include "lib/dht/libhipdht.h" #include "lib/core/debug.h" #include "lib/tool/lutil.h" #include "lib/conf/hipconf.h" +#include "lib/core/hostsfiles.h" +#include "lib/core/hip_udp.h" +#include "lib/core/hit.h" #include "hipd.h" /** @@ -102,7 +105,7 @@ int ret = 0; ifr.ifr_ifindex = -1; - strncpy(ifr.ifr_name, device_name, (size_t) IFNAMSIZ); + strncpy(ifr.ifr_name, device_name, (size_t) IF_NAMESIZE); sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (ioctl(sock, SIOCGIFINDEX, &ifr) == 0) { @@ -825,8 +828,6 @@ * depending on dst_hit value. * If dst_hit is a HIT -> find LSI and hostname * If dst_hit is an LSI -> find HIT and hostname - * The natural place to handle this is either in the getaddrinfo or - * getendpointinfo function with AI_NUMERICHOST flag set. * We can fallback to e.g. DHT search if the mapping is not * found from local files.*/ === modified file 'hipd/netdev.h' --- hipd/netdev.h 2010-03-03 13:16:18 +0000 +++ hipd/netdev.h 2010-03-19 09:53:35 +0000 @@ -8,15 +8,12 @@ #include <sys/socket.h> #include <netinet/ip6.h> #include <openssl/rand.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/tool/nlink.h" #include "lib/core/list.h" #include "lib/core/debug.h" #include "lib/core/prefix.h" -#include "lib/core/misc.h" + #include "hit_to_ip.h" #ifdef CONFIG_HIP_MAEMO === modified file 'hipd/nsupdate.c' --- hipd/nsupdate.c 2010-02-17 17:38:08 +0000 +++ hipd/nsupdate.c 2010-03-19 09:53:35 +0000 @@ -24,12 +24,10 @@ #include <string.h> #include <sys/resource.h> // for getrlimit -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - +#include "config.h" #include "hidb.h" #include "nsupdate.h" +#include "lib/core/hit.h" // parameters for nsupdate.pl #define VAR_IPS "HIPD_IPS" === modified file 'hipd/oppdb.c' --- hipd/oppdb.c 2010-03-03 13:16:18 +0000 +++ hipd/oppdb.c 2010-03-19 09:53:35 +0000 @@ -1,24 +1,50 @@ -/* - * hipd oppdb.c - * - * Licence: GNU/GPL +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * Opportunistic mode databases for lib/opphip and HIP registration. The system-based + * opportunistic mode in the firewall uses also this functionality to trigger an + * opportunistic base base exchange. See the following publication on the details: + * + * <a href="http://www.iki.fi/miika/docs/ccnc09.pdf";> + * Miika Komu and Janne Lindqvist, Leap-of-Faith Security is Enough + * for IP Mobility, 6th Annual IEEE Consumer + * Communications & Networking Conference IEEE CCNC 2009, Las Vegas, + * Nevada, January 2009</a> + * + * The pseudo HIT is mentioned on multiple places in this file. When hipd sends + * the opportunistic I1, the destination HIT is NULL. For this reason, we don't + * know the Responder HIT until receiving the R2. During this unawareness period, + * we use a "pseudo HIT" to denote the Responder. It is calculated by extracting + * part of the IP address of the Responder and prefixing it with HIT prefix and some + * additional zeroes. Once the R1 received, the opportunistic database entry can + * be removed and the pseudo HIT becomes unnecessary. Consequtive opportunistic + * mode connections with the same Responder are cached and the pseudo HIT is not needed. + * + * The opportunistic mode supports also "fallback" which occurs with + * peers that do not support HIP. When the peer does not support HIP, + * hipd notices it after a certain time out in maintenance.c loop + * because there was no R1 response. The handlers in this function + * then send a "reject" message to the blocked opportunistic library + * process which means that it should proceed without HIP. Consequtive + * rejects are faster because they are cached. + * + * See firewall/opptcp.c extension on how the initial timeout can be + * reduced to a single round-trip time. + * * Authors: * - Bing Zhou <bingzhou@xxxxxxxxx> - * */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - -#ifdef CONFIG_HIP_OPPORTUNISTIC - +#include "config.h" #include "oppdb.h" #include "hadb.h" #include "accessor.h" +#include "lib/core/hit.h" #define HIP_LOCK_OPP_INIT(entry) #define HIP_UNLOCK_OPP_INIT(entry) @@ -54,6 +80,12 @@ hip_portpair_t *msg_info); static int hip_force_opptcp_fallback(hip_opp_block_t *entry, void *ips); +/** + * hashing function for the hashtable implementation + * + * @param a pointer to a hip_opp_block_t structure + * @return the calculated hash + */ static unsigned long hip_oppdb_hash_hit(const void *ptr) { hip_opp_block_t *entry = (hip_opp_block_t *) ptr; @@ -66,17 +98,30 @@ return *((unsigned long *) (void *) hash); } +/** + * matching function for the hashtable implementation + * + * @param ptr1 a pointer to a hip_opp_block_t structure + * @param ptr2 a pointer to a hip_opp_block_t structure + * @return zero on match or non-zero otherwise + */ static int hip_oppdb_match_hit(const void *ptr1, const void *ptr2) { return hip_hash_hit(ptr1) != hip_hash_hit(ptr2); } +/** + * expire an opportunistic connection + * + * @param opp_entry the entry to be expired + * @return zero on success or negative on error + */ int hip_oppdb_entry_clean_up(hip_opp_block_t *opp_entry) { int err = 0; - /* XX FIXME: this does not support multiple multiple opp - * connections: a better solution might be trash collection */ + /** @todo this does not support multiple multiple opp + connections: a better solution might be trash collection */ HIP_ASSERT(opp_entry); err = hip_del_peer_info(&opp_entry->peer_phit, @@ -86,6 +131,13 @@ return err; } +/** + * a for-each iterator function for the opportunistic database + * + * @param func a callback iterator function + * @param opaque an extra parameter to be passed to the callback + * @return zero on success and non-zero on error + */ int hip_for_each_opp(int (*func)(hip_opp_block_t *entry, void *opaq), void *opaque) { int i = 0, fail = 0; @@ -113,7 +165,11 @@ return fail; } -//void hip_hadb_delete_hs(struct hip_hit_spi *hs) +/** + * delete an opportunistic database entry + * + * @param entry the entry to be deleted + */ static void hip_oppdb_del_entry_by_entry(hip_opp_block_t *entry) { hip_opp_block_t *deleted; @@ -126,18 +182,38 @@ //HIP_FREE(entry); } +/** + * an iterator function for uninitializing the opportunistic database + * + * @param entry the entry to be uninitialized + * @param unused unused + * @return zero + */ static int hip_oppdb_uninit_wrap(hip_opp_block_t *entry, void *unused) { hip_oppdb_del_entry_by_entry(entry); return 0; } +/** + * uninitialize the whole opportunistic database + */ void hip_oppdb_uninit(void) { hip_for_each_opp(hip_oppdb_uninit_wrap, NULL); hip_ht_uninit(oppdb); + oppdb = NULL; } +/** + * Unblock a caller from the opportunistic library + * + * @param app_id the UDP port of the local library process + * @param opp_info information related to the opportunistic connection + * @param reject Zero if Responder supports HIP or one if Responder + * did not respond within a certain timeout (should fallback to TCP/IP). + * @return zero on success or negative on failure + */ static int hip_opp_unblock_app(const struct sockaddr_in6 *app_id, hip_opp_info_t *opp_info, int reject) { @@ -217,6 +293,13 @@ return err; } +/** + * unblock all opportunistic connections with a certain remote host + * + * @param entry the opportunistic mode connection + * @param ptr the pseudo HIT denoting the remote host + * @return zero on success or negative on error + */ static int hip_oppdb_unblock_group(hip_opp_block_t *entry, void *ptr) { hip_opp_info_t *opp_info = (hip_opp_info_t *) ptr; @@ -235,6 +318,11 @@ return err; } +/** + * create a opportunistic mode database entry + * + * @return the created databased entry (caller deallocates) + */ static hip_opp_block_t *hip_create_opp_block_entry(void) { hip_opp_block_t *entry = NULL; @@ -247,17 +335,23 @@ memset(entry, 0, sizeof(*entry)); -//INIT_LIST_HEAD(&entry->next_entry); - HIP_LOCK_OPP_INIT(entry); - //atomic_set(&entry->refcnt,0); time(&entry->creation_time); HIP_UNLOCK_OPP_INIT(entry); return entry; } -//int hip_hadb_add_peer_info(hip_hit_t *peer_hit, struct in6_addr *peer_addr) +/** + * add an opportunistic mode connection entry to the database + * + * @param phit_peer the pseudo HIT of peer + * @param hit_our local HIT + * @param ip_peer remote IP address + * @param ip_our local IP address + * @param caller the UDP port of the local library process + * @return zero on success or negative on failure + */ static int hip_oppdb_add_entry(const hip_hit_t *phit_peer, const hip_hit_t *hit_our, const struct in6_addr *ip_peer, @@ -292,11 +386,17 @@ return err; } +/** + * initialize the opportunistic database + */ void hip_init_opp_db(void) { oppdb = hip_ht_init(hip_oppdb_hash_hit, hip_oppdb_match_hit); } +/** + * dump the contents of the database + */ static void hip_oppdb_dump(void) { int i; @@ -321,6 +421,14 @@ HIP_DEBUG("end oppdb dump\n"); } +/** + * fetch an hadb entry corresponding to a pseudo HIT + * + * @param init_hit the local HIT of the Initiator + * @param resp_addr the remote IP address of the Responder from + * which to calculate the pseudo HIT + * @return a host assocition or NULL if not found + */ hip_ha_t *hip_oppdb_get_hadb_entry(hip_hit_t *init_hit, struct in6_addr *resp_addr) { @@ -341,6 +449,15 @@ return entry_tmp; } +/** + * find a host association based on I1 or R1 message + * + * @param msg the I1 or R2 message + * @param src_addr the source address of the message + * @param dst_addr the destination address of the message + * @param msg_info the transport layer port numbers (UDP tunnel) + * @return the host association or NULL if not found + */ hip_ha_t *hip_oppdb_get_hadb_entry_i1_r1(struct hip_common *msg, struct in6_addr *src_addr, struct in6_addr *dst_addr, @@ -365,6 +482,16 @@ return entry; } +/** + * process an incoming R1 packet + * + * @param msg the R1 packet + * @param src_addr the source address of the message + * @param dst_addr the destination address of the message + * @param opp_entry the opportunistic database entry + * @param msg_info the transport layer port numbers (UDP tunnel) + * @return zero on success or negative on failure + */ static int hip_receive_opp_r1(struct hip_common *msg, struct in6_addr *src_addr, struct in6_addr *dst_addr, @@ -445,6 +572,15 @@ return err; } +/** + * add an entry to the opportunistic mode dabase and host association + * database (with pseudo HIT) + * + * @param dst_ip the remote IP address of the Responder + * @param hit_our the local HIT of the Initiator + * @param caller the UDP port of the local library process + * @return the created host association + */ hip_ha_t *hip_opp_add_map(const struct in6_addr *dst_ip, const struct in6_addr *hit_our, const struct sockaddr_in6 *caller) @@ -501,7 +637,13 @@ } /** - * No description. + * Trigger opportunistic I1 to obtain the HIT of the Responder. + * The TCP optimization may also be used if it is requested. + * + * @param msg contains information on the Responder's IP address + * and on the use of the TCP optimization + * @param src the UDP port number of the calling library process + * @return zero on success or negative on failure */ int hip_opp_get_peer_hit(struct hip_common *msg, const struct sockaddr_in6 *src) @@ -740,10 +882,14 @@ return err; } -/* +/** * Used by opportunistic tcp option to force an application fallback * immediately (without timeout) to non-hip communications. This occurs * when the firewall detects that peer does not support HIP. + * + * @param entry the opportunistic mode connection entry + * @param data in6_addr the IP address of the Responder + * @return zero on success or negative on failure */ static int hip_force_opptcp_fallback(hip_opp_block_t *entry, void *data) { @@ -769,6 +915,14 @@ return err; } +/** + * check if it is time for an opportunistic connection to + * time out and make it happen when needed + * + * @param entry the database entry for the opportunistic connection + * @param current_time the current time + * @return zero on success or negative on failure + */ int hip_handle_opp_fallback(hip_opp_block_t *entry, void *current_time) { @@ -777,7 +931,7 @@ struct in6_addr *addr; //HIP_DEBUG("now=%d e=%d\n", *now, entry->creation_time); -#if defined(CONFIG_HIP_AGENT) && defined(CONFIG_HIP_OPPORTUNISTIC) +#ifdef CONFIG_HIP_AGENT /* If agent is prompting user, let's make sure that * the death counter in maintenance does not expire */ if (hip_agent_is_alive()) { @@ -807,6 +961,13 @@ return err; } +/** + * reject an opportunistic mode connection + * + * @param entry the connection to reject + * @param data the remote IP address of the Responder + * @return zero on success or negative on failure + */ int hip_handle_opp_reject(hip_opp_block_t *entry, void *data) { int err = 0; @@ -828,13 +989,12 @@ } /** - * hip_oppdb_find_byip: - * Seeks an ip within the oppdb hash table. - * If the ip is found in the table, that host is not HIP capable. + * check if a remote host is not capable of HIP * * @param ip_peer: pointer to the ip of the host to check whether - * it is HIP capable - * @return pointer to the entry if the ip is found in the table; NULL otherwise + * it is HIP capable or not + * @return pointer to the entry if the remote host does not definitely support HIP or + * NULL if it is potentially HIP capable */ hip_opp_block_t *hip_oppdb_find_by_ip(const struct in6_addr *ip_peer) { @@ -842,6 +1002,9 @@ hip_opp_block_t *this, *ret = NULL; hip_list_t *item, *tmp; + if (oppdb == NULL) + return NULL; + HIP_LOCK_HT(&opp_db); list_for_each_safe(item, tmp, oppdb, i) { @@ -856,5 +1019,3 @@ HIP_UNLOCK_HT(&opp_db); return ret; } - -#endif /* CONFIG_HIP_OPPORTUNISTIC */ === modified file 'hipd/oppdb.h' --- hipd/oppdb.h 2010-03-03 13:16:18 +0000 +++ hipd/oppdb.h 2010-03-19 09:53:35 +0000 @@ -13,7 +13,7 @@ #include <sys/socket.h> #include <sys/un.h> #include "lib/core/debug.h" -#include "lib/core/misc.h" + #include "hidb.h" #include "lib/core/hashtable.h" #include "lib/core/builder.h" @@ -65,4 +65,5 @@ void *opaque); int hip_handle_opp_reject(hip_opp_block_t *entry, void *ips); -#endif /* HIP_HADB_H */ + +#endif /* HIP_HIPD_OPPDB_H */ === modified file 'hipd/oppipdb.c' --- hipd/oppipdb.c 2010-02-17 17:38:08 +0000 +++ hipd/oppipdb.c 2010-03-19 09:53:35 +0000 @@ -1,5 +1,7 @@ /** @file - * oppipdb.c: + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * * This file defines handling functions for opportunistic mode to remember * IP's which are not HIP capable. This means faster communication in second * connection attempts to these hosts. Otherwise it would always take the same @@ -8,16 +10,12 @@ * * @author Antti Partanen * @author Alberto Garcia - * @note Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a>. */ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #ifdef CONFIG_HIP_OPPORTUNISTIC #include "oppipdb.h" @@ -33,7 +31,6 @@ static void hip_oppipdb_uninit_wrap(hip_oppip_t *entry, void *unused); /** - * hip_oppipdb_hash_ip: * Generates the hash information that is used to index the table * * @param ptr: pointer to the ip address used to make the hash @@ -65,7 +62,6 @@ } /** - * hip_for_each_oppip: * Map function @func to every entry in the oppipdb hash table * * @param func: mapper function to apply to all entries @@ -101,7 +97,6 @@ } /** - * hip_oppipdb_del_entry_by_entry: * Deletes an entry that is present in oppipdb hash table * * @param entry: pointer to the entry to delete @@ -115,7 +110,6 @@ } /** - * hip_oppipdb_uninit_wrap: * Wrap function for hip_oppipdb_del_entry_by_entry() * * @param entry: pointer to the entry to delete @@ -129,7 +123,6 @@ } /** - * hip_oppipdb_uninit: * Deletes the whole oppipdb hash table */ void hip_oppipdb_uninit(void) @@ -138,7 +131,6 @@ } /** - * hip_create_oppip_entry: * Allocates and initilizes the node to store the information * in the oppipdb hash table * @@ -160,7 +152,6 @@ } /** - * hip_oppipdb_add_entry: * Adds a new entry to the oppipdb hash table. * This table stores the ip addresses of the hosts that are not HIP capable. * @@ -191,7 +182,6 @@ } /** - * hip_init_oppip_db: * Creates and initializes the oppipdb hash table * * @return 0 on success @@ -204,7 +194,6 @@ #if 0 /** - * hip_oppipdb_dump: * Dumps the whole oppipdb hash table for monitoring purposes */ static void hip_oppipdb_dump(void) @@ -229,7 +218,6 @@ #endif /** - * hip_oppipdb_find_byip: * Seeks an ip within the oppipdb hash table. * If the ip is found in the table, that host is not HIP capable. * @@ -254,7 +242,6 @@ } /** - * hip_oppipdb_delentry: * This function should be called after receiving an R1 from the peer and after * a successful base exchange in the opportunistic mode. It checks whether an * address of a HIP capable host is found from database. If the address is === modified file 'hipd/output.c' --- hipd/output.c 2010-03-19 09:24:10 +0000 +++ hipd/output.c 2010-03-19 09:53:35 +0000 @@ -16,10 +16,7 @@ #include <netinet/icmp6.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "output.h" #ifdef CONFIG_HIP_PERFORMANCE #include "lib/performance/performance.h" @@ -29,48 +26,14 @@ #include "i3/i3_client/i3_client_id.h" #endif +#include "lib/core/hip_udp.h" +#include "lib/tool/checksum.h" + enum number_dh_keys_t { ONE, TWO }; enum number_dh_keys_t number_dh_keys = TWO; /** - * Standard BSD internet checksum routine from nmap - * for calculating the checksum field of the TCP header - */ -unsigned short in_cksum(uint16_t *ptr, int nbytes) -{ - register uint32_t sum; - uint16_t oddbyte; - register uint16_t answer; - - /* - * Our algorithm is simple, using a 32-bit accumulator (sum), - * we add sequential 16-bit words to it, and at the end, fold back - * all the carry bits from the top 16 bits into the lower 16 bits. - */ - sum = 0; - while (nbytes > 1) { - sum += *ptr++; - nbytes -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nbytes == 1) { - oddbyte = 0; /* make sure top half is zero */ - *((u_char *) &oddbyte) = *(u_char *) ptr; /* one byte only */ - sum += oddbyte; - } - - /* - * Add back carry outs from top 16 bits to low 16 bits. - */ - sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* ones-complement, then truncate to 16 bits */ - return answer; -} - -/** * @brief Sends a TCP packet through a raw socket. * * @param hdr @@ -269,6 +232,7 @@ * the peer. The src and dst ports are included in this parameter * @return nothing */ +#ifdef CONFIG_HIP_OPPORTUNISTIC static void hip_send_opp_tcp_i1(hip_ha_t *entry) { int ipType = !IN6_IS_ADDR_V4MAPPED(&entry->peer_addr); @@ -344,6 +308,7 @@ send_tcp_packet(&bytes[0], hdr_size + 4 * tcphdr->doff, 6, hip_raw_sock_output_v6, 1, 0); } } +#endif /* CONFIG_HIP_OPPORTUNISTIC */ /** * Sends an I1 packet to the peer. Used internally by hip_send_i1 @@ -403,6 +368,7 @@ err = 0; } +#ifdef CONFIG_HIP_OPPORTUNISTIC /*send the TCP SYN_i1 packet*/ if (hip_get_opportunistic_tcp_status() && hit_is_opportunistic_hit(dst_hit)) { @@ -410,6 +376,7 @@ usleep(50); hip_send_opp_tcp_i1(entry); } +#endif /* CONFIG_HIP_OPPORTUNISTIC */ return err; } === modified file 'hipd/output.h' --- hipd/output.h 2010-02-17 17:38:08 +0000 +++ hipd/output.h 2010-03-19 09:53:35 +0000 @@ -17,14 +17,11 @@ #include <unistd.h> #include <string.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "dh.h" #include "hidb.h" #include "hadb.h" -#include "lib/core/misc.h" + #include "lib/core/builder.h" #include "cookie.h" #include "close.h" === modified file 'hipd/pfkeyapi.c' --- hipd/pfkeyapi.c 2010-03-19 09:24:10 +0000 +++ hipd/pfkeyapi.c 2010-03-19 09:53:35 +0000 @@ -8,16 +8,11 @@ /* required for caddr_t */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - -#ifdef CONFIG_HIP_PFKEY -#include <libinet6/include/net/pfkeyv2.h> -#include </usr/include/linux/pfkeyv2.h> -#include </usr/include/linux/ipsec.h> +#include "config.h" #include "lib/ipsec/libpfkey.h" #include "pfkeyapi.h" +#include "lib/core/hip_udp.h" +#include "lib/core/keylen.h" // FIXME: This must be turned to BEET when BEET will be supported by pfkey as well @@ -441,5 +436,3 @@ HIP_DEBUG("\n"); return 0; } - -#endif /* CONFIG_HIP_PFKEY */ === modified file 'hipd/pfkeyapi.h' --- hipd/pfkeyapi.h 2010-02-17 13:08:39 +0000 +++ hipd/pfkeyapi.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,7 @@ #ifndef HIP_HIPD_PFKEYAPI_H #define HIP_HIPD_PFKEYAPI_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/tool/xfrmapi.h" #endif /* HIP_HIPD_PFKEYAPI_H */ === modified file 'hipd/registration.c' --- hipd/registration.c 2010-02-17 17:38:08 +0000 +++ hipd/registration.c 2010-03-19 09:53:35 +0000 @@ -14,6 +14,7 @@ #define _BSD_SOURCE #include "registration.h" +#include "hadb.h" /** * Pending request lifetime. Pending requests are created when the requester === modified file 'hipd/registration.h' --- hipd/registration.h 2010-02-17 17:38:08 +0000 +++ hipd/registration.h 2010-03-19 09:53:35 +0000 @@ -14,7 +14,6 @@ #ifndef HIP_HIPD_REGISTRATION_H #define HIP_HIPD_REGISTRATION_H -#include "lib/core/misc.h" #include "lib/core/builder.h" // For lifetime conversions. #include "lib/core/protodefs.h" // For service type values and hip_ha_t #ifndef __KERNEL__ === modified file 'hipd/update.c' --- hipd/update.c 2010-03-19 09:25:52 +0000 +++ hipd/update.c 2010-03-19 09:53:35 +0000 @@ -13,13 +13,12 @@ /* requiread for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "update.h" #include "lib/core/protodefs.h" +#include "lib/core/hip_udp.h" +#include "lib/core/solve.h" #include "netdev.h" #include "lib/core/builder.h" #include "update_legacy.h" === modified file 'hipd/user.c' --- hipd/user.c 2010-03-19 09:24:10 +0000 +++ hipd/user.c 2010-03-19 09:53:35 +0000 @@ -16,13 +16,13 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" +#include "accessor.h" #include "user.h" #include "esp_prot_anchordb.h" #include "lib/dht/libhipdht.h" +#include "lib/core/hostid.h" +#include "lib/core/hip_udp.h" #include "hipd.h" int hip_sendto_user(const struct hip_common *msg, const struct sockaddr *dst) @@ -46,7 +46,6 @@ int hip_handle_user_msg(hip_common_t *msg, struct sockaddr_in6 *src) { hip_hit_t *src_hit = NULL, *dst_hit = NULL; - in6_addr_t *dst_ip = NULL; hip_ha_t *entry = NULL; int err = 0, msg_type = 0, n = 0, len = 0, reti = 0; int access_ok = 0, is_root = 0; @@ -353,8 +352,16 @@ hip_opendht_sock_hit = init_dht_gateway_socket_gw(hip_opendht_sock_hit, opendht_serving_gateway); hip_opendht_hit_sent = STATE_OPENDHT_IDLE; } - hip_init_dht_sockets(&hip_opendht_sock_fqdn, &hip_opendht_fqdn_sent); - hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent); + ret = hip_init_dht_sockets(&hip_opendht_sock_fqdn, &hip_opendht_fqdn_sent); + if (ret < 0) { + close(hip_opendht_sock_fqdn); + hip_opendht_sock_fqdn = -1; + } + ret = hip_init_dht_sockets(&hip_opendht_sock_hit, &hip_opendht_hit_sent); + if (ret < 0) { + close(hip_opendht_sock_hit); + hip_opendht_sock_hit = -1; + } } else { HIP_DEBUG("Error in changing the serving gateway!"); } @@ -702,6 +709,7 @@ struct hip_reg_request *reg_req = NULL; hip_pending_request_t *pending_req = NULL; uint8_t *reg_types = NULL; + in6_addr_t *dst_ip = NULL; int i = 0, type_count = 0; int opp_mode = 0; int add_to_global = 0; @@ -1257,12 +1265,10 @@ if (nat_port) { HIP_DEBUG("Setting local NAT port\n"); hip_set_local_nat_udp_port(nat_port->port); - // We need to recreate the NAT UDP sockets to bind to the new port. - close(hip_nat_sock_output_udp); + /* We need to recreate only the input socket to bind to the new + port. Output port must be left intact as it is a raw socket */ close(hip_nat_sock_input_udp); - hip_nat_sock_output_udp = 0; hip_nat_sock_input_udp = 0; - hip_create_nat_sock_udp(&hip_nat_sock_output_udp, 0, 1); hip_create_nat_sock_udp(&hip_nat_sock_input_udp, 0, 0); } else { HIP_DEBUG("Setting peer NAT port\n"); === modified file 'hipd/user_ipsec_hipd_msg.c' --- hipd/user_ipsec_hipd_msg.c 2010-02-17 14:11:29 +0000 +++ hipd/user_ipsec_hipd_msg.c 2010-03-19 09:53:35 +0000 @@ -14,6 +14,9 @@ #define _BSD_SOURCE #include "user_ipsec_hipd_msg.h" +#include "hipd.h" +#include "init.h" +#include "user_ipsec_sadb_api.h" #include "lib/core/builder.h" /** === modified file 'i3/i3_client/http.c' --- i3/i3_client/http.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/http.c 2010-03-19 09:53:35 +0000 @@ -17,6 +17,7 @@ #include <sys/types.h> #include <string.h> #include <errno.h> +#include <arpa/inet.h> #ifndef _WIN32 #include <unistd.h> #endif === modified file 'i3/i3_client/i3_client_context.c' --- i3/i3_client/i3_client_context.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/i3_client_context.c 2010-03-19 09:53:35 +0000 @@ -15,6 +15,7 @@ #include <string.h> #include <sys/types.h> /* basic system data types */ #include <time.h> /* timespec{} for pselect() */ +#include <arpa/inet.h> #ifndef _WIN32 #include <unistd.h> #include <sys/errno.h> === modified file 'i3/i3_client/i3_client_pkt.c' --- i3/i3_client/i3_client_pkt.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/i3_client_pkt.c 2010-03-19 09:53:35 +0000 @@ -10,6 +10,7 @@ #include <string.h> #include <sys/types.h> /* basic system data types */ #include <time.h> /* timespec{} for pselect() */ +#include <arpa/inet.h> #ifndef _WIN32 #include <sys/time.h> /* timeval{} for select() */ #include <sys/errno.h> === modified file 'i3/i3_client/i3_client_trigger.c' --- i3/i3_client/i3_client_trigger.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/i3_client_trigger.c 2010-03-19 09:53:35 +0000 @@ -18,10 +18,7 @@ #include <sys/time.h> #endif -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "../i3/i3.h" #include "../i3/i3_fun.h" === modified file 'i3/i3_client/i3server_list.c' --- i3/i3_client/i3server_list.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/i3server_list.c 2010-03-19 09:53:35 +0000 @@ -13,6 +13,7 @@ #include <math.h> #include <stdio.h> #include <stdlib.h> +#include <arpa/inet.h> #ifndef _WIN32 #include <pthread.h> #endif === modified file 'i3/i3_client/ping.c' --- i3/i3_client/ping.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/ping.c 2010-03-19 09:53:35 +0000 @@ -3,6 +3,7 @@ #include <sys/types.h> #include <string.h> +#include <arpa/inet.h> #ifndef _WIN32 #include <unistd.h> #endif === modified file 'i3/i3_client/ping_thread.c' --- i3/i3_client/ping_thread.c 2010-02-17 17:38:08 +0000 +++ i3/i3_client/ping_thread.c 2010-03-19 09:53:35 +0000 @@ -11,6 +11,7 @@ #include <stdio.h> +#include <arpa/inet.h> #include <errno.h> #ifndef _WIN32 #include <pthread.h> === modified file 'lib/android/regex.c' --- lib/android/regex.c 2010-02-18 14:58:39 +0000 +++ lib/android/regex.c 2010-03-19 09:53:35 +0000 @@ -27,9 +27,7 @@ #undef _GNU_SOURCE #define _GNU_SOURCE -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif +#include "config.h" /* We need this for `regex.h', and perhaps for the Emacs include files. */ #include <sys/types.h> === modified file 'lib/conf/hipconf.c' --- lib/conf/hipconf.c 2010-03-03 13:16:18 +0000 +++ lib/conf/hipconf.c 2010-03-19 09:53:35 +0000 @@ -35,15 +35,17 @@ /* required for ifreq */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include <sys/ioctl.h> +#include "config.h" #include "lib/core/builder.h" #include "lib/core/debug.h" +#include "lib/core/straddr.h" #include "hipconf.h" #include "lib/core/prefix.h" #include "lib/dht/libhipdht.h" +#include "lib/core/hostid.h" +#include "lib/core/message.h" +#include "lib/core/crypto.h" /** * TYPE_ constant list, as an index for each action_handler function. @@ -117,13 +119,8 @@ "new hi anon|pub rsa|dsa filebasename keylen\n" "new|add hi default (HI must be created as root)\n" "new hi default rsa_keybits dsa_keybits\n" -#ifdef CONFIG_HIP_ICOOKIE - "get|inc|dec|new puzzle all|<hit>\n" - "set puzzle all|<hit> new_value\n" -#else "get|inc|dec|new puzzle all\n" "set puzzle all new_value\n" -#endif "bos all\n" "nat none|plain-udp\n" "nat port local <port>\n" === modified file 'lib/conf/hipconf.h' --- lib/conf/hipconf.h 2010-02-17 17:38:08 +0000 +++ lib/conf/hipconf.h 2010-03-19 09:53:35 +0000 @@ -15,11 +15,9 @@ #ifndef HIP_LIB_CONF_HIPCONF_H #define HIP_LIB_CONF_HIPCONF_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #include <stdlib.h> + +#include "config.h" #include "lib/core/protodefs.h" /* @@ -84,6 +82,8 @@ # opp normal|advanced|none\n\ # transform order 213 # crypto preference order (1=AES, 2=3DES, 3=NULL)\n\ nat plain-udp # use UDP capsulation (for NATted environments)\n\ +#nat port local 11111 # change local default UDP port\n\ +#nat port peer 22222 # change local peer UDP port\n\ debug medium # debug verbosity: all, medium or none\n" #define HOSTS_FILE "/etc/hosts" === modified file 'lib/core/builder.c' --- lib/core/builder.c 2010-03-19 09:24:10 +0000 +++ lib/core/builder.c 2010-03-19 09:53:35 +0000 @@ -68,13 +68,12 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include <config.h> -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "builder.h" #include "hipd/input.h" #include "lib/core/crypto.h" +#include "lib/core/hostid.h" +#include "lib/tool/checksum.h" /* Not needed, already defined in netinet/in.h */ /* #define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } */ @@ -2007,93 +2006,6 @@ } /** - * Calculates the checksum of a HIP packet with pseudo-header. - * - * @param data a pointer to a hip_common structure - * @param src The source address of the packet as a sockaddr_in or sockaddr_in6 - * structure in network byte order. IPv6 mapped addresses are not supported. - * @param dst The destination address of the packet as a sockaddr_in or sockaddr_in6 - * structure in network byte order. IPv6 mapped addresses are not supported. - * @return the checksum - * @note Checksumming is from Boeing's HIPD. - */ -uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr *dst) -{ - uint16_t checksum = 0; - unsigned long sum = 0; - int count = 0, length = 0; - unsigned short *p = NULL; /* 16-bit */ - struct pseudo_header pseudoh; - struct pseudo_header6 pseudoh6; - uint32_t src_network, dst_network; - struct in6_addr *src6, *dst6; - struct hip_common *hiph = (struct hip_common *) data; - - if (src->sa_family == AF_INET) { - /* IPv4 checksum based on UDP-- Section 6.1.2 */ - src_network = ((struct sockaddr_in *) src)->sin_addr.s_addr; - dst_network = ((struct sockaddr_in *) dst)->sin_addr.s_addr; - - memset(&pseudoh, 0, sizeof(struct pseudo_header)); - memcpy(&pseudoh.src_addr, &src_network, 4); - memcpy(&pseudoh.dst_addr, &dst_network, 4); - pseudoh.protocol = IPPROTO_HIP; - length = (hiph->payload_len + 1) * 8; - pseudoh.packet_length = htons(length); - - count = sizeof(struct pseudo_header); /* count always even number */ - p = (unsigned short *) &pseudoh; - } else { - /* IPv6 checksum based on IPv6 pseudo-header */ - src6 = &((struct sockaddr_in6 *) src)->sin6_addr; - dst6 = &((struct sockaddr_in6 *) dst)->sin6_addr; - - memset(&pseudoh6, 0, sizeof(struct pseudo_header6)); - memcpy(&pseudoh6.src_addr[0], src6, 16); - memcpy(&pseudoh6.dst_addr[0], dst6, 16); - length = (hiph->payload_len + 1) * 8; - pseudoh6.packet_length = htonl(length); - pseudoh6.next_hdr = IPPROTO_HIP; - - count = sizeof(struct pseudo_header6); /* count always even number */ - p = (unsigned short *) &pseudoh6; - } - /* - * this checksum algorithm can be found - * in RFC 1071 section 4.1 - */ - - /* sum the pseudo-header */ - /* count and p are initialized above per protocol */ - while (count > 1) { - sum += *p++; - count -= 2; - } - - /* one's complement sum 16-bit words of data */ - HIP_DEBUG("Checksumming %d bytes of data.\n", length); - count = length; - p = (unsigned short *) data; - while (count > 1) { - sum += *p++; - count -= 2; - } - /* add left-over byte, if any */ - if (count > 0) { - sum += (unsigned char) *p; - } - - /* Fold 32-bit sum to 16 bits */ - while (sum >> 16) { - sum = (sum & 0xffff) + (sum >> 16); - } - /* take the one's complement of the sum */ - checksum = ~sum; - - return checksum; -} - -/** * sanity checking for a HIP control packet originating from the network * * @param src The source address of the packet as a sockaddr_in or sockaddr_in6 @@ -2134,14 +2046,9 @@ /** @todo handle the RVS case better. */ if (ipv6_addr_any(&hip_common->hitr)) { /* Required for e.g. BOS */ - HIP_DEBUG("Received opportunistic HIT\n"); + HIP_DEBUG("Received a connection to opportunistic HIT\n"); } else { -#ifdef CONFIG_HIP_RVS - HIP_DEBUG("Received HIT is ours or we are RVS\n"); -#else - HIP_IFEL(!hip_hidb_hit_is_our(&hip_common->hitr), -EFAULT, - "Receiver HIT is not ours\n"); -#endif /* CONFIG_HIP_RVS */ + HIP_DEBUG_HIT("Received a connection to HIT", &hip_common->hitr); } /* Check checksum. */ @@ -4888,3 +4795,41 @@ return err; } + +/** + * calculate a digest over given data + * @param type the type of digest, e.g. "sha1" + * @param in the beginning of the data to be digested + * @param in_len the length of data to be digested in octets + * @param out the digest + * + * @note out should be long enough to hold the digest. This cannot be + * checked! + * + * @return 0 on success and negative on error. + */ +int hip_build_digest(const int type, const void *in, int in_len, void *out) +{ + SHA_CTX sha; + MD5_CTX md5; + + switch (type) { + case HIP_DIGEST_SHA1: + SHA1_Init(&sha); + SHA1_Update(&sha, in, in_len); + SHA1_Final(out, &sha); + break; + + case HIP_DIGEST_MD5: + MD5_Init(&md5); + MD5_Update(&md5, in, in_len); + MD5_Final(out, &md5); + break; + + default: + HIP_ERROR("Unknown digest: %x\n", type); + return -EFAULT; + } + + return 0; +} === modified file 'lib/core/builder.h' --- lib/core/builder.h 2010-03-19 09:24:10 +0000 +++ lib/core/builder.h 2010-03-19 09:53:35 +0000 @@ -15,10 +15,6 @@ #include <openssl/dsa.h> #endif -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif /* HAVE_CONFIG_H */ - #ifdef __KERNEL__ # include "usercompat.h" # include "protodefs.h" @@ -28,7 +24,9 @@ # include "misc.h" # include "icomm.h" # include "certtools.h" +# include "config.h" #endif +#include "debug.h" #include "hipd/registration.h" #include "state.h" @@ -191,7 +189,6 @@ struct sockaddr *src, struct sockaddr *dst, int len); -uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr *dst); int hip_check_userspace_msg(const struct hip_common *); int hip_check_userspace_msg_type(const struct hip_common *); void hip_dump_msg(const struct hip_common *); @@ -310,5 +307,6 @@ const in_port_t port, hip_tlv_type_t hipparam); struct in6_addr *hip_get_locator_item_address(void *item); +int hip_build_digest(const int type, const void *in, int in_len, void *out); #endif /* HIP_LIB_CORE_BUILDER_H */ === modified file 'lib/core/certtools.c' --- lib/core/certtools.c 2010-03-03 13:16:18 +0000 +++ lib/core/certtools.c 2010-03-19 09:53:35 +0000 @@ -8,6 +8,8 @@ #define _BSD_SOURCE #include "certtools.h" +#include "straddr.h" +#include "lib/core/crypto.h" /******************************************************************************* * FUNCTIONS FOR SPKI * === modified file 'lib/core/certtools.h' --- lib/core/certtools.h 2010-02-17 17:38:08 +0000 +++ lib/core/certtools.h 2010-03-19 09:53:35 +0000 @@ -22,13 +22,11 @@ #include <openssl/conf.h> #include <openssl/x509.h> #include <openssl/x509v3.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ +#include "config.h" #include "debug.h" #include "ife.h" -#include "misc.h" + #include "hashtable.h" /** Defines */ === modified file 'lib/core/crypto.c' --- lib/core/crypto.c 2010-03-19 09:24:10 +0000 +++ lib/core/crypto.c 2010-03-19 09:53:35 +0000 @@ -31,11 +31,9 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "crypto.h" +#include "keylen.h" #ifdef CONFIG_HIP_PERFORMANCE #include "lib/performance/performance.h" @@ -1113,3 +1111,14 @@ out_err: return err; } + +/** + * get random bytes + * + * @param buf a buffer where to write random bytes + * @param n write n bytes to @c buf + */ +void get_random_bytes(void *buf, int n) +{ + RAND_bytes(buf, n); +} === modified file 'lib/core/crypto.h' --- lib/core/crypto.h 2010-03-19 09:24:10 +0000 +++ lib/core/crypto.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,6 @@ #ifndef HIP_LIB_CORE_CRYPTO_H #define HIP_LIB_CORE_CRYPTO_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #include <sys/time.h> #include <time.h> #include <openssl/dsa.h> @@ -26,8 +22,10 @@ #include <string.h> #include <netinet/in.h> +#include "config.h" #include "hipd/hidb.h" #include "lib/core/debug.h" +#include "lib/core/transform.h" #include "lib/core/ife.h" #include "hipd/hadb.h" #define HIP_DSA_SIG_SIZE 41 /* T(1) + R(20) + S(20) from RFC 2536 */ @@ -103,5 +101,6 @@ int hip_write_hmac(int type, const void *key, void *in, int in_len, void *out); int hip_crypto_encrypted(void *data, const void *iv, int enc_alg, int enc_len, void *enc_key, int direction); +void get_random_bytes(void *buf, int n); #endif /* HIP_LIB_CORE_CRYPTO_H */ === modified file 'lib/core/debug.c' --- lib/core/debug.c 2010-03-03 13:16:18 +0000 +++ lib/core/debug.c 2010-03-19 09:53:35 +0000 @@ -49,11 +49,9 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "debug.h" +#include "straddr.h" #include "lib/tool/lutil.h" #include "lib/conf/hipconf.h" === modified file 'lib/core/debug.h' --- lib/core/debug.h 2010-03-03 13:16:18 +0000 +++ lib/core/debug.h 2010-03-19 09:53:35 +0000 @@ -9,10 +9,7 @@ #include <stdlib.h> #include <assert.h> #include <netinet/in.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "protodefs.h" #include "prefix.h" #include "ife.h" === added file 'lib/core/filemanip.c' --- lib/core/filemanip.c 1970-01-01 00:00:00 +0000 +++ lib/core/filemanip.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,199 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief file manipulation tools + * + * @author Miika Komu <miika@xxxxxx> + */ + +#include "filemanip.h" + +#include <unistd.h> + +#include "config.h" +#include "crypto.h" + +/** + * get rid of a lock file + * + * @param filename the file name of the lock file + * @return zero on success and negative on error + */ +int hip_remove_lock_file(char *filename) +{ + return unlink(filename); +} + +/** + * create a new lock file + * + * @param filename the file name of the lock + * @param killold one if the function should steal the lock from + * and existing process and kill it, or zero otherwise + * @return zero on success and negative on error + */ +int hip_create_lock_file(char *filename, int killold) +{ + int err = 0, fd = 0, old_pid = 0, new_pid_str_len = 0; + char old_pid_str[64], new_pid_str[64]; + int pid_set = 0; /* the pid was read successfully */ + memset(old_pid_str, 0, sizeof(old_pid_str)); + memset(new_pid_str, 0, sizeof(new_pid_str)); + + /* New pid */ + snprintf(new_pid_str, sizeof(new_pid_str) - 1, "%d\n", getpid()); + new_pid_str_len = strlen(new_pid_str); + HIP_IFEL((new_pid_str_len <= 0), -1, "pID length error.\n"); + + /* Read old pid */ + fd = HIP_CREATE_FILE(filename); + HIP_IFEL((fd <= 0), -1, "opening lock file failed\n"); + + /** @todo This is possibly unsafe: the pid is read from the file without checking + * file permissions and the process with the number is simply killed. + * THIS COULD BE USED TO ATTACK THE SYSTEM + */ + pid_set = read(fd, old_pid_str, sizeof(old_pid_str) - 1); + old_pid = atoi(old_pid_str); + + if (lockf(fd, F_TLOCK, 0) < 0) { + HIP_IFEL(!killold, -12, + "\nHIP daemon already running with pid %d\n" + "Give: -k option to kill old daemon.\n", old_pid); + + HIP_INFO("\nDaemon is already running with pid %d\n" + "-k option given, terminating old one...\n", old_pid); + /* Erase the old lock file to avoid having multiple pids + * in the file */ + if (lockf(fd, F_ULOCK, 0) == -1) { + HIP_ERROR("Cannot unlock pid lock."); + } + + close(fd); + HIP_IFEL(hip_remove_lock_file(filename), -1, + "Removing lock file failed.\n"); + + /* fd = open(filename, O_RDWR | O_CREAT, 0644); */ + fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0644); + + /* Don't close file descriptor because new started process is + * running. */ + HIP_IFEL((fd <= 0), -1, "Opening lock file failed.\n"); + HIP_IFEL(lockf(fd, F_TLOCK, 0), -1, "Lock attempt failed.\n"); + if (pid_set) { + err = kill(old_pid, SIGKILL); + } + if (err != 0) { + HIP_ERROR("\nError when trying to send signal SIGKILL " \ + "process identified by process identifier " \ + "%d.\n", old_pid); + HIP_PERROR("errno after kill() is: "); + } + } + + lseek(fd, 0, SEEK_SET); + + HIP_IFEL((write(fd, new_pid_str, new_pid_str_len) != new_pid_str_len), + -1, "Writing new process identifier failed.\n"); + +out_err: + if (err == -12) { + exit(0); + } + + return err; +} + +/** + * check and create a directory + * @param dirname the name of the directory + * @param mode creation mode for the directory, if it does not exist + * + * @return 0 if successful, or negative on error. + */ +int check_and_create_dir(char *dirname, mode_t mode) +{ + int err = 0; + struct stat dir_stat; + + HIP_INFO("dirname=%s mode=%o\n", dirname, mode); + err = stat(dirname, &dir_stat); + if (err && errno == ENOENT) { /* no such file or directory */ + err = mkdir(dirname, mode); + if (err) { + HIP_ERROR("mkdir %s failed: %s\n", dirname, + strerror(errno)); + } + } else if (err) { + HIP_ERROR("stat %s failed: %s\n", dirname, + strerror(errno)); + } + + return err; +} + +/** + * check and create a file + * @param file the name of the file + * @param mode creation mode for the file, if it does not exist + * + * @return file descriptor of the created file + */ +int check_and_create_file(char *filename, mode_t mode) +{ + int err = 0, fd = 0; + struct stat file_stat; + + HIP_INFO("filename=%s mode=%o\n", filename, mode); + err = stat(filename, &file_stat); + if (err && errno == ENOENT) { /* no such file or file */ + fd = open(filename, O_RDWR | O_CREAT, 0644); + if (fd < 0) { + HIP_ERROR("creating file %s failed: %s\n", filename, + strerror(errno)); + } + } else { + fd = open(filename, O_RDWR); + if (fd < 0) { + HIP_ERROR("opening file %s failed: %s\n", filename, + strerror(errno)); + } + } + + return fd; +} + +/** + * make /etc/hip file permissions more secure + * + * @param filenamebase the file name based for keys + */ +void change_key_file_perms(char *filenamebase) +{ + char *pubfilename = NULL; + int pubfilename_len; + + pubfilename_len = + strlen(filenamebase) + strlen(DEFAULT_PUB_FILE_SUFFIX) + 1; + pubfilename = malloc(pubfilename_len); + if (!pubfilename) { + HIP_ERROR("malloc(%d) failed\n", pubfilename_len); + goto out_err; + } + + /* check retval */ + snprintf(pubfilename, pubfilename_len, "%s%s", filenamebase, + DEFAULT_PUB_FILE_SUFFIX); + + chmod(filenamebase, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + chmod(pubfilename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + +out_err: + if (pubfilename) { + HIP_FREE(pubfilename); + } + + return; +} === added file 'lib/core/filemanip.h' --- lib/core/filemanip.h 1970-01-01 00:00:00 +0000 +++ lib/core/filemanip.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,23 @@ +#ifndef HIP_LIB_CORE_FILEMANIP_H +#define HIP_LIB_CORE_FILEMANIP_H + +#include <sys/types.h> + +#include "config.h" + +#ifdef CONFIG_HIP_OPENWRT +# define HIP_CREATE_FILE(x) check_and_create_file(x, 0644) +#else +# define HIP_CREATE_FILE(x) open((x), O_RDWR | O_CREAT, 0644) +#endif + +/* system/bin for Android */ +#define HIP_DEFAULT_EXEC_PATH "/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin:/usr/local/bin:/system/bin" + +int hip_create_lock_file(char *filename, int killold); +int hip_remove_lock_file(char *filename); +int check_and_create_dir(char *dirname, mode_t mode); +int check_and_create_file(char *filename, mode_t mode); +void change_key_file_perms(char *filenamebase); + +#endif /* HIP_LIB_CORE_FILEMANIP_H */ === modified file 'lib/core/hashtable.c' --- lib/core/hashtable.c 2010-03-03 13:16:18 +0000 +++ lib/core/hashtable.c 2010-03-19 09:53:35 +0000 @@ -24,9 +24,43 @@ */ #include "hashtable.h" +/** + * A generic object hashing function for lib/core/hashtable.c + * + * @param ptr an pointer to hash (must be at least 32 bits) + * @return a hash of the first 32-bits of the ptr's data + */ +unsigned long hip_hash_generic(const void *ptr) +{ + unsigned long hash = (unsigned long) (*((uint32_t *) ptr)); + return hash % ULONG_MAX; +} + +/** + * A generic matching function for lib/core/hashtable.c + * + * @param ptr1 a pointer to an item in the hash table + * @param ptr2 a pointer to an item in the hash table + * @return zero if the pointers match or one otherwise + */ +int hip_match_generic(const void *ptr1, const void *ptr2) +{ + return ptr1 != ptr2; +} + #ifdef HIPL_OPENSSL_100 /** + * Returns a generic linked list based on the hash table implementation + * + * @return an allocated hash table which is caller is responsible to free + */ +LHASH_OF(HIP_HT) * hip_linked_list_init(void) +{ + return (LHASH_OF(HIP_HT) *) hip_ht_init(hip_hash_generic, hip_match_generic); +} + +/** * Initialize hash table (or linked list) * * @param hashfunc hash function to calculated the hash @@ -41,6 +75,11 @@ #else /* not HIPL_OPENSSL_100 */ +HIP_HASHTABLE *hip_linked_list_init(void) +{ + return (HIP_HASHTABLE *) hip_ht_init(hip_hash_generic, hip_match_generic); +} + HIP_HASHTABLE *hip_ht_init(LHASH_HASH_FN_TYPE hashfunc, LHASH_COMP_FN_TYPE cmpfunc) { === modified file 'lib/core/hashtable.h' --- lib/core/hashtable.h 2010-02-17 17:38:08 +0000 +++ lib/core/hashtable.h 2010-03-19 09:53:35 +0000 @@ -4,6 +4,7 @@ #include <openssl/bio.h> #include <openssl/crypto.h> #include <openssl/lhash.h> +#include <limits.h> #include "debug.h" #include "list.h" @@ -35,6 +36,7 @@ typedef DECLARE_LHASH_OF (HIP_HT) hip_ht_common; typedef hip_ht_common HIP_HASHTABLE; +LHASH_OF(HIP_HT) * hip_linked_list_init(void); LHASH_OF(HIP_HT) * hip_ht_init(LHASH_HASH_FN_TYPE hashfunc, LHASH_COMP_FN_TYPE cmpfunc); #else @@ -70,6 +72,7 @@ typedef DECLARE_LHASH_OF (HIP_HT) hip_ht_common; typedef LHASH HIP_HASHTABLE; +HIP_HASHTABLE *hip_linked_list_init(void); HIP_HASHTABLE *hip_ht_init(LHASH_HASH_FN_TYPE hashfunc, LHASH_COMP_FN_TYPE cmpfunc); #endif === modified file 'lib/core/hip_capability.c' --- lib/core/hip_capability.c 2010-03-03 13:16:18 +0000 +++ lib/core/hip_capability.c 2010-03-19 09:53:35 +0000 @@ -19,10 +19,7 @@ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #ifdef CONFIG_HIP_PRIVSEP #ifdef CONFIG_HIP_ALTSEP /* Note: OpenWRT has to use <linux/capability.h> */ === modified file 'lib/core/hip_statistics.c' --- lib/core/hip_statistics.c 2010-03-03 16:51:18 +0000 +++ lib/core/hip_statistics.c 2010-03-19 09:53:35 +0000 @@ -91,8 +91,8 @@ HIP_ASSERT(timeval_start != NULL); HIP_ASSERT(timeval_end != NULL); - // check that timeval_high really is higher - if ((timeval_end->tv_sec > timeval_start->tv_sec) && + /* check that timeval_high really is higher */ + if ((timeval_end->tv_sec >= timeval_start->tv_sec) && (timeval_end->tv_usec > timeval_start->tv_usec)) { rel_timeval.tv_sec = timeval_end->tv_sec - timeval_start->tv_sec; === added file 'lib/core/hip_udp.c' --- lib/core/hip_udp.c 1970-01-01 00:00:00 +0000 +++ lib/core/hip_udp.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,67 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief UDP-related functions + * + * @author Miika Komu <miika@xxxxxx> + */ + +#include "hip_udp.h" +#include "debug.h" + +/** Port numbers for NAT traversal of hip control packets. */ +in_port_t hip_local_nat_udp_port = HIP_NAT_UDP_PORT; +in_port_t hip_peer_nat_udp_port = HIP_NAT_UDP_PORT; + + +/** + * Retrieve the default local UDP port + * + * @return the default local UDP port + */ +in_port_t hip_get_local_nat_udp_port() +{ + return hip_local_nat_udp_port; +} + +/** + * Retrieve the default remote UDP port + * + * @return the default remote UDP port + */ +in_port_t hip_get_peer_nat_udp_port() +{ + return hip_peer_nat_udp_port; +} + +/** + * set the default local UDP port + * + * @param port the port to set as the default local UDP port + * @return zero + */ +int hip_set_local_nat_udp_port(in_port_t port) +{ + int err = 0; + HIP_DEBUG("set local nat udp port %d\n", port); + hip_local_nat_udp_port = port; + + return err; +} + +/** + * set the default remote UDP port + * + * @param port the port to set as the default remote UDP port + * @return zero + */ +int hip_set_peer_nat_udp_port(in_port_t port) +{ + int err = 0; + + HIP_DEBUG("set peer nat udp port %d\n", port); + hip_peer_nat_udp_port = port; + return err; +} === added file 'lib/core/hip_udp.h' --- lib/core/hip_udp.h 1970-01-01 00:00:00 +0000 +++ lib/core/hip_udp.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,36 @@ +#ifndef HIP_LIB_CORE_HIP_UDP_H +#define HIP_LIB_CORE_HIP_UDP_H + +#include <netinet/in.h> + +#define HIP_NAT_UDP_PORT 10500 +//#define HIP_NAT_TURN_PORT 10500 + +/** For setting socket to listen for beet-udp packets. */ +#define HIP_UDP_ENCAP 100 +/** UDP encapsulation type. */ +#define HIP_UDP_ENCAP_ESPINUDP 2 +/** UDP encapsulation type. */ +#define HIP_UDP_ENCAP_ESPINUDP_NONIKE 1 + +/** + * Get HIP local NAT UDP port. + */ +in_port_t hip_get_local_nat_udp_port(void); + +/** + * Get HIP peer NAT UDP port. + */ +in_port_t hip_get_peer_nat_udp_port(void); + +/** + * Set HIP local NAT UDP port. + */ +int hip_set_local_nat_udp_port(in_port_t port); + +/** + * Set HIP peer NAT UDP port. + */ +int hip_set_peer_nat_udp_port(in_port_t port); + +#endif /* HIP_LIB_CORE_HIP_UDP_H */ === added file 'lib/core/hit.c' --- lib/core/hit.c 1970-01-01 00:00:00 +0000 +++ lib/core/hit.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,100 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief HIT-related utility functions + * + * @author Miika Komu <miika@xxxxxx> + */ + +#define _BSD_SOURCE + +#include "config.h" +#include "hit.h" +#include "debug.h" +#include "straddr.h" +#include "builder.h" + +/** + * convert a binary HIT into a string + * + * @param hit a binary HIT + * @param prefix an optional HIT prefix as a string + * @param hit_str the HIT as a string with the given prefix + * @return zero on success and negative on error + */ +int hip_convert_hit_to_str(const hip_hit_t *hit, + const char *prefix, + char *hit_str) +{ + int err = 0; + + HIP_ASSERT(hit); + + memset(hit_str, 0, INET6_ADDRSTRLEN); + err = !hip_in6_ntop(hit, hit_str); + + if (prefix) { + memcpy(hit_str + strlen(hit_str), prefix, strlen(prefix)); + } + + return err; +} +/** + * compare two HITs to check which HIT is "bigger" + * + * @param hit1 the first HIT to be compared + * @param hit2 the second HIT to be compared + * + * @return 1 if hit1 was bigger than hit2, or else 0 + */ +int hip_hit_is_bigger(const struct in6_addr *hit1, + const struct in6_addr *hit2) +{ + return ipv6_addr_cmp(hit1, hit2) > 0; +} + +/** + * compare two HITs to check which if they are equal + * + * @param hit1 the first HIT to be compared + * @param hit2 the second HIT to be compared + * + * @return 1 if the HITs were equal and zero otherwise + */ +int hip_hit_are_equal(const struct in6_addr *hit1, + const struct in6_addr *hit2) +{ + return ipv6_addr_cmp(hit1, hit2) == 0; +} + +/** + * hip_hash_hit - calculate a hash from a HIT + * + * @param key pointer to a HIT + * @param range range of the hash + * + * Returns value in range: 0 <= x < range + */ +unsigned long hip_hash_hit(const void *ptr) +{ + uint8_t hash[HIP_AH_SHA_LEN]; + + hip_build_digest(HIP_DIGEST_SHA1, ptr + sizeof(uint16_t), + 7 * sizeof(uint16_t), hash); + + return *((unsigned long *) hash); +} + +/** + * Verify if if two HITs match based on hashing + * + * @param ptr1 a HIT + * @param ptr2 a HIT + * @return zero if the HITs match or one otherwise + */ +int hip_match_hit(const void *ptr1, const void *ptr2) +{ + return hip_hash_hit(ptr1) != hip_hash_hit(ptr2); +} === added file 'lib/core/hit.h' --- lib/core/hit.h 1970-01-01 00:00:00 +0000 +++ lib/core/hit.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,15 @@ +#ifndef HIP_LIB_CORE_HIT_H +#define HIP_LIB_CORE_HIT_H + +#include <netinet/in.h> +#include "protodefs.h" + +int hip_convert_hit_to_str(const hip_hit_t *hit, const char *prefix, char *str); +int hip_hit_is_bigger(const struct in6_addr *hit1, + const struct in6_addr *hit2); +int hip_hit_are_equal(const struct in6_addr *hit1, + const struct in6_addr *hit2); +unsigned long hip_hash_hit(const void *hit); +int hip_match_hit(const void *, const void *); + +#endif /* HIP_LIB_CORE_HIT_H */ === added file 'lib/core/hostid.c' --- lib/core/hostid.c 1970-01-01 00:00:00 +0000 +++ lib/core/hostid.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,1197 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Host identifier manipulation functions + * + * @author Miika Komu <miika@xxxxxx> + */ + +#include <netinet/in.h> +#include <stdlib.h> +#include "lib/core/ife.h" +#include "lib/core/debug.h" +#include "lib/core/protodefs.h" +#include "lib/core/crypto.h" +#include "lib/tool/pk.h" + +#include "config.h" +#include "hostid.h" +#include "filemanip.h" + +/* needed due to missing system inlcude for openWRT */ +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 64 +#endif + +#define HOST_ID_FILENAME_MAX_LEN 256 + + +/** + * calculate a HIT from a HI without the prefix + * + * @param orig a pointer to a host identity + * @param orig_len the length of the host identity in bits + * @param encoded an output argument where the HIT will be stored + * @param encoded_len the length of the encoded HIT in bits + * @return zero on success or negative on error + */ +int khi_encode(unsigned char *orig, int orig_len, + unsigned char *encoded, + int encoded_len) +{ + BIGNUM *bn = NULL; + int err = 0, shift = (orig_len - encoded_len) / 2, + len = encoded_len / 8 + ((encoded_len % 8) ? 1 : 0); + + HIP_IFEL((encoded_len > orig_len), -1, "len mismatch\n"); + HIP_IFEL((!(bn = BN_bin2bn(orig, orig_len / 8, NULL))), -1, + "BN_bin2bn\n"); + HIP_IFEL(!BN_rshift(bn, bn, shift), -1, "BN_lshift\n"); + HIP_IFEL(!BN_mask_bits(bn, encoded_len), -1, + "BN_mask_bits\n"); + HIP_IFEL((bn2bin_safe(bn, encoded, len) != len), -1, + "BN_bn2bin_safe\n"); + + _HIP_HEXDUMP("encoded: ", encoded, len); + +out_err: + if (bn) { + BN_free(bn); + } + return err; +} + +/** + * Calculates a Host Identity Tag (HIT) from a Host Identifier (HI) using DSA + * encryption. + * + * @param host_id a pointer to a Host Identifier + * @param hit a target buffer where to put the calculated HIT. + * @param hit_type type of the HIT (must be HIP_HIT_TYPE_HASH100). + * @return zero on success, negative otherwise. + */ +int hip_dsa_host_id_to_hit(const struct hip_host_id *host_id, + struct in6_addr *hit, int hit_type) +{ + int err = 0; + uint8_t digest[HIP_AH_SHA_LEN]; + uint8_t *key_rr = (uint8_t *) host_id->key; /* skip the header */ + /* hit excludes rdata but it is included in hi_length; + subtract rdata */ + unsigned int key_rr_len = ntohs(host_id->hi_length) - + sizeof(struct hip_host_id_key_rdata); + uint8_t *khi_data = NULL; + uint8_t khi_context_id[] = HIP_KHI_CONTEXT_ID_INIT; + int khi_data_len = key_rr_len + sizeof(khi_context_id); + int khi_index = 0; + + _HIP_DEBUG("key_rr_len=%u\n", key_rr_len); + HIP_IFE(hit_type != HIP_HIT_TYPE_HASH100, -ENOSYS); + _HIP_HEXDUMP("key_rr", key_rr, key_rr_len); + + /* Hash Input := Context ID | Input */ + khi_data = HIP_MALLOC(khi_data_len, 0); + khi_index = 0; + memcpy(khi_data + khi_index, khi_context_id, sizeof(khi_context_id)); + khi_index += sizeof(khi_context_id); + memcpy(khi_data + khi_index, key_rr, key_rr_len); + khi_index += key_rr_len; + + HIP_ASSERT(khi_index == khi_data_len); + + _HIP_HEXDUMP("khi data", khi_data, khi_data_len); + + /* Hash := SHA1( Expand( Hash Input ) ) */ + HIP_IFEL((err = hip_build_digest(HIP_DIGEST_SHA1, khi_data, + khi_data_len, digest)), err, + "Building of digest failed\n"); + + _HIP_HEXDUMP("digest", digest, sizeof(digest)); + + memset(hit, 0, sizeof(hip_hit_t)); + HIP_IFEL(khi_encode(digest, sizeof(digest) * 8, + ((uint8_t *) hit) + 3, + sizeof(hip_hit_t) * 8 - HIP_HIT_PREFIX_LEN), + -1, "encoding failed\n"); + + _HIP_DEBUG_HIT("HIT before prefix: ", hit); + set_hit_prefix(hit); + _HIP_DEBUG_HIT("HIT after prefix: ", hit); + +out_err: + if (khi_data) { + HIP_FREE(khi_data); + } + + return err; +} + +/** + * convert DSA or RSA-based host id to a HIT + * + * @param host_id a host id + * @param hit output argument, the calculated HIT will stored here + * @param hit_type the type of the HIT + * @return zero on success or negative on error + */ +int hip_host_id_to_hit(const struct hip_host_id *host_id, + struct in6_addr *hit, + int hit_type) +{ + int algo = hip_get_host_id_algo(host_id); + int err = 0; + + if (algo == HIP_HI_DSA) { + err = hip_dsa_host_id_to_hit(host_id, hit, hit_type); + } else if (algo == HIP_HI_RSA) { + err = hip_rsa_host_id_to_hit(host_id, hit, hit_type); + } else { + err = -ENOSYS; + } + + return err; +} + +/** + * convert DSA-based private host id to a HIT + * + * @param host_id a host id + * @param hit output argument, the calculated HIT will stored here + * @param hit_type the type of the HIT + * @return zero on success or negative on error + */ +int hip_private_dsa_host_id_to_hit(const struct hip_host_id_priv *host_id, + struct in6_addr *hit, + int hit_type) +{ + int err = 0; + struct hip_host_id *host_id_pub = NULL; + int contents_len; + int total_len; + + contents_len = hip_get_param_contents_len(host_id); + total_len = hip_get_param_total_len(host_id); + + /*! \todo add an extra check for the T val */ + + HIP_IFEL(contents_len <= 20, -EMSGSIZE, "Host id too short\n"); + + /* Allocate enough space for host id; there will be 20 bytes extra + * to avoid hassle with padding. */ + host_id_pub = (struct hip_host_id *) HIP_MALLOC(total_len, 0); + HIP_IFE(!host_id_pub, -EFAULT); + memset(host_id_pub, 0, total_len); + + memcpy(host_id_pub, host_id, + sizeof(struct hip_tlv_common) + contents_len - DSA_PRIV); + + host_id_pub->hi_length = htons(ntohs(host_id_pub->hi_length) - DSA_PRIV); + hip_set_param_contents_len((struct hip_tlv_common *) host_id_pub, + contents_len - DSA_PRIV); + + _HIP_HEXDUMP("extracted pubkey", host_id_pub, + hip_get_param_total_len(host_id_pub)); + + if ((err = hip_dsa_host_id_to_hit(host_id_pub, hit, hit_type))) { + HIP_ERROR("Failed to convert HI to HIT.\n"); + goto out_err; + } + +out_err: + + if (host_id_pub) { + HIP_FREE(host_id_pub); + } + + return err; +} + +/** + * convert RSA-based private host id to a HIT + * + * @param host_id a host id + * @param hit output argument, the calculated HIT will stored here + * @param hit_type the type of the HIT + * @return zero on success or negative on error + */ +int hip_private_rsa_host_id_to_hit(const struct hip_host_id_priv *host_id, + struct in6_addr *hit, + int hit_type) +{ + int err = 0; + struct hip_host_id host_id_pub; + int rsa_pub_len, rsa_priv_len; + struct hip_rsa_keylen keylen; + + /* Length of the private part of the RSA key d + p + q + * is twice the length of the public modulus. + * dmp1 + dmq1 + iqmp is another 1.5 times */ + + hip_get_rsa_keylen(host_id, &keylen, 1); + rsa_pub_len = keylen.e_len + keylen.e + keylen.n; + rsa_priv_len = keylen.n * 7 / 2; + + memcpy(&host_id_pub, host_id, sizeof(host_id_pub) + - sizeof(host_id_pub.key) - sizeof(host_id_pub.hostname)); + + host_id_pub.hi_length = + htons(ntohs(host_id_pub.hi_length) - rsa_priv_len); + memcpy(host_id_pub.key, host_id->key, rsa_pub_len); + + _HIP_HEXDUMP("extracted pubkey", &host_id_pub, + hip_get_param_total_len(host_id_pub)); + + if ((err = hip_rsa_host_id_to_hit(&host_id_pub, hit, hit_type))) { + HIP_ERROR("Failed to convert HI to HIT.\n"); + goto out_err; + } + +out_err: + + return err; +} + +/** + * convert RSA or DSA-based private host id to a HIT + * + * @param host_id a host id + * @param hit output argument, the calculated HIT will stored here + * @param hit_type the type of the HIT + * @return zero on success or negative on error + */ +int hip_private_host_id_to_hit(const struct hip_host_id_priv *host_id, + struct in6_addr *hit, + int hit_type) +{ + int algo = hip_get_host_id_algo((struct hip_host_id *) host_id); + int err = 0; + + if (algo == HIP_HI_DSA) { + err = hip_private_dsa_host_id_to_hit(host_id, hit, + hit_type); + } else if (algo == HIP_HI_RSA) { + err = hip_private_rsa_host_id_to_hit(host_id, hit, + hit_type); + } else { + err = -ENOSYS; + } + + return err; +} + + +/** + * check if a given host id just contains a public key (i.e. can + * be sent on wire) or if it is piggypacked with the private component + * + * @param host_id the host id structure + * @return 1 if the host id contains the private component or 0 otherwise + */ +int hip_host_id_contains_private_key(struct hip_host_id *host_id) +{ + uint16_t len = hip_get_param_contents_len(host_id); + uint8_t *buf = (uint8_t *) host_id->key; + uint8_t t = *buf; + + return len >= 3 * (64 + 8 * t) + 2 * 20; /* PQGXY 3*(64+8*t) + 2*20 */ +} + +/** + * dig out RSA key length from an host id + * + * @param host_id the host id + * @param ret the RSA key component lengths will be stored here + * @param is_priv one if the host_id contains also the private key + * component or zero otherwise + */ +void hip_get_rsa_keylen(const struct hip_host_id_priv *host_id, + struct hip_rsa_keylen *ret, + int is_priv) +{ + int bytes; + uint8_t *tmp = (uint8_t *) host_id->key; + int offset = 0; + int e_len = tmp[offset++]; + + /* Check for public exponent longer than 255 bytes (see RFC 3110) */ + if (e_len == 0) { + e_len = ntohs((uint16_t) tmp[offset]); + offset += 2; + } + + /* + * hi_length is the total length of: + * rdata struct (4 bytes), length of e (1 byte for e < 255 bytes, 3 bytes otherwise), + * e (normally 3 bytes), followed by public n, private d, p, q, dmp1, dmq1, iqmp + * n_len == d_len == 2 * p_len == 2 * q_len == dmp1_len == dmq1_len == iqmp_len + * for 9/2 * n_len + */ + if (is_priv) { + bytes = (ntohs(host_id->hi_length) - sizeof(struct hip_host_id_key_rdata) - + offset - e_len) * 2 / 9; + } else { + bytes = (ntohs(host_id->hi_length) - sizeof(struct hip_host_id_key_rdata) - + offset - e_len); + } + + ret->e_len = offset; + ret->e = e_len; + ret->n = bytes; +} + +/** + * convert a RSA-based host id into an OpenSSL structure + * + * @param host_id the host id + * @param is_priv one if the host_id contains also the private key + * component or zero otherwise + * @return The OpenSSL formatted RSA key corresponding to @c host_id. + * Caller is responsible of freeing. + */ +RSA *hip_key_rr_to_rsa(const struct hip_host_id_priv *host_id, int is_priv) +{ + int offset; + struct hip_rsa_keylen keylen; + RSA *rsa = NULL; + + hip_get_rsa_keylen(host_id, &keylen, is_priv); + + rsa = RSA_new(); + if (!rsa) { + HIP_ERROR("Failed to allocate RSA\n"); + return NULL; + } + + offset = keylen.e_len; + rsa->e = BN_bin2bn(&host_id->key[offset], keylen.e, 0); + offset += keylen.e; + rsa->n = BN_bin2bn(&host_id->key[offset], keylen.n, 0); + + if (is_priv) { + offset += keylen.n; + rsa->d = BN_bin2bn(&host_id->key[offset], keylen.n, 0); + offset += keylen.n; + rsa->p = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0); + offset += keylen.n / 2; + rsa->q = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0); + offset += keylen.n / 2; + rsa->dmp1 = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0); + offset += keylen.n / 2; + rsa->dmq1 = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0); + offset += keylen.n / 2; + rsa->iqmp = BN_bin2bn(&host_id->key[offset], keylen.n / 2, 0); + } + + return rsa; +} + +/** + * convert a DSA-based host id into an OpenSSL structure + * + * @param host_id the host id + * @param is_priv one if the host_id contains also the private key + * component or zero otherwise + * @return The OpenSSL formatted DSA key corresponding to @c host_id. + * Caller is responsible of freeing. + */ +DSA *hip_key_rr_to_dsa(const struct hip_host_id_priv *host_id, int is_priv) +{ + int offset = 0; + DSA *dsa = NULL; + uint8_t t = host_id->key[offset++]; + int key_len = 64 + (t * 8); + + dsa = DSA_new(); + if (!dsa) { + HIP_ERROR("Failed to allocate DSA\n"); + return NULL; + } + + dsa->q = BN_bin2bn(&host_id->key[offset], DSA_PRIV, 0); + offset += DSA_PRIV; + dsa->p = BN_bin2bn(&host_id->key[offset], key_len, 0); + offset += key_len; + dsa->g = BN_bin2bn(&host_id->key[offset], key_len, 0); + offset += key_len; + dsa->pub_key = BN_bin2bn(&host_id->key[offset], key_len, 0); + + if (is_priv) { + offset += key_len; + dsa->priv_key = BN_bin2bn(&host_id->key[offset], DSA_PRIV, 0); + + /* Precompute values for faster signing */ + DSA_sign_setup(dsa, NULL, &dsa->kinv, &dsa->r); + } + + return dsa; +} + +/** + * verify the signature in a HIP control packet + * + * @param pkt the hip packet + * @param peer_host_id peer host id + * @return zero on success, or negative error value on failure + */ +int hip_verify_packet_signature(struct hip_common *pkt, + struct hip_host_id *peer_host_id) +{ + int err = 0; + struct hip_host_id *peer_pub = NULL; + int len = hip_get_param_total_len(peer_host_id); + char *key = NULL; + + HIP_IFEL(!(peer_pub = HIP_MALLOC(len, 0)), + -ENOMEM, "Out of memory\n"); + + memcpy(peer_pub, peer_host_id, len); + + if (peer_host_id->rdata.algorithm == HIP_HI_DSA) { + key = (char *) hip_key_rr_to_rsa( + (struct hip_host_id_priv *) peer_pub, 0); + err = hip_dsa_verify((DSA *) key, pkt); + } else if (peer_host_id->rdata.algorithm == HIP_HI_RSA) { + key = (char *) hip_key_rr_to_rsa( + (struct hip_host_id_priv *) peer_pub, 0); + err = hip_rsa_verify((RSA *) key, pkt); + } else { + HIP_ERROR("Unknown algorithm\n"); + err = -1; + } + +out_err: + if (peer_pub) { + free(peer_pub); + } + + return err; +} + +/** + * Convert a local host id into LSI/HIT information and write the + * result into a HIP message as a HIP_PARAM_HIT_INFO parameter. + * Interprocess communications only. + * + * @param entry an hip_host_id_entry structure + * @param msg a HIP user message where the HIP_PARAM_HIT_INFO + * parameter will be written + * @return zero on success and negative on error + */ +int hip_host_id_entry_to_hit_info(struct hip_host_id_entry *entry, + void *msg) +{ + struct hip_hit_info data; + int err = 0; + + memcpy(&data.lhi, &entry->lhi, sizeof(struct hip_lhi)); + /* FIXME: algo is 0 in entry->lhi */ + data.lhi.algo = hip_get_host_id_algo(entry->host_id); + memcpy(&data.lsi, &entry->lsi, sizeof(hip_lsi_t)); + + HIP_IFEL(hip_build_param_contents(msg, + &data, + HIP_PARAM_HIT_INFO, + sizeof(data)), + -1, + "Error building parameter\n"); + +out_err: + return err; +} + +/** + * (Re)create new host identities or load existing ones, and append the + * private identities into a message. This functionality is used by hipd + * but can also be invoked with hipconf. + * + * @param msg an output argument where the identities will be appended + * @param action Currently ACTION_ADD and ACTION_NEW are supported. Warning, + * ACTION_NEW will override the existing identities on disk! + * @param anon set to one when you want to process only anonymous (short-term) + * identities or zero otherwise + * @param use_default One when dealing with default identities in /etc/hip. + * Zero when user supplies own identities denoted by + * @c hi_file argument. + * @param hi_fmt "dsa" or "rsa" currently supported + * @param hi_file an optional location for user-supplied host identities. + * Argument @c use_default must be zero when used. + * @param rsa_key_bits size for RSA keys in bits + * @param dsa_key_bits size of DSA keys in bits + * + * @return zero on success and negative on error + */ +int hip_serialize_host_id_action(struct hip_common *msg, + int action, + int anon, + int use_default, + const char *hi_fmt, + const char *hi_file, + int rsa_key_bits, + int dsa_key_bits) +{ + int err = 0, dsa_key_rr_len = 0, rsa_key_rr_len = 0; + int dsa_pub_key_rr_len = 0, rsa_pub_key_rr_len = 0; + hip_hdr_type_t numeric_action = 0; + char addrstr[INET6_ADDRSTRLEN], hostname[HIP_HOST_ID_HOSTNAME_LEN_MAX]; + char *dsa_filenamebase = NULL, *rsa_filenamebase = NULL; + char *dsa_filenamebase_pub = NULL, *rsa_filenamebase_pub = NULL; + unsigned char *dsa_key_rr = NULL, *rsa_key_rr = NULL; + unsigned char *dsa_pub_key_rr = NULL, *rsa_pub_key_rr = NULL; + DSA *dsa_key = NULL, *dsa_pub_key = NULL; + RSA *rsa_key = NULL, *rsa_pub_key = NULL; + struct hip_lhi rsa_lhi, dsa_lhi, rsa_pub_lhi, dsa_pub_lhi; + struct hip_host_id *dsa_host_id = NULL, *rsa_host_id = NULL; + struct hip_host_id *dsa_pub_host_id = NULL, *rsa_pub_host_id = NULL; + struct endpoint_hip *endpoint_dsa_hip = NULL; + struct endpoint_hip *endpoint_dsa_pub_hip = NULL; + struct endpoint_hip *endpoint_rsa_hip = NULL; + struct endpoint_hip *endpoint_rsa_pub_hip = NULL; + + if (action == ACTION_ADD) { + numeric_action = SO_HIP_ADD_LOCAL_HI; + } + + if ((err = hip_build_user_hdr(msg, numeric_action, 0))) { + HIP_ERROR("build hdr error %d\n", err); + goto out_err; + } + + memset(addrstr, '\0', INET6_ADDRSTRLEN); + memset(hostname, '\0', HIP_HOST_ID_HOSTNAME_LEN_MAX); + + if ((err = -gethostname(hostname, HIP_HOST_ID_HOSTNAME_LEN_MAX - 1))) { + HIP_ERROR("Failed to get hostname. Err is (%d).\n", err); + goto out_err; + } + + HIP_INFO("Using hostname: %s\n", hostname); + + HIP_IFEL((!use_default && strcmp(hi_fmt, "rsa") && strcmp(hi_fmt, "dsa")), + -ENOSYS, "Only RSA and DSA keys are supported\n"); + + /* Set filenamebase (depending on whether the user supplied a + * filenamebase or not) */ + if (!use_default) { + if (!strcmp(hi_fmt, "dsa")) { + dsa_filenamebase = malloc(strlen(hi_file) + 1); + HIP_IFEL(!dsa_filenamebase, -ENOMEM, + "Could not allocate DSA filename.\n"); + memcpy(dsa_filenamebase, hi_file, strlen(hi_file)); + } else { /*rsa*/ + rsa_filenamebase = malloc(strlen(hi_file) + 1); + HIP_IFEL(!rsa_filenamebase, -ENOMEM, + "Could not allocate RSA filename.\n"); + memcpy(rsa_filenamebase, hi_file, strlen(hi_file)); + } + } else { /* create dynamically default filenamebase */ + int rsa_filenamebase_len = 0, dsa_filenamebase_len = 0, ret = 0; + + HIP_INFO("No key file given, using default.\n"); + + /* Default_config_dir/default_host_dsa_key_file_base/ + * default_anon_hi_file_name_suffix\0 */ + /* Creation of default keys is called with hi_fmt = NULL, + * adding is called separately for DSA, RSA anon and RSA pub */ + if (hi_fmt == NULL || !strcmp(hi_fmt, "dsa")) { + dsa_filenamebase_len = + strlen(DEFAULT_CONFIG_DIR) + strlen("/") + + strlen(DEFAULT_HOST_DSA_KEY_FILE_BASE) + 1; + dsa_filenamebase = malloc(HOST_ID_FILENAME_MAX_LEN); + HIP_IFEL(!dsa_filenamebase, -ENOMEM, + "Could not allocate DSA filename.\n"); + + ret = snprintf(dsa_filenamebase, + dsa_filenamebase_len + + strlen(DEFAULT_ANON_HI_FILE_NAME_SUFFIX), + "%s/%s%s", + DEFAULT_CONFIG_DIR, + DEFAULT_HOST_DSA_KEY_FILE_BASE, + DEFAULT_ANON_HI_FILE_NAME_SUFFIX); + + HIP_IFE(ret <= 0, -EINVAL); + + dsa_filenamebase_pub = malloc(HOST_ID_FILENAME_MAX_LEN); + HIP_IFEL(!dsa_filenamebase_pub, -ENOMEM, + "Could not allocate DSA (pub) filename.\n"); + + ret = snprintf(dsa_filenamebase_pub, + HOST_ID_FILENAME_MAX_LEN, "%s/%s%s", + DEFAULT_CONFIG_DIR, + DEFAULT_HOST_DSA_KEY_FILE_BASE, + DEFAULT_PUB_HI_FILE_NAME_SUFFIX); + + HIP_IFE(ret <= 0, -EINVAL); + + HIP_DEBUG("Using dsa (anon hi) filenamebase: %s\n", + dsa_filenamebase); + HIP_DEBUG("Using dsa (pub hi) filenamebase: %s\n", + dsa_filenamebase_pub); + } + + if (hi_fmt == NULL || !strcmp(hi_fmt, "rsa")) { + rsa_filenamebase_len = + strlen(DEFAULT_CONFIG_DIR) + strlen("/") + + strlen(DEFAULT_HOST_RSA_KEY_FILE_BASE) + 1; + + if (anon || hi_fmt == NULL) { + rsa_filenamebase = + malloc(HOST_ID_FILENAME_MAX_LEN); + HIP_IFEL(!rsa_filenamebase, -ENOMEM, + "Could not allocate RSA filename.\n"); + + ret = snprintf( + rsa_filenamebase, + HOST_ID_FILENAME_MAX_LEN, "%s/%s%s", + DEFAULT_CONFIG_DIR, + DEFAULT_HOST_RSA_KEY_FILE_BASE, + DEFAULT_ANON_HI_FILE_NAME_SUFFIX); + + HIP_IFE(ret <= 0, -EINVAL); + + HIP_DEBUG("Using RSA (anon HI) filenamebase: " \ + "%s.\n", rsa_filenamebase); + } + + if (!anon || hi_fmt == NULL) { + rsa_filenamebase_pub = + malloc(HOST_ID_FILENAME_MAX_LEN); + HIP_IFEL(!rsa_filenamebase_pub, -ENOMEM, + "Could not allocate RSA (pub) " \ + "filename.\n"); + + ret = snprintf( + rsa_filenamebase_pub, + rsa_filenamebase_len + + strlen(DEFAULT_PUB_HI_FILE_NAME_SUFFIX), + "%s/%s%s", DEFAULT_CONFIG_DIR, + DEFAULT_HOST_RSA_KEY_FILE_BASE, + DEFAULT_PUB_HI_FILE_NAME_SUFFIX); + + HIP_IFE(ret <= 0, -EINVAL); + + HIP_DEBUG("Using RSA (pub HI) filenamebase: " \ + "%s\n", rsa_filenamebase_pub); + } + } + } + + switch (action) { + case ACTION_NEW: + /* Default directory is created only in "hipconf new default hi" */ + if (use_default) { + if ((err = check_and_create_dir(DEFAULT_CONFIG_DIR, + DEFAULT_CONFIG_DIR_MODE))) { + HIP_ERROR("Could not create default directory.\n"); + goto out_err; + } + } else if (!use_default) { + if (!strcmp(hi_fmt, "dsa")) { + dsa_key = create_dsa_key(dsa_key_bits); + HIP_IFEL(!dsa_key, -EINVAL, + "Creation of DSA key failed.\n"); + if ((err = save_dsa_private_key(dsa_filenamebase, dsa_key))) { + HIP_ERROR("Saving of DSA key failed.\n"); + goto out_err; + } + } else { /*RSA*/ + rsa_key = create_rsa_key(rsa_key_bits); + HIP_IFEL(!rsa_key, -EINVAL, + "Creation of RSA key failed.\n"); + if ((err = save_rsa_private_key(rsa_filenamebase, rsa_key))) { + HIP_ERROR("Saving of RSA key failed.\n"); + goto out_err; + } + } + HIP_DEBUG("Key saved.\n"); + break; + } + + /* Using default */ + dsa_key = create_dsa_key(dsa_key_bits); + HIP_IFEL(!dsa_key, -EINVAL, + "Creation of DSA key failed.\n"); + + dsa_pub_key = create_dsa_key(dsa_key_bits); + HIP_IFEL(!dsa_pub_key, -EINVAL, + "Creation of public DSA key failed.\n"); + + rsa_key = create_rsa_key(rsa_key_bits); + HIP_IFEL(!rsa_key, -EINVAL, + "Creation of RSA key failed.\n"); + + rsa_pub_key = create_rsa_key(rsa_key_bits); + HIP_IFEL(!dsa_pub_key, -EINVAL, + "Creation of public RSA key failed.\n"); + + if ((err = save_dsa_private_key(dsa_filenamebase, dsa_key))) { + HIP_ERROR("Saving of DSA key failed.\n"); + goto out_err; + } + + if ((err = save_dsa_private_key(dsa_filenamebase_pub, dsa_pub_key))) { + HIP_ERROR("Saving of public DSA key failed.\n"); + goto out_err; + } + + if ((err = save_rsa_private_key(rsa_filenamebase, rsa_key))) { + HIP_ERROR("Saving of RSA key failed.\n"); + goto out_err; + } + + if ((err = save_rsa_private_key(rsa_filenamebase_pub, rsa_pub_key))) { + HIP_ERROR("Saving of public RSA key failed.\n"); + goto out_err; + } + + break; + + case ACTION_ADD: + if (!use_default) { + if (!strcmp(hi_fmt, "dsa")) { + if ((err = load_dsa_private_key(dsa_filenamebase, &dsa_key))) { + HIP_ERROR("Loading of the DSA key failed\n"); + goto out_err; + } + dsa_key_rr_len = dsa_to_dns_key_rr(dsa_key, &dsa_key_rr); + HIP_IFEL(dsa_key_rr_len <= 0, -EFAULT, "dsa_key_rr_len <= 0\n"); + + if ((err = dsa_to_hip_endpoint(dsa_key, &endpoint_dsa_hip, + anon ? HIP_ENDPOINT_FLAG_ANON : 0, hostname))) { + HIP_ERROR("Failed to allocate and build DSA endpoint.\n"); + goto out_err; + } + if ((err = hip_build_param_eid_endpoint(msg, endpoint_dsa_hip))) { + HIP_ERROR("Building of host id failed\n"); + goto out_err; + } + } else { /*RSA*/ + if ((err = load_rsa_private_key(rsa_filenamebase, &rsa_key))) { + HIP_ERROR("Loading of the RSA key failed\n"); + goto out_err; + } + rsa_key_rr_len = rsa_to_dns_key_rr(rsa_key, &rsa_key_rr); + HIP_IFEL(rsa_key_rr_len <= 0, -EFAULT, "rsa_key_rr_len <= 0\n"); + + if ((err = rsa_to_hip_endpoint(rsa_key, &endpoint_rsa_hip, + anon ? HIP_ENDPOINT_FLAG_ANON : 0, hostname))) { + HIP_ERROR("Failed to allocate and build RSA endpoint.\n"); + goto out_err; + } + if ((err = hip_build_param_eid_endpoint(msg, endpoint_rsa_hip))) { + HIP_ERROR("Building of host id failed\n"); + goto out_err; + } + } + goto skip_host_id; + } + + /* using default */ + + HIP_IFEL(hi_fmt == NULL, -1, "Key type is null.\n"); + + if (!strcmp(hi_fmt, "dsa")) { + if ((err = load_dsa_private_key(dsa_filenamebase, &dsa_key))) { + HIP_ERROR("Loading of the DSA key failed\n"); + goto out_err; + } + + dsa_key_rr_len = dsa_to_dns_key_rr(dsa_key, &dsa_key_rr); + HIP_IFEL(dsa_key_rr_len <= 0, -EFAULT, "dsa_key_rr_len <= 0\n"); + + if ((err = dsa_to_hip_endpoint(dsa_key, &endpoint_dsa_hip, + HIP_ENDPOINT_FLAG_ANON, hostname))) { + HIP_ERROR("Failed to allocate and build DSA endpoint (anon).\n"); + goto out_err; + } + + if ((err = hip_private_dsa_to_hit(dsa_key, dsa_key_rr, + HIP_HIT_TYPE_HASH100, &dsa_lhi.hit))) { + HIP_ERROR("Conversion from DSA to HIT failed\n"); + goto out_err; + } + + if ((err = load_dsa_private_key(dsa_filenamebase_pub, &dsa_pub_key))) { + HIP_ERROR("Loading of the DSA key (pub) failed\n"); + goto out_err; + } + + dsa_pub_key_rr_len = dsa_to_dns_key_rr(dsa_pub_key, &dsa_pub_key_rr); + HIP_IFEL(dsa_pub_key_rr_len <= 0, -EFAULT, "dsa_pub_key_rr_len <= 0\n"); + + HIP_DEBUG_HIT("DSA HIT", &dsa_lhi.hit); + + if ((err = hip_private_dsa_to_hit(dsa_pub_key, dsa_pub_key_rr, + HIP_HIT_TYPE_HASH100, &dsa_pub_lhi.hit))) { + HIP_ERROR("Conversion from DSA to HIT failed\n"); + goto out_err; + } + HIP_DEBUG_HIT("DSA HIT", &dsa_pub_lhi.hit); + + if ((err = dsa_to_hip_endpoint(dsa_pub_key, + &endpoint_dsa_pub_hip, 0, hostname))) { + HIP_ERROR("Failed to allocate and build DSA endpoint (pub).\n"); + goto out_err; + } + } else if (anon) { /* rsa anon */ + if ((err = load_rsa_private_key(rsa_filenamebase, &rsa_key))) { + HIP_ERROR("Loading of the RSA key failed\n"); + goto out_err; + } + + rsa_key_rr_len = rsa_to_dns_key_rr(rsa_key, &rsa_key_rr); + HIP_IFEL(rsa_key_rr_len <= 0, -EFAULT, "rsa_key_rr_len <= 0\n"); + + if ((err = rsa_to_hip_endpoint(rsa_key, &endpoint_rsa_hip, + HIP_ENDPOINT_FLAG_ANON, hostname))) { + HIP_ERROR("Failed to allocate and build RSA endpoint (anon).\n"); + goto out_err; + } + + if ((err = hip_private_rsa_to_hit(rsa_key, rsa_key_rr, + HIP_HIT_TYPE_HASH100, &rsa_lhi.hit))) { + HIP_ERROR("Conversion from RSA to HIT failed\n"); + goto out_err; + } + HIP_DEBUG_HIT("RSA HIT", &rsa_lhi.hit); + } else { /* rsa pub */ + if ((err = load_rsa_private_key(rsa_filenamebase_pub, &rsa_pub_key))) { + HIP_ERROR("Loading of the RSA key (pub) failed\n"); + goto out_err; + } + + rsa_pub_key_rr_len = rsa_to_dns_key_rr(rsa_pub_key, &rsa_pub_key_rr); + HIP_IFEL(rsa_pub_key_rr_len <= 0, -EFAULT, "rsa_pub_key_rr_len <= 0\n"); + + if ((err = rsa_to_hip_endpoint(rsa_pub_key, + &endpoint_rsa_pub_hip, 0, hostname))) { + HIP_ERROR("Failed to allocate and build RSA endpoint (pub).\n"); + goto out_err; + } + + if ((err = hip_private_rsa_to_hit(rsa_pub_key, rsa_pub_key_rr, + HIP_HIT_TYPE_HASH100, &rsa_pub_lhi.hit))) { + HIP_ERROR("Conversion from RSA to HIT failed\n"); + goto out_err; + } + HIP_DEBUG_HIT("RSA HIT", &rsa_pub_lhi.hit); + } + + break; + } /* end switch */ + + if (numeric_action == 0) { + goto skip_msg; + } + + if (!strcmp(hi_fmt, "dsa")) { + if ((err = hip_build_param_eid_endpoint(msg, endpoint_dsa_hip))) { + HIP_ERROR("Building of host id failed\n"); + goto out_err; + } + if ((err = hip_build_param_eid_endpoint(msg, endpoint_dsa_pub_hip))) { + HIP_ERROR("Building of host id failed\n"); + goto out_err; + } + } else if (anon) { + if ((err = hip_build_param_eid_endpoint(msg, endpoint_rsa_hip))) { + HIP_ERROR("Building of host id failed\n"); + goto out_err; + } + } else { + if ((err = hip_build_param_eid_endpoint(msg, endpoint_rsa_pub_hip))) { + HIP_ERROR("Building of host id failed\n"); + goto out_err; + } + } + +skip_host_id: +skip_msg: + +out_err: + if (dsa_filenamebase != NULL) { + change_key_file_perms(dsa_filenamebase); + } + if (rsa_filenamebase != NULL) { + change_key_file_perms(rsa_filenamebase); + } + if (dsa_filenamebase_pub != NULL) { + change_key_file_perms(dsa_filenamebase_pub); + } + if (rsa_filenamebase_pub != NULL) { + change_key_file_perms(rsa_filenamebase_pub); + } + + if (dsa_host_id) { + free(dsa_host_id); + } + if (dsa_pub_host_id) { + free(dsa_pub_host_id); + } + if (rsa_host_id) { + free(rsa_host_id); + } + if (rsa_pub_host_id) { + free(rsa_pub_host_id); + } + if (dsa_key) { + DSA_free(dsa_key); + } + if (rsa_key) { + RSA_free(rsa_key); + } + if (dsa_pub_key) { + DSA_free(dsa_pub_key); + } + if (rsa_pub_key) { + RSA_free(rsa_pub_key); + } + if (dsa_key_rr) { + free(dsa_key_rr); + } + if (rsa_key_rr) { + free(rsa_key_rr); + } + if (dsa_pub_key_rr) { + free(dsa_pub_key_rr); + } + if (rsa_pub_key_rr) { + free(rsa_pub_key_rr); + } + if (dsa_filenamebase) { + free(dsa_filenamebase); + } + if (rsa_filenamebase) { + free(rsa_filenamebase); + } + if (dsa_filenamebase_pub) { + free(dsa_filenamebase_pub); + } + if (rsa_filenamebase_pub) { + free(rsa_filenamebase_pub); + } + if (endpoint_dsa_hip) { + free(endpoint_dsa_hip); + } + if (endpoint_rsa_hip) { + free(endpoint_rsa_hip); + } + if (endpoint_dsa_pub_hip) { + free(endpoint_dsa_pub_hip); + } + if (endpoint_rsa_pub_hip) { + free(endpoint_rsa_pub_hip); + } + + return err; +} + +/** + * create DNS KEY RR record from host DSA key + * @param dsa the DSA structure from where the KEY RR record is to be created + * @param dsa_key_rr where the resultin KEY RR is stored + * + * @note Caller must free dsa_key_rr when it is not used anymore. + * + * @return On successful operation, the length of the KEY RR buffer is + * returned (greater than zero) and pointer to the buffer containing + * DNS KEY RR is stored at dsa_key_rr. On error function returns negative + * and sets dsa_key_rr to NULL. + */ +int dsa_to_dns_key_rr(DSA *dsa, unsigned char **dsa_key_rr) +{ + int err = 0; + int dsa_key_rr_len = -1; + signed char t; /* in units of 8 bytes */ + unsigned char *p = NULL; + int key_len; + + HIP_ASSERT(dsa != NULL); /* should not happen */ + + *dsa_key_rr = NULL; + + _HIP_DEBUG("numbytes p=%d\n", BN_num_bytes(dsa->p)); + _HIP_DEBUG("numbytes q=%d\n", BN_num_bytes(dsa->q)); + _HIP_DEBUG("numbytes g=%d\n", BN_num_bytes(dsa->g)); + // shouldn't this be NULL also? + _HIP_DEBUG("numbytes pubkey=%d\n", BN_num_bytes(dsa->pub_key)); + + + /* notice that these functions allocate memory */ + _HIP_DEBUG("p=%s\n", BN_bn2hex(dsa->p)); + _HIP_DEBUG("q=%s\n", BN_bn2hex(dsa->q)); + _HIP_DEBUG("g=%s\n", BN_bn2hex(dsa->g)); + _HIP_DEBUG("pubkey=%s\n", BN_bn2hex(dsa->pub_key)); + + /* ***** is use of BN_num_bytes ok ? ***** */ + t = (BN_num_bytes(dsa->p) - 64) / 8; + HIP_IFEL((t < 0 || t > 8), -EINVAL, + "Invalid RSA key length %d bits\n", (64 + t * 8) * 8); + _HIP_DEBUG("t=%d\n", t); + + /* RFC 2536 section 2 */ + /* + * Field Size + * ----- ---- + * T 1 octet + * Q 20 octets + * P 64 + T*8 octets + * G 64 + T*8 octets + * Y 64 + T*8 octets + * [ X 20 optional octets (private key hack) ] + * + */ + key_len = 64 + t * 8; + dsa_key_rr_len = 1 + DSA_PRIV + 3 * key_len; + + if (dsa->priv_key) { + dsa_key_rr_len += DSA_PRIV; /* private key hack */ + _HIP_DEBUG("Private key included\n"); + } else { + _HIP_DEBUG("No private key\n"); + } + + _HIP_DEBUG("dsa key rr len = %d\n", dsa_key_rr_len); + *dsa_key_rr = malloc(dsa_key_rr_len); + HIP_IFEL(!*dsa_key_rr, -ENOMEM, "Malloc for *dsa_key_rr failed\n"); + memset(*dsa_key_rr, 0, dsa_key_rr_len); + + p = *dsa_key_rr; + + /* set T */ + memset(p, t, 1); // XX FIX: WTF MEMSET? + p++; + _HIP_HEXDUMP("DSA KEY RR after T:", *dsa_key_rr, p - *dsa_key_rr); + + /* add given dsa_param to the *dsa_key_rr */ + + bn2bin_safe(dsa->q, p, DSA_PRIV); + p += DSA_PRIV; + _HIP_HEXDUMP("DSA KEY RR after Q:", *dsa_key_rr, p - *dsa_key_rr); + + bn2bin_safe(dsa->p, p, key_len); + p += key_len; + _HIP_HEXDUMP("DSA KEY RR after P:", *dsa_key_rr, p - *dsa_key_rr); + + bn2bin_safe(dsa->g, p, key_len); + p += key_len; + _HIP_HEXDUMP("DSA KEY RR after G:", *dsa_key_rr, p - *dsa_key_rr); + + bn2bin_safe(dsa->pub_key, p, key_len); + p += key_len; + _HIP_HEXDUMP("DSA KEY RR after Y:", *dsa_key_rr, p - *dsa_key_rr); + + if (dsa->priv_key) { + bn2bin_safe(dsa->priv_key, p, DSA_PRIV); + _HIP_HEXDUMP("DSA KEY RR after X:", *dsa_key_rr, p - *dsa_key_rr); + } + +out_err: + + if (err) { + if (*dsa_key_rr) { + free(*dsa_key_rr); + } + return err; + } else { + return dsa_key_rr_len; + } +} + +/** + * create a DNS KEY RR record from a given host RSA public key + * + * @param rsa the RSA structure from where the KEY RR record is to be created + * @param rsa_key_rr where the resultin KEY RR is stored + * @return On successful operation, the length of the KEY RR buffer is + * returned (greater than zero) and pointer to the buffer containing + * DNS KEY RR is stored at rsa_key_rr. On error function returns + * negative and sets rsa_key_rr to NULL. + * @note Caller must free rsa_key_rr when it is not used anymore. + * @note This function assumes that RSA given as a parameter is always public. + */ +int rsa_to_dns_key_rr(RSA *rsa, unsigned char **rsa_key_rr) +{ + int err = 0; + int rsa_key_rr_len = -1; + unsigned char *c = NULL; + int public = -1; + int e_len_bytes = 1; + int e_len, key_len; + + HIP_ASSERT(rsa != NULL); /* should not happen */ + + *rsa_key_rr = NULL; + + e_len = BN_num_bytes(rsa->e); + key_len = RSA_size(rsa); + + /* RFC 3110 limits e to 4096 bits */ + HIP_IFEL(e_len > 512, -EINVAL, "Invalid rsa->e length %d bytes\n", e_len); + if (e_len > 255) { + e_len_bytes = 3; + } + + /* let's check if the RSA key is public or private + * private exponent is NULL in public keys */ + if (rsa->d == NULL) { + public = 1; + rsa_key_rr_len = e_len_bytes + e_len + key_len; + + /* + * See RFC 2537 for flags, protocol and algorithm and check RFC 3110 for + * the RSA public key part ( 1-3 octets defining length of the exponent, + * exponent is as many octets as the length defines and the modulus is + * all the rest of the bytes). + */ + } else { + public = 0; + rsa_key_rr_len = e_len_bytes + e_len + key_len * 9 / 2; + } + + *rsa_key_rr = malloc(rsa_key_rr_len); + HIP_IFEL(!*rsa_key_rr, -ENOMEM, "Malloc for *rsa_key_rr failed\n"); + memset(*rsa_key_rr, 0, rsa_key_rr_len); + + c = *rsa_key_rr; + + if (e_len_bytes == 1) { + *c = (unsigned char) e_len; + } + c++; /* If e_len is more than one byte, first byte is 0. */ + if (e_len_bytes == 3) { + *c = htons((uint16_t) e_len); + c += 2; + } + + bn2bin_safe(rsa->e, c, e_len); + c += e_len; + bn2bin_safe(rsa->n, c, key_len); + c += key_len; + + if (!public) { + bn2bin_safe(rsa->d, c, key_len); + c += key_len; + bn2bin_safe(rsa->p, c, key_len / 2); + c += key_len / 2; + bn2bin_safe(rsa->q, c, key_len / 2); + c += key_len / 2; + bn2bin_safe(rsa->dmp1, c, key_len / 2); + c += key_len / 2; + bn2bin_safe(rsa->dmq1, c, key_len / 2); + c += key_len / 2; + bn2bin_safe(rsa->iqmp, c, key_len / 2); + } + +out_err: + + if (err) { + if (*rsa_key_rr) { + free(*rsa_key_rr); + } + return err; + } + + return rsa_key_rr_len; +} === added file 'lib/core/hostid.h' --- lib/core/hostid.h 1970-01-01 00:00:00 +0000 +++ lib/core/hostid.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,68 @@ +#ifndef HIP_LIB_CORE_HOSTID_H +#define HIP_LIB_CORE_HOSTID_H + +#include "state.h" + +struct hip_rsa_keylen { + int e_len; + int e; + int n; +}; + +struct hip_hit_info { + struct hip_lhi lhi; + hip_lsi_t lsi; +}; + +int hip_verify_packet_signature(struct hip_common *pkt, + struct hip_host_id *peer_host_id); + +int hip_dsa_host_id_to_hit(const struct hip_host_id *host_id, + struct in6_addr *hit, int hit_type); + +/* Useless abstraction, goes to the same function anyway -- SAMU + * + * True that. Let's make this a static inline function and move it to the header + * file. It still remains as useless abstraction, but at least we eliminate the + * need for a call and return sequence. -Lauri 06.08.2008 + */ +static inline int hip_rsa_host_id_to_hit(const struct hip_host_id *host_id, + struct in6_addr *hit, int hit_type) +{ + return hip_dsa_host_id_to_hit(host_id, hit, hit_type); +} + +int hip_host_id_to_hit(const struct hip_host_id *host_id, + struct in6_addr *hit, int hit_type); +int hip_private_dsa_host_id_to_hit(const struct hip_host_id_priv *host_id, + struct in6_addr *hit, + int hit_type); +int hip_private_rsa_host_id_to_hit(const struct hip_host_id_priv *host_id, + struct in6_addr *hit, + int hit_type); +int hip_private_host_id_to_hit(const struct hip_host_id_priv *host_id, + struct in6_addr *hit, int hit_type); +int hip_host_id_contains_private_key(struct hip_host_id *host_id); +void hip_get_rsa_keylen(const struct hip_host_id_priv *host_id, + struct hip_rsa_keylen *ret, + int is_priv); + +RSA *hip_key_rr_to_rsa(const struct hip_host_id_priv *host_id, int is_priv); +DSA *hip_key_rr_to_dsa(const struct hip_host_id_priv *host_id, int is_priv); +int dsa_to_dns_key_rr(DSA *dsa, unsigned char **buf); +int rsa_to_dns_key_rr(RSA *rsa, unsigned char **rsa_key_rr); +int hip_host_id_entry_to_hit_info(struct hip_host_id_entry *entry, + void *msg); +int hip_serialize_host_id_action(struct hip_common *msg, + int action, + int anon, + int use_default, + const char *hi_fmt, + const char *hi_file, + int rsa_key_bits, + int dsa_key_bits); +int khi_encode(unsigned char *orig, int orig_len, + unsigned char *encoded, + int encoded_len); + +#endif /* HIP_LIB_CORE_HOSTID_H */ === added file 'lib/core/hostsfiles.c' --- lib/core/hostsfiles.c 1970-01-01 00:00:00 +0000 +++ lib/core/hostsfiles.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,624 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * This file contains iterator functions to access and parse + * /etc/hosts and /etc/hip/hosts files. Also, this file contains a + * number of predefined functions that support mapping between + * hostnames, HITs, LSIs and routable IP addresses. + * + * @brief parser for /etc/hosts and /etc/hip/hosts + * + * @author Miika Komu <miika@xxxxxx> + * + * @todo is there a standard API for accessing hosts files? + */ + +/* required for s6_addr32 */ +#define _BSD_SOURCE + +#include <arpa/inet.h> +#include <time.h> +#include <netinet/in.h> + +#include "config.h" + +#include "hostsfiles.h" +#include "lib/tool/lutil.h" + +/** + * A "for-each" iterator function for hosts files that returns the first + * hostname that matches the given address + * + * @param entry a hosts file line entry + * @param arg the IPv6 or IPv6-mapped IPv4 address to match + * @param result An output argument where the matching hostname will be + * written. Minimum buffer length is HOST_NAME_MAX chars. + * @return zero on match or one otherwise + */ +int hip_map_first_id_to_hostname_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int err = 1; + + if (!ipv6_addr_cmp((struct in6_addr *) arg, &entry->id)) { + _HIP_DEBUG("Match on line %d\n", entry->lineno); + memcpy(result, entry->hostname, strlen(entry->hostname)); + err = 0; /* Stop at the first match */ + } + + return err; +} + +/** + * A "for-each" iterator function for hosts files that returns the first + * hostname that matches the given LSI + * + * @param entry a hosts file line entry + * @param arg an IPv6-mapped LSI to match + * @param result An output argument where the matching hostname will be + * written. Minimum buffer length is HOST_NAME_MAX chars. + * @return zero on match or one otherwise + */ +int hip_map_first_lsi_to_hostname_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int err = 1; + int is_lsi = hip_id_type_match(&entry->id, 2); + + if (!ipv6_addr_cmp((struct in6_addr *) arg, &entry->id) && is_lsi) { + _HIP_DEBUG("Match on line %d\n", entry->lineno); + memcpy(result, entry->hostname, strlen(entry->hostname)); + err = 0; /* Stop at the first match */ + } + + return err; +} + +/** + * find the hostname matching the given LSI from /etc/hip/hosts and + * /etc/hosts (in this particular order) + * + * @param lsi the LSI to match + * @param hostname An output argument where the matching hostname + * will be written. Minimum buffer length is + * HOST_NAME_MAX chars. + * @return zero on successful match or non-zero otherwise + */ +int hip_map_lsi_to_hostname_from_hosts(hip_lsi_t *lsi, char *hostname) +{ + return hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_lsi_to_hostname_from_hosts, + lsi, hostname) && + hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_lsi_to_hostname_from_hosts, + lsi, hostname); +} + +/** + * A "for-each" iterator function for hosts files that returns the first + * HIT that matches the hostname + * + * @param entry a hosts file line entry + * @param arg a hostname as a string + * @param result An output argument where the matching matching HIT will be + * written. Minimum buffer length is sizeof(struct hip_hit_t) + * @return zero on match or one otherwise + */ +int hip_map_first_hostname_to_hit_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int err = 1; + int is_hit; + + /* test if hostname/alias matches and the type is hit */ + if (!strncmp(arg, entry->hostname, HOST_NAME_MAX) || + (entry->alias && !strncmp(arg, entry->alias, HOST_NAME_MAX)) || + (entry->alias2 && !strncmp(arg, entry->alias2, HOST_NAME_MAX))) { + is_hit = hip_id_type_match(&entry->id, 1); + + HIP_IFE(!is_hit, 1); + + _HIP_DEBUG("Match on line %d\n", entry->lineno); + ipv6_addr_copy(result, &entry->id); + err = 0; /* Stop at the first match */ + } + +out_err: + + return err; +} + +/** + * A "for-each" iterator function for hosts files that returns the first + * LSI that matches the hostname + * + * @param entry a hosts file line entry + * @param arg a hostname as a string + * @param result An output argument where the matching matching LSI will be + * written in IPv6 mapped format. Minimum buffer length is + * sizeof(struct in6_addr) + * @return zero on match or one otherwise + */ +int hip_map_first_hostname_to_lsi_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int err = 1; + int is_lsi; + + /* test if hostname/alias matches and the type is lsi */ + if (!strncmp(arg, entry->hostname, HOST_NAME_MAX) || + (entry->alias && !strncmp(arg, entry->alias, HOST_NAME_MAX)) || + (entry->alias2 && !strncmp(arg, entry->alias2, HOST_NAME_MAX))) { + is_lsi = hip_id_type_match(&entry->id, 2); + + HIP_IFE(!is_lsi, 1); + + _HIP_DEBUG("Match on line %d\n", entry->lineno); + ipv6_addr_copy(result, &entry->id); + err = 0; /* Stop at the first match */ + } + +out_err: + + return err; +} + +/** + * A "for-each" iterator function for hosts files that returns the first + * routable IP address that matches the hostname + * + * @param entry a hosts file line entry + * @param arg a hostname as a string + * @param result An output argument where the matching matching IP address will be + * written. IPv4 addresses are written in IPv6 mapped format and + * the minimum buffer length is sizeof(struct in6_addr) + * @return zero on match or one otherwise + */ +int hip_map_first_hostname_to_ip_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int err = 1; + int is_lsi, is_hit; + + /* test if hostname/alias matches and the type is routable ip */ + if (!strncmp(arg, entry->hostname, HOST_NAME_MAX) || + (entry->alias && !strncmp(arg, entry->alias, HOST_NAME_MAX)) || + (entry->alias2 && !strncmp(arg, entry->alias2, HOST_NAME_MAX))) { + is_hit = hip_id_type_match(&entry->id, 1); + is_lsi = hip_id_type_match(&entry->id, 2); + + HIP_IFE((is_hit || is_lsi), 1); + + _HIP_DEBUG("Match on line %d\n", entry->lineno); + ipv6_addr_copy(result, &entry->id); + err = 0; /* Stop at the first match */ + } + +out_err: + + return err; +} + +/** + * A "for-each" iterator function for hosts files to calculate + * the number of non-commented lines + * + * @param entry a hosts file line entry + * @param arg unused, but required by the API + * @param result an int pointer where the number of lines + * will be calculated + * @return always one + */ +int hip_calc_lines_in_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int *res = (int *) result; + (*res)++; + return 1; +} + +/** + * A "for-each" iterator function for hosts files that returns the Nth + * identifier (address, LSI or HIT) from a hosts file + * + * @param entry a hosts file line entry + * @param arg the N as an int pointer + * @param result An output argument where the matching matching address will be + * written. IPv4 addresses are written in IPv6 mapped format and + * the minimum buffer length is sizeof(struct in6_addr). + * @return zero on match or one otherwise + */ +int hip_get_nth_id_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result) +{ + int err = 1; + const int *nth = (const int *) arg; + int *total_past = (int *) result; + + if (*nth == *total_past) { + ipv6_addr_copy(result, &entry->id); + err = 0; + } else { + (*total_past)++; + } + return err; +} + +/** + * "For-each" loop to iterate through /etc/hosts or /etc/hip/hosts file, line + * by line. + * + * @param hosts_file the path and name to the hosts file + * @param func the iterator function pointer + * @param arg an input argument for the function pointer + * @param an output argument for the function pointer + * @return zero on success or non-zero on failure + */ +int hip_for_each_hosts_file_line(const char *hosts_file, + int(*func)(const struct hosts_file_line *line, + const void *arg, + void *result), + void *arg, + void *result) +{ + FILE *hip_hosts = NULL; + List mylist; + char line[500]; + int err = 0, lineno = 0; + struct in_addr in_addr; + struct hosts_file_line entry; + char *hostname = NULL, *alias = NULL, *alias2 = NULL, *addr_ptr = NULL; + + initlist(&mylist); + memset(line, 0, sizeof(line)); + + /* check whether given hit_str is actually a HIT */ + + hip_hosts = fopen(hosts_file, "r"); + + HIP_IFEL(!hip_hosts, -1, "Failed to open hosts file\n"); + + /* For each line in the given hosts file, convert the line into binary format and + * call the given the handler */ + + err = 1; + while (fgets(line, sizeof(line) - 1, hip_hosts) != NULL) { + char *eofline, *c, *comment; + int len; + + lineno++; + c = line; + + /* Remove whitespace */ + while (*c == ' ' || *c == '\t') { + c++; + } + + /* Line is a comment or empty */ + if (*c == '#' || *c == '\n' || *c == '\0') { + continue; + } + + eofline = strchr(c, '\n'); + if (eofline) { + *eofline = '\0'; + } + + /* Terminate before (the first) trailing comment */ + comment = strchr(c, '#'); + if (comment) { + *comment = '\0'; + } + + /* shortest hostname: ":: a" = 4 */ + if ((len = strlen(c)) < 4) { + HIP_DEBUG("skip line\n"); + continue; + } + + _HIP_DEBUG("lineno=%d, str=%s\n", lineno, c); + + /* Split line into list */ + extractsubstrings(c, &mylist); + + len = length(&mylist); + if (len < 2 || len > 4) { + HIP_ERROR("Bad number of items on line %d in %s, skipping\n", + lineno, hosts_file); + continue; + } + + /* The list contains hosts line in reverse order. Let's sort it. */ + switch (len) { + case (2): + alias = NULL; + hostname = getitem(&mylist, 0); + addr_ptr = getitem(&mylist, 1); + break; + case (3): + alias = getitem(&mylist, 0); + hostname = getitem(&mylist, 1); + addr_ptr = getitem(&mylist, 2); + break; + case (4): + alias2 = getitem(&mylist, 0); + alias = getitem(&mylist, 1); + hostname = getitem(&mylist, 2); + addr_ptr = getitem(&mylist, 3); + break; + } + + /* Initialize entry */ + + memset(&entry, 0, sizeof(entry)); + + HIP_ASSERT(addr_ptr); + err = inet_pton(AF_INET6, addr_ptr, &entry.id); + if (err <= 0) { + err = inet_pton(AF_INET, addr_ptr, &in_addr); + if (err <= 0) { + HIP_ERROR("Bad address %s on line %d in %s, skipping\n", + addr_ptr, lineno, hosts_file); + continue; + } + IPV4_TO_IPV6_MAP(&in_addr, &entry.id); + } + + entry.hostname = hostname; + HIP_ASSERT(entry.hostname) + + entry.alias2 = alias2; + entry.alias = alias; + entry.lineno = lineno; + + /* Finally, call the handler function to handle the line */ + + if (func(&entry, arg, result) == 0) { + _HIP_DEBUG("Match on line %d in %s\n", lineno, hosts_file); + err = 0; + break; + } + + memset(line, 0, sizeof(line)); + destroy(&mylist); + } + +out_err: + + destroy(&mylist); + + if (hip_hosts) { + fclose(hip_hosts); + } + + return err; +} + +/** + * find the HIT matching to the given LSI from /etc/hip/hosts and + * /etc/hosts (in this particular order) + * + * @param lsi the LSI to match + * @param hit An output argument where the matching matching HIT will be + * written. Minimum buffer length is sizeof(struct hip_hit_t) + * @return zero on successful match or non-zero otherwise + */ +int hip_map_lsi_to_hit_from_hosts_files(hip_lsi_t *lsi, hip_hit_t *hit) +{ + int err = 0; + uint8_t hostname[HOST_NAME_MAX]; + struct in6_addr mapped_lsi; + + memset(hostname, 0, sizeof(hostname)); + HIP_ASSERT(lsi && hit); + + IPV4_TO_IPV6_MAP(lsi, &mapped_lsi); + + err = hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + &mapped_lsi, hostname); + if (err) { + err = hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + &mapped_lsi, hostname); + } + + HIP_IFEL(err, -1, "Failed to map id to hostname\n"); + + err = hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_hostname_to_hit_from_hosts, + hostname, hit); + if (err) { + err = hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_hostname_to_hit_from_hosts, + hostname, hit); + } + + HIP_IFEL(err, -1, "Failed to map id to hostname\n"); + + HIP_DEBUG_HIT("Found hit: ", hit); + +out_err: + + return err; +} + +/** + * find the LSI matching to the given HIT from /etc/hip/hosts and + * /etc/hosts (in this particular order) + * + * @param hit the HIT to match + * @param lsi An output argument where the matching matching LSI will + * will be written + * @return zero on successful match or non-zero otherwise + */ +int hip_map_hit_to_lsi_from_hosts_files(const hip_hit_t *hit, hip_lsi_t *lsi) +{ + int err = 0; + uint8_t hostname[HOST_NAME_MAX]; + struct in6_addr mapped_lsi; + + memset(hostname, 0, sizeof(hostname)); + HIP_ASSERT(lsi && hit); + + err = (hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + (hip_hit_t *) hit, hostname) && + hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + (hip_hit_t *) hit, hostname)); + HIP_IFEL(err, -1, "Failed to map id to hostname\n"); + + err = (hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_hostname_to_lsi_from_hosts, + hostname, &mapped_lsi) && + hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_hostname_to_lsi_from_hosts, + hostname, &mapped_lsi)); + HIP_IFEL(err, -1, "Failed to map hostname to lsi\n"); + + IPV6_TO_IPV4_MAP(&mapped_lsi, lsi); + + HIP_DEBUG_LSI("Found lsi: ", lsi); + +out_err: + + return err; +} + +/** + * Fetch a random host name from a hosts file. Currently this + * is used for selecting a random DHT node for load balancing. + * + * @param filename the hosts file path and file name + * @param hostname the hostname will be written here + * @param id_str The address, LSI or HIT corresponding to the + * the hostname will be written here as a string. + * @return zero on successful match or non-zero on failure + */ +int hip_get_random_hostname_id_from_hosts(char *filename, + char *hostname, + char *id_str) +{ + int lines = 0, err = 0, nth; + struct in6_addr id; + + memset(&id, 0, sizeof(struct in6_addr)); + + /* ignore return value, returns always error */ + hip_for_each_hosts_file_line(filename, + hip_calc_lines_in_hosts, + NULL, + &lines); + HIP_IFEL((lines == 0), -1, + "No lines in host file %s\n", filename); + + srand(time(NULL)); + nth = rand() % lines; + + err = hip_for_each_hosts_file_line(filename, + hip_get_nth_id_from_hosts, + &nth, + &id); + HIP_IFEL(err, -1, "Failed to get random id\n"); + + err = hip_for_each_hosts_file_line(filename, + hip_map_first_id_to_hostname_from_hosts, + &id, + hostname); + HIP_IFEL(err, -1, "Failed to map to hostname\n"); + + if (IN6_IS_ADDR_V4MAPPED(&id)) { + struct in_addr id4; + IPV6_TO_IPV4_MAP(&id, &id4); + HIP_IFEL(!inet_ntop(AF_INET, &id4, id_str, + INET_ADDRSTRLEN), -1, + "inet_ntop failed\n"); + } else { + HIP_IFEL(!inet_ntop(AF_INET6, &id, id_str, + INET6_ADDRSTRLEN), -1, + "inet_ntop failed\n"); + } + +out_err: + return err; +} + +/** + * This function maps a HIT or a LSI (nodename) to an IP address using the two hosts files. + * The function implements this in two steps. First, it maps the HIT or LSI to an hostname + * from /etc/hip/hosts or /etc/hosts. Second, it maps the hostname to a IP address from + * /etc/hosts. The IP address is returned in the res argument. + * + * @param hit a HIT to be mapped + * @param lsi an LSI to be mapped + * @param ip the resulting routable IP address if found + * @return zero on successful match or non-zero otherwise + */ +int hip_map_id_to_ip_from_hosts_files(hip_hit_t *hit, hip_lsi_t *lsi, struct in6_addr *ip) +{ + int err = 0; + uint8_t hostname[HOST_NAME_MAX]; + + HIP_ASSERT((hit || lsi) && ip); + + memset(hostname, 0, sizeof(hostname)); + + if (hit && !ipv6_addr_any(hit)) { + err = hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + hit, hostname); + } else { + struct in6_addr mapped_lsi; + IPV4_TO_IPV6_MAP(lsi, &mapped_lsi); + err = (hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + &mapped_lsi, hostname) && + hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + &mapped_lsi, hostname)); + } + + HIP_IFEL(err, -1, "Failed to map id to hostname\n"); + + err = hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_hostname_to_ip_from_hosts, + hostname, ip); + HIP_IFEL(err, -1, "Failed to map id to ip\n"); + +out_err: + return err; +} + +/** + * check if the given LSI is in the hosts files + * + * @param lsi the LSI to be searched for + * @return one if the LSI exists or zero otherwise + * + */ +int hip_host_file_info_exists_lsi(hip_lsi_t *lsi) +{ + uint8_t hostname[HOST_NAME_MAX]; + struct in6_addr mapped_lsi; + + memset(hostname, 0, sizeof(hostname)); + + IPV4_TO_IPV6_MAP(lsi, &mapped_lsi); + + return !(hip_for_each_hosts_file_line(HIPL_HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + &mapped_lsi, hostname) && + hip_for_each_hosts_file_line(HOSTS_FILE, + hip_map_first_id_to_hostname_from_hosts, + &mapped_lsi, hostname)); +} === added file 'lib/core/hostsfiles.h' --- lib/core/hostsfiles.h 1970-01-01 00:00:00 +0000 +++ lib/core/hostsfiles.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,40 @@ +#ifndef HIP_LIB_CORE_HOSTSFILES_H +#define HIP_LIB_CORE_HOSTSFILES_H + +#include "prefix.h" +#include "lib/conf/hipconf.h" + +#ifndef HOST_NAME_MAX +# define HOST_NAME_MAX 64 +#endif /* HOST_NAME_MAX */ + +int hip_map_first_id_to_hostname_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result); +int hip_map_first_hostname_to_hit_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result); +int hip_map_first_hostname_to_lsi_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result); +int hip_map_first_hostname_to_ip_from_hosts(const struct hosts_file_line *entry, + const void *arg, + void *result); +int hip_for_each_hosts_file_line(const char *hosts_file, + int(*func)(const struct hosts_file_line *line, + const void *arg, + void *result), + void *arg, + void *result); +int hip_map_lsi_to_hit_from_hosts_files(hip_lsi_t *lsi, hip_hit_t *hit); +int hip_map_hit_to_lsi_from_hosts_files(const hip_hit_t *hit, hip_lsi_t *lsi); +int hip_map_id_to_ip_from_hosts_files(hip_hit_t *hit, + hip_lsi_t *lsi, + struct in6_addr *ip); +int hip_map_lsi_to_hostname_from_hosts(hip_lsi_t *lsi, char *hostname); +int hip_get_random_hostname_id_from_hosts(char *filename, + char *hostname, + char *id_str); +int hip_host_file_info_exists_lsi(hip_lsi_t *lsi); + +#endif /* HIP_LIB_CORE_HOSTSFILES_H */ === added file 'lib/core/keylen.c' --- lib/core/keylen.c 1970-01-01 00:00:00 +0000 +++ lib/core/keylen.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,103 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Various key length calculation functions + * + * @author Miika Komu <miika@xxxxxx> + */ + +#include "keylen.h" +#include "protodefs.h" +#include "debug.h" + +/** + * get encryption key length for a transform + * + * @param tid transform + * @return the encryption key length of the chosen transform, + * or negative on error. + */ +int hip_enc_key_length(int tid) +{ + int ret = -1; + + switch (tid) { + case HIP_ESP_AES_SHA1: + ret = 16; + break; + case HIP_ESP_3DES_SHA1: + ret = 24; + break; + case HIP_ESP_NULL_SHA1: + case HIP_ESP_NULL_NULL: + ret = 0; + break; + default: + HIP_ERROR("unknown tid=%d\n", tid); + HIP_ASSERT(0); + break; + } + + return ret; +} + +/** + * get hmac key length of a transform + * + * @param tid transform + * @return the encryption key length based of the chosen transform, + * or negative on error. + */ +int hip_hmac_key_length(int tid) +{ + int ret = -1; + switch (tid) { + case HIP_ESP_AES_SHA1: + case HIP_ESP_3DES_SHA1: + case HIP_ESP_NULL_SHA1: + ret = 20; + break; + case HIP_ESP_NULL_NULL: + ret = 0; + break; + default: + HIP_ERROR("unknown tid=%d\n", tid); + HIP_ASSERT(0); + break; + } + + return ret; +} + + +/** + * get authentication key length for an ESP transform + * + * @param tid transform + * @return the authentication key length for the chosen transform. + * or negative on error + */ +int hip_auth_key_length_esp(int tid) +{ + int ret = -1; + + switch (tid) { + case HIP_ESP_AES_SHA1: + case HIP_ESP_NULL_SHA1: + case HIP_ESP_3DES_SHA1: + ret = 20; + break; + case HIP_ESP_NULL_NULL: + ret = 0; + break; + default: + HIP_ERROR("unknown tid=%d\n", tid); + HIP_ASSERT(0); + break; + } + + return ret; +} + === added file 'lib/core/keylen.h' --- lib/core/keylen.h 1970-01-01 00:00:00 +0000 +++ lib/core/keylen.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,8 @@ +#ifndef HIP_LIB_CORE_KEYLEN_H +#define HIP_LIB_CORE_KEYLEN_H + +int hip_auth_key_length_esp(int tid); +int hip_hmac_key_length(int tid); +int hip_enc_key_length(int tid); + +#endif /* HIP_LIB_CORE_KEYLEN_H */ === modified file 'lib/core/message.c' --- lib/core/message.c 2010-03-19 09:32:05 +0000 +++ lib/core/message.c 2010-03-19 09:53:35 +0000 @@ -67,7 +67,9 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <unistd.h> #include "message.h" +#include "hip_udp.h" /** * Finds out how much data is coming from a socket @@ -309,9 +311,6 @@ * @return zero on success and negative on failure * @note currently the only SOCK_DGRAM and AF_INET6 are supported */ -/* - * Don't call this function directly. Use hip_send_recv_daemon_info instead - */ static int hip_send_recv_daemon_info_internal(struct hip_common *msg, int opt_socket) { int hip_user_sock = 0, err = 0, n = 0, len = 0; === modified file 'lib/core/message.h' --- lib/core/message.h 2010-03-03 13:16:18 +0000 +++ lib/core/message.h 2010-03-19 09:53:35 +0000 @@ -9,17 +9,10 @@ #ifndef HIP_LIB_CORE_MESSAGE_H #define HIP_LIB_CORE_MESSAGE_H -#if HAVE_CONFIG_H -#include <config.h> -#endif - #include <errno.h> #include <netinet/in.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/tool/nlink.h" #include "debug.h" #include "icomm.h" === modified file 'lib/core/prefix.c' --- lib/core/prefix.c 2010-03-03 13:16:18 +0000 +++ lib/core/prefix.c 2010-03-19 09:53:35 +0000 @@ -15,6 +15,11 @@ #define _BSD_SOURCE #include "prefix.h" +#include "builder.h" + +/* Definitions */ +#define HIP_ID_TYPE_HIT 1 +#define HIP_ID_TYPE_LSI 2 /** * Test if the given IPv6 address has HIT prefix (RFC4843 ORCHID prefix) @@ -111,3 +116,289 @@ lsi_begin |= htonl(HIP_LSI_PREFIX); memcpy(lsi, &lsi_begin, sizeof(hip_closest_prefix_type_t)); } + +/** + * compare two LSIs for equality + * + * @param lsi1 an LSI + * @param lsi2 an LSI + * @return one if the LSIs are equal or zero otherwise + */ +int hip_lsi_are_equal(const hip_lsi_t *lsi1, + const hip_lsi_t *lsi2) +{ + return ipv4_addr_cmp(lsi1, lsi2) == 0; +} + +/** + * check the type of an IPv6 addresses + * + * @param id an IPv6 address, possibly in IPv6 mapped format + * @param type HIP_ID_TYPE_HIT or HIP_ID_TYPE_LSI + * + * @return zero for type match, greater than zero for mismatch or + * negative on error + */ +int hip_id_type_match(const struct in6_addr *id, int id_type) +{ + int ret = 0, is_lsi = 0, is_hit = 0; + hip_lsi_t lsi; + + if (ipv6_addr_is_hit(id)) { + is_hit = 1; + } else if (IN6_IS_ADDR_V4MAPPED(id)) { + IPV6_TO_IPV4_MAP(id, &lsi); + if (IS_LSI32(lsi.s_addr)) { + is_lsi = 1; + } + } + + HIP_ASSERT(!(is_lsi && is_hit)); + + if (id_type == HIP_ID_TYPE_HIT) { + ret = (is_hit ? 1 : 0); + } else if (id_type == HIP_ID_TYPE_LSI) { + ret = (is_lsi ? 1 : 0); + } else { + ret = ((is_hit || is_lsi) ? 0 : 1); + } + + return ret; +} + +#ifdef CONFIG_HIP_OPPORTUNISTIC +/** + * Convert a given IP address into a pseudo HIT + * + * @param ip an IPv4 or IPv6 address address + * @param hit a pseudo HIT generated from the IP address + * @param hit_type the type of the HIT + * @return zero on success and non-zero on failure + * @see <a + * href="http://hipl.hiit.fi/hipl/thesis_teresa_finez.pdf";>T. Finez, + * Backwards Compatibility Experimentation with Host Identity Protocol + * and Legacy Software and Networks , final project, December 2008</a> + * + */ +int hip_opportunistic_ipv6_to_hit(const struct in6_addr *ip, + struct in6_addr *hit, + int hit_type) +{ + int err = 0; + uint8_t digest[HIP_AH_SHA_LEN]; + char *key = (char *) (ip); + unsigned int key_len = sizeof(struct in6_addr); + + HIP_IFE(hit_type != HIP_HIT_TYPE_HASH100, -ENOSYS); + _HIP_HEXDUMP("key", key, key_len); + HIP_IFEL((err = hip_build_digest(HIP_DIGEST_SHA1, key, key_len, digest)), + err, + "Building of digest failed\n"); + + memcpy(hit, digest + (HIP_AH_SHA_LEN - sizeof(struct in6_addr)), + sizeof(struct in6_addr)); + + hit->s6_addr32[3] = 0; // this separates phit from normal hit + + set_hit_prefix(hit); + +out_err: + + return err; +} + +#endif /* CONFIG_HIP_OPPORTUNISTIC */ + +/** + * cast a socket address to an IPv4 or IPv6 address. + * + * @note The parameter @c sockaddr is first cast to a struct sockaddr + * and the IP address cast is then done based on the value of the + * sa_family field in the struct sockaddr. If sa_family is neither + * AF_INET nor AF_INET6, the cast fails. + * + * @param sockaddr a pointer to a socket address that holds the IP address. + * @return a pointer to an IPv4 or IPv6 address inside @c sockaddr or + * NULL if the cast fails. + */ + +void *hip_cast_sa_addr(const struct sockaddr *sa) +{ + if (sa == NULL) { + HIP_ERROR("sockaddr is NULL, skipping type conversion\n"); + + return NULL; + } + + switch (sa->sa_family) { + case AF_INET: + return &(((struct sockaddr_in *) sa)->sin_addr); + case AF_INET6: + return &(((struct sockaddr_in6 *) sa)->sin6_addr); + default: + HIP_ERROR("unhandled type: %i, skipping cast\n", sa->sa_family); + return NULL; + } +} + +/** + * Test if a sockaddr_in6 structure is in IPv6 mapped format (i.e. + * contains an IPv4 address) + * + * @param sa socket address structure + * @return one if the structure is in IPv6 mapped format or zero otherwise + */ +int hip_sockaddr_is_v6_mapped(struct sockaddr *sa) +{ + int family = sa->sa_family; + + HIP_ASSERT(family == AF_INET || family == AF_INET6); + if (family != AF_INET6) { + return 0; + } else { + return IN6_IS_ADDR_V4MAPPED((struct in6_addr *) hip_cast_sa_addr(sa)); + } +} + +/** + * Calculate the actual length of any sockaddr structure + * + * @param sockaddr the sockaddr structure + * @return the length of the actual sockaddr structure in bytes + */ +int hip_sockaddr_len(const void *sockaddr) +{ + struct sockaddr *sa = (struct sockaddr *) sockaddr; + int len; + + switch (sa->sa_family) { + case AF_INET: + len = sizeof(struct sockaddr_in); + break; + case AF_INET6: + len = sizeof(struct sockaddr_in6); + break; + case AF_UNIX: + len = sizeof(struct sockaddr_un); + break; + default: + len = 0; + } + return len; +} + +/** + * Calculate the address field length of any sockaddr structure + * + * @param sockaddr the sockaddr structure + * @return the length of the address field in the @c sockaddr structure + */ +int hip_sa_addr_len(void *sockaddr) +{ + struct sockaddr *sa = (struct sockaddr *) sockaddr; + int len; + + switch (sa->sa_family) { + case AF_INET: + len = 4; + break; + case AF_INET6: + len = 16; + break; + default: + len = 0; + } + return len; +} + +/** + * converts an in6_addr structure to sockaddr_storage + * + * @param addr the in6_addr to convert + * @param sa a sockaddr_storage structure where the result is stored + * @note remember to fill in the port number by yourself + * if necessary + */ +void hip_addr_to_sockaddr(struct in6_addr *addr, struct sockaddr_storage *sa) +{ + memset(sa, 0, sizeof(struct sockaddr_storage)); + + if (IN6_IS_ADDR_V4MAPPED(addr)) { + struct sockaddr_in *in = (struct sockaddr_in *) sa; + in->sin_family = AF_INET; + IPV6_TO_IPV4_MAP(addr, &in->sin_addr); + } else { + struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) sa; + in6->sin6_family = AF_INET6; + ipv6_addr_copy(&in6->sin6_addr, addr); + } +} + +/** + * verify if a given IPv6 address or IPv6 mapped IPv4 address + * is a loopback + * + * @param addr the address to verify + * @return one if the address if loopback or zero otherwise + */ +int hip_addr_is_loopback(struct in6_addr *addr) +{ + struct in_addr addr_in; + + if (!IN6_IS_ADDR_V4MAPPED(addr)) { + return IN6_IS_ADDR_LOOPBACK(addr); + } + IPV6_TO_IPV4_MAP(addr, &addr_in); + return IS_IPV4_LOOPBACK(addr_in.s_addr); +} + +int ipv4_addr_cmp(const struct in_addr *a1, + const struct in_addr *a2) { + return memcmp((const char *) a1, (const char *) a2, + sizeof(struct in_addr)); +} + +void ipv4_addr_copy(struct in_addr *a1, + const struct in_addr *a2) { + memcpy((char *) a1, (const char *) a2, sizeof(struct in_addr)); +} + +int ipv6_addr_cmp(const struct in6_addr *a1, + const struct in6_addr *a2) { + return memcmp((const char *) a1, (const char *) a2, + sizeof(struct in6_addr)); +} + +void ipv6_addr_copy(struct in6_addr *a1, + const struct in6_addr *a2) { + memcpy((char *) a1, (const char *) a2, sizeof(struct in6_addr)); +} + +int ipv6_addr_any(const struct in6_addr *a) { + return (a->s6_addr[0] | a->s6_addr[1] | a->s6_addr[2] | a->s6_addr[3] | + a->s6_addr[4] |a->s6_addr[5] |a->s6_addr[6] |a->s6_addr[7] | + a->s6_addr[8] |a->s6_addr[9] |a->s6_addr[10] |a->s6_addr[11] | + a->s6_addr[12] |a->s6_addr[13] |a->s6_addr[14] |a->s6_addr[15]) == 0; +} + +void hip_copy_in6addr_null_check(struct in6_addr *to, + struct in6_addr *from) { + HIP_ASSERT(to); + if (from) { + ipv6_addr_copy(to, from); + } else { + memset(to, 0, sizeof(*to)); + } +} + +void hip_copy_inaddr_null_check(struct in_addr *to, + struct in_addr *from) { + HIP_ASSERT(to); + if (from) { + memcpy(to, from, sizeof(*to)); + } else { + memset(to, 0, sizeof(*to)); + } +} + + === modified file 'lib/core/prefix.h' --- lib/core/prefix.h 2010-03-03 13:16:18 +0000 +++ lib/core/prefix.h 2010-03-19 09:53:35 +0000 @@ -1,10 +1,6 @@ #ifndef HIP_LIB_CORE_UTILS_H #define HIP_LIB_CORE_UTILS_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #ifdef __KERNEL__ # include <linux/un.h> # include <linux/in6.h> @@ -41,6 +37,31 @@ int hit_is_opportunistic_hit(const struct in6_addr *hit); void set_hit_prefix(struct in6_addr *hit); void set_lsi_prefix(hip_lsi_t *lsi); +int hip_id_type_match(const struct in6_addr *id, int id_type); +int hip_opportunistic_ipv6_to_hit(const struct in6_addr *ip, + struct in6_addr *hit, int hit_type); +void *hip_cast_sa_addr(const struct sockaddr *sa); +int hip_sockaddr_len(const void *sockaddr); +int hip_sa_addr_len(void *sockaddr); +void hip_addr_to_sockaddr(struct in6_addr *addr, struct sockaddr_storage *sa); +int hip_sockaddr_is_v6_mapped(struct sockaddr *sa); +int hip_addr_is_loopback(struct in6_addr *addr); +int hip_lsi_are_equal(const hip_lsi_t *lsi1, + const hip_lsi_t *lsi2); + +int ipv4_addr_cmp(const struct in_addr *a1, + const struct in_addr *a2); +void ipv4_addr_copy(struct in_addr *a1, + const struct in_addr *a2); +int ipv6_addr_cmp(const struct in6_addr *a1, + const struct in6_addr *a2); +void ipv6_addr_copy(struct in6_addr *a1, + const struct in6_addr *a2); +int ipv6_addr_any(const struct in6_addr *a); +void hip_copy_in6addr_null_check(struct in6_addr *to, + struct in6_addr *from); +void hip_copy_inaddr_null_check(struct in_addr *to, + struct in_addr *from); /* IN6_IS_ADDR_V4MAPPED(a) is defined in /usr/include/netinet/in.h */ === modified file 'lib/core/protodefs.h' --- lib/core/protodefs.h 2010-02-17 17:38:08 +0000 +++ lib/core/protodefs.h 2010-03-19 09:53:35 +0000 @@ -22,6 +22,8 @@ #endif #endif +#define IPV4_HDR_SIZE 20 + #define HIP_MAX_PACKET 4096 #define HIP_MAX_NETWORK_PACKET 2048 /** @addtogroup hip_msg === added file 'lib/core/solve.c' --- lib/core/solve.c 1970-01-01 00:00:00 +0000 +++ lib/core/solve.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,177 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief HIP computation puzzle solving algorithms + * + * @author Miika Komu <miika@xxxxxx> + */ + +#include "solve.h" + +/** + * solve a computational puzzle for HIP + * + * @param puzzle_or_solution Either a pointer to hip_puzzle or hip_solution structure + * @param hdr The incoming R1/I2 packet header. + * @param mode Either HIP_VERIFY_PUZZLE of HIP_SOLVE_PUZZLE + * + * @note The K and I is read from the @c puzzle_or_solution. + * @note Regarding to return value of zero, I don't see why 0 couldn't solve the + * puzzle too, but since the odds are 1/2^64 to try 0, I don't see the point + * in improving this now. + * @return The J that solves the puzzle is returned, or 0 to indicate an error. + */ +uint64_t hip_solve_puzzle(void *puzzle_or_solution, + struct hip_common *hdr, + int mode) +{ + uint64_t mask = 0; + uint64_t randval = 0; + uint64_t maxtries = 0; + uint64_t digest = 0; + uint8_t cookie[48]; + int err = 0; + union { + struct hip_puzzle pz; + struct hip_solution sl; + } *u; + + HIP_HEXDUMP("puzzle", puzzle_or_solution, + (mode == HIP_VERIFY_PUZZLE ? sizeof(struct hip_solution) : + sizeof(struct hip_puzzle))); + + _HIP_DEBUG("\n"); + /* pre-create cookie */ + u = puzzle_or_solution; + + _HIP_DEBUG("current hip_cookie_max_k_r1=%d\n", max_k); + HIP_IFEL(u->pz.K > HIP_PUZZLE_MAX_K, 0, + "Cookie K %u is higher than we are willing to calculate" + " (current max K=%d)\n", u->pz.K, HIP_PUZZLE_MAX_K); + + mask = hton64((1ULL << u->pz.K) - 1); + memcpy(cookie, (uint8_t *) &(u->pz.I), sizeof(uint64_t)); + + HIP_DEBUG("(u->pz.I: 0x%llx\n", u->pz.I); + + if (mode == HIP_VERIFY_PUZZLE) { + ipv6_addr_copy((hip_hit_t *) (cookie + 8), &hdr->hits); + ipv6_addr_copy((hip_hit_t *) (cookie + 24), &hdr->hitr); + //randval = ntoh64(u->sl.J); + randval = u->sl.J; + _HIP_DEBUG("u->sl.J: 0x%llx\n", randval); + maxtries = 1; + } else if (mode == HIP_SOLVE_PUZZLE) { + ipv6_addr_copy((hip_hit_t *) (cookie + 8), &hdr->hitr); + ipv6_addr_copy((hip_hit_t *) (cookie + 24), &hdr->hits); + maxtries = 1ULL << (u->pz.K + 3); + get_random_bytes(&randval, sizeof(u_int64_t)); + } else { + HIP_IFEL(1, 0, "Unknown mode: %d\n", mode); + } + + HIP_DEBUG("K=%u, maxtries (with k+2)=%llu\n", u->pz.K, maxtries); + /* while loops should work even if the maxtries is unsigned + * if maxtries = 1 ---> while(1 > 0) [maxtries == 0 now]... + * the next round while (0 > 0) [maxtries > 0 now] + */ + while (maxtries-- > 0) { + uint8_t sha_digest[HIP_AH_SHA_LEN]; + + /* must be 8 */ + memcpy(cookie + 40, (uint8_t *) &randval, sizeof(uint64_t)); + + hip_build_digest(HIP_DIGEST_SHA1, cookie, 48, sha_digest); + + /* copy the last 8 bytes for checking */ + memcpy(&digest, sha_digest + 12, sizeof(uint64_t)); + + /* now, in order to be able to do correctly the bitwise + * AND-operation we have to remember that little endian + * processors will interpret the digest and mask reversely. + * digest is the last 64 bits of the sha1-digest.. how that is + * ordered in processors registers etc.. does not matter to us. + * If the last 64 bits of the sha1-digest is + * 0x12345678DEADBEEF, whether we have 0xEFBEADDE78563412 + * doesn't matter because the mask matters... if the mask is + * 0x000000000000FFFF (or in other endianness + * 0xFFFF000000000000). Either ways... the result is + * 0x000000000000BEEF or 0xEFBE000000000000, which the cpu + * interprets as 0xBEEF. The mask is converted to network byte + * order (above). + */ + if ((digest & mask) == 0) { + _HIP_DEBUG("*** Puzzle solved ***: 0x%llx\n", randval); + _HIP_HEXDUMP("digest", sha_digest, HIP_AH_SHA_LEN); + _HIP_HEXDUMP("cookie", cookie, sizeof(cookie)); + return randval; + } + + /* It seems like the puzzle was not correctly solved */ + HIP_IFEL(mode == HIP_VERIFY_PUZZLE, 0, "Puzzle incorrect\n"); + randval++; + } + + HIP_ERROR("Could not solve the puzzle, no solution found\n"); +out_err: + return err; +} + +#ifdef CONFIG_HIP_MIDAUTH +/** + * solve a midauth puzzle which is essentially a normal HIP cookie + * with some extra whipped cream on the top + * + * @param out the received R1 message + * @param in an I2 message where the solution will be written + * @param entry the related host association + * @return zero on success and negative on error + * @see <a + * href="http://tools.ietf.org/id/draft-heer-hip-middle-auth";>Heer et + * al, End-Host Authentication for HIP Middleboxes, Internet draft, + * work in progress, February 2009</a> + */ +int hip_solve_puzzle_m(struct hip_common *out, + struct hip_common *in, + hip_ha_t *entry) +{ + struct hip_challenge_request *pz; + struct hip_puzzle tmp; + uint64_t solution; + int err = 0; + uint8_t digist[HIP_AH_SHA_LEN]; + + + pz = hip_get_param(in, HIP_PARAM_CHALLENGE_REQUEST); + while (pz) { + if (hip_get_param_type(pz) != HIP_PARAM_CHALLENGE_REQUEST) { + break; + } + + HIP_IFEL(hip_build_digest(HIP_DIGEST_SHA1, pz->opaque, 24, digist) < 0, + -1, "Building of SHA1 Random seed I failed\n"); + tmp.type = pz->type; + tmp.length = pz->length; + tmp.K = pz->K; + tmp.lifetime = pz->lifetime; + tmp.opaque[0] = tmp.opaque[1] = 0; + tmp.I = *digist & 0x40; //truncate I to 8 byte length + + HIP_IFEL((solution = entry->hadb_misc_func->hip_solve_puzzle( + &tmp, in, HIP_SOLVE_PUZZLE)) == 0, + -EINVAL, "Solving of puzzle failed\n"); + + HIP_IFEL(hip_build_param_challenge_response(out, pz, ntoh64(solution)) < 0, + -1, + "Error while creating solution_m reply parameter\n"); + pz = (struct hip_challenge_request *) hip_get_next_param(in, + (struct hip_tlv_common *) pz); + } + +out_err: + return err; +} +#endif /* CONFIG_HIP_MIDAUTH */ + === added file 'lib/core/solve.h' --- lib/core/solve.h 1970-01-01 00:00:00 +0000 +++ lib/core/solve.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,19 @@ +#ifndef HIP_LIB_CORE_SOLVE_H +#define HIP_LIB_CORE_SOLVE_H + +#include <sys/types.h> + +#include "config.h" +#include "lib/core/crypto.h" +#include "protodefs.h" +#include "state.h" + + +#define HIP_PUZZLE_MAX_K 28 + +uint64_t hip_solve_puzzle(void *puzzle, struct hip_common *hdr, int mode); +int hip_solve_puzzle_m(struct hip_common *out, + struct hip_common *in, + hip_ha_t *entry); + +#endif /* HIP_LIB_CORE_SOLVE_H */ === modified file 'lib/core/sqlitedbapi.c' --- lib/core/sqlitedbapi.c 2010-02-17 17:38:08 +0000 +++ lib/core/sqlitedbapi.c 2010-03-19 09:53:35 +0000 @@ -5,10 +5,7 @@ * */ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #ifdef CONFIG_HIP_AGENT #include "sqlitedbapi.h" === modified file 'lib/core/sqlitedbapi.h' --- lib/core/sqlitedbapi.h 2010-02-17 17:38:08 +0000 +++ lib/core/sqlitedbapi.h 2010-03-19 09:53:35 +0000 @@ -15,10 +15,8 @@ #include <stdio.h> #include <sqlite3.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ +#include "config.h" #include "debug.h" #include "ife.h" === modified file 'lib/core/state.h' --- lib/core/state.h 2010-03-19 09:24:10 +0000 +++ lib/core/state.h 2010-03-19 09:53:35 +0000 @@ -7,15 +7,10 @@ #ifndef HIP_LIB_CORE_STATE_H #define HIP_LIB_CORE_STATE_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #ifndef __KERNEL__ #include "hashtable.h" #include "esp_prot_common.h" #include "hip_statistics.h" - #endif #define HIP_ENDPOINT_FLAG_PUBKEY 0 === added file 'lib/core/straddr.c' --- lib/core/straddr.c 1970-01-01 00:00:00 +0000 +++ lib/core/straddr.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,177 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Conversion functions from string to address and vice versa + * + * @author Miika Komu <miika@xxxxxx> + */ + +/* required for s6_addr32 */ +#define _BSD_SOURCE + +#include <errno.h> +#include <arpa/inet.h> +#include <ctype.h> +#include <openssl/evp.h> +#include "config.h" +#include "straddr.h" +#include "debug.h" + +/** + * convert a binary IPv6 address to a string + * + * @param in6 the IPv6 address to convert + * @param buf a preallocated buffer where the string will be stored + * @return a pointer to the buf + */ +char *hip_in6_ntop(const struct in6_addr *in6, char *buf) +{ + if (!buf) { + return NULL; + } + sprintf(buf, + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", + ntohs(in6->s6_addr16[0]), ntohs(in6->s6_addr16[1]), + ntohs(in6->s6_addr16[2]), ntohs(in6->s6_addr16[3]), + ntohs(in6->s6_addr16[4]), ntohs(in6->s6_addr16[5]), + ntohs(in6->s6_addr16[6]), ntohs(in6->s6_addr16[7])); + return buf; +} + +/** + * convert a string into a binary IPv4 address (a wrapper for inet_pton()) + * + * @param str the string to convert + * @param ip an output argument that will contain a binary IPv4 calculated + * from the @c str + * @return zero on success and negative on error + */ +int convert_string_to_address_v4(const char *str, struct in_addr *ip) +{ + int ret = 0, err = 0; + + ret = inet_pton(AF_INET, str, ip); + HIP_IFEL((ret < 0 && errno == EAFNOSUPPORT), -1, + "inet_pton: not a valid address family\n"); + HIP_IFEL((ret == 0), -1, + "inet_pton: %s: not a valid network address\n", str); +out_err: + return err; +} + +/** + * Convert a string to an IPv6 address. This function can handle + * also IPv6 mapped addresses. + * + * @param str the string to convert + * @param ip6 An output argument that will contain a binary IPv4 calculated + * from the @c str. Possibly in IPv6 mapped format. + * @return zero on success or negative on error + */ +int convert_string_to_address(const char *str, + struct in6_addr *ip6) +{ + int ret = 0, err = 0; + struct in_addr ip4; + + ret = inet_pton(AF_INET6, str, ip6); + HIP_IFEL((ret < 0 && errno == EAFNOSUPPORT), -1, + "\"%s\" is not of valid address family.\n", str); + if (ret > 0) { + /* IPv6 address conversion was ok */ + _HIP_DEBUG_IN6ADDR("Converted IPv6", ip6); + goto out_err; + } + + /* Might be an ipv4 address (ret == 0). Lets catch it here. */ + err = convert_string_to_address_v4(str, &ip4); + if (err) { + goto out_err; + } + + IPV4_TO_IPV6_MAP(&ip4, ip6); + HIP_DEBUG("Mapped v4 to v6.\n"); + HIP_DEBUG_IN6ADDR("mapped v6", ip6); + +out_err: + return err; +} + +/** + * convert a string containing upper case characters to lower case + * + * @param to the result of the conversion (minimum length @c count) + * @param from a string possibly containing upper case characters + * @return zero on success or negative on failure + */ +int hip_string_to_lowercase(char *to, const char *from, const size_t count) +{ + if (to == NULL || from == NULL || count == 0) { + return -1; + } + + int i = 0; + + for (; i < count; i++) { + if (isalpha(from[i])) { + to[i] = tolower(from[i]); + } else { + to[i] = from[i]; + } + } + return 0; +} + +/** + * test if a given string contains a positive integer + * + * @param string the string to test + * @return zero if the string is digit or negative otherwise + */ +int hip_string_is_digit(const char *string) +{ + if (string == NULL) { + return -1; + } + + int i = 0; + + while (string[i] != '\0') { + if (!isdigit(string[i])) { + return -1; + } + i++; + } + return 0; +} + + +/** + * encode the given content to Base64 + * + * @param buf Pointer to contents to be encoded + * @param len How long is the first parameter in bytes + * + * @return Returns a pointer to encoded content or NULL on error + */ +unsigned char *base64_encode(unsigned char *buf, unsigned int len) +{ + unsigned char *ret; + unsigned int b64_len; + + b64_len = (((len + 2) / 3) * 4) + 1; + ret = (unsigned char *) malloc(b64_len); + if (ret == NULL) { + goto out_err; + } + EVP_EncodeBlock(ret, buf, len); + return ret; +out_err: + if (ret) { + free(ret); + } + return NULL; +} + === added file 'lib/core/straddr.h' --- lib/core/straddr.h 1970-01-01 00:00:00 +0000 +++ lib/core/straddr.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,14 @@ +#ifndef HIP_LIB_CORE_STRADDR_H +#define HIP_LIB_CORE_STRADDR_H + +#include <sys/types.h> +#include <netinet/in.h> + +int convert_string_to_address_v4(const char *str, struct in_addr *ip); +int convert_string_to_address(const char *str, struct in6_addr *ip6); +char *hip_in6_ntop(const struct in6_addr *in6, char *buf); +int hip_string_to_lowercase(char *to, const char *from, const size_t count); +int hip_string_is_digit(const char *string); +unsigned char *base64_encode(unsigned char *, unsigned int); + +#endif /* HIP_LIB_CORE_STRADDR_H */ === added file 'lib/core/transform.c' --- lib/core/transform.c 1970-01-01 00:00:00 +0000 +++ lib/core/transform.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,148 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Transform related functions for HIP + * + * @author Miika Komu <miika@xxxxxx> + */ + +#include "debug.h" +#include "builder.h" +#include "transform.h" + +/** + * select a HIP transform + * + * @param ht HIP_TRANSFORM payload where the transform is selected from + * @return the first acceptable Transform-ID or negative if no + * acceptable transform was found. The return value is in host byte order. + */ +hip_transform_suite_t hip_select_hip_transform(struct hip_hip_transform *ht) +{ + hip_transform_suite_t tid = 0; + int i; + int length; + hip_transform_suite_t *suggestion; + + length = ntohs(ht->length); + suggestion = (hip_transform_suite_t *) &ht->suite_id[0]; + + if ((length >> 1) > 6) { + HIP_ERROR("Too many transforms (%d)\n", length >> 1); + goto out; + } + + for (i = 0; i < length; i++) { + switch (ntohs(*suggestion)) { + case HIP_HIP_AES_SHA1: + case HIP_HIP_3DES_SHA1: + case HIP_HIP_NULL_SHA1: + tid = ntohs(*suggestion); + goto out; + break; + + default: + /* Specs don't say what to do when unknown are found. + * We ignore. + */ + HIP_ERROR("Unknown HIP suite id suggestion (%u)\n", + ntohs(*suggestion)); + break; + } + suggestion++; + } + +out: + if (tid == 0) { + HIP_ERROR("None HIP transforms accepted\n"); + } else { + HIP_DEBUG("Chose HIP transform: %d\n", tid); + } + + return tid; +} + +/** + * select an ESP transform to use + * @param ht ESP_TRANSFORM payload where the transform is selected from + * + * @return the first acceptable Suite-ID or negative if no + * acceptable Suite-ID was found. + */ +hip_transform_suite_t hip_select_esp_transform(struct hip_esp_transform *ht) +{ + hip_transform_suite_t tid = 0; + int i; + int length; + hip_transform_suite_t *suggestion; + + length = hip_get_param_contents_len(ht); + suggestion = (uint16_t *) &ht->suite_id[0]; + + if (length > sizeof(struct hip_esp_transform) - + sizeof(struct hip_common)) { + HIP_ERROR("Too many transforms\n"); + goto out; + } + + for (i = 0; i < length; i++) { + switch (ntohs(*suggestion)) { + case HIP_ESP_AES_SHA1: + case HIP_ESP_NULL_NULL: + case HIP_ESP_3DES_SHA1: + case HIP_ESP_NULL_SHA1: + tid = ntohs(*suggestion); + goto out; + break; + default: + /* Specs don't say what to do when unknowns are found. + * We ignore. + */ + HIP_ERROR("Unknown ESP suite id suggestion (%u)\n", + ntohs(*suggestion)); + break; + } + suggestion++; + } + +out: + HIP_DEBUG("Took ESP transform %d\n", tid); + + if (tid == 0) { + HIP_ERROR("Faulty ESP transform\n"); + } + + return tid; +} + +/** + * get transform key length for a transform + * @param tid transform + * + * @return the transform key length based for the chosen transform, + * or negative on error. + */ +int hip_transform_key_length(int tid) +{ + int ret = -1; + + switch (tid) { + case HIP_HIP_AES_SHA1: + ret = 16; + break; + case HIP_HIP_3DES_SHA1: + ret = 24; + break; + case HIP_HIP_NULL_SHA1: // XX FIXME: SHOULD BE NULL_SHA1? + ret = 0; + break; + default: + HIP_ERROR("unknown tid=%d\n", tid); + HIP_ASSERT(0); + break; + } + + return ret; +} === added file 'lib/core/transform.h' --- lib/core/transform.h 1970-01-01 00:00:00 +0000 +++ lib/core/transform.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,11 @@ +#ifndef HIP_LIB_CORE_TRANSFORM_H +#define HIP_LIB_CORE_TRANSFORM_H + +#include "config.h" +#include "protodefs.h" + +hip_transform_suite_t hip_select_esp_transform(struct hip_esp_transform *ht); +hip_transform_suite_t hip_select_hip_transform(struct hip_hip_transform *ht); +int hip_transform_key_length(int tid); + +#endif /* HIP_LIB_CORE_TRANSFORM_H */ === modified file 'lib/dht/libhipdht.c' --- lib/dht/libhipdht.c 2010-03-03 13:16:18 +0000 +++ lib/dht/libhipdht.c 2010-03-19 09:53:35 +0000 @@ -18,6 +18,8 @@ #include <stdlib.h> #include <string.h> #include <netdb.h> +#include <unistd.h> +#include <ctype.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> @@ -31,7 +33,10 @@ #include "lib/core/debug.h" #include "lib/core/ife.h" #include "lib/core/icomm.h" -#include "lib/core/misc.h" +#include "lib/core/builder.h" +#include "lib/core/straddr.h" +#include "lib/core/message.h" + #include "libhipdht.h" #include "libhipdhtxml.h" === modified file 'lib/dht/libhipdht.h' --- lib/dht/libhipdht.h 2010-02-17 17:38:08 +0000 +++ lib/dht/libhipdht.h 2010-03-19 09:53:35 +0000 @@ -1,11 +1,11 @@ #ifndef HIP_LIB_DHT_LIBHIPDHT_H #define HIP_LIB_DHT_LIBHIPDHT_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - - +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> + +#include "config.h" #include "lib/core/protodefs.h" /* Resolve the gateway address using opendht.nyuld.net */ === modified file 'lib/dht/libhipdhtxml.c' --- lib/dht/libhipdhtxml.c 2010-02-17 17:38:08 +0000 +++ lib/dht/libhipdhtxml.c 2010-03-19 09:53:35 +0000 @@ -8,6 +8,7 @@ #include <libxml2/libxml/tree.h> #include "libhipdhtxml.h" #include "lib/core/debug.h" +#include "lib/core/straddr.h" #include "hipd/netdev.h" xmlNodePtr xml_new_param(xmlNodePtr node_parent, char *type, char *value); === modified file 'lib/ipsec/ipsec_strerror.c' --- lib/ipsec/ipsec_strerror.c 2010-03-03 13:16:18 +0000 +++ lib/ipsec/ipsec_strerror.c 2010-03-19 09:53:35 +0000 @@ -31,16 +31,13 @@ * SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <sys/types.h> #include <sys/param.h> - #include <string.h> #include <inttypes.h> #include <linux/ipsec.h> + +#include "config.h" #include "ipsec_strerror.h" int __ipsec_errcode; === modified file 'lib/ipsec/pfkey.c' --- lib/ipsec/pfkey.c 2010-03-03 13:16:18 +0000 +++ lib/ipsec/pfkey.c 2010-03-19 09:53:35 +0000 @@ -34,10 +34,6 @@ /* required for caddr_t */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -51,9 +47,10 @@ #include <errno.h> #include <stdio.h> +#include "config.h" #include "ipsec_strerror.h" #include "libpfkey.h" -#include "libinet6/include/net/pfkeyv2.h" +#include "pfkeyv2.h" #define CALLOC(size, cast) (cast) calloc(1, (size)) === added file 'lib/ipsec/pfkeyv2.h' --- lib/ipsec/pfkeyv2.h 1970-01-01 00:00:00 +0000 +++ lib/ipsec/pfkeyv2.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,71 @@ +/* $NetBSD: pfkeyv2.h,v 1.4 2006/09/09 16:22:08 manu Exp $ */ + +#ifndef __NET_PFKEYV2_H_ +#define __NET_PFKEYV2_H_ 1 + +#include <stdint.h> +#include <linux/pfkeyv2.h> + +/* Private allocations for authentication algorithms */ +#define SADB_AALG_SHA2_256 SADB_X_AALG_SHA2_256HMAC +#define SADB_X_AALG_SHA2_256 SADB_X_AALG_SHA2_256HMAC +#define SADB_AALG_SHA2_384 SADB_X_AALG_SHA2_384HMAC +#define SADB_X_AALG_SHA2_384 SADB_X_AALG_SHA2_384HMAC +#define SADB_AALG_SHA2_512 SADB_X_AALG_SHA2_512HMAC +#define SADB_X_AALG_SHA2_512 SADB_X_AALG_SHA2_512HMAC +#define SADB_AALG_RIPEMD160HMAC SADB_X_AALG_RIPEMD160HMAC +#define SADB_X_AALG_MD5 249 +#define SADB_X_AALG_SHA 250 + +/* private allocations - based on RFC2407/IANA assignment */ +#define SADB_X_EALG_CAST128CBC 5 /* SADB_X_EALG_CASTCBC? == 6 */ +#define SADB_X_EALG_RIJNDAELCBC SADB_X_EALG_AESCBC +#define SADB_X_EALG_AES SADB_X_EALG_AESCBC + + +#define SADB_X_CALG_NONE 0 +#define SADB_X_CALG_OUI 1 +#define SADB_X_CALG_DEFLATE 2 +#define SADB_X_CALG_LZS 3 +#define SADB_X_CALG_MAX 4 + + +#define SADB_X_EXT_NONE 0x0000 /* i.e. new format. */ +#define SADB_X_EXT_OLD 0x0001 /* old format. */ + +#define SADB_X_EXT_IV4B 0x0010 /* IV length of 4 bytes in use */ +#define SADB_X_EXT_DERIV 0x0020 /* DES derived */ +#define SADB_X_EXT_CYCSEQ 0x0040 /* allowing to cyclic sequence. */ + + /* three of followings are exclusive flags each them */ +#define SADB_X_EXT_PSEQ 0x0000 /* sequencial padding for ESP */ +#define SADB_X_EXT_PRAND 0x0100 /* random padding for ESP */ +#define SADB_X_EXT_PZERO 0x0200 /* zero padding for ESP */ +#define SADB_X_EXT_PMASK 0x0300 /* mask for padding flag */ + +#define SADB_X_EXT_RAWCPI 0x0080 /* use well known CPI (IPComp) */ + + +#define PFKEY_SOFT_LIFETIME_RATE 80 + +#define SADB_X_LIFETIME_ALLOCATIONS 0 +#define SADB_X_LIFETIME_BYTES 1 +#define SADB_X_LIFETIME_ADDTIME 2 +#define SADB_X_LIFETIME_USETIME 3 + + +#define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) +#define PFKEY_EXTLEN(msg) \ + PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len) +#define PFKEY_ADDR_PREFIX(ext) \ + (((struct sadb_address *)(ext))->sadb_address_prefixlen) +#define PFKEY_ADDR_PROTO(ext) \ + (((struct sadb_address *)(ext))->sadb_address_proto) +#define PFKEY_ADDR_SADDR(ext) \ + ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address))) + +/* in 64bits */ +#define PFKEY_UNUNIT64(a) ((a) << 3) +#define PFKEY_UNIT64(a) ((a) >> 3) + +#endif === modified file 'lib/ipsec/policy_parse.c' --- lib/ipsec/policy_parse.c 2010-03-03 13:16:18 +0000 +++ lib/ipsec/policy_parse.c 2010-03-19 09:53:35 +0000 @@ -44,10 +44,6 @@ #define YYPREFIX "__libipsec" #line 64 "policy_parse.y" -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -62,6 +58,7 @@ #include <errno.h> +#include "config.h" #include "ipsec_strerror.h" #include "libpfkey.h" === modified file 'lib/ipsec/policy_parse.y' --- lib/ipsec/policy_parse.y 2010-03-03 13:16:18 +0000 +++ lib/ipsec/policy_parse.y 2010-03-19 09:53:35 +0000 @@ -64,10 +64,6 @@ %{ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -82,11 +78,10 @@ #include <errno.h> -//#include "config.h" - +#include "config.h" #include "ipsec_strerror.h" #include "libpfkey.h" -#include "libinet6/include/net/pfkeyv2.h" +#include "pfkeyv2.h" #ifndef INT32_MAX #define INT32_MAX (0xffffffff) === modified file 'lib/ipsec/policy_token.l' --- lib/ipsec/policy_token.l 2010-03-03 13:16:18 +0000 +++ lib/ipsec/policy_token.l 2010-03-19 09:53:35 +0000 @@ -32,12 +32,10 @@ */ %{ +#include "config.h" + #ifdef CONFIG_HIP_PFKEY -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> === modified file 'lib/opphip/wrap.c' --- lib/opphip/wrap.c 2010-02-17 17:38:08 +0000 +++ lib/opphip/wrap.c 2010-03-19 09:53:35 +0000 @@ -15,10 +15,6 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #include <sys/types.h> #include <unistd.h> #include <errno.h> @@ -27,7 +23,9 @@ #include <pthread.h> #include <poll.h> +#include "config.h" #include "lib/core/debug.h" +#include "lib/core/message.h" #include "hipd/hadb.h" #include "lib/core/hashtable.h" #include "lib/tool/lutil.h" === modified file 'lib/opphip/wrap_db.c' --- lib/opphip/wrap_db.c 2010-02-17 17:38:08 +0000 +++ lib/opphip/wrap_db.c 2010-03-19 09:53:35 +0000 @@ -11,10 +11,6 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #include <sys/types.h> #include <unistd.h> #include <errno.h> @@ -22,6 +18,7 @@ #include <sys/socket.h> #include <pthread.h> +#include "config.h" #include "lib/core/hashtable.h" #include "hipd/hadb.h" #include "wrap_db.h" === modified file 'lib/performance/performance.c' --- lib/performance/performance.c 2010-03-19 09:32:05 +0000 +++ lib/performance/performance.c 2010-03-19 09:53:35 +0000 @@ -4,7 +4,8 @@ * \brief Primitive performance measurement library. * \author Tobias Heer * - * This file provides a set of functions to mneasure execution time. + * This file provides a set of functions to measure execution time. + * The measurement unit is second. * * \note Distributed under * <a href="http://www.gnu.org/licenses/gpl.txt";>GNU/GPL</a>. @@ -17,12 +18,6 @@ #include "lib/core/debug.h" #include "lib/core/ife.h" -int hip_perf_enabled() -{ - printf("PERF ENABLED"); - return 1; -} - /*! * \brief Create a set of performance slots. Each performance measurement type * needs a slot. === added file 'lib/tool/checksum.c' --- lib/tool/checksum.c 1970-01-01 00:00:00 +0000 +++ lib/tool/checksum.c 2010-03-19 09:53:35 +0000 @@ -0,0 +1,332 @@ +/** + * @file + * + * Distributed under <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> + * + * @brief Checksum functions + * + * @author Miika Komu <miika@xxxxxx> + * @note check if some of the checksum algos are redundant + */ + +/* required for s6_addr */ +#define _BSD_SOURCE + +#include <netinet/ip.h> +#include <sys/types.h> +#include <string.h> +#include "config.h" +#include "checksum.h" +#include "lib/core/debug.h" + +struct pseudo_header { + unsigned char src_addr[4]; + unsigned char dst_addr[4]; + uint8_t zero; + uint8_t protocol; + uint16_t packet_length; +}; +typedef struct pseudo_v6 { + struct in6_addr src; + struct in6_addr dst; + uint16_t length; + uint16_t zero1; + uint8_t zero2; + uint8_t next; +} pseudo_v6; + +/** @todo this is redundant with pseudo_v6 */ +struct pseudo_header6 { + unsigned char src_addr[16]; + unsigned char dst_addr[16]; + uint32_t packet_length; + unsigned char zero[3]; + uint8_t next_hdr; +}; + +/** + * Generate the IPv4 header checksum + * + * @param s source address + * @param d destination address + * @param c data + * @return the calculated IPv4 header checksum + */ +uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t len) +{ + uint8_t *src = s; + uint8_t *dst = d; + uint8_t *data = c; + uint16_t word16; + uint32_t sum; + uint16_t i; + + /* initialize sum to zero */ + sum = 0; + + /* make 16 bit words out of every two adjacent 8 bit words and */ + /* calculate the sum of all 16 vit words */ + for (i = 0; i < len; i = i + 2) { + word16 = ((((uint16_t) (data[i] << 8))) & 0xFF00) + (((uint16_t) data[i + 1]) & 0xFF); + sum = sum + (unsigned long) word16; + } + /* add the TCP pseudo header which contains: + the IP source and destination addresses, */ + for (i = 0; i < 4; i = i + 2) { + word16 = ((src[i] << 8) & 0xFF00) + (src[i + 1] & 0xFF); + sum = sum + word16; + } + for (i = 0; i < 4; i = i + 2) { + word16 = ((dst[i] << 8) & 0xFF00) + (dst[i + 1] & 0xFF); + sum = sum + word16; + } + /* the protocol number and the length of the TCP packet */ + sum = sum + protocol + len; + + /* keep only the last 16 bits of the 32 bit calculated sum + and add the carries */ + while (sum >> 16) { + sum = (sum & 0xFFFF) + (sum >> 16); + } + + /* Take the one's complement of sum */ + sum = ~sum; + return htons((unsigned short) sum); +} + +/** + * calculate IPv6 checksum + * + * @param protocol the protocol + * @param src source address + * @param dst destination address + * @param data the data to checksum + * @param len the length of the data + * @return the calculated checksum + */ +uint16_t ipv6_checksum(uint8_t protocol, + struct in6_addr *src, + struct in6_addr *dst, + void *data, uint16_t len) +{ + uint32_t chksum = 0; + pseudo_v6 pseudo; + memset(&pseudo, 0, sizeof(pseudo_v6)); + + pseudo.src = *src; + pseudo.dst = *dst; + pseudo.length = htons(len); + pseudo.next = protocol; + + chksum = inchksum(&pseudo, sizeof(pseudo_v6)); + chksum += inchksum(data, len); + + chksum = (chksum >> 16) + (chksum & 0xffff); + chksum += (chksum >> 16); + + chksum = (uint16_t) (~chksum); + if (chksum == 0) { + chksum = 0xffff; + } + + return chksum; +} + +/** calculate an IP checksum + * + * @param ip_hdr packet to be checksumed + * @param ip_hl header length field inside the header + * @return the IP checksum + * @note taken from RFC 1071 section 4.1 + */ +uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl) +{ + uint16_t checksum = 0; + unsigned long sum = 0; + int count = ip_hl * 4; + unsigned short *p = (unsigned short *) ip_hdr; + + /* + * this checksum algorithm can be found + * in RFC 1071 section 4.1 + */ + + /* one's complement sum 16-bit words of data */ + while (count > 1) { + sum += *p++; + count -= 2; + } + /* add left-over byte, if any */ + if (count > 0) { + sum += (unsigned char) *p; + } + + /* Fold 32-bit sum to 16 bits */ + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); + } + /* take the one's complement of the sum */ + checksum = (uint16_t) (~sum); + + return checksum; +} + +/** + * yet another checksummer + * + * @param data the data to checksum + * @param length the length of the data + * @return the calculated checksum + */ +uint16_t inchksum(const void *data, uint32_t length) +{ + long sum = 0; + const uint16_t *wrd = (uint16_t *) data; + long slen = (long) length; + + while (slen > 1) { + sum += *wrd++; + slen -= 2; + } + + if (slen > 0) { + sum += *((uint8_t *) wrd); + } + + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); + } + + return (uint16_t) sum; +} + +/** + * Standard BSD internet checksum routine from nmap + * for calculating the checksum field of the TCP header. + * + * @param ptr the data to checksum + * @param nbytes the length of data + * @return the checksum + * + * @note borrowed from Steven's network programming manual + */ +unsigned short in_cksum(uint16_t *ptr, int nbytes) +{ + register uint32_t sum; + uint16_t oddbyte; + register uint16_t answer; + + /* + * Our algorithm is simple, using a 32-bit accumulator (sum), + * we add sequential 16-bit words to it, and at the end, fold back + * all the carry bits from the top 16 bits into the lower 16 bits. + */ + sum = 0; + while (nbytes > 1) { + sum += *ptr++; + nbytes -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nbytes == 1) { + oddbyte = 0; /* make sure top half is zero */ + *((u_char *) &oddbyte) = *(u_char *) ptr; /* one byte only */ + sum += oddbyte; + } + + /* + * Add back carry outs from top 16 bits to low 16 bits. + */ + sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* ones-complement, then truncate to 16 bits */ + return answer; +} + +/** + * Calculates the checksum of a HIP packet with pseudo-header. + * + * @param data a pointer to a hip_common structure + * @param src The source address of the packet as a sockaddr_in or sockaddr_in6 + * structure in network byte order. IPv6 mapped addresses are not supported. + * @param dst The destination address of the packet as a sockaddr_in or sockaddr_in6 + * structure in network byte order. IPv6 mapped addresses are not supported. + * @return the checksum + * @note Checksumming is from Boeing's HIPD. + */ +uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr *dst) +{ + uint16_t checksum = 0; + unsigned long sum = 0; + int count = 0, length = 0; + unsigned short *p = NULL; /* 16-bit */ + struct pseudo_header pseudoh; + struct pseudo_header6 pseudoh6; + uint32_t src_network, dst_network; + struct in6_addr *src6, *dst6; + struct hip_common *hiph = (struct hip_common *) data; + + if (src->sa_family == AF_INET) { + /* IPv4 checksum based on UDP-- Section 6.1.2 */ + src_network = ((struct sockaddr_in *) src)->sin_addr.s_addr; + dst_network = ((struct sockaddr_in *) dst)->sin_addr.s_addr; + + memset(&pseudoh, 0, sizeof(struct pseudo_header)); + memcpy(&pseudoh.src_addr, &src_network, 4); + memcpy(&pseudoh.dst_addr, &dst_network, 4); + pseudoh.protocol = IPPROTO_HIP; + length = (hiph->payload_len + 1) * 8; + pseudoh.packet_length = htons(length); + + count = sizeof(struct pseudo_header); /* count always even number */ + p = (unsigned short *) &pseudoh; + } else { + /* IPv6 checksum based on IPv6 pseudo-header */ + src6 = &((struct sockaddr_in6 *) src)->sin6_addr; + dst6 = &((struct sockaddr_in6 *) dst)->sin6_addr; + + memset(&pseudoh6, 0, sizeof(struct pseudo_header6)); + memcpy(&pseudoh6.src_addr[0], src6, 16); + memcpy(&pseudoh6.dst_addr[0], dst6, 16); + length = (hiph->payload_len + 1) * 8; + pseudoh6.packet_length = htonl(length); + pseudoh6.next_hdr = IPPROTO_HIP; + + count = sizeof(struct pseudo_header6); /* count always even number */ + p = (unsigned short *) &pseudoh6; + } + /* + * this checksum algorithm can be found + * in RFC 1071 section 4.1 + */ + + /* sum the pseudo-header */ + /* count and p are initialized above per protocol */ + while (count > 1) { + sum += *p++; + count -= 2; + } + + /* one's complement sum 16-bit words of data */ + HIP_DEBUG("Checksumming %d bytes of data.\n", length); + count = length; + p = (unsigned short *) data; + while (count > 1) { + sum += *p++; + count -= 2; + } + /* add left-over byte, if any */ + if (count > 0) { + sum += (unsigned char) *p; + } + + /* Fold 32-bit sum to 16 bits */ + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); + } + /* take the one's complement of the sum */ + checksum = ~sum; + + return checksum; +} + === added file 'lib/tool/checksum.h' --- lib/tool/checksum.h 1970-01-01 00:00:00 +0000 +++ lib/tool/checksum.h 2010-03-19 09:53:35 +0000 @@ -0,0 +1,18 @@ +#ifndef HIP_LIB_CORE_CHECKSUM_H +#define HIP_LIB_CORE_CHECKSUM_H + +#include <sys/types.h> +#include <netinet/in.h> +#include "lib/core/protodefs.h" + +uint16_t ipv4_checksum(uint8_t protocol, void *s, void *d, void *c, uint16_t len); +uint16_t ipv6_checksum(uint8_t protocol, + struct in6_addr *src, + struct in6_addr *dst, + void *data, uint16_t len); +uint16_t checksum_ip(struct ip *ip_hdr, const unsigned int ip_hl); +unsigned short in_cksum(uint16_t *ptr, int nbytes); +uint16_t inchksum(const void *data, uint32_t length); +uint16_t hip_checksum_packet(char *data, struct sockaddr *src, struct sockaddr *dst); + +#endif /* HIP_LIB_CORE_CHECKSUM_H */ === modified file 'lib/tool/lutil.c' --- lib/tool/lutil.c 2010-02-17 17:38:08 +0000 +++ lib/tool/lutil.c 2010-03-19 09:53:35 +0000 @@ -4,7 +4,8 @@ * Distributed under * <a href="http://www.gnu.org/licenses/gpl2.txt";>GNU/GPL</a> * - * @brief String-related and linked list utilities borrowed from libinet6. + * @brief Utilities borrowed from libinet6. Function hip_timeval_diff() + * is borrowed from glibc project. */ /* required for s6_addr32 */ @@ -224,3 +225,66 @@ } return NULL; } + +/** + * calculate difference between two timevalues + * + * @param t1 timevalue 1 + * @param t2 timevalue 2 + * @param result where the result is stored + * + * ** CHECK comments ** + * result = t1 - t2 + * + * Code taken from http://www.gnu.org/manual/glibc-2.2.5/html_node/Elapsed-Time.html + * + * @return 1 if t1 is equal or later than t2, else 0. + */ +int hip_timeval_diff(const struct timeval *t1, + const struct timeval *t2, + struct timeval *result) +{ + struct timeval _t1, _t2; + _t1 = *t1; + _t2 = *t2; + + if (_t1.tv_usec < _t2.tv_usec) { + int nsec = (_t2.tv_usec - _t1.tv_usec) / 1000000 + 1; + _t2.tv_usec -= 1000000 * nsec; + _t2.tv_sec += nsec; + } + if (_t1.tv_usec - _t2.tv_usec > 1000000) { + int nsec = (_t1.tv_usec - _t2.tv_usec) / 1000000; + _t2.tv_usec += 1000000 * nsec; + _t2.tv_sec -= nsec; + } + + result->tv_sec = _t2.tv_sec - _t1.tv_sec; + result->tv_usec = _t2.tv_usec - _t1.tv_usec; + + return _t1.tv_sec >= _t2.tv_sec; +} + +/** + * find the maximum value from a variable list of integers + * + * @param num_args number of list items + * @param ... the integers from which to find maximum + * @return the integer with the largest value from the + * list provided + */ +int maxof(int num_args, ...) +{ + int max, i, a; + va_list ap; + + va_start(ap, num_args); + max = va_arg(ap, int); + for (i = 2; i <= num_args; i++) { + if ((a = va_arg(ap, int)) > max) { + max = a; + } + } + va_end(ap); + return max; +} === modified file 'lib/tool/lutil.h' --- lib/tool/lutil.h 2010-03-03 16:51:18 +0000 +++ lib/tool/lutil.h 2010-03-19 09:53:35 +0000 @@ -7,10 +7,6 @@ #ifndef HIP_LIB_TOOL_LUTIL_H #define HIP_LIB_TOOL_LUTIL_H -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - #include <dirent.h> #include <sys/stat.h> #include <unistd.h> @@ -20,6 +16,7 @@ #include <stdlib.h> #include <malloc.h> +#include "config.h" #include "lib/core/builder.h" #include "lib/core/debug.h" @@ -54,6 +51,8 @@ void insert(List *, char *data); void destroy(List *); int length(List *); +int hip_timeval_diff(const struct timeval *t1, const struct timeval *t2, + struct timeval *result); /** * Gets an item from a linked list. Gets <code>n</code>th item from a linked @@ -78,4 +77,6 @@ */ void extractsubstrings(char *string, List *list); +int maxof(int num_args, ...); + #endif /* HIP_LIB_TOOL_LUTIL_H */ === modified file 'lib/tool/nlink.c' --- lib/tool/nlink.c 2010-03-19 09:24:10 +0000 +++ lib/tool/nlink.c 2010-03-19 09:53:35 +0000 @@ -30,10 +30,11 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include <net/if.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include "config.h" +#include "lib/core/hip_udp.h" #include "nlink.h" /* New one to prevent netlink overrun */ @@ -1362,7 +1363,7 @@ int fd; int err; - strncpy(ifr.ifr_name, dev, IFNAMSIZ); + strncpy(ifr.ifr_name, dev, IF_NAMESIZE); fd = get_ctl_fd(); if (fd < 0) { return -1; === modified file 'lib/tool/nlink.h' --- lib/tool/nlink.h 2010-03-19 09:24:10 +0000 +++ lib/tool/nlink.h 2010-03-19 09:53:35 +0000 @@ -18,6 +18,9 @@ #include "lib/core/builder.h" #include "lib/core/debug.h" +#define HIP_OPTION_KIND 30 +#define HIP_NETLINK_TALK_ACK 0 /* see netlink_talk */ + struct pseudo_hdr { uint32_t s_addr; @@ -35,8 +38,6 @@ uint16_t length; }; -#define HIP_OPTION_KIND 30 - struct netdev_address { //hip_list_t next; struct sockaddr_storage addr; === modified file 'lib/tool/pk.c' --- lib/tool/pk.c 2010-03-19 09:24:10 +0000 +++ lib/tool/pk.c 2010-03-19 09:53:35 +0000 @@ -13,10 +13,7 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "pk.h" #ifdef CONFIG_HIP_PERFORMANCE === modified file 'lib/tool/xfrmapi.c' --- lib/tool/xfrmapi.c 2010-03-19 09:24:10 +0000 +++ lib/tool/xfrmapi.c 2010-03-19 09:53:35 +0000 @@ -16,11 +16,10 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/tool/nlink.h" +#include "lib/core/hip_udp.h" +#include "lib/core/keylen.h" #include "xfrmapi.h" === modified file 'lib/tool/xfrmapi.h' --- lib/tool/xfrmapi.h 2010-03-19 09:24:10 +0000 +++ lib/tool/xfrmapi.h 2010-03-19 09:53:35 +0000 @@ -15,7 +15,7 @@ #include "lib/core/hashtable.h" #include "hipd/hadb.h" #include "hipd/user.h" -#include "lib/core/misc.h" + #include "lib/core/state.h" #include "nlink.h" === added directory 'patches/kernel/2.6.20' === added file 'patches/kernel/2.6.20/beet-2.6.20.21.patch' --- patches/kernel/2.6.20/beet-2.6.20.21.patch 1970-01-01 00:00:00 +0000 +++ patches/kernel/2.6.20/beet-2.6.20.21.patch 2010-03-19 09:53:35 +0000 @@ -0,0 +1,1555 @@ +diff -urN linux-2.6.20.21/include/net/route.h linux-2.6.20.21-hipl/include/net/route.h +--- linux-2.6.20.21/include/net/route.h 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/include/net/route.h 2010-03-12 17:41:05.000000000 +0200 +@@ -146,7 +146,8 @@ + + static inline int ip_route_connect(struct rtable **rp, __be32 dst, + __be32 src, u32 tos, int oif, u8 protocol, +- __be16 sport, __be16 dport, struct sock *sk) ++ __be16 sport, __be16 dport, struct sock *sk, ++ int flags) + { + struct flowi fl = { .oif = oif, + .nl_u = { .ip4_u = { .daddr = dst, +@@ -168,7 +169,7 @@ + *rp = NULL; + } + security_sk_classify_flow(sk, &fl); +- return ip_route_output_flow(rp, &fl, sk, 0); ++ return ip_route_output_flow(rp, &fl, sk, flags); + } + + static inline int ip_route_newports(struct rtable **rp, u8 protocol, +diff -urN linux-2.6.20.21/include/net/xfrm.h linux-2.6.20.21-hipl/include/net/xfrm.h +--- linux-2.6.20.21/include/net/xfrm.h 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/include/net/xfrm.h 2010-03-12 17:41:05.000000000 +0200 +@@ -237,7 +237,7 @@ + extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); + extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c); + extern void km_state_notify(struct xfrm_state *x, struct km_event *c); +-#define XFRM_ACQ_EXPIRES 30 ++#define XFRM_ACQ_EXPIRES 3 + + struct xfrm_tmpl; + extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +@@ -928,14 +928,14 @@ + extern int xfrm_init_state(struct xfrm_state *x); + extern int xfrm4_rcv(struct sk_buff *skb); + extern int xfrm4_output(struct sk_buff *skb); +-extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); +-extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); ++extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); ++extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); + extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi); + extern int xfrm6_rcv(struct sk_buff **pskb); + extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, + xfrm_address_t *saddr, u8 proto); +-extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); +-extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); ++extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); ++extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); + extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); + extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); + extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); +diff -urN linux-2.6.20.21/net/dccp/ipv4.c linux-2.6.20.21-hipl/net/dccp/ipv4.c +--- linux-2.6.20.21/net/dccp/ipv4.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/dccp/ipv4.c 2010-03-12 17:41:05.000000000 +0200 +@@ -72,7 +72,7 @@ + tmp = ip_route_connect(&rt, nexthop, inet->saddr, + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, + IPPROTO_DCCP, +- inet->sport, usin->sin_port, sk); ++ inet->sport, usin->sin_port, sk, 1); + if (tmp < 0) + return tmp; + +diff -urN linux-2.6.20.21/net/dccp/ipv6.c linux-2.6.20.21-hipl/net/dccp/ipv6.c +--- linux-2.6.20.21/net/dccp/ipv6.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/dccp/ipv6.c 2010-03-12 17:41:05.000000000 +0200 +@@ -1041,7 +1041,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- err = xfrm_lookup(&dst, &fl, sk, 0); ++ err = xfrm_lookup(&dst, &fl, sk, 1); + if (err < 0) + goto failure; + +diff -urN linux-2.6.20.21/net/ipv4/af_inet.c linux-2.6.20.21-hipl/net/ipv4/af_inet.c +--- linux-2.6.20.21/net/ipv4/af_inet.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/af_inet.c 2010-03-12 17:41:05.000000000 +0200 +@@ -1007,7 +1007,7 @@ + RT_CONN_FLAGS(sk), + sk->sk_bound_dev_if, + sk->sk_protocol, +- inet->sport, inet->dport, sk); ++ inet->sport, inet->dport, sk, 0); + if (err) + return err; + +diff -urN linux-2.6.20.21/net/ipv4/datagram.c linux-2.6.20.21-hipl/net/ipv4/datagram.c +--- linux-2.6.20.21/net/ipv4/datagram.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/datagram.c 2010-03-12 17:41:05.000000000 +0200 +@@ -49,7 +49,7 @@ + err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr, + RT_CONN_FLAGS(sk), oif, + sk->sk_protocol, +- inet->sport, usin->sin_port, sk); ++ inet->sport, usin->sin_port, sk, 1); + if (err) + return err; + if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { +diff -urN linux-2.6.20.21/net/ipv4/esp4.c linux-2.6.20.21-hipl/net/ipv4/esp4.c +--- linux-2.6.20.21/net/ipv4/esp4.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/esp4.c 2010-03-12 17:41:05.000000000 +0200 +@@ -402,6 +402,8 @@ + x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; + if (x->props.mode == XFRM_MODE_TUNNEL) + x->props.header_len += sizeof(struct iphdr); ++ else if (x->props.mode == XFRM_MODE_BEET) ++ x->props.header_len += IPV4_BEET_PHMAXLEN; + if (x->encap) { + struct xfrm_encap_tmpl *encap = x->encap; + +diff -urN linux-2.6.20.21/net/ipv4/ipip.c linux-2.6.20.21-hipl/net/ipv4/ipip.c +--- linux-2.6.20.21/net/ipv4/ipip.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/ipip.c 2010-03-12 17:41:05.000000000 +0200 +@@ -870,7 +870,7 @@ + + printk(banner); + +- if (xfrm4_tunnel_register(&ipip_handler)) { ++ if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { + printk(KERN_INFO "ipip init: can't register tunnel\n"); + return -EAGAIN; + } +@@ -892,7 +892,7 @@ + err2: + free_netdev(ipip_fb_tunnel_dev); + err1: +- xfrm4_tunnel_deregister(&ipip_handler); ++ xfrm4_tunnel_deregister(&ipip_handler, AF_INET); + goto out; + } + +@@ -912,7 +912,7 @@ + + static void __exit ipip_fini(void) + { +- if (xfrm4_tunnel_deregister(&ipip_handler)) ++ if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) + printk(KERN_INFO "ipip close: can't deregister tunnel\n"); + + rtnl_lock(); +diff -urN linux-2.6.20.21/net/ipv4/raw.c linux-2.6.20.21-hipl/net/ipv4/raw.c +--- linux-2.6.20.21/net/ipv4/raw.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/raw.c 2010-03-12 17:41:05.000000000 +0200 +@@ -489,7 +489,7 @@ + } + + security_sk_classify_flow(sk, &fl); +- err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); ++ err = ip_route_output_flow(&rt, &fl, sk, 1); + } + if (err) + goto done; +diff -urN linux-2.6.20.21/net/ipv4/route.c linux-2.6.20.21-hipl/net/ipv4/route.c +--- linux-2.6.20.21/net/ipv4/route.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/route.c 2010-03-12 17:41:05.000000000 +0200 +@@ -108,6 +108,7 @@ + #ifdef CONFIG_SYSCTL + #include <linux/sysctl.h> + #endif ++#include <linux/xfrm.h> + + #define RT_FL_TOS(oldflp) \ + ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) +diff -urN linux-2.6.20.21/net/ipv4/tcp_ipv4.c linux-2.6.20.21-hipl/net/ipv4/tcp_ipv4.c +--- linux-2.6.20.21/net/ipv4/tcp_ipv4.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/tcp_ipv4.c 2010-03-12 17:41:05.000000000 +0200 +@@ -191,7 +191,7 @@ + tmp = ip_route_connect(&rt, nexthop, inet->saddr, + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, + IPPROTO_TCP, +- inet->sport, usin->sin_port, sk); ++ inet->sport, usin->sin_port, sk, 1); + if (tmp < 0) + return tmp; + +diff -urN linux-2.6.20.21/net/ipv4/tunnel4.c linux-2.6.20.21-hipl/net/ipv4/tunnel4.c +--- linux-2.6.20.21/net/ipv4/tunnel4.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/tunnel4.c 2010-03-12 17:41:05.000000000 +0200 +@@ -14,9 +14,10 @@ + #include <net/xfrm.h> + + static struct xfrm_tunnel *tunnel4_handlers; ++static struct xfrm_tunnel *tunnel64_handlers; + static DEFINE_MUTEX(tunnel4_mutex); + +-int xfrm4_tunnel_register(struct xfrm_tunnel *handler) ++int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) + { + struct xfrm_tunnel **pprev; + int ret = -EEXIST; +@@ -24,7 +25,8 @@ + + mutex_lock(&tunnel4_mutex); + +- for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if ((*pprev)->priority > priority) + break; + if ((*pprev)->priority == priority) +@@ -44,14 +46,15 @@ + + EXPORT_SYMBOL(xfrm4_tunnel_register); + +-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) ++int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) + { + struct xfrm_tunnel **pprev; + int ret = -ENOENT; + + mutex_lock(&tunnel4_mutex); + +- for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if (*pprev == handler) { + *pprev = handler->next; + ret = 0; +@@ -86,6 +89,26 @@ + return 0; + } + ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++static int tunnel64_rcv(struct sk_buff *skb) ++{ ++ struct xfrm_tunnel *handler; ++ ++ if (!pskb_may_pull(skb, sizeof(struct iphdr))) ++ goto drop; ++ ++ for (handler = tunnel64_handlers; handler; handler = handler->next) ++ if (!handler->handler(skb)) ++ return 0; ++ ++ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); ++ ++drop: ++ kfree_skb(skb); ++ return 0; ++} ++#endif ++ + static void tunnel4_err(struct sk_buff *skb, u32 info) + { + struct xfrm_tunnel *handler; +@@ -101,17 +124,36 @@ + .no_policy = 1, + }; + ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++static struct net_protocol tunnel64_protocol = { ++ .handler = tunnel64_rcv, ++ .err_handler = tunnel4_err, ++ .no_policy = 1, ++}; ++#endif ++ + static int __init tunnel4_init(void) + { + if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { + printk(KERN_ERR "tunnel4 init: can't add protocol\n"); + return -EAGAIN; + } ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { ++ printk(KERN_ERR "tunnel64 init: can't add protocol\n"); ++ inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); ++ return -EAGAIN; ++ } ++#endif + return 0; + } + + static void __exit tunnel4_fini(void) + { ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) ++ printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); ++#endif + if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) + printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); + } +diff -urN linux-2.6.20.21/net/ipv4/udp.c linux-2.6.20.21-hipl/net/ipv4/udp.c +--- linux-2.6.20.21/net/ipv4/udp.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/udp.c 2010-03-12 17:41:05.000000000 +0200 +@@ -629,7 +629,7 @@ + { .sport = inet->sport, + .dport = dport } } }; + security_sk_classify_flow(sk, &fl); +- err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); ++ err = ip_route_output_flow(&rt, &fl, sk, 1); + if (err) + goto out; + +diff -urN linux-2.6.20.21/net/ipv4/xfrm4_input.c linux-2.6.20.21-hipl/net/ipv4/xfrm4_input.c +--- linux-2.6.20.21/net/ipv4/xfrm4_input.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_input.c 2010-03-12 17:41:05.000000000 +0200 +@@ -106,7 +106,7 @@ + if (x->mode->input(x, skb)) + goto drop; + +- if (x->props.mode == XFRM_MODE_TUNNEL) { ++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { + decaps = 1; + break; + } +diff -urN linux-2.6.20.21/net/ipv4/xfrm4_mode_beet.c linux-2.6.20.21-hipl/net/ipv4/xfrm4_mode_beet.c +--- linux-2.6.20.21/net/ipv4/xfrm4_mode_beet.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_mode_beet.c 2010-03-12 17:41:05.000000000 +0200 +@@ -6,6 +6,7 @@ + * Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> + * Abhinav Pathak <abhinav.pathak@xxxxxxx> + * Jeff Ahrenholz <ahrenholz@xxxxxxxxx> ++ * Joakim Koskela <jookos@xxxxxxxxx> + */ + + #include <linux/init.h> +@@ -14,54 +15,97 @@ + #include <linux/skbuff.h> + #include <linux/stringify.h> + #include <net/dst.h> ++#include <net/dsfield.h> + #include <net/ip.h> ++#include <net/inet_ecn.h> + #include <net/xfrm.h> + +-/* Add encapsulation header. +- * +- * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. +- * The following fields in it shall be filled in by x->type->output: +- * tot_len +- * check +- * +- * On exit, skb->h will be set to the start of the payload to be processed +- * by x->type->output and skb->nh will be set to the top IP header. +- */ + static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) + { +- struct iphdr *iph, *top_iph = NULL; +- int hdrlen, optlen; ++ struct dst_entry *dst = skb->dst; ++ int hdrlen; ++ struct iphdr *iphv4, *top_iphv4; ++ struct ipv6hdr *iphv6, *top_iphv6; + +- iph = skb->nh.iph; +- skb->h.ipiph = iph; ++ if (skb->nh.iph->version == 4) { + +- hdrlen = 0; +- optlen = iph->ihl * 4 - sizeof(*iph); +- if (unlikely(optlen)) +- hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); +- +- skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); +- top_iph = skb->nh.iph; +- hdrlen = iph->ihl * 4 - optlen; +- skb->h.raw += hdrlen; +- +- memmove(top_iph, iph, hdrlen); +- if (unlikely(optlen)) { +- struct ip_beet_phdr *ph; +- +- BUG_ON(optlen < 0); +- +- ph = (struct ip_beet_phdr *)skb->h.raw; +- ph->padlen = 4 - (optlen & 4); +- ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; +- ph->nexthdr = top_iph->protocol; ++ int optlen; + +- top_iph->protocol = IPPROTO_BEETPH; +- top_iph->ihl = sizeof(struct iphdr) / 4; +- } ++ /* 4-4 */ ++ ++ iphv4 = skb->nh.iph; ++ skb->h.ipiph = iphv4; ++ ++ hdrlen = x->props.header_len; ++ ++ optlen = iphv4->ihl * 4 - sizeof(*iphv4); ++ ++ if (!optlen) { ++ hdrlen -= IPV4_BEET_PHMAXLEN; ++ } else { ++ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4)); ++ hdrlen -= optlen & 4; ++ } ++ ++ skb->nh.raw = skb_push(skb, hdrlen); ++ ++ top_iphv4 = skb->nh.iph; ++ hdrlen = iphv4->ihl * 4 - optlen; ++ skb->h.raw += hdrlen; ++ memmove(top_iphv4, iphv4, hdrlen); ++ ++ if (unlikely(optlen)) { ++ struct ip_beet_phdr *ph; ++ ++ BUG_ON(optlen < 0); ++ ++ ph = (struct ip_beet_phdr *)skb->h.raw; ++ ph->padlen = 4 - (optlen & 4); ++ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; ++ ph->nexthdr = iphv4->protocol; ++ top_iphv4->protocol = IPPROTO_BEETPH; ++ top_iphv4->ihl = sizeof(struct iphdr) / 4; ++ } ++ ++ top_iphv4->saddr = x->props.saddr.a4; ++ top_iphv4->daddr = x->id.daddr.a4; ++ ++ skb->protocol = htons(ETH_P_IP); ++ ++ } else if (skb->nh.iph->version == 6) { ++ ++ u8 protocol; ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ ++ /* Inner = 6, Outer = 4 : changing the external IP hdr ++ * to the outer addresses ++ */ ++ ++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN; ++ skb_push(skb, hdrlen); ++ iphv6 = skb->nh.ipv6h; ++ ++ skb->nh.raw = skb->data; ++ top_iphv6 = skb->nh.ipv6h; ++ ++ protocol = iphv6->nexthdr; ++ skb->nh.raw = skb_pull(skb, delta); ++ top_iphv4 = skb->nh.iph; ++ skb->h.raw = skb->data + hdrlen; ++ top_iphv4->ihl = (sizeof(struct iphdr) >> 2); ++ top_iphv4->version = 4; ++ top_iphv4->id = 0; ++ top_iphv4->frag_off = htons(IP_DF); ++ top_iphv4->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); ++ top_iphv4->saddr = x->props.saddr.a4; ++ top_iphv4->daddr = x->id.daddr.a4; ++ skb->h.raw += top_iphv4->ihl*4; ++ top_iphv4->protocol = protocol; ++ ++ skb->protocol = htons(ETH_P_IP); ++ } else ++ BUG_ON(1); + +- top_iph->saddr = x->props.saddr.a4; +- top_iph->daddr = x->id.daddr.a4; + + return 0; + } +@@ -69,45 +113,73 @@ + static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) + { + struct iphdr *iph = skb->nh.iph; ++ int hops = skb->nh.iph->ttl; + int phlen = 0; + int optlen = 0; ++ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr); ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); + __u8 ph_nexthdr = 0, protocol = 0; + int err = -EINVAL; + + protocol = iph->protocol; + +- if (unlikely(iph->protocol == IPPROTO_BEETPH)) { +- struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); ++ if (x->sel.family == AF_INET6) { ++ /* Here, the inner family is 6, therefore I have to ++ * substitute the IPhdr by enlarging it */ ++ if (skb_tailroom(skb) < delta){ ++ if (pskb_expand_head(skb, 0, delta, GFP_ATOMIC)) ++ goto out; ++ } ++ skb->nh.raw -= delta; ++ } else if (x->sel.family == AF_INET) { ++ if (unlikely(iph->protocol == IPPROTO_BEETPH)) { ++ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); ++ ++ if (!pskb_may_pull(skb, sizeof(*ph))) ++ goto out; ++ ++ phlen = ph->hdrlen * 8; ++ optlen = phlen - ph->padlen - sizeof(*ph); ++ if (optlen < 0 || optlen & 3 || optlen > 250) ++ goto out; ++ ++ if (!pskb_may_pull(skb, phlen)) ++ goto out; ++ ++ ph_nexthdr = ph->nexthdr; ++ } ++ } else ++ BUG_ON(1); + +- if (!pskb_may_pull(skb, sizeof(*ph))) +- goto out; +- +- phlen = ph->hdrlen * 8; +- optlen = phlen - ph->padlen - sizeof(*ph); +- if (optlen < 0 || optlen & 3 || optlen > 250) +- goto out; +- +- if (!pskb_may_pull(skb, phlen)) +- goto out; +- +- ph_nexthdr = ph->nexthdr; +- } +- +- skb_push(skb, sizeof(*iph) - phlen + optlen); ++ size += (optlen - phlen); ++ skb_push(skb, size); + memmove(skb->data, skb->nh.raw, sizeof(*iph)); + skb->nh.raw = skb->data; + +- iph = skb->nh.iph; +- iph->ihl = (sizeof(*iph) + optlen) / 4; +- iph->tot_len = htons(skb->len); +- iph->daddr = x->sel.daddr.a4; +- iph->saddr = x->sel.saddr.a4; +- if (ph_nexthdr) +- iph->protocol = ph_nexthdr; +- else +- iph->protocol = protocol; +- iph->check = 0; +- iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); ++ if (x->sel.family == AF_INET) { ++ iph = skb->nh.iph; ++ iph->ihl = (sizeof(*iph) + optlen) / 4; ++ iph->tot_len = htons(skb->len); ++ iph->daddr = x->sel.daddr.a4; ++ iph->saddr = x->sel.saddr.a4; ++ if (ph_nexthdr) ++ iph->protocol = ph_nexthdr; ++ else ++ iph->protocol = protocol; ++ iph->check = 0; ++ iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); ++ } else if (x->sel.family == AF_INET6) { ++ struct ipv6hdr *ip6h = skb->nh.ipv6h; ++ memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl)); ++ ip6h->version = 6; ++ ip6h->priority = 0; ++ ip6h->nexthdr = protocol; ++ ip6h->hop_limit = hops; ++ ip6h->payload_len = htons(skb->len - size); ++ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *)&x->sel.daddr.a6); ++ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *)&x->sel.saddr.a6); ++ skb->protocol = htons(ETH_P_IPV6); ++ } + err = 0; + out: + return err; +diff -urN linux-2.6.20.21/net/ipv4/xfrm4_policy.c linux-2.6.20.21-hipl/net/ipv4/xfrm4_policy.c +--- linux-2.6.20.21/net/ipv4/xfrm4_policy.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_policy.c 2010-03-12 17:42:24.000000000 +0200 +@@ -15,6 +15,7 @@ + + static struct dst_ops xfrm4_dst_ops; + static struct xfrm_policy_afinfo xfrm4_policy_afinfo; ++static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu); + + static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) + { +@@ -72,17 +73,20 @@ + struct dst_entry *dst, *dst_prev; + struct rtable *rt0 = (struct rtable*)(*dst_p); + struct rtable *rt = rt0; +- __be32 remote = fl->fl4_dst; +- __be32 local = fl->fl4_src; + struct flowi fl_tunnel = { + .nl_u = { + .ip4_u = { +- .saddr = local, +- .daddr = remote, ++ .saddr = fl->fl4_src, ++ .daddr = fl->fl4_dst, + .tos = fl->fl4_tos + } + } + }; ++ union { ++ struct in6_addr *in6; ++ struct in_addr *in; ++ } remote, local; ++ unsigned short outer_family6 = 0; + int i; + int err; + int header_len = 0; +@@ -94,7 +98,7 @@ + for (i = 0; i < nx; i++) { + struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops); + struct xfrm_dst *xdst; +- int tunnel = 0; ++ unsigned short outer_family = 0; + + if (unlikely(dst1 == NULL)) { + err = -ENOBUFS; +@@ -117,20 +121,41 @@ + dst1->next = dst_prev; + dst_prev = dst1; + if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { +- remote = xfrm[i]->id.daddr.a4; +- local = xfrm[i]->props.saddr.a4; +- tunnel = 1; ++ outer_family = xfrm[i]->props.family; ++ if(outer_family == AF_INET){ ++ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4; ++ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4; ++ } else if (outer_family == AF_INET6){ ++ outer_family6 = 1; ++ remote.in6 = (struct in6_addr*)xfrm[i]->id.daddr.a6; ++ local.in6 = (struct in6_addr*)xfrm[i]->props.saddr.a6; ++ } else ++ BUG_ON(1); + } + header_len += xfrm[i]->props.header_len; + trailer_len += xfrm[i]->props.trailer_len; + +- if (tunnel) { +- fl_tunnel.fl4_src = local; +- fl_tunnel.fl4_dst = remote; ++ if (outer_family) { ++ switch (outer_family) { ++ default: ++ case AF_INET: ++ fl_tunnel.fl4_src = local.in->s_addr; ++ fl_tunnel.fl4_dst = remote.in->s_addr; ++ break; ++ case AF_INET6: ++ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6); ++ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6); ++ break; ++ } + err = xfrm_dst_lookup((struct xfrm_dst **)&rt, +- &fl_tunnel, AF_INET); ++ &fl_tunnel, outer_family); + if (err) + goto error; ++ /* Without this, the atomic inc below segfaults */ ++ if (outer_family == AF_INET6) { ++ rt->peer = NULL; ++ rt_bind_peer(rt,1); ++ } + } else + dst_hold(&rt->u.dst); + } +@@ -181,6 +206,12 @@ + } + + xfrm_init_pmtu(dst); ++ if (outer_family6) { ++ /* The worst case */ ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ u32 mtu = dst_mtu(dst); ++ xfrm4_update_pmtu(dst, mtu - delta); ++ } + return 0; + + error: +diff -urN linux-2.6.20.21/net/ipv4/xfrm4_tunnel.c linux-2.6.20.21-hipl/net/ipv4/xfrm4_tunnel.c +--- linux-2.6.20.21/net/ipv4/xfrm4_tunnel.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv4/xfrm4_tunnel.c 2010-03-12 17:42:24.000000000 +0200 +@@ -13,7 +13,7 @@ + static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) + { + struct iphdr *iph; +- ++ + iph = skb->nh.iph; + iph->tot_len = htons(skb->len); + ip_send_check(iph); +@@ -28,7 +28,7 @@ + + static int ipip_init_state(struct xfrm_state *x) + { +- if (x->props.mode != XFRM_MODE_TUNNEL) ++ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET) + return -EINVAL; + + if (x->encap) +@@ -64,24 +64,45 @@ + .priority = 2, + }; + ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++static struct xfrm_tunnel xfrm64_tunnel_handler = { ++ .handler = xfrm4_rcv, ++ .err_handler = xfrm_tunnel_err, ++ .priority = 2, ++}; ++#endif ++ + static int __init ipip_init(void) + { + if (xfrm_register_type(&ipip_type, AF_INET) < 0) { + printk(KERN_INFO "ipip init: can't add xfrm type\n"); + return -EAGAIN; + } +- if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) { +- printk(KERN_INFO "ipip init: can't add xfrm handler\n"); ++ ++ if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) { ++ printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n"); ++ xfrm_unregister_type(&ipip_type, AF_INET); ++ return -EAGAIN; ++ } ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) { ++ printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n"); ++ xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET); + xfrm_unregister_type(&ipip_type, AF_INET); + return -EAGAIN; + } ++#endif + return 0; + } + + static void __exit ipip_fini(void) + { +- if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler)) +- printk(KERN_INFO "ipip close: can't remove xfrm handler\n"); ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6)) ++ printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n"); ++#endif ++ if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET)) ++ printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n"); + if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) + printk(KERN_INFO "ipip close: can't remove xfrm type\n"); + } +diff -urN linux-2.6.20.21/net/ipv6/datagram.c linux-2.6.20.21-hipl/net/ipv6/datagram.c +--- linux-2.6.20.21/net/ipv6/datagram.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/datagram.c 2010-03-12 17:42:24.000000000 +0200 +@@ -178,7 +178,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto out; + + /* source address lookup done in ip6_dst_lookup */ +diff -urN linux-2.6.20.21/net/ipv6/esp6.c linux-2.6.20.21-hipl/net/ipv6/esp6.c +--- linux-2.6.20.21/net/ipv6/esp6.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/esp6.c 2010-03-12 17:42:24.000000000 +0200 +@@ -240,9 +240,9 @@ + static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) + { + struct esp_data *esp = x->data; +- u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); ++ u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); + +- if (x->props.mode == XFRM_MODE_TUNNEL) { ++ if (x->props.mode) { + mtu = ALIGN(mtu + 2, blksize); + } else { + /* The worst case. */ +@@ -365,6 +365,8 @@ + x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; + if (x->props.mode == XFRM_MODE_TUNNEL) + x->props.header_len += sizeof(struct ipv6hdr); ++ else if (x->props.mode == XFRM_MODE_BEET) ++ x->props.header_len += IPV4_BEET_PHMAXLEN; + x->data = esp; + return 0; + +diff -urN linux-2.6.20.21/net/ipv6/icmp.c linux-2.6.20.21-hipl/net/ipv6/icmp.c +--- linux-2.6.20.21/net/ipv6/icmp.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/icmp.c 2010-03-12 17:42:24.000000000 +0200 +@@ -64,6 +64,7 @@ + #include <net/ip6_route.h> + #include <net/addrconf.h> + #include <net/icmp.h> ++#include <linux/xfrm.h> + + #include <asm/uaccess.h> + #include <asm/system.h> +diff -urN linux-2.6.20.21/net/ipv6/ip6_tunnel.c linux-2.6.20.21-hipl/net/ipv6/ip6_tunnel.c +--- linux-2.6.20.21/net/ipv6/ip6_tunnel.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/ip6_tunnel.c 2010-03-12 17:42:24.000000000 +0200 +@@ -1127,7 +1127,7 @@ + { + int err; + +- if (xfrm6_tunnel_register(&ip6ip6_handler)) { ++ if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { + printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); + return -EAGAIN; + } +@@ -1146,7 +1146,7 @@ + } + return 0; + fail: +- xfrm6_tunnel_deregister(&ip6ip6_handler); ++ xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); + return err; + } + +@@ -1170,7 +1170,7 @@ + + static void __exit ip6_tunnel_cleanup(void) + { +- if (xfrm6_tunnel_deregister(&ip6ip6_handler)) ++ if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) + printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); + + rtnl_lock(); +diff -urN linux-2.6.20.21/net/ipv6/raw.c linux-2.6.20.21-hipl/net/ipv6/raw.c +--- linux-2.6.20.21/net/ipv6/raw.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/raw.c 2010-03-12 17:42:24.000000000 +0200 +@@ -815,7 +815,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto out; + + if (hlimit < 0) { +diff -urN linux-2.6.20.21/net/ipv6/tcp_ipv6.c linux-2.6.20.21-hipl/net/ipv6/tcp_ipv6.c +--- linux-2.6.20.21/net/ipv6/tcp_ipv6.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/tcp_ipv6.c 2010-03-12 17:42:24.000000000 +0200 +@@ -265,7 +265,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto failure; + + if (saddr == NULL) { +diff -urN linux-2.6.20.21/net/ipv6/tunnel6.c linux-2.6.20.21-hipl/net/ipv6/tunnel6.c +--- linux-2.6.20.21/net/ipv6/tunnel6.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/tunnel6.c 2010-03-12 17:42:24.000000000 +0200 +@@ -30,9 +30,10 @@ + #include <net/xfrm.h> + + static struct xfrm6_tunnel *tunnel6_handlers; ++static struct xfrm6_tunnel *tunnel46_handlers; + static DEFINE_MUTEX(tunnel6_mutex); + +-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) ++int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) + { + struct xfrm6_tunnel **pprev; + int ret = -EEXIST; +@@ -40,7 +41,8 @@ + + mutex_lock(&tunnel6_mutex); + +- for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if ((*pprev)->priority > priority) + break; + if ((*pprev)->priority == priority) +@@ -60,14 +62,15 @@ + + EXPORT_SYMBOL(xfrm6_tunnel_register); + +-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) ++int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) + { + struct xfrm6_tunnel **pprev; + int ret = -ENOENT; + + mutex_lock(&tunnel6_mutex); + +- for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if (*pprev == handler) { + *pprev = handler->next; + ret = 0; +@@ -103,6 +106,25 @@ + return 0; + } + ++static int tunnel46_rcv(struct sk_buff **pskb) ++{ ++ struct sk_buff *skb = *pskb; ++ struct xfrm6_tunnel *handler; ++ ++ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ goto drop; ++ ++ for (handler = tunnel46_handlers; handler; handler = handler->next) ++ if (!handler->handler(skb)) ++ return 0; ++ ++ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev); ++ ++drop: ++ kfree_skb(skb); ++ return 0; ++} ++ + static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __be32 info) + { +@@ -119,17 +141,30 @@ + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, + }; + ++static struct inet6_protocol tunnel46_protocol = { ++ .handler = tunnel46_rcv, ++ .err_handler = tunnel6_err, ++ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, ++}; ++ + static int __init tunnel6_init(void) + { + if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { + printk(KERN_ERR "tunnel6 init(): can't add protocol\n"); + return -EAGAIN; + } ++ if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) { ++ printk(KERN_ERR "tunnel6 init(): can't add protocol\n"); ++ inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); ++ return -EAGAIN; ++ } + return 0; + } + + static void __exit tunnel6_fini(void) + { ++ if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP)) ++ printk(KERN_ERR "tunnel6 close: can't remove protocol\n"); + if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) + printk(KERN_ERR "tunnel6 close: can't remove protocol\n"); + } +diff -urN linux-2.6.20.21/net/ipv6/udp.c linux-2.6.20.21-hipl/net/ipv6/udp.c +--- linux-2.6.20.21/net/ipv6/udp.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/udp.c 2010-03-12 17:42:24.000000000 +0200 +@@ -736,7 +736,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto out; + + if (hlimit < 0) { +diff -urN linux-2.6.20.21/net/ipv6/xfrm6_input.c linux-2.6.20.21-hipl/net/ipv6/xfrm6_input.c +--- linux-2.6.20.21/net/ipv6/xfrm6_input.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_input.c 2010-03-12 17:42:24.000000000 +0200 +@@ -72,7 +72,7 @@ + if (x->mode->input(x, skb)) + goto drop; + +- if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ ++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { /* XXX */ + decaps = 1; + break; + } +diff -urN linux-2.6.20.21/net/ipv6/xfrm6_mode_beet.c linux-2.6.20.21-hipl/net/ipv6/xfrm6_mode_beet.c +--- linux-2.6.20.21/net/ipv6/xfrm6_mode_beet.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_mode_beet.c 2010-03-12 17:42:24.000000000 +0200 +@@ -6,6 +6,7 @@ + * Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> + * Abhinav Pathak <abhinav.pathak@xxxxxxx> + * Jeff Ahrenholz <ahrenholz@xxxxxxxxx> ++ * Joakim Koskela <jookos@xxxxxxxxx> + */ + + #include <linux/init.h> +@@ -16,6 +17,7 @@ + #include <net/dsfield.h> + #include <net/dst.h> + #include <net/inet_ecn.h> ++#include <net/ip.h> + #include <net/ipv6.h> + #include <net/xfrm.h> + +@@ -31,38 +33,165 @@ + * its absence, that of the top IP header. The value of skb->data will always + * point to the top IP header. + */ ++/* Add encapsulation header. ++ * ++ * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. ++ * The following fields in it shall be filled in by x->type->output: ++ * tot_len ++ * check ++ * ++ * On exit, skb->h will be set to the start of the payload to be processed ++ * by x->type->output and skb->nh will be set to the top IP header. ++ */ + static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) + { +- struct ipv6hdr *iph, *top_iph; +- u8 *prevhdr; +- int hdr_len; +- +- skb_push(skb, x->props.header_len); +- iph = skb->nh.ipv6h; +- +- hdr_len = ip6_find_1stfragopt(skb, &prevhdr); +- skb->nh.raw = prevhdr - x->props.header_len; +- skb->h.raw = skb->data + hdr_len; +- memmove(skb->data, iph, hdr_len); + +- skb->nh.raw = skb->data; +- top_iph = skb->nh.ipv6h; +- skb->nh.raw = &top_iph->nexthdr; +- skb->h.ipv6h = top_iph + 1; +- +- ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); +- ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); ++ struct dst_entry *dst = skb->dst; ++ int hdrlen; ++ struct iphdr *iphv4, *top_iphv4; ++ struct ipv6hdr *iphv6, *top_iphv6; ++ ++ if (skb->nh.iph->version == 6) { ++ ++ u8 *prevhdr; ++ int hdr_len; ++ ++/* 6-6 */ ++ ++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN; ++ skb_push(skb, hdrlen); ++ iphv6 = skb->nh.ipv6h; ++ ++ hdr_len = ip6_find_1stfragopt(skb, &prevhdr); ++ skb->nh.raw = prevhdr - hdrlen; ++ skb->h.raw = skb->data + hdr_len; ++ memmove(skb->data, iphv6, hdr_len); ++ ++ skb->nh.raw = skb->data; ++ top_iphv6 = skb->nh.ipv6h; ++ skb->nh.raw = &top_iphv6->nexthdr; ++ skb->h.ipv6h = top_iphv6 + 1; ++ ipv6_addr_copy(&top_iphv6->saddr, (struct in6_addr *)&x->props.saddr); ++ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr); ++ ++ skb->protocol = htons(ETH_P_IPV6); ++ ++ } else if (skb->nh.iph->version == 4) { ++ ++ int flags; ++ int optlen; ++ int dsfield; ++ u8 protocol; ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ ++ /* Inner = 4, Outer = 6*/ ++ ++ iphv4 = skb->nh.iph; ++ skb->h.ipiph = iphv4; ++ ++ hdrlen = x->props.header_len; ++ ++ optlen = iphv4->ihl * 4 - sizeof(*iphv4); ++ ++ if (!optlen) { ++ hdrlen -= IPV4_BEET_PHMAXLEN; ++ } else { ++ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4)); ++ hdrlen -= optlen & 4; ++ } ++ ++ skb->nh.raw = skb_push(skb, hdrlen); ++ ++ top_iphv4 = skb->nh.iph; ++ hdrlen = iphv4->ihl * 4 - optlen; ++ skb->h.raw += hdrlen; ++ if (unlikely(optlen)) { ++ struct ip_beet_phdr *ph; ++ ++ BUG_ON(optlen < 0); ++ ++ ph = (struct ip_beet_phdr *)skb->h.raw; ++ ph->padlen = 4 - (optlen & 4); ++ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; ++ ph->nexthdr = iphv4->protocol; ++ top_iphv4->protocol = IPPROTO_BEETPH; ++ top_iphv4->ihl = sizeof(struct iphdr) / 4; ++ } ++ ++ if (unlikely(optlen)) ++ protocol = top_iphv4->protocol; ++ else ++ protocol = iphv4->protocol; ++ ++ if (skb_headroom(skb) <= 2*delta){ ++ if (pskb_expand_head(skb, delta,0, GFP_ATOMIC)) ++ return -ENOMEM; ++ } ++ ++ skb->nh.raw = skb_push(skb, delta); ++ ++ top_iphv6 = skb->nh.ipv6h; ++ skb->h.ipv6h = top_iphv6 + 1; ++ /* DS disclosed */ ++ top_iphv6->version = 6; ++ top_iphv6->priority = 0; ++ top_iphv6->flow_lbl[0] = 0; ++ top_iphv6->flow_lbl[1] = 0; ++ top_iphv6->flow_lbl[2] = 0; ++ dsfield = ipv6_get_dsfield(top_iphv6); ++ dsfield = INET_ECN_encapsulate(dsfield, dsfield); ++ flags = x->props.flags; ++ if (flags & XFRM_STATE_NOECN) ++ dsfield &= ~INET_ECN_MASK; ++ ipv6_change_dsfield(top_iphv6, 0, dsfield); ++ ++ top_iphv6->nexthdr = protocol; ++ top_iphv6->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); ++ top_iphv6->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); ++ ipv6_addr_copy(&top_iphv6->saddr,(struct in6_addr *)&x->props.saddr); ++ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr); ++ skb->nh.raw = &top_iphv6->nexthdr; ++ ++ skb->protocol = htons(ETH_P_IPV6); ++ } else ++ BUG_ON(1); + + return 0; + } + + static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) + { +- struct ipv6hdr *ip6h; +- int size = sizeof(struct ipv6hdr); ++ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->h.raw); ++ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr); ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ __u8 proto = skb->nh.ipv6h->nexthdr, hops = skb->nh.ipv6h->hop_limit; ++ __u8 ph_nexthdr = 0; ++ int phlen = 0; ++ int optlen = 0; ++ + int err = -EINVAL; + +- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ if (x->sel.family == AF_INET) { ++ /* Inner = IPv4, therefore the IPhdr must be shrunk */ ++ /* Inner = 4, Outer = 6 */ ++ if (unlikely(proto == IPPROTO_BEETPH)) { ++ if (!pskb_may_pull(skb, sizeof(*ph))) ++ goto out; ++ phlen = ph->hdrlen * 8; ++ optlen = phlen - ph->padlen - sizeof(*ph); ++ ++ if (optlen < 0 || optlen & 3 || optlen > 250) ++ goto out; ++ if (!pskb_may_pull(skb, phlen)) ++ goto out; ++ ++ proto = ph_nexthdr = ph->nexthdr; ++ } ++ skb->nh.raw += delta; ++ } ++ ++ if (skb_cloned(skb) && ++ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto out; + + skb_push(skb, size); +@@ -71,11 +200,36 @@ + + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); +- +- ip6h = skb->nh.ipv6h; +- ip6h->payload_len = htons(skb->len - size); +- ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); +- ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); ++ if (unlikely(phlen)) { ++ skb_pull(skb, phlen - optlen); ++ skb->nh.raw = skb->data; ++ } ++ if (x->sel.family == AF_INET6) { ++ struct ipv6hdr *ip6h = skb->nh.ipv6h; ++ ip6h->payload_len = htons(skb->len - size); ++ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); ++ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); ++ } else if (x->sel.family == AF_INET) { ++ struct iphdr *iph = skb->nh.iph; ++ iph->ihl = (sizeof(*iph) + optlen) / 4; ++ iph->version = 4; ++ iph->tos = 0; ++ iph->id = 0; ++ iph->frag_off = 0; ++ iph->ttl = hops; ++ iph->protocol = proto; ++ iph->daddr = x->sel.daddr.a4; ++ iph->saddr = x->sel.saddr.a4; ++ iph->tot_len = htons(skb->len); ++ ip_send_check(iph); ++ skb->protocol = htons(ETH_P_IP); ++ if (unlikely(!optlen)) { ++ skb->h.raw = skb->nh.raw; ++ } ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ } else ++ BUG_ON(1); + err = 0; + out: + return err; +diff -urN linux-2.6.20.21/net/ipv6/xfrm6_policy.c linux-2.6.20.21-hipl/net/ipv6/xfrm6_policy.c +--- linux-2.6.20.21/net/ipv6/xfrm6_policy.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_policy.c 2010-03-12 17:42:24.000000000 +0200 +@@ -24,6 +24,7 @@ + + static struct dst_ops xfrm6_dst_ops; + static struct xfrm_policy_afinfo xfrm6_policy_afinfo; ++static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu); + + static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl) + { +@@ -89,7 +90,7 @@ + static inline struct in6_addr* + __xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr) + { +- return (x->type->remote_addr) ? ++ return (x->type && x->type->remote_addr) ? + (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) : + (struct in6_addr*)&x->id.daddr; + } +@@ -97,7 +98,7 @@ + static inline struct in6_addr* + __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr) + { +- return (x->type->local_addr) ? ++ return (x->type && x->type->local_addr) ? + (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) : + (struct in6_addr*)&x->props.saddr; + } +@@ -105,7 +106,7 @@ + static inline void + __xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x) + { +- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT) ++ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT) + *nflen += x->props.header_len; + else + *len += x->props.header_len; +@@ -114,7 +115,7 @@ + static inline void + __xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x) + { +- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT) ++ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT) + *nflen -= x->props.header_len; + else + *len -= x->props.header_len; +@@ -131,16 +132,19 @@ + struct dst_entry *dst, *dst_prev; + struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); + struct rt6_info *rt = rt0; +- struct in6_addr *remote = &fl->fl6_dst; +- struct in6_addr *local = &fl->fl6_src; ++ unsigned short outer_family = 0, beet = 0; + struct flowi fl_tunnel = { + .nl_u = { + .ip6_u = { +- .saddr = *local, +- .daddr = *remote ++ .saddr = fl->fl6_src, ++ .daddr = fl->fl6_dst + } + } + }; ++ union { ++ struct in6_addr *in6; ++ struct in_addr *in; ++ } remote, local; + int i; + int err = 0; + int header_len = 0; +@@ -153,7 +157,6 @@ + for (i = 0; i < nx; i++) { + struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops); + struct xfrm_dst *xdst; +- int tunnel = 0; + + if (unlikely(dst1 == NULL)) { + err = -ENOBUFS; +@@ -178,18 +181,38 @@ + dst1->next = dst_prev; + dst_prev = dst1; + if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { +- remote = __xfrm6_bundle_addr_remote(xfrm[i], remote); +- local = __xfrm6_bundle_addr_local(xfrm[i], local); +- tunnel = 1; ++ outer_family = xfrm[i]->props.family; ++ beet = (xfrm[i]->props.mode == XFRM_MODE_BEET); ++ if (outer_family == AF_INET6) { ++ remote.in6 = __xfrm6_bundle_addr_remote(xfrm[i], remote.in6); ++ local.in6 = __xfrm6_bundle_addr_local(xfrm[i], local.in6); ++ } else if (outer_family == AF_INET) { ++ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4; ++ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4; ++ } else { ++ BUG_ON(1); ++ } + } ++ + __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); + trailer_len += xfrm[i]->props.trailer_len; + +- if (tunnel) { +- ipv6_addr_copy(&fl_tunnel.fl6_dst, remote); +- ipv6_addr_copy(&fl_tunnel.fl6_src, local); ++ if (outer_family) { ++ switch (outer_family) { ++ default: ++ case AF_INET6: ++ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6); ++ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6); ++ break; ++ case AF_INET: ++ fl_tunnel.fl4_dst = remote.in->s_addr; ++ fl_tunnel.fl4_src = local.in->s_addr; ++ fl_tunnel.fl4_tos = 0; ++ fl_tunnel.fl4_scope = 0; ++ break; ++ } + err = xfrm_dst_lookup((struct xfrm_dst **) &rt, +- &fl_tunnel, AF_INET6); ++ &fl_tunnel, outer_family); + if (err) + goto error; + } else +@@ -241,6 +264,12 @@ + } + + xfrm_init_pmtu(dst); ++ if (beet && outer_family == AF_INET) { ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ u32 mtu = dst_mtu(dst); ++ xfrm6_update_pmtu(dst, mtu + delta); ++ } ++ + return 0; + + error: +diff -urN linux-2.6.20.21/net/ipv6/xfrm6_state.c linux-2.6.20.21-hipl/net/ipv6/xfrm6_state.c +--- linux-2.6.20.21/net/ipv6/xfrm6_state.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_state.c 2010-03-12 17:42:24.000000000 +0200 +@@ -98,6 +98,18 @@ + src[i] = NULL; + } + } ++ if (j == n) ++ goto end; ++ ++ /* Rule 5: select IPsec BEET */ ++ for (i = 0; i < n; i++) { ++ if (src[i] && ++ src[i]->props.mode == XFRM_MODE_BEET) { ++ dst[j++] = src[i]; ++ src[i] = NULL; ++ } ++ } ++ + if (likely(j == n)) + goto end; + +diff -urN linux-2.6.20.21/net/ipv6/xfrm6_tunnel.c linux-2.6.20.21-hipl/net/ipv6/xfrm6_tunnel.c +--- linux-2.6.20.21/net/ipv6/xfrm6_tunnel.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/ipv6/xfrm6_tunnel.c 2010-03-12 17:42:24.000000000 +0200 +@@ -5,12 +5,12 @@ + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. +- * ++ * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +- * ++ * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -32,7 +32,7 @@ + #include <linux/mutex.h> + + /* +- * xfrm_tunnel_spi things are for allocating unique id ("spi") ++ * xfrm_tunnel_spi things are for allocating unique id ("spi") + * per xfrm_address_t. + */ + struct xfrm6_tunnel_spi { +@@ -70,7 +70,7 @@ + return h; + } + +-static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi) ++static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) + { + return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; + } +@@ -155,8 +155,8 @@ + + for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { + index = xfrm6_tunnel_spi_hash_byspi(spi); +- hlist_for_each_entry(x6spi, pos, +- &xfrm6_tunnel_spi_byspi[index], ++ hlist_for_each_entry(x6spi, pos, ++ &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_1; +@@ -167,8 +167,8 @@ + } + for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { + index = xfrm6_tunnel_spi_hash_byspi(spi); +- hlist_for_each_entry(x6spi, pos, +- &xfrm6_tunnel_spi_byspi[index], ++ hlist_for_each_entry(x6spi, pos, ++ &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_2; +@@ -222,7 +222,7 @@ + + write_lock_bh(&xfrm6_tunnel_spi_lock); + +- hlist_for_each_entry_safe(x6spi, pos, n, ++ hlist_for_each_entry_safe(x6spi, pos, n, + &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + list_byaddr) + { +@@ -269,9 +269,9 @@ + { + /* xfrm6_tunnel native err handling */ + switch (type) { +- case ICMPV6_DEST_UNREACH: ++ case ICMPV6_DEST_UNREACH: + switch (code) { +- case ICMPV6_NOROUTE: ++ case ICMPV6_NOROUTE: + case ICMPV6_ADM_PROHIBITED: + case ICMPV6_NOT_NEIGHBOUR: + case ICMPV6_ADDR_UNREACH: +@@ -287,7 +287,7 @@ + case ICMPV6_EXC_HOPLIMIT: + break; + case ICMPV6_EXC_FRAGTIME: +- default: ++ default: + break; + } + break; +@@ -307,7 +307,7 @@ + + static int xfrm6_tunnel_init_state(struct xfrm_state *x) + { +- if (x->props.mode != XFRM_MODE_TUNNEL) ++ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET) + return -EINVAL; + + if (x->encap) +@@ -339,17 +339,29 @@ + .priority = 2, + }; + ++static struct xfrm6_tunnel xfrm46_tunnel_handler = { ++ .handler = xfrm6_tunnel_rcv, ++ .err_handler = xfrm6_tunnel_err, ++ .priority = 2, ++}; ++ + static int __init xfrm6_tunnel_init(void) + { + if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) + return -EAGAIN; + +- if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { ++ if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) { ++ xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); ++ return -EAGAIN; ++ } ++ if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) { ++ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + return -EAGAIN; + } + if (xfrm6_tunnel_spi_init() < 0) { +- xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); ++ xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); ++ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + return -EAGAIN; + } +@@ -359,7 +371,8 @@ + static void __exit xfrm6_tunnel_fini(void) + { + xfrm6_tunnel_spi_fini(); +- xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); ++ xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); ++ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + } + +diff -urN linux-2.6.20.21/net/xfrm/xfrm_policy.c linux-2.6.20.21-hipl/net/xfrm/xfrm_policy.c +--- linux-2.6.20.21/net/xfrm/xfrm_policy.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/xfrm/xfrm_policy.c 2010-03-12 17:42:24.000000000 +0200 +@@ -1206,7 +1206,7 @@ + xfrm_address_t *local = saddr; + struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; + +- if (tmpl->mode == XFRM_MODE_TUNNEL) { ++ if (tmpl->mode == XFRM_MODE_TUNNEL || tmpl->mode == XFRM_MODE_BEET) { + remote = &tmpl->id.daddr; + local = &tmpl->saddr; + family = tmpl->encap_family; +@@ -1550,7 +1550,7 @@ + unsigned short family) + { + if (xfrm_state_kern(x)) +- return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family); ++ return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family); + return x->id.proto == tmpl->id.proto && + (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && + (x->props.reqid == tmpl->reqid || !tmpl->reqid) && +diff -urN linux-2.6.20.21/net/xfrm/xfrm_state.c linux-2.6.20.21-hipl/net/xfrm/xfrm_state.c +--- linux-2.6.20.21/net/xfrm/xfrm_state.c 2007-10-17 22:31:14.000000000 +0300 ++++ linux-2.6.20.21-hipl/net/xfrm/xfrm_state.c 2010-03-12 17:42:24.000000000 +0200 +@@ -561,7 +561,7 @@ + selector. + */ + if (x->km.state == XFRM_STATE_VALID) { +- if (!xfrm_selector_match(&x->sel, fl, family) || ++ if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || + !security_xfrm_state_pol_flow_match(x, pol, fl)) + continue; + if (!best || +@@ -573,9 +573,10 @@ + acquire_in_progress = 1; + } else if (x->km.state == XFRM_STATE_ERROR || + x->km.state == XFRM_STATE_EXPIRED) { +- if (xfrm_selector_match(&x->sel, fl, family) && +- security_xfrm_state_pol_flow_match(x, pol, fl)) ++ if (xfrm_selector_match(&x->sel, fl, x->sel.family) && ++ security_xfrm_state_pol_flow_match(x, pol, fl)) { + error = -ESRCH; ++ } + } + } + } === added file 'patches/kernel/2.6.20/beet-2.6.20.patch' --- patches/kernel/2.6.20/beet-2.6.20.patch 1970-01-01 00:00:00 +0000 +++ patches/kernel/2.6.20/beet-2.6.20.patch 2010-03-19 09:53:35 +0000 @@ -0,0 +1,1605 @@ +diff -urN linux-2.6.20/include/net/route.h linux-2.6.20-hipl/include/net/route.h +--- linux-2.6.20/include/net/route.h 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/include/net/route.h 2010-03-12 14:20:22.000000000 +0200 +@@ -146,7 +146,8 @@ + + static inline int ip_route_connect(struct rtable **rp, __be32 dst, + __be32 src, u32 tos, int oif, u8 protocol, +- __be16 sport, __be16 dport, struct sock *sk) ++ __be16 sport, __be16 dport, struct sock *sk, ++ int flags) + { + struct flowi fl = { .oif = oif, + .nl_u = { .ip4_u = { .daddr = dst, +@@ -168,7 +169,7 @@ + *rp = NULL; + } + security_sk_classify_flow(sk, &fl); +- return ip_route_output_flow(rp, &fl, sk, 0); ++ return ip_route_output_flow(rp, &fl, sk, flags); + } + + static inline int ip_route_newports(struct rtable **rp, u8 protocol, +diff -urN linux-2.6.20/include/net/xfrm.h linux-2.6.20-hipl/include/net/xfrm.h +--- linux-2.6.20/include/net/xfrm.h 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/include/net/xfrm.h 2010-03-12 14:20:22.000000000 +0200 +@@ -237,7 +237,7 @@ + extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); + extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c); + extern void km_state_notify(struct xfrm_state *x, struct km_event *c); +-#define XFRM_ACQ_EXPIRES 30 ++#define XFRM_ACQ_EXPIRES 3 + + struct xfrm_tmpl; + extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); +@@ -929,14 +929,14 @@ + extern int xfrm_init_state(struct xfrm_state *x); + extern int xfrm4_rcv(struct sk_buff *skb); + extern int xfrm4_output(struct sk_buff *skb); +-extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); +-extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); ++extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); ++extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); + extern int xfrm6_rcv_spi(struct sk_buff *skb, __be32 spi); + extern int xfrm6_rcv(struct sk_buff **pskb); + extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, + xfrm_address_t *saddr, u8 proto); +-extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); +-extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); ++extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family); ++extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family); + extern __be32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); + extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); + extern __be32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); +diff -urN linux-2.6.20/net/dccp/ipv4.c linux-2.6.20-hipl/net/dccp/ipv4.c +--- linux-2.6.20/net/dccp/ipv4.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/dccp/ipv4.c 2010-03-12 14:20:22.000000000 +0200 +@@ -72,7 +72,7 @@ + tmp = ip_route_connect(&rt, nexthop, inet->saddr, + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, + IPPROTO_DCCP, +- inet->sport, usin->sin_port, sk); ++ inet->sport, usin->sin_port, sk, 1); + if (tmp < 0) + return tmp; + +diff -urN linux-2.6.20/net/dccp/ipv6.c linux-2.6.20-hipl/net/dccp/ipv6.c +--- linux-2.6.20/net/dccp/ipv6.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/dccp/ipv6.c 2010-03-12 14:20:22.000000000 +0200 +@@ -1041,7 +1041,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- err = xfrm_lookup(&dst, &fl, sk, 0); ++ err = xfrm_lookup(&dst, &fl, sk, 1); + if (err < 0) + goto failure; + +diff -urN linux-2.6.20/net/ipv4/af_inet.c linux-2.6.20-hipl/net/ipv4/af_inet.c +--- linux-2.6.20/net/ipv4/af_inet.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/af_inet.c 2010-03-12 14:20:22.000000000 +0200 +@@ -1007,7 +1007,7 @@ + RT_CONN_FLAGS(sk), + sk->sk_bound_dev_if, + sk->sk_protocol, +- inet->sport, inet->dport, sk); ++ inet->sport, inet->dport, sk, 0); + if (err) + return err; + +diff -urN linux-2.6.20/net/ipv4/datagram.c linux-2.6.20-hipl/net/ipv4/datagram.c +--- linux-2.6.20/net/ipv4/datagram.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/datagram.c 2010-03-12 14:20:22.000000000 +0200 +@@ -49,7 +49,7 @@ + err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr, + RT_CONN_FLAGS(sk), oif, + sk->sk_protocol, +- inet->sport, usin->sin_port, sk); ++ inet->sport, usin->sin_port, sk, 1); + if (err) + return err; + if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { +diff -urN linux-2.6.20/net/ipv4/esp4.c linux-2.6.20-hipl/net/ipv4/esp4.c +--- linux-2.6.20/net/ipv4/esp4.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/esp4.c 2010-03-12 14:20:22.000000000 +0200 +@@ -402,6 +402,8 @@ + x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; + if (x->props.mode == XFRM_MODE_TUNNEL) + x->props.header_len += sizeof(struct iphdr); ++ else if (x->props.mode == XFRM_MODE_BEET) ++ x->props.header_len += IPV4_BEET_PHMAXLEN; + if (x->encap) { + struct xfrm_encap_tmpl *encap = x->encap; + +diff -urN linux-2.6.20/net/ipv4/ipip.c linux-2.6.20-hipl/net/ipv4/ipip.c +--- linux-2.6.20/net/ipv4/ipip.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/ipip.c 2010-03-12 14:20:22.000000000 +0200 +@@ -870,7 +870,7 @@ + + printk(banner); + +- if (xfrm4_tunnel_register(&ipip_handler)) { ++ if (xfrm4_tunnel_register(&ipip_handler, AF_INET)) { + printk(KERN_INFO "ipip init: can't register tunnel\n"); + return -EAGAIN; + } +@@ -892,7 +892,7 @@ + err2: + free_netdev(ipip_fb_tunnel_dev); + err1: +- xfrm4_tunnel_deregister(&ipip_handler); ++ xfrm4_tunnel_deregister(&ipip_handler, AF_INET); + goto out; + } + +@@ -912,7 +912,7 @@ + + static void __exit ipip_fini(void) + { +- if (xfrm4_tunnel_deregister(&ipip_handler)) ++ if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET)) + printk(KERN_INFO "ipip close: can't deregister tunnel\n"); + + rtnl_lock(); +diff -urN linux-2.6.20/net/ipv4/raw.c linux-2.6.20-hipl/net/ipv4/raw.c +--- linux-2.6.20/net/ipv4/raw.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/raw.c 2010-03-12 14:20:22.000000000 +0200 +@@ -489,7 +489,7 @@ + } + + security_sk_classify_flow(sk, &fl); +- err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); ++ err = ip_route_output_flow(&rt, &fl, sk, 1); + } + if (err) + goto done; +diff -urN linux-2.6.20/net/ipv4/route.c linux-2.6.20-hipl/net/ipv4/route.c +--- linux-2.6.20/net/ipv4/route.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/route.c 2010-03-12 14:20:22.000000000 +0200 +@@ -108,6 +108,7 @@ + #ifdef CONFIG_SYSCTL + #include <linux/sysctl.h> + #endif ++#include <linux/xfrm.h> + + #define RT_FL_TOS(oldflp) \ + ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK))) +diff -urN linux-2.6.20/net/ipv4/tcp_ipv4.c linux-2.6.20-hipl/net/ipv4/tcp_ipv4.c +--- linux-2.6.20/net/ipv4/tcp_ipv4.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/tcp_ipv4.c 2010-03-12 14:20:22.000000000 +0200 +@@ -191,7 +191,7 @@ + tmp = ip_route_connect(&rt, nexthop, inet->saddr, + RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, + IPPROTO_TCP, +- inet->sport, usin->sin_port, sk); ++ inet->sport, usin->sin_port, sk, 1); + if (tmp < 0) + return tmp; + +diff -urN linux-2.6.20/net/ipv4/tunnel4.c linux-2.6.20-hipl/net/ipv4/tunnel4.c +--- linux-2.6.20/net/ipv4/tunnel4.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/tunnel4.c 2010-03-12 14:20:22.000000000 +0200 +@@ -14,9 +14,10 @@ + #include <net/xfrm.h> + + static struct xfrm_tunnel *tunnel4_handlers; ++static struct xfrm_tunnel *tunnel64_handlers; + static DEFINE_MUTEX(tunnel4_mutex); + +-int xfrm4_tunnel_register(struct xfrm_tunnel *handler) ++int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family) + { + struct xfrm_tunnel **pprev; + int ret = -EEXIST; +@@ -24,7 +25,8 @@ + + mutex_lock(&tunnel4_mutex); + +- for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if ((*pprev)->priority > priority) + break; + if ((*pprev)->priority == priority) +@@ -44,14 +46,15 @@ + + EXPORT_SYMBOL(xfrm4_tunnel_register); + +-int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler) ++int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family) + { + struct xfrm_tunnel **pprev; + int ret = -ENOENT; + + mutex_lock(&tunnel4_mutex); + +- for (pprev = &tunnel4_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET) ? &tunnel4_handlers : &tunnel64_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if (*pprev == handler) { + *pprev = handler->next; + ret = 0; +@@ -86,6 +89,26 @@ + return 0; + } + ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++static int tunnel64_rcv(struct sk_buff *skb) ++{ ++ struct xfrm_tunnel *handler; ++ ++ if (!pskb_may_pull(skb, sizeof(struct iphdr))) ++ goto drop; ++ ++ for (handler = tunnel64_handlers; handler; handler = handler->next) ++ if (!handler->handler(skb)) ++ return 0; ++ ++ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); ++ ++drop: ++ kfree_skb(skb); ++ return 0; ++} ++#endif ++ + static void tunnel4_err(struct sk_buff *skb, u32 info) + { + struct xfrm_tunnel *handler; +@@ -101,17 +124,36 @@ + .no_policy = 1, + }; + ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++static struct net_protocol tunnel64_protocol = { ++ .handler = tunnel64_rcv, ++ .err_handler = tunnel4_err, ++ .no_policy = 1, ++}; ++#endif ++ + static int __init tunnel4_init(void) + { + if (inet_add_protocol(&tunnel4_protocol, IPPROTO_IPIP)) { + printk(KERN_ERR "tunnel4 init: can't add protocol\n"); + return -EAGAIN; + } ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (inet_add_protocol(&tunnel64_protocol, IPPROTO_IPV6)) { ++ printk(KERN_ERR "tunnel64 init: can't add protocol\n"); ++ inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP); ++ return -EAGAIN; ++ } ++#endif + return 0; + } + + static void __exit tunnel4_fini(void) + { ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (inet_del_protocol(&tunnel64_protocol, IPPROTO_IPV6)) ++ printk(KERN_ERR "tunnel64 close: can't remove protocol\n"); ++#endif + if (inet_del_protocol(&tunnel4_protocol, IPPROTO_IPIP)) + printk(KERN_ERR "tunnel4 close: can't remove protocol\n"); + } +diff -urN linux-2.6.20/net/ipv4/udp.c linux-2.6.20-hipl/net/ipv4/udp.c +--- linux-2.6.20/net/ipv4/udp.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/udp.c 2010-03-12 14:20:22.000000000 +0200 +@@ -629,7 +629,7 @@ + { .sport = inet->sport, + .dport = dport } } }; + security_sk_classify_flow(sk, &fl); +- err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); ++ err = ip_route_output_flow(&rt, &fl, sk, 1); + if (err) + goto out; + +diff -urN linux-2.6.20/net/ipv4/xfrm4_input.c linux-2.6.20-hipl/net/ipv4/xfrm4_input.c +--- linux-2.6.20/net/ipv4/xfrm4_input.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/xfrm4_input.c 2010-03-12 14:26:28.000000000 +0200 +@@ -106,7 +106,7 @@ + if (x->mode->input(x, skb)) + goto drop; + +- if (x->props.mode == XFRM_MODE_TUNNEL) { ++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { + decaps = 1; + break; + } +@@ -136,10 +136,8 @@ + nf_reset(skb); + + if (decaps) { +- if (!(skb->dev->flags&IFF_LOOPBACK)) { +- dst_release(skb->dst); +- skb->dst = NULL; +- } ++ dst_release(skb->dst); ++ skb->dst = NULL; + netif_rx(skb); + return 0; + } else { +diff -urN linux-2.6.20/net/ipv4/xfrm4_mode_beet.c linux-2.6.20-hipl/net/ipv4/xfrm4_mode_beet.c +--- linux-2.6.20/net/ipv4/xfrm4_mode_beet.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/xfrm4_mode_beet.c 2010-03-12 14:45:37.000000000 +0200 +@@ -6,6 +6,7 @@ + * Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> + * Abhinav Pathak <abhinav.pathak@xxxxxxx> + * Jeff Ahrenholz <ahrenholz@xxxxxxxxx> ++ * Joakim Koskela <jookos@xxxxxxxxx> + */ + + #include <linux/init.h> +@@ -14,54 +15,97 @@ + #include <linux/skbuff.h> + #include <linux/stringify.h> + #include <net/dst.h> ++#include <net/dsfield.h> + #include <net/ip.h> ++#include <net/inet_ecn.h> + #include <net/xfrm.h> + +-/* Add encapsulation header. +- * +- * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. +- * The following fields in it shall be filled in by x->type->output: +- * tot_len +- * check +- * +- * On exit, skb->h will be set to the start of the payload to be processed +- * by x->type->output and skb->nh will be set to the top IP header. +- */ + static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb) + { +- struct iphdr *iph, *top_iph = NULL; +- int hdrlen, optlen; ++ struct dst_entry *dst = skb->dst; ++ int hdrlen; ++ struct iphdr *iphv4, *top_iphv4; ++ struct ipv6hdr *iphv6, *top_iphv6; + +- iph = skb->nh.iph; +- skb->h.ipiph = iph; ++ if (skb->nh.iph->version == 4) { + +- hdrlen = 0; +- optlen = iph->ihl * 4 - sizeof(*iph); +- if (unlikely(optlen)) +- hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4); +- +- skb->nh.raw = skb_push(skb, x->props.header_len + hdrlen); +- top_iph = skb->nh.iph; +- hdrlen = iph->ihl * 4 - optlen; +- skb->h.raw += hdrlen; +- +- memmove(top_iph, iph, hdrlen); +- if (unlikely(optlen)) { +- struct ip_beet_phdr *ph; +- +- BUG_ON(optlen < 0); +- +- ph = (struct ip_beet_phdr *)skb->h.raw; +- ph->padlen = 4 - (optlen & 4); +- ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; +- ph->nexthdr = top_iph->protocol; ++ int optlen; + +- top_iph->protocol = IPPROTO_BEETPH; +- top_iph->ihl = sizeof(struct iphdr) / 4; +- } ++ /* 4-4 */ ++ ++ iphv4 = skb->nh.iph; ++ skb->h.ipiph = iphv4; ++ ++ hdrlen = x->props.header_len; ++ ++ optlen = iphv4->ihl * 4 - sizeof(*iphv4); ++ ++ if (!optlen) { ++ hdrlen -= IPV4_BEET_PHMAXLEN; ++ } else { ++ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4)); ++ hdrlen -= optlen & 4; ++ } ++ ++ skb->nh.raw = skb_push(skb, hdrlen); ++ ++ top_iphv4 = skb->nh.iph; ++ hdrlen = iphv4->ihl * 4 - optlen; ++ skb->h.raw += hdrlen; ++ memmove(top_iphv4, iphv4, hdrlen); ++ ++ if (unlikely(optlen)) { ++ struct ip_beet_phdr *ph; ++ ++ BUG_ON(optlen < 0); ++ ++ ph = (struct ip_beet_phdr *)skb->h.raw; ++ ph->padlen = 4 - (optlen & 4); ++ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; ++ ph->nexthdr = iphv4->protocol; ++ top_iphv4->protocol = IPPROTO_BEETPH; ++ top_iphv4->ihl = sizeof(struct iphdr) / 4; ++ } ++ ++ top_iphv4->saddr = x->props.saddr.a4; ++ top_iphv4->daddr = x->id.daddr.a4; ++ ++ skb->protocol = htons(ETH_P_IP); ++ ++ } else if (skb->nh.iph->version == 6) { ++ ++ u8 protocol; ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ ++ /* Inner = 6, Outer = 4 : changing the external IP hdr ++ * to the outer addresses ++ */ ++ ++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN; ++ skb_push(skb, hdrlen); ++ iphv6 = skb->nh.ipv6h; ++ ++ skb->nh.raw = skb->data; ++ top_iphv6 = skb->nh.ipv6h; ++ ++ protocol = iphv6->nexthdr; ++ skb->nh.raw = skb_pull(skb, delta); ++ top_iphv4 = skb->nh.iph; ++ skb->h.raw = skb->data + hdrlen; ++ top_iphv4->ihl = (sizeof(struct iphdr) >> 2); ++ top_iphv4->version = 4; ++ top_iphv4->id = 0; ++ top_iphv4->frag_off = htons(IP_DF); ++ top_iphv4->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); ++ top_iphv4->saddr = x->props.saddr.a4; ++ top_iphv4->daddr = x->id.daddr.a4; ++ skb->h.raw += top_iphv4->ihl*4; ++ top_iphv4->protocol = protocol; ++ ++ skb->protocol = htons(ETH_P_IP); ++ } else ++ BUG_ON(1); + +- top_iph->saddr = x->props.saddr.a4; +- top_iph->daddr = x->id.daddr.a4; + + return 0; + } +@@ -69,45 +113,73 @@ + static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) + { + struct iphdr *iph = skb->nh.iph; ++ int hops = skb->nh.iph->ttl; + int phlen = 0; + int optlen = 0; ++ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr); ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); + __u8 ph_nexthdr = 0, protocol = 0; + int err = -EINVAL; + + protocol = iph->protocol; + +- if (unlikely(iph->protocol == IPPROTO_BEETPH)) { +- struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); ++ if (x->sel.family == AF_INET6) { ++ /* Here, the inner family is 6, therefore I have to ++ * substitute the IPhdr by enlarging it */ ++ if (skb_tailroom(skb) < delta){ ++ if (pskb_expand_head(skb, 0, delta, GFP_ATOMIC)) ++ goto out; ++ } ++ skb->nh.raw -= delta; ++ } else if (x->sel.family == AF_INET) { ++ if (unlikely(iph->protocol == IPPROTO_BEETPH)) { ++ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(iph + 1); ++ ++ if (!pskb_may_pull(skb, sizeof(*ph))) ++ goto out; ++ ++ phlen = ph->hdrlen * 8; ++ optlen = phlen - ph->padlen - sizeof(*ph); ++ if (optlen < 0 || optlen & 3 || optlen > 250) ++ goto out; ++ ++ if (!pskb_may_pull(skb, phlen)) ++ goto out; ++ ++ ph_nexthdr = ph->nexthdr; ++ } ++ } else ++ BUG_ON(1); + +- if (!pskb_may_pull(skb, sizeof(*ph))) +- goto out; +- +- phlen = ph->hdrlen * 8; +- optlen = phlen - ph->padlen - sizeof(*ph); +- if (optlen < 0 || optlen & 3 || optlen > 250) +- goto out; +- +- if (!pskb_may_pull(skb, phlen)) +- goto out; +- +- ph_nexthdr = ph->nexthdr; +- } +- +- skb_push(skb, sizeof(*iph) - phlen + optlen); ++ size += (optlen - phlen); ++ skb_push(skb, size); + memmove(skb->data, skb->nh.raw, sizeof(*iph)); + skb->nh.raw = skb->data; + +- iph = skb->nh.iph; +- iph->ihl = (sizeof(*iph) + optlen) / 4; +- iph->tot_len = htons(skb->len); +- iph->daddr = x->sel.daddr.a4; +- iph->saddr = x->sel.saddr.a4; +- if (ph_nexthdr) +- iph->protocol = ph_nexthdr; +- else +- iph->protocol = protocol; +- iph->check = 0; +- iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); ++ if (x->sel.family == AF_INET) { ++ iph = skb->nh.iph; ++ iph->ihl = (sizeof(*iph) + optlen) / 4; ++ iph->tot_len = htons(skb->len); ++ iph->daddr = x->sel.daddr.a4; ++ iph->saddr = x->sel.saddr.a4; ++ if (ph_nexthdr) ++ iph->protocol = ph_nexthdr; ++ else ++ iph->protocol = protocol; ++ iph->check = 0; ++ iph->check = ip_fast_csum(skb->nh.raw, iph->ihl); ++ } else if (x->sel.family == AF_INET6) { ++ struct ipv6hdr *ip6h = skb->nh.ipv6h; ++ memset(ip6h->flow_lbl, 0, sizeof(ip6h->flow_lbl)); ++ ip6h->version = 6; ++ ip6h->priority = 0; ++ ip6h->nexthdr = protocol; ++ ip6h->hop_limit = hops; ++ ip6h->payload_len = htons(skb->len - size); ++ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *)&x->sel.daddr.a6); ++ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *)&x->sel.saddr.a6); ++ skb->protocol = htons(ETH_P_IPV6); ++ } + err = 0; + out: + return err; +diff -urN linux-2.6.20/net/ipv4/xfrm4_mode_tunnel.c linux-2.6.20-hipl/net/ipv4/xfrm4_mode_tunnel.c +--- linux-2.6.20/net/ipv4/xfrm4_mode_tunnel.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/xfrm4_mode_tunnel.c 2010-03-12 14:32:11.000000000 +0200 +@@ -66,6 +66,8 @@ + top_iph->daddr = x->id.daddr.a4; + top_iph->protocol = IPPROTO_IPIP; + ++ skb->protocol = htons(ETH_P_IP); ++ + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + return 0; + } +diff -urN linux-2.6.20/net/ipv4/xfrm4_policy.c linux-2.6.20-hipl/net/ipv4/xfrm4_policy.c +--- linux-2.6.20/net/ipv4/xfrm4_policy.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/xfrm4_policy.c 2010-03-12 14:32:35.000000000 +0200 +@@ -15,6 +15,7 @@ + + static struct dst_ops xfrm4_dst_ops; + static struct xfrm_policy_afinfo xfrm4_policy_afinfo; ++static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu); + + static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) + { +@@ -72,17 +73,20 @@ + struct dst_entry *dst, *dst_prev; + struct rtable *rt0 = (struct rtable*)(*dst_p); + struct rtable *rt = rt0; +- __be32 remote = fl->fl4_dst; +- __be32 local = fl->fl4_src; + struct flowi fl_tunnel = { + .nl_u = { + .ip4_u = { +- .saddr = local, +- .daddr = remote, ++ .saddr = fl->fl4_src, ++ .daddr = fl->fl4_dst, + .tos = fl->fl4_tos + } + } + }; ++ union { ++ struct in6_addr *in6; ++ struct in_addr *in; ++ } remote, local; ++ unsigned short outer_family6 = 0; + int i; + int err; + int header_len = 0; +@@ -94,7 +98,7 @@ + for (i = 0; i < nx; i++) { + struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops); + struct xfrm_dst *xdst; +- int tunnel = 0; ++ unsigned short outer_family = 0; + + if (unlikely(dst1 == NULL)) { + err = -ENOBUFS; +@@ -117,20 +121,41 @@ + dst1->next = dst_prev; + dst_prev = dst1; + if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { +- remote = xfrm[i]->id.daddr.a4; +- local = xfrm[i]->props.saddr.a4; +- tunnel = 1; ++ outer_family = xfrm[i]->props.family; ++ if(outer_family == AF_INET){ ++ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4; ++ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4; ++ } else if (outer_family == AF_INET6){ ++ outer_family6 = 1; ++ remote.in6 = (struct in6_addr*)xfrm[i]->id.daddr.a6; ++ local.in6 = (struct in6_addr*)xfrm[i]->props.saddr.a6; ++ } else ++ BUG_ON(1); + } + header_len += xfrm[i]->props.header_len; + trailer_len += xfrm[i]->props.trailer_len; + +- if (tunnel) { +- fl_tunnel.fl4_src = local; +- fl_tunnel.fl4_dst = remote; ++ if (outer_family) { ++ switch (outer_family) { ++ default: ++ case AF_INET: ++ fl_tunnel.fl4_src = local.in->s_addr; ++ fl_tunnel.fl4_dst = remote.in->s_addr; ++ break; ++ case AF_INET6: ++ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6); ++ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6); ++ break; ++ } + err = xfrm_dst_lookup((struct xfrm_dst **)&rt, +- &fl_tunnel, AF_INET); ++ &fl_tunnel, outer_family); + if (err) + goto error; ++ /* Without this, the atomic inc below segfaults */ ++ if (outer_family == AF_INET6) { ++ rt->peer = NULL; ++ rt_bind_peer(rt,1); ++ } + } else + dst_hold(&rt->u.dst); + } +@@ -181,6 +206,12 @@ + } + + xfrm_init_pmtu(dst); ++ if (outer_family6) { ++ /* The worst case */ ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ u32 mtu = dst_mtu(dst); ++ xfrm4_update_pmtu(dst, mtu - delta); ++ } + return 0; + + error: +diff -urN linux-2.6.20/net/ipv4/xfrm4_tunnel.c linux-2.6.20-hipl/net/ipv4/xfrm4_tunnel.c +--- linux-2.6.20/net/ipv4/xfrm4_tunnel.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv4/xfrm4_tunnel.c 2010-03-12 14:33:28.000000000 +0200 +@@ -13,7 +13,7 @@ + static int ipip_output(struct xfrm_state *x, struct sk_buff *skb) + { + struct iphdr *iph; +- ++ + iph = skb->nh.iph; + iph->tot_len = htons(skb->len); + ip_send_check(iph); +@@ -28,7 +28,7 @@ + + static int ipip_init_state(struct xfrm_state *x) + { +- if (x->props.mode != XFRM_MODE_TUNNEL) ++ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET) + return -EINVAL; + + if (x->encap) +@@ -64,24 +64,45 @@ + .priority = 2, + }; + ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++static struct xfrm_tunnel xfrm64_tunnel_handler = { ++ .handler = xfrm4_rcv, ++ .err_handler = xfrm_tunnel_err, ++ .priority = 2, ++}; ++#endif ++ + static int __init ipip_init(void) + { + if (xfrm_register_type(&ipip_type, AF_INET) < 0) { + printk(KERN_INFO "ipip init: can't add xfrm type\n"); + return -EAGAIN; + } +- if (xfrm4_tunnel_register(&xfrm_tunnel_handler)) { +- printk(KERN_INFO "ipip init: can't add xfrm handler\n"); ++ ++ if (xfrm4_tunnel_register(&xfrm_tunnel_handler, AF_INET)) { ++ printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET\n"); ++ xfrm_unregister_type(&ipip_type, AF_INET); ++ return -EAGAIN; ++ } ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (xfrm4_tunnel_register(&xfrm64_tunnel_handler, AF_INET6)) { ++ printk(KERN_INFO "ipip init: can't add xfrm handler for AF_INET6\n"); ++ xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET); + xfrm_unregister_type(&ipip_type, AF_INET); + return -EAGAIN; + } ++#endif + return 0; + } + + static void __exit ipip_fini(void) + { +- if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler)) +- printk(KERN_INFO "ipip close: can't remove xfrm handler\n"); ++#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) ++ if (xfrm4_tunnel_deregister(&xfrm64_tunnel_handler, AF_INET6)) ++ printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET6\n"); ++#endif ++ if (xfrm4_tunnel_deregister(&xfrm_tunnel_handler, AF_INET)) ++ printk(KERN_INFO "ipip close: can't remove xfrm handler for AF_INET\n"); + if (xfrm_unregister_type(&ipip_type, AF_INET) < 0) + printk(KERN_INFO "ipip close: can't remove xfrm type\n"); + } +diff -urN linux-2.6.20/net/ipv6/datagram.c linux-2.6.20-hipl/net/ipv6/datagram.c +--- linux-2.6.20/net/ipv6/datagram.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/datagram.c 2010-03-12 14:20:22.000000000 +0200 +@@ -178,7 +178,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto out; + + /* source address lookup done in ip6_dst_lookup */ +diff -urN linux-2.6.20/net/ipv6/esp6.c linux-2.6.20-hipl/net/ipv6/esp6.c +--- linux-2.6.20/net/ipv6/esp6.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/esp6.c 2010-03-12 14:20:22.000000000 +0200 +@@ -240,9 +240,9 @@ + static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) + { + struct esp_data *esp = x->data; +- u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); ++ u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); + +- if (x->props.mode == XFRM_MODE_TUNNEL) { ++ if (x->props.mode) { + mtu = ALIGN(mtu + 2, blksize); + } else { + /* The worst case. */ +@@ -365,6 +365,8 @@ + x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; + if (x->props.mode == XFRM_MODE_TUNNEL) + x->props.header_len += sizeof(struct ipv6hdr); ++ else if (x->props.mode == XFRM_MODE_BEET) ++ x->props.header_len += IPV4_BEET_PHMAXLEN; + x->data = esp; + return 0; + +diff -urN linux-2.6.20/net/ipv6/icmp.c linux-2.6.20-hipl/net/ipv6/icmp.c +--- linux-2.6.20/net/ipv6/icmp.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/icmp.c 2010-03-12 14:20:22.000000000 +0200 +@@ -64,6 +64,7 @@ + #include <net/ip6_route.h> + #include <net/addrconf.h> + #include <net/icmp.h> ++#include <linux/xfrm.h> + + #include <asm/uaccess.h> + #include <asm/system.h> +diff -urN linux-2.6.20/net/ipv6/ip6_tunnel.c linux-2.6.20-hipl/net/ipv6/ip6_tunnel.c +--- linux-2.6.20/net/ipv6/ip6_tunnel.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/ip6_tunnel.c 2010-03-12 14:20:22.000000000 +0200 +@@ -1127,7 +1127,7 @@ + { + int err; + +- if (xfrm6_tunnel_register(&ip6ip6_handler)) { ++ if (xfrm6_tunnel_register(&ip6ip6_handler, AF_INET6)) { + printk(KERN_ERR "ip6ip6 init: can't register tunnel\n"); + return -EAGAIN; + } +@@ -1146,7 +1146,7 @@ + } + return 0; + fail: +- xfrm6_tunnel_deregister(&ip6ip6_handler); ++ xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6); + return err; + } + +@@ -1170,7 +1170,7 @@ + + static void __exit ip6_tunnel_cleanup(void) + { +- if (xfrm6_tunnel_deregister(&ip6ip6_handler)) ++ if (xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6)) + printk(KERN_INFO "ip6ip6 close: can't deregister tunnel\n"); + + rtnl_lock(); +diff -urN linux-2.6.20/net/ipv6/raw.c linux-2.6.20-hipl/net/ipv6/raw.c +--- linux-2.6.20/net/ipv6/raw.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/raw.c 2010-03-12 14:20:22.000000000 +0200 +@@ -815,7 +815,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto out; + + if (hlimit < 0) { +diff -urN linux-2.6.20/net/ipv6/tcp_ipv6.c linux-2.6.20-hipl/net/ipv6/tcp_ipv6.c +--- linux-2.6.20/net/ipv6/tcp_ipv6.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/tcp_ipv6.c 2010-03-12 14:20:22.000000000 +0200 +@@ -265,7 +265,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto failure; + + if (saddr == NULL) { +diff -urN linux-2.6.20/net/ipv6/tunnel6.c linux-2.6.20-hipl/net/ipv6/tunnel6.c +--- linux-2.6.20/net/ipv6/tunnel6.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/tunnel6.c 2010-03-12 14:20:22.000000000 +0200 +@@ -30,9 +30,10 @@ + #include <net/xfrm.h> + + static struct xfrm6_tunnel *tunnel6_handlers; ++static struct xfrm6_tunnel *tunnel46_handlers; + static DEFINE_MUTEX(tunnel6_mutex); + +-int xfrm6_tunnel_register(struct xfrm6_tunnel *handler) ++int xfrm6_tunnel_register(struct xfrm6_tunnel *handler, unsigned short family) + { + struct xfrm6_tunnel **pprev; + int ret = -EEXIST; +@@ -40,7 +41,8 @@ + + mutex_lock(&tunnel6_mutex); + +- for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if ((*pprev)->priority > priority) + break; + if ((*pprev)->priority == priority) +@@ -60,14 +62,15 @@ + + EXPORT_SYMBOL(xfrm6_tunnel_register); + +-int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler) ++int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler, unsigned short family) + { + struct xfrm6_tunnel **pprev; + int ret = -ENOENT; + + mutex_lock(&tunnel6_mutex); + +- for (pprev = &tunnel6_handlers; *pprev; pprev = &(*pprev)->next) { ++ for (pprev = (family == AF_INET6) ? &tunnel6_handlers : &tunnel46_handlers; ++ *pprev; pprev = &(*pprev)->next) { + if (*pprev == handler) { + *pprev = handler->next; + ret = 0; +@@ -103,6 +106,25 @@ + return 0; + } + ++static int tunnel46_rcv(struct sk_buff **pskb) ++{ ++ struct sk_buff *skb = *pskb; ++ struct xfrm6_tunnel *handler; ++ ++ if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ goto drop; ++ ++ for (handler = tunnel46_handlers; handler; handler = handler->next) ++ if (!handler->handler(skb)) ++ return 0; ++ ++ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, skb->dev); ++ ++drop: ++ kfree_skb(skb); ++ return 0; ++} ++ + static void tunnel6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __be32 info) + { +@@ -119,17 +141,30 @@ + .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, + }; + ++static struct inet6_protocol tunnel46_protocol = { ++ .handler = tunnel46_rcv, ++ .err_handler = tunnel6_err, ++ .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, ++}; ++ + static int __init tunnel6_init(void) + { + if (inet6_add_protocol(&tunnel6_protocol, IPPROTO_IPV6)) { + printk(KERN_ERR "tunnel6 init(): can't add protocol\n"); + return -EAGAIN; + } ++ if (inet6_add_protocol(&tunnel46_protocol, IPPROTO_IPIP)) { ++ printk(KERN_ERR "tunnel6 init(): can't add protocol\n"); ++ inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6); ++ return -EAGAIN; ++ } + return 0; + } + + static void __exit tunnel6_fini(void) + { ++ if (inet6_del_protocol(&tunnel46_protocol, IPPROTO_IPIP)) ++ printk(KERN_ERR "tunnel6 close: can't remove protocol\n"); + if (inet6_del_protocol(&tunnel6_protocol, IPPROTO_IPV6)) + printk(KERN_ERR "tunnel6 close: can't remove protocol\n"); + } +diff -urN linux-2.6.20/net/ipv6/udp.c linux-2.6.20-hipl/net/ipv6/udp.c +--- linux-2.6.20/net/ipv6/udp.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/udp.c 2010-03-12 14:20:22.000000000 +0200 +@@ -736,7 +736,7 @@ + if (final_p) + ipv6_addr_copy(&fl.fl6_dst, final_p); + +- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) ++ if ((err = xfrm_lookup(&dst, &fl, sk, 1)) < 0) + goto out; + + if (hlimit < 0) { +diff -urN linux-2.6.20/net/ipv6/xfrm6_input.c linux-2.6.20-hipl/net/ipv6/xfrm6_input.c +--- linux-2.6.20/net/ipv6/xfrm6_input.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/xfrm6_input.c 2010-03-12 14:34:37.000000000 +0200 +@@ -72,7 +72,7 @@ + if (x->mode->input(x, skb)) + goto drop; + +- if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ ++ if (x->props.mode == XFRM_MODE_TUNNEL || x->props.mode == XFRM_MODE_BEET) { /* XXX */ + decaps = 1; + break; + } +@@ -103,10 +103,8 @@ + nf_reset(skb); + + if (decaps) { +- if (!(skb->dev->flags&IFF_LOOPBACK)) { +- dst_release(skb->dst); +- skb->dst = NULL; +- } ++ dst_release(skb->dst); ++ skb->dst = NULL; + netif_rx(skb); + return -1; + } else { +diff -urN linux-2.6.20/net/ipv6/xfrm6_mode_beet.c linux-2.6.20-hipl/net/ipv6/xfrm6_mode_beet.c +--- linux-2.6.20/net/ipv6/xfrm6_mode_beet.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/xfrm6_mode_beet.c 2010-03-12 14:46:23.000000000 +0200 +@@ -6,6 +6,7 @@ + * Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx> + * Abhinav Pathak <abhinav.pathak@xxxxxxx> + * Jeff Ahrenholz <ahrenholz@xxxxxxxxx> ++ * Joakim Koskela <jookos@xxxxxxxxx> + */ + + #include <linux/init.h> +@@ -16,6 +17,7 @@ + #include <net/dsfield.h> + #include <net/dst.h> + #include <net/inet_ecn.h> ++#include <net/ip.h> + #include <net/ipv6.h> + #include <net/xfrm.h> + +@@ -31,38 +33,165 @@ + * its absence, that of the top IP header. The value of skb->data will always + * point to the top IP header. + */ ++/* Add encapsulation header. ++ * ++ * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. ++ * The following fields in it shall be filled in by x->type->output: ++ * tot_len ++ * check ++ * ++ * On exit, skb->h will be set to the start of the payload to be processed ++ * by x->type->output and skb->nh will be set to the top IP header. ++ */ + static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) + { +- struct ipv6hdr *iph, *top_iph; +- u8 *prevhdr; +- int hdr_len; +- +- skb_push(skb, x->props.header_len); +- iph = skb->nh.ipv6h; +- +- hdr_len = ip6_find_1stfragopt(skb, &prevhdr); +- skb->nh.raw = prevhdr - x->props.header_len; +- skb->h.raw = skb->data + hdr_len; +- memmove(skb->data, iph, hdr_len); + +- skb->nh.raw = skb->data; +- top_iph = skb->nh.ipv6h; +- skb->nh.raw = &top_iph->nexthdr; +- skb->h.ipv6h = top_iph + 1; +- +- ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); +- ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); ++ struct dst_entry *dst = skb->dst; ++ int hdrlen; ++ struct iphdr *iphv4, *top_iphv4; ++ struct ipv6hdr *iphv6, *top_iphv6; ++ ++ if (skb->nh.iph->version == 6) { ++ ++ u8 *prevhdr; ++ int hdr_len; ++ ++/* 6-6 */ ++ ++ hdrlen = x->props.header_len - IPV4_BEET_PHMAXLEN; ++ skb_push(skb, hdrlen); ++ iphv6 = skb->nh.ipv6h; ++ ++ hdr_len = ip6_find_1stfragopt(skb, &prevhdr); ++ skb->nh.raw = prevhdr - hdrlen; ++ skb->h.raw = skb->data + hdr_len; ++ memmove(skb->data, iphv6, hdr_len); ++ ++ skb->nh.raw = skb->data; ++ top_iphv6 = skb->nh.ipv6h; ++ skb->nh.raw = &top_iphv6->nexthdr; ++ skb->h.ipv6h = top_iphv6 + 1; ++ ipv6_addr_copy(&top_iphv6->saddr, (struct in6_addr *)&x->props.saddr); ++ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr); ++ ++ skb->protocol = htons(ETH_P_IPV6); ++ ++ } else if (skb->nh.iph->version == 4) { ++ ++ int flags; ++ int optlen; ++ int dsfield; ++ u8 protocol; ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ ++ /* Inner = 4, Outer = 6*/ ++ ++ iphv4 = skb->nh.iph; ++ skb->h.ipiph = iphv4; ++ ++ hdrlen = x->props.header_len; ++ ++ optlen = iphv4->ihl * 4 - sizeof(*iphv4); ++ ++ if (!optlen) { ++ hdrlen -= IPV4_BEET_PHMAXLEN; ++ } else { ++ skb->h.raw -= (IPV4_BEET_PHMAXLEN - (optlen & 4)); ++ hdrlen -= optlen & 4; ++ } ++ ++ skb->nh.raw = skb_push(skb, hdrlen); ++ ++ top_iphv4 = skb->nh.iph; ++ hdrlen = iphv4->ihl * 4 - optlen; ++ skb->h.raw += hdrlen; ++ if (unlikely(optlen)) { ++ struct ip_beet_phdr *ph; ++ ++ BUG_ON(optlen < 0); ++ ++ ph = (struct ip_beet_phdr *)skb->h.raw; ++ ph->padlen = 4 - (optlen & 4); ++ ph->hdrlen = (optlen + ph->padlen + sizeof(*ph)) / 8; ++ ph->nexthdr = iphv4->protocol; ++ top_iphv4->protocol = IPPROTO_BEETPH; ++ top_iphv4->ihl = sizeof(struct iphdr) / 4; ++ } ++ ++ if (unlikely(optlen)) ++ protocol = top_iphv4->protocol; ++ else ++ protocol = iphv4->protocol; ++ ++ if (skb_headroom(skb) <= 2*delta){ ++ if (pskb_expand_head(skb, delta,0, GFP_ATOMIC)) ++ return -ENOMEM; ++ } ++ ++ skb->nh.raw = skb_push(skb, delta); ++ ++ top_iphv6 = skb->nh.ipv6h; ++ skb->h.ipv6h = top_iphv6 + 1; ++ /* DS disclosed */ ++ top_iphv6->version = 6; ++ top_iphv6->priority = 0; ++ top_iphv6->flow_lbl[0] = 0; ++ top_iphv6->flow_lbl[1] = 0; ++ top_iphv6->flow_lbl[2] = 0; ++ dsfield = ipv6_get_dsfield(top_iphv6); ++ dsfield = INET_ECN_encapsulate(dsfield, dsfield); ++ flags = x->props.flags; ++ if (flags & XFRM_STATE_NOECN) ++ dsfield &= ~INET_ECN_MASK; ++ ipv6_change_dsfield(top_iphv6, 0, dsfield); ++ ++ top_iphv6->nexthdr = protocol; ++ top_iphv6->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); ++ top_iphv6->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); ++ ipv6_addr_copy(&top_iphv6->saddr,(struct in6_addr *)&x->props.saddr); ++ ipv6_addr_copy(&top_iphv6->daddr, (struct in6_addr *)&x->id.daddr); ++ skb->nh.raw = &top_iphv6->nexthdr; ++ ++ skb->protocol = htons(ETH_P_IPV6); ++ } else ++ BUG_ON(1); + + return 0; + } + + static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) + { +- struct ipv6hdr *ip6h; +- int size = sizeof(struct ipv6hdr); ++ struct ip_beet_phdr *ph = (struct ip_beet_phdr*)(skb->h.raw); ++ int size = (x->sel.family == AF_INET) ? sizeof(struct iphdr) : sizeof(struct ipv6hdr); ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ __u8 proto = skb->nh.ipv6h->nexthdr, hops = skb->nh.ipv6h->hop_limit; ++ __u8 ph_nexthdr = 0; ++ int phlen = 0; ++ int optlen = 0; ++ + int err = -EINVAL; + +- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) ++ if (x->sel.family == AF_INET) { ++ /* Inner = IPv4, therefore the IPhdr must be shrunk */ ++ /* Inner = 4, Outer = 6 */ ++ if (unlikely(proto == IPPROTO_BEETPH)) { ++ if (!pskb_may_pull(skb, sizeof(*ph))) ++ goto out; ++ phlen = ph->hdrlen * 8; ++ optlen = phlen - ph->padlen - sizeof(*ph); ++ ++ if (optlen < 0 || optlen & 3 || optlen > 250) ++ goto out; ++ if (!pskb_may_pull(skb, phlen)) ++ goto out; ++ ++ proto = ph_nexthdr = ph->nexthdr; ++ } ++ skb->nh.raw += delta; ++ } ++ ++ if (skb_cloned(skb) && ++ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto out; + + skb_push(skb, size); +@@ -71,11 +200,36 @@ + + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); +- +- ip6h = skb->nh.ipv6h; +- ip6h->payload_len = htons(skb->len - size); +- ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); +- ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); ++ if (unlikely(phlen)) { ++ skb_pull(skb, phlen - optlen); ++ skb->nh.raw = skb->data; ++ } ++ if (x->sel.family == AF_INET6) { ++ struct ipv6hdr *ip6h = skb->nh.ipv6h; ++ ip6h->payload_len = htons(skb->len - size); ++ ipv6_addr_copy(&ip6h->daddr, (struct in6_addr *) &x->sel.daddr.a6); ++ ipv6_addr_copy(&ip6h->saddr, (struct in6_addr *) &x->sel.saddr.a6); ++ } else if (x->sel.family == AF_INET) { ++ struct iphdr *iph = skb->nh.iph; ++ iph->ihl = (sizeof(*iph) + optlen) / 4; ++ iph->version = 4; ++ iph->tos = 0; ++ iph->id = 0; ++ iph->frag_off = 0; ++ iph->ttl = hops; ++ iph->protocol = proto; ++ iph->daddr = x->sel.daddr.a4; ++ iph->saddr = x->sel.saddr.a4; ++ iph->tot_len = htons(skb->len); ++ ip_send_check(iph); ++ skb->protocol = htons(ETH_P_IP); ++ if (unlikely(!optlen)) { ++ skb->h.raw = skb->nh.raw; ++ } ++ dst_release(skb->dst); ++ skb->dst = NULL; ++ } else ++ BUG_ON(1); + err = 0; + out: + return err; +diff -urN linux-2.6.20/net/ipv6/xfrm6_mode_tunnel.c linux-2.6.20-hipl/net/ipv6/xfrm6_mode_tunnel.c +--- linux-2.6.20/net/ipv6/xfrm6_mode_tunnel.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/xfrm6_mode_tunnel.c 2010-03-12 14:36:47.000000000 +0200 +@@ -65,6 +65,8 @@ + top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); + ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); ++ skb->protocol = htons(ETH_P_IPV6); ++ + return 0; + } + +diff -urN linux-2.6.20/net/ipv6/xfrm6_policy.c linux-2.6.20-hipl/net/ipv6/xfrm6_policy.c +--- linux-2.6.20/net/ipv6/xfrm6_policy.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/xfrm6_policy.c 2010-03-12 14:38:03.000000000 +0200 +@@ -24,6 +24,7 @@ + + static struct dst_ops xfrm6_dst_ops; + static struct xfrm_policy_afinfo xfrm6_policy_afinfo; ++static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu); + + static int xfrm6_dst_lookup(struct xfrm_dst **xdst, struct flowi *fl) + { +@@ -89,7 +90,7 @@ + static inline struct in6_addr* + __xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr) + { +- return (x->type->remote_addr) ? ++ return (x->type && x->type->remote_addr) ? + (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) : + (struct in6_addr*)&x->id.daddr; + } +@@ -97,7 +98,7 @@ + static inline struct in6_addr* + __xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr) + { +- return (x->type->local_addr) ? ++ return (x->type && x->type->local_addr) ? + (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) : + (struct in6_addr*)&x->props.saddr; + } +@@ -105,7 +106,7 @@ + static inline void + __xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x) + { +- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT) ++ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT) + *nflen += x->props.header_len; + else + *len += x->props.header_len; +@@ -114,7 +115,7 @@ + static inline void + __xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x) + { +- if (x->type->flags & XFRM_TYPE_NON_FRAGMENT) ++ if (x->type && x->type->flags & XFRM_TYPE_NON_FRAGMENT) + *nflen -= x->props.header_len; + else + *len -= x->props.header_len; +@@ -131,16 +132,19 @@ + struct dst_entry *dst, *dst_prev; + struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); + struct rt6_info *rt = rt0; +- struct in6_addr *remote = &fl->fl6_dst; +- struct in6_addr *local = &fl->fl6_src; ++ unsigned short outer_family = 0, beet = 0; + struct flowi fl_tunnel = { + .nl_u = { + .ip6_u = { +- .saddr = *local, +- .daddr = *remote ++ .saddr = fl->fl6_src, ++ .daddr = fl->fl6_dst + } + } + }; ++ union { ++ struct in6_addr *in6; ++ struct in_addr *in; ++ } remote, local; + int i; + int err = 0; + int header_len = 0; +@@ -153,7 +157,6 @@ + for (i = 0; i < nx; i++) { + struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops); + struct xfrm_dst *xdst; +- int tunnel = 0; + + if (unlikely(dst1 == NULL)) { + err = -ENOBUFS; +@@ -178,18 +181,38 @@ + dst1->next = dst_prev; + dst_prev = dst1; + if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { +- remote = __xfrm6_bundle_addr_remote(xfrm[i], remote); +- local = __xfrm6_bundle_addr_local(xfrm[i], local); +- tunnel = 1; ++ outer_family = xfrm[i]->props.family; ++ beet = (xfrm[i]->props.mode == XFRM_MODE_BEET); ++ if (outer_family == AF_INET6) { ++ remote.in6 = __xfrm6_bundle_addr_remote(xfrm[i], remote.in6); ++ local.in6 = __xfrm6_bundle_addr_local(xfrm[i], local.in6); ++ } else if (outer_family == AF_INET) { ++ remote.in = (struct in_addr*)&xfrm[i]->id.daddr.a4; ++ local.in = (struct in_addr*)&xfrm[i]->props.saddr.a4; ++ } else { ++ BUG_ON(1); ++ } + } ++ + __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); + trailer_len += xfrm[i]->props.trailer_len; + +- if (tunnel) { +- ipv6_addr_copy(&fl_tunnel.fl6_dst, remote); +- ipv6_addr_copy(&fl_tunnel.fl6_src, local); ++ if (outer_family) { ++ switch (outer_family) { ++ default: ++ case AF_INET6: ++ ipv6_addr_copy(&fl_tunnel.fl6_dst, remote.in6); ++ ipv6_addr_copy(&fl_tunnel.fl6_src, local.in6); ++ break; ++ case AF_INET: ++ fl_tunnel.fl4_dst = remote.in->s_addr; ++ fl_tunnel.fl4_src = local.in->s_addr; ++ fl_tunnel.fl4_tos = 0; ++ fl_tunnel.fl4_scope = 0; ++ break; ++ } + err = xfrm_dst_lookup((struct xfrm_dst **) &rt, +- &fl_tunnel, AF_INET6); ++ &fl_tunnel, outer_family); + if (err) + goto error; + } else +@@ -241,6 +264,12 @@ + } + + xfrm_init_pmtu(dst); ++ if (beet && outer_family == AF_INET) { ++ int delta = sizeof(struct ipv6hdr) - sizeof(struct iphdr); ++ u32 mtu = dst_mtu(dst); ++ xfrm6_update_pmtu(dst, mtu + delta); ++ } ++ + return 0; + + error: +diff -urN linux-2.6.20/net/ipv6/xfrm6_state.c linux-2.6.20-hipl/net/ipv6/xfrm6_state.c +--- linux-2.6.20/net/ipv6/xfrm6_state.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/xfrm6_state.c 2010-03-12 14:20:22.000000000 +0200 +@@ -98,6 +98,18 @@ + src[i] = NULL; + } + } ++ if (j == n) ++ goto end; ++ ++ /* Rule 5: select IPsec BEET */ ++ for (i = 0; i < n; i++) { ++ if (src[i] && ++ src[i]->props.mode == XFRM_MODE_BEET) { ++ dst[j++] = src[i]; ++ src[i] = NULL; ++ } ++ } ++ + if (likely(j == n)) + goto end; + +diff -urN linux-2.6.20/net/ipv6/xfrm6_tunnel.c linux-2.6.20-hipl/net/ipv6/xfrm6_tunnel.c +--- linux-2.6.20/net/ipv6/xfrm6_tunnel.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/ipv6/xfrm6_tunnel.c 2010-03-12 14:20:22.000000000 +0200 +@@ -5,12 +5,12 @@ + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. +- * ++ * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. +- * ++ * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +@@ -32,7 +32,7 @@ + #include <linux/mutex.h> + + /* +- * xfrm_tunnel_spi things are for allocating unique id ("spi") ++ * xfrm_tunnel_spi things are for allocating unique id ("spi") + * per xfrm_address_t. + */ + struct xfrm6_tunnel_spi { +@@ -70,7 +70,7 @@ + return h; + } + +-static unsigned inline xfrm6_tunnel_spi_hash_byspi(u32 spi) ++static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) + { + return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; + } +@@ -155,8 +155,8 @@ + + for (spi = xfrm6_tunnel_spi; spi <= XFRM6_TUNNEL_SPI_MAX; spi++) { + index = xfrm6_tunnel_spi_hash_byspi(spi); +- hlist_for_each_entry(x6spi, pos, +- &xfrm6_tunnel_spi_byspi[index], ++ hlist_for_each_entry(x6spi, pos, ++ &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_1; +@@ -167,8 +167,8 @@ + } + for (spi = XFRM6_TUNNEL_SPI_MIN; spi < xfrm6_tunnel_spi; spi++) { + index = xfrm6_tunnel_spi_hash_byspi(spi); +- hlist_for_each_entry(x6spi, pos, +- &xfrm6_tunnel_spi_byspi[index], ++ hlist_for_each_entry(x6spi, pos, ++ &xfrm6_tunnel_spi_byspi[index], + list_byspi) { + if (x6spi->spi == spi) + goto try_next_2; +@@ -222,7 +222,7 @@ + + write_lock_bh(&xfrm6_tunnel_spi_lock); + +- hlist_for_each_entry_safe(x6spi, pos, n, ++ hlist_for_each_entry_safe(x6spi, pos, n, + &xfrm6_tunnel_spi_byaddr[xfrm6_tunnel_spi_hash_byaddr(saddr)], + list_byaddr) + { +@@ -269,9 +269,9 @@ + { + /* xfrm6_tunnel native err handling */ + switch (type) { +- case ICMPV6_DEST_UNREACH: ++ case ICMPV6_DEST_UNREACH: + switch (code) { +- case ICMPV6_NOROUTE: ++ case ICMPV6_NOROUTE: + case ICMPV6_ADM_PROHIBITED: + case ICMPV6_NOT_NEIGHBOUR: + case ICMPV6_ADDR_UNREACH: +@@ -287,7 +287,7 @@ + case ICMPV6_EXC_HOPLIMIT: + break; + case ICMPV6_EXC_FRAGTIME: +- default: ++ default: + break; + } + break; +@@ -307,7 +307,7 @@ + + static int xfrm6_tunnel_init_state(struct xfrm_state *x) + { +- if (x->props.mode != XFRM_MODE_TUNNEL) ++ if (x->props.mode != XFRM_MODE_TUNNEL || x->props.mode != XFRM_MODE_BEET) + return -EINVAL; + + if (x->encap) +@@ -339,17 +339,29 @@ + .priority = 2, + }; + ++static struct xfrm6_tunnel xfrm46_tunnel_handler = { ++ .handler = xfrm6_tunnel_rcv, ++ .err_handler = xfrm6_tunnel_err, ++ .priority = 2, ++}; ++ + static int __init xfrm6_tunnel_init(void) + { + if (xfrm_register_type(&xfrm6_tunnel_type, AF_INET6) < 0) + return -EAGAIN; + +- if (xfrm6_tunnel_register(&xfrm6_tunnel_handler)) { ++ if (xfrm6_tunnel_register(&xfrm6_tunnel_handler, AF_INET6)) { ++ xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); ++ return -EAGAIN; ++ } ++ if (xfrm6_tunnel_register(&xfrm46_tunnel_handler, AF_INET)) { ++ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + return -EAGAIN; + } + if (xfrm6_tunnel_spi_init() < 0) { +- xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); ++ xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); ++ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + return -EAGAIN; + } +@@ -359,7 +371,8 @@ + static void __exit xfrm6_tunnel_fini(void) + { + xfrm6_tunnel_spi_fini(); +- xfrm6_tunnel_deregister(&xfrm6_tunnel_handler); ++ xfrm6_tunnel_deregister(&xfrm46_tunnel_handler, AF_INET); ++ xfrm6_tunnel_deregister(&xfrm6_tunnel_handler, AF_INET6); + xfrm_unregister_type(&xfrm6_tunnel_type, AF_INET6); + } + +diff -urN linux-2.6.20/net/xfrm/xfrm_policy.c linux-2.6.20-hipl/net/xfrm/xfrm_policy.c +--- linux-2.6.20/net/xfrm/xfrm_policy.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/xfrm/xfrm_policy.c 2010-03-12 14:48:34.000000000 +0200 +@@ -1206,7 +1206,7 @@ + xfrm_address_t *local = saddr; + struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; + +- if (tmpl->mode == XFRM_MODE_TUNNEL) { ++ if (tmpl->mode == XFRM_MODE_TUNNEL || tmpl->mode == XFRM_MODE_BEET) { + remote = &tmpl->id.daddr; + local = &tmpl->saddr; + family = tmpl->encap_family; +@@ -1550,7 +1550,7 @@ + unsigned short family) + { + if (xfrm_state_kern(x)) +- return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, family); ++ return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family); + return x->id.proto == tmpl->id.proto && + (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && + (x->props.reqid == tmpl->reqid || !tmpl->reqid) && +diff -urN linux-2.6.20/net/xfrm/xfrm_state.c linux-2.6.20-hipl/net/xfrm/xfrm_state.c +--- linux-2.6.20/net/xfrm/xfrm_state.c 2007-02-04 20:44:54.000000000 +0200 ++++ linux-2.6.20-hipl/net/xfrm/xfrm_state.c 2010-03-12 14:48:35.000000000 +0200 +@@ -561,7 +561,7 @@ + selector. + */ + if (x->km.state == XFRM_STATE_VALID) { +- if (!xfrm_selector_match(&x->sel, fl, family) || ++ if (!xfrm_selector_match(&x->sel, fl, x->sel.family) || + !security_xfrm_state_pol_flow_match(x, pol, fl)) + continue; + if (!best || +@@ -573,9 +573,10 @@ + acquire_in_progress = 1; + } else if (x->km.state == XFRM_STATE_ERROR || + x->km.state == XFRM_STATE_EXPIRED) { +- if (xfrm_selector_match(&x->sel, fl, family) && +- security_xfrm_state_pol_flow_match(x, pol, fl)) ++ if (xfrm_selector_match(&x->sel, fl, x->sel.family) && ++ security_xfrm_state_pol_flow_match(x, pol, fl)) { + error = -ESRCH; ++ } + } + } + } === added file 'patches/kernel/2.6.20/notes.txt' --- patches/kernel/2.6.20/notes.txt 1970-01-01 00:00:00 +0000 +++ patches/kernel/2.6.20/notes.txt 2010-03-19 09:53:35 +0000 @@ -0,0 +1,14 @@ +HIPL 2.6.20 kernel patch notes 12.3.2010 +======================================== + +This patch adds support for interfamily xfrm (beet, tunnel) as well as +the sleep-thingy and everything else needed to run HIP(L). + +Note: + +This patch has NOT been tested thoroughly and is considered +experimental, only for the brave (or desperate) enough stuck with the +2.6.20 kernel. + + +- joakim.koskela@xxxxxxx === modified file 'patches/openwrt/package/Makefile' --- patches/openwrt/package/Makefile 2010-03-03 17:48:34 +0000 +++ patches/openwrt/package/Makefile 2010-03-19 09:53:35 +0000 @@ -17,7 +17,7 @@ define Package/hipl-hipd SECTION:=net CATEGORY:=Network - DEPENDS:=+hipl-common +genl +ip +kmod-ipsec +kmod-ipsec4 +kmod-ipsec6 +kmod-loop +kmod-nbd +kmod-tun +libpthread +libuuid +losetup +kmod-dummy +kmod-ipip +kmod-crypto-authenc + DEPENDS:=+hipl-common +genl +ip +kmod-ipsec +kmod-ipsec4 +kmod-ipsec6 +kmod-loop +kmod-nbd +kmod-tun +libpthread +libuuid +losetup +kmod-dummy +kmod-ipip +kmod-crypto-authenc +kmod-ip6-tunnel # TODO: probably not needed: #+kmod-capi +libpcap +udevtrigger +ipsec-tools +isakmpd TITLE:=HIPL deamon @@ -104,10 +104,6 @@ define Build/Configure (cd $(PKG_BUILD_DIR); rm -rf config.{cache,status}; ./autogen.sh --host=$(GNU_TARGET_NAME) --target=$(GNU_TARGET_NAME)); -# (cd $(PKG_BUILD_DIR)/libinet6; test -L include || ln -v -s include_glibc23 include;); - -# (cp $(PKG_BUILD_DIR)/libinet6/include/ifaddrs.h $(STAGING_DIR)/include/); - (cd ..;); $(CONFIGURE_VARS); @@ -180,12 +176,8 @@ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhipconf.la $(1)/usr/lib/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhiptool.so* $(1)/usr/lib/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libhiptool.la $(1)/usr/lib/ -# $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libinet6.so* $(1)/usr/lib/ -# $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libinet6.la $(1)/usr/lib/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libopphip.so* $(1)/usr/lib/ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libopphip.la $(1)/usr/lib/ - $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/hipsetup $(1)/usr/bin/ -# $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/listifaces $(1)/usr/bin/ endef $(eval $(call BuildPackage,hipl-common)) === modified file 'release.version' --- release.version 2010-03-19 09:32:05 +0000 +++ release.version 2010-03-19 09:53:35 +0000 @@ -1,2 +1,2 @@ Version: 1.0.6 -Release: 2 +Release: 5 === modified file 'test/auth_performance.c' --- test/auth_performance.c 2010-02-18 13:36:05 +0000 +++ test/auth_performance.c 2010-03-19 09:53:35 +0000 @@ -16,15 +16,16 @@ #include <stdio.h> /* printf & co */ #include <stdlib.h> /* exit & co */ #include <unistd.h> -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ +#include "config.h" #include "lib/core/hip_statistics.h" +#include "lib/core/keylen.h" #include "lib/core/crypto.h" -#ifdef CONFIG_HIP_ECDSA + +// only use ecdsa when available +#ifdef HAVE_EC_CRYPTO #include <openssl/ecdsa.h> -#endif /* CONFIG_HIP_ECDSA */ +#endif #define PACKET_LENGTH 1280 @@ -97,10 +98,10 @@ DSA *dsa_key_pool[key_pool_size]; DSA_SIG *dsa_sig_pool[num_measurements]; -#ifdef CONFIG_HIP_ECDSA +#ifdef HAVE_EC_CRYPTO EC_KEY *ecdsa_key_pool[key_pool_size]; ECDSA_SIG *ecdsa_sig_pool[num_measurements]; -#endif /* CONFIG_HIP_ECDSA */ +#endif hip_set_logdebug(LOGDEBUG_NONE); @@ -440,7 +441,7 @@ #endif -#ifdef CONFIG_HIP_ECDSA +#ifdef HAVE_EC_CRYPTO printf("\n-------------------------------\n" "ECDSA performance test\n" "-------------------------------\n"); @@ -486,7 +487,8 @@ printf("%i. ecdsa signature: %.3f ms\n", i + 1, timediff / 1000.0); } } -#endif /* CONFIG_HIP_ECDSA */ +#endif + #if 0 calc_statistics(&creation_stats, &num_items, &min, &max, &avg, &std_dev, STATS_IN_MSECS); === modified file 'test/certteststub.c' --- test/certteststub.c 2010-02-17 17:38:08 +0000 +++ test/certteststub.c 2010-03-19 09:53:35 +0000 @@ -13,6 +13,7 @@ /* required for s6_addr32 */ #define _BSD_SOURCE +#include <arpa/inet.h> #include <sys/time.h> #include <time.h> #include <zlib.h> === modified file 'test/conntest-client-hip.c' --- test/conntest-client-hip.c 2010-02-17 17:38:08 +0000 +++ test/conntest-client-hip.c 2010-03-19 09:53:35 +0000 @@ -9,10 +9,6 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#if HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -25,6 +21,8 @@ #include <netdb.h> #include <sys/time.h> #include <time.h> + +#include "config.h" #include "lib/core/debug.h" #include "lib/core/ife.h" #include "conntest.h" === modified file 'test/conntest-client-native.c' --- test/conntest-client-native.c 2010-02-17 17:38:08 +0000 +++ test/conntest-client-native.c 2010-03-19 09:53:35 +0000 @@ -18,10 +18,6 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#if HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -36,9 +32,10 @@ #include <time.h> #include <arpa/inet.h> #include <net/if.h> + +#include "config.h" #include "lib/core/debug.h" #include "lib/core/ife.h" - #include "conntest.h" int main(int argc, char *argv[]) === modified file 'test/conntest-client-opp.c' --- test/conntest-client-opp.c 2010-02-17 17:38:08 +0000 +++ test/conntest-client-opp.c 2010-03-19 09:53:35 +0000 @@ -7,10 +7,6 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#if HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -23,6 +19,8 @@ #include <netdb.h> #include <sys/time.h> #include <time.h> + +#include "config.h" #include "lib/core/debug.h" #include "lib/core/ife.h" #include "conntest.h" === modified file 'test/conntest-server.c' --- test/conntest-server.c 2010-02-17 17:38:08 +0000 +++ test/conntest-server.c 2010-03-19 09:53:35 +0000 @@ -12,10 +12,6 @@ /* required for s6_addr32 */ #define _BSD_SOURCE -#if HAVE_CONFIG_H -#include <config.h> -#endif - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -31,6 +27,8 @@ # define __user #endif #include <signal.h> + +#include "config.h" #include "conntest.h" static void sig_handler(int signo) === modified file 'test/conntest.c' --- test/conntest.c 2010-03-19 09:09:25 +0000 +++ test/conntest.c 2010-03-19 09:53:35 +0000 @@ -2,6 +2,8 @@ #define _BSD_SOURCE #include "conntest.h" +#include "lib/tool/nlink.h" +#include "lib/tool/lutil.h" /** * create_serversocket - given the port and the protocol === modified file 'test/conntest.h' --- test/conntest.h 2010-02-17 17:38:08 +0000 +++ test/conntest.h 2010-03-19 09:53:35 +0000 @@ -16,7 +16,7 @@ #include <sys/uio.h> #include "lib/core/debug.h" #include "lib/core/ife.h" -#include "lib/core/misc.h" + int create_socket(int proto); int create_serversocket(int type, in_port_t port); === modified file 'test/cookietest.c' --- test/cookietest.c 2010-02-17 17:38:08 +0000 +++ test/cookietest.c 2010-03-19 09:53:35 +0000 @@ -2,7 +2,8 @@ #define _BSD_SOURCE #include "lib/core/debug.h" -#include "lib/core/misc.h" + +#include "lib/core/solve.h" #include <sys/time.h> #include <time.h> === modified file 'test/dh_performance.c' --- test/dh_performance.c 2010-03-19 09:24:10 +0000 +++ test/dh_performance.c 2010-03-19 09:53:35 +0000 @@ -19,11 +19,9 @@ #include <openssl/sha.h> /* open ssl library for SHA operations */ #include <openssl/dsa.h> /* open ssl library for DSA operations */ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #include "lib/core/crypto.h" +#include "lib/core/filemanip.h" #include "lib/core/hashchain.h" #include "lib/performance/performance.h" === modified file 'test/dhtteststub.c' --- test/dhtteststub.c 2010-02-17 17:38:08 +0000 +++ test/dhtteststub.c 2010-03-19 09:53:35 +0000 @@ -23,9 +23,10 @@ #include <netinet/ip.h> #include <errno.h> #include <time.h> +#include <sys/time.h> #include "lib/dht/libhipdht.h" #include "lib/core/debug.h" -#include "lib/core/misc.h" +#include "lib/core/straddr.h" int main(int argc, char *argv[]) { === modified file 'test/keygentest.c' --- test/keygentest.c 2010-02-17 17:38:08 +0000 +++ test/keygentest.c 2010-03-19 09:53:35 +0000 @@ -13,7 +13,8 @@ #include <time.h> #include "lib/core/debug.h" -#include "lib/core/misc.h" +#include "lib/core/crypto.h" +#include "lib/tool/lutil.h" int main(int argc, char *argv[]) { === modified file 'test/performance/perf_measure.sh' --- test/performance/perf_measure.sh 2010-03-19 09:20:44 +0000 +++ test/performance/perf_measure.sh 2010-03-19 09:53:35 +0000 @@ -20,15 +20,17 @@ RTT_POSTFIX= TCP_POSTFIX= UDP_POSTFIX= +INTERVAL=10 # get the command line options if [ $# -eq 0 ] then - echo "Usage: `basename $0` options: -a <family> [-n <value>] [-p <prefix>] -s|-c <dst> -r|-t <type> [-b <value>] [-l <length>]" + echo "Usage: `basename $0` options: -a <family> [-n <value>] [-i <interval> ] [-p <prefix>] -s|-c <dst> -r|-t <type> [-b <value>] [-l <length>]" echo echo " -a <family> = address family (4 - IPv4, 6 - IPv6)" echo " -b <value> = bandwith to be used for UDP measurements (append K or M)" echo " -c <dst> = client mode with destination ip address" + echo " -i <value> = time interval between runs (in sec)" echo " -l <value> = maximum packet length" echo " -n <value> = number of sequential measurements" echo " -p <prefix> = output file prefix (including absolut path)" @@ -39,7 +41,7 @@ exit 0 fi -set -- `getopt a:b:c:l:n:p:rst: "$@"` +set -- `getopt a:b:c:i:l:n:p:rst: "$@"` [ $# -lt 1 ] && exit 1 # getopt failed while [ $# -gt 0 ] @@ -49,6 +51,7 @@ -b) BANDWIDTH=$2; shift;; -c) RUN_MODE=1 REMOTE_ADDRESS=$2; shift;; + -i) INTERVAL=$2; shift;; -l) PACKET_LENGTH=$2; shift;; -n) MEASUREMENT_COUNT=$2; shift;; -p) FILE=$2; shift;; @@ -128,7 +131,7 @@ then while [ $i -lt $MEASUREMENT_COUNT ] do - iperf -c $REMOTE_ADDRESS $TCP_LENGTH | $OUTPUT$TCP_POSTFIX + iperf -c $REMOTE_ADDRESS $TCP_LENGTH -t $INTERVAL -i 2 | $OUTPUT$TCP_POSTFIX i=`expr $i + 1` sleep 2 done @@ -136,7 +139,7 @@ then while [ $i -lt $MEASUREMENT_COUNT ] do - iperf -V -c $REMOTE_ADDRESS $TCP_LENGTH | $OUTPUT$TCP_POSTFIX + iperf -V -c $REMOTE_ADDRESS $TCP_LENGTH -t $INTERVAL -i 2 | $OUTPUT$TCP_POSTFIX i=`expr $i + 1` sleep 2 done @@ -185,7 +188,7 @@ then while [ $i -lt $MEASUREMENT_COUNT ] do - iperf -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth $BANDWIDTH | $OUTPUT$UDP_POSTFIX + iperf -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth $BANDWIDTH -t $INTERVAL | $OUTPUT$UDP_POSTFIX i=`expr $i + 1` sleep 2 done @@ -193,7 +196,7 @@ then while [ $i -lt $MEASUREMENT_COUNT ] do - iperf -V -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth $BANDWIDTH | $OUTPUT$UDP_POSTFIX + iperf -V -c $REMOTE_ADDRESS --udp --len $PACKET_LENGTH --bandwidth $BANDWIDTH -t $INTERVAL | $OUTPUT$UDP_POSTFIX i=`expr $i + 1` sleep 2 done === modified file 'test/sqliteteststub.c' --- test/sqliteteststub.c 2010-03-03 13:16:18 +0000 +++ test/sqliteteststub.c 2010-03-19 09:53:35 +0000 @@ -10,10 +10,7 @@ * */ -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif /* HAVE_CONFIG_H */ - +#include "config.h" #ifdef CONFIG_HIP_AGENT #include "lib/core/prefix.h" === modified file 'tools/hipl_autobuild' --- tools/hipl_autobuild 2010-03-19 09:20:44 +0000 +++ tools/hipl_autobuild 2010-03-19 09:53:35 +0000 @@ -2,14 +2,17 @@ # HIPL autobuild script for periodic compilation tests. # The name of the branch to test needs to be passed as the first parameter. # +# This script relies on the following home directory layout: +# - $HOME/src/hipl/ - location for HIPL shared repository +# - $HOME/src/hipl/<branch> - location for HIPL <branch> to be tested +# - $HOME/tmp/hipl_autobuild/ - temporary build directory +# # If the HIPL_NOTIFICATION_EMAIL environment variable is set to a suitable value # for the user running this script, then email will be sent in case of failure. BRANCH_NAME=$1 -BRANCH_LOCATION=$2 - BUILD_DIR=$HOME/tmp/hipl_autobuild -BRANCH_URL=http://hipl.hiit.fi/hipl/hipl-bzr/$BRANCH_LOCATION +BRANCH_URL=$HOME/src/hipl/$BRANCH_NAME CHECKOUT_DIR=$BUILD_DIR/$(date +"%Y-%m-%d-%H%M")_$BRANCH_NAME BRANCH_REVISION=$(bzr revno -q $BRANCH_URL) BRANCH_REVISION_FILE=$BUILD_DIR/HIPL_REVISION_$BRANCH_NAME @@ -23,13 +26,27 @@ rm -f log.txt return 0 else - SUBJECT="[$BRANCH_NAME] [autobuild] failing command: $@" - test $HIPL_NOTIFICATION_EMAIL && - mailx -s "$SUBJECT" $HIPL_NOTIFICATION_EMAIL < log.txt + test $HIPL_NOTIFICATION_EMAIL && mail_notify "$1" cleanup 1 fi } +mail_notify() +{ + COMMAND="$1" + cat > msg.txt <<EOF +branch: $BRANCH_NAME +revision: $BRANCH_REVISION +configuration: $CONFIGURATION +command: $COMMAND +compiler output: + +EOF + cat log.txt >> msg.txt + SUBJECT="[autobuild] [$BRANCH_NAME] revision $BRANCH_REVISION" + mailx -s "$SUBJECT" $HIPL_NOTIFICATION_EMAIL < msg.txt +} + cleanup() { chmod -R u+rwx "$CHECKOUT_DIR" @@ -40,24 +57,29 @@ compile() { - run_program ./autogen.sh && - run_program ./configure --prefix=$(pwd)/local_install $@ && - run_program make -j16 && - run_program make -j16 distcheck && - run_program make install + CONFIGURATION="--prefix=$(pwd)/local_install $@" + run_program "./autogen.sh" && + run_program "./configure" $CONFIGURATION && + run_program "make -j17" && + run_program "make -j17 distcheck" && + run_program "make install" } test $BRANCH_REVISION = $AUTOBUILD_REVISION && exit 0 -bzr checkout -q --lightweight $BRANCH_URL $CHECKOUT_DIR +bzr checkout -q --lightweight $BRANCH_URL $CHECKOUT_DIR || exit 1 -cd "$CHECKOUT_DIR" +cd "$CHECKOUT_DIR" || exit 1 # Compile HIPL in different configurations +# vanilla configuration compile -# The following configuration is commented out until HIPL is fixed -#compile --disable-rvs --disable-ice --disable-hipproxy --disable-opportunistic --disable-savaipopt -#compile --enable-agent --enable-cookie --enable-pfkey --enable-cert --disable-rvs --disable-ice --disable-hipproxy --enable-openwrt --enable-altsep --enable-i3 --disable-privsep --disable-opportunistic --disable-savaipopt --disable-dht --enable-blind --enable-libinet6 --enable-profiling --enable-ecdsa --disable-debug --enable-midauth --enable-performance --enable-demo + +# PISA configuration +compile --enable-firewall --disable-agent --disable-pfkey --disable-rvs --disable-hipproxy --disable-altsep --enable-privsep --disable-i3 --disable-opportunistic --disable-dht --disable-blind --disable-profiling --enable-debug --enable-midauth --disable-performance --disable-demo + +# Alternative path to vanilla +compile --enable-firewall --enable-agent --enable-pfkey --disable-rvs --disable-hipproxy --enable-openwrt --enable-altsep --disable-privsep --enable-i3 --disable-opportunistic --disable-dht --enable-blind --enable-profiling --disable-debug --enable-midauth --enable-performance --enable-demo cleanup 0 === modified file 'tools/pisacert.c' --- tools/pisacert.c 2010-02-17 17:38:08 +0000 +++ tools/pisacert.c 2010-03-19 09:53:35 +0000 @@ -10,10 +10,14 @@ #include <sys/time.h> #include <time.h> #include <zlib.h> +#include <unistd.h> +#include <sys/types.h> #include "lib/core/ife.h" #include "lib/core/icomm.h" #include "lib/core/debug.h" #include "lib/core/certtools.h" +#include "lib/core/builder.h" +#include "lib/core/message.h" /** * Get the default hit of the local HIPD.