[hipl-dev] [Merge] lp:~hipl-core/hipl/libhip into lp:hipl

  • From: Xin <eric.nevup@xxxxxxxxx>
  • To: HIPL core team <hipl-dev@xxxxxxxxxxxxx>
  • Date: Wed, 08 Feb 2012 08:43:18 -0000

You have been requested to review the proposed merge of 
lp:~hipl-core/hipl/libhip into lp:hipl.

For more details, see:
https://code.launchpad.net/~hipl-core/hipl/libhip/+merge/91407

Libhip merge proposal:

The libhip branch mainly aims to provide a convenient way for system test of 
HIPL without full installation and configuration. In addition to this purpose, 
it also provides a socket API alike library approach for application to use 
HIP. Last by not least, since vanilla Linux TCP does not yet support long 
periods of disconnectivity [1] , libhip can be a solution in this condition.

In the libhip branch, we build a library version of HIP for upper applications, 
which only exposes traditional socket like API. when using the libhip, hip 
control messages are transmitted over TCP or UDP, which is similar to TLS/DTLS 
but we have a unified protocol to handle both datagram and streaming 
traffic[2]. Compared to TLS/DTLS, this is a big advantage and it may be better 
use case for HIP[3].

In the libhip, most of code of hipd has been moved to lib/hipdaemon which then 
becomes a library for both hipd and libhip. By this way, the libhip can reuse 
the code of hipd to the max extend. This is also the reason why libhip can be a 
system test approach for hipd, especially in the process of base exchange, the 
libhip and hipd share the same code base. Meanwhile, the hip daemon, and other 
functionalities previous exist in the trunk, are kept unchanged and functioning 
after this merge.

We also implement a sample application called hipnetcat, which is a 
client-server style application on top of libhip and these 2 sides establish 
HIP association via BEX before actual data communication. The hipnetcat is 
integrated into our automatically test framework (check_hipnetcat). In 
check_hipnetcat, 2 hipnetcat processes try to establish BEX on loopback address 
on top of TCP/UDP, therefore, the execution of this test suite will check the 
functionality of base exchange in a system level.

Currently the libhip is still at an eary stage, there are several features 
waiting for implementation. First there is no support in the firewall; Second, 
although the control plane base exchange functions well, the data plane 
security is not implemented yet. We plan to introduce libsrtp for this purpose; 
Third, the libhip is not thread save yet, because the socket descriptors we use 
now are global variables; Last, the support of long period disconnectivity we 
mention in the first paragraph is not included in this merge, there will be 
another merge request for this feature.

[1] Schutz et al,. Protocol enhancements for intermittently connected hosts, 
2005
[2] Komu et al, Technical report: Sockets and Beyond Assessing the Source Code 
of Network Applications, 2012
[3] Levä et al, Adoption of General-purpose Communication Protocols: the Case 
of Host Identity Protocol, unpublished manuscript, 2012 

-- 
https://code.launchpad.net/~hipl-core/hipl/libhip/+merge/91407
Your team HIPL core team is requested to review the proposed merge of 
lp:~hipl-core/hipl/libhip into lp:hipl.
=== modified file '.bzrignore'
--- .bzrignore  2012-01-25 10:44:48 +0000
+++ .bzrignore  2012-02-07 15:20:56 +0000
@@ -60,6 +60,7 @@
 test/dh_performance
 test/fw_port_bindings_performance
 test/hc_performance
+test/hipnetcat
 tools/hipconf
 tools/hipdnskeyparse/hipdnskeyparse
 tools/hipdnsproxy/hipdnsproxy

=== modified file 'Makefile.am'
--- Makefile.am 2012-01-30 12:28:31 +0000
+++ Makefile.am 2012-02-07 15:20:56 +0000
@@ -40,7 +40,8 @@
 ### user programs ###
 bin_PROGRAMS = test/auth_performance    \
                test/certteststub        \
-               test/hc_performance
+               test/hc_performance      \
+               test/hipnetcat
 
 if HIP_PERFORMANCE
 bin_PROGRAMS += test/dh_performance
@@ -64,19 +65,22 @@
 
 ### libraries ###
 lib_LTLIBRARIES = lib/core/libhipcore.la
-
+lib_LTLIBRARIES += lib/hipdaemon/libhipdaemon.la
 
 ### tests ###
 if HIP_UNITTESTS
-TESTS           = test/check_hipd     \
-                  test/check_hipfw    \
-                  test/check_lib_core \
-                  test/check_lib_tool \
+TESTS           = test/check_hipd       \
+                  test/check_hipfw      \
+                  test/check_hipnetcat  \
+                  test/check_lib_core   \
+                  test/check_lib_tool   \
                   test/check_modules_midauth
-check_PROGRAMS  = test/check_hipd     \
-                  test/check_hipfw    \
-                  test/check_lib_core \
-                  test/check_lib_tool \
+
+check_PROGRAMS  = test/check_hipd       \
+                  test/check_hipfw      \
+                  test/check_hipnetcat  \
+                  test/check_lib_core   \
+                  test/check_lib_tool   \
                   test/check_modules_midauth
 endif
 
@@ -86,55 +90,17 @@
 test_auth_performance_SOURCES               = test/auth_performance.c
 test_certteststub_SOURCES                   = test/certteststub.c
 test_dh_performance_SOURCES                 = test/dh_performance.c
-test_fw_port_bindings_performance_SOURCES   = 
test/fw_port_bindings_performance.c \
-                                              hipfw/file_buffer.c              
   \
+test_fw_port_bindings_performance_SOURCES   = hipfw/file_buffer.c              
   \
                                               hipfw/line_parser.c              
   \
-                                              hipfw/port_bindings.c
+                                              hipfw/port_bindings.c            
   \
+                                              
test/fw_port_bindings_performance.c
 test_hc_performance_SOURCES                 = test/hc_performance.c
+test_hipnetcat_SOURCES        = test/hipnetcat.c
 
 tools_hipconf_SOURCES  = tools/hipconf.c
 tools_pisacert_SOURCES = tools/pisacert.c
 
-hipd_hipd_sources = hipd/accessor.c              \
-                    hipd/cert.c                  \
-                    hipd/close.c                 \
-                    hipd/configfilereader.c      \
-                    hipd/cookie.c                \
-                    hipd/dh.c                    \
-                    hipd/esp_prot_anchordb.c     \
-                    hipd/esp_prot_hipd_msg.c     \
-                    hipd/esp_prot_light_update.c \
-                    hipd/hadb.c                  \
-                    hipd/hidb.c                  \
-                    hipd/hip_socket.c            \
-                    hipd/hipd.c                  \
-                    hipd/hiprelay.c              \
-                    hipd/hit_to_ip.c             \
-                    hipd/init.c                  \
-                    hipd/input.c                 \
-                    hipd/keymat.c                \
-                    hipd/lsidb.c                 \
-                    hipd/maintenance.c           \
-                    hipd/nat.c                   \
-                    hipd/netdev.c                \
-                    hipd/nsupdate.c              \
-                    hipd/opp_mode.c              \
-                    hipd/output.c                \
-                    hipd/pkt_handling.c          \
-                    hipd/registration.c          \
-                    hipd/user.c                  \
-                    hipd/user_ipsec_hipd_msg.c   \
-                    hipd/user_ipsec_sadb_api.c   \
-                    modules/heartbeat/hipd/heartbeat.c          \
-                    modules/heartbeat_update/hipd/hb_update.c   \
-                    modules/midauth/lib/midauth_builder.c       \
-                    modules/update/hipd/update.c                \
-                    modules/update/hipd/update_builder.c        \
-                    modules/update/hipd/update_locator.c        \
-                    modules/update/hipd/update_param_handling.c
-
-hipd_hipd_SOURCES = $(hipd_hipd_sources)                \
-                    modules/midauth/hipd/midauth.c      \
+hipd_hipd_SOURCES = hipd/hipd.c          \
                     hipd/main.c
 
 dist_sysconf_DATA = hipd/hipd.conf                \
@@ -164,8 +130,7 @@
                       hipfw/user_ipsec_api.c      \
                       hipfw/user_ipsec_esp.c      \
                       hipfw/user_ipsec_fw_msg.c   \
-                      hipfw/user_ipsec_sadb.c     \
-                      modules/midauth/lib/midauth_builder.c
+                      hipfw/user_ipsec_sadb.c
 
 # The hipfw unit test program is linked against the hipfw object files.
 # To avoid duplicate symbols during linking some object files need to excluded.
@@ -210,6 +175,49 @@
 lib_core_libhipcore_la_SOURCES += lib/core/performance.c
 endif
 
+lib_hipdaemon_libhipdaemon_la_sources = lib/hipdaemon/accessor.c              \
+                                        lib/hipdaemon/cert.c                  \
+                                        lib/hipdaemon/close.c                 \
+                                        lib/hipdaemon/configfilereader.c      \
+                                        lib/hipdaemon/cookie.c                \
+                                        lib/hipdaemon/dh.c                    \
+                                        lib/hipdaemon/esp_prot_anchordb.c     \
+                                        lib/hipdaemon/esp_prot_hipd_msg.c     \
+                                        lib/hipdaemon/esp_prot_light_update.c \
+                                        lib/hipdaemon/hadb.c                  \
+                                        lib/hipdaemon/hidb.c                  \
+                                        lib/hipdaemon/hip_socket.c            \
+                                        lib/hipdaemon/hiprelay.c              \
+                                        lib/hipdaemon/hit_to_ip.c             \
+                                        lib/hipdaemon/init.c                  \
+                                        lib/hipdaemon/input.c                 \
+                                        lib/hipdaemon/keymat.c                \
+                                        lib/hipdaemon/lsidb.c                 \
+                                        lib/hipdaemon/maintenance.c           \
+                                        lib/hipdaemon/nat.c                   \
+                                        lib/hipdaemon/netdev.c                \
+                                        lib/hipdaemon/nsupdate.c              \
+                                        lib/hipdaemon/opp_mode.c              \
+                                        lib/hipdaemon/output.c                \
+                                        lib/hipdaemon/pkt_handling.c          \
+                                        lib/hipdaemon/registration.c          \
+                                        lib/hipdaemon/socket_wrapper.c        \
+                                        lib/hipdaemon/user.c                  \
+                                        lib/hipdaemon/user_ipsec_hipd_msg.c   \
+                                        lib/hipdaemon/user_ipsec_sadb_api.c   \
+                                        modules/heartbeat/hipd/heartbeat.c     
     \
+                                        
modules/heartbeat_update/hipd/hb_update.c   \
+                                        modules/midauth/lib/midauth_builder.c  
     \
+                                        modules/update/hipd/update.c           
     \
+                                        modules/update/hipd/update_builder.c   
     \
+                                        modules/update/hipd/update_locator.c   
     \
+                                        
modules/update/hipd/update_param_handling.c
+
+lib_hipdaemon_libhipdaemon_la_SOURCES = 
$(lib_hipdaemon_libhipdaemon_la_sources) \
+                                        lib/hipdaemon/pisa.c    \
+                                        modules/midauth/hipd/midauth.c
+
+lib_hipdaemon_libhipdaemon_la_LIBADD  = lib/core/libhipcore.la
 
 test_check_hipd_SOURCES     = test/check_hipd.c              \
                               test/hipd/lsidb.c
@@ -225,6 +233,8 @@
                            test/hipfw/rewrite.c        \
                            $(hipfw_hipfw_sources)
 
+test_check_hipnetcat_SOURCES = test/check_hipnetcat.c
+
 test_check_lib_core_SOURCES = test/check_lib_core.c          \
                               test/lib/core/crypto.c         \
                               test/lib/core/hit.c            \
@@ -241,21 +251,35 @@
                                      test/modules/midauth/hipd/midauth.c       
 \
                                      $(hipd_hipd_sources)
 
-
 ### static library dependencies ###
-
-hipd_hipd_LDADD                          = lib/core/libhipcore.la
-hipfw_hipfw_LDADD                        = lib/core/libhipcore.la
-test_auth_performance_LDADD              = lib/core/libhipcore.la
-test_check_hipd_LDADD                    = lib/core/libhipcore.la
-test_check_hipfw_LDADD                   = lib/core/libhipcore.la
-test_check_lib_core_LDADD                = lib/core/libhipcore.la
-test_check_lib_tool_LDADD                = lib/core/libhipcore.la
-test_check_modules_midauth_LDADD         = lib/core/libhipcore.la
-test_certteststub_LDADD                  = lib/core/libhipcore.la
-test_dh_performance_LDADD                = lib/core/libhipcore.la
-test_fw_port_bindings_performance_LDADD  = lib/core/libhipcore.la
-test_hc_performance_LDADD                = lib/core/libhipcore.la
+hipd_hipd_LDADD                          = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+hipfw_hipfw_LDADD                        = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_auth_performance_LDADD              = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_check_hipd_LDADD                    = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_check_hipfw_LDADD                   = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_check_hipnetcat_LDADD               = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_check_lib_core_LDADD                = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_check_lib_tool_LDADD                = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_check_modules_midauth_LDADD         = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_certteststub_LDADD                  = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_dh_performance_LDADD                = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_fw_port_bindings_performance_LDADD  = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_hc_performance_LDADD                = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
+test_hipnetcat_LDADD                     = lib/core/libhipcore.la \
+                                           lib/hipdaemon/libhipdaemon.la
 tools_hipconf_LDADD                      = lib/core/libhipcore.la
 tools_pisacert_LDADD                     = lib/core/libhipcore.la
 

=== modified file 'doc/HOWTO.xml.in'
--- doc/HOWTO.xml.in    2012-01-25 10:44:48 +0000
+++ doc/HOWTO.xml.in    2012-02-07 15:20:56 +0000
@@ -764,6 +764,58 @@
     </para>
   </section> <!-- handover -->
 
+  <section id="ch_hipnetcat">
+    <title>Test HIPL by the hipnetcat program</title>
+    <para>
+      The hipnetcat can be used to test the base exchange functionality of the 
HIPL without
+      installing the HIPL binary. This section explains its usage in detail.
+    </para>
+    <para>
+      The hipnetcat program takes similar parameters as the normal netcat 
program. In
+      order to check the functionality of the base exchange, a hipnetcat 
server and a
+      hipnetcat client are required.
+    </para>
+    <para>
+      The usage of hipnetcat is shown as follow:
+      <programlisting>
+        Usage: hipnetcat [-hlt] [-p source_port] [-s source_ip_address]
+                 [-d dest_port] [peer_identifier[s]]
+
+          -h: help
+          -l: Listening mode, hip netcat acts as the server side.
+          -t: Using TCP as transportation protocol, otherwise UDP will be used.
+      </programlisting>
+      The peer_identifiers can be a list of combination of peer's HIT, IP 
address and
+      host name.
+    </para>
+    <para>
+      Example 1: localhost hipnetcat connection via TCP. The server listens on 
127.0.0.1:22300
+      and the client connects from 127.0.0.1:22345 with HIT 
2001:1c:809e:244a:c33:78fb:45e3:d132.
+      <programlisting>
+        The server:
+        hipnetcat -l -t -s 127.0.0.1 -p 22300
+
+        The client:
+        hipnetcat -t -s 127.0.0.1 -p 22345 -d 22300 127.0.0.1 
2001:1c:809e:244a:c33:78fb:45e3:d132
+      </programlisting>
+    </para>
+    <para>
+      Example 2: localhost hipnetcat connection via UDP. The server listens on 
127.0.0.1:22300
+      and the client connects from 127.0.0.1:22345 with HIT 
2001:1c:809e:244a:c33:78fb:45e3:d132.
+      <programlisting>
+        The server:
+        hipnetcat -l -s 127.0.0.1 -p 22300
+
+        The client:
+        hipnetcat -s 127.0.0.1 -p 22345 -d 22300 127.0.0.1 
2001:1c:809e:244a:c33:78fb:45e3:d132
+      </programlisting>
+    </para>
+    <para>
+      If the hipnetcat execution successes, the server will receive one 
message from the client,
+      and then both sides exit without any error.
+    </para>
+  </section> <!-- hipnetcat -->
+
   </chapter> <!-- ch_prebuilt -->
 
   <chapter id="ch_how_to_use_hip">
