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

  • From: Xin <eric.nevup@xxxxxxxxx>
  • To: mp+105783@xxxxxxxxxxxxxxxxxx
  • Date: Tue, 15 May 2012 09:26:17 -0000

Xin has proposed merging lp:~hipl-core/hipl/libhip into lp:hipl.

Requested reviews:
  HIPL core team (hipl-core)

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

May 15, 2012

This version of libhipl fixes issues in Diego's review. Since we agreed to
change the directory layout, the "lib/hipl/" folder has been also changed to
"libhipl/". Therefore I propose a new merge request to make it clear.

=========================================================================

Apr 17, 2012

The merge proposal this time has several big changes, in order to facilitate
further development & merge and reflects suggestions from previous reviews.
The changes are:

1. Divide the 'socket_wrapper.c/h' to 3 parts: 'lhipl.c/h', 'lhipl_sock.c/h'
and 'lhipl_operations.c/h'.
   * 'lhipl.c/h' contains public APIs of libhipl, and it validates the
     parameters input by user. 'lhipl.c/h' relies on the support of the other
     two parts. For libhipl users, lhipl.h is the only header file they need.
   * 'lhipl_sock.c/h' contains functions to maintain libhipl sockets.
   * 'lhipl_operations.c/h' contains functions to operate libhipl sockets.

2. Add single-process version test cases, NO multi-process and NO time waiting
   anymore.

3. The merge size is reduced. Since we get the single-process test cases, we
   decide to postpone the hipnetcat and its test cases to another merge 
proposal.
   I also improve the code to reduce the code size.

4. The libhipl now can work with 'select()'.

PS: There is one review from Diego for last proposal I didn't address, I have
    fixed them in this proposal.

=============================================

Mar 15, 2012 Fixed issues based on Christof and Stefan's review.

Feb 20, 2012 Code revisd based on Diego's second review and Christof's review
New APIs also have been changed to start with 'hipl_' prefix

Feb 10, 2012 code revised based on Diego's review

=============================================

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/105783
Your team HIPL core team is requested to review the proposed merge of 
lp:~hipl-core/hipl/libhip into lp:hipl.
=== modified file 'Makefile.am'
--- Makefile.am 2012-05-12 06:54:33 +0000
+++ Makefile.am 2012-05-15 09:25:24 +0000
@@ -23,7 +23,7 @@
 
 ACLOCAL_AMFLAGS  = -I m4
 
-HIPL_HEADER_LOCATIONS = hipd/*.h hipfw/*.h libcore/*.h libcore/*/*.h 
modules/*/*/*.h test/*.h test/*/*.h test/*/*/*.h
+HIPL_HEADER_LOCATIONS = hipd/*.h hipfw/*.h libcore/*.h libcore/*/*.h 
libhipl/*.h modules/*/*/*.h test/*.h test/*/*.h test/*/*/*.h
 HIPL_HEADER_LIST = $(wildcard $(addprefix $(srcdir)/,$(HIPL_HEADER_LOCATIONS)))
 
 # For "make dist"
@@ -58,7 +58,8 @@
 
 
 ### libraries ###
-lib_LTLIBRARIES = libcore/libcore.la
+lib_LTLIBRARIES = libcore/libcore.la                                    \
+                  libhipl/libhipl.la
 
 
 ### tests ###
@@ -66,10 +67,14 @@
 TESTS           = test/check_hipd                                       \
                   test/check_hipfw                                      \
                   test/check_libcore                                    \
+                  test/check_libhipl                                    \
+                  test/check_libcore                                    \
                   $(tools_hipdnsproxy_PYTHON)
+
 check_PROGRAMS  = test/check_hipd                                       \
                   test/check_hipfw                                      \
-                  test/check_libcore
+                  test/check_libcore                                    \
+                  test/check_libhipl
 endif
 
 
@@ -86,47 +91,7 @@
 
 tools_hipconf_SOURCES  = tools/hipconf.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/cert/hipd/cert.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/main.c
+hipd_hipd_SOURCES = hipd/main.c
 
 dist_sysconf_DATA = hipd/hipd.conf                                      \
                     hipd/hosts                                          \
@@ -203,6 +168,47 @@
 libcore_libcore_la_SOURCES += libcore/performance.c
 endif
 
+libhipl_libhipl_la_SOURCES = libhipl/accessor.c                           \
+                             libhipl/cert.c                               \
+                             libhipl/close.c                              \
+                             libhipl/configfilereader.c                   \
+                             libhipl/cookie.c                             \
+                             libhipl/dh.c                                 \
+                             libhipl/esp_prot_anchordb.c                  \
+                             libhipl/esp_prot_hipd_msg.c                  \
+                             libhipl/esp_prot_light_update.c              \
+                             libhipl/hadb.c                               \
+                             libhipl/hidb.c                               \
+                             libhipl/hip_socket.c                         \
+                             libhipl/hipd.c                               \
+                             libhipl/hiprelay.c                           \
+                             libhipl/hit_to_ip.c                          \
+                             libhipl/init.c                               \
+                             libhipl/input.c                              \
+                             libhipl/keymat.c                             \
+                             libhipl/lhipl.c                              \
+                             libhipl/lhipl_sock.c                         \
+                             libhipl/lhipl_operations.c                   \
+                             libhipl/lsidb.c                              \
+                             libhipl/maintenance.c                        \
+                             libhipl/nat.c                                \
+                             libhipl/netdev.c                             \
+                             libhipl/nsupdate.c                           \
+                             libhipl/opp_mode.c                           \
+                             libhipl/output.c                             \
+                             libhipl/pkt_handling.c                       \
+                             libhipl/registration.c                       \
+                             libhipl/user.c                               \
+                             libhipl/user_ipsec_hipd_msg.c                \
+                             libhipl/user_ipsec_sadb_api.c                \
+                             modules/cert/hipd/cert.c                     \
+                             modules/heartbeat/hipd/heartbeat.c           \
+                             modules/heartbeat_update/hipd/hb_update.c    \
+                             modules/midauth/hipd/midauth.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
 
 test_check_hipd_SOURCES = test/check_hipd.c                             \
                           test/hipd/lsidb.c                             \
@@ -231,14 +237,18 @@
                              test/libcore/gpl/pk.c                      \
                              test/libcore/modules/midauth_builder.c
 
+test_check_libhipl_SOURCES = test/check_libhipl.c
+
 
 ### static library dependencies ###
 
-hipd_hipd_LDADD                          = libcore/libcore.la
+hipd_hipd_LDADD                          = libhipl/libhipl.la
 hipfw_hipfw_LDADD                        = libcore/libcore.la
-test_check_hipd_LDADD                    = libcore/libcore.la
+libhipl_libhipl_la_LIBADD                = libcore/libcore.la
+test_check_hipd_LDADD                    = libhipl/libhipl.la
 test_check_hipfw_LDADD                   = libcore/libcore.la
 test_check_libcore_LDADD                 = libcore/libcore.la
+test_check_libhipl_LDADD                 = libhipl/libhipl.la
 test_certteststub_LDADD                  = libcore/libcore.la
 test_performance_auth_performance_LDADD  = libcore/libcore.la
 test_performance_dh_performance_LDADD    = libcore/libcore.la

=== modified file 'doc/HOWTO.xml.in'
--- doc/HOWTO.xml.in    2012-02-28 18:38:18 +0000
+++ doc/HOWTO.xml.in    2012-05-15 09:25:24 +0000
@@ -2659,6 +2659,112 @@
 
   </section>
 
+  <section id="ch_libhipl_usage">
+    <title>The Libhipl Extension</title>
+
+    <para>
+      Libhipl provides HIP functionality as a library for upper layer
+      applications without requiring the HIPL daemon.
+      Instead, HIP control messages are transmitted on top of TCP/UDP.
+      From the applications' point of view, there is an API similar to the
+      normal socket API. This section describes the libhipl API.
+    </para>
+
+    <para>
+      The libhipl API is described in <emphasis>"lhipl.h"</emphasis>. Detailed
+      information about each function is available there.
+    </para>
+
+    <formalpara>
+      <title>Libhipl initialization</title>
+      <para>
+      Libhipl requires initialization before calling any other related
+      functions. The function: <emphasis>hipl_lib_init_all()</emphasis>
+      serves this purpose and different debug levels can be set as its
+      parameters to track problems inside the library.
+      </para>
+    </formalpara>
+
+    <formalpara>
+      <title>Name-based API</title>
+      <para>
+      Compared to standard socket API, one apparent difference in Libhipl is
+      that a peer is specified by giving a peer name and a port number instead
+      of a sockaddr data structure. The peer name is a string representation of
+      the peer. Currently, libhipl only supports a HIT string as peer name.
+      </para>
+    </formalpara>
+
+    <formalpara>
+      <title>Libhipl socket creation</title>
+      <para>
+      The function hipl_socket() creates a new libhipl socket. An ID is
+      assigned to each created libhipl socket and returned by this function,
+      then the caller can pass this ID to other libhipl functions to operate on
+      this libhipl socket. NOTE: there is NO relation between libhipl socket
+      IDs and normal socket file descriptors, and the result of using
+      this ID as file descriptor is undefined.
+      </para>
+    </formalpara>
+
+    <formalpara><title>Setup TCP connection</title><para>
+      When using libhipl in TCP mode, TCP connection setup is the first task.
+      Similar to the normal socket syntax, libhipl provides:
+      <emphasis>hipl_connect()</emphasis>, <emphasis>hipl_listen()</emphasis>
+      and <emphasis>hipl_accept()</emphasis> for this goal. Those functions
+      process the 3-way handshake and establish a TCP connection.
+    </para></formalpara>
+
+    <formalpara>
+      <title>libhipl Base Exchange (BEX) and user data transmission</title>
+      <para>
+      Data transmission is handled by <emphasis>hipl_sendto()</emphasis> and
+      <emphasis>hipl_recvfrom()</emphasis>.
+      In libhipl, The first sending data call triggers BEX and the first
+      receiving call waits for an incoming BEX message. Once BEX succeeds,
+      the pending user data is transmitted to the peer side. This BEX process
+      is handled by libhipl automatically by default. Meanwhile, there is also
+      an advanced way to handle BEX step by step, which will be explained
+      bellow.
+      </para>
+    </formalpara>
+
+    <formalpara>
+      <title>libhipl assistant API</title>
+      <para>
+        <itemizedlist>
+          <listitem>
+            <para>
+              <emphasis>hipl_add_peer_info()</emphasis> adds the peer's HIT and
+              IP address mappings to the database of libhipl. The library can
+              use this information to look up a peer's locator when a peer name
+              is given.
+            </para>
+          </listitem>
+
+          <listitem>
+            <para>
+              <emphasis>hipl_lib_set_bex_feedback()</emphasis>: This function
+              turns the step-by-step process of BEX on/off. By default, BEX
+              feedback is off. When it is on, sending/receiving functions only
+              process one BEX messages at a time, and give different return
+              values to notify the progress of BEX.
+            </para>
+          </listitem>
+        </itemizedlist>
+      </para>
+    </formalpara>
+
+    <formalpara>
+      <title>Libhipl sample program</title>
+      <para>
+        For a libhipl usage example, refer to the
+        <emphasis>check_libhipl</emphasis> program in the
+        <emphasis>test</emphasis> directory.
+      </para>
+    </formalpara>
+
+  </section> <!-- ch_libhipl_usage -->
 </chapter> <!-- ch_exp_extensions -->
 
 </book>

=== modified file 'hipd/main.c'
--- hipd/main.c 2012-05-12 06:54:33 +0000
+++ hipd/main.c 2012-05-15 09:25:24 +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
@@ -33,9 +33,9 @@
 #include <sys/types.h>
 
 
-#include "hipd/hipd.h"
-#include "init.h"
 #include "libcore/debug.h"
+#include "libhipl/hipd.h"
+#include "libhipl/init.h"
 
 
 /**

=== modified file 'hipfw/hipfw.c'
--- hipfw/hipfw.c       2012-05-12 06:54:33 +0000
+++ hipfw/hipfw.c       2012-05-15 09:25:24 +0000
@@ -75,7 +75,7 @@
 #include "libcore/performance.h"
 #include "libcore/prefix.h"
 #include "libcore/util.h"
-#include "hipd/hipd.h"
+#include "libhipl/hipd.h"
 #include "config.h"
 #include "cache.h"
 #include "cert.h"

=== modified file 'libcore/hostid.c'
--- libcore/hostid.c    2012-05-12 06:54:33 +0000
+++ libcore/hostid.c    2012-05-15 09:25:24 +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
@@ -29,6 +29,7 @@
  */
 
 #include <errno.h>
+#include <libgen.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -678,6 +679,7 @@
     int                      err                = 0, dsa_key_rr_len = 0, 
rsa_key_rr_len = 0;
     int                      dsa_pub_key_rr_len = 0, rsa_pub_key_rr_len = 0;
     hip_hdr                  numeric_action     = 0;
+    char                    *hi_file_dup        = NULL;
     char                     hostname[HIP_HOST_ID_HOSTNAME_LEN_MAX];
     const char              *rsa_filenamebase     = 
DEFAULT_HOST_RSA_KEY_FILE_BASE DEFAULT_ANON_HI_FILE_NAME_SUFFIX;
     const char              *dsa_filenamebase     = 
DEFAULT_HOST_DSA_KEY_FILE_BASE DEFAULT_ANON_HI_FILE_NAME_SUFFIX;
@@ -743,11 +745,16 @@
                 goto out_err;
             }
         } else if (!use_default) {
+            hi_file_dup = strdup(hi_file);
+            if ((err = check_and_create_dir(dirname(hi_file_dup), 
HIP_DIR_MODE))) {
+                HIP_ERROR("Could not create directory 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 +763,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 +772,7 @@
                 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;
                 }
@@ -1093,6 +1100,7 @@
         change_key_file_perms(rsa_filenamebase_pub);
     }
 
+    free(hi_file_dup);
     free(dsa_host_id);
     free(dsa_pub_host_id);
     free(rsa_host_id);

=== added directory 'libhipl'
=== renamed file 'hipd/accessor.c' => 'libhipl/accessor.c'
=== renamed file 'hipd/accessor.h' => 'libhipl/accessor.h'
--- hipd/accessor.h     2012-05-12 06:54:33 +0000
+++ libhipl/accessor.h  2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_ACCESSOR_H
-#define HIPL_HIPD_ACCESSOR_H
+#ifndef HIPL_LIBHIPL_ACCESSOR_H
+#define HIPL_LIBHIPL_ACCESSOR_H
 
 #include "libcore/protodefs.h"
 
@@ -47,4 +47,4 @@
 int hipd_get_flag(unsigned int);
 void hipd_set_flag(unsigned int);
 
-#endif /* HIPL_HIPD_ACCESSOR_H */
+#endif /* HIPL_LIBHIPL_ACCESSOR_H */

=== renamed file 'hipd/cert.c' => 'libhipl/cert.c'
=== renamed file 'hipd/cert.h' => 'libhipl/cert.h'
--- hipd/cert.h 2012-05-12 06:54:33 +0000
+++ libhipl/cert.h      2012-05-15 09:25:24 +0000
@@ -29,8 +29,8 @@
  * Certificate signing and verification functions.
  */
 
-#ifndef HIPL_HIPD_CERT_H
-#define HIPL_HIPD_CERT_H
+#ifndef HIPL_LIBHIPL_CERT_H
+#define HIPL_LIBHIPL_CERT_H
 
 #include <openssl/rsa.h>
 
@@ -45,4 +45,4 @@
 int hip_cert_x509v3_handle_request_to_sign(struct hip_common *);
 int hip_cert_x509v3_handle_request_to_verify(struct hip_common *);
 
-#endif /* HIPL_HIPD_CERT_H */
+#endif /* HIPL_LIBHIPL_CERT_H */

=== renamed file 'hipd/close.c' => 'libhipl/close.c'
=== renamed file 'hipd/close.h' => 'libhipl/close.h'
--- hipd/close.h        2012-05-12 06:54:33 +0000
+++ libhipl/close.h     2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_CLOSE_H
-#define HIPL_HIPD_CLOSE_H
+#ifndef HIPL_LIBHIPL_CLOSE_H
+#define HIPL_LIBHIPL_CLOSE_H
 
 #include "libcore/protodefs.h"
 #include "libcore/state.h"
@@ -48,4 +48,4 @@
                                 struct hip_packet_context *ctx);
 int hip_purge_closing_ha(struct hip_hadb_state *ha, void *opaque);
 
-#endif /* HIPL_HIPD_CLOSE_H */
+#endif /* HIPL_LIBHIPL_CLOSE_H */

=== renamed file 'hipd/configfilereader.c' => 'libhipl/configfilereader.c'
=== renamed file 'hipd/configfilereader.h' => 'libhipl/configfilereader.h'
--- hipd/configfilereader.h     2012-01-06 14:38:54 +0000
+++ libhipl/configfilereader.h  2012-05-15 09:25:24 +0000
@@ -22,8 +22,8 @@
  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE O
  */
 
-#ifndef HIPL_HIPD_CONFIGFILEREADER_H
-#define HIPL_HIPD_CONFIGFILEREADER_H
+#ifndef HIPL_LIBHIPL_CONFIGFILEREADER_H
+#define HIPL_LIBHIPL_CONFIGFILEREADER_H
 
 #include <stdio.h>
 
@@ -52,4 +52,4 @@
                                               struct hip_configfile_value 
*current);
 void print_node(struct hip_configfile_value *node);
 
-#endif /* HIPL_HIPD_CONFIGFILEREADER_H */
+#endif /* HIPL_LIBHIPL_CONFIGFILEREADER_H */

=== renamed file 'hipd/cookie.c' => 'libhipl/cookie.c'
=== renamed file 'hipd/cookie.h' => 'libhipl/cookie.h'
--- hipd/cookie.h       2012-05-12 06:54:33 +0000
+++ libhipl/cookie.h    2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_COOKIE_H
-#define HIPL_HIPD_COOKIE_H
+#ifndef HIPL_LIBHIPL_COOKIE_H
+#define HIPL_LIBHIPL_COOKIE_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -58,4 +58,4 @@
 int hip_get_puzzle_difficulty_msg(struct hip_common *msg);
 int hip_set_puzzle_difficulty_msg(struct hip_common *msg);
 
-#endif /* HIPL_HIPD_COOKIE_H */
+#endif /* HIPL_LIBHIPL_COOKIE_H */

=== renamed file 'hipd/dh.c' => 'libhipl/dh.c'
=== renamed file 'hipd/dh.h' => 'libhipl/dh.h'
--- hipd/dh.h   2011-11-25 17:56:24 +0000
+++ libhipl/dh.h        2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_DH_H
-#define HIPL_HIPD_DH_H
+#ifndef HIPL_LIBHIPL_DH_H
+#define HIPL_LIBHIPL_DH_H
 
 #include <stdint.h>
 
@@ -37,4 +37,4 @@
                                 int bufsize);
 int hip_init_cipher(void);
 
-#endif /* HIPL_HIPD_DH_H */
+#endif /* HIPL_LIBHIPL_DH_H */

=== renamed file 'hipd/esp_prot_anchordb.c' => 'libhipl/esp_prot_anchordb.c'
=== renamed file 'hipd/esp_prot_anchordb.h' => 'libhipl/esp_prot_anchordb.h'
--- hipd/esp_prot_anchordb.h    2012-05-12 06:54:33 +0000
+++ libhipl/esp_prot_anchordb.h 2012-05-15 09:25:24 +0000
@@ -33,8 +33,8 @@
  * @brief Stores anchor elements to be used for the esp protection
  */
 
-#ifndef HIPL_HIPD_ESP_PROT_ANCHORDB_H
-#define HIPL_HIPD_ESP_PROT_ANCHORDB_H
+#ifndef HIPL_LIBHIPL_ESP_PROT_ANCHORDB_H
+#define HIPL_LIBHIPL_ESP_PROT_ANCHORDB_H
 
 #include <stdint.h>
 
@@ -47,4 +47,4 @@
 int anchor_db_get_anchor_length(const uint8_t transform);
 int anchor_db_get_hash_item_length(const uint8_t transform);
 
-#endif /* HIPL_HIPD_ESP_PROT_ANCHORDB_H */
+#endif /* HIPL_LIBHIPL_ESP_PROT_ANCHORDB_H */

=== renamed file 'hipd/esp_prot_hipd_msg.c' => 'libhipl/esp_prot_hipd_msg.c'
=== renamed file 'hipd/esp_prot_hipd_msg.h' => 'libhipl/esp_prot_hipd_msg.h'
--- hipd/esp_prot_hipd_msg.h    2012-05-12 06:54:33 +0000
+++ libhipl/esp_prot_hipd_msg.h 2012-05-15 09:25:24 +0000
@@ -31,8 +31,8 @@
  * @brief Messaging with hipfw and other HIP instances
  */
 
-#ifndef HIPL_HIPD_ESP_PROT_HIPD_MSG_H
-#define HIPL_HIPD_ESP_PROT_HIPD_MSG_H
+#ifndef HIPL_LIBHIPL_ESP_PROT_HIPD_MSG_H
+#define HIPL_LIBHIPL_ESP_PROT_HIPD_MSG_H
 
 #include <stdint.h>
 
@@ -72,4 +72,4 @@
                                   struct hip_hadb_state *entry,
                                   uint32_t *spi);
 
-#endif /* HIPL_HIPD_ESP_PROT_HIPD_MSG_H */
+#endif /* HIPL_LIBHIPL_ESP_PROT_HIPD_MSG_H */

=== renamed file 'hipd/esp_prot_light_update.c' => 
'libhipl/esp_prot_light_update.c'
=== renamed file 'hipd/esp_prot_light_update.h' => 
'libhipl/esp_prot_light_update.h'
--- hipd/esp_prot_light_update.h        2012-05-12 06:54:33 +0000
+++ libhipl/esp_prot_light_update.h     2012-05-15 09:25:24 +0000
@@ -31,8 +31,8 @@
  * @brief Messaging required for HHL-based anchor element updates
  */
 
-#ifndef HIPL_HIPD_ESP_PROT_LIGHT_UPDATE_H
-#define HIPL_HIPD_ESP_PROT_LIGHT_UPDATE_H
+#ifndef HIPL_LIBHIPL_ESP_PROT_LIGHT_UPDATE_H
+#define HIPL_LIBHIPL_ESP_PROT_LIGHT_UPDATE_H
 
 #include "libcore/modularization.h"
 #include "libcore/protodefs.h"
@@ -48,4 +48,4 @@
                                  const enum hip_state ha_state,
                                  struct hip_packet_context *ctx);
 
-#endif /* HIPL_HIPD_ESP_PROT_LIGHT_UPDATE_H */
+#endif /* HIPL_LIBHIPL_ESP_PROT_LIGHT_UPDATE_H */

=== renamed file 'hipd/hadb.c' => 'libhipl/hadb.c'
--- hipd/hadb.c 2012-05-12 06:54:33 +0000
+++ libhipl/hadb.c      2012-05-15 09:25:24 +0000
@@ -610,9 +610,15 @@
                HIP_HOST_ID_HOSTNAME_LEN_MAX - 1);
     }
 
-    if (hip_select_source_address(&peer_map.our_addr, &peer_map.peer_addr)) {
+    /* hip_select_source_address() is incompatible with libhipl, therefore we 
skip
+     * this function and set the source address in peer_map to the ANY source
+     * address.*/
+    if (!hipl_is_libhip_mode()
+        && hip_select_source_address(&peer_map.our_addr, &peer_map.peer_addr)) 
{
         HIP_ERROR("Cannot find source address\n");
         return -1;
+    } else if (hipl_is_libhip_mode()) {
+        memset(&peer_map.our_addr, 0, sizeof(peer_map.our_addr));
     }
 
     if (hip_for_each_hi(hadb_add_peer_info_wrapper, &peer_map)) {
@@ -1453,6 +1459,10 @@
  */
 void hip_delete_security_associations_and_sp(struct hip_hadb_state *const ha)
 {
+    if (hipl_is_libhip_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 +1532,11 @@
                         ha),
              -1, "Error while changing outbound security association\n");
 
+    if (hipl_is_libhip_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' => 'libhipl/hadb.h'
--- hipd/hadb.h 2012-05-12 06:54:33 +0000
+++ libhipl/hadb.h      2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_HADB_H
-#define HIPL_HIPD_HADB_H
+#ifndef HIPL_LIBHIPL_HADB_H
+#define HIPL_LIBHIPL_HADB_H
 
 #include <stdint.h>
 
@@ -125,4 +125,4 @@
                                             const struct in6_addr *const 
src_addr,
                                             const struct in6_addr *const 
dst_addr);
 
-#endif /* HIPL_HIPD_HADB_H */
+#endif /* HIPL_LIBHIPL_HADB_H */

=== renamed file 'hipd/hidb.c' => 'libhipl/hidb.c'
--- hipd/hidb.c 2012-05-12 06:54:33 +0000
+++ libhipl/hidb.c      2012-05-15 09:25:24 +0000
@@ -596,13 +596,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 (!hipl_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' => 'libhipl/hidb.h'
--- hipd/hidb.h 2012-05-12 06:54:33 +0000
+++ libhipl/hidb.h      2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_HIDB_H
-#define HIPL_HIPD_HIDB_H
+#ifndef HIPL_LIBHIPL_HIDB_H
+#define HIPL_LIBHIPL_HIDB_H
 
 /**
  * @file
@@ -75,4 +75,4 @@
 int hip_get_default_hit_msg(struct hip_common *msg);
 int hip_get_default_lsi(struct in_addr *lsi);
 
-#endif /* HIPL_HIPD_HIDB_H */
+#endif /* HIPL_LIBHIPL_HIDB_H */

=== renamed file 'hipd/hip_socket.c' => 'libhipl/hip_socket.c'
=== renamed file 'hipd/hip_socket.h' => 'libhipl/hip_socket.h'
--- hipd/hip_socket.h   2012-05-12 06:54:33 +0000
+++ libhipl/hip_socket.h        2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_HIP_SOCKET_H
-#define HIPL_HIPD_HIP_SOCKET_H
+#ifndef HIPL_LIBHIPL_HIP_SOCKET_H
+#define HIPL_LIBHIPL_HIP_SOCKET_H
 
 #include <stdint.h>
 #include <sys/select.h>
@@ -50,4 +50,4 @@
 
 void hip_run_socket_handles(fd_set *read_fdset, struct hip_packet_context 
*ctx);
 
-#endif /* HIPL_HIPD_HIP_SOCKET_H */
+#endif /* HIPL_LIBHIPL_HIP_SOCKET_H */

=== renamed file 'hipd/hipd.c' => 'libhipl/hipd.c'
=== renamed file 'hipd/hipd.h' => 'libhipl/hipd.h'
--- hipd/hipd.h 2012-05-12 06:54:33 +0000
+++ libhipl/hipd.h      2012-05-15 09:25:24 +0000
@@ -23,10 +23,11 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_HIPD_H
-#define HIPL_HIPD_HIPD_H
+#ifndef HIPL_LIBHIPL_HIPD_H
+#define HIPL_LIBHIPL_HIPD_H
 
 #include <netdb.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <netinet/in.h>
 #include <sys/types.h>
@@ -80,4 +81,8 @@
 int hipd_parse_cmdline_opts(int argc, char *argv[], uint64_t * flags);
 int hipd_main(uint64_t flags);
 
-#endif /* HIPL_HIPD_HIPD_H */
+/* libhip_mode accessor */
+bool hipl_is_libhip_mode(void);
+void hipl_set_libhip_mode(void);
+
+#endif /* HIPL_LIBHIPL_HIPD_H */

=== renamed file 'hipd/hiprelay.c' => 'libhipl/hiprelay.c'
=== renamed file 'hipd/hiprelay.h' => 'libhipl/hiprelay.h'
--- hipd/hiprelay.h     2012-05-12 06:54:33 +0000
+++ libhipl/hiprelay.h  2012-05-15 09:25:24 +0000
@@ -30,8 +30,8 @@
  *          draft-ietf-hip-nat-traversal-03</a>
  */
 
-#ifndef HIPL_HIPD_HIPRELAY_H
-#define HIPL_HIPD_HIPRELAY_H
+#ifndef HIPL_LIBHIPL_HIPRELAY_H
+#define HIPL_LIBHIPL_HIPRELAY_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -133,4 +133,4 @@
                       struct hip_relrec *rec,
                       const uint8_t type_hdr);
 
-#endif /* HIPL_HIPD_HIPRELAY_H */
+#endif /* HIPL_LIBHIPL_HIPRELAY_H */

=== renamed file 'hipd/hit_to_ip.c' => 'libhipl/hit_to_ip.c'
=== renamed file 'hipd/hit_to_ip.h' => 'libhipl/hit_to_ip.h'
--- hipd/hit_to_ip.h    2012-05-12 06:54:33 +0000
+++ libhipl/hit_to_ip.h 2012-05-15 09:25:24 +0000
@@ -29,8 +29,8 @@
  * @brief usually invoked by hip_map_id_to_addr
  */
 
-#ifndef HIPL_HIPD_HIT_TO_IP_H
-#define HIPL_HIPD_HIT_TO_IP_H
+#ifndef HIPL_LIBHIPL_HIT_TO_IP_H
+#define HIPL_LIBHIPL_HIT_TO_IP_H
 
 #include <netinet/in.h>
 
@@ -42,4 +42,4 @@
 int hip_get_hit_to_ip_status(void);
 void hip_hit_to_ip_set(const char *zone);
 
-#endif /* HIPL_HIPD_HIT_TO_IP_H */
+#endif /* HIPL_LIBHIPL_HIT_TO_IP_H */

=== renamed file 'hipd/init.c' => 'libhipl/init.c'
--- hipd/init.c 2012-05-12 06:54:33 +0000
+++ libhipl/init.c      2012-05-15 09:25:24 +0000
@@ -34,7 +34,9 @@
 
 #include <errno.h>
 #include <limits.h>
+#include <pwd.h>
 #include <signal.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -118,6 +120,34 @@
 #endif
 /** end ICMPV6_FILTER related stuff */
 
+#define HIPL_USER_DIR ".hipl"
+#define HIPL_USER_RSA_KEY_NAME "libhipl_rsa_key"
+
+/* 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 bool hipd_library_mode = false;
+
+/**
+ * Test if the library mode is on.
+ *
+ * @return true if the library mode is on, false otherwise.
+ */
+bool hipl_is_libhip_mode(void)
+{
+    return hipd_library_mode;
+}
+
+/**
+ * Turn on library mode.
+ */
+void hipl_set_libhip_mode(void)
+{
+    hipd_library_mode = true;
+}
+
 /* Startup flags of the HIPD. Keep the around, for they will be used at exit */
 static uint64_t sflags;
 
@@ -523,6 +553,199 @@
     lmod_register_packet_type(HIP_LUPDATE,   "HIP_LUPDATE");
 }
 
+static int libhip_init_handle_functions(void)
+{
+    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_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_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_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_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_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_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_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_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_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 0;
+}
+
 static int init_handle_functions(void)
 {
     int err = 0;
@@ -1090,6 +1313,78 @@
 }
 
 /**
+ * Initialization function for libhipl.
+ *
+ * @param debug_level debug level for log output.
+ * @return            0 on success, negative number on error.
+ */
+int hipl_lib_init(enum logdebug debug_level)
+{
+    int                err         = 0;
+    int                keypath_len = 0;
+    char              *key_path    = NULL;
+    struct hip_common *msg         = NULL;
+    struct passwd     *pwd;
+
+    hipl_set_libhip_mode();
+    hip_nat_status = 1;
+
+    /* disable hip_firewall */
+    lsi_status = HIP_MSG_LSI_OFF;
+
+    hip_set_logdebug(debug_level);
+
+    hip_init_hadb();
+    hip_init_hostid_db();
+    hip_netdev_init_addresses();
+    libhip_init_handle_functions();
+
+    /* Load default key from ~/.hipl/ */
+    if ((pwd = getpwuid(getuid())) == NULL) {
+        return -1;
+    }
+
+    /* +3 because we need 2 slashes and a NULL for termination */
+    keypath_len = strlen(pwd->pw_dir) +
+                  strlen(HIPL_USER_DIR) +
+                  strlen(HIPL_USER_RSA_KEY_NAME) +
+                  strlen(DEFAULT_PUB_HI_FILE_NAME_SUFFIX) + 3;
+    if ((key_path = malloc(keypath_len)) == NULL) {
+        HIP_ERROR("malloc() failed\n");
+        return -ENOMEM;
+    }
+
+    HIP_IFEL(snprintf(key_path, keypath_len, "%s/%s/%s%s", pwd->pw_dir,
+                      HIPL_USER_DIR,
+                      HIPL_USER_RSA_KEY_NAME,
+                      DEFAULT_PUB_HI_FILE_NAME_SUFFIX) < 0,
+             -1, "snprintf() failed");
+
+    HIP_DEBUG("Using key: %s\n", key_path);
+    HIP_IFEL(!(msg = hip_msg_alloc()), -ENOMEM, "hip_msg_alloc()");
+    if (hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa",
+                                     key_path, 0, 0, 0)) {
+        hip_msg_init(msg);
+        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);
+
+        hip_msg_init(msg);
+        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' => 'libhipl/init.h'
--- hipd/init.h 2011-11-25 17:56:24 +0000
+++ libhipl/init.h      2012-05-15 09:25:24 +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
@@ -23,12 +23,14 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_INIT_H
-#define HIPL_HIPD_INIT_H
+#ifndef HIPL_LIBHIPL_INIT_H
+#define HIPL_LIBHIPL_INIT_H
 
 #include <stdint.h>
 #include <netinet/in.h>
 
+#include "libcore/debug.h"
+
 
 /* startup flags options to be configured via the command line */
 #define HIPD_START_FOREGROUND               (1 << 0)
@@ -60,4 +62,6 @@
                             int is_output);
 void hip_exit(void);
 
-#endif /* HIPL_HIPD_INIT_H */
+int hipl_lib_init(enum logdebug);
+
+#endif /* HIPL_LIBHIPL_INIT_H */

=== renamed file 'hipd/input.c' => 'libhipl/input.c'
--- hipd/input.c        2012-05-12 06:54:33 +0000
+++ libhipl/input.c     2012-05-15 09:25:24 +0000
@@ -707,6 +707,11 @@
                                &ctx->src_addr);
     }
 
+    if (hipl_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' => 'libhipl/input.h'
--- hipd/input.h        2012-05-12 06:54:33 +0000
+++ libhipl/input.h     2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_INPUT_H
-#define HIPL_HIPD_INPUT_H
+#ifndef HIPL_LIBHIPL_INPUT_H
+#define HIPL_LIBHIPL_INPUT_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -133,4 +133,4 @@
                                UNUSED const enum hip_state ha_state,
                                struct hip_packet_context *const ctx);
 
-#endif /* HIPL_HIPD_INPUT_H */
+#endif /* HIPL_LIBHIPL_INPUT_H */

=== renamed file 'hipd/keymat.c' => 'libhipl/keymat.c'
=== renamed file 'hipd/keymat.h' => 'libhipl/keymat.h'
--- hipd/keymat.h       2012-05-12 06:54:33 +0000
+++ libhipl/keymat.h    2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_KEYMAT_H
-#define HIPL_HIPD_KEYMAT_H
+#ifndef HIPL_LIBHIPL_KEYMAT_H
+#define HIPL_LIBHIPL_KEYMAT_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -44,4 +44,4 @@
                              struct hip_keymat_keymat *keymat,
                              int len);
 
-#endif /* HIPL_HIPD_KEYMAT_H */
+#endif /* HIPL_LIBHIPL_KEYMAT_H */

=== added file 'libhipl/lhipl.c'
--- libhipl/lhipl.c     1970-01-01 00:00:00 +0000
+++ libhipl/lhipl.c     2012-05-15 09:25:24 +0000
@@ -0,0 +1,536 @@
+/*
+ * 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
+ * Provides the implementation of the libhipl public APIs.
+ */
+
+#define _BSD_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libcore/builder.h"
+#include "libcore/ife.h"
+#include "libcore/prefix.h"
+#include "close.h"
+#include "hadb.h"
+#include "init.h"
+#include "lhipl_sock.h"
+#include "lhipl_operations.h"
+#include "netdev.h"
+#include "output.h"
+#include "lhipl.h"
+
+
+/* A switch to turn BEX feedback off/on.
+ *
+ * If it is on, when the BEX process is conducted during "recvmsg" and 
"sendmsg",
+ * the intermediate result is returned to the caller.
+ * If it is off, "recvmsg" and "sendmsg" will only return after the message 
gets
+ * sent or received.
+ */
+static bool libhipl_bex_feedback;
+
+/**
+ * build a @c sockaddr_in6 address to store a peer's HIT and port number from a
+ * string-based peer name and a port number.
+ *
+ * @param peername the string representation of a peer, only support HIT string
+ *                 currently.
+ * @param port     the port of the peer.
+ * @param peer     the @c sockaddr_in6 to hold the peer's HIT and port number.
+ * @return         0 on success, -1 on error.
+ */
+static int build_peer_hit(const char *peername, const uint16_t port,
+                          struct sockaddr_in6 *peer)
+{
+    if (!peername || !peer) {
+        HIP_ERROR("Invalid input\n");
+        return -1;
+    }
+
+    if (inet_pton(AF_INET6, peername, &peer->sin6_addr) != 1) {
+        HIP_ERROR("Failed to translate %s into HIT\n", peername);
+    }
+    peer->sin6_port   = htons(port);
+    peer->sin6_family = AF_INET6;
+    return 0;
+}
+
+/**
+ * Initialize libhipl library.
+ *
+ * This function should be called before using libhipl.
+ *
+ * @param debug_level the debug level of the libhipl library.
+ * @return            0 on success, negative number on error.
+ */
+int hipl_lib_init_all(enum hipl_lib_loglv debug_level)
+{
+    hipl_hsock_init();
+    switch (debug_level) {
+    case HIPL_LIB_LOG_DEBUG:
+        return hipl_lib_init(LOGDEBUG_ALL);
+    case HIPL_LIB_LOG_INFO:
+        return hipl_lib_init(LOGDEBUG_MEDIUM);
+    case HIPL_LIB_LOG_ERROR:
+        return hipl_lib_init(LOGDEBUG_LOW);
+    case HIPL_LIB_LOG_NONE:
+        return hipl_lib_init(LOGDEBUG_NONE);
+    }
+
+    return -1;
+}
+
+/**
+ * Check the current state of the BEX feedback switch.
+ *
+ * @return true if the switch is on, false if it is off.
+ */
+bool hipl_lib_bex_feedback(void)
+{
+    return libhipl_bex_feedback;
+}
+
+/**
+ * Turn the BEX feedback switch off/on.
+ *
+ * @param val true to turn the switch on, false to turn it off.
+ */
+void hipl_lib_set_bex_feedback(bool val)
+{
+    libhipl_bex_feedback = val;
+}
+
+/**
+ * Turn the non-blocking feature on/off for a libhipl socket.
+ *
+ * @param hsock_id ID of the libhipl socket.
+ * @param on       true to turn non-blocking on, false otherwise.
+ * @return         0 on success, negative number on error.
+ */
+int hipl_lib_set_nonblock(const hipl_sock_id hsock_id, bool on)
+{
+    int               flags;
+    struct hipl_sock *hsock = NULL;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
+        return -EBADF;
+    }
+
+    flags = fcntl(hsock->sock_fd, F_GETFL, 0);
+    if (on && !(flags & O_NONBLOCK)) {
+        fcntl(hsock->sock_fd, F_SETFL, flags | O_NONBLOCK);
+    } else if (!on && (flags & O_NONBLOCK)) {
+        fcntl(hsock->sock_fd, F_SETFL, flags & ~O_NONBLOCK);
+    }
+    return 0;
+}
+
+/**
+ * Return the corresponding socket file descriptor of a libhipl socket.
+ *
+ * @param hsock_id the ID of the libhipl socket
+ * @return         socket file descriptor on success, -1 on error.
+ */
+int hipl_lib_get_sockfd(const hipl_sock_id hsock_id)
+{
+    struct hipl_sock *hsock = NULL;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
+        return -1;
+    }
+
+    return hsock->sock_fd;
+}
+
+/**
+ * Save peer's HIT-to-IP mapping.
+ *
+ * @param hit  peer's hit.
+ * @param addr peer's IP address.
+ * @return     0 on success, -1 otherwise.
+ */
+int hipl_add_peer_info(const char *const hit, const char *const addr)
+{
+    struct in6_addr peer_hit, peer_addr6;
+    struct in_addr  peer_addr4;
+
+    if (!hit || !addr) {
+        HIP_ERROR("Invalid argument\n");
+        return -1;
+    }
+    if (inet_pton(AF_INET6, hit, &peer_hit) != 1) {
+        HIP_ERROR("Invalid hit: %s\n", hit);
+        return -1;
+    }
+    if (!ipv6_addr_is_hit(&peer_hit)) {
+        HIP_ERROR("Invalid hit: %s\n", hit);
+        return -1;
+    }
+    if (inet_pton(AF_INET6, addr, &peer_addr6) != 1) {
+        if (inet_pton(AF_INET, addr, &peer_addr4) != 1) {
+            HIP_ERROR("Invalid address: %s\n", addr);
+            return -1;
+        }
+        IPV4_TO_IPV6_MAP(&peer_addr4, &peer_addr6);
+    }
+
+    return hip_hadb_add_peer_info(&peer_hit, &peer_addr6, NULL, NULL);
+}
+
+/**
+ * Create a libhipl socket.
+ *
+ * @param domain    the domain of the libhipl socket (AF_INET / AF_INET6).
+ * @param type      the type of the libhipl socket (SOCK_DGRAM / SOCK_STREAM).
+ * @param protocol  the protocol (IPPROTO_UDP / IPPROTO_TCP).
+ * @return          the ID of the new libhipl socket on success, negative
+ *                  number on error.
+ */
+int hipl_socket(const int domain, const int type, const int protocol)
+{
+    if (domain != AF_INET && domain != AF_INET6) {
+        HIP_ERROR("Invalid domain: %d\n", domain);
+        return -EINVAL;
+    }
+    if (type != SOCK_DGRAM && type != SOCK_STREAM) {
+        HIP_ERROR("Invalid type: %d\n", type);
+        return -EINVAL;
+    }
+    if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
+        HIP_ERROR("Invalid protocol: %d\n", protocol);
+        return -EINVAL;
+    }
+
+    return hipl_socket_internal(domain, type, protocol);
+}
+
+/**
+ * Close a socket.
+ *
+ * Send HIP CLOSE message to the associated peer and delete the libhipl
+ * socket information.
+ *
+ * @param hsock_id the ID of the libhipl socket to be closed.
+ * @return         0 on success, negative number on error.
+ */
+int hipl_close(const hipl_sock_id hsock_id)
+{
+    int                ret   = 0;
+    struct hip_common *msg   = NULL;
+    struct hipl_sock  *hsock = NULL;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
+        return -1;
+    }
+    if (!hsock->ha || hsock->ha->state == HIP_STATE_CLOSED) {
+        HIP_DEBUG("Not sending CLOSE.\n");
+        goto skip_close_msg;
+    }
+
+    /* Build HIP_CLOSE message and send it to the peer */
+    if ((msg = hip_msg_alloc()) == NULL) {
+        HIP_ERROR("hip_msg_alloc() failed");
+        ret = -ENOMEM;
+        goto skip_close_msg;
+    }
+    if ((ret = hip_build_param_contents(msg, &hsock->peer_hit,
+                                        HIP_PARAM_HIT,
+                                        sizeof(hsock->peer_hit))) < 0) {
+        HIP_ERROR("hip_build_param_contents() failed\n");
+        goto skip_close_msg;
+    }
+    if ((ret = hip_send_close(msg, 1)) < 0) {
+        HIP_ERROR("hip_send_close() failed\n");
+    }
+
+skip_close_msg:
+    if (hsock) {
+        close(hsock->sock_fd);
+        hipl_hsock_delete_and_free(hsock);
+    }
+    free(msg);
+    return ret;
+}
+
+/**
+ * Bind a libhipl socket to a local IP address.
+ *
+ * @param hsock_id      the ID of the libhipl socket.
+ * @param address       the IP address to be bound.
+ * @param address_len   the length of the @c address.
+ * @return              0 on success, negative number on error.
+ */
+int hipl_bind(const hipl_sock_id hsock_id, const struct sockaddr *const 
address,
+              const socklen_t address_len)
+{
+    struct hipl_sock *hsock;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
+        return -1;
+    }
+
+    return hipl_bind_internal(hsock, address, address_len);
+}
+
+/**
+ * Switch a libhipl socket to listening mode.
+ *
+ * @param hsock_id the ID of the libhipl socket.
+ * @param backlog  the max length of the queue for pending connections.
+ * @return         zero on success, negative number on error.
+ */
+int hipl_listen(const hipl_sock_id hsock_id, const int backlog)
+{
+    struct hipl_sock *hsock;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
+        return -1;
+    }
+
+    return listen(hsock->sock_fd, backlog);
+}
+
+/**
+ * Send data to a peer.
+ *
+ * Triggers base exchange if no HIP association exists.
+ * @note Data is currently sent unencrypted.
+ *
+ * @param hsock_id  the ID of the libhipl socket for sending data.
+ * @param msg       data to send.
+ * @param len       size of the data.
+ * @param flags     the flags of the socket function @c sendto().
+ * @param peername  the string representation of the peer.
+ * @param port      peer's port number.
+ * @return          number of bytes sent on success, negative number on error.
+ */
+int hipl_sendto(const hipl_sock_id hsock_id, const void *const msg,
+                const size_t len, const int flags,
+                const char *const peername, uint16_t port)
+{
+    struct hipl_sock   *hsock;
+    struct sockaddr_in6 peer;
+    struct msghdr       params = { 0 };
+    struct iovec        iov;
+    char               *buf = NULL;
+    int                 err = 0;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
+        return -1;
+    }
+    if (hsock->sock_proto == IPPROTO_UDP
+        && (peername == NULL || build_peer_hit(peername, port, &peer) < 0)) {
+        HIP_ERROR("Invalid argument: peername\n");
+        return -EINVAL;
+    }
+    if (hsock->sock_proto == IPPROTO_TCP
+        && hsock->peer_locator.ss_family == 0) {
+        HIP_ERROR("Not connected!\n");
+        return -ENOTCONN;
+    }
+    if (msg == NULL) {
+        HIP_ERROR("Invalid argument: msg\n");
+        return -EINVAL;
+    }
+
+    struct sockaddr_storage dst;
+    struct sockaddr_in6    *p6;
+    if (hsock->sock_proto == IPPROTO_UDP) {
+        hipl_build_addrstorage(&peer.sin6_addr, ntohs(peer.sin6_port), &dst);
+    } else {
+        dst             = hsock->peer_locator;
+        p6              = (struct sockaddr_in6 *) &dst;
+        p6->sin6_addr   = hsock->peer_hit;
+        p6->sin6_family = AF_INET6;
+    }
+    if ((buf = malloc(len)) == NULL) {
+        return -ENOMEM;
+    }
+    memcpy(buf, msg, len);
+    iov.iov_base       = buf;
+    iov.iov_len        = len;
+    params.msg_name    = &dst;
+    params.msg_namelen = sizeof(dst);
+    params.msg_iovlen  = 1;
+    params.msg_iov     = &iov;
+
+    if (hipl_lib_bex_feedback()) {
+        err = hipl_sendmsg_internal(hsock, &params, flags);
+    } else {
+        fd_set fdset;
+        if (hipl_hsock_ha_state(hsock) == HIP_STATE_UNASSOCIATED) {
+            HIP_DEBUG("Sending via hsock %d, Triggering BEX.\n", hsock->sid);
+            err = hipl_sendmsg_internal(hsock, &params, flags);
+            HIP_IFEL(err != -EWAITBEX, -1, "hipl_sendmsg_internal() failed\n");
+        }
+        if (hipl_hsock_ha_state(hsock) == HIP_STATE_ESTABLISHED) {
+            HIP_DEBUG("Sending via hsock %d, HA established.\n", hsock->sid);
+            err = hipl_sendmsg_internal(hsock, &params, flags);
+        } else {
+            while (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
+                FD_ZERO(&fdset);
+                FD_SET(hsock->sock_fd, &fdset);
+                HIP_DEBUG("Sending via hsock %d, Waiting BEX.\n", hsock->sid);
+                err = select(hsock->sock_fd + 1, &fdset, NULL, NULL, NULL);
+                HIP_IFEL(err < 0, -1, "select(): %s\n", strerror(errno));
+                err = hipl_sendmsg_internal(hsock, &params, flags);
+                HIP_IFEL(err < 0 && err != -EWAITBEX && err != 
-EBEXESTABLISHED,
+                         -1, "hipl_sendmsg_internal() failed\n");
+            }
+            err = hipl_sendmsg_internal(hsock, &params, flags);
+        }
+    }
+
+out_err:
+    free(buf);
+    return err;
+}
+
+/**
+ * Receive data from a peer.
+ *
+ * Wait for base exchange if no host association exists.
+ * @note Data is currently sent unencrypted.
+ *
+ * @param hsock_id  the ID of the libhipl socket for receiving data.
+ * @param buf       buffer for received data.
+ * @param len       the size of the @c buf.
+ * @param flags     the flags of the socket function @c recvfrom().
+ * @param peername  buffer for the HIT of the associated peer, the size of
+ *                  this buffer should be at least @c HIPL_MAX_PEERNAME.
+ * @param port      buffer for the port of the associated peer.
+ * @return          number of bytes received on success,
+ *                  negative number on error,
+ *                  0 on end-of-file.
+ */
+int hipl_recvfrom(const hipl_sock_id hsock_id, void *const buf,
+                  const size_t len, const int flags,
+                  char *const peername, uint16_t *const port)
+{
+    struct hipl_sock   *hsock  = NULL;
+    struct msghdr       params = { 0 };
+    struct iovec        iov;
+    struct sockaddr_in6 hit;
+    int                 ret;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
+        return -1;
+    }
+    if (hsock->sock_proto == IPPROTO_TCP
+        && hsock->peer_locator.ss_family == 0) {
+        HIP_ERROR("Not connected!\n");
+        return -ENOTCONN;
+    }
+
+    iov.iov_base       = buf;
+    iov.iov_len        = len;
+    params.msg_name    = &hit;
+    params.msg_namelen = sizeof(hit);
+    params.msg_iovlen  = 1;
+    params.msg_iov     = &iov;
+
+    if (!hipl_lib_bex_feedback()) {
+        fd_set fdset;
+        while (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
+            FD_ZERO(&fdset);
+            FD_SET(hsock->sock_fd, &fdset);
+            if (select(hsock->sock_fd + 1, &fdset, NULL, NULL, NULL) < 0) {
+                HIP_PERROR("select()");
+            }
+            ret = hipl_recvmsg_internal(hsock, &params, flags);
+            if (ret < 0 && ret != -EWAITBEX && ret != -EBEXESTABLISHED) {
+                HIP_ERROR("hipl_recvmsg_internal() failed()\n");
+                return ret;
+            }
+        }
+    }
+    ret = hipl_recvmsg_internal(hsock, &params, flags);
+
+    if (peername) {
+        inet_ntop(AF_INET6, &hit.sin6_addr, peername, HIPL_MAX_PEERNAME);
+    }
+    if (port) {
+        *port = ntohs(hit.sin6_port);
+    }
+    return ret;
+}
+
+/**
+ * Initiate a connection to a peer.
+ *
+ * @param hsock_id   the ID of the libhipl socket to initiate a connection.
+ * @param peername   the string representation of the peer.
+ * @param port       the port number of the peer.
+ * @return           0 on success, negative number on error.
+ */
+int hipl_connect(const hipl_sock_id hsock_id, const char *peername,
+                 const uint16_t port)
+{
+    struct hipl_sock   *hsock = NULL;
+    struct sockaddr_in6 peer;
+
+    if (peername == NULL || build_peer_hit(peername, port, &peer) < 0) {
+        HIP_ERROR("Invalid argument: peername\n");
+        return -EINVAL;
+    }
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
+        return -1;
+    }
+
+    return hipl_connect_internal(hsock, &peer);
+}
+
+/**
+ * Wait for an incoming connection.
+ *
+ * @param hsock_id the ID of the libhipl socket for waiting connections.
+ * @return         the ID of the accepted libhipl socket, negative number
+ *                 on error.
+ */
+int hipl_accept(const hipl_sock_id hsock_id)
+{
+    struct hipl_sock *hsock = NULL;
+
+    if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
+        HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
+        return -1;
+    }
+
+    return hipl_accept_internal(hsock);
+}

=== added file 'libhipl/lhipl.h'
--- libhipl/lhipl.h     1970-01-01 00:00:00 +0000
+++ libhipl/lhipl.h     2012-05-15 09:25:24 +0000
@@ -0,0 +1,76 @@
+/*
+ * 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_HIPL_LHIPL_H
+#define HIPL_LIB_HIPL_LHIPL_H
+
+#include <sys/socket.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#define EWAITBEX        139000
+#define EBEXESTABLISHED 139001
+
+#define HIPL_MAX_PEERNAME 128
+
+enum hipl_lib_loglv { HIPL_LIB_LOG_DEBUG, HIPL_LIB_LOG_INFO,
+                      HIPL_LIB_LOG_ERROR, HIPL_LIB_LOG_NONE };
+
+typedef uint16_t hipl_sock_id;
+
+int hipl_lib_init_all(enum hipl_lib_loglv);
+
+void hipl_lib_set_bex_feedback(bool val);
+bool hipl_lib_bex_feedback(void);
+
+int hipl_lib_set_nonblock(const hipl_sock_id hsock_id, bool on);
+int hipl_lib_get_sockfd(const hipl_sock_id hsock_id);
+
+int hipl_add_peer_info(const char *const hit, const char *const addr);
+
+int hipl_socket(const int domain, const int type, const int protocol);
+
+int hipl_close(const hipl_sock_id hsock_id);
+
+int hipl_listen(const hipl_sock_id hsock_id, const int backlog);
+
+int hipl_bind(const hipl_sock_id hsock_id, const struct sockaddr *const 
address,
+              const socklen_t address_len);
+
+int hipl_sendto(const hipl_sock_id hsock_id, const void *const msg,
+                const size_t len, const int flags,
+                const char *const peername, const uint16_t port);
+
+int hipl_recvfrom(const hipl_sock_id hsock_id, void *const buf,
+                  const size_t len, const int flags,
+                  char *const peername, uint16_t *const port);
+
+int hipl_connect(const hipl_sock_id hsock_id, const char *const peername,
+                 const uint16_t port);
+
+int hipl_accept(const hipl_sock_id hsock_id);
+
+#endif /* HIPL_LIB_HIPL_LHIPL_H */

=== added file 'libhipl/lhipl_operations.c'
--- libhipl/lhipl_operations.c  1970-01-01 00:00:00 +0000
+++ libhipl/lhipl_operations.c  2012-05-15 09:25:24 +0000
@@ -0,0 +1,774 @@
+/*
+ * Copyright (c) 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
+ * Provides the internal implementation of the libhipl socket related
+ * operations.
+ */
+
+#define _BSD_SOURCE
+
+#include <sys/socket.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libcore/builder.h"
+#include "libcore/hip_udp.h"
+#include "libcore/ife.h"
+#include "libcore/prefix.h"
+#include "lhipl.h"
+#include "lhipl_sock.h"
+#include "hadb.h"
+#include "hidb.h"
+#include "input.h"
+#include "netdev.h"
+#include "output.h"
+#include "lhipl_operations.h"
+
+
+/**
+ * Automatically bind to a port for a libhipl socket.
+ *
+ * @param hsock the libhipl socket for port binding.
+ * @return      0 on success, -1 on error.
+ */
+static int auto_bind(struct hipl_sock *const hsock)
+{
+    struct sockaddr_storage ss = { 0 };
+    struct sockaddr_in     *addr4;
+    struct sockaddr_in6    *addr6;
+
+    if (hsock->src_port != 0) {
+        HIP_DEBUG("A bound port exists, auto_bind stops\n");
+        return 0;
+    }
+
+    if (hsock->sock_family == AF_INET) {
+        ss.ss_family    = AF_INET;
+        addr4           = (struct sockaddr_in *) &ss;
+        addr4->sin_port = 0;
+        return hipl_bind_internal(hsock, (struct sockaddr *) addr4,
+                                  sizeof(ss));
+    } else {
+        ss.ss_family     = AF_INET6;
+        addr6            = (struct sockaddr_in6 *) &ss;
+        addr6->sin6_port = 0;
+        return hipl_bind_internal(hsock, (struct sockaddr *) addr6,
+                                  sizeof(ss));
+    }
+}
+
+static uint16_t get_port_from_saddr(const struct sockaddr *const addr)
+{
+    const struct sockaddr_in  *addr4 = (const struct sockaddr_in *) addr;
+    const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
+
+    if (addr->sa_family == AF_INET) {
+        return addr4->sin_port;
+    } else {
+        return addr6->sin6_port;
+    }
+}
+
+/**
+ * Set global variables in order to inter-operate with libhipdeamon.
+ *
+ * @param sock_fd     the socket file descriptor for sending message.
+ * @param local_port  the local port for sending message.
+ * @param remote_port the remote port for receiving message.
+ */
+static void set_hip_connection_parameters(const int sock_fd,
+                                          const int local_port,
+                                          const int remote_port)
+{
+    HIP_DEBUG("Set connection params: 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 packet.
+ * @param len   size of the @c buf.
+ * @param hsock the libhipl socket receiving the packet.
+ * @return      1 on a control message, 0 on a user message,
+ *              negative number on error.
+ */
+static int hipl_is_control_msg(char *const buf, unsigned int len,
+                               struct hipl_sock *const hsock)
+{
+    char                    udp_pad[HIP_UDP_ZERO_BYTES_LEN] = { 0 };
+    struct hip_common      *msg;
+    struct sockaddr_storage src    = { 0 };
+    socklen_t               srclen = sizeof(src);
+
+    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;
+    }
+
+    if (getsockname(hsock->sock_fd, (struct sockaddr *) &src, &srclen) < 0) {
+        HIP_PERROR("getsockname()");
+        return true;
+    }
+
+    return !hip_verify_network_header(msg, (struct sockaddr *) &src,
+                                      (struct sockaddr *) &hsock->peer_locator,
+                                      len);
+}
+
+static void build_packet_context(struct hip_packet_context *const ctx,
+                                 struct sockaddr *ctx_dst, struct sockaddr 
*ctx_src)
+{
+    struct sockaddr_in  *s4;
+    struct sockaddr_in6 *s6;
+
+    if (ctx_dst->sa_family == AF_INET) {
+        s4 = (struct sockaddr_in *) ctx_dst;
+        IPV4_TO_IPV6_MAP(&s4->sin_addr, &ctx->dst_addr);
+        ctx->msg_ports.dst_port = ntohs(s4->sin_port);
+    } else if (ctx_dst->sa_family == AF_INET6) {
+        s6                      = (struct sockaddr_in6 *) ctx_dst;
+        ctx->dst_addr           = s6->sin6_addr;
+        ctx->msg_ports.dst_port = ntohs(s6->sin6_port);
+    }
+
+    if (ctx_src->sa_family == AF_INET) {
+        s4 = (struct sockaddr_in *) ctx_src;
+        IPV4_TO_IPV6_MAP(&s4->sin_addr, &ctx->src_addr);
+        ctx->msg_ports.src_port = ntohs(s4->sin_port);
+    } else if (ctx_src->sa_family == AF_INET6) {
+        s6                      = (struct sockaddr_in6 *) ctx_src;
+        ctx->src_addr           = s6->sin6_addr;
+        ctx->msg_ports.src_port = ntohs(s6->sin6_port);
+    }
+}
+
+/**
+ * Receive and pre-process an incoming message.
+ *
+ * This function discards UDP packet from an unknown peer, identifies
+ * user/control packet, eliminates zero padding in control packets and
+ * builds the packet context for handling control packets.
+ *
+ * @param hsock       the libhipl socket for receiving message.
+ * @param msg         buffer to hold the incoming message.
+ * @param flags       the flags of socket @c recvmsg().
+ * @param ctx         the HIP packet context to be built.
+ * @param is_user_msg true if the message is a user message, false otherwise.
+ * @return            negative number on errors, 0 on end-of-file, number of
+ *                    bytes received otherwise.
+ */
+static int recv_msg_wrapper(struct hipl_sock *const hsock,
+                            struct msghdr *const msg, const int flags,
+                            struct hip_packet_context *const ctx,
+                            bool *is_user_msg)
+{
+    int                     ret;
+    struct sockaddr_storage our_locator = { 0 };
+    socklen_t               sslen       = sizeof(our_locator);
+
+    *is_user_msg = true;
+    if ((ret = recvmsg(hsock->sock_fd, msg, flags)) < 0) {
+        HIP_PERROR("recvmsg()");
+        return -1;
+    }
+
+    //in UDP mode, we don't know the peer locator until we receive the
+    //first message from the peer. Once we get the peer locator, save it
+    //to 'hsock'. We should also fill the packet context for UDP.
+    if (hsock->sock_proto == IPPROTO_UDP) {
+        if (msg->msg_name != NULL && hsock->peer_locator.ss_family == 0) {
+            memcpy(&hsock->peer_locator, msg->msg_name,
+                   sizeof(hsock->peer_locator));
+        }
+        if (ctx != NULL) {
+            if (getsockname(hsock->sock_fd, (struct sockaddr *) &our_locator,
+                            &sslen) < 0) {
+                HIP_PERROR("getsockname()");
+                return -1;
+            }
+            build_packet_context(ctx, (struct sockaddr *) &our_locator,
+                                 (struct sockaddr *) &hsock->peer_locator);
+        }
+    }
+
+    char *buf = msg->msg_iov->iov_base;
+    if (hipl_is_control_msg(buf, ret, hsock)) {
+        memmove(buf, buf + HIP_UDP_ZERO_BYTES_LEN,
+                HIP_MAX_PACKET - HIP_UDP_ZERO_BYTES_LEN);
+        ret         -= HIP_UDP_ZERO_BYTES_LEN;
+        *is_user_msg = false;
+    }
+
+    return ret;
+}
+
+static int nonblock_result_check(const int ret, const int err)
+{
+    if (ret < 0 && err != EWOULDBLOCK && err != EAGAIN) {
+        HIP_ERROR("BEX failed, errno = %d, errstr = %s\n", err,
+                  strerror(err));
+        return -1;
+    }
+    if (ret < 0 && (err == EWOULDBLOCK || err == EAGAIN)) {
+        HIP_DEBUG("BEX returns EWOULDBLOCK or EAGAIN\n");
+        return -EWAITBEX;
+    }
+
+    return 0;
+}
+
+/**
+ * Wait for a HIP I1 packet and continue performing base exchange.
+ *
+ * @param hsock     the libhipl socket waiting for the I1 packet.
+ * @param ctx       the HIP packet context for HIP packet processing.
+ * @return          0 on success, -1 on error, -EWAITBEX when BEX is pending
+ */
+static int nonblock_await_bex(struct hipl_sock *const hsock,
+                              struct hip_packet_context *const ctx)
+{
+    struct msghdr           params = { 0 };
+    struct iovec            iov;
+    struct sockaddr_storage ss;
+    bool                    is_user_msg;
+    int                     ret = 0;
+    int                     flag;
+
+    params.msg_name    = &ss;
+    params.msg_namelen = sizeof(ss);
+    params.msg_iovlen  = 1;
+    iov.iov_base       = ctx->input_msg;
+    iov.iov_len        = HIP_MAX_PACKET;
+    params.msg_iov     = &iov;
+
+    flag = fcntl(hsock->sock_fd, F_GETFL, 0);
+    fcntl(hsock->sock_fd, F_SETFL, flag | O_NONBLOCK);
+
+    set_hip_connection_parameters(hsock->sock_fd, hsock->src_port, 0);
+    ret = recv_msg_wrapper(hsock, &params, 0, ctx, &is_user_msg);
+    if ((ret = nonblock_result_check(ret, errno)) != 0) {
+        HIP_DEBUG("returns %d\n", ret);
+        goto out;
+    }
+
+    if (is_user_msg || hip_receive_control_packet(ctx) < 0) {
+        HIP_ERROR("hip_receive_control_packet() failed\n");
+        ret = -1;
+    }
+
+out:
+    fcntl(hsock->sock_fd, F_SETFL, flag);
+    return ret;
+}
+
+/**
+ * Trigger BEX in a non-blocking way.
+ *
+ * @param hsock    the libhipl socket to trigger BEX.
+ * @param src_hit  the source HIT for base exchange.
+ * @param dst_hit  the destination HIT for base exchange.
+ * @param dst_port the destination port.
+ * @return         -1 on error, -EWAITBEX when the BEX is pending, 0 if sending
+ *                 BEX trigger message successfully.
+ */
+static int nonblock_trigger_bex(struct hipl_sock *hsock,
+                                const hip_hit_t *src_hit,
+                                const hip_hit_t *dst_hit,
+                                const int dst_port)
+{
+    struct in6_addr dst_addr;
+    int             err = 0, flag;
+
+    flag = fcntl(hsock->sock_fd, F_GETFL, 0);
+    fcntl(hsock->sock_fd, F_SETFL, flag | O_NONBLOCK);
+
+    err = hip_map_id_to_addr(dst_hit, NULL, &dst_addr);
+    HIP_IFEL(err < 0, -1, "failed to match hit to IP\n");
+    HIP_IFEL(ipv6_addr_any(&dst_addr), -1, "Couldn't map HIT to IP\n");
+
+    set_hip_connection_parameters(hsock->sock_fd, hsock->src_port, dst_port);
+    err = netdev_trigger_bex(src_hit, dst_hit, NULL, NULL, NULL, &dst_addr);
+    HIP_DEBUG("netdev_trigger_bex returns %d, errno = %d\n", err, errno);
+    err = nonblock_result_check(err, errno);
+    if (err == 0) {
+        hsock->ha = hip_hadb_find_byhits(src_hit, dst_hit);
+    }
+
+out_err:
+    fcntl(hsock->sock_fd, F_SETFL, flag);
+    return err;
+}
+
+/**
+ * Handle BEX for a libhipl socket.
+ *
+ * If param @c peer_hit is given, current libhipl socket will be the initiator
+ * and trigger the BEX. otherwise, it acts as a responder and waits for an I1
+ * message.
+ *
+ * @param hsock    the libhipl socket to handle BEX.
+ * @param peer_hit the peer's hit and port.
+ * @return         -1 on error, -EWAITBEX when the BEX is pending, and
+ *                 -EBEXESTABLISHED when BEX finishes.
+ */
+static int handle_bex(struct hipl_sock *hsock, struct sockaddr_in6 *peer_hit)
+{
+    int                       err = 0;
+    struct hip_packet_context ctx = { 0 };
+
+    // We are the initiator, send I1
+    if (hipl_hsock_ha_state(hsock) == HIP_STATE_UNASSOCIATED && peer_hit) {
+        hsock->peer_hit = peer_hit->sin6_addr;
+
+        err = nonblock_trigger_bex(hsock, &hsock->src_hit,
+                                   &peer_hit->sin6_addr,
+                                   ntohs(peer_hit->sin6_port));
+        // send I1 successfully, return -EWAITBEX.
+        if (err == 0) {
+            err = -EWAITBEX;
+        }
+        return err;
+    }
+
+    // waiting for and handle control messages
+    hsock->ha = hip_hadb_find_byhits(&hsock->src_hit, &hsock->peer_hit);
+    if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
+        ctx.input_msg  = hip_msg_alloc();
+        ctx.output_msg = hip_msg_alloc();
+        HIP_IFEL(!ctx.input_msg || !ctx.output_msg, -ENOMEM,
+                 "hip_msg_alloc() failed\n");
+
+        err = nonblock_await_bex(hsock, &ctx);
+        HIP_DEBUG("nonb_await_bex returns %d\n", err);
+        if (err < 0) { /* -1 or -EWAITBEX */
+            goto out_err;
+        }
+        hsock->peer_hit = ctx.input_msg->hit_sender;
+        hsock->ha       = hip_hadb_find_byhits(&hsock->src_hit, 
&hsock->peer_hit);
+    }
+
+    if (hipl_hsock_ha_state(hsock) == HIP_STATE_ESTABLISHED) {
+        err = -EBEXESTABLISHED;
+    } else {
+        err = -EWAITBEX;
+    }
+
+out_err:
+    free(ctx.input_msg);
+    free(ctx.output_msg);
+    return err;
+}
+
+static int validate_udp_peer_addr(const struct hipl_sock *const hsock,
+                                  const struct sockaddr_storage *const saddr)
+{
+    const struct in6_addr *paddr;
+    struct in6_addr        peer_addr;
+
+    if (hsock->sock_proto != IPPROTO_UDP) {
+        return 0;
+    }
+
+    switch (saddr->ss_family) {
+    case AF_INET:
+        IPV4_TO_IPV6_MAP(&((const struct sockaddr_in *) saddr)->sin_addr,
+                         &peer_addr);
+        paddr = &peer_addr;
+        break;
+
+    case AF_INET6:
+        paddr = &((const struct sockaddr_in6 *) saddr)->sin6_addr;
+        break;
+
+    default:
+        HIP_DEBUG("Unsupported family: %d\n", saddr->ss_family);
+        return -1;
+    }
+
+    if (ipv6_addr_cmp(&hsock->ha->peer_addr, paddr)) {
+        HIP_DEBUG("Packet not from associated address. Dropping.\n");
+        HIP_DEBUG_IN6ADDR("expected", &hsock->ha->peer_addr);
+        HIP_DEBUG_IN6ADDR("got", paddr);
+        return -1;
+    }
+
+    return 0;
+}
+
+/**
+ * Build a @c sockaddr_storage from a given IPv6 address and a port number.
+ *
+ * If the address is V4MAPPED, the storage family will be @c AF_INET,
+ * otherwise the storage family will be @c AF_INET6.
+ *
+ * @param addr    a V6 address or a V4MAPPED address.
+ * @param port    the port number.
+ * @param ss      the @c sockaddr_storage to be filled.
+ */
+void hipl_build_addrstorage(const struct in6_addr *const addr,
+                            const uint16_t port,
+                            struct sockaddr_storage *const ss)
+{
+    HIP_ASSERT(addr && ss);
+    memset(ss, 0, sizeof(*ss));
+
+    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 = htons(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 = htons(port);
+    }
+}
+
+/**
+ * Create a libhipl socket.
+ *
+ * @param family    the communications domain of the libhipl socket
+ * @param type      the socket type of the libhipl socket
+ * @param protocol  the protocol of the libhipl socket
+ * @return          the ID of the new libhipl socket on success, negative
+ *                  number otherwise
+ */
+int hipl_socket_internal(const int family, const int type, const int protocol)
+{
+    int               sock;
+    int               on    = 1, off = 0;
+    struct hipl_sock *hsock = NULL;
+
+    //TODO support IPV6
+    if (family == AF_INET6) {
+        HIP_ERROR("No IPv6 support yet.\n");
+        return -ENOTSUP;
+    }
+
+    sock = socket(family, type, protocol);
+    if (family == 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));
+    }
+    if ((hsock = hipl_hsock_new(family, type, protocol)) == NULL) {
+        HIP_ERROR("Failed to create libhipl socket.\n");
+        close(sock);
+        return -1;
+    }
+    hsock->sock_fd = sock;
+    hip_get_default_hit(&hsock->src_hit);
+
+    return hsock->sid;
+}
+
+/**
+ * Bind a libhipl socket to a local address.
+ *
+ * @param hsock         the libhipl socket for address binding.
+ * @param address       the IP address to be bound.
+ * @param address_len   the length of the @c address.
+ * @return              0 on success, -1 on error.
+ */
+int hipl_bind_internal(struct hipl_sock *const hsock,
+                       const struct sockaddr *const address,
+                       const socklen_t address_len)
+{
+    struct     sockaddr_storage laddr     = { 0 };
+    socklen_t                   laddr_len = sizeof(laddr);
+    uint16_t                    request_port;
+
+    request_port = get_port_from_saddr(address);
+    if (bind(hsock->sock_fd, address, address_len) < 0) {
+        HIP_PERROR("bind error:");
+        return -1;
+    }
+
+    /* Ask OS for the assigned port number */
+    if (request_port == 0) {
+        if (0 > getsockname(hsock->sock_fd, (struct sockaddr *) &laddr,
+                            &laddr_len)) {
+            HIP_PERROR("getsockname() error: ");
+            return -1;
+        }
+        request_port = get_port_from_saddr((struct sockaddr *) &laddr);
+    }
+
+    hsock->src_port = ntohs(request_port);
+    HIP_DEBUG("bind to port %d\n", hsock->src_port);
+
+    return 0;
+}
+
+/**
+ * Initiate a connection to a peer.
+ *
+ * @param hsock    the libhipl socket to initiate the connection.
+ * @param peer     the peer's HIT and port number.
+ * @return         0 on success, -1 on error.
+ */
+int hipl_connect_internal(struct hipl_sock *const hsock,
+                          const struct sockaddr_in6 *const peer)
+{
+    struct in6_addr         dst_addr = { { { 0 } } };
+    struct sockaddr_storage ss;
+
+    if (ipv6_addr_any(&peer->sin6_addr)) {
+        HIP_ERROR("Invalid argument: dst_hit.\n");
+        return -1;
+    }
+
+    if (hip_map_id_to_addr(&peer->sin6_addr, 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));
+    hipl_build_addrstorage(&dst_addr, ntohs(peer->sin6_port), &ss);
+
+    if (connect(hsock->sock_fd, (struct sockaddr *) &ss, sizeof(ss)) < 0) {
+        HIP_ERROR("connect(): %s\n", strerror(errno));
+        return -1;
+    }
+
+    /* Save related information into hsock */
+    hsock->peer_hit     = peer->sin6_addr;
+    hsock->peer_locator = ss;
+    if (hsock->src_port == 0) {
+        socklen_t taddr_len = sizeof(ss);
+
+        if (getsockname(hsock->sock_fd, (struct sockaddr *) &ss,
+                        &taddr_len) < 0) {
+            HIP_PERROR("getsockname() error: ");
+            return -1;
+        }
+        hsock->src_port = ntohs(get_port_from_saddr((struct sockaddr *) &ss));
+    }
+
+    return 0;
+}
+
+/**
+ * Wait for an incoming connection on a libhipl socket.
+ *
+ * @param hsock the libhipl socket waiting for the connection.
+ * @return      the ID of the accepted libhipl socket on success, -1 on error.
+ */
+int hipl_accept_internal(struct hipl_sock *const hsock)
+{
+    int                     new_fd;
+    struct hipl_sock       *hsock_new = NULL;
+    struct sockaddr_storage ss        = { 0 };
+    socklen_t               ss_len    = sizeof(ss);
+
+    new_fd = accept(hsock->sock_fd, (struct sockaddr *) &ss, &ss_len);
+    if (new_fd < 0) {
+        HIP_PERROR("accept(): ");
+        return -1;
+    }
+
+    hsock_new = hipl_hsock_new(hsock->sock_family, hsock->sock_type,
+                               hsock->sock_proto);
+    hsock_new->src_port     = hsock->src_port;
+    hsock_new->src_hit      = hsock->src_hit;
+    hsock_new->sock_fd      = new_fd;
+    hsock_new->peer_locator = ss;
+
+    return hsock_new->sid;
+}
+
+/**
+ * Receive data from a remote peer.
+ *
+ * Wait for base exchange if no host association exists.
+ * @note Data is currently sent unencrypted.
+ * @note Scatter read is not supported yet.
+ *
+ * @param hsock     the libhipl socket for receiving data.
+ * @param msg       the buffer to hold data and peer information.
+ * @param flags     the flags of the socket function @c recvmsg().
+ * @return          number of bytes received on success,
+ *                  0 on end-of-file,
+ *                  -EWAITBEX when the BEX is pending,
+ *                  -EBEXESTABLISHED when BEX finishes,
+ *                  other negative numbers on error.
+ */
+ssize_t hipl_recvmsg_internal(struct hipl_sock *const hsock,
+                              struct msghdr *const msg,
+                              const int flags)
+{
+    struct hip_packet_context ctx    = { 0 };
+    struct msghdr             params = { 0 };
+    struct iovec              iov;
+    struct sockaddr_storage   recv_remote_addr;
+    int                       err = 0;
+    bool                      is_user_msg;
+
+    if (msg->msg_iovlen != 1) {
+        HIP_ERROR("Invalid iovlen: %d, scatter read is not supported yet\n",
+                  msg->msg_iovlen);
+        return -ENOTSUP;
+    }
+
+    /* Bind to an ephemeral port if the src port hasn't been bound yet */
+    if (auto_bind(hsock)) {
+        HIP_ERROR("Fail to bind the hip socket.\n");
+        return -1;
+    }
+
+    /* Handle BEX if HA hasn't established */
+    if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED
+        && hipl_hsock_ha_state(hsock) != HIP_STATE_CLOSING) {
+        return handle_bex(hsock, NULL);
+    }
+
+    ctx.input_msg  = hip_msg_alloc();
+    ctx.output_msg = hip_msg_alloc();
+    HIP_IFEL(!ctx.input_msg || !ctx.output_msg, -ENOMEM,
+             "hip_msg_alloc() failed\n");
+    params.msg_name    = &recv_remote_addr;
+    params.msg_namelen = sizeof(recv_remote_addr);
+    params.msg_iovlen  = 1;
+    iov.iov_base       = ctx.input_msg;
+    iov.iov_len        = HIP_MAX_PACKET;
+    params.msg_iov     = &iov;
+
+    err = recv_msg_wrapper(hsock, &params, flags, &ctx, &is_user_msg);
+    HIP_IFEL(err < 0, -1, "recv_msg_wrapper() failed\n");
+
+    if (validate_udp_peer_addr(hsock, &recv_remote_addr) < 0) {
+        HIP_IFEL(true, -EAGAIN,
+                 "Received a packet with invalid peer address, dropping.\n");
+    }
+    if (!is_user_msg) {
+        HIP_DEBUG("receive a hip control message.\n");
+        hip_receive_control_packet(&ctx);
+        if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
+            HIP_DEBUG("HA state change to %d, return 0.\n", hsock->ha->state);
+            return 0;
+        }
+    } else {
+        HIP_DEBUG("receive a user message.\n");
+        // TODO, if buffer size is too small, we should save it to a internal 
buffer
+        // and only return content with length specified by user's buffer 
(TCP).
+        // return error for UDP in this case.
+        struct iovec        *iovp;
+        struct sockaddr_in6 *hitp;
+        hitp = msg->msg_name;
+        iovp = msg->msg_iov;
+        HIP_IFEL(iovp->iov_len < (unsigned int) err, -1,
+                 "buffer size too small\n");
+        HIP_DEBUG_HIT("ha->hit_peer:", &hsock->ha->hit_peer);
+        hitp->sin6_family = AF_INET6;
+        hitp->sin6_port   = get_port_from_saddr((const struct sockaddr *) 
&hsock->peer_locator);
+        HIP_DEBUG("hitp port: %d\n", ntohs(hitp->sin6_port));
+        hitp->sin6_addr = hsock->ha->hit_peer;
+        memcpy(iovp->iov_base, ctx.input_msg, err);
+    }
+
+out_err:
+    free(ctx.input_msg);
+    free(ctx.output_msg);
+    return err;
+}
+
+/**
+ * Send data to a peer.
+ *
+ * Trigger base exchange if no host association exists.
+ * @note Data is currently sent unencrypted.
+ * @note Gather write is not supported yet.
+ *
+ * @param hsock     the libhipl socket for sending data.
+ * @param msg       containing data, and peer information.
+ * @param flags     the flags of the socket function @c sendmsg().
+ * @return          number of bytes sent on success,
+ *                  -EWAITBEX if the BEX is pending,
+ *                  -EBEXESTABLISHED if the BEX finishes,
+ *                  other negative number on error.
+ */
+ssize_t hipl_sendmsg_internal(struct hipl_sock *const hsock,
+                              struct msghdr *const msg,
+                              const int flags)
+{
+    int fd = hsock->sock_fd;
+
+    /* Gather write is not supported yet */
+    if (msg->msg_iovlen > 1) {
+        HIP_ERROR("Invalid iovlen: %d, gather write is not supported\n",
+                  msg->msg_iovlen);
+        return -ENOTSUP;
+    }
+
+    /* Bind to an ephemeral port if the src port hasn't been bound yet */
+    if (auto_bind(hsock)) {
+        HIP_ERROR("Fail to bind the hip socket.\n");
+        return -1;
+    }
+
+    /* Start BEX if HA hasn't established */
+    if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
+        return handle_bex(hsock, msg->msg_name);
+    }
+
+    /* Determine peer's locator and send out the message */
+    HIP_DEBUG("BEX ok, start to send user data\n");
+    if (hsock->peer_locator.ss_family == 0) {
+        hipl_build_addrstorage(&hsock->ha->peer_addr,
+                               hsock->ha->peer_udp_port,
+                               &hsock->peer_locator);
+    }
+    msg->msg_namelen = sizeof(hsock->peer_locator);
+    memcpy(msg->msg_name, &hsock->peer_locator, msg->msg_namelen);
+    return sendmsg(fd, msg, flags);
+}

=== added file 'libhipl/lhipl_operations.h'
--- libhipl/lhipl_operations.h  1970-01-01 00:00:00 +0000
+++ libhipl/lhipl_operations.h  2012-05-15 09:25:24 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 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_HIPL_LHIPL_OPERATIONS_H
+#define HIPL_LIB_HIPL_LHIPL_OPERATIONS_H
+
+#include "lhipl_sock.h"
+
+
+int hipl_socket_internal(const int family, const int type, const int protocol);
+
+int hipl_bind_internal(struct hipl_sock *const hsock,
+                       const struct sockaddr *const address,
+                       const socklen_t address_len);
+
+int hipl_connect_internal(struct hipl_sock *const hsock,
+                          const struct sockaddr_in6 *const addr);
+
+int hipl_accept_internal(struct hipl_sock *const hsock);
+
+ssize_t hipl_recvmsg_internal(struct hipl_sock *const hsock,
+                              struct msghdr *const msg,
+                              const int flags);
+
+ssize_t hipl_sendmsg_internal(struct hipl_sock *const hsock,
+                              struct msghdr *const msg,
+                              const int flags);
+
+void hipl_build_addrstorage(const struct in6_addr *const addr,
+                            const uint16_t port,
+                            struct sockaddr_storage *const ss);
+
+#endif /* HIPL_LIB_HIPL_LHIPL_OPERATIONS_H */

=== added file 'libhipl/lhipl_sock.c'
--- libhipl/lhipl_sock.c        1970-01-01 00:00:00 +0000
+++ libhipl/lhipl_sock.c        2012-05-15 09:25:24 +0000
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 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
+ * Provides functions for maintaining libhipl sockets.
+ */
+
+#define _BSD_SOURCE
+
+#include <sys/socket.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libcore/debug.h"
+#include "libcore/hashtable.h"
+#include "lhipl_sock.h"
+
+
+/* A hashtable to record all opening libhipl sockets */
+static HIP_HASHTABLE *hsocks = NULL;
+
+static unsigned long hipl_sk_hash(const struct hipl_sock *hsock)
+{
+    return hsock->sid;
+}
+
+STATIC_IMPLEMENT_LHASH_HASH_FN(hipl_sk, struct hipl_sock)
+
+static int hipl_sk_cmp(const struct hipl_sock *hsock1,
+                       const struct hipl_sock *hsock2)
+{
+    return memcmp(&hsock1->sid, &hsock2->sid, sizeof(hsock1->sid));
+}
+
+STATIC_IMPLEMENT_LHASH_COMP_FN(hipl_sk, struct hipl_sock)
+
+static uint32_t hsock_generate_id(void)
+{
+    static uint32_t id_generator = HIPL_LIB_HSOCK_ID_MIN;
+
+    if (id_generator == HIPL_LIB_HSOCK_ID_MAX) {
+        id_generator = HIPL_LIB_HSOCK_ID_MIN;
+    } else {
+        id_generator += 1;
+    }
+
+    return id_generator;
+}
+
+/**
+ * Initialize the libhipl socket hashtable.
+ */
+void hipl_hsock_init(void)
+{
+    hsocks = hip_ht_init(LHASH_HASH_FN(hipl_sk), LHASH_COMP_FN(hipl_sk));
+}
+
+/**
+ * Create a new libhipl socket and save it to the libhipl socket hashtable.
+ *
+ * @param family      the address family of the libhipl socket (INET or INET6).
+ * @param type        the type of the protocol.
+ * @param protocol    the protocol of the libhipl socket (TCP or UDP).
+ * @return            pointer to the created libhipl socket on success, NULL on
+ *                    error.
+ */
+struct hipl_sock *hipl_hsock_new(const int family, const int type,
+                                 const int protocol)
+{
+    struct hipl_sock *hsock = NULL;
+
+    hsock = calloc(sizeof(struct hipl_sock), sizeof(uint8_t));
+    if (hsock == NULL) {
+        HIP_ERROR("calloc() failed.\n");
+        return NULL;
+    }
+
+    hsock->sid         = hsock_generate_id();
+    hsock->sock_family = family;
+    hsock->sock_type   = type;
+    hsock->sock_proto  = protocol;
+    hip_ht_add(hsocks, hsock);
+    return hsock;
+}
+
+/**
+ * Get a libhipl socket by its ID.
+ *
+ * @param hsock_id the ID of the libhipl socket.
+ * @return         pointer to the libhipl socket on success, or NULL if the
+ *                 given ID doesn't match any record.
+ */
+struct hipl_sock *hipl_hsock_find(const uint16_t hsock_id)
+{
+    struct hipl_sock hsock;
+
+    hsock.sid = hsock_id;
+    return hip_ht_find(hsocks, &hsock);
+}
+
+/**
+ * Delete a libhipl socket and free the memory it occupies.
+ *
+ * @param hsock pointer to the libhipl socket to be deleted.
+ */
+void hipl_hsock_delete_and_free(struct hipl_sock *const hsock)
+{
+    struct hipl_sock *deleted_item;
+
+    deleted_item = hip_ht_delete(hsocks, hsock);
+    free(deleted_item);
+}
+
+/**
+ * Get the HIP association state of a given libhipl socket.
+ *
+ * @param hsock the libhipl socket.
+ * @return      the HIP association state of the libhipl socket.
+ */
+enum hip_state hipl_hsock_ha_state(const struct hipl_sock *const hsock)
+{
+    if (!hsock->ha) {
+        return HIP_STATE_UNASSOCIATED;
+    } else {
+        return hsock->ha->state;
+    }
+}

=== added file 'libhipl/lhipl_sock.h'
--- libhipl/lhipl_sock.h        1970-01-01 00:00:00 +0000
+++ libhipl/lhipl_sock.h        2012-05-15 09:25:24 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 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_HIPL_LHIPL_SOCK_H
+#define HIPL_LIB_HIPL_LHIPL_SOCK_H
+
+#include <limits.h>
+
+#include "libcore/protodefs.h"
+#include "libcore/state.h"
+
+
+#define HIPL_LIB_HSOCK_ID_MIN  1
+#define HIPL_LIB_HSOCK_ID_MAX  USHRT_MAX
+#define HIPL_LIB_HSOCK_MAX     1024
+
+/* The internal information about each libhipl socket.
+ *
+ * It is generated when a new libhipl socket is created.
+ */
+struct hipl_sock {
+    uint16_t                sid;           /* libhipl socket ID */
+    struct hip_hadb_state  *ha;
+    hip_hit_t               peer_hit;
+    struct sockaddr_storage peer_locator;
+    hip_hit_t               src_hit;       /* our HIT */
+    int                     src_port;      /* our port number */
+    int                     sock_fd;       /* underlying socket */
+    int                     sock_family;
+    int                     sock_type;
+    int                     sock_proto;
+};
+
+void hipl_hsock_init(void);
+
+enum hip_state hipl_hsock_ha_state(const struct hipl_sock *const hsock);
+
+struct hipl_sock *hipl_hsock_new(const int family, const int type,
+                                 const int protocol);
+
+struct hipl_sock *hipl_hsock_find(const uint16_t hsock_id);
+
+void hipl_hsock_delete_and_free(struct hipl_sock *const hsock);
+
+#endif /* HIPL_LIB_HIPL_LHIPL_SOCK_H */

=== renamed file 'hipd/lsidb.c' => 'libhipl/lsidb.c'
=== renamed file 'hipd/lsidb.h' => 'libhipl/lsidb.h'
--- hipd/lsidb.h        2012-05-12 06:54:33 +0000
+++ libhipl/lsidb.h     2012-05-15 09:25:24 +0000
@@ -30,8 +30,8 @@
  * host and which LSIs are still available.
  */
 
-#ifndef HIPL_HIPD_LSIDB_H
-#define HIPL_HIPD_LSIDB_H
+#ifndef HIPL_LIBHIPL_LSIDB_H
+#define HIPL_LIBHIPL_LSIDB_H
 
 #include <stdbool.h>
 
@@ -40,4 +40,4 @@
 bool lsidb_allocate_lsi(hip_lsi_t *const lsi);
 bool lsidb_free_lsi(const hip_lsi_t const lsi);
 
-#endif /* HIPL_HIPD_LSIDB_H */
+#endif /* HIPL_LIBHIPL_LSIDB_H */

=== renamed file 'hipd/maintenance.c' => 'libhipl/maintenance.c'
=== renamed file 'hipd/maintenance.h' => 'libhipl/maintenance.h'
--- hipd/maintenance.h  2012-03-20 21:45:03 +0000
+++ libhipl/maintenance.h       2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_MAINTENANCE_H
-#define HIPL_HIPD_MAINTENANCE_H
+#ifndef HIPL_LIBHIPL_MAINTENANCE_H
+#define HIPL_LIBHIPL_MAINTENANCE_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -43,4 +43,4 @@
                        struct in6_addr *hit_r);
 int hipfw_set_esp_relay(int action);
 
-#endif /* HIPL_HIPD_MAINTENANCE_H */
+#endif /* HIPL_LIBHIPL_MAINTENANCE_H */

=== renamed file 'hipd/nat.c' => 'libhipl/nat.c'
=== renamed file 'hipd/nat.h' => 'libhipl/nat.h'
--- hipd/nat.h  2012-05-12 06:54:33 +0000
+++ libhipl/nat.h       2012-05-15 09:25:24 +0000
@@ -35,8 +35,8 @@
  * @note    All Doxygen comments have been added in version 1.1.
  */
 
-#ifndef HIPL_HIPD_NAT_H
-#define HIPL_HIPD_NAT_H
+#ifndef HIPL_LIBHIPL_NAT_H
+#define HIPL_LIBHIPL_NAT_H
 
 #include "libcore/protodefs.h"
 
@@ -52,4 +52,4 @@
 int hip_nat_refresh_port(void);
 int hip_user_nat_mode(int nat_mode);
 
-#endif /* HIPL_HIPD_NAT_H */
+#endif /* HIPL_LIBHIPL_NAT_H */

=== renamed file 'hipd/netdev.c' => 'libhipl/netdev.c'
=== renamed file 'hipd/netdev.h' => 'libhipl/netdev.h'
--- hipd/netdev.h       2012-05-12 06:54:33 +0000
+++ libhipl/netdev.h    2012-05-15 09:25:24 +0000
@@ -29,8 +29,8 @@
  * events over netlink from the kernel.
  */
 
-#ifndef HIPL_HIPD_NETDEV_H
-#define HIPL_HIPD_NETDEV_H
+#ifndef HIPL_LIBHIPL_NETDEV_H
+#define HIPL_LIBHIPL_NETDEV_H
 
 #include <stdbool.h>
 #include <netinet/in.h>
@@ -73,4 +73,4 @@
 int hip_map_id_to_addr(const hip_hit_t *hit, const hip_lsi_t *lsi,
                        struct in6_addr *addr);
 
-#endif /* HIPL_HIPD_NETDEV_H */
+#endif /* HIPL_LIBHIPL_NETDEV_H */

=== renamed file 'hipd/nsupdate.c' => 'libhipl/nsupdate.c'
=== renamed file 'hipd/nsupdate.h' => 'libhipl/nsupdate.h'
--- hipd/nsupdate.h     2011-11-25 17:56:24 +0000
+++ libhipl/nsupdate.h  2012-05-15 09:25:24 +0000
@@ -33,12 +33,12 @@
  * @brief and nsupdate by hip_send_locators_to_all_peers and hipd_init
  */
 
-#ifndef HIPL_HIPD_NSUPDATE_H
-#define HIPL_HIPD_NSUPDATE_H
+#ifndef HIPL_LIBHIPL_NSUPDATE_H
+#define HIPL_LIBHIPL_NSUPDATE_H
 
 void hip_set_nsupdate_status(int status);
 int hip_get_nsupdate_status(void);
 
 int nsupdate(int start);
 
-#endif /* HIPL_HIPD_NSUPDATE_H */
+#endif /* HIPL_LIBHIPL_NSUPDATE_H */

=== renamed file 'hipd/opp_mode.c' => 'libhipl/opp_mode.c'
=== renamed file 'hipd/opp_mode.h' => 'libhipl/opp_mode.h'
--- hipd/opp_mode.h     2012-05-12 06:54:33 +0000
+++ libhipl/opp_mode.h  2012-05-15 09:25:24 +0000
@@ -31,8 +31,8 @@
  * @brief Interface of the HIP opportunistic mode
  */
 
-#ifndef HIPL_HIPD_OPP_MODE_H
-#define HIPL_HIPD_OPP_MODE_H
+#ifndef HIPL_LIBHIPL_OPP_MODE_H
+#define HIPL_LIBHIPL_OPP_MODE_H
 
 #include <netinet/in.h>
 
@@ -43,4 +43,4 @@
                                                     const struct in6_addr 
*const src_addr);
 int hip_handle_opp_r1(struct hip_packet_context *ctx);
 
-#endif /* HIPL_HIPD_OPP_MODE_H */
+#endif /* HIPL_LIBHIPL_OPP_MODE_H */

=== renamed file 'hipd/output.c' => 'libhipl/output.c'
--- hipd/output.c       2012-05-12 06:54:33 +0000
+++ libhipl/output.c    2012-05-15 09:25:24 +0000
@@ -848,7 +848,8 @@
     HIP_ASSERT(!hit_is_opportunistic_hit(&ctx->input_msg->hit_receiver));
 
     /* Case: I ----->IPv4---> RVS ---IPv6---> R */
-    if (IN6_IS_ADDR_V4MAPPED(r1_src_addr) !=
+    if (!hipl_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);
@@ -1217,6 +1218,9 @@
         goto out_err;
     }
 
+    if (hipl_is_libhip_mode()) {
+        udp = 1;
+    }
     dst_is_ipv4 = IN6_IS_ADDR_V4MAPPED(peer_addr);
     len         = hip_get_msg_total_len(msg);
 
@@ -1245,13 +1249,16 @@
     if (local_addr) {
         HIP_DEBUG("local address given\n");
         memcpy(&my_addr, local_addr, sizeof(struct in6_addr));
-    } else {
+    } else if (!hipl_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);
@@ -1305,9 +1312,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 (!hipl_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()) {
@@ -1324,18 +1332,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 (!hipl_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' => 'libhipl/output.h'
--- hipd/output.h       2012-05-12 06:54:33 +0000
+++ libhipl/output.h    2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_OUTPUT_H
-#define HIPL_HIPD_OUTPUT_H
+#ifndef HIPL_LIBHIPL_OUTPUT_H
+#define HIPL_LIBHIPL_OUTPUT_H
 
 #include <netinet/in.h>
 
@@ -116,4 +116,4 @@
                       in_port_t src_port, in_port_t dst_port,
                       const void *msg, int length);
 
-#endif /* HIPL_HIPD_OUTPUT_H */
+#endif /* HIPL_LIBHIPL_OUTPUT_H */

=== renamed file 'hipd/pkt_handling.c' => 'libhipl/pkt_handling.c'
=== renamed file 'hipd/pkt_handling.h' => 'libhipl/pkt_handling.h'
--- hipd/pkt_handling.h 2012-05-12 06:54:33 +0000
+++ libhipl/pkt_handling.h      2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_PKT_HANDLING_H
-#define HIPL_HIPD_PKT_HANDLING_H
+#ifndef HIPL_LIBHIPL_PKT_HANDLING_H
+#define HIPL_LIBHIPL_PKT_HANDLING_H
 
 #include <stdint.h>
 
@@ -44,4 +44,4 @@
 
 void hip_uninit_handle_functions(void);
 
-#endif /* HIPL_HIPD_PKT_HANDLING_H */
+#endif /* HIPL_LIBHIPL_PKT_HANDLING_H */

=== renamed file 'hipd/registration.c' => 'libhipl/registration.c'
=== renamed file 'hipd/registration.h' => 'libhipl/registration.h'
--- hipd/registration.h 2012-05-12 06:54:33 +0000
+++ libhipl/registration.h      2012-05-15 09:25:24 +0000
@@ -31,8 +31,8 @@
  * @see     hiprelay.h
  */
 
-#ifndef HIPL_HIPD_REGISTRATION_H
-#define HIPL_HIPD_REGISTRATION_H
+#ifndef HIPL_LIBHIPL_REGISTRATION_H
+#define HIPL_LIBHIPL_REGISTRATION_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -80,4 +80,4 @@
 int hip_handle_reg_from(struct hip_hadb_state *entry, struct hip_common *msg);
 int hip_handle_req_user_msg(const struct hip_common *const msg);
 
-#endif /* HIPL_HIPD_REGISTRATION_H */
+#endif /* HIPL_LIBHIPL_REGISTRATION_H */

=== renamed file 'hipd/user.c' => 'libhipl/user.c'
=== renamed file 'hipd/user.h' => 'libhipl/user.h'
--- hipd/user.h 2012-05-12 06:54:33 +0000
+++ libhipl/user.h      2012-05-15 09:25:24 +0000
@@ -23,8 +23,8 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#ifndef HIPL_HIPD_USER_H
-#define HIPL_HIPD_USER_H
+#ifndef HIPL_LIBHIPL_USER_H
+#define HIPL_LIBHIPL_USER_H
 
 #include <netinet/in.h>
 
@@ -43,4 +43,4 @@
 int hip_handle_user_msg(struct hip_common *msg,
                         struct sockaddr_in6 *src);
 
-#endif /* HIPL_HIPD_USER_H */
+#endif /* HIPL_LIBHIPL_USER_H */

=== renamed file 'hipd/user_ipsec_hipd_msg.c' => 'libhipl/user_ipsec_hipd_msg.c'
=== renamed file 'hipd/user_ipsec_hipd_msg.h' => 'libhipl/user_ipsec_hipd_msg.h'
--- hipd/user_ipsec_hipd_msg.h  2012-05-12 06:54:33 +0000
+++ libhipl/user_ipsec_hipd_msg.h       2012-05-15 09:25:24 +0000
@@ -30,8 +30,8 @@
  * @brief userspace IPsec hipd <-> hipfw communication
  */
 
-#ifndef HIPL_HIPD_USER_IPSEC_HIPD_MSG_H
-#define HIPL_HIPD_USER_IPSEC_HIPD_MSG_H
+#ifndef HIPL_LIBHIPL_USER_IPSEC_HIPD_MSG_H
+#define HIPL_LIBHIPL_USER_IPSEC_HIPD_MSG_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -57,4 +57,4 @@
                                         const int dst_port);
 struct hip_common *create_flush_all_sa_msg(void);
 
-#endif /* HIPL_HIPD_USER_IPSEC_HIPD_MSG_H */
+#endif /* HIPL_LIBHIPL_USER_IPSEC_HIPD_MSG_H */

=== renamed file 'hipd/user_ipsec_sadb_api.c' => 'libhipl/user_ipsec_sadb_api.c'
=== renamed file 'hipd/user_ipsec_sadb_api.h' => 'libhipl/user_ipsec_sadb_api.h'
--- hipd/user_ipsec_sadb_api.h  2012-05-12 06:54:33 +0000
+++ libhipl/user_ipsec_sadb_api.h       2012-05-15 09:25:24 +0000
@@ -31,8 +31,8 @@
  * @brief API used by the hipd to set up and maintain userspace IPsec state
  */
 
-#ifndef HIPL_HIPD_USER_IPSEC_SADB_API_H
-#define HIPL_HIPD_USER_IPSEC_SADB_API_H
+#ifndef HIPL_LIBHIPL_USER_IPSEC_SADB_API_H
+#define HIPL_LIBHIPL_USER_IPSEC_SADB_API_H
 
 #include <stdint.h>
 #include <netinet/in.h>
@@ -52,4 +52,4 @@
 
 int hip_userspace_ipsec_setup_default_sp_prefix_pair(void);
 
-#endif /* HIPL_HIPD_USER_IPSEC_SADB_API_H */
+#endif /* HIPL_LIBHIPL_USER_IPSEC_SADB_API_H */

=== modified file 'modules/cert/hipd/cert.c'
--- modules/cert/hipd/cert.c    2012-05-12 06:54:33 +0000
+++ modules/cert/hipd/cert.c    2012-05-15 09:25:24 +0000
@@ -33,13 +33,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "hipd/hipd.h"
-#include "hipd/pkt_handling.h"
 #include "libcore/builder.h"
 #include "libcore/cert.h"
 #include "libcore/debug.h"
 #include "libcore/ife.h"
 #include "libcore/protodefs.h"
+#include "libhipl/hipd.h"
+#include "libhipl/pkt_handling.h"
 #include "modules/midauth/hipd/midauth.h"
 #include "modules/update/hipd/update.h"
 #include "cert.h"

=== modified file 'modules/heartbeat/hipd/heartbeat.c'
--- modules/heartbeat/hipd/heartbeat.c  2012-05-12 06:54:33 +0000
+++ modules/heartbeat/hipd/heartbeat.c  2012-05-15 09:25:24 +0000
@@ -65,15 +65,6 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 
-#include "hipd/close.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 "libcore/common.h"
 #include "libcore/debug.h"
 #include "libcore/icomm.h"
@@ -84,6 +75,15 @@
 #include "libcore/straddr.h"
 #include "libcore/modularization.h"
 #include "libcore/gpl/nlink.h"
+#include "libhipl/close.h"
+#include "libhipl/hadb.h"
+#include "libhipl/hip_socket.h"
+#include "libhipl/init.h"
+#include "libhipl/maintenance.h"
+#include "libhipl/nat.h"
+#include "libhipl/output.h"
+#include "libhipl/pkt_handling.h"
+#include "libhipl/user.h"
 #include "heartbeat.h"
 
 #define HIP_MAX_ICMP_PACKET 512

=== modified file 'modules/heartbeat_update/hipd/hb_update.c'
--- modules/heartbeat_update/hipd/hb_update.c   2012-05-12 06:54:33 +0000
+++ modules/heartbeat_update/hipd/hb_update.c   2012-05-15 09:25:24 +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
@@ -40,12 +40,12 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#include "hipd/hadb.h"
-#include "hipd/maintenance.h"
 #include "libcore/builder.h"
 #include "libcore/common.h"
 #include "libcore/debug.h"
 #include "libcore/protodefs.h"
+#include "libhipl/hadb.h"
+#include "libhipl/maintenance.h"
 #include "modules/update/hipd/update.h"
 #include "modules/update/hipd/update_locator.h"
 #include "hb_update.h"

=== modified file 'modules/midauth/hipd/midauth.c'
--- modules/midauth/hipd/midauth.c      2012-05-12 06:54:33 +0000
+++ modules/midauth/hipd/midauth.c      2012-05-15 09:25:24 +0000
@@ -33,8 +33,6 @@
 #include <stdint.h>
 #include <string.h>
 
-#include "hipd/hidb.h"
-#include "hipd/pkt_handling.h"
 #include "libcore/builder.h"
 #include "libcore/common.h"
 #include "libcore/ife.h"
@@ -42,6 +40,8 @@
 #include "libcore/protodefs.h"
 #include "libcore/solve.h"
 #include "libcore/state.h"
+#include "libhipl/hidb.h"
+#include "libhipl/pkt_handling.h"
 #include "modules/midauth/lib/midauth_builder.h"
 #include "modules/update/hipd/update.h"
 #include "midauth.h"

=== modified file 'modules/update/hipd/update.c'
--- modules/update/hipd/update.c        2012-05-12 06:54:33 +0000
+++ modules/update/hipd/update.c        2012-05-15 09:25:24 +0000
@@ -37,17 +37,6 @@
 #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 "libcore/builder.h"
 #include "libcore/debug.h"
 #include "libcore/hip_udp.h"
@@ -57,6 +46,17 @@
 #include "libcore/prefix.h"
 #include "libcore/state.h"
 #include "libcore/performance.h"
+#include "libhipl/cookie.h"
+#include "libhipl/hadb.h"
+#include "libhipl/hidb.h"
+#include "libhipl/hipd.h"
+#include "libhipl/input.h"
+#include "libhipl/maintenance.h"
+#include "libhipl/netdev.h"
+#include "libhipl/nsupdate.h"
+#include "libhipl/output.h"
+#include "libhipl/pkt_handling.h"
+#include "libhipl/user.h"
 #include "update_builder.h"
 #include "update_locator.h"
 #include "update_param_handling.h"

=== modified file 'modules/update/hipd/update_builder.c'
--- modules/update/hipd/update_builder.c        2012-05-12 06:54:33 +0000
+++ modules/update/hipd/update_builder.c        2012-05-15 09:25:24 +0000
@@ -34,12 +34,12 @@
 #include <string.h>
 #include <errno.h>
 
-#include "hipd/hadb.h"
-#include "hipd/netdev.h"
 #include "libcore/builder.h"
 #include "libcore/ife.h"
 #include "libcore/list.h"
 #include "libcore/prefix.h"
+#include "libhipl/hadb.h"
+#include "libhipl/netdev.h"
 #include "update_builder.h"
 
 enum hip_locator_traffic_type {

=== modified file 'modules/update/hipd/update_locator.c'
--- modules/update/hipd/update_locator.c        2012-05-12 06:54:33 +0000
+++ modules/update/hipd/update_locator.c        2012-05-15 09:25:24 +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
@@ -34,11 +34,11 @@
 #include <string.h>
 #include <openssl/lhash.h>
 
-#include "hipd/maintenance.h"
 #include "libcore/builder.h"
 #include "libcore/debug.h"
 #include "libcore/ife.h"
 #include "libcore/protodefs.h"
+#include "libhipl/maintenance.h"
 #include "update_builder.h"
 #include "update.h"
 #include "update_locator.h"

=== added file 'test/check_libhipl.c'
--- test/check_libhipl.c        1970-01-01 00:00:00 +0000
+++ test/check_libhipl.c        2012-05-15 09:25:24 +0000
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 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 libhipl on localhost (see doc/HACKING on unit tests).
+ */
+
+#include <arpa/inet.h>
+#include <check.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/select.h>
+#include <unistd.h>
+
+#include "libhipl/hidb.h"
+#include "libhipl/lhipl.h"
+
+#ifndef max
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+#define LO_IP    "127.0.0.1"
+#define TEST_MSG "Hello Sailor!"
+#define SEND_PORT 22345
+#define RECV_PORT 22300
+
+static struct in6_addr    lo_hit;
+static char               peername[HIPL_MAX_PEERNAME];
+static struct sockaddr_in send_addr;
+static struct sockaddr_in recv_addr;
+
+static int sender;
+static int receiver;
+
+static void test_libhipl_lo_init(int proto)
+{
+    if (hipl_lib_init_all(HIPL_LIB_LOG_NONE) < 0) {
+        fail("hipl_lib_init_all");
+    }
+
+    fail_if(hip_get_default_hit(&lo_hit) < 0, "Failed to load local hit");
+    inet_ntop(AF_INET6, &lo_hit, peername, HIPL_MAX_PEERNAME);
+    fail_if(hipl_add_peer_info(peername, LO_IP) < 0,
+            "Failed to insert peer info");
+
+    send_addr.sin_family = AF_INET;
+    inet_pton(AF_INET, LO_IP, &send_addr.sin_addr);
+    send_addr.sin_port   = htons(SEND_PORT);
+    recv_addr.sin_family = AF_INET;
+    inet_pton(AF_INET, LO_IP, &recv_addr.sin_addr);
+    recv_addr.sin_port = htons(RECV_PORT);
+
+    if (proto == IPPROTO_TCP) {
+        sender   = hipl_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+        receiver = hipl_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    } else if (proto == IPPROTO_UDP) {
+        sender   = hipl_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+        receiver = hipl_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+    }
+    fail_if(sender <= 0 || receiver <= 0);
+
+    if (hipl_bind(sender, (struct sockaddr *) &send_addr,
+                  sizeof(send_addr)) < 0) {
+        fail("hipl_bind() for sender");
+    }
+    if (hipl_bind(receiver, (struct sockaddr *) &recv_addr,
+                  sizeof(recv_addr)) < 0) {
+        fail("hipl_bind() for receiver");
+    }
+
+    hipl_lib_set_bex_feedback(true);
+}
+
+static void test_libhipl_lo_main_loop(int send_hid, int recv_hid)
+{
+    char     peer[HIPL_MAX_PEERNAME];
+    uint16_t peer_port;
+    char     buf[1024];
+    fd_set   rset;
+    int      ret   = 0;
+    int      maxfd = max(hipl_lib_get_sockfd(send_hid),
+                         hipl_lib_get_sockfd(recv_hid));
+
+    //trigger BEX
+    ret = hipl_sendto(send_hid, TEST_MSG, strlen(TEST_MSG), 0,
+                      peername, RECV_PORT);
+    fail_if(ret != -EWAITBEX);
+
+    while (1) {
+        FD_ZERO(&rset);
+        FD_SET(hipl_lib_get_sockfd(send_hid), &rset);
+        FD_SET(hipl_lib_get_sockfd(recv_hid), &rset);
+        fail_if(select(maxfd + 1, &rset, NULL, NULL, NULL) < 0);
+
+        if (FD_ISSET(hipl_lib_get_sockfd(recv_hid), &rset)) {
+            ret = hipl_recvfrom(recv_hid, buf, 1024, 0, peer, &peer_port);
+            fail_if(ret < 0 && ret != -EWAITBEX && ret != -EBEXESTABLISHED);
+            fail_if(ret > 0 && ret != strlen(TEST_MSG));
+
+            if (ret == strlen(TEST_MSG)) {
+                buf[ret] = '\0';
+                fail_if(strcmp(buf, TEST_MSG) != 0);
+                fail_if(strcmp(peername, peer) != 0);
+                fail_if(peer_port != SEND_PORT);
+                // Finish test
+                break;
+            }
+        }
+        if (FD_ISSET(hipl_lib_get_sockfd(send_hid), &rset)) {
+            ret = hipl_sendto(send_hid, TEST_MSG, strlen(TEST_MSG), 0,
+                              peername, RECV_PORT);
+            fail_if(ret < 0 && ret != -EWAITBEX && ret != -EBEXESTABLISHED);
+            fail_if(ret > 0 && ret != strlen(TEST_MSG));
+        }
+    }
+
+    hipl_close(send_hid);
+    hipl_close(recv_hid);
+}
+
+START_TEST(test_libhipl_lo_tcp)
+{
+    fd_set wset, rset;
+    int    maxfd, recv_slave = 0;
+
+    test_libhipl_lo_init(IPPROTO_TCP);
+
+    // Setup TCP connection
+    maxfd = max(hipl_lib_get_sockfd(sender), hipl_lib_get_sockfd(receiver));
+    if (hipl_listen(receiver, 5) < 0) {
+        fail("hipl_listen()");
+    }
+    fail_if(hipl_lib_set_nonblock(sender, true) < 0);
+    fail_if(hipl_lib_set_nonblock(receiver, true) < 0);
+    hipl_accept(receiver);
+    hipl_connect(sender, peername, RECV_PORT);
+    while (recv_slave <= 0) {
+        FD_ZERO(&wset);
+        FD_ZERO(&rset);
+        FD_SET(hipl_lib_get_sockfd(sender), &wset);
+        FD_SET(hipl_lib_get_sockfd(receiver), &rset);
+        fail_if(select(maxfd + 1, &rset, &wset, NULL, NULL) < 0);
+        if (FD_ISSET(hipl_lib_get_sockfd(receiver), &rset)) {
+            if ((recv_slave = hipl_accept(receiver)) < 0) {
+                fail("hipl_accept(), %s", strerror(errno));
+            }
+        }
+        if (FD_ISSET(hipl_lib_get_sockfd(sender), &wset)) {
+            if (hipl_connect(sender, peername, RECV_PORT) < 0
+                && errno != EINPROGRESS && errno != EISCONN) {
+                fail("hipl_connect() %s", strerror(errno));
+            }
+        }
+    }
+    fail_if(hipl_connect(sender, peername, RECV_PORT) < 0 && errno != EISCONN);
+    fail_if(hipl_lib_set_nonblock(sender, false) < 0);
+
+    // Process base exchange and user data
+    test_libhipl_lo_main_loop(sender, recv_slave);
+    hipl_close(receiver);
+}
+END_TEST
+
+START_TEST(test_libhipl_lo_udp)
+{
+    test_libhipl_lo_init(IPPROTO_UDP);
+    test_libhipl_lo_main_loop(sender, receiver);
+}
+END_TEST
+
+static Suite *hipnc_suite(void)
+{
+    Suite *s = suite_create("libhipl");
+
+    TCase *tc_libhipl_lo = tcase_create("libhipl_lo");
+    tcase_add_test(tc_libhipl_lo, test_libhipl_lo_udp);
+    tcase_add_test(tc_libhipl_lo, test_libhipl_lo_tcp);
+    suite_add_tcase(s, tc_libhipl_lo);
+
+    return s;
+}
+
+int main(void)
+{
+    int      number_failed;
+    Suite   *s  = hipnc_suite();
+    SRunner *sr = srunner_create(NULL);
+
+    srunner_add_suite(sr, 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-05-15 09:25:24 +0000
@@ -26,7 +26,7 @@
 #include <check.h>
 #include <stdlib.h>
 
-#include "hipd/lsidb.c"
+#include "libhipl/lsidb.c"
 #include "test_suites.h"
 
 START_TEST(test_lsidb_allocate_lsi_valid)

Other related posts: