You have been requested to review the proposed merge of lp:~hipl-core/hipl/libhip into lp:hipl. For more details, see: https://code.launchpad.net/~hipl-core/hipl/libhip/+merge/97589 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/97589 Your team HIPL core team is requested to review the proposed merge of lp:~hipl-core/hipl/libhip into lp:hipl.
=== modified file '.bzrignore' --- .bzrignore 2012-03-13 15:00:27 +0000 +++ .bzrignore 2012-03-15 08:58:36 +0000 @@ -55,6 +55,7 @@ test/check_hipfw test/check_lib_core test/check_modules_midauth +test/hipnetcat test/performance/auth_performance test/performance/dh_performance test/performance/fw_port_bindings_performance === modified file 'Makefile.am' --- Makefile.am 2012-03-13 15:00:27 +0000 +++ Makefile.am 2012-03-15 08:58:36 +0000 @@ -34,7 +34,7 @@ EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/tools/,*.cfg *.pl *.sh *.xml)) EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/hipfw/,*.cfg)) EXTRA_DIST += $(HIPL_HEADER_LIST) -EXTRA_DIST += hipd/pisa.c hipfw/pisa.c hipfw/pisa_cert.c +EXTRA_DIST += lib/hipl/pisa.c hipfw/pisa.c hipfw/pisa_cert.c ### superuser programs ### @@ -48,6 +48,7 @@ ### test programs ### noinst_PROGRAMS = test/certteststub \ + test/hipnetcat \ test/performance/auth_performance \ test/performance/fw_port_bindings_performance \ test/performance/hc_performance @@ -59,15 +60,19 @@ ### libraries ### lib_LTLIBRARIES = lib/core/libhipcore.la +lib_LTLIBRARIES += lib/hipl/libhipl.la ### tests ### if HIP_UNITTESTS TESTS = test/check_hipd \ test/check_hipfw \ + test/check_hipnetcat \ test/check_lib_core + check_PROGRAMS = test/check_hipd \ test/check_hipfw \ + test/check_hipnetcat \ test/check_lib_core endif @@ -75,6 +80,7 @@ ### source declarations ### test_certteststub_SOURCES = test/certteststub.c +test_hipnetcat_SOURCES = test/hipnetcat.c test_performance_auth_performance_SOURCES = test/performance/auth_performance.c test_performance_dh_performance_SOURCES = test/performance/dh_performance.c test_performance_fw_port_bindings_performance_SOURCES = hipfw/file_buffer.c \ @@ -85,46 +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/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 \ @@ -199,6 +166,48 @@ lib_core_libhipcore_la_SOURCES += lib/core/performance.c endif +lib_hipl_libhipl_la_sources = lib/hipl/accessor.c \ + lib/hipl/cert.c \ + lib/hipl/close.c \ + lib/hipl/configfilereader.c \ + lib/hipl/cookie.c \ + lib/hipl/dh.c \ + lib/hipl/esp_prot_anchordb.c \ + lib/hipl/esp_prot_hipd_msg.c \ + lib/hipl/esp_prot_light_update.c \ + lib/hipl/hadb.c \ + lib/hipl/hidb.c \ + lib/hipl/hip_socket.c \ + lib/hipl/hipd.c \ + lib/hipl/hiprelay.c \ + lib/hipl/hit_to_ip.c \ + lib/hipl/init.c \ + lib/hipl/input.c \ + lib/hipl/keymat.c \ + lib/hipl/lsidb.c \ + lib/hipl/maintenance.c \ + lib/hipl/nat.c \ + lib/hipl/netdev.c \ + lib/hipl/nsupdate.c \ + lib/hipl/opp_mode.c \ + lib/hipl/output.c \ + lib/hipl/pkt_handling.c \ + lib/hipl/registration.c \ + lib/hipl/socket_wrapper.c \ + lib/hipl/user.c \ + lib/hipl/user_ipsec_hipd_msg.c \ + lib/hipl/user_ipsec_sadb_api.c \ + modules/heartbeat/hipd/heartbeat.c \ + modules/heartbeat_update/hipd/hb_update.c \ + modules/update/hipd/update.c \ + modules/update/hipd/update_builder.c \ + modules/update/hipd/update_locator.c \ + modules/update/hipd/update_param_handling.c + +lib_hipl_libhipl_la_SOURCES = $(lib_hipl_libhipl_la_sources) \ + modules/midauth/hipd/midauth.c + +lib_hipl_libhipl_la_LIBADD = lib/core/libhipcore.la test_check_hipd_SOURCES = test/check_hipd.c \ test/hipd/lsidb.c \ @@ -216,10 +225,13 @@ test/hipfw/rewrite.c \ $(hipfw_hipfw_sources) +test_check_hipnetcat_SOURCES = test/check_hipnetcat.c + test_check_lib_core_SOURCES = test/check_lib_core.c \ test/lib/core/crypto.c \ test/lib/core/hit.c \ test/lib/core/hostid.c \ + test/lib/core/linkedlist.c \ test/lib/core/solve.c \ test/lib/core/straddr.c \ test/lib/core/gpl/checksum.c \ @@ -229,18 +241,21 @@ ### static library dependencies ### -hipd_hipd_LDADD = lib/core/libhipcore.la +hipd_hipd_LDADD = lib/hipl/libhipl.la hipfw_hipfw_LDADD = lib/core/libhipcore.la -test_check_hipd_LDADD = lib/core/libhipcore.la +test_check_hipd_LDADD = lib/hipl/libhipl.la test_check_hipfw_LDADD = lib/core/libhipcore.la +test_check_hipnetcat_LDADD = lib/hipl/libhipl.la test_check_lib_core_LDADD = lib/core/libhipcore.la test_certteststub_LDADD = lib/core/libhipcore.la +test_hipnetcat_LDADD = lib/hipl/libhipl.la test_performance_auth_performance_LDADD = lib/core/libhipcore.la test_performance_dh_performance_LDADD = lib/core/libhipcore.la test_performance_fw_port_bindings_performance_LDADD = lib/core/libhipcore.la test_performance_hc_performance_LDADD = lib/core/libhipcore.la tools_hipconf_LDADD = lib/core/libhipcore.la + ### dynamic library dependencies ### test_check_hipd_LDFLAGS = -ldl -Wl,-z,muldefs === modified file 'doc/HOWTO.xml.in' --- doc/HOWTO.xml.in 2012-01-25 10:44:48 +0000 +++ doc/HOWTO.xml.in 2012-03-15 08:58:36 +0000 @@ -764,6 +764,80 @@ </para> </section> <!-- handover --> + <section id="ch_hipnetcat"> + <title>Test HIPL with the hipnetcat program</title> + <para> + Hipnetcat can be used to test the base exchange functionality of HIPL. + This section explains its usage in detail. + </para> + <para> + Hipnetcat program takes similar parameters as the normal netcat program. + In order to check the functionality of the base exchange, a hipnetcat + server and a hipnetcat client are required. + </para> + <para> + The usage of hipnetcat is shown as follow: + <programlisting> + Usage: hipnetcat [-hlt] [-p source_port] [-s source_ip_address] + [-d dest_port] [peer_identifier[s]] + + -h: help + -l: Listening mode, hip netcat acts as the server side. + -t: Using TCP as transportation protocol, otherwise UDP will be used. + </programlisting> + The last parameter peer_identifiers supports multiple peer indentities + with different types. The types includes: HIT, IP address and host name. + host name. + </para> + + <itemizedlist> + <listitem><para> + Example 1: localhost hipnetcat connection via TCP. The server listens on + 127.0.0.1:22300 and the client connects from 127.0.0.1:22345 with HIT + 2001:1c:809e:244a:c33:78fb:45e3:d132. + <programlisting> + The server: + hipnetcat -l -t -s 127.0.0.1 -p 22300 + + The client: + hipnetcat -t -s 127.0.0.1 -p 22345 -d 22300 \ + 127.0.0.1 2001:1c:809e:244a:c33:78fb:45e3:d132 + </programlisting> + </para></listitem> + <listitem><para> + Example 2: localhost hipnetcat connection via UDP. The server listens on + 127.0.0.1:22300 and the client connects from 127.0.0.1:22345 with HIT + 2001:1c:809e:244a:c33:78fb:45e3:d132. + <programlisting> + The server: + hipnetcat -l -s 127.0.0.1 -p 22300 + + The client: + hipnetcat -s 127.0.0.1 -p 22345 -d 22300 \ + 127.0.0.1 2001:1c:809e:244a:c33:78fb:45e3:d132 + </programlisting> + </para></listitem> + </itemizedlist> + + <para> + Example 2: localhost hipnetcat connection via UDP. The server listens on + 127.0.0.1:22300 and the client connects from 127.0.0.1:22345 with HIT + 2001:1c:809e:244a:c33:78fb:45e3:d132. + <programlisting> + The server: + hipnetcat -l -s 127.0.0.1 -p 22300 + + The client: + hipnetcat -s 127.0.0.1 -p 22345 -d 22300 \ + 127.0.0.1 2001:1c:809e:244a:c33:78fb:45e3:d132 + </programlisting> + </para> + + <para> + If the hipnetcat execution successes, the server will receive one message + from the client, and then both sides exit without any error. + </para> + </section> <!-- hipnetcat --> </chapter> <!-- ch_prebuilt --> <chapter id="ch_how_to_use_hip"> @@ -2584,6 +2658,68 @@ </section> + <section id="ch_libhipl_usage"> + <title>The Libhipl Extension</title> + + <para> + Libhipl provides HIP functionality as a library for upper layer + applications and it does not require the presence of normal HIPL daemon. + Instead, the HIP control messages are transmitted on top of TCP/UDP. + From the applications' point of view, they get similar API set as normal + socket API. This section describes the usage of libhipl API. + </para> + + <para> + Libhipl API set is mainly located in + <emphasis>"socket_wrapper.h"</emphasis>. The initialization function: + <emphasis>libhipd_init(void)</emphasis> is declared in + <emphasis>"init.h"</emphasis> + </para> + + <para> + Libhipl requires user to initialize it before calling any socket wrapper + function which starts with "hip_" prefix. To initialize libhipl, call the + <emphasis>libhipd_init</emphasis> function in "init.h" + </para> + + <para> + Once the libhipl initialization finishes, user can use functions provided + by socket_wrapper.h and it works like normal socket function except that: + <itemizedlist> + <listitem> + <para> + In <emphasis>hip_sendto</emphasis> and + <emphasis>hip_connect</emphasis>, the destination address should be a + HIT, not an IP address. The destination port should also be included + in the same structure. + </para> + </listitem> + <listitem> + <para> + In <emphasis>hip_recvfrom</emphasis>, the remote peer address should + also be a HIT, not an IP address.The peer's port should also be + included in the same structure. + </para> + </listitem> + <listitem> + <para> + In <emphasis>hip_accept</emphasis>, after a new peer is accepted, the + <emphasis>addr</emphasis> parameter returns a structure which + contains peer's HIT and port (NOT IP). The + <emphasis>addr_len</emphasis> parameter returns the length of this + structure. The user then can use this structure for further function + calls such as <emphasis>hip_recvfrom</emphasis>. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + For more detail usage of the libhipl, please refer the hipnetcat program + in the <emphasis>test</emphasis> directory. + </para> + + </section> <!-- ch_libhipl_usage --> </chapter> <!-- ch_exp_extensions --> </book> === modified file 'hipd/main.c' --- hipd/main.c 2011-11-03 09:21:12 +0000 +++ hipd/main.c 2012-03-15 08:58:36 +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 @@ -32,10 +32,9 @@ #include <unistd.h> #include <sys/types.h> - -#include "hipd/hipd.h" -#include "init.h" #include "lib/core/debug.h" +#include "lib/hipl/hipd.h" +#include "lib/hipl/init.h" /** === modified file 'hipfw/hipfw.c' --- hipfw/hipfw.c 2012-03-08 12:28:00 +0000 +++ hipfw/hipfw.c 2012-03-15 08:58:36 +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 @@ -75,7 +75,7 @@ #include "lib/core/performance.h" #include "lib/core/prefix.h" #include "lib/core/util.h" -#include "hipd/hipd.h" +#include "lib/hipl/hipd.h" #include "config.h" #include "cache.h" #include "common_types.h" === modified file 'lib/core/crypto.h' --- lib/core/crypto.h 2011-11-25 17:56:24 +0000 +++ lib/core/crypto.h 2012-03-15 08:58:36 +0000 @@ -65,9 +65,9 @@ #define RSA_KEY_DEFAULT_BITS 1024 #define ECDSA_DEFAULT_CURVE NID_X9_62_prime256v1 - +#define DEFAULT_HOST_RSA_KEY_FILE_NAME "hip_host_rsa_key" #define DEFAULT_HOST_DSA_KEY_FILE_BASE HIPL_SYSCONFDIR "/hip_host_dsa_key" -#define DEFAULT_HOST_RSA_KEY_FILE_BASE HIPL_SYSCONFDIR "/hip_host_rsa_key" +#define DEFAULT_HOST_RSA_KEY_FILE_BASE HIPL_SYSCONFDIR "/" DEFAULT_HOST_RSA_KEY_FILE_NAME #define DEFAULT_HOST_ECDSA_KEY_FILE_BASE HIPL_SYSCONFDIR "/hip_host_ecdsa_key" #define DEFAULT_PUB_FILE_SUFFIX ".pub" === modified file 'lib/core/hostid.c' --- lib/core/hostid.c 2012-03-01 14:26:43 +0000 +++ lib/core/hostid.c 2012-03-15 08:58:36 +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 direcory for path: %s\n", hi_file); + goto out_err; + } if (!strcmp(hi_fmt, "dsa")) { dsa_key = create_dsa_key(dsa_key_bits); HIP_IFEL(!dsa_key, -EINVAL, "Creation of DSA key failed.\n"); - if ((err = save_dsa_private_key(dsa_filenamebase, dsa_key))) { + if ((err = save_dsa_private_key(hi_file, dsa_key))) { HIP_ERROR("Saving of DSA key failed.\n"); goto out_err; } @@ -756,7 +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); === modified file 'lib/core/linkedlist.c' --- lib/core/linkedlist.c 2011-08-15 14:11:56 +0000 +++ lib/core/linkedlist.c 2012-03-15 08:58:36 +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 @@ -298,6 +298,42 @@ } /** + * Deletes the first node from list which contains the payload pointer ptr. + * If there is no match, does nothing. + * + * @param linkedlist list to remove an element from + * @param ptr pointer by which to identify the node + * @param free_element a function pointer to a function for freeing the memory + * allocated for an element at a node or NULL if the element + * itself is not to be freed. + */ +void hip_ll_del_by_ptr(struct hip_ll *const linkedlist, const void *const ptr, + free_elem_fn free_element) +{ + if (!linkedlist || linkedlist->element_count == 0) { + return; + } + + struct hip_ll_node **storage = &linkedlist->head; + + while (*storage) { + struct hip_ll_node *const node = *storage; + + if (node->ptr == ptr) { + *storage = node->next; + linkedlist->element_count--; + if (free_element != NULL) { + free_element(node->ptr); + } + free(node); + return; + } else { + storage = &node->next; + } + } +} + +/** * Deletes the first node from a linked list. If there are no nodes in the list, * no action will be taken. If @c free_element is non-NULL the memory allocated * for the element itself is also freed. When @c free_element is non-NULL, make === modified file 'lib/core/linkedlist.h' --- lib/core/linkedlist.h 2011-11-25 17:56:24 +0000 +++ lib/core/linkedlist.h 2012-03-15 08:58:36 +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 @@ -69,6 +69,8 @@ void *hip_ll_del(struct hip_ll *linkedlist, const unsigned int index, free_elem_fn free_element); void *hip_ll_del_first(struct hip_ll *linkedlist, free_elem_fn free_element); +void hip_ll_del_by_ptr(struct hip_ll *const linkedlist, const void *const ptr, + free_elem_fn free_element); void *hip_ll_get(const struct hip_ll *const linkedlist, const unsigned int index); const struct hip_ll_node *hip_ll_iterate(const struct hip_ll *const linkedlist, const struct hip_ll_node *const current); === modified file 'lib/core/message.c' --- lib/core/message.c 2012-03-01 14:06:24 +0000 +++ lib/core/message.c 2012-03-15 08:58:36 +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 @@ -686,6 +686,84 @@ } /** + * Read a control message over TCP socket and save it to @c hip_packet_context + * for future processing. The source address, source port, destination address + * and destination port in the @c ctx are set based on the information from the + * input socket descriptor. Finally, this method eliminates the HIP padding and + * verify if the header of the new message confirms to the standard HIP header. + * + * @param sockfd a socket file descriptor + * @param ctx a pointer to the packet context + * @return -1 in case of an error, 0 otherwise. Socket related + * errors have been set to @c errno + */ +int hip_read_control_msg_tcp(const int sockfd, + struct hip_packet_context *const ctx) +{ + int len, is_ipv4; + struct sockaddr dst_addr = { 0 }; + struct sockaddr src_addr = { 0 }; + struct sockaddr_in *saddr4; + struct sockaddr_in6 *saddr6; + socklen_t saddr_len = sizeof(struct sockaddr); + + len = recv(sockfd, ctx->input_msg, HIP_MAX_PACKET, 0); + if (len < 0) { + HIP_PERROR("recvfrom(): "); + return -1; + } + + /* Get peer address */ + if (getpeername(sockfd, &src_addr, &saddr_len) < 0) { + HIP_PERROR("getpeername(): "); + return -1; + } + + is_ipv4 = (src_addr.sa_family == AF_INET); + if (is_ipv4) { + saddr4 = (struct sockaddr_in *) &src_addr; + IPV4_TO_IPV6_MAP(&saddr4->sin_addr, &ctx->src_addr); + ctx->msg_ports.src_port = ntohs(saddr4->sin_port); + } else { + saddr6 = (struct sockaddr_in6 *) &src_addr; + ctx->dst_addr = saddr6->sin6_addr; + ctx->msg_ports.src_port = ntohs(saddr6->sin6_port); + } + + /* Get local (bound) address */ + if (getsockname(sockfd, &dst_addr, &saddr_len) < 0) { + HIP_PERROR("getsockname(): "); + return -1; + } + if (is_ipv4) { + saddr4 = (struct sockaddr_in *) &dst_addr; + IPV4_TO_IPV6_MAP(&saddr4->sin_addr, &ctx->dst_addr); + ctx->msg_ports.dst_port = saddr4->sin_port; + } else { + saddr6 = (struct sockaddr_in6 *) &dst_addr; + memcpy(&ctx->dst_addr, &saddr6->sin6_addr, sizeof(struct in6_addr)); + ctx->msg_ports.dst_port = saddr6->sin6_port; + } + + HIP_DEBUG("Received packet from TCP socket:\n"); + HIP_DEBUG_IN6ADDR("src", &ctx->src_addr); + HIP_DEBUG_IN6ADDR("dst", &ctx->dst_addr); + + memmove(ctx->input_msg, + ((char *) ctx->input_msg) + HIP_UDP_ZERO_BYTES_LEN, + HIP_MAX_PACKET - HIP_UDP_ZERO_BYTES_LEN); + len -= HIP_UDP_ZERO_BYTES_LEN; + + if (hip_verify_network_header(ctx->input_msg, &src_addr, + &dst_addr, len) < 0) { + HIP_ERROR("verifying network header failed\n"); + return -1; + } + + return 0; +} + +/** * Read an IPv6 control message. * * @param sockfd a socket file descriptor === modified file 'lib/core/message.h' --- lib/core/message.h 2011-11-25 17:56:24 +0000 +++ lib/core/message.h 2012-03-15 08:58:36 +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 @@ -46,6 +46,8 @@ int hip_send_recv_daemon_info(struct hip_common *msg, int send_only, int opt_socket); +int hip_read_control_msg_tcp(const int sockfd, + struct hip_packet_context *const ctx); int hip_send_recv_firewall_info(struct hip_common *const msg); #endif /* HIPL_LIB_CORE_MESSAGE_H */ === added directory 'lib/hipl' === renamed file 'hipd/accessor.c' => 'lib/hipl/accessor.c' === renamed file 'hipd/accessor.h' => 'lib/hipl/accessor.h' === renamed file 'hipd/cert.c' => 'lib/hipl/cert.c' === renamed file 'hipd/cert.h' => 'lib/hipl/cert.h' === renamed file 'hipd/close.c' => 'lib/hipl/close.c' === renamed file 'hipd/close.h' => 'lib/hipl/close.h' === renamed file 'hipd/configfilereader.c' => 'lib/hipl/configfilereader.c' === renamed file 'hipd/configfilereader.h' => 'lib/hipl/configfilereader.h' === renamed file 'hipd/cookie.c' => 'lib/hipl/cookie.c' === renamed file 'hipd/cookie.h' => 'lib/hipl/cookie.h' === renamed file 'hipd/dh.c' => 'lib/hipl/dh.c' === renamed file 'hipd/dh.h' => 'lib/hipl/dh.h' === renamed file 'hipd/esp_prot_anchordb.c' => 'lib/hipl/esp_prot_anchordb.c' === renamed file 'hipd/esp_prot_anchordb.h' => 'lib/hipl/esp_prot_anchordb.h' === renamed file 'hipd/esp_prot_hipd_msg.c' => 'lib/hipl/esp_prot_hipd_msg.c' === renamed file 'hipd/esp_prot_hipd_msg.h' => 'lib/hipl/esp_prot_hipd_msg.h' === renamed file 'hipd/esp_prot_light_update.c' => 'lib/hipl/esp_prot_light_update.c' === renamed file 'hipd/esp_prot_light_update.h' => 'lib/hipl/esp_prot_light_update.h' === renamed file 'hipd/hadb.c' => 'lib/hipl/hadb.c' --- hipd/hadb.c 2012-03-09 13:38:34 +0000 +++ lib/hipl/hadb.c 2012-03-15 08:58:36 +0000 @@ -614,9 +614,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 to 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)) { @@ -1457,6 +1463,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); @@ -1526,6 +1536,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' => 'lib/hipl/hadb.h' === renamed file 'hipd/hidb.c' => 'lib/hipl/hidb.c' --- hipd/hidb.c 2012-03-08 12:28:00 +0000 +++ lib/hipl/hidb.c 2012-03-15 08:58:36 +0000 @@ -599,13 +599,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' => 'lib/hipl/hidb.h' === renamed file 'hipd/hip_socket.c' => 'lib/hipl/hip_socket.c' === renamed file 'hipd/hip_socket.h' => 'lib/hipl/hip_socket.h' === renamed file 'hipd/hipd.c' => 'lib/hipl/hipd.c' --- hipd/hipd.c 2012-02-01 15:55:13 +0000 +++ lib/hipl/hipd.c 2012-03-15 08:58:36 +0000 @@ -58,14 +58,14 @@ #include "lib/core/protodefs.h" #include "lib/core/straddr.h" #include "lib/core/util.h" -#include "config.h" #include "accessor.h" -#include "hadb.h" #include "hip_socket.h" #include "init.h" #include "maintenance.h" #include "netdev.h" +#include "hadb.h" #include "hipd.h" +#include "config.h" /** For receiving netlink IPsec events (acquire, expire, etc) */ === renamed file 'hipd/hipd.h' => 'lib/hipl/hipd.h' --- hipd/hipd.h 2012-03-09 13:38:34 +0000 +++ lib/hipl/hipd.h 2012-03-15 08:58:36 +0000 @@ -27,6 +27,7 @@ #define HIPL_HIPD_HIPD_H #include <netdb.h> +#include <stdbool.h> #include <stdint.h> #include <netinet/in.h> #include <sys/types.h> @@ -81,4 +82,8 @@ int hipd_parse_cmdline_opts(int argc, char *argv[], uint64_t * flags); int hipd_main(uint64_t flags); +/* libhip_mode accessor */ +bool hipl_is_libhip_mode(void); +void hipl_set_libhip_mode(void); + #endif /* HIPL_HIPD_HIPD_H */ === renamed file 'hipd/hiprelay.c' => 'lib/hipl/hiprelay.c' === renamed file 'hipd/hiprelay.h' => 'lib/hipl/hiprelay.h' === renamed file 'hipd/hit_to_ip.c' => 'lib/hipl/hit_to_ip.c' === renamed file 'hipd/hit_to_ip.h' => 'lib/hipl/hit_to_ip.h' === renamed file 'hipd/init.c' => 'lib/hipl/init.c' --- hipd/init.c 2012-03-01 14:06:24 +0000 +++ lib/hipl/init.c 2012-03-15 08:58:36 +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> @@ -74,6 +76,7 @@ #include "accessor.h" #include "close.h" #include "dh.h" +#include "esp_prot_hipd_msg.h" #include "esp_prot_light_update.h" #include "hadb.h" #include "hidb.h" @@ -88,9 +91,9 @@ #include "output.h" #include "pkt_handling.h" #include "registration.h" +#include "socket_wrapper.h" #include "user.h" #include "init.h" -#include "hipd/esp_prot_hipd_msg.h" /** @@ -118,6 +121,31 @@ #endif /** end ICMPV6_FILTER related stuff */ +#define HIP_USER_DIR ".hipl/" + +/* 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 HIPL is running on library mode. + * @return 1 on library mode, 0 otherwise. + */ +bool hipl_is_libhip_mode() +{ + return hipd_library_mode; +} + +/** + * Set HIPL to run on library mode. + */ +void hipl_set_libhip_mode() +{ + 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 +551,208 @@ 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_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2_in_i2_sent, 21000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_send_r2, 50000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_check_i2, 20000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_handle_i2, 30000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_setup_ipsec_sa, 30500); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_create_r2, 40000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_add_rvs_reg_from, 41000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_hmac2_and_sign, 42000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_add_rvs_relay_to, 43000); + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_send_r2, 50000); + + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_check_r1, 20000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_r1, 30000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_update_retransmissions, 30500); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_build_esp_info, 31000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_build_solution, 32000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_diffie_hellman, 33000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &esp_prot_r1_handle_transforms, 34000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_create_i2, 40000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_add_signed_echo_response, 41000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_mac_and_sign_handler, 42000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_add_unsigned_echo_response, 43000); + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_send_i2, 50000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_check_r1, 20000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_r1, 30000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30500); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_build_esp_info, 31000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_build_solution, 32000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_diffie_hellman, 33000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &esp_prot_r1_handle_transforms, 34000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_create_i2, 40000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_add_signed_echo_response, 41000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_mac_and_sign_handler, 42000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_add_unsigned_echo_response, 43000); + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_send_i2, 50000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_check_r1, 20000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_r1, 30000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_update_retransmissions, 30500); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_build_esp_info, 31000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_build_solution, 32000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_diffie_hellman, 33000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &esp_prot_r1_handle_transforms, 34000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_create_i2, 40000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_add_signed_echo_response, 41000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_mac_and_sign_handler, 42000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_add_unsigned_echo_response, 43000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_send_i2, 50000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_check_r1, 20000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_r1, 30000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_update_retransmissions, 30500); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_build_esp_info, 31000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_build_solution, 32000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_diffie_hellman, 33000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &esp_prot_r1_handle_transforms, 34000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_create_i2, 40000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_add_signed_echo_response, 41000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_mac_and_sign_handler, 42000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_add_unsigned_echo_response, 43000); + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_send_i2, 50000); + + hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_check_r2, 20000); + hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_handle_r2, 30000); + hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30250); + //hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_setup_ipsec_sa, 30500); + + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, &hip_check_notify, 20000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, &hip_handle_notify, 30000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I2_SENT, &hip_check_notify, 20000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I2_SENT, &hip_handle_notify, 30000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_R2_SENT, &hip_check_notify, 20000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_R2_SENT, &hip_handle_notify, 30000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_ESTABLISHED, &hip_check_notify, 20000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_ESTABLISHED, &hip_handle_notify, 30000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSING, &hip_check_notify, 20000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSING, &hip_handle_notify, 30000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, &hip_check_notify, 20000); + hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, &hip_handle_notify, 30000); + + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_check_packet, 20000); + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 25000); + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_create_response, 30000); + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_send_response, 40000); + + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_check_packet, 20000); + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_update_retransmissions, 25000); + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_create_response, 30000); + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_send_response, 40000); + + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_close_ack_check_packet, 20000); + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_update_retransmissions, 25000); + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_close_ack_handle_packet, 30000); + + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_close_ack_check_packet, 20000); + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_update_retransmissions, 25000); + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_close_ack_handle_packet, 30000); + + hip_register_handle_function(HIP_LUPDATE, HIP_STATE_ESTABLISHED, &esp_prot_handle_light_update, 20000); + hip_register_handle_function(HIP_LUPDATE, HIP_STATE_R2_SENT, &esp_prot_handle_light_update, 20000); + + return 0; +} + static int init_handle_functions(void) { int err = 0; @@ -1090,6 +1320,71 @@ return err; } +int hipl_lib_init(void) +{ + 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; +#ifdef CONFIG_HIP_FIREWALL + hipfw_status = 0; +#endif + + 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; + } + + /* +2 because we need a slash after pwd and a NULL for termination */ + keypath_len = strlen(pwd->pw_dir) + + strlen(HIP_USER_DIR) + + strlen(DEFAULT_HOST_RSA_KEY_FILE_NAME) + + strlen(DEFAULT_PUB_HI_FILE_NAME_SUFFIX) + 2; + if ((key_path = malloc(keypath_len)) == NULL) { + HIP_ERROR("malloc() failed\n"); + return -1; + } + + HIP_IFEL(snprintf(key_path, keypath_len, "%s/%s%s%s", pwd->pw_dir, + HIP_USER_DIR, + DEFAULT_HOST_RSA_KEY_FILE_NAME, + DEFAULT_PUB_HI_FILE_NAME_SUFFIX) < 0, + -1, "snprintf() failed"); + + HIP_DEBUG("Using key: %s\n", key_path); + HIP_IFEL(!(msg = hip_msg_alloc()), -1, "hip_msg_alloc()"); + if (hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa", + key_path, 0, 0, 0)) { + free(msg); + HIP_IFEL(!(msg = hip_msg_alloc()), -1, "hip_msg_alloc()"); + HIP_IFEL(hip_serialize_host_id_action(msg, ACTION_NEW, 0, 0, "rsa", + key_path, RSA_KEY_DEFAULT_BITS, + DSA_KEY_DEFAULT_BITS, + ECDSA_DEFAULT_CURVE), -1, + "Fail to create local key at %s.", key_path); + free(msg); + HIP_IFE(!(msg = hip_msg_alloc()), -1); + HIP_IFEL(hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa", + key_path, 0, 0, 0), -1, + "Fail to load local key at %s.", key_path); + } + HIP_IFE(hip_handle_add_local_hi(msg), -1); + +out_err: + free(msg); + free(key_path); + return err; +} + /** * create a socket to handle UDP encapsulation of HIP control * packets === renamed file 'hipd/init.h' => 'lib/hipl/init.h' --- hipd/init.h 2011-11-25 17:56:24 +0000 +++ lib/hipl/init.h 2012-03-15 08:58:36 +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 @@ -60,4 +60,6 @@ int is_output); void hip_exit(void); +int hipl_lib_init(void); + #endif /* HIPL_HIPD_INIT_H */ === renamed file 'hipd/input.c' => 'lib/hipl/input.c' --- hipd/input.c 2012-03-14 19:03:04 +0000 +++ lib/hipl/input.c 2012-03-15 08:58:36 +0000 @@ -708,6 +708,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' => 'lib/hipl/input.h' === renamed file 'hipd/keymat.c' => 'lib/hipl/keymat.c' === renamed file 'hipd/keymat.h' => 'lib/hipl/keymat.h' === renamed file 'hipd/lsidb.c' => 'lib/hipl/lsidb.c' === renamed file 'hipd/lsidb.h' => 'lib/hipl/lsidb.h' === renamed file 'hipd/maintenance.c' => 'lib/hipl/maintenance.c' --- hipd/maintenance.c 2012-03-09 13:38:34 +0000 +++ lib/hipl/maintenance.c 2012-03-15 08:58:36 +0000 @@ -58,6 +58,7 @@ #include "cookie.h" #include "hadb.h" #include "hidb.h" +#include "hip_socket.h" #include "hipd.h" #include "init.h" #include "input.h" === renamed file 'hipd/maintenance.h' => 'lib/hipl/maintenance.h' === renamed file 'hipd/nat.c' => 'lib/hipl/nat.c' === renamed file 'hipd/nat.h' => 'lib/hipl/nat.h' === renamed file 'hipd/netdev.c' => 'lib/hipl/netdev.c' === renamed file 'hipd/netdev.h' => 'lib/hipl/netdev.h' === renamed file 'hipd/nsupdate.c' => 'lib/hipl/nsupdate.c' === renamed file 'hipd/nsupdate.h' => 'lib/hipl/nsupdate.h' === renamed file 'hipd/opp_mode.c' => 'lib/hipl/opp_mode.c' === renamed file 'hipd/opp_mode.h' => 'lib/hipl/opp_mode.h' === renamed file 'hipd/output.c' => 'lib/hipl/output.c' --- hipd/output.c 2012-03-09 13:38:34 +0000 +++ lib/hipl/output.c 2012-03-15 08:58:36 +0000 @@ -850,7 +850,8 @@ HIP_ASSERT(!hit_is_opportunistic_hit(&ctx->input_msg->hitr)); /* Case: I ----->IPv4---> RVS ---IPv6---> R */ - if (IN6_IS_ADDR_V4MAPPED(r1_src_addr) != + if (!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); @@ -1219,6 +1220,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); @@ -1247,13 +1251,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); @@ -1307,9 +1314,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()) { @@ -1326,18 +1334,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' => 'lib/hipl/output.h' === renamed file 'hipd/pisa.c' => 'lib/hipl/pisa.c' === renamed file 'hipd/pisa.h' => 'lib/hipl/pisa.h' === renamed file 'hipd/pkt_handling.c' => 'lib/hipl/pkt_handling.c' === renamed file 'hipd/pkt_handling.h' => 'lib/hipl/pkt_handling.h' === renamed file 'hipd/registration.c' => 'lib/hipl/registration.c' === renamed file 'hipd/registration.h' => 'lib/hipl/registration.h' === added file 'lib/hipl/socket_wrapper.c' --- lib/hipl/socket_wrapper.c 1970-01-01 00:00:00 +0000 +++ lib/hipl/socket_wrapper.c 2012-03-15 08:58:36 +0000 @@ -0,0 +1,827 @@ +/* + * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * This file contains the implementation of libhipl API. + */ + +#define _BSD_SOURCE + +#include <string.h> +#include <unistd.h> + +#include "lib/core/builder.h" +#include "lib/core/conf.h" +#include "lib/core/crypto.h" +#include "lib/core/hip_udp.h" +#include "lib/core/linkedlist.h" +#include "lib/core/message.h" +#include "lib/core/prefix.h" +#include "close.h" +#include "hadb.h" +#include "hidb.h" +#include "init.h" +#include "input.h" +#include "netdev.h" +#include "output.h" +#include "socket_wrapper.h" + + +/* This struct contains information for each HIPL socket. + * When HIPL socket is created, a socket descriptor is return to the user while + * a new @c hipl_fd_info is also created to link the socket descriptor to its + * corresponding HIP association. */ +struct hipl_fd_info { + int fd; + int bound_port; + int family; + int proto; + struct hip_hadb_state *ha; +}; + +/* A list of @c hipl_fd_info. + * This lists maintains all the HIPL sockets which user operates on */ +static struct hip_ll socket_list; + +/* The default hit used by LIBHIPL for establishing HIP association */ +static struct in6_addr default_hit; + +static uint16_t get_port_from_saddr(const struct sockaddr *const addr) +{ + const struct sockaddr_in *addr4; + const struct sockaddr_in6 *addr6; + + if (addr->sa_family == AF_INET) { + addr4 = (const struct sockaddr_in *) addr; + return addr4->sin_port; + } else { + addr6 = (const struct sockaddr_in6 *) addr; + return addr6->sin6_port; + } +} + +/** + * Build a suitable sockaddr_storage. + * If the address is V4MAPPED, the storage family will be INET4. + * Otherwise the storage family will be INET6. + * + * @param addr a V6 address or V4MAPPED address + * @param port port number (in NETWORK byte order) + * @param ss the sockaddr_storage to be filled. + */ +static void build_sockaddr(const struct in6_addr *const addr, + const uint16_t port, + struct sockaddr_storage *const ss) +{ + HIP_ASSERT(addr && ss); + memset(ss, 0, sizeof(struct sockaddr_storage)); + + if (IN6_IS_ADDR_V4MAPPED(addr)) { + struct sockaddr_in *const in = (struct sockaddr_in *) ss; + in->sin_family = AF_INET; + IPV6_TO_IPV4_MAP(addr, &in->sin_addr); + in->sin_port = port; + } else { + struct sockaddr_in6 *const in6 = (struct sockaddr_in6 *) ss; + in6->sin6_family = AF_INET6; + ipv6_addr_copy(&in6->sin6_addr, addr); + in6->sin6_port = port; + } +} + +/** + * Create a new HIP socket info struct and insert it into global list. + * + * @param fd file descriptor of the socket + * @param bound_port the port number which this fd bound to (in HOST order) + * @param family the address family of this fd (INET or INET6) + * @param proto the protocol of this fd (TCP or UDP) + * @return pointer of the new struct, NULL if we fail to create it. + */ +static struct hipl_fd_info *create_new_fd_info(const int fd, + const uint16_t bound_port, + const int family, + const int proto) +{ + int err = 0; + struct hipl_fd_info *fd_info_new = NULL; + + if ((fd_info_new = calloc(sizeof(struct hipl_fd_info), 1)) == NULL) { + HIP_PERROR("calloc()"); + return NULL; + } + + HIP_IFEL(hip_ll_add_last(&socket_list, fd_info_new), + -1, "Error adding FD info struct to list\n"); + fd_info_new->fd = fd; + fd_info_new->bound_port = bound_port; + fd_info_new->family = family; + fd_info_new->proto = proto; + +out_err: + if (err) { + free(fd_info_new); + fd_info_new = NULL; + } + return fd_info_new; +} + +/** + * Get information on a HIP socket by its file descriptor. + * + * @param fd file descriptor of the HIP socket + * @return a structure containing information on the status of the socket + * or NULL if none is found + */ +static struct hipl_fd_info *hipl_socket_get_info(const int fd) +{ + const struct hip_ll_node *current = NULL; + struct hipl_fd_info *fd_info; + + while ((current = hip_ll_iterate(&socket_list, current))) { + fd_info = current->ptr; + if (fd_info->fd == fd) { + return fd_info; + } + } + + return NULL; +} + +/** + * Automatically bind to a port for hip_fd_info struct. + * + * @param info hip_fd_info struct + * @return 0 if it successes, -1 on error + */ +static int auto_bind(const struct hipl_fd_info *const info) +{ + struct sockaddr_storage ss = { 0 }; + struct sockaddr_in *addr4; + struct sockaddr_in6 *addr6; + + if (info->bound_port != 0) { + HIP_ERROR("A bound port exists, auto_bind stops\n"); + return -1; + } + + if (info->family == AF_INET) { + ss.ss_family = AF_INET; + addr4 = (struct sockaddr_in *) &ss; + addr4->sin_port = 0; + return hipl_bind(info->fd, (struct sockaddr *) addr4, sizeof(ss)); + } else { + ss.ss_family = AF_INET6; + addr6 = (struct sockaddr_in6 *) &ss; + addr6->sin6_port = 0; + return hipl_bind(info->fd, (struct sockaddr *) addr6, sizeof(ss)); + } +} + +/** + * Add peer's hit-to-addr mapping to hadb. + * @param peer_hit peer's hit + * @param peer_addr peer's addr, v4 addr should be mapped. + * @return 0 on success, -1 otherwise. + */ +int hipl_add_peer_info(const hip_hit_t *const peer_hit, + const struct in6_addr *const peer_addr) +{ + return hip_hadb_add_peer_info(peer_hit, peer_addr, NULL, NULL); +} + +/** + * Set global variables in order to interoperate with libhipdeamon. + * @param sock_fd the sock fd used 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("fd = %d, lport = %d, rport= %d\n", sock_fd, local_port, remote_port); + hip_nat_sock_output_udp = sock_fd; + hip_raw_sock_output_v4 = sock_fd; + hip_raw_sock_output_v6 = sock_fd; + hip_set_local_nat_udp_port(local_port); + hip_set_peer_nat_udp_port(remote_port); +} + +/** + * Check whether a received packet is a HIP control packet + * + * @param buf buffer containing the received data + * @param len size of buf + * @param fd_info information of the socket which the data was received from + * @return + */ +static int hipl_is_control_msg(char *const buf, unsigned int len, + const struct hipl_fd_info *const fd_info) +{ + char udp_pad[HIP_UDP_ZERO_BYTES_LEN] = { 0 }; + struct hip_common *msg; + struct sockaddr_storage src = { 0 }; + struct sockaddr_storage dst = { 0 }; + + if (len < sizeof(struct hip_common)) { + return 0; + } + + if (!memcmp(udp_pad, buf, HIP_UDP_ZERO_BYTES_LEN)) { + HIP_DEBUG("Message is padded\n"); + msg = (struct hip_common *) (buf + HIP_UDP_ZERO_BYTES_LEN); + len -= HIP_UDP_ZERO_BYTES_LEN; + } else { + msg = (struct hip_common *) buf; + } + + src.ss_family = fd_info->family; + dst.ss_family = fd_info->family; + + if (fd_info->family == AF_INET) { + struct sockaddr_in *src4 = (struct sockaddr_in *) &src; + struct sockaddr_in *dst4 = (struct sockaddr_in *) &dst; + + src4->sin_port = fd_info->ha->peer_udp_port; + dst4->sin_port = fd_info->ha->local_udp_port; + + IPV6_TO_IPV4_MAP(&fd_info->ha->peer_addr, &src4->sin_addr); + IPV6_TO_IPV4_MAP(&fd_info->ha->our_addr, &dst4->sin_addr); + + HIP_DEBUG_INADDR("src", &src4->sin_addr); + HIP_DEBUG_INADDR("dst", &dst4->sin_addr); + } else if (fd_info->family == AF_INET6) { + struct sockaddr_in6 *src6 = (struct sockaddr_in6 *) &src; + struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *) &dst; + + src6->sin6_port = fd_info->ha->peer_udp_port; + dst6->sin6_port = fd_info->ha->local_udp_port; + + memcpy(&src6->sin6_addr, &fd_info->ha->peer_addr, + sizeof(struct in6_addr)); + memcpy(&dst6->sin6_addr, &fd_info->ha->our_addr, + sizeof(struct in6_addr)); + + HIP_DEBUG_IN6ADDR("src", &src6->sin6_addr); + HIP_DEBUG_IN6ADDR("dst", &dst6->sin6_addr); + } + + return !hip_verify_network_header(msg, (struct sockaddr *) &src, + (struct sockaddr *) &dst, len); +} + +/** + * Initiate and perform a base exchange with a peer. + * + * @param fd file descriptor + * @param dst_hit_sockaddr hit of the peer to be contacted + * @return 0 on success, -1 otherwise + */ +static int hipl_do_bex(const int fd, + const struct sockaddr_in6 *const dst_hit_sockaddr) +{ + struct in6_addr dst_hit; + struct in6_addr dst_addr; + struct hip_packet_context ctx = { 0 }; + struct hipl_fd_info *fd_info; + + if ((fd_info = hipl_socket_get_info(fd)) == NULL) { + HIP_ERROR("No socket info found.\n"); + return -1; + } + + hip_get_default_hit(&default_hit); + + memcpy(&dst_hit, &dst_hit_sockaddr->sin6_addr, sizeof(dst_hit)); + if (hip_map_id_to_addr(&dst_hit, NULL, &dst_addr) < 0) { + return -1; + } + if (ipv6_addr_any(&dst_addr)) { + HIP_ERROR("Couldn't map HIT to IP\n"); + return -1; + } + + set_hip_connection_parameters(fd, fd_info->bound_port, + ntohs(dst_hit_sockaddr->sin6_port)); + if (netdev_trigger_bex(&default_hit, &dst_hit, + NULL, NULL, NULL, &dst_addr) < 0) { + HIP_ERROR("Couldn't start base exchange.\n"); + return -1; + } + + ctx.input_msg = hip_msg_alloc(); + ctx.output_msg = hip_msg_alloc(); + + fd_info->ha = hip_hadb_find_byhits(&default_hit, &dst_hit); + + do { + if (fd_info->proto == IPPROTO_TCP) { + if (!hip_read_control_msg_tcp(fd, &ctx)) { + hip_receive_control_packet(&ctx); + } + } else if (fd_info->family == AF_INET) { + if (!hip_read_control_msg_v4(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN)) { + hip_receive_control_packet(&ctx); + } + } else { + if (!hip_read_control_msg_v6(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN)) { + hip_receive_control_packet(&ctx); + } + } + } while (fd_info->ha->state != HIP_STATE_ESTABLISHED); + + fd_info->ha->local_udp_port = fd_info->bound_port; + + free(ctx.input_msg); + free(ctx.output_msg); + return 0; +} + +/** + * Wait for an I1 packet and perform base exchange. + * + * @param fd_info fd information of the socket for incoming BEX msg. + * @param peer_addr peer's locator + * @return 0 on success, -1 otherwise + */ +static int hipl_await_bex(struct hipl_fd_info *const fd_info, + const struct sockaddr *const peer_addr) +{ + int fd = fd_info->fd; + struct hip_packet_context ctx = { 0 }; + + ctx.input_msg = hip_msg_alloc(); + ctx.output_msg = hip_msg_alloc(); + + set_hip_connection_parameters(fd, fd_info->bound_port, + ntohs(get_port_from_saddr(peer_addr))); + + do { + if (fd_info->proto == IPPROTO_TCP) { + if (!hip_read_control_msg_tcp(fd, &ctx) && + !hip_receive_control_packet(&ctx)) { + fd_info->ha = hip_hadb_find_byhits(&ctx.input_msg->hitr, + &ctx.input_msg->hits); + } + } else if (fd_info->family == AF_INET) { + if (!hip_read_control_msg_v4(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN) && + !hip_receive_control_packet(&ctx)) { + fd_info->ha = hip_hadb_find_byhits(&ctx.input_msg->hitr, + &ctx.input_msg->hits); + } + } else { + if (!hip_read_control_msg_v6(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN) && + !hip_receive_control_packet(&ctx)) { + fd_info->ha = hip_hadb_find_byhits(&ctx.input_msg->hitr, + &ctx.input_msg->hits); + } + } + } while (!fd_info->ha || fd_info->ha->state != HIP_STATE_ESTABLISHED); + + fd_info->ha->local_udp_port = fd_info->bound_port; + + free(ctx.input_msg); + free(ctx.output_msg); + return 0; +} + +/** + * Create a socket and an information entry for it + * + * @param domain Communications domain for the socket + * @param type Socket type + * @param protocol Socket protocol + * @return file descriptor of the new socket on success, -1 otherwise + */ +int hipl_socket(const int domain, const int type, const int protocol) +{ + int sock; + int on = 1, off = 0, err = 0; + struct hipl_fd_info *fd_info = NULL; + + sock = socket(domain, type, protocol); + + if (domain == AF_INET) { + setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); + setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)); + setsockopt(sock, IPPROTO_IP, IP_RECVERR, &off, sizeof(off)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + } else { + setsockopt(sock, IPPROTO_IPV6, IPV6_RECVERR, &off, sizeof(off)); + setsockopt(sock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + } + + //TODO support IPV6 + HIP_IFEL(domain == AF_INET6, -1, "No support for IPv6.\n"); + + fd_info = create_new_fd_info(sock, 0, domain, protocol); + HIP_IFEL(!fd_info, -1, "Fail to create hip socket info for fd: %d\n", sock); + +out_err: + if (err) { + close(sock); + return err; + } + + return sock; +} + +/** + * Close a socket. Sends CLOSE to the associated peer and deletes + * the socket information. + * + * @param fd file descriptor of the socket to be closed + * @return 0 if the socket was successfully closed, -1 otherwise + */ +int hipl_close(const int fd) +{ + int err = 0; + struct hip_common *msg = NULL; + struct hipl_fd_info *fd_info = NULL; + + fd_info = hipl_socket_get_info(fd); + if (!fd_info || !fd_info->ha || fd_info->ha->state == HIP_STATE_CLOSED) { + HIP_DEBUG("Not sending CLOSE.\n"); + goto skip_close_msg; + } + + if (!(msg = hip_msg_alloc()) || + hip_build_param_contents(msg, &fd_info->ha->hit_peer, + HIP_PARAM_HIT, sizeof(struct in6_addr)) || + hip_send_close(msg, 1)) { + HIP_ERROR("Sending CLOSE failed\n"); + goto skip_close_msg; + } + +skip_close_msg: + err = close(fd); + + if (fd_info) { + hip_ll_del_by_ptr(&socket_list, fd_info, free); + } + free(msg); + return err; +} + +/** + * Bind a socket to a local address + * + * @param fd file descriptor of the socket + * @param address address to bind to + * @param address_len length of address + * @return 0 on success, -1 otherwise + */ +int hipl_bind(const int fd, const struct sockaddr *const address, + const socklen_t address_len) +{ + struct hipl_fd_info *fd_info; + struct sockaddr_storage laddr = { 0 }; + socklen_t laddr_len = sizeof(laddr); + uint16_t request_port; + + if ((fd_info = hipl_socket_get_info(fd)) == NULL) { + HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd); + return -1; + } + + request_port = get_port_from_saddr(address); + if (bind(fd, address, address_len) < 0) { + HIP_PERROR("bind error:"); + return -1; + } + + /* Ask OS to get assigned port number */ + if (request_port == 0) { + if (getsockname(fd, (struct sockaddr *) &laddr, &laddr_len) < 0) { + HIP_PERROR("getsockname() error: "); + return -1; + } + request_port = get_port_from_saddr((struct sockaddr *) &laddr); + } + + fd_info->bound_port = ntohs(request_port); + HIP_DEBUG("bind to port %d\n", fd_info->bound_port); + + return 0; +} + +/** + * Send data to the peer associated with a socket. Triggers base exchange + * if no host association exists. + * + * @note Data is currently sent unencrypted. + * + * @param fd file descriptor of the socket to send from + * @param msg data to send + * @param len size of data + * @param flags sendto() flags + * @param dst_hit HIT of the peer to send to + * @param dst_len size of dst_hit + * @return number of bytes sent on success, -1 otherwise + */ +int hipl_sendto(const int fd, const void *const msg, const size_t len, + const int flags, const struct sockaddr *const dst_hit, + const socklen_t dst_len) +{ + struct sockaddr_storage dst_addr; + uint16_t dst_port; + struct hipl_fd_info *fd_info; + + dst_port = ((const struct sockaddr_in6 *) dst_hit)->sin6_port; + + if (dst_len != sizeof(struct sockaddr_in6)) { + HIP_ERROR("Only HITs are supported\n"); + return -1; + } + + if ((fd_info = hipl_socket_get_info(fd)) == NULL) { + HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd); + return -1; + } + + /* Bind to a ephemeral port if the src port hasn't been bound yet */ + if (fd_info->bound_port == 0) { + if (auto_bind(fd_info)) { + HIP_ERROR("Fail to bind the hip socket.\n"); + return -1; + } + } + + /* Start BEX if HA hasn't establised */ + if (!fd_info->ha) { + if (hipl_do_bex(fd, (const struct sockaddr_in6 *) dst_hit)) { + HIP_ERROR("Base exchange not successful.\n"); + return -1; + } + } + + /* Send user data */ + build_sockaddr(&fd_info->ha->peer_addr, dst_port, &dst_addr); + return sendto(fd, msg, len, flags, + (struct sockaddr *) &dst_addr, sizeof(dst_addr)); +} + +/** + * Receive data from the peer associated with a socket. + * Waits for base exchange if no host association exists. + * + * @note Data is currently sent unencrypted. + * + * @param fd file descriptor of the socket to receive from + * @param buf buffer for received data + * @param len size of buf + * @param flags recvfrom() flags + * @param addr buffer for the associated peer HIT + * @param addr_len size of dst_hit + * @return number of bytes received on success, -1 otherwise + */ +int hipl_recvfrom(const int fd, void *const buf, const size_t len, + const int flags, struct sockaddr *const addr, + socklen_t *const addr_len) +{ + int err = 0; + socklen_t socklen = *addr_len; + struct sockaddr_in6 *peer_hit = (struct sockaddr_in6 *) addr; + struct in6_addr peer_addr = { { { 0 } } }; + struct in6_addr *peer_addr6; + struct in_addr *peer_addr4; + struct hipl_fd_info *fd_info = NULL; + struct hip_packet_context ctx = { 0 }; + int (*read_control_msg)(int, struct hip_packet_context *, int) = NULL; + + + if ((fd_info = hipl_socket_get_info(fd)) == NULL) { + HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd); + return -1; + } + + /* Bind to a ephemeral port if the src port hasn't been bound yet */ + if (fd_info->bound_port == 0) { + if (auto_bind(fd_info)) { + HIP_ERROR("Fail to bind the hip socket.\n"); + return -1; + } + } + + /* Handle BEX if HA hasn't establised */ + if (!fd_info->ha) { + if (hipl_await_bex(fd_info, addr)) { + HIP_ERROR("Base exchange not successful.\n"); + return -1; + } + } + + ctx.input_msg = hip_msg_alloc(); + ctx.output_msg = hip_msg_alloc(); + read_control_msg = fd_info->family == AF_INET ? hip_read_control_msg_v4 + : hip_read_control_msg_v6; + + /* Loop until we get a non-control packet or a CLOSE packet */ + while (fd_info->ha->state == HIP_STATE_ESTABLISHED) { + err = recvfrom(fd, buf, len, flags | MSG_PEEK, addr, &socklen); + HIP_DEBUG("Peek packet len: %d\n", err); + HIP_DEBUG("peer sockaddr: AF = %d, socklen = %d\n", addr->sa_family, socklen); + if (err < 0) { + perror("recvfrom"); + } + + /* Drop the packet if it doesn't come from the address associated + * with the correct peer. */ + if (fd_info->proto == IPPROTO_UDP) { + if (addr->sa_family == AF_INET) { + peer_addr4 = &((struct sockaddr_in *) addr)->sin_addr; + IPV4_TO_IPV6_MAP(peer_addr4, &peer_addr); + peer_addr6 = &peer_addr; + } else { + peer_addr6 = &((struct sockaddr_in6 *) addr)->sin6_addr; + } + if (ipv6_addr_cmp(&fd_info->ha->peer_addr, peer_addr6)) { + HIP_DEBUG("Packet not from associated address. Dropping.\n"); + HIP_DEBUG_IN6ADDR("expected", &fd_info->ha->peer_addr); + HIP_DEBUG_IN6ADDR("got", peer_addr6); + err = recvfrom(fd, buf, 1, flags, addr, &socklen); + HIP_IFEL(err < 0, err, "recvfrom()\n"); + continue; + } + } + + /* Receive message */ + if (hipl_is_control_msg(buf, err, fd_info)) { + HIP_DEBUG("receive a hip control message.\n"); + if (fd_info->proto == IPPROTO_TCP) { + if (!hip_read_control_msg_tcp(fd, &ctx)) { + hip_receive_control_packet(&ctx); + } + } else if (!read_control_msg(fd, &ctx, HIP_UDP_ZERO_BYTES_LEN)) { + hip_receive_control_packet(&ctx); + } else { + HIP_ERROR("Error reading control packet\n"); + } + err = 0; + } else { + HIP_DEBUG("receive a non hip control message.\n"); + err = recvfrom(fd, buf, len, flags, addr, &socklen); + HIP_IFEL(err < 0, err, "recvfrom() error\n"); + break; + } + } + + if (peer_hit) { + memset(peer_hit, 0, *addr_len); + memcpy(&peer_hit->sin6_addr, &fd_info->ha->hit_peer, + sizeof(struct in6_addr)); + peer_hit->sin6_port = fd_info->ha->peer_udp_port; + *addr_len = sizeof(struct sockaddr_in6); + } + +out_err: + free(ctx.input_msg); + free(ctx.output_msg); + return err; +} + +/** + * Initiate a connection on a socket and perform base exchange as Initiator + * + * @param fd file descriptor of the socket + * @param addr peer HIT to connect to + * @param addr_len size of addr + * @return 0 on success, -1 otherwise + */ +int hipl_connect(const int fd, const struct sockaddr *const addr, + const socklen_t addr_len) +{ + uint16_t dst_port; + struct hipl_fd_info *fd_info = NULL; + struct in6_addr dst_hit; + struct in6_addr dst_addr = { { { 0 } } }; + struct sockaddr_storage ss; + + if ((fd_info = hipl_socket_get_info(fd)) == NULL) { + HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd); + return -1; + } + + if (addr_len != sizeof(struct sockaddr_in6)) { + HIP_ERROR("Invalid argument, Only HITs supported\n"); + return -1; + } + + dst_port = ((const struct sockaddr_in6 *) addr)->sin6_port; + ipv6_addr_copy(&dst_hit, &((const struct sockaddr_in6 *) addr)->sin6_addr); + if (ipv6_addr_any(&dst_hit)) { + HIP_ERROR("Invalid argument: The ANY dest address is not supported.\n"); + return -1; + } + + if (hip_map_id_to_addr(&dst_hit, NULL, &dst_addr) < 0) { + return -1; + } + if (ipv6_addr_any(&dst_addr)) { + HIP_ERROR("Couldn't map HIT to IP\n"); + return -1; + } + + HIP_DEBUG_IN6ADDR("Dest locator is: ", &dst_addr); + HIP_DEBUG("Dest locator is V4MAPPED: %d\n", IN6_IS_ADDR_V4MAPPED(&dst_addr)); + build_sockaddr(&dst_addr, dst_port, &ss); + + if (connect(fd, (struct sockaddr *) &ss, sizeof(ss)) < 0) { + HIP_PERROR("connect():"); + return -1; + } + + /* Bind to a ephemeral port if the src port hasn't been bound yet */ + if (fd_info->bound_port == 0) { + if (auto_bind(fd_info)) { + HIP_ERROR("Fail to bind the hip socket.\n"); + return -1; + } + } + + if (hipl_do_bex(fd, (const struct sockaddr_in6 *) addr) < 0) { + HIP_ERROR("Base exchange not successful.\n"); + return -1; + } + + return 0; +} + +/** + * Wait for an incoming connection on a socket and perform base exchange as + * Responder + * + * @param fd file descriptor of the socket + * @param new_peer_hit buffer to store peer hit and port + * @param hit_len size of new_peer_hit + * @return file descriptor of accepted socket, -1 on error + */ +int hipl_accept(const int fd, struct sockaddr *const new_peer_hit, + socklen_t *const hit_len) +{ + int new_fd; + struct hipl_fd_info *fd_info = NULL; + struct hipl_fd_info *fd_info_new = NULL; + struct sockaddr_storage ss = { 0 }; + socklen_t ss_len = sizeof(struct sockaddr_storage); + struct sockaddr_in6 *phit = NULL; + + if (*hit_len < sizeof(struct sockaddr_in6)) { + return -1; + } + + if ((fd_info = hipl_socket_get_info(fd)) == NULL) { + HIP_ERROR("Fd %d is not a hip socket, exiting.\n", fd); + return -1; + } + + new_fd = accept(fd, (struct sockaddr *) &ss, &ss_len); + if (new_fd < 0) { + HIP_PERROR("accept(): "); + return -1; + } + + fd_info_new = create_new_fd_info(new_fd, fd_info->bound_port, + fd_info->family, fd_info->proto); + + if (hipl_await_bex(fd_info_new, (struct sockaddr *) &ss) < 0) { + HIP_ERROR("Base exchange not successful.\n"); + return -1; + } + + if (new_peer_hit) { + phit = (struct sockaddr_in6 *) new_peer_hit; + memset(phit, 0, *hit_len); + memcpy(&phit->sin6_addr, &fd_info_new->ha->hit_peer, + sizeof(struct in6_addr)); + phit->sin6_port = get_port_from_saddr((struct sockaddr *) &ss); + *hit_len = sizeof(struct sockaddr_in6); + } + + return new_fd; +} === added file 'lib/hipl/socket_wrapper.h' --- lib/hipl/socket_wrapper.h 1970-01-01 00:00:00 +0000 +++ lib/hipl/socket_wrapper.h 2012-03-15 08:58:36 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef HIPL_LIB_HIPDAEMON_SOCKET_WRAPPER_H +#define HIPL_LIB_HIPDAEMON_SOCKET_WRAPPER_H + +#include <sys/socket.h> + +#include "lib/core/protodefs.h" + + +int hipl_add_peer_info(const hip_hit_t *const peer_hit, + const struct in6_addr *const peer_addr); + +int hipl_socket(const int domain, const int type, const int protocol); +int hipl_close(const int fd); +int hipl_bind(const int fd, const struct sockaddr *const address, + const socklen_t address_len); +int hipl_sendto(const int fd, const void *const msg, const size_t len, + const int flags, const struct sockaddr *const dst_hit, + const socklen_t dst_len); +int hipl_recvfrom(const int fd, void *const buf, const size_t len, + const int flags, struct sockaddr *const addr, + socklen_t *const addr_len); +int hipl_connect(const int fd, const struct sockaddr *const addr, + const socklen_t addr_len); +int hipl_accept(const int fd, struct sockaddr *const addr, + socklen_t *const addr_len); + +#endif /* HIPL_LIB_HIPDAEMON_SOCKET_WRAPPER_H */ === renamed file 'hipd/user.c' => 'lib/hipl/user.c' === renamed file 'hipd/user.h' => 'lib/hipl/user.h' === renamed file 'hipd/user_ipsec_hipd_msg.c' => 'lib/hipl/user_ipsec_hipd_msg.c' === renamed file 'hipd/user_ipsec_hipd_msg.h' => 'lib/hipl/user_ipsec_hipd_msg.h' === renamed file 'hipd/user_ipsec_sadb_api.c' => 'lib/hipl/user_ipsec_sadb_api.c' === renamed file 'hipd/user_ipsec_sadb_api.h' => 'lib/hipl/user_ipsec_sadb_api.h' === modified file 'modules/heartbeat/hipd/heartbeat.c' --- modules/heartbeat/hipd/heartbeat.c 2012-03-14 16:31:36 +0000 +++ modules/heartbeat/hipd/heartbeat.c 2012-03-15 08:58:36 +0000 @@ -66,14 +66,6 @@ #include <sys/types.h> #include <sys/socket.h> -#include "hipd/hadb.h" -#include "hipd/init.h" -#include "hipd/hip_socket.h" -#include "hipd/maintenance.h" -#include "hipd/nat.h" -#include "hipd/output.h" -#include "hipd/pkt_handling.h" -#include "hipd/user.h" #include "lib/core/common.h" #include "lib/core/debug.h" #include "lib/core/icomm.h" @@ -84,6 +76,14 @@ #include "lib/core/straddr.h" #include "lib/core/modularization.h" #include "lib/core/gpl/nlink.h" +#include "lib/hipl/hadb.h" +#include "lib/hipl/hip_socket.h" +#include "lib/hipl/init.h" +#include "lib/hipl/maintenance.h" +#include "lib/hipl/nat.h" +#include "lib/hipl/output.h" +#include "lib/hipl/pkt_handling.h" +#include "lib/hipl/user.h" #include "heartbeat.h" #define HIP_HEARTBEAT_INTERVAL 20 === modified file 'modules/heartbeat_update/hipd/hb_update.c' --- modules/heartbeat_update/hipd/hb_update.c 2012-03-13 18:26:08 +0000 +++ modules/heartbeat_update/hipd/hb_update.c 2012-03-15 08:58:36 +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 "lib/core/builder.h" #include "lib/core/common.h" #include "lib/core/debug.h" #include "lib/core/protodefs.h" +#include "lib/hipl/hadb.h" +#include "lib/hipl/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-01-16 22:06:09 +0000 +++ modules/midauth/hipd/midauth.c 2012-03-15 08:58:36 +0000 @@ -33,8 +33,6 @@ #include <stdint.h> #include <string.h> -#include "hipd/hidb.h" -#include "hipd/pkt_handling.h" #include "lib/core/builder.h" #include "lib/core/common.h" #include "lib/core/ife.h" @@ -42,6 +40,8 @@ #include "lib/core/protodefs.h" #include "lib/core/solve.h" #include "lib/core/state.h" +#include "lib/hipl/hidb.h" +#include "lib/hipl/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-01-17 08:34:18 +0000 +++ modules/update/hipd/update.c 2012-03-15 08:58:36 +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 "lib/core/builder.h" #include "lib/core/debug.h" #include "lib/core/hip_udp.h" @@ -57,6 +46,17 @@ #include "lib/core/prefix.h" #include "lib/core/state.h" #include "lib/core/performance.h" +#include "lib/hipl/cookie.h" +#include "lib/hipl/hadb.h" +#include "lib/hipl/hidb.h" +#include "lib/hipl/hipd.h" +#include "lib/hipl/input.h" +#include "lib/hipl/maintenance.h" +#include "lib/hipl/netdev.h" +#include "lib/hipl/nsupdate.h" +#include "lib/hipl/output.h" +#include "lib/hipl/pkt_handling.h" +#include "lib/hipl/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-02-15 17:37:10 +0000 +++ modules/update/hipd/update_builder.c 2012-03-15 08:58:36 +0000 @@ -34,12 +34,12 @@ #include <string.h> #include <errno.h> -#include "hipd/hadb.h" -#include "hipd/netdev.h" #include "lib/core/builder.h" #include "lib/core/ife.h" #include "lib/core/list.h" #include "lib/core/prefix.h" +#include "lib/hipl/hadb.h" +#include "lib/hipl/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 2011-12-12 14:18:05 +0000 +++ modules/update/hipd/update_locator.c 2012-03-15 08:58:36 +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 "lib/core/builder.h" #include "lib/core/debug.h" #include "lib/core/ife.h" #include "lib/core/protodefs.h" +#include "lib/hipl/maintenance.h" #include "update_builder.h" #include "update.h" #include "update_locator.h" === added file 'test/check_hipnetcat.c' --- test/check_hipnetcat.c 1970-01-01 00:00:00 +0000 +++ test/check_hipnetcat.c 2012-03-15 08:58:36 +0000 @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * @brief Tests of libhip (see doc/HACKING on unit tests). + */ + +#include <arpa/inet.h> +#include <check.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/select.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "lib/hipl/hidb.h" +#include "lib/hipl/init.h" + + +#define TEST_HIPNC_TIMEOUT 10 + +static void hipnc_test_start(char *serv_argv[], char *client_argv[]) +{ + pid_t serv_pid, client_pid, pid; + int status, i, j, round; + struct timeval tv; + int remain_cld = 2; + + /* start hipnetcat server */ + if ((pid = fork()) > 0) { + serv_pid = pid; + printf("server pid: %d\n", serv_pid); + } + + if (pid == 0 && execv("test/hipnetcat", serv_argv)) { + perror("execv"); + return; + } + + /* start hipnetcat client */ + sleep(1); + if ((pid = fork()) > 0) { + client_pid = pid; + printf("client_pid: %d\n", client_pid); + } + + if (pid == 0 && execv("test/hipnetcat", client_argv)) { + perror("execv"); + return; + } + + /* check server & client status */ + for (i = 0; i < TEST_HIPNC_TIMEOUT; i++) { + tv.tv_sec = 1; + tv.tv_usec = 0; + select(0, NULL, NULL, NULL, &tv); + round = remain_cld; + for (j = 0; j < round; j++) { + pid = waitpid(-1, &status, WNOHANG); + fail_if(pid > 0 && status != 0, "hipnetcat failed"); + if (pid > 0 && status == 0) { + remain_cld--; + if (remain_cld == 0) { + break; + } + } + } + } + + fail_if(remain_cld > 0, "hipnetcat test timeout!"); +} + +START_TEST(test_hipnc_lo_tcp) +{ + char *serv_argv[16]; + char *client_argv[16]; + struct in6_addr local_hit = { { { 0 } } }; + char hit_buf[128]; + int idx = 0; + + /* init */ + fail_if(hipl_lib_init(), "Failed to init libhip"); + fail_if(hip_get_default_hit(&local_hit), + "Failed to load local hit for hipnetcat startup"); + fail_if(inet_ntop(AF_INET6, &local_hit, hit_buf, 128) == NULL, + "Failed to parse hit to string."); + + serv_argv[idx++] = strdup("hipnetcat"); + serv_argv[idx++] = strdup("-l"); + serv_argv[idx++] = strdup("-p"); + serv_argv[idx++] = strdup("22300"); + serv_argv[idx++] = strdup("-s"); + serv_argv[idx++] = strdup("127.0.0.1"); + serv_argv[idx++] = strdup("-t"); + serv_argv[idx++] = NULL; + + idx = 0; + client_argv[idx++] = strdup("hipnetcat"); + client_argv[idx++] = strdup("-p"); + client_argv[idx++] = strdup("22345"); + client_argv[idx++] = strdup("-s"); + client_argv[idx++] = strdup("127.0.0.1"); + client_argv[idx++] = strdup("-d"); + client_argv[idx++] = strdup("22300"); + client_argv[idx++] = strdup("-t"); + client_argv[idx++] = strdup("127.0.0.1"); + client_argv[idx++] = hit_buf; + client_argv[idx++] = NULL; + + hipnc_test_start(serv_argv, client_argv); +} +END_TEST + +START_TEST(test_hipnc_lo_udp) +{ + char *serv_argv[16]; + char *client_argv[16]; + struct in6_addr local_hit = { { { 0 } } }; + char hit_buf[128]; + int idx = 0; + + /* init */ + fail_if(hipl_lib_init(), "Failed to init libhip"); + fail_if(hip_get_default_hit(&local_hit), + "Failed to load local hit for hipnetcat startup"); + fail_if(inet_ntop(AF_INET6, &local_hit, hit_buf, 128) == NULL, + "Failed to parse hit to string."); + + serv_argv[idx++] = strdup("hipnetcat"); + serv_argv[idx++] = strdup("-l"); + serv_argv[idx++] = strdup("-p"); + serv_argv[idx++] = strdup("22300"); + serv_argv[idx++] = strdup("-s"); + serv_argv[idx++] = strdup("127.0.0.1"); + serv_argv[idx++] = NULL; + + idx = 0; + client_argv[idx++] = strdup("hipnetcat"); + client_argv[idx++] = strdup("-p"); + client_argv[idx++] = strdup("22345"); + client_argv[idx++] = strdup("-s"); + client_argv[idx++] = strdup("127.0.0.1"); + client_argv[idx++] = strdup("-d"); + client_argv[idx++] = strdup("22300"); + client_argv[idx++] = strdup("127.0.0.1"); + client_argv[idx++] = hit_buf; + client_argv[idx++] = NULL; + + hipnc_test_start(serv_argv, client_argv); +} +END_TEST + +static Suite *hipnc_suite(void) +{ + Suite *s = suite_create("hipnc"); + + TCase *tc_hipnc_lo = tcase_create("hipnc_lo"); + tcase_add_test(tc_hipnc_lo, test_hipnc_lo_udp); + tcase_add_test(tc_hipnc_lo, test_hipnc_lo_tcp); + tcase_set_timeout(tc_hipnc_lo, 20); + suite_add_tcase(s, tc_hipnc_lo); + + return s; +} + +int main(void) +{ + int number_failed; + Suite *s = hipnc_suite(); + SRunner *sr = srunner_create(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/check_lib_core.c' --- test/check_lib_core.c 2012-03-13 13:33:06 +0000 +++ test/check_lib_core.c 2012-03-15 08:58:36 +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 @@ -43,6 +43,7 @@ srunner_add_suite(sr, lib_core_straddr()); srunner_add_suite(sr, lib_core_gpl_checksum()); + srunner_add_suite(sr, lib_core_linkedlist()); srunner_add_suite(sr, lib_core_modules_midauth_builder()); === modified file 'test/hipd/lsidb.c' --- test/hipd/lsidb.c 2012-01-18 21:09:47 +0000 +++ test/hipd/lsidb.c 2012-03-15 08:58:36 +0000 @@ -26,7 +26,7 @@ #include <check.h> #include <stdlib.h> -#include "hipd/lsidb.c" +#include "lib/hipl/lsidb.c" #include "test_suites.h" START_TEST(test_lsidb_allocate_lsi_valid) === added file 'test/hipnetcat.c' --- test/hipnetcat.c 1970-01-01 00:00:00 +0000 +++ test/hipnetcat.c 2012-03-15 08:58:36 +0000 @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * @file + * The hipnetcat sample program using libhip. + */ + +#define _BSD_SOURCE + +#include <arpa/inet.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "lib/core/debug.h" +#include "lib/core/hip_udp.h" +#include "lib/core/ife.h" +#include "lib/core/linkedlist.h" +#include "lib/core/prefix.h" +#include "lib/hipl/init.h" +#include "lib/hipl/socket_wrapper.h" + +#define HIPNC_SERVER_MODE 0x0001 +#define HIPNC_UDP_MODE 0x0002 +#define HIPNC_IP6 0x0004 + +static int dst_port = HIP_NAT_UDP_PORT; +static unsigned int hipnc_flag = HIPNC_UDP_MODE & ~HIPNC_SERVER_MODE & ~HIPNC_IP6; +static struct sockaddr_storage local_ss; +static struct hip_ll hit_list; +static struct hip_ll locator_list; + + +static int create_hip_socket(const unsigned int flag) +{ + return hipl_socket((flag & HIPNC_IP6) ? AF_INET6 : AF_INET, + (flag & HIPNC_UDP_MODE) ? SOCK_DGRAM : SOCK_STREAM, + (flag & HIPNC_UDP_MODE) ? IPPROTO_UDP : IPPROTO_TCP); +} + +static int hipnc_run_client(const unsigned int flag, + const struct sockaddr *const local_addr, + const socklen_t addr_len, + const struct sockaddr_in6 *const peer_hit_saddr) +{ + int fd, err = 0; + unsigned int len = 0; + static char buf[256] = { 0 }; + + if ((fd = create_hip_socket(flag)) < 0) { + HIP_PERROR("Failed to create hip socket."); + return -1; + } + + HIP_IFEL(hipl_bind(fd, local_addr, addr_len), -1, + "hipl_bind(): %s\n", strerror(errno)); + + if (!(flag & HIPNC_UDP_MODE)) { + HIP_IFEL(hipl_connect(fd, (const struct sockaddr *) peer_hit_saddr, + sizeof(struct sockaddr_in6)), + -1, "hipl_connect(): %s\n", strerror(errno)); + } + + sprintf(buf, "Hello, sailor!"); + len = hipl_sendto(fd, buf, sizeof(buf), 0, + (const struct sockaddr *) peer_hit_saddr, + sizeof(struct sockaddr_in6)); + + HIP_INFO("Sent %d bytes\n", len); + if (len < sizeof(buf)) { + err = -1; + } + +out_err: + hipl_close(fd); + + return err; +} + +static int hipnc_run_server(const unsigned int flag, + const struct sockaddr *const local_addr, + const socklen_t addr_len) +{ + int fd; + int err = 0, len = 0; + int new_fd = 0; + struct sockaddr_in6 peer_hit_saddr = { 0 }; + socklen_t socklen = sizeof(peer_hit_saddr); + char buf[256] = { 0 }; + + if ((fd = create_hip_socket(flag)) < 0) { + HIP_PERROR("Failed to create hip socket"); + return -1; + } + + HIP_IFEL(hipl_bind(fd, local_addr, addr_len), -1, + "hipl_bind(): %s\n", strerror(errno)); + + if (!(flag & HIPNC_UDP_MODE)) { + HIP_IFEL(listen(fd, 0), -1, "listen(): %s\n", strerror(errno)); + new_fd = hipl_accept(fd, (struct sockaddr *) &peer_hit_saddr, &socklen); + HIP_IFEL(new_fd < 0, -1, "hipl_accept(): %s\n", strerror(errno)); + } else { + new_fd = fd; + } + + while ((len = hipl_recvfrom(new_fd, buf, sizeof(buf), 0, + (struct sockaddr *) &peer_hit_saddr, + &socklen)) > 0) { + HIP_INFO("Received %d bytes\n", len); + printf("%.256s\n", buf); + HIP_INFO_IN6ADDR("Peer HIT", &peer_hit_saddr.sin6_addr); + } + + if (len < 0) { + perror("hip_recvfrom"); + err = len; + } + +out_err: + if (new_fd > 0) { + close(new_fd); + } + hipl_close(fd); + + return err; +} + +static void usage(void) +{ + printf("Hipnetcat program.\n" + "Usage: hipnetcat [-hlt] [-p source_port] [-s source_ip_address]\n" + " [-d dest_port] [peer_identifier[s]]\n\n" + " -h: help\n" + " -l: Listening mode, hipnetcat acts as the server side.\n" + " -t: Use TCP as transport protocol, otherwise UDP will be used.\n"); +} + +static int parse_source_to_ss(const char *const ip, const int port, + struct sockaddr_storage *const ss) +{ + struct sockaddr_in *sa4; + struct sockaddr_in6 *sa6; + + sa4 = (struct sockaddr_in *) ss; + sa6 = (struct sockaddr_in6 *) ss; + + /*try to parse ip to v4 format */ + ss->ss_family = AF_INET; + sa4->sin_port = htons(port); + + if (inet_pton(AF_INET, ip, &sa4->sin_addr) > 0) { + hipnc_flag &= ~HIPNC_IP6; + return 0; + } + + /* v4 parse failed, try v6 format */ + memset(ss, 0, sizeof(*ss)); + ss->ss_family = AF_INET6; + sa6->sin6_port = htons(port); + + if (inet_pton(AF_INET6, ip, &sa6->sin6_addr) > 0) { + hipnc_flag |= HIPNC_IP6; + return 0; + } + + /* Both v4 and v6 failed, return error */ + return -1; +} + +static int parse_arguments(const int argc, char *argv[]) +{ + int err = 0; + char opt = 0, *arg = NULL; + const char *src_ip = "0.0.0.0"; + int src_port = HIP_NAT_UDP_PORT; + struct in6_addr *paddr6 = NULL; + + while ((opt = getopt(argc, argv, "hltp:d:s:")) != -1) { + switch (opt) { + case 'l': + hipnc_flag |= HIPNC_SERVER_MODE; + break; + case 'p': + src_port = atoi(optarg); + break; + case 'd': + dst_port = atoi(optarg); + break; + case 's': + src_ip = optarg; + break; + case 't': + hipnc_flag &= ~HIPNC_UDP_MODE; + break; + case 'u': + hipnc_flag |= HIPNC_UDP_MODE; + break; + case 'h': + usage(); + exit(EXIT_SUCCESS); + default: + HIP_ERROR("Invalid option.\n"); + return -1; + } + } + + if (parse_source_to_ss(src_ip, src_port, &local_ss) < 0) { + HIP_ERROR("Failed to parse source ip address.\n"); + return -1; + } + + if (!(hipnc_flag & HIPNC_SERVER_MODE) && optind == argc) { + HIP_ERROR("No identifier has been provided.\n"); + return -1; + } + + /* parse identifiers */ + while (optind < argc) { + struct addrinfo *res; + struct addrinfo addr_hint = { 0 }; + struct sockaddr_in *sa4; + struct sockaddr_in6 *sa6; + + arg = argv[optind++]; + addr_hint.ai_family = AF_UNSPEC; + + HIP_DEBUG("Parse identifier: %s\n", arg); + err = getaddrinfo(arg, NULL, &addr_hint, &res); + HIP_IFEL(err, -1, "failed to parse: %s, %s\n", arg, gai_strerror(err)); + for (; res != NULL; res = res->ai_next) { + paddr6 = malloc(sizeof(struct in6_addr)); + HIP_IFEL(!paddr6, -1, "malloc() failed\n"); + if (res->ai_family == AF_INET) { + sa4 = (struct sockaddr_in *) res->ai_addr; + IPV4_TO_IPV6_MAP(&sa4->sin_addr, paddr6); + hip_ll_add_last(&locator_list, paddr6); + } else if (res->ai_family == AF_INET6) { + sa6 = (struct sockaddr_in6 *) res->ai_addr; + memcpy(paddr6, &sa6->sin6_addr, sizeof(struct in6_addr)); + if (ipv6_addr_is_hit(paddr6)) { + hip_ll_add_last(&hit_list, paddr6); + } else { + hip_ll_add_last(&locator_list, paddr6); + } + } + } + freeaddrinfo(res); + } + + if (!(hipnc_flag & HIPNC_SERVER_MODE) && locator_list.element_count == 0) { + HIP_ERROR("No locator is provided.\n"); + return -1; + } + +out_err: + if (err) { + free(paddr6); + } + return err; +} + +int main(int argc, char *argv[]) +{ + int err = 0; + struct sockaddr_in6 peer_hit_saddr = { 0 }; + + if (parse_arguments(argc, argv)) { + usage(); + exit(EXIT_FAILURE); + } + + if (hipl_lib_init() < 0) { + HIP_ERROR("libhipd init failed.\n"); + return -1; + } + + /* add peer hit-addr mapping */ + if (hit_list.element_count != 0) { + const struct hip_ll_node *hit_i = NULL; + const struct hip_ll_node *locator_i = NULL; + struct in6_addr *p_hit; + struct in6_addr *p_locator; + while ((hit_i = hip_ll_iterate(&hit_list, hit_i))) { + p_hit = (struct in6_addr *) hit_i->ptr; + while ((locator_i = hip_ll_iterate(&locator_list, locator_i))) { + p_locator = (struct in6_addr *) locator_i->ptr; + HIP_DEBUG_HIT("HIPNC input hit:", p_hit); + hipl_add_peer_info(p_hit, p_locator); + } + } + } + + HIP_DEBUG("hipnc_flag = %08x\n", hipnc_flag); + + if (hipnc_flag & HIPNC_SERVER_MODE) { + return hipnc_run_server(hipnc_flag, (struct sockaddr *) &local_ss, + sizeof(local_ss)); + } else if (hit_list.element_count != 0) { + const struct hip_ll_node *hit_i = NULL; + while ((hit_i = hip_ll_iterate(&hit_list, hit_i))) { + memcpy(&peer_hit_saddr.sin6_addr, hit_i->ptr, sizeof(struct in6_addr)); + peer_hit_saddr.sin6_port = htons(dst_port); + HIP_DEBUG_HIT("Connect to hit", &peer_hit_saddr.sin6_addr); + HIP_DEBUG("Connect to port: %d\n", dst_port); + + err = hipnc_run_client(hipnc_flag, (struct sockaddr *) &local_ss, + sizeof(local_ss), &peer_hit_saddr); + + /* if no errors, finish execution, otherwise we try another HIT */ + if (err == 0) { + return 0; + } + } + return err; + } else { + //TODO opportunistic mode + HIP_ERROR("opportunistic mode not supported. Please provide a HIT\n"); + return 0; + } +} === added file 'test/lib/core/linkedlist.c' --- test/lib/core/linkedlist.c 1970-01-01 00:00:00 +0000 +++ test/lib/core/linkedlist.c 2012-03-15 08:58:36 +0000 @@ -0,0 +1,120 @@ +/* + * 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. + */ + +#include <check.h> +#include <stdlib.h> +#include <stdio.h> + +#include "lib/core/linkedlist.h" +#include "test_suites.h" + + +static struct hip_ll *create_list(const int item_count) +{ + struct hip_ll *const list = malloc(sizeof(struct hip_ll)); + int i; + unsigned int *value = NULL; + + hip_ll_init(list); + for (i = 0; i < item_count; i++) { + value = malloc(sizeof(int)); + *value = i; + hip_ll_add_last(list, value); + } + + return list; +} + +START_TEST(test_hip_ll_del_by_ptr_first_elem_deleted) +{ + unsigned int list_size = 5; + struct hip_ll *list = create_list(list_size); + unsigned int *value; + + fail_unless(list != NULL && list->element_count == list_size); + + value = hip_ll_get(list, 0); + fail_unless(value != NULL && *value == 0); + + hip_ll_del_by_ptr(list, value, free); + list_size--; + fail_unless(list->element_count == list_size); + value = hip_ll_get(list, 0); + fail_unless(value != NULL && *value == 1); +} +END_TEST + +START_TEST(test_hip_ll_del_by_ptr_middle_elem_deleted) +{ + unsigned int list_size = 5; + struct hip_ll *list = create_list(list_size); + unsigned int *value; + unsigned int idx = list_size / 2; + + fail_unless(list != NULL && list->element_count == list_size); + + value = hip_ll_get(list, idx); + fail_unless(value != NULL && *value == idx); + + hip_ll_del_by_ptr(list, value, free); + list_size--; + fail_unless(list->element_count == list_size); + value = hip_ll_get(list, idx); + fail_unless(value != NULL && *value == idx + 1); +} +END_TEST + +START_TEST(test_hip_ll_del_by_ptr_last_elem_deleted) +{ + unsigned int list_size = 5; + struct hip_ll *list = create_list(list_size); + unsigned int *value; + unsigned int idx = list_size - 1; + + fail_unless(list != NULL && list->element_count == list_size); + + value = hip_ll_get(list, idx); + fail_unless(value != NULL && *value == idx); + + hip_ll_del_by_ptr(list, value, free); + list_size--; + fail_unless(list->element_count == list_size); + value = hip_ll_get(list, idx - 1); + fail_unless(value != NULL && *value == idx - 1); +} +END_TEST + +Suite *lib_core_linkedlist(void) +{ + Suite *s = suite_create("lib/core/linkedlist"); + + TCase *tc_core = tcase_create("Core"); + tcase_add_test(tc_core, test_hip_ll_del_by_ptr_first_elem_deleted); + tcase_add_test(tc_core, test_hip_ll_del_by_ptr_middle_elem_deleted); + tcase_add_test(tc_core, test_hip_ll_del_by_ptr_last_elem_deleted); + suite_add_tcase(s, tc_core); + + return s; +} === modified file 'test/lib/core/test_suites.h' --- test/lib/core/test_suites.h 2012-03-13 13:33:06 +0000 +++ test/lib/core/test_suites.h 2012-03-15 08:58:36 +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,6 +33,7 @@ Suite *lib_core_hostid(void); Suite *lib_core_solve(void); Suite *lib_core_straddr(void); +Suite *lib_core_linkedlist(void); Suite *lib_core_gpl_checksum(void); Suite *lib_core_gpl_pk(void);