@@ -2583,7 +2635,79 @@
     </para>
 
   </section>
-
+  <section id="ch_libhip_usage">
+    <title>The Libhip Extension</title>
+
+    <para>
+      The Libhip provides HIP functionality as a library for upper layer
+      applications and it does not require the present of normal hip
+      daemon. Instead, the HIP control messages are transmitted on top of
+      TCP/UDP. From the application points of view, they get similar API set
+      as normal socket API. This section describes the usage of libhip API.
+    </para>
+
+    <para>
+      The Libhip API set is listed as follow:
+      <programlisting>
+        <emphasis>"socket_wrapper.h"</emphasis>
+        int hip_socket(int domain, int type, int protocol);
+        int hip_close(int fd);
+        int hip_bind(int fd, const struct sockaddr *address, socklen_t 
address_len);
+        int hip_sendto(int fd, const void *msg, size_t len,
+                       int flags, const struct sockaddr *dst_hit,
+                       socklen_t dst_len);
+        int hip_recvfrom(int fd, void *buf, size_t len, int flags,
+                         struct sockaddr *addr, socklen_t *addr_len);
+        int hip_connect(int fd, const struct sockaddr *addr, socklen_t 
addr_len);
+        int hip_accept(int fd, struct sockaddr *addr, socklen_t *addr_len);
+
+        <emphasis>"init.h"</emphasis>
+        int libhipd_init(void);
+      </programlisting>
+    </para>
+
+    <para>
+      The libhip requires user to initialize it before calling any socket 
wrapper
+      function which starts with "hip_" prefix. To initialize the libhip, call 
the
+      <emphasis>libhipd_init</emphasis> function in init.h
+    </para>
+
+    <para>
+      Once the libhip initialization finishes, user can use functions provided 
by
+      socket_wrapper.h and it works like normal socket function except that:
+      <itemizedlist>
+        <listitem>
+        <para>
+          In <emphasis>hip_sendto</emphasis> and 
<emphasis>hip_connect</emphasis>,
+          the destination address should be a HIT, not an IP address.The 
destination
+          port should also be included in the same structure.
+        </para>
+        </listitem>
+        <listitem>
+        <para>
+          In <emphasis>hip_recvfrom</emphasis>, the remote peer address should 
also
+          be a HIT, not an IP address.The peer's port should also be included 
in the
+          same structure.
+        </para>
+        </listitem>
+        <listitem>
+        <para>
+          In <emphasis>hip_accept</emphasis>, after it accepts a new peer, the
+          <emphasis>addr</emphasis> parameter returns a structure which 
container peer's
+          HIT and port (NOT IP). the <emphasis>addr_len</emphasis> parameter 
returns
+          the length of this structure. The user then can use this structure 
for further
+          function calls such as <emphasis>hip_recvfrom</emphasis>.
+        </para>
+        </listitem>
+      </itemizedlist>
+    </para>
+
+    <para>
+      For more detail usage of the libhip, please refer to the hipnetcat 
program
+      in the <emphasis>test</emphasis> directory.
+    </para>
+
+  </section> <!-- ch_libhip_usage -->
 </chapter> <!-- ch_exp_extensions -->
 
 </book>

=== modified file 'hipd/hipd.c'
--- hipd/hipd.c 2011-11-25 16:40:40 +0000
+++ hipd/hipd.c 2012-02-07 15:20:56 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -58,49 +58,14 @@
 #include "lib/core/protodefs.h"
 #include "lib/core/straddr.h"
 #include "lib/core/util.h"
+#include "lib/hipdaemon/accessor.h"
+#include "lib/hipdaemon/hip_socket.h"
+#include "lib/hipdaemon/init.h"
+#include "lib/hipdaemon/maintenance.h"
+#include "lib/hipdaemon/netdev.h"
+#include "lib/hipdaemon/hipd.h"
+
 #include "config.h"
-#include "accessor.h"
-#include "hip_socket.h"
-#include "init.h"
-#include "maintenance.h"
-#include "netdev.h"
-#include "hipd.h"
-
-
-/** Suppress advertising of none, AF_INET or AF_INET6 address in UPDATEs.
- *  0 = none = default, AF_INET, AF_INET6 */
-int suppress_af_family = 0;
-
-/* For sending HIP control messages */
-int hip_raw_sock_output_v6 = 0;
-int hip_raw_sock_output_v4 = 0;
-
-/* For receiving HIP control messages */
-int hip_raw_sock_input_v6 = 0;
-int hip_raw_sock_input_v4 = 0;
-
-/** File descriptor of the socket used for sending HIP control packet
- *  NAT traversal on UDP/IPv4
- */
-int hip_nat_sock_output_udp = 0;
-
-/** File descriptor of the socket used for receiving HIP control packet
- *  NAT traversal on UDP/IPv4
- */
-int hip_nat_sock_input_udp = 0;
-
-int hip_nat_sock_output_udp_v6 = 0;
-int hip_nat_sock_input_udp_v6  = 0;
-
-/** Specifies the NAT status of the daemon. This value indicates if the current
- *  machine is behind a NAT. */
-hip_transform_suite hip_nat_status = 0;
-
-/* Encrypt host id in I2 */
-int hip_encrypt_i2_hi = 0;
-
-/* Communication interface to userspace apps (hipconf etc) */
-int hip_user_sock = 0;
 
 /** For receiving netlink IPsec events (acquire, expire, etc) */
 struct rtnl_handle hip_nl_ipsec;
@@ -109,18 +74,6 @@
  *  nf_ipsec for this purpose). */
 struct rtnl_handle hip_nl_route;
 
-struct sockaddr_in6 hipfw_addr = { 0 };
-static int          hipfw_sock = 0;
-
-/* used to change the transform order see hipconf usage to see the usage
- * This is set to AES, 3DES, NULL by default see hipconf transform order for
- * more information.
- */
-int hip_transform_order = 123;
-
-/* Tells to the daemon should it build LOCATOR parameters to R1 and I2 */
-int hip_locator_status = HIP_MSG_SET_LOCATOR_OFF;
-
 /* We are caching the IP addresses of the host here. The reason is that during
  * in hip_handle_acquire it is not possible to call getifaddrs (it creates
  * a new netlink socket and seems like only one can be open per process).
@@ -132,24 +85,6 @@
 int            address_count;
 HIP_HASHTABLE *addresses;
 
-int address_change_time_counter = -1;
-
-/*Define hip_use_userspace_ipsec variable to indicate whether use
- * userspace ipsec or not. If it is 1, hip uses the user space ipsec.
- * It will not use if hip_use_userspace_ipsec = 0. Added By Tao Wan
- */
-int hip_use_userspace_ipsec = 0;
-
-int  esp_prot_active               = 0;
-int  esp_prot_num_transforms       = 0;
-long esp_prot_num_parallel_hchains = 0;
-
-int hip_shotgun_status = HIP_MSG_SHOTGUN_OFF;
-
-int hip_broadcast_status = HIP_MSG_BROADCAST_OFF;
-
-int hip_wait_addr_changes_to_stabilize = 1;
-
 /**
  * print hipd usage instructions on stderr
  */
@@ -173,32 +108,6 @@
 }
 
 /**
- * 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(HIPFW const struct hip_common *msg)
-{
-#ifdef CONFIG_HIP_FIREWALL
-    int n = 0;
-    HIP_DEBUG("CONFIG_HIP_FIREWALL DEFINED AND STATUS IS %d\n",
-              hipfw_is_alive());
-
-    n = sendto(hipfw_sock,
-               msg,
-               hip_get_msg_total_len(msg),
-               0,
-               (struct sockaddr *) &hipfw_addr,
-               sizeof(hipfw_addr));
-    return n;
-#else
-    HIP_DEBUG("Firewall is disabled.\n");
-    return 0;
-#endif // CONFIG_HIP_FIREWALL
-}
-
-/**
  * Parse the command line options
  * @param argc  number of command line parameters
  * @param argv  command line parameters

=== modified file 'hipd/main.c'
--- hipd/main.c 2011-11-03 09:21:12 +0000
+++ hipd/main.c 2012-02-07 15:20:56 +0000
@@ -33,8 +33,8 @@
 #include <sys/types.h>
 
 
-#include "hipd/hipd.h"
-#include "init.h"
+#include "lib/hipdaemon/hipd.h"
+#include "lib/hipdaemon/init.h"
 #include "lib/core/debug.h"
 
 

=== modified file 'hipfw/hipfw.c'
--- hipfw/hipfw.c       2011-11-25 16:40:40 +0000
+++ hipfw/hipfw.c       2012-02-07 15:20:56 +0000
@@ -75,7 +75,7 @@
 #include "lib/core/performance.h"
 #include "lib/core/prefix.h"
 #include "lib/core/util.h"
-#include "hipd/hipd.h"
+#include "lib/hipdaemon/hipd.h"
 #include "config.h"
 #include "cache.h"
 #include "common_types.h"

=== modified file 'lib/core/crypto.h'
--- lib/core/crypto.h   2011-11-25 17:56:24 +0000
+++ lib/core/crypto.h   2012-02-07 15:20:56 +0000
@@ -65,9 +65,9 @@
 #define RSA_KEY_DEFAULT_BITS       1024
 #define ECDSA_DEFAULT_CURVE        NID_X9_62_prime256v1
 
-
+#define DEFAULT_HOST_RSA_KEY_FILE_NAME      "hip_host_rsa_key"
 #define DEFAULT_HOST_DSA_KEY_FILE_BASE      HIPL_SYSCONFDIR "/hip_host_dsa_key"
-#define DEFAULT_HOST_RSA_KEY_FILE_BASE      HIPL_SYSCONFDIR "/hip_host_rsa_key"
+#define DEFAULT_HOST_RSA_KEY_FILE_BASE      HIPL_SYSCONFDIR "/" 
DEFAULT_HOST_RSA_KEY_FILE_NAME
 #define DEFAULT_HOST_ECDSA_KEY_FILE_BASE    HIPL_SYSCONFDIR 
"/hip_host_ecdsa_key"
 #define DEFAULT_PUB_FILE_SUFFIX             ".pub"
 

=== modified file 'lib/core/hostid.c'
--- lib/core/hostid.c   2011-11-10 10:35:47 +0000
+++ lib/core/hostid.c   2012-02-07 15:20:56 +0000
@@ -29,6 +29,7 @@
  */
 
 #include <errno.h>
+#include <libgen.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -743,11 +744,16 @@
                 goto out_err;
             }
         } else if (!use_default) {
+            char *hi_file_dup = strdup(hi_file);
+            if ((err = check_and_create_dir(dirname(hi_file_dup), 
HIP_DIR_MODE))) {
+                HIP_ERROR("Could not create direcory for path: %s\n", hi_file);
+                goto out_err;
+            }
             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))) {
+                if ((err = save_dsa_private_key(hi_file, dsa_key))) {
                     HIP_ERROR("Saving of DSA key failed.\n");
                     goto out_err;
                 }
@@ -756,7 +762,7 @@
                 ecdsa_key = create_ecdsa_key(ecdsa_nid);
                 HIP_IFEL(!ecdsa_key, -EINVAL,
                          "Creation of ECDSA key failed.\n");
-                if ((err = save_ecdsa_private_key(ecdsa_filenamebase, 
ecdsa_key))) {
+                if ((err = save_ecdsa_private_key(hi_file, ecdsa_key))) {
                     HIP_ERROR("Saving of ECDSA key failed.\n");
                     goto out_err;
                 }
@@ -765,7 +771,8 @@
                 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))) {
+
+                if ((err = save_rsa_private_key(hi_file, rsa_key))) {
                     HIP_ERROR("Saving of RSA key failed.\n");
                     goto out_err;
                 }

=== modified file 'lib/core/linkedlist.c'
--- lib/core/linkedlist.c       2011-08-15 14:11:56 +0000
+++ lib/core/linkedlist.c       2012-02-07 15:20:56 +0000
@@ -297,6 +297,31 @@
     return ptr;
 }
 
+/*
+ * Deletes the first node in a list with the given element as its data.
+ * If there is no match, does nothing.
+ *
+ * @param linkedlist   the list where from to remove the element.
+ * @param ptr          pointer by which to identify the node
+ * @param free_element a function pointer to a function for freeing the memory
+ *                     allocated for an element at a node or NULL if the 
element
+ *                     itself is not to be freed.
+ */
+void hip_ll_del_by_ptr(struct hip_ll *linkedlist, void *ptr,
+                       free_elem_fn free_element)
+{
+    int                       index   = 0;
+    const struct hip_ll_node *current = NULL;
+
+    while ((current = hip_ll_iterate(linkedlist, current))) {
+        if (current->ptr == ptr) {
+            hip_ll_del(linkedlist, index, free_element);
+            return;
+        }
+        index++;
+    }
+}
+
 /**
  * Deletes the first node from a linked list. If there are no nodes in the 
list,
  * no action will be taken. If @c free_element is non-NULL the memory allocated

=== modified file 'lib/core/linkedlist.h'
--- lib/core/linkedlist.h       2011-11-25 17:56:24 +0000
+++ lib/core/linkedlist.h       2012-02-07 15:20:56 +0000
@@ -69,6 +69,8 @@
 void *hip_ll_del(struct hip_ll *linkedlist, const unsigned int index,
                  free_elem_fn free_element);
 void *hip_ll_del_first(struct hip_ll *linkedlist, free_elem_fn free_element);
+void hip_ll_del_by_ptr(struct hip_ll *linkedlist, void *ptr,
+                       free_elem_fn free_element);
 void *hip_ll_get(const struct hip_ll *const linkedlist, const unsigned int 
index);
 const struct hip_ll_node *hip_ll_iterate(const struct hip_ll *const linkedlist,
                                          const struct hip_ll_node *const 
current);

=== modified file 'lib/core/message.c'
--- lib/core/message.c  2011-11-08 15:25:41 +0000
+++ lib/core/message.c  2012-02-07 15:20:56 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -94,9 +94,9 @@
 #include "hip_udp.h"
 #include "icomm.h"
 #include "ife.h"
+#include "message.h"
 #include "prefix.h"
 #include "protodefs.h"
-#include "message.h"
 
 
 #define HIP_DEFAULT_MSG_TIMEOUT 4000000000ul /* nanoseconds */
@@ -685,6 +685,72 @@
     return err;
 }
 
+int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx)
+{
+    int                  err = 0;
+    int                  len, is_ipv4;
+    struct sockaddr      dst_addr = { 0 };
+    struct sockaddr      src_addr = { 0 };
+    struct sockaddr_in  *saddr4;
+    struct sockaddr_in6 *saddr6;
+    socklen_t            saddr_len = sizeof(struct sockaddr);
+
+    hip_msg_init(ctx->input_msg);
+
+    len = recv(sockfd, ctx->input_msg, HIP_MAX_PACKET, 0);
+    if (len < 0) {
+        HIP_PERROR("recvfrom(): ");
+        return -1;
+    }
+
+    /* Get peer address */
+    if ((err = getpeername(sockfd, &src_addr, &saddr_len))) {
+        HIP_PERROR("getpeername(): ");
+        return err;
+    }
+
+    is_ipv4 = src_addr.sa_family == AF_INET ? 1 : 0;
+    if (is_ipv4) {
+        saddr4 = (struct sockaddr_in *) &src_addr;
+        IPV4_TO_IPV6_MAP(&saddr4->sin_addr, &ctx->src_addr);
+        ctx->msg_ports.src_port = ntohs(saddr4->sin_port);
+    } else {
+        saddr6 = (struct sockaddr_in6 *) &src_addr;
+        memcpy(&ctx->dst_addr, &saddr6->sin6_addr, sizeof(struct in6_addr));
+        ctx->msg_ports.src_port = ntohs(saddr6->sin6_port);
+    }
+
+    /* Get local (bound) address */
+    if ((err = getsockname(sockfd, &dst_addr, &saddr_len))) {
+        HIP_PERROR("getsockname(): ");
+        return err;
+    }
+    if (is_ipv4) {
+        saddr4 = (struct sockaddr_in *) &dst_addr;
+        IPV4_TO_IPV6_MAP(&saddr4->sin_addr, &ctx->dst_addr);
+        ctx->msg_ports.dst_port = saddr4->sin_port;
+    } else {
+        saddr6 = (struct sockaddr_in6 *) &dst_addr;
+        memcpy(&ctx->dst_addr, &saddr6->sin6_addr, sizeof(struct in6_addr));
+        ctx->msg_ports.dst_port = saddr6->sin6_port;
+    }
+
+    HIP_DEBUG_IN6ADDR("src", &ctx->src_addr);
+    HIP_DEBUG_IN6ADDR("dst", &ctx->dst_addr);
+
+    memmove(ctx->input_msg,
+            ((char *) ctx->input_msg) + HIP_UDP_ZERO_BYTES_LEN,
+            HIP_MAX_PACKET - HIP_UDP_ZERO_BYTES_LEN);
+    len -= HIP_UDP_ZERO_BYTES_LEN;
+
+    HIP_IFEL(hip_verify_network_header(ctx->input_msg, &src_addr,
+                                       &dst_addr, len),
+             -1, "verifying network header failed\n");
+
+out_err:
+    return err;
+}
+
 /**
  * Read an IPv6 control message.
  *

=== modified file 'lib/core/message.h'
--- lib/core/message.h  2011-11-25 17:56:24 +0000
+++ lib/core/message.h  2012-02-07 15:20:56 +0000
@@ -46,6 +46,7 @@
 int hip_send_recv_daemon_info(struct hip_common *msg,
                               int send_only,
                               int opt_socket);
+int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx);
 int hip_send_recv_firewall_info(struct hip_common *const msg);
 
 #endif /* HIPL_LIB_CORE_MESSAGE_H */

=== added directory 'lib/hipdaemon'
=== renamed file 'hipd/accessor.c' => 'lib/hipdaemon/accessor.c'
=== renamed file 'hipd/accessor.h' => 'lib/hipdaemon/accessor.h'
=== renamed file 'hipd/cert.c' => 'lib/hipdaemon/cert.c'
=== renamed file 'hipd/cert.h' => 'lib/hipdaemon/cert.h'
=== renamed file 'hipd/close.c' => 'lib/hipdaemon/close.c'
=== renamed file 'hipd/close.h' => 'lib/hipdaemon/close.h'
=== renamed file 'hipd/configfilereader.c' => 'lib/hipdaemon/configfilereader.c'
=== renamed file 'hipd/configfilereader.h' => 'lib/hipdaemon/configfilereader.h'
=== renamed file 'hipd/cookie.c' => 'lib/hipdaemon/cookie.c'
=== renamed file 'hipd/cookie.h' => 'lib/hipdaemon/cookie.h'
=== renamed file 'hipd/dh.c' => 'lib/hipdaemon/dh.c'
=== renamed file 'hipd/dh.h' => 'lib/hipdaemon/dh.h'
=== renamed file 'hipd/esp_prot_anchordb.c' => 
'lib/hipdaemon/esp_prot_anchordb.c'
=== renamed file 'hipd/esp_prot_anchordb.h' => 
'lib/hipdaemon/esp_prot_anchordb.h'
=== renamed file 'hipd/esp_prot_hipd_msg.c' => 
'lib/hipdaemon/esp_prot_hipd_msg.c'
--- hipd/esp_prot_hipd_msg.c    2011-12-16 13:37:33 +0000
+++ lib/hipdaemon/esp_prot_hipd_msg.c   2012-02-07 15:20:56 +0000
@@ -57,6 +57,10 @@
 
 static uint8_t esp_prot_transforms[MAX_NUM_TRANSFORMS];
 
+int  esp_prot_active               = 0;
+int  esp_prot_num_transforms       = 0;
+long esp_prot_num_parallel_hchains = 0;
+
 /**
  * Sends second update message for a public-key-based anchor element update
  *

=== renamed file 'hipd/esp_prot_hipd_msg.h' => 
'lib/hipdaemon/esp_prot_hipd_msg.h'
=== renamed file 'hipd/esp_prot_light_update.c' => 
'lib/hipdaemon/esp_prot_light_update.c'
=== renamed file 'hipd/esp_prot_light_update.h' => 
'lib/hipdaemon/esp_prot_light_update.h'
=== renamed file 'hipd/hadb.c' => 'lib/hipdaemon/hadb.c'
--- hipd/hadb.c 2012-01-25 20:45:27 +0000
+++ lib/hipdaemon/hadb.c        2012-02-07 15:20:56 +0000
@@ -105,6 +105,23 @@
     uint8_t         peer_hostname[HIP_HOST_ID_HOSTNAME_LEN_MAX];
 };
 
+/* Flag to show if hipl is running in libhip mode (=1) or normal mode (=0).
+ * This variable should NOT be accessed directly. Always use the accessor
+ * functions instead.
+ */
+static int hipd_library_mode = 0;
+
+int is_libhip_mode()
+{
+    return hipd_library_mode;
+}
+
+int set_libhip_mode()
+{
+    hipd_library_mode = 1;
+    return 0;
+}
+
 /**
  * The hash function of the hashtable. Calculates a hash from parameter host
  * association HITs (hit_our and hit_peer).
@@ -616,7 +633,12 @@
 
     if (hip_select_source_address(&peer_map.our_addr, &peer_map.peer_addr)) {
         HIP_ERROR("Cannot find source address\n");
-        return -1;
+        if (is_libhip_mode()) {
+            memset(&peer_map.our_addr, 0, sizeof(peer_map.our_addr));
+            HIP_DEBUG("Using ANY for source address\n");
+        } else {
+            return -1;
+        }
     }
 
     if (hip_for_each_hi(hadb_add_peer_info_wrapper, &peer_map)) {
@@ -1459,6 +1481,10 @@
     int prev_spi_out = ha->spi_outbound_current;
     int prev_spi_in  = ha->spi_inbound_current;
 
+    if (hipd_library_mode) {
+        return;
+    }
+
     // Delete previous security policies
     hip_delete_hit_sp_pair(&ha->hit_our, &ha->hit_peer, 1);
     hip_delete_hit_sp_pair(&ha->hit_peer, &ha->hit_our, 1);
@@ -1522,6 +1548,11 @@
                         ha),
              -1, "Error while changing outbound security association\n");
 
+    if (hipd_library_mode) {
+        HIP_DEBUG("No SP set up in library mode\n");
+        goto out_err;
+    }
+
     // Create a new security policy pointing to SAs after SA setup
     HIP_IFEL(hip_setup_hit_sp_pair(&ha->hit_peer,
                                    &ha->hit_our,

=== renamed file 'hipd/hadb.h' => 'lib/hipdaemon/hadb.h'
=== renamed file 'hipd/hidb.c' => 'lib/hipdaemon/hidb.c'
--- hipd/hidb.c 2012-01-25 20:45:27 +0000
+++ lib/hipdaemon/hidb.c        2012-02-07 15:20:56 +0000
@@ -600,13 +600,15 @@
         hip_add_iface_local_route(&in6_lsi);
 
         /* Adding HITs and LSIs to the interface */
-        if (hip_add_iface_local_hit(&hit)) {
-            HIP_ERROR("Failed to add HIT to the device\n");
-            return -1;
-        }
-        if (hip_add_iface_local_hit(&in6_lsi)) {
-            HIP_ERROR("Failed to add LSI to the device\n");
-            return -1;
+        if (!is_libhip_mode()) {
+            if (hip_add_iface_local_hit(&hit)) {
+                HIP_ERROR("Failed to add HIT to the device\n");
+                return -1;
+            }
+            if (hip_add_iface_local_hit(&in6_lsi)) {
+                HIP_ERROR("Failed to add LSI to the device\n");
+                return -1;
+            }
         }
     }
 

=== renamed file 'hipd/hidb.h' => 'lib/hipdaemon/hidb.h'
=== renamed file 'hipd/hip_socket.c' => 'lib/hipdaemon/hip_socket.c'
--- hipd/hip_socket.c   2011-10-25 21:14:16 +0000
+++ lib/hipdaemon/hip_socket.c  2012-02-07 15:20:56 +0000
@@ -55,6 +55,30 @@
     int      (*func_ptr)(struct hip_packet_context *ctx);
 };
 
+/* For sending HIP control messages */
+int hip_raw_sock_output_v6 = 0;
+int hip_raw_sock_output_v4 = 0;
+
+/* For receiving HIP control messages */
+int hip_raw_sock_input_v6 = 0;
+int hip_raw_sock_input_v4 = 0;
+
+/** File descriptor of the socket used for sending HIP control packet
+ *  NAT traversal on UDP/IPv4
+ */
+int hip_nat_sock_output_udp = 0;
+
+/** File descriptor of the socket used for receiving HIP control packet
+ *  NAT traversal on UDP/IPv4
+ */
+int hip_nat_sock_input_udp = 0;
+
+int hip_nat_sock_output_udp_v6 = 0;
+int hip_nat_sock_input_udp_v6  = 0;
+
+/* Communication interface to userspace apps (hipconf etc) */
+int hip_user_sock = 0;
+
 /**
  * List for storage of used sockets
  */

=== renamed file 'hipd/hip_socket.h' => 'lib/hipdaemon/hip_socket.h'
--- hipd/hip_socket.h   2011-11-25 17:56:24 +0000
+++ lib/hipdaemon/hip_socket.h  2012-02-07 15:20:56 +0000
@@ -30,6 +30,15 @@
 #include <sys/select.h>
 #include "lib/core/protodefs.h"
 
+extern int hip_raw_sock_input_v6;
+extern int hip_raw_sock_input_v4;
+extern int hip_nat_sock_input_udp;
+extern int hip_nat_sock_input_udp_v6;
+
+extern int                 hip_user_sock;
+extern int                 hip_firewall_sock;
+extern struct sockaddr_in6 hip_firewall_addr;
+
 void hip_register_sockets(void);
 
 void hip_unregister_sockets(void);

=== renamed file 'hipd/hipd.h' => 'lib/hipdaemon/hipd.h'
--- hipd/hipd.h 2011-11-25 17:56:24 +0000
+++ lib/hipdaemon/hipd.h        2012-02-07 15:20:56 +0000
@@ -59,50 +59,18 @@
 
 #define HIP_ADDRESS_CHANGE_WAIT_INTERVAL 3 /* seconds */
 
-extern struct rtnl_handle hip_nl_route;
-extern struct rtnl_handle hip_nl_ipsec;
 extern struct rtnl_handle hip_nl_generic;
 
-extern int hip_raw_sock_input_v6;
-extern int hip_raw_sock_input_v4;
-extern int hip_nat_sock_input_udp;
-
-extern int hip_raw_sock_output_v6;
-extern int hip_raw_sock_output_v4;
-extern int hip_nat_sock_output_udp;
-
-extern int hip_nat_sock_output_udp_v6;
-extern int hip_nat_sock_input_udp_v6;
-
-extern int address_change_time_counter;
-
-extern int hip_wait_addr_changes_to_stabilize;
-
-extern int hip_user_sock;
-
 extern struct sockaddr_in6 hipfw_addr;
 
 extern int hit_db_lock;
 
-extern int hip_shotgun_status;
-
 extern int hip_broadcast_status;
 
-extern int hip_encrypt_i2_hi;
-
-extern hip_transform_suite hip_nat_status;
-
 extern int  esp_prot_active;
 extern int  esp_prot_num_transforms;
 extern long esp_prot_num_parallel_hchains;
 
-extern int hip_locator_status;
-extern int hip_transform_order;
-
-extern int            suppress_af_family;
-extern int            address_count;
-extern HIP_HASHTABLE *addresses;
-
 /* For switch userspace / kernel IPsec */
 extern int hip_use_userspace_ipsec;
 
@@ -115,4 +83,8 @@
 int hipd_parse_cmdline_opts(int argc, char *argv[], uint64_t * flags);
 int hipd_main(uint64_t flags);
 
+/* libhip_mode accessor */
+int is_libhip_mode(void);
+int set_libhip_mode(void);
+
 #endif /* HIPL_HIPD_HIPD_H */

=== renamed file 'hipd/hiprelay.c' => 'lib/hipdaemon/hiprelay.c'
=== renamed file 'hipd/hiprelay.h' => 'lib/hipdaemon/hiprelay.h'
=== renamed file 'hipd/hit_to_ip.c' => 'lib/hipdaemon/hit_to_ip.c'
=== renamed file 'hipd/hit_to_ip.h' => 'lib/hipdaemon/hit_to_ip.h'
=== renamed file 'hipd/init.c' => 'lib/hipdaemon/init.c'
--- hipd/init.c 2012-01-18 21:21:26 +0000
+++ lib/hipdaemon/init.c        2012-02-07 15:20:56 +0000
@@ -34,6 +34,7 @@
 
 #include <errno.h>
 #include <limits.h>
+#include <pwd.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -74,12 +75,14 @@
 #include "accessor.h"
 #include "close.h"
 #include "dh.h"
+#include "esp_prot_hipd_msg.h"
 #include "esp_prot_light_update.h"
 #include "hadb.h"
 #include "hidb.h"
 #include "hip_socket.h"
 #include "hipd.h"
 #include "hiprelay.h"
+#include "init.h"
 #include "input.h"
 #include "maintenance.h"
 #include "nat.h"
@@ -88,9 +91,8 @@
 #include "output.h"
 #include "pkt_handling.h"
 #include "registration.h"
+#include "socket_wrapper.h"
 #include "user.h"
-#include "init.h"
-#include "hipd/esp_prot_hipd_msg.h"
 
 
 /**
@@ -118,6 +120,8 @@
 #endif
 /** end ICMPV6_FILTER related stuff */
 
+#define HIP_USER_DIR ".hipl/"
+
 /* Startup flags of the HIPD. Keep the around, for they will be used at exit */
 static uint64_t sflags;
 
@@ -523,6 +527,210 @@
     lmod_register_packet_type(HIP_LUPDATE,   "HIP_LUPDATE");
 }
 
+static int libhip_init_handle_functions(void)
+{
+    int err = 0;
+
+    HIP_DEBUG("Initialize handle functions for libhip.\n");
+
+    hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, 
&hip_check_i1,  20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, 
&hip_handle_i1, 30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_send_r1, 
  40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_check_i1,  
20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_handle_i1, 
30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_send_r1,   
40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_check_i1,  
20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_handle_i1, 
30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_send_r1,   
40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_check_i1,  
20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_handle_i1, 
30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_send_r1,   
40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_check_i1, 
 20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, 
&hip_handle_i1, 30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_send_r1,  
 40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_check_i1,  
20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_handle_i1, 
30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_send_r1,   
40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_check_i1,  
20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_handle_i1, 
30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_send_r1,   
40000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_check_i1,  
20000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_handle_i1, 
30000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_NONE, 
&hip_update_retransmissions, 35000);
+    hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_send_r1,   
40000);
+
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_check_i2,  20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_handle_i2, 30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_create_r2, 40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_check_i2,  
20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_handle_i2, 
30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_create_r2, 
40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_check_i2,     
        20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, 
&hip_handle_i2_in_i2_sent, 21000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2,    
        30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_create_r2, 
40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_check_i2,  
20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_handle_i2, 
30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_create_r2, 
40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_check_i2, 
 20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_handle_i2, 30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_create_r2, 40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_check_i2,  
20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_handle_i2, 
30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_create_r2, 
40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_check_i2,  
20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_handle_i2, 
30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_create_r2, 
40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, 
&hip_hmac2_and_sign, 42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_send_r2, 
50000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_check_i2,  
20000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_handle_i2, 
30000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_I2, HIP_STATE_NONE, 
&hip_setup_ipsec_sa, 30500);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_create_r2, 
40000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, 
&hip_add_rvs_reg_from, 41000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_hmac2_and_sign, 
42000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, 
&hip_add_rvs_relay_to, 43000);
+    hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_send_r2, 50000);
+
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_check_r1,  
20000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_r1, 
30000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_update_retransmissions, 30500);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_build_esp_info, 31000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_build_solution, 32000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_handle_diffie_hellman, 33000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&esp_prot_r1_handle_transforms, 34000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_create_i2, 
40000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_add_signed_echo_response, 41000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_mac_and_sign_handler, 42000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, 
&hip_add_unsigned_echo_response, 43000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_send_i2,   
50000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_check_r1,  
20000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_r1, 
30000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_update_retransmissions, 30500);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_build_esp_info, 31000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_build_solution, 32000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_handle_diffie_hellman, 33000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&esp_prot_r1_handle_transforms, 34000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_create_i2, 
40000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_add_signed_echo_response, 41000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_mac_and_sign_handler, 42000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, 
&hip_add_unsigned_echo_response, 43000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_send_i2,   
50000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_check_r1,  
20000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_r1, 
30000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_update_retransmissions, 30500);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_build_esp_info, 31000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_build_solution, 32000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_handle_diffie_hellman, 33000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&esp_prot_r1_handle_transforms, 34000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_create_i2, 
40000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_add_signed_echo_response, 41000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_mac_and_sign_handler, 42000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, 
&hip_add_unsigned_echo_response, 43000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_send_i2,   
50000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_check_r1,  
20000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_r1, 
30000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_update_retransmissions, 30500);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_build_esp_info, 31000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_build_solution, 32000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_handle_diffie_hellman, 33000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&esp_prot_r1_handle_transforms, 34000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_create_i2, 
40000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_add_signed_echo_response, 41000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_mac_and_sign_handler, 42000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, 
&hip_add_unsigned_echo_response, 43000);
+    hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_send_i2, 
50000);
+
+    hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_check_r2,  
20000);
+    hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_handle_r2, 
30000);
+    hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, 
&hip_update_retransmissions, 30250);
+    //hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, 
&hip_setup_ipsec_sa, 30500);
+
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, 
&hip_check_notify,  20000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, 
&hip_handle_notify, 30000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I2_SENT, 
&hip_check_notify,  20000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I2_SENT, 
&hip_handle_notify, 30000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_R2_SENT, 
&hip_check_notify,  20000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_R2_SENT, 
&hip_handle_notify, 30000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_ESTABLISHED, 
&hip_check_notify, 20000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_ESTABLISHED, 
&hip_handle_notify, 30000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSING, 
&hip_check_notify,  20000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSING, 
&hip_handle_notify, 30000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, 
&hip_check_notify,  20000);
+    hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, 
&hip_handle_notify, 30000);
+
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED,  
&hip_close_check_packet,     20000);
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED,  
&hip_update_retransmissions, 25000);
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED,  
&hip_close_create_response,  30000);
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED,  
&hip_close_send_response,    40000);
+
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING,  
&hip_close_check_packet,     20000);
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING,  
&hip_update_retransmissions, 25000);
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING,  
&hip_close_create_response,  30000);
+    hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING,  
&hip_close_send_response,    40000);
+
+    hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, 
&hip_close_ack_check_packet,  20000);
+    hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, 
&hip_update_retransmissions,  25000);
+    hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, 
&hip_close_ack_handle_packet, 30000);
+
+    hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED,  
&hip_close_ack_check_packet,  20000);
+    hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED,  
&hip_update_retransmissions,  25000);
+    hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED,  
&hip_close_ack_handle_packet, 30000);
+
+    hip_register_handle_function(HIP_LUPDATE, HIP_STATE_ESTABLISHED, 
&esp_prot_handle_light_update, 20000);
+    hip_register_handle_function(HIP_LUPDATE, HIP_STATE_R2_SENT,     
&esp_prot_handle_light_update, 20000);
+
+    return err;
+}
+
 static int init_handle_functions(void)
 {
     int err = 0;
@@ -866,7 +1074,7 @@
  *
  * @param signum signal the signal hipd received from OS
  */
-static void hip_close(int signum)
+static void hipd_close(int signum)
 {
     static int terminate = 0;
 
@@ -928,8 +1136,8 @@
     }
 
     /* Register signal handlers */
-    signal(SIGINT, hip_close);
-    signal(SIGTERM, hip_close);
+    signal(SIGINT, hipd_close);
+    signal(SIGTERM, hipd_close);
     signal(SIGCHLD, sig_chld);
 
     HIP_IFEL(hip_init_cipher() < 0, -1, "Unable to init ciphers.\n");
@@ -1090,6 +1298,66 @@
     return err;
 }
 
+int libhipd_init(void)
+{
+    int                err         = 0;
+    int                keypath_len = 0;
+    char              *key_path    = NULL;
+    struct hip_common *msg         = NULL;
+    struct passwd     *pwd;
+
+    set_libhip_mode();
+    hip_nat_status = 1;
+#ifdef CONFIG_HIP_FIREWALL
+    hipfw_status = 0;
+#endif
+
+    hip_init_hadb();
+    hip_init_hostid_db();
+    hip_netdev_init_addresses();
+    libhip_init_handle_functions();
+    hip_init_socket_wrapper();
+
+    /* Load default key from ~/.hipl/ */
+    HIP_IFE(!(pwd = getpwuid(getuid())), -1);
+
+    /* +2 because we need a slash after pwd and a NULL for termination */
+    keypath_len = strlen(pwd->pw_dir) +
+                  strlen(HIP_USER_DIR) +
+                  strlen(DEFAULT_HOST_RSA_KEY_FILE_NAME) +
+                  strlen(DEFAULT_PUB_HI_FILE_NAME_SUFFIX) + 2;
+    HIP_IFE(!(key_path = malloc(keypath_len)), -1);
+    HIP_IFE(snprintf(key_path, keypath_len, "%s/%s%s%s", pwd->pw_dir,
+                     HIP_USER_DIR,
+                     DEFAULT_HOST_RSA_KEY_FILE_NAME,
+                     DEFAULT_PUB_HI_FILE_NAME_SUFFIX) < 0,
+            -1);
+
+    HIP_DEBUG("Using key: %s\n", key_path);
+    HIP_IFE(!(msg = hip_msg_alloc()), -1);
+    if (hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa",
+                                     key_path, 0, 0, 0)) {
+        free(msg);
+        HIP_IFE(!(msg = hip_msg_alloc()), -1);
+        HIP_IFEL(hip_serialize_host_id_action(msg, ACTION_NEW, 0, 0, "rsa",
+                                              key_path, RSA_KEY_DEFAULT_BITS,
+                                              DSA_KEY_DEFAULT_BITS,
+                                              ECDSA_DEFAULT_CURVE), -1,
+                 "Fail to create local key at %s.", key_path);
+        free(msg);
+        HIP_IFE(!(msg = hip_msg_alloc()), -1);
+        HIP_IFEL(hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa",
+                                              key_path, 0, 0, 0), -1,
+                 "Fail to load local key at %s.", key_path);
+    }
+    HIP_IFE(hip_handle_add_local_hi(msg), -1);
+
+out_err:
+    free(msg);
+    free(key_path);
+    return err;
+}
+
 /**
  * create a socket to handle UDP encapsulation of HIP control
  * packets

=== renamed file 'hipd/init.h' => 'lib/hipdaemon/init.h'
--- hipd/init.h 2011-11-25 17:56:24 +0000
+++ lib/hipdaemon/init.h        2012-02-07 15:20:56 +0000
@@ -60,4 +60,6 @@
                             int is_output);
 void hip_exit(void);
 
+int libhipd_init(void);
+
 #endif /* HIPL_HIPD_INIT_H */

=== renamed file 'hipd/input.c' => 'lib/hipdaemon/input.c'
--- hipd/input.c        2012-01-30 11:29:16 +0000
+++ lib/hipdaemon/input.c       2012-02-07 15:20:56 +0000
@@ -709,6 +709,11 @@
                                &ctx->src_addr);
     }
 
+    if (is_libhip_mode()) {
+        ctx->msg_ports.src_port = ctx->hadb_entry->peer_udp_port;
+        ctx->msg_ports.dst_port = ctx->hadb_entry->local_udp_port;
+    }
+
     hip_relay_add_rvs_to_ha(ctx->input_msg, ctx->hadb_entry);
 
 #ifdef CONFIG_HIP_RVS

=== renamed file 'hipd/input.h' => 'lib/hipdaemon/input.h'
=== renamed file 'hipd/keymat.c' => 'lib/hipdaemon/keymat.c'
=== renamed file 'hipd/keymat.h' => 'lib/hipdaemon/keymat.h'
=== renamed file 'hipd/lsidb.c' => 'lib/hipdaemon/lsidb.c'
=== renamed file 'hipd/lsidb.h' => 'lib/hipdaemon/lsidb.h'
=== renamed file 'hipd/maintenance.c' => 'lib/hipdaemon/maintenance.c'
--- hipd/maintenance.c  2011-12-29 18:52:56 +0000
+++ lib/hipdaemon/maintenance.c 2012-02-07 15:20:56 +0000
@@ -58,6 +58,7 @@
 #include "cookie.h"
 #include "hadb.h"
 #include "hidb.h"
+#include "hip_socket.h"
 #include "hipd.h"
 #include "init.h"
 #include "input.h"
@@ -74,6 +75,9 @@
 int hipfw_sock_lsi_fd = -1;
 int hipfw_status      = -1;
 
+struct sockaddr_in6 hipfw_addr = { 0 };
+int                 hipfw_sock = 0;
+
 static float retrans_counter    = HIP_RETRANSMIT_INIT;
 static float precreate_counter  = HIP_R1_PRECREATE_INIT;
 static int   force_exit_counter = FORCE_EXIT_COUNTER_START;
@@ -387,3 +391,27 @@
     free(msg);
     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
+    int n = 0;
+
+    n = sendto(hipfw_sock,
+               msg,
+               hip_get_msg_total_len(msg),
+               0,
+               (struct sockaddr *) &hipfw_addr,
+               sizeof(hipfw_addr));
+    return n;
+#else
+    HIP_DEBUG("Firewall is disabled.\n");
+    return 0;
+#endif // CONFIG_HIP_FIREWALL
+}

=== renamed file 'hipd/maintenance.h' => 'lib/hipdaemon/maintenance.h'
--- hipd/maintenance.h  2011-11-25 17:56:24 +0000
+++ lib/hipdaemon/maintenance.h 2012-02-07 15:20:56 +0000
@@ -30,9 +30,10 @@
 #include <netinet/in.h>
 #include <sys/time.h>
 
-
+extern int hip_firewall_status;
 extern int hipfw_sock_lsi_fd;
 extern int hipfw_status;
+extern int hipfw_sock;
 
 int hip_register_maint_function(int (*maint_function)(void),
                                 const uint16_t priority);

=== renamed file 'hipd/nat.c' => 'lib/hipdaemon/nat.c'
--- hipd/nat.c  2011-11-07 15:56:02 +0000
+++ lib/hipdaemon/nat.c 2012-02-07 15:20:56 +0000
@@ -64,6 +64,7 @@
 #include "lib/core/state.h"
 #include "hadb.h"
 #include "hipd.h"
+#include "netdev.h"
 #include "output.h"
 #include "user.h"
 #include "nat.h"

=== renamed file 'hipd/nat.h' => 'lib/hipdaemon/nat.h'
=== renamed file 'hipd/netdev.c' => 'lib/hipdaemon/netdev.c'
--- hipd/netdev.c       2011-12-30 23:20:44 +0000
+++ lib/hipdaemon/netdev.c      2012-02-07 15:20:56 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -89,6 +89,34 @@
 /** Maximum lenght of the address family string */
 #define FAM_STR_MAX               32
 
+/** For receiving netlink IPsec events (acquire, expire, etc) */
+struct rtnl_handle hip_nl_ipsec;
+/** For getting/setting routes and adding HITs (it was not possible to use
+ *  nf_ipsec for this purpose). */
+struct rtnl_handle hip_nl_route;
+
+/* We are caching the IP addresses of the host here. The reason is that during
+ * in hip_handle_acquire it is not possible to call getifaddrs (it creates
+ * a new netlink socket and seems like only one can be open per process).
+ * Feel free to experiment by porting the required functionality from
+ * iproute2/ip/ipaddrs.c:ipaddr_list_or_flush(). It would make these global
+ * variable and most of the functions referencing them unnecessary -miika
+ */
+int            address_count;
+HIP_HASHTABLE *addresses;
+
+int hip_broadcast_status = HIP_MSG_BROADCAST_OFF;
+
+int hip_use_userspace_data_packet_mode =  0;
+/** Suppress advertising of none, AF_INET or AF_INET6 address in UPDATEs.
+ *  0 = none = default, AF_INET, AF_INET6 */
+int suppress_af_family =  0;
+/** Specifies the NAT status of the daemon. This value indicates if the current
+ *  machine is behind a NAT. */
+hip_transform_suite hip_nat_status                     =  0;
+int                 address_change_time_counter        = -1;
+int                 hip_wait_addr_changes_to_stabilize =  1;
+
 /**
  * This is the white list. For every interface, which is in our white list,
  * this array has a fixed size, because there seems to be no need at this
@@ -745,12 +773,12 @@
  *       will be used as a last resort.
  * @todo move this function to some other file
  */
-static int netdev_trigger_bex(const hip_hit_t *src_hit_in,
-                              const hip_hit_t *dst_hit_in,
-                              const hip_lsi_t *src_lsi_in,
-                              const hip_lsi_t *dst_lsi_in,
-                              const struct in6_addr *src_addr_in,
-                              const struct in6_addr *dst_addr_in)
+int netdev_trigger_bex(const hip_hit_t *src_hit_in,
+                       const hip_hit_t *dst_hit_in,
+                       const hip_lsi_t *src_lsi_in,
+                       const hip_lsi_t *dst_lsi_in,
+                       const struct in6_addr *src_addr_in,
+                       const struct in6_addr *dst_addr_in)
 {
     int                     err                      = 0, if_index = 0, 
is_ipv4_locator;
     int                     reuse_hadb_local_address = 0, ha_nat_mode = 
hip_nat_status;

=== renamed file 'hipd/netdev.h' => 'lib/hipdaemon/netdev.h'
--- hipd/netdev.h       2011-11-25 17:56:24 +0000
+++ lib/hipdaemon/netdev.h      2012-02-07 15:20:56 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
@@ -36,8 +36,19 @@
 #include <netinet/in.h>
 #include <sys/socket.h>
 
+#include "lib/core/hashtable.h"
+#include "lib/tool/nlink.h"
 #include "lib/core/protodefs.h"
-#include "lib/tool/nlink.h"
+
+extern struct rtnl_handle  hip_nl_route;
+extern struct rtnl_handle  hip_nl_ipsec;
+extern int                 hip_use_userspace_data_packet_mode;
+extern int                 suppress_af_family;
+extern int                 address_count;
+extern HIP_HASHTABLE      *addresses;
+extern hip_transform_suite hip_nat_status;
+extern int                 address_change_time_counter;
+extern int                 hip_wait_addr_changes_to_stabilize;
 
 int hip_devaddr2ifindex(struct in6_addr *addr);
 int hip_netdev_init_addresses(void);
@@ -47,6 +58,13 @@
 int hip_remove_iface_all_local_hits(void);
 int hip_add_iface_local_route(const hip_hit_t *local_hit);
 int hip_select_source_address(struct in6_addr *src, const struct in6_addr 
*dst);
+
+int netdev_trigger_bex(const hip_hit_t *src_hit_in,
+                       const hip_hit_t *dst_hit_in,
+                       const hip_lsi_t *src_lsi_in,
+                       const hip_lsi_t *dst_lsi_in,
+                       const struct in6_addr *src_addr_in,
+                       const struct in6_addr *dst_addr_in);
 int hip_netdev_trigger_bex_msg(const struct hip_common *msg);
 void hip_add_address_to_list(struct sockaddr *addr, int ifindex, int flags);
 

=== renamed file 'hipd/nsupdate.c' => 'lib/hipdaemon/nsupdate.c'
--- hipd/nsupdate.c     2012-01-25 10:44:48 +0000
+++ lib/hipdaemon/nsupdate.c    2012-02-07 15:20:56 +0000
@@ -57,6 +57,7 @@
 #include "config.h"
 #include "hidb.h"
 #include "hipd.h"
+#include "netdev.h"
 #include "nsupdate.h"
 
 // parameters for nsupdate

=== renamed file 'hipd/nsupdate.h' => 'lib/hipdaemon/nsupdate.h'
=== renamed file 'hipd/opp_mode.c' => 'lib/hipdaemon/opp_mode.c'
=== renamed file 'hipd/opp_mode.h' => 'lib/hipdaemon/opp_mode.h'
=== renamed file 'hipd/output.c' => 'lib/hipdaemon/output.c'
--- hipd/output.c       2012-01-16 22:06:09 +0000
+++ lib/hipdaemon/output.c      2012-02-07 15:20:56 +0000
@@ -69,6 +69,19 @@
 #include "registration.h"
 #include "output.h"
 
+int hip_shotgun_status = HIP_MSG_SHOTGUN_OFF;
+
+/* Encrypt host id in I2 */
+int hip_encrypt_i2_hi = 0;
+
+/* used to change the transform order see hipconf usage to see the usage
+ * This is set to AES, 3DES, NULL by default see hipconf transform order for
+ * more information.
+ */
+int hip_transform_order = 123;
+
+/* Tells to the daemon should it build LOCATOR parameters to R1 and I2 */
+int hip_locator_status = HIP_MSG_SET_LOCATOR_OFF;
 
 /* Set to 1 if you want to simulate lost output packet */
 #define HIP_SIMULATE_PACKET_LOSS             1
@@ -836,7 +849,8 @@
     HIP_ASSERT(!hit_is_opportunistic_hit(&ctx->input_msg->hitr));
 
     /* Case: I ----->IPv4---> RVS ---IPv6---> R */
-    if (IN6_IS_ADDR_V4MAPPED(r1_src_addr) !=
+    if (!is_libhip_mode() &&
+        IN6_IS_ADDR_V4MAPPED(r1_src_addr) !=
         IN6_IS_ADDR_V4MAPPED(r1_dst_addr)) {
         HIP_DEBUG_IN6ADDR("r1_src_addr", r1_src_addr);
         HIP_DEBUG_IN6ADDR("r1_dst_addr", r1_dst_addr);
@@ -1203,6 +1217,9 @@
         goto out_err;
     }
 
+    if (is_libhip_mode()) {
+        udp = 1;
+    }
     dst_is_ipv4 = IN6_IS_ADDR_V4MAPPED(peer_addr);
     len         = hip_get_msg_total_len(msg);
 
@@ -1231,13 +1248,16 @@
     if (local_addr) {
         HIP_DEBUG("local address given\n");
         memcpy(&my_addr, local_addr, sizeof(struct in6_addr));
-    } else {
+    } else if (!is_libhip_mode()) {
         HIP_DEBUG("no local address, selecting one\n");
         HIP_IFEL(hip_select_source_address(&my_addr, peer_addr), -1,
                  "Cannot find source address\n");
+    } else {
+        memset(&my_addr, 0, sizeof(my_addr));
     }
 
-    src_is_ipv4 = IN6_IS_ADDR_V4MAPPED(&my_addr);
+    src_is_ipv4 = IN6_IS_ADDR_V4MAPPED(&my_addr) ||
+                  (dst_is_ipv4 && ipv6_addr_any(&my_addr));
 
     if (src_is_ipv4) {
         IPV6_TO_IPV4_MAP(&my_addr, &src4->sin_addr);
@@ -1252,7 +1272,6 @@
     if (dst_is_ipv4) {
         IPV6_TO_IPV4_MAP(peer_addr, &dst4->sin_addr);
         dst4->sin_family = AF_INET;
-
         HIP_DEBUG_INADDR("dst4", &dst4->sin_addr);
     } else {
         memcpy(&dst6->sin6_addr, peer_addr, sizeof(struct in6_addr));
@@ -1291,9 +1310,10 @@
 
     /* Handover may cause e.g. on-link duplicate address detection
      * which may cause bind to fail. */
-
-    HIP_IFEL(bind(hip_raw_sock_output, (struct sockaddr *) &src, sa_size),
-             -1, "Binding to raw sock failed\n");
+    if (!is_libhip_mode()) {
+        HIP_IFEL(bind(hip_raw_sock_output, (struct sockaddr *) &src, sa_size),
+                 -1, "Binding to raw sock failed\n");
+    }
 
 #if (HIP_SIMULATE_PACKET_LOSS_PROBABILITY > 0)
     if (HIP_SIMULATE_PACKET_LOSS && HIP_SIMULATE_PACKET_IS_LOST()) {
@@ -1310,18 +1330,25 @@
     len = hip_get_msg_total_len(msg);
 
     if (udp) {
-        struct udphdr *uh = (struct udphdr *) msg;
-
-        /* Insert 32 bits of zero bytes between UDP and HIP */
-        memmove((char *) msg + HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr), 
msg, len);
-        memset(msg, 0, HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr));
-        len += HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr);
-
-        uh->source = htons(src_port);
-        uh->dest   = htons(dst_port);
-        uh->len    = htons(len);
-        uh->check  = 0;
-        memmoved   = 1;
+        if (!is_libhip_mode()) {
+            /* Insert 32 bits of zero bytes between UDP and HIP */
+            memmove((char *) msg + HIP_UDP_ZERO_BYTES_LEN + sizeof(struct 
udphdr), msg, len);
+            memset(msg, 0, HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr));
+            len += HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr);
+
+            struct udphdr *uh = (struct udphdr *) msg;
+            uh->source = htons(src_port);
+            uh->dest   = htons(dst_port);
+            uh->len    = htons(len);
+            uh->check  = 0;
+        } else {
+            memmove((char *) msg + HIP_UDP_ZERO_BYTES_LEN, msg, len);
+            memset(msg, 0, HIP_UDP_ZERO_BYTES_LEN);
+            len += HIP_UDP_ZERO_BYTES_LEN;
+
+            dst4->sin_port = htons(dst_port);
+        }
+        memmoved = 1;
     }
 
     sent = sendto(hip_raw_sock_output, msg, len, 0,

=== renamed file 'hipd/output.h' => 'lib/hipdaemon/output.h'
--- hipd/output.h       2011-11-25 17:56:24 +0000
+++ lib/hipdaemon/output.h      2012-02-07 15:20:56 +0000
@@ -35,6 +35,17 @@
 extern int hip_raw_sock_v6;
 extern int hip_raw_sock_v4;
 
+extern int hip_raw_sock_output_v6;
+extern int hip_raw_sock_output_v4;
+extern int hip_nat_sock_output_udp;
+extern int hip_nat_sock_output_udp_v6;
+
+extern int is_active_mhaddr;
+extern int is_hard_handover;
+extern int hip_shotgun_status;
+extern int hip_encrypt_i2_hi;
+extern int hip_locator_status;
+extern int hip_transform_order;
 
 int hip_create_r1(struct hip_common *const msg,
                   const struct in6_addr *const src_hit,

=== renamed file 'hipd/pisa.c' => 'lib/hipdaemon/pisa.c'
=== renamed file 'hipd/pisa.h' => 'lib/hipdaemon/pisa.h'
=== renamed file 'hipd/pkt_handling.c' => 'lib/hipdaemon/pkt_handling.c'
=== renamed file 'hipd/pkt_handling.h' => 'lib/hipdaemon/pkt_handling.h'
=== renamed file 'hipd/registration.c' => 'lib/hipdaemon/registration.c'
=== renamed file 'hipd/registration.h' => 'lib/hipdaemon/registration.h'
=== added file 'lib/hipdaemon/socket_wrapper.c'
--- lib/hipdaemon/socket_wrapper.c      1970-01-01 00:00:00 +0000
+++ lib/hipdaemon/socket_wrapper.c      2012-02-07 15:20:56 +0000
@@ -0,0 +1,792 @@
+/*
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * This file contains implementation of libhip API.
+ *
+ */
+
+#define _BSD_SOURCE
+
+#include <string.h>
+#include <unistd.h>
+
+#include "lib/core/builder.h"
+#include "lib/core/conf.h"
+#include "lib/core/crypto.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/linkedlist.h"
+#include "lib/core/message.h"
+#include "lib/core/prefix.h"
+#include "close.h"
+#include "hadb.h"
+#include "hidb.h"
+#include "init.h"
+#include "input.h"
+#include "netdev.h"
+#include "output.h"
+#include "socket_wrapper.h"
+
+struct hip_fd_info {
+    int                    fd;
+    int                    bound_port;
+    int                    family;
+    int                    proto;
+    struct hip_hadb_state *ha;
+};
+
+static struct hip_ll   socket_list;
+static struct in6_addr default_hit;
+
+static uint16_t get_port_from_saddr(const struct sockaddr *addr)
+{
+    const struct sockaddr_in  *addr4;
+    const struct sockaddr_in6 *addr6;
+
+    if (addr->sa_family == AF_INET) {
+        addr4 = (const struct sockaddr_in *) addr;
+        return addr4->sin_port;
+    } else {
+        addr6 = (const struct sockaddr_in6 *) addr;
+        return addr6->sin6_port;
+    }
+}
+
+/**
+ * Build a suitable sockaddr_storage.
+ * If the addr is V4MAPPED, the storage family will be INET4.
+ * Otherwise the sotrage family will be INET6.
+ *
+ * @param addr    a V6 addr or V4MAPPED addr
+ * @param port    port number (in NETWORK order)
+ * @param ss      the sockaddr_storage to be filled.
+ */
+static void build_sockaddr(struct in6_addr *const addr, const uint16_t port,
+                           struct sockaddr_storage *const ss)
+{
+    HIP_ASSERT(addr && ss);
+    memset(ss, 0, sizeof(struct sockaddr_storage));
+
+    if (IN6_IS_ADDR_V4MAPPED(addr)) {
+        struct sockaddr_in *const in = (struct sockaddr_in *) ss;
+        in->sin_family = AF_INET;
+        IPV6_TO_IPV4_MAP(addr, &in->sin_addr);
+        in->sin_port = port;
+    } else {
+        struct sockaddr_in6 *const in6 = (struct sockaddr_in6 *) ss;
+        in6->sin6_family = AF_INET6;
+        ipv6_addr_copy(&in6->sin6_addr, addr);
+        in6->sin6_port = port;
+    }
+}
+
+/**
+ * Create a new hip socket info struct and insert it into global list.
+ *
+ * @param fd          file descriptor of the socket
+ * @param bound_port  the port number which this @fd bound to (in HOST order)
+ * @param family      the address family of this @fd (INET or INET6)
+ * @param proto       the protocol of this @fd (TCP or UDP)
+ * @return            pointer of the new struct, NULL if we fail to create it.
+ */
+static struct hip_fd_info *create_new_fd_info(const int fd,
+                                              const uint16_t bound_port,
+                                              const int family, const int 
proto)
+{
+    int                 err         = 0;
+    struct hip_fd_info *fd_info_new = NULL;
+
+    fd_info_new = malloc(sizeof(struct hip_fd_info));
+    HIP_IFEL(!fd_info_new, -1, "malloc()\n");
+    memset(fd_info_new, 0, sizeof(struct hip_fd_info));
+    HIP_IFEL(hip_ll_add_last(&socket_list, fd_info_new),
+             -1, "Error adding FD info struct to list\n");
+    fd_info_new->fd         = fd;
+    fd_info_new->bound_port = bound_port;
+    fd_info_new->family     = family;
+    fd_info_new->proto      = proto;
+
+out_err:
+    if (err) {
+        free(fd_info_new);
+        fd_info_new = NULL;
+    }
+    return fd_info_new;
+}
+
+/**
+ * Get information on a socket by FD
+ *
+ * @param fd    file descriptor of the socket
+ * @return      a structure containing information on the status of the socket
+ *              or NULL if none is found
+ */
+static struct hip_fd_info *hip_socket_get_info(int fd)
+{
+    const struct hip_ll_node *current = NULL;
+    struct       hip_fd_info *fd_info;
+
+    while ((current = hip_ll_iterate(&socket_list, current))) {
+        fd_info = current->ptr;
+        if (fd_info->fd == fd) {
+            return fd_info;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ * Automatically bind a port for hip_fd_info struct.
+ * If the bound_port of hip_fd_info is not zero, this function does nothing.
+ *
+ * @param info       hip_fd_info struct
+ * @return           0 if it successes, -1 on error
+ */
+static int auto_bind(const struct hip_fd_info *info)
+{
+    struct sockaddr_storage ss = { 0 };
+    struct sockaddr_in     *addr4;
+    struct sockaddr_in6    *addr6;
+
+    if (info->bound_port != 0) {
+        HIP_ERROR("A bound port exists, auto_bind stops\n");
+        return 0;
+    }
+
+    if (info->family == AF_INET) {
+        ss.ss_family    = AF_INET;
+        addr4           = (struct sockaddr_in *) &ss;
+        addr4->sin_port = 0;
+        return hip_bind(info->fd, (struct sockaddr *) addr4, sizeof(ss));
+    } else {
+        ss.ss_family     = AF_INET6;
+        addr6            = (struct sockaddr_in6 *) &ss;
+        addr6->sin6_port = 0;
+        return hip_bind(info->fd, (struct sockaddr *) addr6, sizeof(ss));
+    }
+}
+
+/**
+ * Initialization function for socket wrapper functionality
+ */
+void hip_init_socket_wrapper(void)
+{
+    hip_ll_init(&socket_list);
+    memset(&default_hit, 0, sizeof(default_hit));
+}
+
+/**
+ * Add peer hit-addr mapping to hadb.
+ * @param peer_hit peer's hit
+ * @param peer_addr peer's addr, v4 addr should be mapped.
+ * @return 0 if success, -1 otherwise.
+ */
+int add_peer_info(const hip_hit_t *peer_hit,
+                  const struct in6_addr *peer_addr)
+{
+    return hip_hadb_add_peer_info(peer_hit, peer_addr, NULL, NULL);
+}
+
+static void set_hip_connection_parameters(int sock_fd, int local_port,
+                                          int remote_port)
+{
+    HIP_DEBUG("fd = %d, lport = %d, rport= %d\n", sock_fd, local_port, 
remote_port);
+    hip_nat_sock_output_udp = sock_fd;
+    hip_raw_sock_output_v4  = sock_fd;
+    hip_raw_sock_output_v6  = sock_fd;
+    hip_set_local_nat_udp_port(local_port);
+    hip_set_peer_nat_udp_port(remote_port);
+}
+
+/**
+ * Check whether a received packet is a HIP control packet
+ *
+ * @param buf       buffer containing the received data
+ * @param len       size of @buf
+ * @param fd_info   information of the socket the data was received on
+ * @return
+ */
+static int hip_is_control_msg(char *buf, unsigned int len,
+                              struct hip_fd_info *fd_info)
+{
+    char                    udp_pad[HIP_UDP_ZERO_BYTES_LEN] = { 0 };
+    struct hip_common      *msg;
+    struct sockaddr_storage src = { 0 };
+    struct sockaddr_storage dst = { 0 };
+
+    if (len < sizeof(struct hip_common)) {
+        return 0;
+    }
+
+    if (!memcmp(udp_pad, buf, HIP_UDP_ZERO_BYTES_LEN)) {
+        HIP_DEBUG("Message is padded\n");
+        msg  = (struct hip_common *) (buf + HIP_UDP_ZERO_BYTES_LEN);
+        len -= HIP_UDP_ZERO_BYTES_LEN;
+    } else {
+        msg = (struct hip_common *) buf;
+    }
+
+    src.ss_family = fd_info->family;
+    dst.ss_family = fd_info->family;
+
+    if (fd_info->family == AF_INET) {
+        struct sockaddr_in *src4 = (struct sockaddr_in *) &src;
+        struct sockaddr_in *dst4 = (struct sockaddr_in *) &dst;
+
+        src4->sin_port = fd_info->ha->peer_udp_port;
+        dst4->sin_port = fd_info->ha->local_udp_port;
+
+        IPV6_TO_IPV4_MAP(&fd_info->ha->peer_addr, &src4->sin_addr);
+        IPV6_TO_IPV4_MAP(&fd_info->ha->our_addr, &dst4->sin_addr);
+
+        HIP_DEBUG_INADDR("src", &src4->sin_addr);
+        HIP_DEBUG_INADDR("dst", &dst4->sin_addr);
+    } else if (fd_info->family == AF_INET6) {
+        struct sockaddr_in6 *src6 = (struct sockaddr_in6 *) &src;
+        struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *) &dst;
+
+        src6->sin6_port = fd_info->ha->peer_udp_port;
+        dst6->sin6_port = fd_info->ha->local_udp_port;
+
+        memcpy(&src6->sin6_addr, &fd_info->ha->peer_addr,
+               sizeof(struct in6_addr));
+        memcpy(&dst6->sin6_addr, &fd_info->ha->our_addr,
+               sizeof(struct in6_addr));
+
+        HIP_DEBUG_IN6ADDR("src", &src6->sin6_addr);
+        HIP_DEBUG_IN6ADDR("dst", &dst6->sin6_addr);
+    }
+
+    return !hip_verify_network_header(msg, (struct sockaddr *) &src,
+                                      (struct sockaddr *) &dst, len);
+}
+
+/**
+ * Initiate and perform a base exchange with a peer.
+ *
+ * @param fd                file descriptor
+ * @param dst_hit_sockaddr  hit of the peer to be contacted
+ * @return                  0 on success, -1 otherwise
+ */
+static int hip_do_bex(int fd, const struct sockaddr_in6 *dst_hit_sockaddr)
+{
+    int                       err = 0;
+    struct in6_addr           dst_hit;
+    struct in6_addr           dst_addr;
+    struct hip_packet_context ctx = { 0 };
+    struct hip_fd_info       *fd_info;
+
+    if ((fd_info = hip_socket_get_info(fd)) == NULL) {
+        HIP_ERROR("No socket info found.\n");
+        return -1;
+    }
+
+    hip_get_default_hit(&default_hit);
+
+    memcpy(&dst_hit, &dst_hit_sockaddr->sin6_addr, sizeof(dst_hit));
+    HIP_IFE(hip_map_id_to_addr(&dst_hit, NULL, &dst_addr), -1);
+    HIP_IFEL(ipv6_addr_any(&dst_addr), -1, "Couldn't map HIT to IP\n");
+
+    set_hip_connection_parameters(fd, fd_info->bound_port,
+                                  ntohs(dst_hit_sockaddr->sin6_port));
+    err = netdev_trigger_bex(&default_hit, &dst_hit, NULL, NULL, NULL, 
&dst_addr);
+    HIP_IFEL(err, err, "Couldn't start base exchange.\n");
+
+    ctx.input_msg  = hip_msg_alloc();
+    ctx.output_msg = hip_msg_alloc();
+
+    fd_info->ha = hip_hadb_find_byhits(&default_hit, &dst_hit);
+
+    do {
+        if (fd_info->proto == IPPROTO_TCP) {
+            if (!hip_read_control_msg_tcp(fd, &ctx)) {
+                hip_receive_control_packet(&ctx);
+            }
+        } else if (fd_info->family == AF_INET) {
+            if (!hip_read_control_msg_v4(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN)) {
+                hip_receive_control_packet(&ctx);
+            }
+        } else {
+            if (!hip_read_control_msg_v6(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN)) {
+                hip_receive_control_packet(&ctx);
+            }
+        }
+    } while (fd_info->ha->state != HIP_STATE_ESTABLISHED);
+
+    fd_info->ha->local_udp_port = fd_info->bound_port;
+
+out_err:
+    free(ctx.input_msg);
+    free(ctx.output_msg);
+    return err;
+}
+
+/**
+ * Wait for an I1 packet and perform base exchange.
+ *
+ * @param fd    file descriptor of the socket to receive from
+ * @return      0 on success, -1 otherwise
+ */
+static int hip_await_bex(struct hip_fd_info *fd_info, struct sockaddr 
*peer_hit)
+{
+    int                       err  = 0;
+    int                       fd   = fd_info->fd;
+    struct hip_packet_context ctx  = { 0 };
+    struct sockaddr_in6      *hit6 = (struct sockaddr_in6 *) peer_hit;
+
+    ctx.input_msg  = hip_msg_alloc();
+    ctx.output_msg = hip_msg_alloc();
+
+    set_hip_connection_parameters(fd, fd_info->bound_port,
+                                  ntohs(hit6->sin6_port));
+
+    do {
+        if (fd_info->proto == IPPROTO_TCP) {
+            if (!hip_read_control_msg_tcp(fd, &ctx) &&
+                !hip_receive_control_packet(&ctx)) {
+                fd_info->ha = hip_hadb_find_byhits(&ctx.input_msg->hitr,
+                                                   &ctx.input_msg->hits);
+            }
+        } else if (fd_info->family == AF_INET) {
+            if (!hip_read_control_msg_v4(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN) &&
+                !hip_receive_control_packet(&ctx)) {
+                fd_info->ha = hip_hadb_find_byhits(&ctx.input_msg->hitr,
+                                                   &ctx.input_msg->hits);
+            }
+        } else {
+            if (!hip_read_control_msg_v6(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN) &&
+                !hip_receive_control_packet(&ctx)) {
+                fd_info->ha = hip_hadb_find_byhits(&ctx.input_msg->hitr,
+                                                   &ctx.input_msg->hits);
+            }
+        }
+    } while (!fd_info->ha || fd_info->ha->state != HIP_STATE_ESTABLISHED);
+
+    fd_info->ha->local_udp_port = fd_info->bound_port;
+
+    free(ctx.input_msg);
+    free(ctx.output_msg);
+    return err;
+}
+
+/**
+ * Create a socket and an information entry for it
+ *
+ * @param domain    Communications domain for the socket
+ * @param type      Socket type
+ * @param protocol  Socket protocol
+ * @return          file descriptor of the new socket on success, -1 otherwise
+ */
+int hip_socket(int domain, int type, int protocol)
+{
+    int                 sock;
+    int                 on      = 1, off = 0, err = 0;
+    struct hip_fd_info *fd_info = NULL;
+
+    sock = socket(domain, type, protocol);
+
+    if (domain == AF_INET) {
+        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
+        setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
+        setsockopt(sock, IPPROTO_IP, IP_RECVERR, &off, sizeof(off));
+        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+    } else {
+        setsockopt(sock, IPPROTO_IPV6, IPV6_RECVERR, &off, sizeof(off));
+        setsockopt(sock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on));
+        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+    }
+
+    //TODO support IPV6
+    HIP_IFEL(domain == AF_INET6, -1, "No support for IPv6.\n");
+
+    fd_info = create_new_fd_info(sock, 0, domain, protocol);
+    HIP_IFEL(!fd_info, -1, "Fail to create hip socket info for fd: %d\n", 
sock);
+
+out_err:
+    if (err) {
+        close(sock);
+        return err;
+    }
+
+    return sock;
+}
+
+/**
+ * Close a socket. Sends CLOSE to the associated peer and deletes
+ * the socket information.
+ *
+ * @param fd    file descriptor of the socket to be closed
+ * @return      0 if the socket was successfully closed, -1 otherwise
+ */
+int hip_close(int fd)
+{
+    int                 err     = 0;
+    struct hip_common  *msg     = NULL;
+    struct hip_fd_info *fd_info = NULL;
+
+    fd_info = hip_socket_get_info(fd);
+    if (!fd_info || !fd_info->ha || fd_info->ha->state == HIP_STATE_CLOSED) {
+        HIP_DEBUG("Not sending CLOSE.\n");
+        goto skip_close_msg;
+    }
+
+    if (!(msg = hip_msg_alloc()) ||
+        hip_build_param_contents(msg, &fd_info->ha->hit_peer,
+                                 HIP_PARAM_HIT, sizeof(struct in6_addr)) ||
+        hip_send_close(msg, 1)) {
+        HIP_ERROR("Sending CLOSE failed\n");
+        goto skip_close_msg;
+    }
+
+skip_close_msg:
+    err = close(fd);
+
+    if (fd_info) {
+        hip_ll_del_by_ptr(&socket_list, fd_info, free);
+    }
+    free(msg);
+    return err;
+}
+
+/**
+ * Bind a socket to a local address
+ *
+ * @param fd            file descriptor of the socket
+ * @param address       address to bind to
+ * @param address_len   length of @address
+ * @return              0 on success, -1 otherwise
+ */
+int hip_bind(int fd, const struct sockaddr *address, socklen_t address_len)
+{
+    struct     hip_fd_info     *fd_info;
+    struct     sockaddr_storage laddr     = { 0 };
+    socklen_t                   laddr_len = sizeof(laddr);
+    uint16_t                    request_port;
+
+    if ((fd_info = hip_socket_get_info(fd)) == NULL) {
+        HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd);
+        return -1;
+    }
+
+    request_port = get_port_from_saddr(address);
+    if (bind(fd, address, address_len) < 0) {
+        HIP_PERROR("bind error:");
+        return -1;
+    }
+
+    /* Ask OS to get assigned port number */
+    if (request_port == 0) {
+        if (getsockname(fd, (struct sockaddr *) &laddr, &laddr_len) < 0) {
+            HIP_PERROR("getsockname() error: ");
+            return -1;
+        }
+        request_port = get_port_from_saddr((struct sockaddr *) &laddr);
+    }
+
+    fd_info->bound_port = ntohs(request_port);
+    HIP_DEBUG("bind to port %d\n", fd_info->bound_port);
+
+    return 0;
+}
+
+/**
+ * Send data to the peer associated with a socket. Triggers base exchange
+ * if no host association exists.
+ *
+ * @note Data is currently sent unencrypted.
+ *
+ * @param fd        file descriptor of the socket to send from
+ * @param msg       data to send
+ * @param len       size of @data
+ * @param flags     sendto() flags
+ * @param dst_hit   HIT of the peer to send to
+ * @param dst_len   size of @dst_hit
+ * @return          number of bytes sent on success, -1 otherwise
+ */
+int hip_sendto(int fd, const void *msg, size_t len,
+               int flags, const struct sockaddr *dst_hit,
+               socklen_t dst_len)
+{
+    struct sockaddr_storage dst_addr;
+    uint16_t                dst_port;
+    struct hip_fd_info     *fd_info;
+
+    dst_port = ((const struct sockaddr_in6 *) dst_hit)->sin6_port;
+
+    if (dst_len != sizeof(struct sockaddr_in6)) {
+        HIP_ERROR("Only HITs are supported\n");
+        return -1;
+    }
+
+    if ((fd_info = hip_socket_get_info(fd)) == NULL) {
+        HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd);
+        return -1;
+    }
+
+    /* Bind to a ephemeral port if the src port hasn't been bound yet */
+    if (fd_info->bound_port == 0) {
+        if (auto_bind(fd_info)) {
+            HIP_ERROR("Fail to bind the hip socket.\n");
+            return -1;
+        }
+    }
+
+    /* Start BEX if HA hasn't establised */
+    if (!fd_info->ha) {
+        if (hip_do_bex(fd, (const struct sockaddr_in6 *) dst_hit)) {
+            HIP_ERROR("Base exchange not successful.\n");
+            return -1;
+        }
+    }
+
+    /* Send user data */
+    build_sockaddr(&fd_info->ha->peer_addr, dst_port, &dst_addr);
+    return sendto(fd, msg, len, flags,
+                  (struct sockaddr *) &dst_addr, sizeof(dst_addr));
+}
+
+/**
+ * Receive data from the peer associated with a socket.
+ * Waits for base exchange if no host association exists.
+ *
+ * @note Data is currently sent unencrypted.
+ *
+ * @param fd        file descriptor of the socket to receive from
+ * @param msg       buffer for received data
+ * @param len       size of @buf
+ * @param flags     recvfrom() flags
+ * @param addr      buffer for the associated peer HIT
+ * @param addr_len  size of @dst_hit
+ * @return          number of bytes received on success, -1 otherwise
+ */
+int hip_recvfrom(int fd, void *buf, size_t len, int flags,
+                 struct sockaddr *addr, socklen_t *addr_len)
+{
+    int                       err       = 0;
+    socklen_t                 socklen   = *addr_len;
+    struct sockaddr_in6      *peer_hit  = (struct sockaddr_in6 *) addr;
+    struct in6_addr           peer_addr = { { { 0 } } };
+    struct in6_addr          *peer_addr6;
+    struct in_addr           *peer_addr4;
+    struct hip_fd_info       *fd_info = NULL;
+    struct hip_packet_context ctx     = { 0 };
+    int                       (*read_control_msg)(int, struct 
hip_packet_context *, int) = NULL;
+
+
+    if ((fd_info = hip_socket_get_info(fd)) == NULL) {
+        HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd);
+        return -1;
+    }
+
+    /* Bind to a ephemeral port if the src port hasn't been bound yet */
+    if (fd_info->bound_port == 0) {
+        if (auto_bind(fd_info)) {
+            HIP_ERROR("Fail to bind the hip socket.\n");
+            return -1;
+        }
+    }
+
+    /* Handle BEX if HA hasn't establised */
+    if (!fd_info->ha) {
+        if (hip_await_bex(fd_info, addr)) {
+            HIP_ERROR("Base exchange not successful.\n");
+            return -1;
+        }
+    }
+
+    ctx.input_msg    = hip_msg_alloc();
+    ctx.output_msg   = hip_msg_alloc();
+    read_control_msg = fd_info->family == AF_INET ? hip_read_control_msg_v4
+                       : hip_read_control_msg_v6;
+
+    /* Loop until we get a non-control packet or a CLOSE packet */
+    while (fd_info->ha->state == HIP_STATE_ESTABLISHED) {
+        err = recvfrom(fd, buf, len, flags | MSG_PEEK, addr, &socklen);
+        HIP_DEBUG("Peek packet len: %d\n", err);
+        HIP_DEBUG("peer sockaddr: AF = %d, socklen = %d\n", addr->sa_family, 
socklen);
+        if (err < 0) {
+            perror("recvfrom");
+        }
+
+        /* Drop the packet if it doesn't come from the address associated
+         * with the correct peer. */
+        if (fd_info->proto == IPPROTO_UDP) {
+            if (addr->sa_family == AF_INET) {
+                peer_addr4 = &((struct sockaddr_in *) addr)->sin_addr;
+                IPV4_TO_IPV6_MAP(peer_addr4, &peer_addr);
+                peer_addr6 = &peer_addr;
+            } else {
+                peer_addr6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
+            }
+            if (ipv6_addr_cmp(&fd_info->ha->peer_addr, peer_addr6)) {
+                HIP_DEBUG("Packet not from associated address. Dropping.\n");
+                HIP_DEBUG_IN6ADDR("expected", &fd_info->ha->peer_addr);
+                HIP_DEBUG_IN6ADDR("got", peer_addr6);
+                err = recvfrom(fd, buf, 1, flags, addr, &socklen);
+                HIP_IFEL(err < 0, err, "recvfrom()\n");
+                continue;
+            }
+        }
+
+        /* Receive message */
+        if (hip_is_control_msg(buf, err, fd_info)) {
+            HIP_DEBUG("receive a hip control message.\n");
+            if (fd_info->proto == IPPROTO_TCP) {
+                if (!hip_read_control_msg_tcp(fd, &ctx)) {
+                    hip_receive_control_packet(&ctx);
+                }
+            } else if (!read_control_msg(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN)) {
+                hip_receive_control_packet(&ctx);
+            } else {
+                HIP_ERROR("Error reading control packet\n");
+            }
+            err = 0;
+        } else {
+            HIP_DEBUG("receive a non hip control message.\n");
+            err = recvfrom(fd, buf, len, flags, addr, &socklen);
+            HIP_IFEL(err < 0, err, "recvfrom() error\n");
+            break;
+        }
+    }
+
+    if (peer_hit) {
+        memset(peer_hit, 0, *addr_len);
+        memcpy(&peer_hit->sin6_addr, &fd_info->ha->hit_peer,
+               sizeof(struct in6_addr));
+        peer_hit->sin6_port = fd_info->ha->peer_udp_port;
+        *addr_len           = sizeof(struct sockaddr_in6);
+    }
+
+out_err:
+    free(ctx.input_msg);
+    free(ctx.output_msg);
+    return err;
+}
+
+/**
+ * Initiate a connection on a socket and perform base exchange as Initiator
+ *
+ * @param fd         file descriptor of the socket
+ * @param addr       peer HIT to connect to
+ * @param addr_len   size of @addr
+ * @return           0 on success, -1 otherwise
+ */
+int hip_connect(int fd, const struct sockaddr *addr, socklen_t addr_len)
+{
+    uint16_t                dst_port;
+    struct hip_fd_info     *fd_info = NULL;
+    struct in6_addr         dst_hit;
+    struct in6_addr         dst_addr = { { { 0 } } };
+    struct sockaddr_storage ss;
+
+    if ((fd_info = hip_socket_get_info(fd)) == NULL) {
+        HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd);
+        return -1;
+    }
+
+    if (addr_len != sizeof(struct sockaddr_in6)) {
+        HIP_ERROR("Invalid argument, Only HITs supported\n");
+        return -1;
+    }
+
+    dst_port = ((const struct sockaddr_in6 *) addr)->sin6_port;
+    ipv6_addr_copy(&dst_hit, &((const struct sockaddr_in6 *) addr)->sin6_addr);
+    if (ipv6_addr_any(&dst_hit)) {
+        HIP_ERROR("Invalid argument: The ANY dest address is not 
supported.\n");
+        return -1;
+    }
+
+    if (hip_map_id_to_addr(&dst_hit, NULL, &dst_addr) < 0) {
+        return -1;
+    }
+    if (ipv6_addr_any(&dst_addr)) {
+        HIP_ERROR("Couldn't map HIT to IP\n");
+        return -1;
+    }
+
+    HIP_DEBUG_IN6ADDR("Dest locator is: ", &dst_addr);
+    HIP_DEBUG("Dest locator is V4MAPPED: %d\n", 
IN6_IS_ADDR_V4MAPPED(&dst_addr));
+    build_sockaddr(&dst_addr, dst_port, &ss);
+
+    if (connect(fd, (struct sockaddr *) &ss, sizeof(ss)) < 0) {
+        HIP_PERROR("connect():");
+        return -1;
+    }
+
+    /* Bind to a ephemeral port if the src port hasn't been bound yet */
+    if (fd_info->bound_port == 0) {
+        if (auto_bind(fd_info)) {
+            HIP_ERROR("Fail to bind the hip socket.\n");
+            return -1;
+        }
+    }
+
+    if (hip_do_bex(fd, (const struct sockaddr_in6 *) addr) < 0) {
+        HIP_ERROR("Base exchange not successful.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * Wait for an incoming connection on a socket and perform base exchange as
+ * Responder
+ *
+ * @param fd         file descriptor of the socket
+ * @param addr       buffer to store peer address
+ * @param addr_len   size of @addr
+ * @return           file descriptor of accepted socket, -1 on error
+ */
+int hip_accept(int fd, struct sockaddr *addr, socklen_t *addr_len)
+{
+    int                 new_fd;
+    struct hip_fd_info *fd_info     = NULL;
+    struct hip_fd_info *fd_info_new = NULL;
+
+    if ((fd_info = hip_socket_get_info(fd)) == NULL) {
+        HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd);
+        return -1;
+    }
+
+    new_fd = accept(fd, addr, addr_len);
+    if (new_fd < 0) {
+        HIP_PERROR("accept(): ");
+        return -1;
+    }
+    HIP_DEBUG("accept new peer, family=%d (INET=%d, INET6=%d)\n", 
addr->sa_family, AF_INET, AF_INET6);
+
+    fd_info_new = create_new_fd_info(new_fd, fd_info->bound_port,
+                                     fd_info->family, fd_info->proto);
+
+    if (hip_await_bex(fd_info_new, addr) < 0) {
+        HIP_ERROR("Base exchange not successful.\n");
+        return -1;
+    }
+
+    return new_fd;
+}

=== added file 'lib/hipdaemon/socket_wrapper.h'
--- lib/hipdaemon/socket_wrapper.h      1970-01-01 00:00:00 +0000
+++ lib/hipdaemon/socket_wrapper.h      2012-02-07 15:20:56 +0000
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef HIPL_LIB_HIPDAEMON_SOCKET_WRAPPER_H
+#define HIPL_LIB_HIPDAEMON_SOCKET_WRAPPER_H
+
+#include <sys/socket.h>
+
+#include "lib/core/protodefs.h"
+
+void hip_init_socket_wrapper(void);
+int add_peer_info(const hip_hit_t *peer_hit,
+                  const struct in6_addr *peer_addr);
+
+int hip_socket(int domain, int type, int protocol);
+int hip_close(int fd);
+int hip_bind(int fd, const struct sockaddr *address, socklen_t address_len);
+int hip_sendto(int fd, const void *msg, size_t len,
+               int flags, const struct sockaddr *dst_hit,
+               socklen_t dst_len);
+int hip_recvfrom(int fd, void *buf, size_t len, int flags,
+                 struct sockaddr *addr, socklen_t *addr_len);
+int hip_connect(int fd, const struct sockaddr *addr, socklen_t addr_len);
+int hip_accept(int fd, struct sockaddr *addr, socklen_t *addr_len);
+
+#endif /* HIPL_LIB_HIPDAEMON_SOCKET_WRAPPER_H */

=== renamed file 'hipd/user.c' => 'lib/hipdaemon/user.c'
--- hipd/user.c 2012-01-14 14:20:17 +0000
+++ lib/hipdaemon/user.c        2012-02-07 15:20:56 +0000
@@ -72,6 +72,7 @@
 #include "esp_prot_hipd_msg.h"
 #include "hadb.h"
 #include "hidb.h"
+#include "hip_socket.h"
 #include "hipd.h"
 #include "hiprelay.h"
 #include "hit_to_ip.h"

=== renamed file 'hipd/user.h' => 'lib/hipdaemon/user.h'
=== renamed file 'hipd/user_ipsec_hipd_msg.c' => 
'lib/hipdaemon/user_ipsec_hipd_msg.c'
--- hipd/user_ipsec_hipd_msg.c  2011-08-15 14:11:56 +0000
+++ lib/hipdaemon/user_ipsec_hipd_msg.c 2012-02-07 15:20:56 +0000
@@ -46,6 +46,11 @@
 #include "user_ipsec_sadb_api.h"
 #include "user_ipsec_hipd_msg.h"
 
+/*Define hip_use_userspace_ipsec variable to indicate whether use
+ * userspace ipsec or not. If it is 1, hip uses the user space ipsec.
+ * It will not use if hip_use_userspace_ipsec = 0. Added By Tao Wan
+ */
+int hip_use_userspace_ipsec = 0;
 
 /**
  * handles a userspace ipsec activation message sent by the fw

=== renamed file 'hipd/user_ipsec_hipd_msg.h' => 
'lib/hipdaemon/user_ipsec_hipd_msg.h'
=== renamed file 'hipd/user_ipsec_sadb_api.c' => 
'lib/hipdaemon/user_ipsec_sadb_api.c'
=== renamed file 'hipd/user_ipsec_sadb_api.h' => 
'lib/hipdaemon/user_ipsec_sadb_api.h'
=== modified file 'modules/heartbeat/hipd/heartbeat.c'
--- modules/heartbeat/hipd/heartbeat.c  2011-10-25 21:14:16 +0000
+++ modules/heartbeat/hipd/heartbeat.c  2012-02-07 15:20:56 +0000
@@ -66,14 +66,14 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include "hipd/hadb.h"
-#include "hipd/init.h"
-#include "hipd/hip_socket.h"
-#include "hipd/maintenance.h"
-#include "hipd/nat.h"
-#include "hipd/output.h"
-#include "hipd/pkt_handling.h"
-#include "hipd/user.h"
+#include "lib/hipdaemon/hadb.h"
+#include "lib/hipdaemon/init.h"
+#include "lib/hipdaemon/hip_socket.h"
+#include "lib/hipdaemon/maintenance.h"
+#include "lib/hipdaemon/nat.h"
+#include "lib/hipdaemon/output.h"
+#include "lib/hipdaemon/pkt_handling.h"
+#include "lib/hipdaemon/user.h"
 #include "lib/core/common.h"
 #include "lib/core/debug.h"
 #include "lib/core/icomm.h"

=== modified file 'modules/heartbeat_update/hipd/hb_update.c'
--- modules/heartbeat_update/hipd/hb_update.c   2011-10-25 21:14:16 +0000
+++ modules/heartbeat_update/hipd/hb_update.c   2012-02-07 15:20:56 +0000
@@ -40,8 +40,8 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#include "hipd/hadb.h"
-#include "hipd/maintenance.h"
+#include "lib/hipdaemon/hadb.h"
+#include "lib/hipdaemon/maintenance.h"
 #include "lib/core/builder.h"
 #include "lib/core/common.h"
 #include "lib/core/debug.h"

=== modified file 'modules/midauth/hipd/midauth.c'
--- modules/midauth/hipd/midauth.c      2012-01-16 22:06:09 +0000
+++ modules/midauth/hipd/midauth.c      2012-02-07 15:20:56 +0000
@@ -33,8 +33,8 @@
 #include <stdint.h>
 #include <string.h>
 
-#include "hipd/hidb.h"
-#include "hipd/pkt_handling.h"
+#include "lib/hipdaemon/hidb.h"
+#include "lib/hipdaemon/pkt_handling.h"
 #include "lib/core/builder.h"
 #include "lib/core/common.h"
 #include "lib/core/ife.h"

=== modified file 'modules/update/hipd/update.c'
--- modules/update/hipd/update.c        2012-01-17 08:34:18 +0000
+++ modules/update/hipd/update.c        2012-02-07 15:20:56 +0000
@@ -37,17 +37,17 @@
 #include <string.h>
 
 #include "config.h"
-#include "hipd/cookie.h"
-#include "hipd/hadb.h"
-#include "hipd/hidb.h"
-#include "hipd/hipd.h"
-#include "hipd/input.h"
-#include "hipd/maintenance.h"
-#include "hipd/netdev.h"
-#include "hipd/nsupdate.h"
-#include "hipd/output.h"
-#include "hipd/pkt_handling.h"
-#include "hipd/user.h"
+#include "lib/hipdaemon/cookie.h"
+#include "lib/hipdaemon/hadb.h"
+#include "lib/hipdaemon/hidb.h"
+#include "lib/hipdaemon/hipd.h"
+#include "lib/hipdaemon/input.h"
+#include "lib/hipdaemon/maintenance.h"
+#include "lib/hipdaemon/netdev.h"
+#include "lib/hipdaemon/nsupdate.h"
+#include "lib/hipdaemon/output.h"
+#include "lib/hipdaemon/pkt_handling.h"
+#include "lib/hipdaemon/user.h"
 #include "lib/core/builder.h"
 #include "lib/core/debug.h"
 #include "lib/core/hip_udp.h"

=== modified file 'modules/update/hipd/update_builder.c'
--- modules/update/hipd/update_builder.c        2012-01-14 14:20:17 +0000
+++ modules/update/hipd/update_builder.c        2012-02-07 15:20:56 +0000
@@ -34,8 +34,8 @@
 #include <string.h>
 #include <errno.h>
 
-#include "hipd/hadb.h"
-#include "hipd/hipd.h"
+#include "lib/hipdaemon/hadb.h"
+#include "lib/hipdaemon/netdev.h"
 #include "lib/core/builder.h"
 #include "lib/core/ife.h"
 #include "lib/core/list.h"

=== modified file 'modules/update/hipd/update_locator.c'
--- modules/update/hipd/update_locator.c        2011-12-12 14:18:05 +0000
+++ modules/update/hipd/update_locator.c        2012-02-07 15:20:56 +0000
@@ -34,7 +34,7 @@
 #include <string.h>
 #include <openssl/lhash.h>
 
-#include "hipd/maintenance.h"
+#include "lib/hipdaemon/maintenance.h"
 #include "lib/core/builder.h"
 #include "lib/core/debug.h"
 #include "lib/core/ife.h"

=== added file 'test/check_hipnetcat.c'
--- test/check_hipnetcat.c      1970-01-01 00:00:00 +0000
+++ test/check_hipnetcat.c      2012-02-07 15:20:56 +0000
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * @brief Tests of libhip (see doc/HACKING on unit tests).
+ */
+
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/wait.h>
+#include <sys/select.h>
+#include <unistd.h>
+#include <check.h>
+
+#include "lib/hipdaemon/hidb.h"
+#include "lib/hipdaemon/init.h"
+
+#define TEST_HIPNC_TIMEOUT 10
+
+static Suite *hipnc_suite(void);
+static void hipnc_test_start(char *serv_argv[], char *client_argv[]);
+
+START_TEST(test_hipnc_lo_tcp)
+{
+    char           *serv_argv[16];
+    char           *client_argv[16];
+    struct in6_addr local_hit = { { { 0 } } };
+    char            hit_buf[128];
+    int             idx = 0;
+
+    /* init */
+    fail_if(libhipd_init(), "fail to init libhip");
+    fail_if(hip_get_default_hit(&local_hit),
+            "fail to load local hit for hipnetcat startup");
+    fail_if(inet_ntop(AF_INET6, &local_hit, hit_buf, 128) == NULL,
+            "fail to parse hit to string.");
+
+    serv_argv[idx++] = strdup("hipnetcat");
+    serv_argv[idx++] = strdup("-l");
+    serv_argv[idx++] = strdup("-p");
+    serv_argv[idx++] = strdup("22300");
+    serv_argv[idx++] = strdup("-s");
+    serv_argv[idx++] = strdup("127.0.0.1");
+    serv_argv[idx++] = strdup("-t");
+    serv_argv[idx++] = (char *) 0;
+
+    idx                = 0;
+    client_argv[idx++] = strdup("hipnetcat");
+    client_argv[idx++] = strdup("-p");
+    client_argv[idx++] = strdup("22345");
+    client_argv[idx++] = strdup("-s");
+    client_argv[idx++] = strdup("127.0.0.1");
+    client_argv[idx++] = strdup("-d");
+    client_argv[idx++] = strdup("22300");
+    client_argv[idx++] = strdup("-t");
+    client_argv[idx++] = strdup("127.0.0.1");
+    client_argv[idx++] = hit_buf;
+    client_argv[idx++] = (char *) 0;
+
+    hipnc_test_start(serv_argv, client_argv);
+}
+END_TEST
+
+START_TEST(test_hipnc_lo_udp)
+{
+    char           *serv_argv[16];
+    char           *client_argv[16];
+    struct in6_addr local_hit = { { { 0 } } };
+    char            hit_buf[128];
+    int             idx = 0;
+
+    /* init */
+    fail_if(libhipd_init(), "fail to init libhip");
+    fail_if(hip_get_default_hit(&local_hit),
+            "fail to load local hit for hipnetcat startup");
+    fail_if(inet_ntop(AF_INET6, &local_hit, hit_buf, 128) == NULL,
+            "fail to parse hit to string.");
+
+    serv_argv[idx++] = strdup("hipnetcat");
+    serv_argv[idx++] = strdup("-l");
+    serv_argv[idx++] = strdup("-p");
+    serv_argv[idx++] = strdup("22300");
+    serv_argv[idx++] = strdup("-s");
+    serv_argv[idx++] = strdup("127.0.0.1");
+    serv_argv[idx++] = (char *) 0;
+
+    idx                = 0;
+    client_argv[idx++] = strdup("hipnetcat");
+    client_argv[idx++] = strdup("-p");
+    client_argv[idx++] = strdup("22345");
+    client_argv[idx++] = strdup("-s");
+    client_argv[idx++] = strdup("127.0.0.1");
+    client_argv[idx++] = strdup("-d");
+    client_argv[idx++] = strdup("22300");
+    client_argv[idx++] = strdup("127.0.0.1");
+    client_argv[idx++] = hit_buf;
+    client_argv[idx++] = (char *) 0;
+
+    hipnc_test_start(serv_argv, client_argv);
+}
+END_TEST
+
+static void hipnc_test_start(char *serv_argv[], char *client_argv[])
+{
+    pid_t          serv_pid, client_pid, pid;
+    int            status, i, j, round;
+    struct timeval tv;
+    int            remain_cld = 2;
+
+    /* start hipnetcat server */
+    if ((pid = fork()) > 0) {
+        serv_pid = pid;
+        printf("server pid: %d\n", serv_pid);
+    }
+
+    if (pid == 0) {
+        if (execv("test/hipnetcat", serv_argv)) {
+            perror("execv");
+            return;
+        }
+    }
+
+    /* start hipnetcat client */
+    if ((pid = fork()) > 0) {
+        client_pid = pid;
+        printf("client_pid: %d\n", client_pid);
+    }
+
+    if (pid == 0) {
+        sleep(1);
+        if (execv("test/hipnetcat", client_argv)) {
+            perror("execv");
+            return;
+        }
+    }
+
+    /* check server & client status */
+    for (i = 0; i < TEST_HIPNC_TIMEOUT; i++) {
+        tv.tv_sec  = 1;
+        tv.tv_usec = 0;
+        select(0, NULL, NULL, NULL, &tv);
+        round = remain_cld;
+        for (j = 0; j < round; j++) {
+            pid = waitpid(-1, &status, WNOHANG);
+            fail_if(pid > 0 && status != 0,
+                    "hipnetcat failed");
+            if (pid > 0 && status == 0) {
+                remain_cld--;
+                if (remain_cld == 0) {
+                    break;
+                }
+            }
+        }
+    }
+
+    fail_if(remain_cld > 0, "hipnetcat test timeout!");
+}
+
+static Suite *hipnc_suite()
+{
+    Suite *s = suite_create("hipnc");
+
+    TCase *tc_hipnc_lo = tcase_create("hipnc_lo");
+    tcase_add_test(tc_hipnc_lo, test_hipnc_lo_udp);
+    tcase_add_test(tc_hipnc_lo, test_hipnc_lo_tcp);
+    tcase_set_timeout(tc_hipnc_lo, 20);
+    suite_add_tcase(s, tc_hipnc_lo);
+
+    return s;
+}
+
+int main(void)
+{
+    int number_failed;
+
+    Suite   *s  = hipnc_suite();
+    SRunner *sr = srunner_create(s);
+    srunner_run_all(sr, CK_NORMAL);
+
+    number_failed = srunner_ntests_failed(sr);
+    srunner_free(sr);
+
+    return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}

=== modified file 'test/hipd/lsidb.c'
--- test/hipd/lsidb.c   2012-01-18 21:09:47 +0000
+++ test/hipd/lsidb.c   2012-02-07 15:20:56 +0000
@@ -26,7 +26,7 @@
 #include <check.h>
 #include <stdlib.h>
 
-#include "hipd/lsidb.c"
+#include "lib/hipdaemon/lsidb.c"
 #include "test_suites.h"
 
 START_TEST(test_lsidb_allocate_lsi_valid)

=== added file 'test/hipnetcat.c'
--- test/hipnetcat.c    1970-01-01 00:00:00 +0000
+++ test/hipnetcat.c    2012-02-07 15:20:56 +0000
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file
+ * The hipnetcat sample program using libhip.
+ *
+ */
+
+#define _BSD_SOURCE
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "lib/core/debug.h"
+#include "lib/core/hip_udp.h"
+#include "lib/core/ife.h"
+#include "lib/core/linkedlist.h"
+#include "lib/core/prefix.h"
+#include "lib/hipdaemon/init.h"
+#include "lib/hipdaemon/socket_wrapper.h"
+
+#define HIPNC_SERVER_MODE 0x0001
+#define HIPNC_UDP_MODE    0x0002
+#define HIPNC_IP6         0x0004
+
+static int                     dst_port   = HIP_NAT_UDP_PORT;
+static unsigned int            hipnc_flag = HIPNC_UDP_MODE & 
~HIPNC_SERVER_MODE & ~HIPNC_IP6;
+static struct sockaddr_storage local_ss   = { 0 };
+static struct hip_ll           hit_list     = HIP_LL_INIT;
+static struct hip_ll           locator_list = HIP_LL_INIT;
+
+
+static int create_hip_socket(unsigned int flag)
+{
+    return hip_socket((flag & HIPNC_IP6) ? AF_INET6 : AF_INET,
+                      (flag & HIPNC_UDP_MODE) ? SOCK_DGRAM : SOCK_STREAM,
+                      (flag & HIPNC_UDP_MODE) ? IPPROTO_UDP : IPPROTO_TCP);
+}
+
+static int hipnc_run_client(const unsigned int flag, struct sockaddr 
*local_addr,
+                            socklen_t addr_len,
+                            struct sockaddr_in6 *peer_hit_saddr)
+{
+    int  fd, err = 0, len = 0;
+    char buf[256] = { 0 };
+
+    fd = create_hip_socket(flag);
+    HIP_IFEL(fd < 0, -1, "Fail to create hip socket: %s\n", strerror(errno));
+
+    HIP_IFEL(hip_bind(fd, local_addr, addr_len), -1, "HIP bind error\n");
+
+    if (!(flag & HIPNC_UDP_MODE)) {
+        HIP_IFEL(hip_connect(fd, (struct sockaddr *) peer_hit_saddr,
+                             sizeof(struct sockaddr_in6)),
+                 -1, "connect()\n");
+    }
+
+    sprintf(buf, "Hello, sailor!");
+    len = hip_sendto(fd, buf, sizeof(buf), 0,
+                     (struct sockaddr *) peer_hit_saddr,
+                     sizeof(struct sockaddr_in6));
+
+    HIP_INFO("Sent %d bytes\n", len);
+    if (len < 0) {
+        err = -1;
+    }
+
+out_err:
+    if (fd > 0) {
+        hip_close(fd);
+    }
+
+    return err;
+}
+
+static int hipnc_run_server(const unsigned int flag, struct sockaddr 
*local_addr,
+                            socklen_t addr_len)
+{
+    int                 fd;
+    int                 err            = 0, len = 0;
+    int                 new_fd         = 0;
+    struct sockaddr_in6 peer_hit_saddr = { 0 };
+    socklen_t           socklen        = sizeof(peer_hit_saddr);
+    char                buf[256]       = { 0 };
+
+    fd = create_hip_socket(flag);
+    HIP_IFEL(fd < 0, -1, "Fail to create hip socket\n", strerror(errno));
+
+    HIP_IFEL(hip_bind(fd, local_addr, addr_len), -1, "HIP bind error\n");
+
+    if (!(flag & HIPNC_UDP_MODE)) {
+        HIP_IFEL(listen(fd, 0), -1, "listen()\n");
+        new_fd = hip_accept(fd, (struct sockaddr *) &peer_hit_saddr, &socklen);
+        HIP_IFEL(new_fd < 0, -1, "accept()\n");
+    } else {
+        new_fd = fd;
+    }
+
+    while ((len = hip_recvfrom(new_fd, buf, sizeof(buf), 0,
+                               (struct sockaddr *) &peer_hit_saddr,
+                               &socklen)) > 0) {
+        HIP_INFO("Received %d bytes\n", len);
+        printf("%s\n", buf);
+        HIP_INFO_IN6ADDR("Peer HIT", &peer_hit_saddr.sin6_addr);
+    }
+
+    if (len < 0) {
+        perror("hip_recvfrom");
+        err = len;
+    }
+
+out_err:
+    if (new_fd > 0) {
+        close(new_fd);
+    }
+    if (fd > 0) {
+        hip_close(fd);
+    }
+
+    return err;
+}
+
+static void usage(void)
+{
+    printf("HIP netcat program.\n"
+           "Usage: hipnetcat [-hlt] [-p source_port] [-s source_ip_address]\n"
+           "                 [-d dest_port] [peer_identifier[s]]\n\n"
+           "   -h: help\n"
+           "   -l: Listening mode, hip netcat acts as the server side.\n"
+           "   -t: Using TCP as transportation protocol, otherwise UDP will be 
used.\n");
+}
+
+static int parse_source_to_ss(const char *ip, int port, struct 
sockaddr_storage *ss)
+{
+    struct sockaddr_in  *sa4;
+    struct sockaddr_in6 *sa6;
+    int                  err = 0;
+
+    sa4 = (struct sockaddr_in *) ss;
+    sa6 = (struct sockaddr_in6 *) ss;
+
+    ss->ss_family = AF_INET;
+    sa4->sin_port = htons(port);
+    hipnc_flag   &= ~HIPNC_IP6;
+    err           = inet_pton(AF_INET, ip, &sa4->sin_addr);
+
+    if (err <= 0) {
+        memset(ss, 0, sizeof(*ss));
+        ss->ss_family  = AF_INET6;
+        sa6->sin6_port = htons(port);
+        hipnc_flag    |= HIPNC_IP6;
+        err            = inet_pton(AF_INET6, ip, &sa6->sin6_addr);
+    }
+
+    return (err <= 0) ? -1 : 0;
+}
+
+static int parse_arguments(int argc, char *argv[])
+{
+    int              err      = 0;
+    char             opt      = 0, *arg = NULL;
+    const char      *src_ip   = "0.0.0.0";
+    int              src_port = HIP_NAT_UDP_PORT;
+    struct in_addr   inaddr4;
+    struct in6_addr  inaddr6;
+    struct in6_addr *paddr6 = NULL;
+    char             addr_buf[256];
+
+    /* Parsing input arguments */
+    while ((opt = getopt(argc, argv, "hltp:d:s:")) != -1) {
+        switch (opt) {
+        case 'l':
+            hipnc_flag |= HIPNC_SERVER_MODE;
+            break;
+        case 'p':
+            src_port = atoi(optarg);
+            break;
+        case 'd':
+            dst_port = atoi(optarg);
+            break;
+        case 's':
+            src_ip = optarg;
+            break;
+        case 't':
+            hipnc_flag &= ~HIPNC_UDP_MODE;
+            break;
+        case 'u':
+            hipnc_flag |= HIPNC_UDP_MODE;
+            break;
+        case 'h':
+            usage();
+            exit(EXIT_SUCCESS);
+        default:
+            HIP_ERROR("Invalid option.\n");
+            return -1;
+        }
+    }
+
+    if (parse_source_to_ss(src_ip, src_port, &local_ss) < 0) {
+        HIP_ERROR("Failed to parse source ip address.\n");
+        return -1;
+    }
+
+    if (!(hipnc_flag & HIPNC_SERVER_MODE) && optind == argc) {
+        HIP_ERROR("No identifier has been provided.\n");
+        return -1;
+    }
+
+    /* parse identifiers */
+    while (optind < argc) {
+        arg = argv[optind++];
+        if (inet_pton(AF_INET, arg, (void *) &inaddr4)) {
+            /* if it is a V4 addr, map it to V6 and add it to locator_list */
+            HIP_DEBUG("%s is parsed to v4", arg);
+            sprintf(addr_buf, "::FFFF:");
+            strcat(addr_buf, arg);
+            inet_pton(AF_INET6, addr_buf, (void *) &inaddr6);
+            HIP_DEBUG(". Map to v6: %s\n", addr_buf);
+            paddr6 = (struct in6_addr *) malloc(sizeof(struct in6_addr));
+            HIP_IFEL(!paddr6, -1, "malloc() failed\n");
+            memcpy(paddr6, &inaddr6, sizeof(struct in6_addr));
+            hip_ll_add_last(&locator_list, (void *) paddr6);
+        } else if (inet_pton(AF_INET6, arg, (void *) &inaddr6)) {
+            /* if it is a V6 addr, add it to locator_list or hit_list */
+            HIP_DEBUG("%s is parsed to v6, is HIT: %d\n", arg,
+                      ipv6_addr_is_hit(&inaddr6));
+            paddr6 = (struct in6_addr *) malloc(sizeof(struct in6_addr));
+            HIP_IFEL(!paddr6, -1, "malloc() failed\n");
+            memcpy(paddr6, &inaddr6, sizeof(struct in6_addr));
+            if (ipv6_addr_is_hit(&inaddr6)) {
+                hip_ll_add_last(&hit_list, (void *) paddr6);
+            } else {
+                hip_ll_add_last(&locator_list, (void *) paddr6);
+            }
+        } else {
+            //Parse hostname
+            struct addrinfo     *res;
+            struct addrinfo      addr_hint = { 0 };
+            struct sockaddr_in  *sa4;
+            struct sockaddr_in6 *sa6;
+
+            addr_hint.ai_family = AF_UNSPEC;
+
+            HIP_DEBUG("Parse identifier: %s\n", arg);
+            err = getaddrinfo(arg, NULL, &addr_hint, &res);
+            HIP_IFEL(err, -1,
+                     "failed to parse: %s, %s\n", arg, gai_strerror(err));
+            for (; res != NULL; res = res->ai_next) {
+                paddr6 = (struct in6_addr *) malloc(sizeof(struct in6_addr));
+                HIP_IFEL(!paddr6, -1, "malloc() failed\n");
+                if (res->ai_family == AF_INET) {
+                    sa4 = (struct sockaddr_in *) res->ai_addr;
+                    IPV4_TO_IPV6_MAP(&sa4->sin_addr, paddr6);
+                    hip_ll_add_last(&locator_list, (void *) paddr6);
+                } else if (res->ai_family == AF_INET6) {
+                    sa6 = (struct sockaddr_in6 *) res->ai_addr;
+                    memcpy(paddr6, &sa6->sin6_addr, sizeof(struct in6_addr));
+                    if (ipv6_addr_is_hit(paddr6)) {
+                        hip_ll_add_last(&hit_list, (void *) paddr6);
+                    } else {
+                        hip_ll_add_last(&locator_list, (void *) paddr6);
+                    }
+                }
+            }
+            freeaddrinfo(res);
+        }
+    }
+
+    if (!(hipnc_flag & HIPNC_SERVER_MODE) && locator_list.element_count == 0) {
+        HIP_ERROR("No locator is provided.\n");
+        return -1;
+    }
+
+out_err:
+    if (err) {
+        free(paddr6);
+    }
+    return err;
+}
+
+int main(int argc, char *argv[])
+{
+    int                 err            = 0;
+    struct sockaddr_in6 peer_hit_saddr = { 0 };
+
+    /* Parsing input arguments */
+    if (parse_arguments(argc, argv)) {
+        usage();
+        exit(EXIT_FAILURE);
+    }
+
+    /* libhip init */
+    if (libhipd_init() < 0) {
+        HIP_ERROR("libhipd init failed.\n");
+        return -1;
+    }
+
+    /* add peer hit-addr mapping */
+    if (hit_list.element_count != 0) {
+        const struct hip_ll_node *hit_i     = NULL;
+        const struct hip_ll_node *locator_i = NULL;
+        struct in6_addr          *p_hit;
+        struct in6_addr          *p_locator;
+        while ((hit_i = hip_ll_iterate(&hit_list, hit_i))) {
+            p_hit = (struct in6_addr *) hit_i->ptr;
+            while ((locator_i = hip_ll_iterate(&locator_list, locator_i))) {
+                p_locator = (struct in6_addr *) locator_i->ptr;
+                HIP_DEBUG_HIT("HIPNC input hit:", p_hit);
+                add_peer_info(p_hit, p_locator);
+            }
+        }
+    }
+
+    HIP_DEBUG("hipnc_flag = %08x\n", hipnc_flag);
+
+    if (hipnc_flag & HIPNC_SERVER_MODE) {
+        return hipnc_run_server(hipnc_flag, (struct sockaddr *) &local_ss,
+                                sizeof(local_ss));
+    } else if (hit_list.element_count != 0) {
+        const struct hip_ll_node *hit_i = NULL;
+        while ((hit_i = hip_ll_iterate(&hit_list, hit_i))) {
+            memcpy(&peer_hit_saddr.sin6_addr, hit_i->ptr, sizeof(struct 
in6_addr));
+            peer_hit_saddr.sin6_port = htons(dst_port);
+            HIP_DEBUG_HIT("Connect to hit", &peer_hit_saddr.sin6_addr);
+            HIP_DEBUG("Connect to port: %d\n", dst_port);
+
+            err = hipnc_run_client(hipnc_flag, (struct sockaddr *) &local_ss,
+                                   sizeof(local_ss), &peer_hit_saddr);
+
+            /* if no errors, finish execution, otherwise we try another hit */
+            if (err == 0) {
+                return 0;
+            }
+        }
+        return err;
+    } else {
+        //TODO opportunistic mode
+        HIP_ERROR("opportunistic mode not supported. Please provide a HIT\n");
+        return 0;
+    }
+}

Other related posts: