Merge lp:~hipl-core/hipl/libhip into lp:hipl

Proposed by Xin
Status: Rejected
Rejected by: Xin
Proposed branch: lp:~hipl-core/hipl/libhip
Merge into: lp:hipl
Diff against target: 3091 lines (+2450/-114)
27 files modified
Makefile.am (+55/-46)
doc/HOWTO.xml.in (+106/-0)
hipd/main.c (+3/-4)
hipfw/hipfw.c (+1/-1)
lib/core/hostid.c (+12/-4)
lib/hipl/hadb.c (+16/-1)
lib/hipl/hidb.c (+9/-7)
lib/hipl/hipd.h (+5/-0)
lib/hipl/init.c (+297/-0)
lib/hipl/init.h (+5/-1)
lib/hipl/input.c (+5/-0)
lib/hipl/lhipl.c (+536/-0)
lib/hipl/lhipl.h (+76/-0)
lib/hipl/lhipl_operations.c (+771/-0)
lib/hipl/lhipl_operations.h (+55/-0)
lib/hipl/lhipl_sock.c (+150/-0)
lib/hipl/lhipl_sock.h (+67/-0)
lib/hipl/output.c (+33/-18)
modules/cert/hipd/cert.c (+2/-2)
modules/heartbeat/hipd/heartbeat.c (+9/-9)
modules/heartbeat_update/hipd/hb_update.c (+3/-3)
modules/midauth/hipd/midauth.c (+2/-2)
modules/update/hipd/update.c (+11/-11)
modules/update/hipd/update_builder.c (+2/-2)
modules/update/hipd/update_locator.c (+2/-2)
test/check_libhipl.c (+216/-0)
test/hipd/lsidb.c (+1/-1)
To merge this branch: bzr merge lp:~hipl-core/hipl/libhip
Reviewer Review Type Date Requested Status
Diego Biurrun Needs Fixing
René Hummen Disapprove
Christof Mroz Needs Information
Stefan Götz Pending
Review via email: mp+97589@code.launchpad.net

This proposal supersedes a proposal from 2012-02-20.

Description of the change

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

To post a comment you must log in.
Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal
Download full text (3.7 KiB)

> === modified file 'lib/core/hostid.c'
> --- lib/core/hostid.c 2011-11-10 10:35:47 +0000
> +++ lib/core/hostid.c 2012-02-20 08:33:22 +0000
> @@ -743,11 +744,17 @@
> goto out_err;
> }
> } else if (!use_default) {
> + char hi_file_dup[strlen(hi_file) + 1];
> + strcpy(hi_file_dup, 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;
> + }

I investigated a bit and seems like PATH_MAX is 4096 chars on linux, which is probably OK even for stacks on embedded devices, but strdup() would be safer nevertheless.
My apologies for advising you to use the stack for that in the last mail (see also further below).

Probably unrelated: should this handle recursive mkdir()? check_and_create_dir() currently does not, as far as I see.

> === modified file 'lib/core/linkedlist.c'
> --- lib/core/linkedlist.c 2011-08-15 14:11:56 +0000
> +++ lib/core/linkedlist.c 2012-02-20 08:33:22 +0000
> @@ -298,6 +298,51 @@
> /**
> + * Deletes the first node from list which has the same ptr given.
> + * If there is no match, does nothing.
> + *
> + * @param linkedlist list to remoe 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 *linkedlist, void *ptr,
> + free_elem_fn free_element)
> +{
> + struct hip_ll_node *curr;
> + struct hip_ll_node *tmp;
> +
> + /* match first list node */
> + if (linkedlist != NULL && linkedlist->element_count > 0
> + && linkedlist->head->ptr == ptr) {
> + tmp = linkedlist->head;
> + linkedlist->head = tmp->next;
> + linkedlist->element_count--;
> + if (free_element != NULL) {
> + free_element(tmp->ptr);
> + }
> + free(tmp);
> + return;
> + }
> +
> + /* match the rest list */
> + tmp = linkedlist->head;
> + for (curr = tmp->next; curr != NULL; curr = curr->next) {
> + if (curr->ptr == ptr) {
> + tmp->next = curr->next;
> + linkedlist->element_count--;
> + if (free_element != NULL) {
> + free_element(curr->ptr);
> + }
> + free(curr);
> + return;
> + }
> + tmp = tmp->next;
> + }
> +}

Looks like both loops can be merged, at first glance (untested):

if(!linkedlist || linkedlist->element_count == 0) {
 return;
}

struct hip_ll_node **storage = &linkedlist->head;
struct hip_ll_node *node = linkedlist->head;

while(node) {
 if(node->ptr == ptr) {
  *storage = node->next;
  free(node);
  node = *storage;

  linkedlist->elementcount -= 1;
  // could return here for micro optimization
 } else {
  storage = &node->next;
  node = node->next;
 }
}

> === renamed file 'hipd/init.c' => 'lib/hipdaemon/init....

Read more...

review: Needs Fixing
Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal

On 20.02.2012 21:03, Christof Mroz wrote:
> struct hip_ll_node **storage = &linkedlist->head;
> struct hip_ll_node *node = linkedlist->head;
>
> while(node) {
> if(node->ptr == ptr) {
> *storage = node->next;
> free(node);
> node = *storage;
>
> linkedlist->elementcount -= 1;
> // could return here for micro optimization
> } else {
> storage = &node->next;
> node = node->next;
> }
> }

Just realized this can be compacted some more:

struct hip_ll_node **storage = &linkedlist->head;

while(*storage) {
     struct hip_ll_node *const node = *storage;

     if(node->ptr == ptr) {
         linkedlist->elementcount -= 1;
         *storage = node->next;

         free(node);
         // could return here for micro optimization
     } else {
         storage = &node->next;
     }
}

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

Hi,

On 20/02/12 22:03, Christof Mroz wrote:
> Review: Needs Fixing
>
>> === modified file 'lib/core/hostid.c'
>> --- lib/core/hostid.c 2011-11-10 10:35:47 +0000
>> +++ lib/core/hostid.c 2012-02-20 08:33:22 +0000
>> @@ -743,11 +744,17 @@
>> goto out_err;
>> }
>> } else if (!use_default) {
>> + char hi_file_dup[strlen(hi_file) + 1];
>> + strcpy(hi_file_dup, 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;
>> + }
> I investigated a bit and seems like PATH_MAX is 4096 chars on linux, which is probably OK even for stacks on embedded devices, but strdup() would be safer nevertheless.
> My apologies for advising you to use the stack for that in the last mail (see also further below).
>
> Probably unrelated: should this handle recursive mkdir()? check_and_create_dir() currently does not, as far as I see.

Related stack memory usages have been reverted to malloc.

Regarding to check_and_create_dir(), in libhipl, using it is save,
because the parent directory (user's home folder) should exist.

Nice hints for linkedlist, it greatly shorten the lines of code :)

Xin

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Tue, Feb 21, 2012 at 05:36:57PM +0200, Xin Gu wrote:
> On 20/02/12 22:03, Christof Mroz wrote:
> >Review: Needs Fixing
> >
> >>=== modified file 'lib/core/hostid.c'
> >>--- lib/core/hostid.c 2011-11-10 10:35:47 +0000
> >>+++ lib/core/hostid.c 2012-02-20 08:33:22 +0000
> >>@@ -743,11 +744,17 @@
> >
> >Probably unrelated: should this handle recursive mkdir()? check_and_create_dir() currently does not, as far as I see.
>
> Regarding to check_and_create_dir(), in libhipl, using it is save,
> because the parent directory (user's home folder) should exist.

What happens if it does not exist?

Diego

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

On 21/02/12 21:21, Diego Biurrun wrote:
> On Tue, Feb 21, 2012 at 05:36:57PM +0200, Xin Gu wrote:
>> On 20/02/12 22:03, Christof Mroz wrote:
>>> Review: Needs Fixing
>>>
>>>> === modified file 'lib/core/hostid.c'
>>>> --- lib/core/hostid.c 2011-11-10 10:35:47 +0000
>>>> +++ lib/core/hostid.c 2012-02-20 08:33:22 +0000
>>>> @@ -743,11 +744,17 @@
>>> Probably unrelated: should this handle recursive mkdir()? check_and_create_dir() currently does not, as far as I see.
>> Regarding to check_and_create_dir(), in libhipl, using it is save,
>> because the parent directory (user's home folder) should exist.
> What happens if it does not exist?
>
>

Then the initialization process (loading the keys) will fail, program
exits with error.

Xin

Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal

Unless there's more to come (as you didn't request another review yet), I'm fine with the proposal.

Note that the early return in the linked list deletion routine is wrong if an item could be present multiple times.
In this case, in DEBUG configuration it could still be useful to trigger a HIP_ASSERT if an item is present multiple times but wasn't expected to (of course, you must always search the complete list then). This not directly related to this branch though.

If you commit the current version, remember to add bug tracker items concerning
- the non-recursive mkdir(): either always create the directory or never, but the current solution is something inbetween,
- the forking unit test: Even though forking is the simplest solution, tests should ideally not rely on their execution environment. Using mock functions you could also simulate dropped or corrupted packets for hipnetcat, etc.

review: Approve
Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Diego, I believe Xin has addressed the main issues, can we proceed to merge? We will continue to polish the library but we'd like to a get a more stable base for further work.

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal
Download full text (3.9 KiB)

 review needs-fixing

Sorry, Stefan the bean counter is back...
> /**
> + * Deletes the first node from list which has the same ptr given.

well, maybe "which contains the payload pointer ptr"?

> + * If there is no match, does nothing.
> + *
> + * @param linkedlist list to remoe an element from

remo[v]e

> + * @param ptr pointer by which to identify the node
> + * @param free_element a function pointer to a function for freeing the memory
> + * allocated for an element at a node or NULL if the element
> + * itself is not to be freed.
> + */
> +void hip_ll_del_by_ptr(struct hip_ll *linkedlist, void *ptr,
> + free_elem_fn free_element)

const correctness: struct hip_ll *const linkedlist, const void *const ptr

To separate memory management from list management, I would find it a cleaner
API to not pass in a free function pointer but to return a void* pointer. If ptr
was found in the list and removed, the function should then return ptr itself.
If ptr was not found in the list, the function should return NULL. In any case,
the caller can free the memory for ptr (if they intend to do so) by calling
free(hip_ll_del_by_ptr(list, ptr)); This separates concerns and is still very
easy to use.

> +{
> + struct hip_ll_node *curr;
> + struct hip_ll_node *tmp;
> +
> + /* match first list node */
> + if (linkedlist != NULL && linkedlist->element_count > 0

the check for linkedlist != NULL should also cover the second part of this
function. I'd suggest adding an assertion for it.

> + && linkedlist->head->ptr == ptr) {
> + tmp = linkedlist->head;
> + linkedlist->head = tmp->next;
> + linkedlist->element_count--;
> + if (free_element != NULL) {
> + free_element(tmp->ptr);
> + }
> + free(tmp);
> + return;
> + }
> +
> + /* match the rest list */

rest [of ]the list?

> + tmp = linkedlist->head;
> + for (curr = tmp->next; curr != NULL; curr = curr->next) {
> + if (curr->ptr == ptr) {
> + tmp->next = curr->next;
> + linkedlist->element_count--;
> + if (free_element != NULL) {
> + free_element(curr->ptr);
> + }
> + free(curr);
> + return;
> + }
> + tmp = tmp->next;
> + }
> +}

Why not go with Christof's version? It looked much simpler to me.

> +void hip_ll_del_by_ptr(struct hip_ll *linkedlist, void *ptr,
> + free_elem_fn free_element);

const correctness

> /**
> + * Read a control message over TCP socket.

What exactly does this function do? What happens after the message is read? Is
it returned to the caller? Sent to another processing function? /dev/null? The
CIA? Paradise?

> + * @param sockfd a socket file descriptor
> + * @param ctx a pointer to the packet context
> + * @return -1 in case of an error, 0 otherwise.
> + */
> +int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx)

const correctness

> +int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx);

const correctness

> --- h...

Read more...

review: Needs Fixing
Revision history for this message
Christof Mroz (christof-mroz) wrote : Posted in a previous version of this proposal

On 26.02.2012 09:25, Stefan Götz wrote:
> To separate memory management from list management, I would find it a cleaner
> API to not pass in a free function pointer but to return a void* pointer. If ptr
> was found in the list and removed, the function should then return ptr itself.
> If ptr was not found in the list, the function should return NULL. In any case,
> the caller can free the memory for ptr (if they intend to do so) by calling
> free(hip_ll_del_by_ptr(list, ptr)); This separates concerns and is still very
> easy to use.

I'd rather vote for someone to pick up and finish your existing linked
list branch instead (one day), so we have a single implementation for
both hipd and hipfw.

I agree that passing the free function every time is stupid. Note though
that we could go the other extreme and store alloc/free function
pointers in the list head instead, to avoid this duplication altogether.
But ultimately your solution would wreak the least havoc, because there
is nothing unexpected going on behind the scenes (easier to comprehend
for new contributors) and we're unlikely to refactor this aspect.

>> +{
>> + struct hip_ll_node *curr;
>> + struct hip_ll_node *tmp;
>> +
>> + /* match first list node */
>> + if (linkedlist != NULL&& linkedlist->element_count> 0
>
> the check for linkedlist != NULL should also cover the second part of this
> function. I'd suggest adding an assertion for it.

Passing NULL to free()-like functions is usually a no-op (by
convention), so I disagree.

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Hi,

On 02/26/2012 01:50 PM, Christof Mroz wrote:
>>> +{
>>> + struct hip_ll_node *curr;
>>> + struct hip_ll_node *tmp;
>>> +
>>> + /* match first list node */
>>> + if (linkedlist != NULL&& linkedlist->element_count> 0
>>
>> the check for linkedlist != NULL should also cover the second part of
>> this
>> function. I'd suggest adding an assertion for it.
>
> Passing NULL to free()-like functions is usually a no-op (by
> convention), so I disagree.

don't know if this applies here but, in general, we have agreed that
calling free(NULL) in the context of e.g. HIP_IFEL() is fine as
indicated by doc/HACKING:

   int f(void)
   {
       char *mem = NULL;
       HIP_IFEL(!(mem = HIP_ALLOC(256, 0)), -1, "alloc\n");

   out_err:
       free(mem);
       return err;
   }

This keeps the line count at minimum.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Sat, Feb 25, 2012 at 09:52:17AM +0000, Miika Komu wrote:
> Diego, I believe Xin has addressed the main issues, can we proceed to
> merge? We will continue to polish the library but we'd like to a get a
> more stable base for further work.

No, the branch still has pending needs-fixing reviews and central issues
like the naming remain undecided.

Diego

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

Hi,

On 26/02/12 10:25, Stefan Götz wrote:
>> + * @param ptr pointer by which to identify the node
>> + * @param free_element a function pointer to a function for freeing the memory
>> + * allocated for an element at a node or NULL if the element
>> + * itself is not to be freed.
>> + */
>> +void hip_ll_del_by_ptr(struct hip_ll *linkedlist, void *ptr,
>> + free_elem_fn free_element)
> const correctness: struct hip_ll *const linkedlist, const void *const ptr

I was wondering if we can just use "const void *ptr"? I haven't figured
out why we need the second const.

If I understand correctly, you also suggest to change "struct
hip_packet_context *ctx" to "struct hip_packet_context *const ctx" for
the following function. Then I have the same question related to const
after asterisk.

int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx)

> Why not go with Christof's version? It looked much simpler to me.

Current version is already based on Christof's advice. It seems that
somehow you receive an old version. I don't know why...

>> --- hipd/hadb.c 2012-02-17 10:45:47 +0000
>> +++ lib/hipdaemon/hadb.c 2012-02-20 08:33:22 +0000
>> @@ -616,7 +616,12 @@
>>
>> if (hip_select_source_address(&peer_map.our_addr,&peer_map.peer_addr)) {
>> HIP_ERROR("Cannot find source address\n");
>> - return -1;
>> + if (hipl_is_libhip_mode()) {
>> + memset(&peer_map.our_addr, 0, sizeof(peer_map.our_addr));
> How about 'peer_map.our_addr = INVALID_ADDR' with a suitable definition (and
> probably a better name for) INVALID_ADDR? It would reveal the intention of this
> code more clearly
>
>> + HIP_DEBUG("Using ANY for source address\n");
>> + } else {
>> + return -1;
>> + }

Hmm, what about add a comment? I add a comment and also rearrange this
part a bit, hope it is more clear.

> I couldn't finish reviewing, maybe later. In any case, const correctness for all
> further functions, please :)
>

I revised other code related to const correctness. Thanks for the review :)

https://code.launchpad.net/~hipl-core/hipl/libhip The diff in the
"Branch merges" section of this page is up-to-date.

Xin

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

Hi,

On 26/02/12 16:34, Diego Biurrun wrote:
> On Sat, Feb 25, 2012 at 09:52:17AM +0000, Miika Komu wrote:
>> Diego, I believe Xin has addressed the main issues, can we proceed to
>> merge? We will continue to polish the library but we'd like to a get a
>> more stable base for further work.
> No, the branch still has pending needs-fixing reviews and central issues
> like the naming remain undecided.
>
>

What is your opinion related to this naming issue? Previous we propose
to call it libhipl instead of libhipdaemon.
Since it will requires some efforts to change this, I hope we can agree
on a new name soon.

Xin

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal

> I was wondering if we can just use "const void *ptr"? I haven't figured
> out why we need the second const.

http://www.parashift.com/c++-faq-lite/const-correctness.html

In short, 'const int *ptr' makes '*ptr = 7' illegal. 'int *const ptr' makes 'ptr
= NULL' illegal.

> If I understand correctly, you also suggest to change "struct
> hip_packet_context *ctx" to "struct hip_packet_context *const ctx" for
> the following function. Then I have the same question related to const
> after asterisk.
>
> int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx)

Actually: const int sockfd, struct hip_packet_context *const ctx

Makes assignments to sockfd and ctx illegal because such assignments are not
necessary, anyway.

>> Why not go with Christof's version? It looked much simpler to me.
>
> Current version is already based on Christof's advice. It seems that
> somehow you receive an old version. I don't know why...

Ah, ok. No worries then.

>>> --- hipd/hadb.c 2012-02-17 10:45:47 +0000
>>> +++ lib/hipdaemon/hadb.c 2012-02-20 08:33:22 +0000
>>> @@ -616,7 +616,12 @@
>>>
>>> if (hip_select_source_address(&peer_map.our_addr,&peer_map.peer_addr)) {
>>> HIP_ERROR("Cannot find source address\n");
>>> - return -1;
>>> + if (hipl_is_libhip_mode()) {
>>> + memset(&peer_map.our_addr, 0, sizeof(peer_map.our_addr));
>> How about 'peer_map.our_addr = INVALID_ADDR' with a suitable definition (and
>> probably a better name for) INVALID_ADDR? It would reveal the intention of this
>> code more clearly
>>
>>> + HIP_DEBUG("Using ANY for source address\n");
>>> + } else {
>>> + return -1;
>>> + }
>
> Hmm, what about add a comment? I add a comment and also rearrange this
> part a bit, hope it is more clear.

Ok

Stefan

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Hi,

> Hi,
>
> On 26/02/12 16:34, Diego Biurrun wrote:
> > On Sat, Feb 25, 2012 at 09:52:17AM +0000, Miika Komu wrote:
> >> Diego, I believe Xin has addressed the main issues, can we proceed to
> >> merge? We will continue to polish the library but we'd like to a get a
> >> more stable base for further work.
> > No, the branch still has pending needs-fixing reviews and central issues
> > like the naming remain undecided.
> >
> >
>
> What is your opinion related to this naming issue? Previous we propose
> to call it libhipl instead of libhipdaemon.
> Since it will requires some efforts to change this, I hope we can agree
> on a new name soon.

I suggested earlier:
* lib/hipl for the directory hierarchy
* libhipl.{so.a} for the resulting binary

Diego, what say ye?

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal

> /**
> + * Read a control message over TCP socket and save it to @c hip_packet_context
> + * for future processing.

Ideally, this would also describe at least the most important checks that this code performs, how it handles socket errors, etc.

> +int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *const ctx)

const sockfd

> + 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;
> + memcpy(&ctx->dst_addr, &saddr6->sin6_addr, sizeof(struct in6_addr));

a plain assignment instead of memcpy is easier to read in such cases, but that is a matter of taste.

> + ctx->msg_ports.src_port = ntohs(saddr6->sin6_port);
> + }

Some of the socket_wrapper functions fit in very well here.

> + HIP_DEBUG_IN6ADDR("src", &ctx->src_addr);
> + HIP_DEBUG_IN6ADDR("dst", &ctx->dst_addr);

Maybe more information than that? Such as 'received packet from TCP socket, src..., dst...'?

> +static int hipd_library_mode = 0;

Why not a boolean type?

> === added file 'lib/hipdaemon/socket_wrapper.c'
> --- lib/hipdaemon/socket_wrapper.c 1970-01-01 00:00:00 +0000
> +++ lib/hipdaemon/socket_wrapper.c 2012-02-26 19:08:21 +0000

It would be extremely good to have more documentation in this file. Why is the struct hipl_fd_info necessary, for example? I don't mean what information in contains - that is obvious - but what is its purpose? Why was it necessary?

All of the functions in this file need to be updated with stricter const correctness.

> +static struct hip_ll socket_list;

What kind of socket is stored in this list? It's struct hipl_fd_info objects, right?

Are there many such objects? If not it may be simpler to just use a fixed size array than a dynamic list that tends to be awkward to use (==read).

> +static struct in6_addr default_hit;

> +/**
> + * Get information on a HIP socket by its file descritor.

descri[p]tor

Please use an editor with a spell checker and respect its suggestions :)

> +/**
> + * 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 *peer_hit,
> + const struct in6_addr *peer_addr)
> +{
> + return hip_hadb_add_peer_info(peer_hit, peer_addr, NULL, NULL);
> +}

What's the point? Why not call hip_hadb_add_peer_info() in the first place?

More to come

Stefan

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Mon, Feb 27, 2012 at 07:25:23AM +0000, Miika Komu wrote:
> > On 26/02/12 16:34, Diego Biurrun wrote:
> > > On Sat, Feb 25, 2012 at 09:52:17AM +0000, Miika Komu wrote:
> > >> Diego, I believe Xin has addressed the main issues, can we proceed to
> > >> merge? We will continue to polish the library but we'd like to a get a
> > >> more stable base for further work.
> > > No, the branch still has pending needs-fixing reviews and central issues
> > > like the naming remain undecided.
> >
> > What is your opinion related to this naming issue? Previous we propose
> > to call it libhipl instead of libhipdaemon.
> > Since it will requires some efforts to change this, I hope we can agree
> > on a new name soon.
>
> I suggested earlier:
> * lib/hipl for the directory hierarchy

I don't think grouping all of that stuff together below lib/ is a bad
idea, just put it in its separate directory.

I previously said I wanted to move lib/core and lib/tool together, I
would still like to.

> * libhipl.{so.a} for the resulting binary

Fine with me.

Diego

Revision history for this message
David Martin (martin-lp) wrote : Posted in a previous version of this proposal

Hi,

On Mon, Feb 27, 2012 at 9:04 AM, Stefan Götz <email address hidden> wrote:

>> +    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;
>> +        memcpy(&ctx->dst_addr, &saddr6->sin6_addr, sizeof(struct in6_addr));
>
> a plain assignment instead of memcpy is easier to read in such cases, but that is a matter of taste.

Either way there's a wrapper function for this purpose in
lib/core/prefix.c: ipv6_addr_copy(). Not sure if assignments are a
good idea but the wrapper should definitely be used instead of the
manual memcpy() with sizeof(). :)

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Mon, Feb 27, 2012 at 08:04:22AM +0000, Stefan Götz wrote:
> > + 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;
> > + memcpy(&ctx->dst_addr, &saddr6->sin6_addr, sizeof(struct in6_addr));
>
> a plain assignment instead of memcpy is easier to read in such cases,
> but that is a matter of taste.

I'd disagree with the taste part - just use assignments.

Diego

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

Hi,

On 26/02/12 22:34, Stefan Götz wrote:
>> I was wondering if we can just use "const void *ptr"? I haven't figured
>> out why we need the second const.
> http://www.parashift.com/c++-faq-lite/const-correctness.html
>
> In short, 'const int *ptr' makes '*ptr = 7' illegal. 'int *const ptr' makes 'ptr
> = NULL' illegal.
>
>> If I understand correctly, you also suggest to change "struct
>> hip_packet_context *ctx" to "struct hip_packet_context *const ctx" for
>> the following function. Then I have the same question related to const
>> after asterisk.
>>
>> int hip_read_control_msg_tcp(int sockfd, struct hip_packet_context *ctx)
> Actually: const int sockfd, struct hip_packet_context *const ctx
>
> Makes assignments to sockfd and ctx illegal because such assignments are not
> necessary, anyway.
>
>

I understand the syntax of const, but from the caller's point of view,
it has no difference if the function parameters are "const int sockfd,
struct hip_packet_context *const ctx" or "int sockfd, struct
hip_packet_context *ctx". Because both integer and pointer are
pass-by-value, and callee changing those parameters or not won't affect
caller.

That's why I am wondering if it is really necessary to add const under
those situations, if we have a look at some other C libraries, it is
also rare to see them using const in this way. For example, socket(int,
int, int) not socket(const int, const int, const int).

Of course, a const pointer like "const char *ptr" is necessary, which
means the function will not alter the data this ptr points to. My commit
last night fixed the const missing for this case.

Xin

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Hi,

On 02/27/2012 10:23 AM, Diego Biurrun wrote:
> On Mon, Feb 27, 2012 at 07:25:23AM +0000, Miika Komu wrote:
>>> On 26/02/12 16:34, Diego Biurrun wrote:
>>>> On Sat, Feb 25, 2012 at 09:52:17AM +0000, Miika Komu wrote:
>>>>> Diego, I believe Xin has addressed the main issues, can we proceed to
>>>>> merge? We will continue to polish the library but we'd like to a get a
>>>>> more stable base for further work.
>>>> No, the branch still has pending needs-fixing reviews and central issues
>>>> like the naming remain undecided.
>>>
>>> What is your opinion related to this naming issue? Previous we propose
>>> to call it libhipl instead of libhipdaemon.
>>> Since it will requires some efforts to change this, I hope we can agree
>>> on a new name soon.
>>
>> I suggested earlier:
>> * lib/hipl for the directory hierarchy
>
> I don't think grouping all of that stuff together below lib/ is a bad
> idea, just put it in its separate directory.
>
> I previously said I wanted to move lib/core and lib/tool together, I
> would still like to.

I believe this request is unrelated to the merge proposal?

Anyway, we have decided earlier that lib/core contains MIT-licensed code
and lib/tool GPL-licensed code. Now that I think about this separation,
I think the copyright already states clearly the difference. So, I don't
really object against merging the two directories.

Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Hi,

On 02/27/2012 11:27 AM, Xin Gu wrote:
> That's why I am wondering if it is really necessary to add const under
> those situations, if we have a look at some other C libraries, it is
> also rare to see them using const in this way. For example, socket(int,
> int, int) not socket(const int, const int, const int).

the Sockets API is a bit sloppy and we're trying to be more strict in HIPL.

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal

Hi Xin,

your understanding is quite correct. It is simply project policy to make all data as 'const' as possible because it helps to detect bugs. For example:

void foo(list_t *list) {
  if (list = NULL) {
    return;
  } else {
    // do stuff with list
  }
}

cannot go unnoticed when foo is declared as 'void foo(list_t *const list)'

So you're right: such const qualifiers are not *necessary*. But the hipl team still considers them a very good idea.

Cheers,
 Stefan

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

On 27/02/12 11:46, Stefan Götz wrote:
> Hi Xin,
>
> your understanding is quite correct. It is simply project policy to make all data as 'const' as possible because it helps to detect bugs. For example:
>
> void foo(list_t *list) {
> if (list = NULL) {
> return;
> } else {
> // do stuff with list
> }
> }
>
> cannot go unnoticed when foo is declared as 'void foo(list_t *const list)'
>
> So you're right: such const qualifiers are not *necessary*. But the hipl team still considers them a very good idea.
>
> Cheers,
> Stefan
>
>

Hi Stefan,

Thanks for this explanation, so we are using const in this case for the
function author to avoid potential bugs and it is also helpful for
others to understand the code. It is a good practice, I will follow this
style.

I have one suggestion: for the function declaration in the header file,
I suggest that we can eliminate this kind of const because it makes no
sense for the API caller. For instance:

In linkedlist.h
void hip_ll_del_by_ptr(struct hip_ll *linkedlist, const void *ptr,
                        free_elem_fn free_element);

In linkedlist.c
void hip_ll_del_by_ptr(struct hip_ll *const linkedlist, const void
*const ptr,
                        free_elem_fn free_element) {
     ... ....
}

Compiler will treat them as the same function. I am also thinking if
there is any compiler option to enforce this const by default, then
perhaps we don't need to type it everywhere :)

Xin

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

On 27/02/12 10:04, Stefan Götz wrote:
>
>> + ctx->msg_ports.src_port = ntohs(saddr6->sin6_port);
>> + }
> Some of the socket_wrapper functions fit in very well here.

Didn't get your point, which function?

>
>> +static struct hip_ll socket_list;
> What kind of socket is stored in this list? It's struct hipl_fd_info objects, right?
>
> Are there many such objects? If not it may be simpler to just use a fixed size array than a dynamic list that tends to be awkward to use (==read).

Added comments about this field.

Yes, it is a list of hipl_fd_info. Since the number of open HIPL sockets
is determined by the user, I think it is difficult to make it as a fixed
size array.

>
>> +/**
>> + * 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 *peer_hit,
>> + const struct in6_addr *peer_addr)
>> +{
>> + return hip_hadb_add_peer_info(peer_hit, peer_addr, NULL, NULL);
>> +}
> What's the point? Why not call hip_hadb_add_peer_info() in the first place?
>

This is an API for LIBHIPL user. We don't want user to directly handle hadb.

The const correctness is applied to all functions.

Xin

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal

>>
>>> + ctx->msg_ports.src_port = ntohs(saddr6->sin6_port);
>>> + }
>> Some of the socket_wrapper functions fit in very well here.
>
> Didn't get your point, which function?

I meant get_port_from_saddr()

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

On 28/02/12 09:28, Stefan Götz wrote:
> I meant get_port_from_saddr()
>
>

This get_port_from_saddr() function is used when you don't know the
saddr is AF_INET or AF_INET6, and it is a static function, but in
currently condition we already know it is IPv4 or v6, because except
port number, we also extract the IP address from it.

Xin

Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

On 27/02/12 14:35, Diego Biurrun wrote:
> On Mon, Feb 27, 2012 at 11:31:45AM +0200, Miika Komu wrote:
>> On 02/27/2012 10:23 AM, Diego Biurrun wrote:
>> I believe this request is unrelated to the merge proposal?
> What to do with lib/core and lib/tool is, yes, but what to do with
> libhipl is not.
>
>
In libhip branch, I have changed libhipdaemon to libhipl, and renamed
folder from lib/hipdaemon to lib/hipl

Xin

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal

Sorry, no time for more reviews :-(

review: Abstain
Revision history for this message
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal

Unless somebody objects by Friday, I would suggest Xin to merge the code then.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

 review needs-fixing

On Tue, Mar 13, 2012 at 09:51:23AM +0000, Miika Komu wrote:
> Unless somebody objects by Friday, I would suggest Xin to merge the code then.

I object. This merge request had many comments and questions that I did
not see addressed. I would expect a fresh merge request at least.

Diego

review: Needs Fixing
Revision history for this message
Xin (eric-nevup) wrote : Posted in a previous version of this proposal

Hi,

On 13/03/12 17:58, Diego Biurrun wrote:
> I object. This merge request had many comments and questions that I did
> not see addressed. I would expect a fresh merge request at least.
>
Since all the reviewers approve this merge request, I don't know where
is the open comments and questions you said. If I miss something, could
you show them so I can fix accordingly?

Xin

Revision history for this message
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal

On Wed, Mar 14, 2012 at 01:51:56PM +0200, Xin Gu wrote:
> On 13/03/12 17:58, Diego Biurrun wrote:
> >I object. This merge request had many comments and questions that I did
> >not see addressed. I would expect a fresh merge request at least.
> >
> Since all the reviewers approve this merge request,

I don't approve it and I set my review to needs-fixing.

> I don't know where is the open comments and questions you said. If I
> miss something, could you show them so I can fix accordingly?

As I said, I am expecting a fresh merge request; this one had far too
many comments.

Diego

Revision history for this message
Christof Mroz (christof-mroz) wrote :
Download full text (3.3 KiB)

> === 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
> @@ -2584,6 +2658,68 @@
> + <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>

A <code> tag looks more appropriate than <emphasis> (also in other places throught the file)
http://www.docbook.org/tdg/en/html/code.html

> === 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 @@
> + 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);

Looks like a lot of this dispatching throughout the patch could be avoided by introducing a generic hip_read_control_msg() function that takes an extra fd_info parameter and runs a switch() through it.
Sorry if this has been mentioned before, but I couldn't find it in the archives right away.

> + 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));
> + }

Since this is a library function (i.e., "user-friendly"), this should error out if neither AF_INET nor AF_INET6 are given.

> + /* 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) {

Since this is a library function, you should check that addr is indeed non-NULL for UDP.
But better yet: don't use the caller's buffer in the first place but provide your own.

> + peer_addr4 = &((struct sockaddr_in *) addr)->sin_addr;
> + IPV4_TO_IPV6_MAP(peer_addr4, &peer_addr);
> + peer_addr6 = &peer_addr;
> + } else {

peer_addr is probably a useless indirection.

> === 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 @@
> +int hipl...

Read more...

review: Needs Information
Revision history for this message
René Hummen (rene-hummen) wrote :

We are currently wrapping up the changes to the HIPL codebase for our project in Aachen. To this end, we are testing the HIPL code thoroughly on the certificate-exchange branch (which is in close sync with trunk). You may have noticed some bug fixes during the last couple of days. Once, we are confident that the certificate-related code is working correctly, we will merge it to trunk.

In order to have a stable HIPL version at the end of our project, I would very much appreciate if you could delay your merge until the end of the month. This will give us enough time to fix remaining issues that we run into. Merging your branch will again result in hugh changes that may result in new bugs and additional effort towards a stabile version of HIPL.

I suggest to make a new HIPL release after the certificate code has been merged. A few people have asked for this functionality. So a release might be helpful for them. The next release may then consist of the librarized version of HIPL.

review: Disapprove
Revision history for this message
Miika Komu (miika-iki) wrote :

The code is actually supposed to improve testing but I do understand your concern. As a compromise, would it be ok to do an intermediate merge proposal where we just change the directory structure to reflect the upcoming changes with the library? This would ease our pain as well.

Regarding to the release, we can do a release from any version in the code base and there's no real reason why the release schedule should stall progress.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (42.1 KiB)

 review needs-fixing

On Thu, Mar 15, 2012 at 08:59:19AM +0000, Xin wrote:
> Xin has proposed merging lp:~hipl-core/hipl/libhip into lp:hipl.

This merge request is huge and not easy to review. Please split it.

> +++ Makefile.am 2012-03-15 08:58:36 +0000
> @@ -34,7 +34,7 @@
> 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

This conflicts with the certificate branch, which just landed on trunk.
You will have to merge trunk soon.

> @@ -48,6 +48,7 @@
>
> ### test programs ###
> noinst_PROGRAMS = test/certteststub \
> + test/hipnetcat \
> test/performance/auth_performance \

I think tools/ would be a better place for this.

> @@ -59,15 +60,19 @@
>
> ### libraries ###
> lib_LTLIBRARIES = lib/core/libhipcore.la
> +lib_LTLIBRARIES += lib/hipl/libhipl.la

Align the = please. Better yet, just put it on one line or continue
with a backslash, there is no need to split it like you did.

> @@ -85,46 +91,7 @@
>
> @@ -199,6 +166,48 @@
>
> +lib_hipl_libhipl_la_sources = lib/hipl/accessor.c \
> + lib/hipl/cert.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

This looks like a merging error to me. I just made this indirection
unnecessary on trunk, midauth.c is just a normal source file.

> +lib_hipl_libhipl_la_LIBADD = lib/core/libhipcore.la

Place this together with the other lib dependencies.

> @@ -216,10 +225,13 @@
> 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 \

This whole linkedlist business could be split out into a separate merge request.

> --- 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>
> +...

review: Needs Fixing
lp:~hipl-core/hipl/libhip updated
4889. By Xin

Check HIP firewall status before sending RESET message when closing HIP SA.

The "fail and retry" mechanism makes closing time unnecessary long when there
is no HIP firewall. In this case, we should simply skip this process.

4890. By Xin

Fix bug in hipnetcat test programming which causes longger testing time.

Previously, the break statement only exits the inner loop, but its purpose is
to exit the outer loop also.

4891. By Xin

Sync: trunk 6344

4892. By Xin

Eliminate redundant code in control message receiving and handling.

4893. By Xin

Fix issues in doc raised during review.

4894. By Xin

Sync: trunk 6360

4895. By Xin

Remove useless indirection.

Revision history for this message
Xin (eric-nevup) wrote :

Hi,

On 15/03/12 13:41, Christof Mroz wrote:
> Review: Needs Information
>
> A<code> tag looks more appropriate than<emphasis> (also in other places throught the file)
> http://www.docbook.org/tdg/en/html/code.html

Although from the link you provided, <code> tag can be the child of
<para>, I found that changing to <code> tag causes XML validation
failure. Now I still using <emphasis> tag.

> Since this is a library function (i.e., "user-friendly"), this should error out if neither AF_INET nor AF_INET6 are given.
>
> Since this is a library function, you should check that addr is indeed non-NULL for UDP.
> But better yet: don't use the caller's buffer in the first place but provide your own.
>
>
> Would a corresponding remove function make sense?

Next version of libhipl (which is what I am working on now) will contain
argument check and other functionalities you mentioned.

Other two issues: code redundancy and useless indirection are fixed.

Sorry for my delayed response. Thanks.

Xin

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :

On Thu, Mar 22, 2012 at 02:49:47PM +0200, Xin Gu wrote:
> On 15/03/12 13:41, Christof Mroz wrote:
> >Review: Needs Information
> >
> >A<code> tag looks more appropriate than<emphasis> (also in other places throught the file)
> >http://www.docbook.org/tdg/en/html/code.html
>
> Although from the link you provided, <code> tag can be the child of
> <para>, I found that changing to <code> tag causes XML validation
> failure. Now I still using <emphasis> tag.

That is not the right solution. Look around in the file for better markup
suggestions.

Diego

lp:~hipl-core/hipl/libhip updated
4896. By Xin

sync: libhipl-mobility 4899

4897. By Xin

change the type of hipl_socket identifier from int to type hipl_sock_id

4898. By Xin

Sync: libhipl-mobility 4911.

4899. By Xin

Sync: trunk 6364

4900. By Xin

Fix document style and missing header.

4901. By Xin

Improve code style and doxygen documentation.

4902. By Xin

sync: trunk 6370

4903. By Xin

Remove unnecessary changes.

4904. By Xin

Change memcpy to assignments

4905. By Xin

Remove hipnetcat

Revision history for this message
Xin (eric-nevup) wrote :

Hi,

On 19/03/12 16:59, Diego Biurrun wrote:
> review needs-fixing
>
>
>> --- lib/core/hostid.c 2012-03-01 14:26:43 +0000
>> +++ lib/core/hostid.c 2012-03-15 08:58:36 +0000
>> @@ -678,6 +679,7 @@
>> 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];
>> @@ -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;
> You strup - why?

the function dirname() might modify the parameter, so I copy it.

>
> unrelated: I'm slightly suspicious of HIP_DIR_MODE, which is 0755.
> Is it really safe to make this world-readable?
>

It seems to be problematic, what should be a safe DIR_MODE?

>
>> @@ -523,6 +551,208 @@
>> +static int libhip_init_handle_functions(void)
>> +{
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_I2, HIP_STATE_NONE,&hip_setup_ipsec_sa, 30500);
>> + //hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT,&hip_setup_ipsec_sa, 30500);
> Why are all these commented-out?

Because kernel-based IPSec functions cannot be used in libhipl. Now I
delete those lines instead of commenting out.

All other issues are fixed.
Although hipnetcat and its test cases are not included in the merge
proposal this time, I fixed those issues you mentioned. You will see
them when I merge the hipnetcat.

Thanks for the review.

Xin

Revision history for this message
Christof Mroz (christof-mroz) wrote :

On 17.04.2012 18:16, Xin wrote:
> On 19/03/12 16:59, Diego Biurrun wrote:
>> > review needs-fixing
>> >
>> >
>>> >> --- lib/core/hostid.c 2012-03-01 14:26:43 +0000
>>> >> +++ lib/core/hostid.c 2012-03-15 08:58:36 +0000
>>> >> @@ -678,6 +679,7 @@
>>> >> 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];
>>> >> @@ -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;
>> > You strup - why?
> the function dirname() might modify the parameter, so I copy it.
>

This is ok now, but tucking the strdup() and dirname() away into
check_and_create_dir() could be less distracting and reusable. I'm not sure.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile.am'
2--- Makefile.am 2012-03-13 15:27:06 +0000
3+++ Makefile.am 2012-04-17 15:16:21 +0000
4@@ -58,17 +58,21 @@
5
6
7 ### libraries ###
8-lib_LTLIBRARIES = lib/core/libhipcore.la
9+lib_LTLIBRARIES = lib/core/libhipcore.la \
10+ lib/hipl/libhipl.la
11
12
13 ### tests ###
14 if HIP_UNITTESTS
15 TESTS = test/check_hipd \
16 test/check_hipfw \
17- test/check_lib_core
18+ test/check_lib_core \
19+ test/check_libhipl
20+
21 check_PROGRAMS = test/check_hipd \
22 test/check_hipfw \
23- test/check_lib_core
24+ test/check_lib_core \
25+ test/check_libhipl
26 endif
27
28
29@@ -85,47 +89,7 @@
30
31 tools_hipconf_SOURCES = tools/hipconf.c
32
33-hipd_hipd_sources = hipd/accessor.c \
34- hipd/cert.c \
35- hipd/close.c \
36- hipd/configfilereader.c \
37- hipd/cookie.c \
38- hipd/dh.c \
39- hipd/esp_prot_anchordb.c \
40- hipd/esp_prot_hipd_msg.c \
41- hipd/esp_prot_light_update.c \
42- hipd/hadb.c \
43- hipd/hidb.c \
44- hipd/hip_socket.c \
45- hipd/hipd.c \
46- hipd/hiprelay.c \
47- hipd/hit_to_ip.c \
48- hipd/init.c \
49- hipd/input.c \
50- hipd/keymat.c \
51- hipd/lsidb.c \
52- hipd/maintenance.c \
53- hipd/nat.c \
54- hipd/netdev.c \
55- hipd/nsupdate.c \
56- hipd/opp_mode.c \
57- hipd/output.c \
58- hipd/pkt_handling.c \
59- hipd/registration.c \
60- hipd/user.c \
61- hipd/user_ipsec_hipd_msg.c \
62- hipd/user_ipsec_sadb_api.c \
63- modules/heartbeat/hipd/heartbeat.c \
64- modules/heartbeat_update/hipd/hb_update.c \
65- modules/cert/hipd/cert.c \
66- modules/update/hipd/update.c \
67- modules/update/hipd/update_builder.c \
68- modules/update/hipd/update_locator.c \
69- modules/update/hipd/update_param_handling.c
70-
71-hipd_hipd_SOURCES = $(hipd_hipd_sources) \
72- modules/midauth/hipd/midauth.c \
73- hipd/main.c
74+hipd_hipd_SOURCES = hipd/main.c
75
76 dist_sysconf_DATA = hipd/hipd.conf \
77 hipd/hosts \
78@@ -202,6 +166,47 @@
79 lib_core_libhipcore_la_SOURCES += lib/core/performance.c
80 endif
81
82+lib_hipl_libhipl_la_SOURCES = lib/hipl/accessor.c \
83+ lib/hipl/cert.c \
84+ lib/hipl/close.c \
85+ lib/hipl/configfilereader.c \
86+ lib/hipl/cookie.c \
87+ lib/hipl/dh.c \
88+ lib/hipl/esp_prot_anchordb.c \
89+ lib/hipl/esp_prot_hipd_msg.c \
90+ lib/hipl/esp_prot_light_update.c \
91+ lib/hipl/hadb.c \
92+ lib/hipl/hidb.c \
93+ lib/hipl/hip_socket.c \
94+ lib/hipl/hipd.c \
95+ lib/hipl/hiprelay.c \
96+ lib/hipl/hit_to_ip.c \
97+ lib/hipl/init.c \
98+ lib/hipl/input.c \
99+ lib/hipl/keymat.c \
100+ lib/hipl/lhipl.c \
101+ lib/hipl/lhipl_sock.c \
102+ lib/hipl/lhipl_operations.c \
103+ lib/hipl/lsidb.c \
104+ lib/hipl/maintenance.c \
105+ lib/hipl/nat.c \
106+ lib/hipl/netdev.c \
107+ lib/hipl/nsupdate.c \
108+ lib/hipl/opp_mode.c \
109+ lib/hipl/output.c \
110+ lib/hipl/pkt_handling.c \
111+ lib/hipl/registration.c \
112+ lib/hipl/user.c \
113+ lib/hipl/user_ipsec_hipd_msg.c \
114+ lib/hipl/user_ipsec_sadb_api.c \
115+ modules/cert/hipd/cert.c \
116+ modules/heartbeat/hipd/heartbeat.c \
117+ modules/heartbeat_update/hipd/hb_update.c \
118+ modules/midauth/hipd/midauth.c \
119+ modules/update/hipd/update.c \
120+ modules/update/hipd/update_builder.c \
121+ modules/update/hipd/update_locator.c \
122+ modules/update/hipd/update_param_handling.c
123
124 test_check_hipd_SOURCES = test/check_hipd.c \
125 test/hipd/lsidb.c \
126@@ -230,14 +235,18 @@
127 test/lib/core/gpl/pk.c \
128 test/lib/core/modules/midauth_builder.c
129
130+test_check_libhipl_SOURCES = test/check_libhipl.c
131+
132
133 ### static library dependencies ###
134
135-hipd_hipd_LDADD = lib/core/libhipcore.la
136+hipd_hipd_LDADD = lib/hipl/libhipl.la
137 hipfw_hipfw_LDADD = lib/core/libhipcore.la
138-test_check_hipd_LDADD = lib/core/libhipcore.la
139+lib_hipl_libhipl_la_LIBADD = lib/core/libhipcore.la
140+test_check_hipd_LDADD = lib/hipl/libhipl.la
141 test_check_hipfw_LDADD = lib/core/libhipcore.la
142 test_check_lib_core_LDADD = lib/core/libhipcore.la
143+test_check_libhipl_LDADD = lib/hipl/libhipl.la
144 test_certteststub_LDADD = lib/core/libhipcore.la
145 test_performance_auth_performance_LDADD = lib/core/libhipcore.la
146 test_performance_dh_performance_LDADD = lib/core/libhipcore.la
147
148=== modified file 'doc/HOWTO.xml.in'
149--- doc/HOWTO.xml.in 2012-02-28 18:38:18 +0000
150+++ doc/HOWTO.xml.in 2012-04-17 15:16:21 +0000
151@@ -2659,6 +2659,112 @@
152
153 </section>
154
155+ <section id="ch_libhipl_usage">
156+ <title>The Libhipl Extension</title>
157+
158+ <para>
159+ Libhipl provides HIP functionality as a library for upper layer
160+ applications and it does not require the presence of the HIPL daemon.
161+ Instead, the HIP control messages are transmitted on top of TCP/UDP.
162+ From the applications' point of view, there is an API similar to the
163+ normal socket API. This section describes the libhipl API.
164+ </para>
165+
166+ <para>
167+ Libhipl API set is located in <emphasis>"lhipl.h"</emphasis>. Refer to
168+ its API documentation for detail information of each function.
169+ </para>
170+
171+ <formalpara>
172+ <title>Libhipl initialization</title>
173+ <para>
174+ Libhipl requires initialization before calling any other related
175+ functions. The function: <emphasis>hipl_lib_init_all()</emphasis>
176+ serves this purpose and different debug levels can be set as its
177+ parameters to track problems inside the library.
178+ </para>
179+ </formalpara>
180+
181+ <formalpara>
182+ <title>Name-based API</title>
183+ <para>
184+ Compared to standard socket API, one apparent difference in Libhipl is
185+ that a peer is specified by given a peer name and a port number instead
186+ of a sockaddr data structure. The peer name is a string representation of
187+ the peer. Currently, Libhipl only support HIT string as peer name.
188+ </para>
189+ </formalpara>
190+
191+ <formalpara>
192+ <title>Libhipl socket creation</title>
193+ <para>
194+ The function hipl_socket() creates a new libhipl socket. An ID is
195+ assigned to each created libhipl socket and returned by this function,
196+ then caller can pass this ID to other libhipl functions to operates on
197+ this libhipl socket. NOTE: there is NO relation between libhipl socket
198+ ID and normal socket file descriptor, and the result of using
199+ this ID as file descriptor is undefined.
200+ </para>
201+ </formalpara>
202+
203+ <formalpara><title>Setup TCP connection</title><para>
204+ When using libhipl in TCP mode, TCP connection setup is the first task.
205+ similar to the normal socket syntax, libhipl provides:
206+ <emphasis>hipl_connect()</emphasis>, <emphasis>hipl_listen()</emphasis>
207+ and <emphasis>hipl_accept()</emphasis> for this goal. Those functions
208+ process the 3-way handshake and establish a TCP connection.
209+ </para></formalpara>
210+
211+ <formalpara>
212+ <title>libhipl Base Exchange (BEX) and user data transmission</title>
213+ <para>
214+ Data transmission is handled by <emphasis>hipl_sendto()</emphasis> and
215+ <emphasis>hipl_recvfrom()</emphasis>.
216+ In libhipl, The first sending data call triggers BEX and the first
217+ receiving call waits for incoming BEX message. Once BEX succeeds,
218+ the pending user data is transmitted to the peer side. This BEX process
219+ is handled by libhipl automatically by default. Meanwhile, we also
220+ provide an advanced way to handle BEX step by step, which we will
221+ explain bellow.
222+ </para>
223+ </formalpara>
224+
225+ <formalpara>
226+ <title>libhipl assistant API</title>
227+ <para>
228+ <itemizedlist>
229+ <listitem>
230+ <para>
231+ <emphasis>hipl_add_peer_info()</emphasis> adds peer's HIT and IP
232+ address mappings to the database of libhipl. The library can use
233+ this information to look up peer's locator when a peer name is
234+ given.
235+ </para>
236+ </listitem>
237+
238+ <listitem>
239+ <para>
240+ <emphasis>hipl_lib_set_bex_feedback()</emphasis>: This function
241+ turns on/off the step-by-step process of BEX. By default, BEX
242+ feedback is off. When it is on, sending/receiving functions only
243+ process one BEX messages at a time, and give different return
244+ values to notify the progress of BEX.
245+ </para>
246+ </listitem>
247+ </itemizedlist>
248+ </para>
249+ </formalpara>
250+
251+ <formalpara>
252+ <title>Libhipl sample program</title>
253+ <para>
254+ For a libhipl usage example, refer to the
255+ <emphasis>check_libhipl</emphasis> program in the
256+ <emphasis>test</emphasis> directory.
257+ </para>
258+ </formalpara>
259+
260+ </section> <!-- ch_libhipl_usage -->
261 </chapter> <!-- ch_exp_extensions -->
262
263 </book>
264
265=== modified file 'hipd/main.c'
266--- hipd/main.c 2011-11-03 09:21:12 +0000
267+++ hipd/main.c 2012-04-17 15:16:21 +0000
268@@ -1,5 +1,5 @@
269 /*
270- * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
271+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
272 *
273 * Permission is hereby granted, free of charge, to any person
274 * obtaining a copy of this software and associated documentation
275@@ -32,10 +32,9 @@
276 #include <unistd.h>
277 #include <sys/types.h>
278
279-
280-#include "hipd/hipd.h"
281-#include "init.h"
282 #include "lib/core/debug.h"
283+#include "lib/hipl/hipd.h"
284+#include "lib/hipl/init.h"
285
286
287 /**
288
289=== modified file 'hipfw/hipfw.c'
290--- hipfw/hipfw.c 2012-04-16 14:55:53 +0000
291+++ hipfw/hipfw.c 2012-04-17 15:16:21 +0000
292@@ -75,7 +75,7 @@
293 #include "lib/core/performance.h"
294 #include "lib/core/prefix.h"
295 #include "lib/core/util.h"
296-#include "hipd/hipd.h"
297+#include "lib/hipl/hipd.h"
298 #include "config.h"
299 #include "cache.h"
300 #include "cert.h"
301
302=== modified file 'lib/core/hostid.c'
303--- lib/core/hostid.c 2012-03-01 14:26:43 +0000
304+++ lib/core/hostid.c 2012-04-17 15:16:21 +0000
305@@ -1,5 +1,5 @@
306 /*
307- * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
308+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
309 *
310 * Permission is hereby granted, free of charge, to any person
311 * obtaining a copy of this software and associated documentation
312@@ -29,6 +29,7 @@
313 */
314
315 #include <errno.h>
316+#include <libgen.h>
317 #include <stdint.h>
318 #include <stdlib.h>
319 #include <string.h>
320@@ -678,6 +679,7 @@
321 int err = 0, dsa_key_rr_len = 0, rsa_key_rr_len = 0;
322 int dsa_pub_key_rr_len = 0, rsa_pub_key_rr_len = 0;
323 hip_hdr numeric_action = 0;
324+ char *hi_file_dup = NULL;
325 char hostname[HIP_HOST_ID_HOSTNAME_LEN_MAX];
326 const char *rsa_filenamebase = DEFAULT_HOST_RSA_KEY_FILE_BASE DEFAULT_ANON_HI_FILE_NAME_SUFFIX;
327 const char *dsa_filenamebase = DEFAULT_HOST_DSA_KEY_FILE_BASE DEFAULT_ANON_HI_FILE_NAME_SUFFIX;
328@@ -743,11 +745,16 @@
329 goto out_err;
330 }
331 } else if (!use_default) {
332+ hi_file_dup = strdup(hi_file);
333+ if ((err = check_and_create_dir(dirname(hi_file_dup), HIP_DIR_MODE))) {
334+ HIP_ERROR("Could not create directory for path: %s\n", hi_file);
335+ goto out_err;
336+ }
337 if (!strcmp(hi_fmt, "dsa")) {
338 dsa_key = create_dsa_key(dsa_key_bits);
339 HIP_IFEL(!dsa_key, -EINVAL,
340 "Creation of DSA key failed.\n");
341- if ((err = save_dsa_private_key(dsa_filenamebase, dsa_key))) {
342+ if ((err = save_dsa_private_key(hi_file, dsa_key))) {
343 HIP_ERROR("Saving of DSA key failed.\n");
344 goto out_err;
345 }
346@@ -756,7 +763,7 @@
347 ecdsa_key = create_ecdsa_key(ecdsa_nid);
348 HIP_IFEL(!ecdsa_key, -EINVAL,
349 "Creation of ECDSA key failed.\n");
350- if ((err = save_ecdsa_private_key(ecdsa_filenamebase, ecdsa_key))) {
351+ if ((err = save_ecdsa_private_key(hi_file, ecdsa_key))) {
352 HIP_ERROR("Saving of ECDSA key failed.\n");
353 goto out_err;
354 }
355@@ -765,7 +772,7 @@
356 rsa_key = create_rsa_key(rsa_key_bits);
357 HIP_IFEL(!rsa_key, -EINVAL,
358 "Creation of RSA key failed.\n");
359- if ((err = save_rsa_private_key(rsa_filenamebase, rsa_key))) {
360+ if ((err = save_rsa_private_key(hi_file, rsa_key))) {
361 HIP_ERROR("Saving of RSA key failed.\n");
362 goto out_err;
363 }
364@@ -1093,6 +1100,7 @@
365 change_key_file_perms(rsa_filenamebase_pub);
366 }
367
368+ free(hi_file_dup);
369 free(dsa_host_id);
370 free(dsa_pub_host_id);
371 free(rsa_host_id);
372
373=== added directory 'lib/hipl'
374=== renamed file 'hipd/accessor.c' => 'lib/hipl/accessor.c'
375=== renamed file 'hipd/accessor.h' => 'lib/hipl/accessor.h'
376=== renamed file 'hipd/cert.c' => 'lib/hipl/cert.c'
377=== renamed file 'hipd/cert.h' => 'lib/hipl/cert.h'
378=== renamed file 'hipd/close.c' => 'lib/hipl/close.c'
379=== renamed file 'hipd/close.h' => 'lib/hipl/close.h'
380=== renamed file 'hipd/configfilereader.c' => 'lib/hipl/configfilereader.c'
381=== renamed file 'hipd/configfilereader.h' => 'lib/hipl/configfilereader.h'
382=== renamed file 'hipd/cookie.c' => 'lib/hipl/cookie.c'
383=== renamed file 'hipd/cookie.h' => 'lib/hipl/cookie.h'
384=== renamed file 'hipd/dh.c' => 'lib/hipl/dh.c'
385=== renamed file 'hipd/dh.h' => 'lib/hipl/dh.h'
386=== renamed file 'hipd/esp_prot_anchordb.c' => 'lib/hipl/esp_prot_anchordb.c'
387=== renamed file 'hipd/esp_prot_anchordb.h' => 'lib/hipl/esp_prot_anchordb.h'
388=== renamed file 'hipd/esp_prot_hipd_msg.c' => 'lib/hipl/esp_prot_hipd_msg.c'
389=== renamed file 'hipd/esp_prot_hipd_msg.h' => 'lib/hipl/esp_prot_hipd_msg.h'
390=== renamed file 'hipd/esp_prot_light_update.c' => 'lib/hipl/esp_prot_light_update.c'
391=== renamed file 'hipd/esp_prot_light_update.h' => 'lib/hipl/esp_prot_light_update.h'
392=== renamed file 'hipd/hadb.c' => 'lib/hipl/hadb.c'
393--- hipd/hadb.c 2012-03-20 13:08:56 +0000
394+++ lib/hipl/hadb.c 2012-04-17 15:16:21 +0000
395@@ -608,9 +608,15 @@
396 HIP_HOST_ID_HOSTNAME_LEN_MAX - 1);
397 }
398
399- if (hip_select_source_address(&peer_map.our_addr, &peer_map.peer_addr)) {
400+ /* hip_select_source_address() is incompatible with libhipl, therefore we skip
401+ * this function and set the source address in peer_map to the ANY source
402+ * address.*/
403+ if (!hipl_is_libhip_mode()
404+ && hip_select_source_address(&peer_map.our_addr, &peer_map.peer_addr)) {
405 HIP_ERROR("Cannot find source address\n");
406 return -1;
407+ } else if (hipl_is_libhip_mode()) {
408+ memset(&peer_map.our_addr, 0, sizeof(peer_map.our_addr));
409 }
410
411 if (hip_for_each_hi(hadb_add_peer_info_wrapper, &peer_map)) {
412@@ -1451,6 +1457,10 @@
413 */
414 void hip_delete_security_associations_and_sp(struct hip_hadb_state *const ha)
415 {
416+ if (hipl_is_libhip_mode()) {
417+ return;
418+ }
419+
420 // Delete previous security policies
421 hip_delete_hit_sp_pair(&ha->hit_our, &ha->hit_peer, 1);
422 hip_delete_hit_sp_pair(&ha->hit_peer, &ha->hit_our, 1);
423@@ -1520,6 +1530,11 @@
424 ha),
425 -1, "Error while changing outbound security association\n");
426
427+ if (hipl_is_libhip_mode()) {
428+ HIP_DEBUG("No SP set up in library mode\n");
429+ goto out_err;
430+ }
431+
432 // Create a new security policy pointing to SAs after SA setup
433 HIP_IFEL(hip_setup_hit_sp_pair(&ha->hit_peer,
434 &ha->hit_our,
435
436=== renamed file 'hipd/hadb.h' => 'lib/hipl/hadb.h'
437=== renamed file 'hipd/hidb.c' => 'lib/hipl/hidb.c'
438--- hipd/hidb.c 2012-04-17 11:20:20 +0000
439+++ lib/hipl/hidb.c 2012-04-17 15:16:21 +0000
440@@ -596,13 +596,15 @@
441 hip_add_iface_local_route(&in6_lsi);
442
443 /* Adding HITs and LSIs to the interface */
444- if (hip_add_iface_local_hit(&hit)) {
445- HIP_ERROR("Failed to add HIT to the device\n");
446- return -1;
447- }
448- if (hip_add_iface_local_hit(&in6_lsi)) {
449- HIP_ERROR("Failed to add LSI to the device\n");
450- return -1;
451+ if (!hipl_is_libhip_mode()) {
452+ if (hip_add_iface_local_hit(&hit)) {
453+ HIP_ERROR("Failed to add HIT to the device\n");
454+ return -1;
455+ }
456+ if (hip_add_iface_local_hit(&in6_lsi)) {
457+ HIP_ERROR("Failed to add LSI to the device\n");
458+ return -1;
459+ }
460 }
461 }
462
463
464=== renamed file 'hipd/hidb.h' => 'lib/hipl/hidb.h'
465=== renamed file 'hipd/hip_socket.c' => 'lib/hipl/hip_socket.c'
466=== renamed file 'hipd/hip_socket.h' => 'lib/hipl/hip_socket.h'
467=== renamed file 'hipd/hipd.c' => 'lib/hipl/hipd.c'
468=== renamed file 'hipd/hipd.h' => 'lib/hipl/hipd.h'
469--- hipd/hipd.h 2012-03-20 21:45:03 +0000
470+++ lib/hipl/hipd.h 2012-04-17 15:16:21 +0000
471@@ -27,6 +27,7 @@
472 #define HIPL_HIPD_HIPD_H
473
474 #include <netdb.h>
475+#include <stdbool.h>
476 #include <stdint.h>
477 #include <netinet/in.h>
478 #include <sys/types.h>
479@@ -80,4 +81,8 @@
480 int hipd_parse_cmdline_opts(int argc, char *argv[], uint64_t * flags);
481 int hipd_main(uint64_t flags);
482
483+/* libhip_mode accessor */
484+bool hipl_is_libhip_mode(void);
485+void hipl_set_libhip_mode(void);
486+
487 #endif /* HIPL_HIPD_HIPD_H */
488
489=== renamed file 'hipd/hiprelay.c' => 'lib/hipl/hiprelay.c'
490=== renamed file 'hipd/hiprelay.h' => 'lib/hipl/hiprelay.h'
491=== renamed file 'hipd/hit_to_ip.c' => 'lib/hipl/hit_to_ip.c'
492=== renamed file 'hipd/hit_to_ip.h' => 'lib/hipl/hit_to_ip.h'
493=== renamed file 'hipd/init.c' => 'lib/hipl/init.c'
494--- hipd/init.c 2012-04-16 14:47:42 +0000
495+++ lib/hipl/init.c 2012-04-17 15:16:21 +0000
496@@ -34,7 +34,9 @@
497
498 #include <errno.h>
499 #include <limits.h>
500+#include <pwd.h>
501 #include <signal.h>
502+#include <stdbool.h>
503 #include <stdint.h>
504 #include <stdlib.h>
505 #include <string.h>
506@@ -118,6 +120,34 @@
507 #endif
508 /** end ICMPV6_FILTER related stuff */
509
510+#define HIPL_USER_DIR ".hipl"
511+#define HIPL_USER_RSA_KEY_NAME "hipl_lib_rsa_key"
512+
513+/* Flag to show if hipl is running in libhip mode (=1) or normal mode (=0).
514+ *
515+ * This variable should NOT be accessed directly. Always use the accessor
516+ * functions instead.
517+ */
518+static bool hipd_library_mode = false;
519+
520+/**
521+ * Test if the library mode is on.
522+ *
523+ * @return true if the library mode is on, false otherwise.
524+ */
525+bool hipl_is_libhip_mode(void)
526+{
527+ return hipd_library_mode;
528+}
529+
530+/**
531+ * Turn on library mode.
532+ */
533+void hipl_set_libhip_mode(void)
534+{
535+ hipd_library_mode = true;
536+}
537+
538 /* Startup flags of the HIPD. Keep the around, for they will be used at exit */
539 static uint64_t sflags;
540
541@@ -523,6 +553,199 @@
542 lmod_register_packet_type(HIP_LUPDATE, "HIP_LUPDATE");
543 }
544
545+static int libhip_init_handle_functions(void)
546+{
547+ HIP_DEBUG("Initialize handle functions for libhip.\n");
548+
549+ hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_check_i1, 20000);
550+ hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_handle_i1, 30000);
551+ hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_update_retransmissions, 35000);
552+ hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_send_r1, 40000);
553+ hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_check_i1, 20000);
554+ hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_handle_i1, 30000);
555+ hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_update_retransmissions, 35000);
556+ hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_send_r1, 40000);
557+ hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_check_i1, 20000);
558+ hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_handle_i1, 30000);
559+ hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_update_retransmissions, 35000);
560+ hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_send_r1, 40000);
561+ hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_check_i1, 20000);
562+ hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_handle_i1, 30000);
563+ hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_update_retransmissions, 35000);
564+ hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_send_r1, 40000);
565+ hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_check_i1, 20000);
566+ hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_handle_i1, 30000);
567+ hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 35000);
568+ hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_send_r1, 40000);
569+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_check_i1, 20000);
570+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_handle_i1, 30000);
571+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_update_retransmissions, 35000);
572+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_send_r1, 40000);
573+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_check_i1, 20000);
574+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_handle_i1, 30000);
575+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_update_retransmissions, 35000);
576+ hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_send_r1, 40000);
577+ hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_check_i1, 20000);
578+ hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_handle_i1, 30000);
579+ hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_update_retransmissions, 35000);
580+ hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_send_r1, 40000);
581+
582+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_check_i2, 20000);
583+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_handle_i2, 30000);
584+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_update_retransmissions, 30250);
585+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_create_r2, 40000);
586+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_add_rvs_reg_from, 41000);
587+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_hmac2_and_sign, 42000);
588+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_add_rvs_relay_to, 43000);
589+ hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_send_r2, 50000);
590+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_check_i2, 20000);
591+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_handle_i2, 30000);
592+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_update_retransmissions, 30250);
593+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_create_r2, 40000);
594+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_add_rvs_reg_from, 41000);
595+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_hmac2_and_sign, 42000);
596+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_add_rvs_relay_to, 43000);
597+ hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_send_r2, 50000);
598+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_check_i2, 20000);
599+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2_in_i2_sent, 21000);
600+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2, 30000);
601+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30250);
602+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_create_r2, 40000);
603+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_add_rvs_reg_from, 41000);
604+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_hmac2_and_sign, 42000);
605+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_add_rvs_relay_to, 43000);
606+ hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_send_r2, 50000);
607+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_check_i2, 20000);
608+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_handle_i2, 30000);
609+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_update_retransmissions, 30250);
610+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_create_r2, 40000);
611+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_add_rvs_reg_from, 41000);
612+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_hmac2_and_sign, 42000);
613+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_add_rvs_relay_to, 43000);
614+ hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_send_r2, 50000);
615+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_check_i2, 20000);
616+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_handle_i2, 30000);
617+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 30250);
618+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_create_r2, 40000);
619+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_add_rvs_reg_from, 41000);
620+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_hmac2_and_sign, 42000);
621+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_add_rvs_relay_to, 43000);
622+ hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_send_r2, 50000);
623+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_check_i2, 20000);
624+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_handle_i2, 30000);
625+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_update_retransmissions, 30250);
626+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_create_r2, 40000);
627+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_add_rvs_reg_from, 41000);
628+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_hmac2_and_sign, 42000);
629+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_add_rvs_relay_to, 43000);
630+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_send_r2, 50000);
631+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_check_i2, 20000);
632+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_handle_i2, 30000);
633+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_update_retransmissions, 30250);
634+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_create_r2, 40000);
635+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_add_rvs_reg_from, 41000);
636+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_hmac2_and_sign, 42000);
637+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_add_rvs_relay_to, 43000);
638+ hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_send_r2, 50000);
639+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_check_i2, 20000);
640+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_handle_i2, 30000);
641+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_update_retransmissions, 30250);
642+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_create_r2, 40000);
643+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_add_rvs_reg_from, 41000);
644+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_hmac2_and_sign, 42000);
645+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_add_rvs_relay_to, 43000);
646+ hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_send_r2, 50000);
647+
648+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_check_r1, 20000);
649+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_r1, 30000);
650+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_update_retransmissions, 30500);
651+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_build_esp_info, 31000);
652+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_build_solution, 32000);
653+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_diffie_hellman, 33000);
654+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &esp_prot_r1_handle_transforms, 34000);
655+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_create_i2, 40000);
656+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_add_signed_echo_response, 41000);
657+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_mac_and_sign_handler, 42000);
658+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_add_unsigned_echo_response, 43000);
659+ hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_send_i2, 50000);
660+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_check_r1, 20000);
661+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_r1, 30000);
662+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30500);
663+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_build_esp_info, 31000);
664+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_build_solution, 32000);
665+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_diffie_hellman, 33000);
666+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &esp_prot_r1_handle_transforms, 34000);
667+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_create_i2, 40000);
668+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_add_signed_echo_response, 41000);
669+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_mac_and_sign_handler, 42000);
670+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_add_unsigned_echo_response, 43000);
671+ hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_send_i2, 50000);
672+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_check_r1, 20000);
673+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_r1, 30000);
674+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_update_retransmissions, 30500);
675+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_build_esp_info, 31000);
676+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_build_solution, 32000);
677+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_diffie_hellman, 33000);
678+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &esp_prot_r1_handle_transforms, 34000);
679+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_create_i2, 40000);
680+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_add_signed_echo_response, 41000);
681+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_mac_and_sign_handler, 42000);
682+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_add_unsigned_echo_response, 43000);
683+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_send_i2, 50000);
684+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_check_r1, 20000);
685+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_r1, 30000);
686+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_update_retransmissions, 30500);
687+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_build_esp_info, 31000);
688+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_build_solution, 32000);
689+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_diffie_hellman, 33000);
690+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &esp_prot_r1_handle_transforms, 34000);
691+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_create_i2, 40000);
692+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_add_signed_echo_response, 41000);
693+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_mac_and_sign_handler, 42000);
694+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_add_unsigned_echo_response, 43000);
695+ hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_send_i2, 50000);
696+
697+ hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_check_r2, 20000);
698+ hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_handle_r2, 30000);
699+ hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30250);
700+
701+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, &hip_check_notify, 20000);
702+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, &hip_handle_notify, 30000);
703+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I2_SENT, &hip_check_notify, 20000);
704+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I2_SENT, &hip_handle_notify, 30000);
705+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_R2_SENT, &hip_check_notify, 20000);
706+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_R2_SENT, &hip_handle_notify, 30000);
707+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_ESTABLISHED, &hip_check_notify, 20000);
708+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_ESTABLISHED, &hip_handle_notify, 30000);
709+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSING, &hip_check_notify, 20000);
710+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSING, &hip_handle_notify, 30000);
711+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, &hip_check_notify, 20000);
712+ hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, &hip_handle_notify, 30000);
713+
714+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_check_packet, 20000);
715+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 25000);
716+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_create_response, 30000);
717+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_send_response, 40000);
718+
719+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_check_packet, 20000);
720+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_update_retransmissions, 25000);
721+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_create_response, 30000);
722+ hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_send_response, 40000);
723+
724+ hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_close_ack_check_packet, 20000);
725+ hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_update_retransmissions, 25000);
726+ hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_close_ack_handle_packet, 30000);
727+
728+ hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_close_ack_check_packet, 20000);
729+ hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_update_retransmissions, 25000);
730+ hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_close_ack_handle_packet, 30000);
731+
732+ hip_register_handle_function(HIP_LUPDATE, HIP_STATE_ESTABLISHED, &esp_prot_handle_light_update, 20000);
733+ hip_register_handle_function(HIP_LUPDATE, HIP_STATE_R2_SENT, &esp_prot_handle_light_update, 20000);
734+
735+ return 0;
736+}
737+
738 static int init_handle_functions(void)
739 {
740 int err = 0;
741@@ -1090,6 +1313,80 @@
742 }
743
744 /**
745+ * Initialization function for libhipl.
746+ *
747+ * @param debug_level debug level for log output.
748+ * @return 0 on success, negative number on errors.
749+ */
750+int hipl_lib_init(enum logdebug debug_level)
751+{
752+ int err = 0;
753+ int keypath_len = 0;
754+ char *key_path = NULL;
755+ struct hip_common *msg = NULL;
756+ struct passwd *pwd;
757+
758+ hipl_set_libhip_mode();
759+ hip_nat_status = 1;
760+
761+ /* disable hip_firewall */
762+ lsi_status = HIP_MSG_LSI_OFF;
763+
764+ /* set the initial verbosity level */
765+ hip_set_logdebug(debug_level);
766+
767+ hip_init_hadb();
768+ hip_init_hostid_db();
769+ hip_netdev_init_addresses();
770+ libhip_init_handle_functions();
771+
772+ /* Load default key from ~/.hipl/ */
773+ if ((pwd = getpwuid(getuid())) == NULL) {
774+ return -1;
775+ }
776+
777+ /* +3 because we need 2 slashes and a NULL for termination */
778+ keypath_len = strlen(pwd->pw_dir) +
779+ strlen(HIPL_USER_DIR) +
780+ strlen(HIPL_USER_RSA_KEY_NAME) +
781+ strlen(DEFAULT_PUB_HI_FILE_NAME_SUFFIX) + 3;
782+ if ((key_path = malloc(keypath_len)) == NULL) {
783+ HIP_ERROR("malloc() failed\n");
784+ return -ENOMEM;
785+ }
786+
787+ HIP_IFEL(snprintf(key_path, keypath_len, "%s/%s/%s%s", pwd->pw_dir,
788+ HIPL_USER_DIR,
789+ HIPL_USER_RSA_KEY_NAME,
790+ DEFAULT_PUB_HI_FILE_NAME_SUFFIX) < 0,
791+ -1, "snprintf() failed");
792+
793+ HIP_DEBUG("Using key: %s\n", key_path);
794+ HIP_IFEL(!(msg = hip_msg_alloc()), -ENOMEM, "hip_msg_alloc()");
795+ if (hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa",
796+ key_path, 0, 0, 0)) {
797+ free(msg);
798+ HIP_IFEL(!(msg = hip_msg_alloc()), -ENOMEM, "hip_msg_alloc()");
799+ HIP_IFEL(hip_serialize_host_id_action(msg, ACTION_NEW, 0, 0, "rsa",
800+ key_path, RSA_KEY_DEFAULT_BITS,
801+ DSA_KEY_DEFAULT_BITS,
802+ ECDSA_DEFAULT_CURVE), -1,
803+ "Fail to create local key at %s.", key_path);
804+ free(msg);
805+ HIP_IFE(!(msg = hip_msg_alloc()), -ENOMEM);
806+ HIP_IFEL(hip_serialize_host_id_action(msg, ACTION_ADD, 0, 0, "rsa",
807+ key_path, 0, 0, 0), -1,
808+ "Fail to load local key at %s.", key_path);
809+ }
810+ HIP_IFE(hip_handle_add_local_hi(msg), -1);
811+
812+out_err:
813+ free(msg);
814+ free(key_path);
815+ return err;
816+}
817+
818+/**
819 * create a socket to handle UDP encapsulation of HIP control
820 * packets
821 *
822
823=== renamed file 'hipd/init.h' => 'lib/hipl/init.h'
824--- hipd/init.h 2011-11-25 17:56:24 +0000
825+++ lib/hipl/init.h 2012-04-17 15:16:21 +0000
826@@ -1,5 +1,5 @@
827 /*
828- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
829+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
830 *
831 * Permission is hereby granted, free of charge, to any person
832 * obtaining a copy of this software and associated documentation
833@@ -29,6 +29,8 @@
834 #include <stdint.h>
835 #include <netinet/in.h>
836
837+#include "lib/core/debug.h"
838+
839
840 /* startup flags options to be configured via the command line */
841 #define HIPD_START_FOREGROUND (1 << 0)
842@@ -60,4 +62,6 @@
843 int is_output);
844 void hip_exit(void);
845
846+int hipl_lib_init(enum logdebug);
847+
848 #endif /* HIPL_HIPD_INIT_H */
849
850=== renamed file 'hipd/input.c' => 'lib/hipl/input.c'
851--- hipd/input.c 2012-04-17 11:20:20 +0000
852+++ lib/hipl/input.c 2012-04-17 15:16:21 +0000
853@@ -707,6 +707,11 @@
854 &ctx->src_addr);
855 }
856
857+ if (hipl_is_libhip_mode()) {
858+ ctx->msg_ports.src_port = ctx->hadb_entry->peer_udp_port;
859+ ctx->msg_ports.dst_port = ctx->hadb_entry->local_udp_port;
860+ }
861+
862 hip_relay_add_rvs_to_ha(ctx->input_msg, ctx->hadb_entry);
863
864 #ifdef CONFIG_HIP_RVS
865
866=== renamed file 'hipd/input.h' => 'lib/hipl/input.h'
867=== renamed file 'hipd/keymat.c' => 'lib/hipl/keymat.c'
868=== renamed file 'hipd/keymat.h' => 'lib/hipl/keymat.h'
869=== added file 'lib/hipl/lhipl.c'
870--- lib/hipl/lhipl.c 1970-01-01 00:00:00 +0000
871+++ lib/hipl/lhipl.c 2012-04-17 15:16:21 +0000
872@@ -0,0 +1,536 @@
873+/*
874+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
875+ *
876+ * Permission is hereby granted, free of charge, to any person
877+ * obtaining a copy of this software and associated documentation
878+ * files (the "Software"), to deal in the Software without
879+ * restriction, including without limitation the rights to use,
880+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
881+ * copies of the Software, and to permit persons to whom the
882+ * Software is furnished to do so, subject to the following
883+ * conditions:
884+ *
885+ * The above copyright notice and this permission notice shall be
886+ * included in all copies or substantial portions of the Software.
887+ *
888+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
889+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
890+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
891+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
892+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
893+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
894+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
895+ * OTHER DEALINGS IN THE SOFTWARE.
896+ */
897+
898+/**
899+ * @file
900+ * This file contains the implementation of the libhipl public APIs.
901+ */
902+
903+#define _BSD_SOURCE
904+
905+#include <errno.h>
906+#include <fcntl.h>
907+#include <string.h>
908+#include <unistd.h>
909+
910+#include "lib/core/builder.h"
911+#include "lib/core/ife.h"
912+#include "lib/core/prefix.h"
913+#include "close.h"
914+#include "hadb.h"
915+#include "init.h"
916+#include "lhipl_sock.h"
917+#include "lhipl_operations.h"
918+#include "netdev.h"
919+#include "output.h"
920+#include "lhipl.h"
921+
922+
923+/* A switch to turn off/on BEX feedback.
924+ *
925+ * If it is on, when the BEX process is conducted during "recvmsg" and "sendmsg",
926+ * the intermediate result is returned to the caller.
927+ * If it is off, "recvmsg" and "sendmsg" will only return after the message gets
928+ * sent or received.
929+ */
930+static bool libhipl_bex_feedback;
931+
932+/**
933+ * build a @c sockaddr_in6 address to store peer's HIT and port number from a
934+ * string-based peer name and a port number.
935+ *
936+ * @param peername the string representation of a peer, only support HIT string
937+ * currently.
938+ * @param port the port of the peer.
939+ * @param peer the @c sockaddr_in6 to hold peer's HIT and port number.
940+ * @return 0 on success, -1 on error.
941+ */
942+static int build_peer_hit(const char *peername, const uint16_t port,
943+ struct sockaddr_in6 *peer)
944+{
945+ if (!peername || !peer) {
946+ HIP_ERROR("Invalid input\n");
947+ return -1;
948+ }
949+
950+ if (inet_pton(AF_INET6, peername, &peer->sin6_addr) != 1) {
951+ HIP_ERROR("Failed to translate %s into HIT\n", peername);
952+ }
953+ peer->sin6_port = htons(port);
954+ peer->sin6_family = AF_INET6;
955+ return 0;
956+}
957+
958+/**
959+ * Initialize libhipl library.
960+ *
961+ * This function should be called before using libhipl.
962+ *
963+ * @param debug_level the debug level of the libhipl library.
964+ * @return 0 on success, negative number on error.
965+ */
966+int hipl_lib_init_all(enum hipl_lib_loglv debug_level)
967+{
968+ hipl_hsock_init();
969+ switch (debug_level) {
970+ case HIPL_LIB_LOG_DEBUG:
971+ return hipl_lib_init(LOGDEBUG_ALL);
972+ case HIPL_LIB_LOG_INFO:
973+ return hipl_lib_init(LOGDEBUG_MEDIUM);
974+ case HIPL_LIB_LOG_ERROR:
975+ return hipl_lib_init(LOGDEBUG_LOW);
976+ case HIPL_LIB_LOG_NONE:
977+ return hipl_lib_init(LOGDEBUG_NONE);
978+ }
979+
980+ return -1;
981+}
982+
983+/**
984+ * Check the current state of the BEX feedback switch.
985+ *
986+ * @return true if the switch is on, false if it is off.
987+ */
988+bool hipl_lib_bex_feedback(void)
989+{
990+ return libhipl_bex_feedback;
991+}
992+
993+/**
994+ * Turn off/on the BEX feedback switch.
995+ *
996+ * @param val true to turn the switch on, false to turn it off.
997+ */
998+void hipl_lib_set_bex_feedback(bool val)
999+{
1000+ libhipl_bex_feedback = val;
1001+}
1002+
1003+/**
1004+ * Turn on/off non-blocking feature for a libhipl socket.
1005+ *
1006+ * @param hsock_id ID of the libhipl socket.
1007+ * @param on true to turn on non-blocking, false otherwise.
1008+ * @return 0 on success, negative number on error.
1009+ */
1010+int hipl_lib_set_nonblock(const hipl_sock_id hsock_id, bool on)
1011+{
1012+ int flags;
1013+ struct hipl_sock *hsock = NULL;
1014+
1015+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1016+ HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
1017+ return -EBADF;
1018+ }
1019+
1020+ flags = fcntl(hsock->sock_fd, F_GETFL, 0);
1021+ if (on && !(flags & O_NONBLOCK)) {
1022+ fcntl(hsock->sock_fd, F_SETFL, flags | O_NONBLOCK);
1023+ } else if (!on && (flags & O_NONBLOCK)) {
1024+ fcntl(hsock->sock_fd, F_SETFL, flags & ~O_NONBLOCK);
1025+ }
1026+ return 0;
1027+}
1028+
1029+/**
1030+ * Return the corresponding socket file descriptor of a libhipl socket.
1031+ *
1032+ * @param hsock_id the ID of the libhipl socket
1033+ * @return socket file descriptor on success, -1 on error.
1034+ */
1035+int hipl_lib_get_sockfd(const hipl_sock_id hsock_id)
1036+{
1037+ struct hipl_sock *hsock = NULL;
1038+
1039+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1040+ HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
1041+ return -1;
1042+ }
1043+
1044+ return hsock->sock_fd;
1045+}
1046+
1047+/**
1048+ * Save peer's HIT-to-IP mapping.
1049+ *
1050+ * @param hit peer's hit.
1051+ * @param addr peer's IP address.
1052+ * @return 0 on success, -1 otherwise.
1053+ */
1054+int hipl_add_peer_info(const char *const hit, const char *const addr)
1055+{
1056+ struct in6_addr peer_hit, peer_addr6;
1057+ struct in_addr peer_addr4;
1058+
1059+ if (!hit || !addr) {
1060+ HIP_ERROR("Invalid argument\n");
1061+ return -1;
1062+ }
1063+ if (inet_pton(AF_INET6, hit, &peer_hit) != 1) {
1064+ HIP_ERROR("Invalid hit: %s\n", hit);
1065+ return -1;
1066+ }
1067+ if (!ipv6_addr_is_hit(&peer_hit)) {
1068+ HIP_ERROR("Invalid hit: %s\n", hit);
1069+ return -1;
1070+ }
1071+ if (inet_pton(AF_INET6, addr, &peer_addr6) != 1) {
1072+ if (inet_pton(AF_INET, addr, &peer_addr4) != 1) {
1073+ HIP_ERROR("Invalid address: %s\n", addr);
1074+ return -1;
1075+ }
1076+ IPV4_TO_IPV6_MAP(&peer_addr4, &peer_addr6);
1077+ }
1078+
1079+ return hip_hadb_add_peer_info(&peer_hit, &peer_addr6, NULL, NULL);
1080+}
1081+
1082+/**
1083+ * Create a libhipl socket.
1084+ *
1085+ * @param domain the domain of the libhipl socket (AF_INET / AF_INET6).
1086+ * @param type the type of the libhipl socket (SOCK_DGRAM / SOCK_STREAM).
1087+ * @param protocol the protocol (IPPROTO_UDP / IPPROTO_TCP).
1088+ * @return the ID of the new libhipl socket on success, negative
1089+ * number on error.
1090+ */
1091+int hipl_socket(const int domain, const int type, const int protocol)
1092+{
1093+ if (domain != AF_INET && domain != AF_INET6) {
1094+ HIP_ERROR("Invalid domain: %d\n", domain);
1095+ return -EINVAL;
1096+ }
1097+ if (type != SOCK_DGRAM && type != SOCK_STREAM) {
1098+ HIP_ERROR("Invalid type: %d\n", type);
1099+ return -EINVAL;
1100+ }
1101+ if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
1102+ HIP_ERROR("Invalid protocol: %d\n", protocol);
1103+ return -EINVAL;
1104+ }
1105+
1106+ return hipl_socket_internal(domain, type, protocol);
1107+}
1108+
1109+/**
1110+ * Close a socket.
1111+ *
1112+ * Send HIP CLOSE message to the associated peer and deletes the libhipl
1113+ * socket information.
1114+ *
1115+ * @param hsock_id the ID of the libhipl socket to be closed.
1116+ * @return 0 on success, negative number on error.
1117+ */
1118+int hipl_close(const hipl_sock_id hsock_id)
1119+{
1120+ int ret = 0;
1121+ struct hip_common *msg = NULL;
1122+ struct hipl_sock *hsock = NULL;
1123+
1124+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1125+ HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
1126+ return -1;
1127+ }
1128+ if (!hsock->ha || hsock->ha->state == HIP_STATE_CLOSED) {
1129+ HIP_DEBUG("Not sending CLOSE.\n");
1130+ goto skip_close_msg;
1131+ }
1132+
1133+ /* Build HIP_CLOSE message and send it to the peer */
1134+ if ((msg = hip_msg_alloc()) == NULL) {
1135+ HIP_ERROR("hip_msg_alloc() failed");
1136+ ret = -ENOMEM;
1137+ goto skip_close_msg;
1138+ }
1139+ if ((ret = hip_build_param_contents(msg, &hsock->peer_hit,
1140+ HIP_PARAM_HIT,
1141+ sizeof(hsock->peer_hit))) < 0) {
1142+ HIP_ERROR("hip_build_param_contents() failed\n");
1143+ goto skip_close_msg;
1144+ }
1145+ if ((ret = hip_send_close(msg, 1)) < 0) {
1146+ HIP_ERROR("hip_send_close() failed\n");
1147+ }
1148+
1149+skip_close_msg:
1150+ if (hsock) {
1151+ close(hsock->sock_fd);
1152+ hipl_hsock_delete_and_free(hsock);
1153+ }
1154+ free(msg);
1155+ return ret;
1156+}
1157+
1158+/**
1159+ * Bind a libhipl socket to a local IP address.
1160+ *
1161+ * @param hsock_id the ID of the libhipl socket.
1162+ * @param address the IP address to be bound.
1163+ * @param address_len the length of the @c address.
1164+ * @return 0 on success, negative number on error.
1165+ */
1166+int hipl_bind(const hipl_sock_id hsock_id, const struct sockaddr *const address,
1167+ const socklen_t address_len)
1168+{
1169+ struct hipl_sock *hsock;
1170+
1171+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1172+ HIP_ERROR("ID %d is not a libhipl socket\n", hsock_id);
1173+ return -1;
1174+ }
1175+
1176+ return hipl_bind_internal(hsock, address, address_len);
1177+}
1178+
1179+/**
1180+ * Switch a libhipl socket to listening mode.
1181+ *
1182+ * @param hsock_id the ID of the libhipl socket.
1183+ * @param backlog the max length of the queue for pending connections.
1184+ * @return zero on success, negative number on error.
1185+ */
1186+int hipl_listen(const hipl_sock_id hsock_id, const int backlog)
1187+{
1188+ struct hipl_sock *hsock;
1189+
1190+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1191+ HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
1192+ return -1;
1193+ }
1194+
1195+ return listen(hsock->sock_fd, backlog);
1196+}
1197+
1198+/**
1199+ * Send data to a peer.
1200+ *
1201+ * Triggers base exchange if no HIP association exists.
1202+ * @note Data is currently sent unencrypted.
1203+ *
1204+ * @param hsock_id the ID of the libhipl socket for sending data.
1205+ * @param msg data to send.
1206+ * @param len size of the data.
1207+ * @param flags the flags of the socket function @c sendto().
1208+ * @param peername the string representation of the peer.
1209+ * @param port peer's port number.
1210+ * @return number of bytes sent on success, negative number on error.
1211+ */
1212+int hipl_sendto(const hipl_sock_id hsock_id, const void *const msg,
1213+ const size_t len, const int flags,
1214+ const char *const peername, uint16_t port)
1215+{
1216+ struct hipl_sock *hsock;
1217+ struct sockaddr_in6 peer;
1218+ struct msghdr params = { 0 };
1219+ struct iovec iov;
1220+ char *buf = NULL;
1221+ int err = 0;
1222+
1223+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1224+ HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
1225+ return -1;
1226+ }
1227+ if (hsock->sock_proto == IPPROTO_UDP
1228+ && (peername == NULL || build_peer_hit(peername, port, &peer) < 0)) {
1229+ HIP_ERROR("Invalid argument: peername\n");
1230+ return -EINVAL;
1231+ }
1232+ if (hsock->sock_proto == IPPROTO_TCP
1233+ && hsock->peer_locator.ss_family == 0) {
1234+ HIP_ERROR("Not connected!\n");
1235+ return -ENOTCONN;
1236+ }
1237+ if (msg == NULL) {
1238+ HIP_ERROR("Invalid argument: msg\n");
1239+ return -EINVAL;
1240+ }
1241+
1242+ struct sockaddr_storage dst;
1243+ struct sockaddr_in6 *p6;
1244+ if (hsock->sock_proto == IPPROTO_UDP) {
1245+ hipl_build_addrstorage(&peer.sin6_addr, ntohs(peer.sin6_port), &dst);
1246+ } else {
1247+ dst = hsock->peer_locator;
1248+ p6 = (struct sockaddr_in6 *) &dst;
1249+ p6->sin6_addr = hsock->peer_hit;
1250+ p6->sin6_family = AF_INET6;
1251+ }
1252+ if ((buf = malloc(len)) == NULL) {
1253+ return -ENOMEM;
1254+ }
1255+ memcpy(buf, msg, len);
1256+ iov.iov_base = buf;
1257+ iov.iov_len = len;
1258+ params.msg_name = &dst;
1259+ params.msg_namelen = sizeof(dst);
1260+ params.msg_iovlen = 1;
1261+ params.msg_iov = &iov;
1262+
1263+ if (hipl_lib_bex_feedback()) {
1264+ err = hipl_sendmsg_internal(hsock, &params, flags);
1265+ } else {
1266+ fd_set fdset;
1267+ if (hipl_hsock_ha_state(hsock) == HIP_STATE_UNASSOCIATED) {
1268+ HIP_DEBUG("Sending via hsock %d, Triggering BEX.\n", hsock->sid);
1269+ err = hipl_sendmsg_internal(hsock, &params, flags);
1270+ HIP_IFEL(err != -EWAITBEX, -1, "hipl_sendmsg_internal() failed\n");
1271+ }
1272+ if (hipl_hsock_ha_state(hsock) == HIP_STATE_ESTABLISHED) {
1273+ HIP_DEBUG("Sending via hsock %d, HA established.\n", hsock->sid);
1274+ err = hipl_sendmsg_internal(hsock, &params, flags);
1275+ } else {
1276+ while (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
1277+ FD_ZERO(&fdset);
1278+ FD_SET(hsock->sock_fd, &fdset);
1279+ HIP_DEBUG("Sending via hsock %d, Waiting BEX.\n", hsock->sid);
1280+ err = select(hsock->sock_fd + 1, &fdset, NULL, NULL, NULL);
1281+ HIP_IFEL(err < 0, -1, "select(): %s\n", strerror(errno));
1282+ err = hipl_sendmsg_internal(hsock, &params, flags);
1283+ HIP_IFEL(err < 0 && err != -EWAITBEX && err != -EBEXESTABLISHED,
1284+ -1, "hipl_sendmsg_internal() failed\n");
1285+ }
1286+ err = hipl_sendmsg_internal(hsock, &params, flags);
1287+ }
1288+ }
1289+
1290+out_err:
1291+ free(buf);
1292+ return err;
1293+}
1294+
1295+/**
1296+ * Receive data from a peer.
1297+ *
1298+ * Wait for base exchange if no host association exists.
1299+ * @note Data is currently sent unencrypted.
1300+ *
1301+ * @param hsock_id the ID of the libhipl socket for receiving data.
1302+ * @param buf buffer for received data.
1303+ * @param len the size of the @c buf.
1304+ * @param flags the flags of the socket function @c recvfrom().
1305+ * @param peername buffer for the HIT of the associated peer, the size of
1306+ * this buffer should be at least @c HIPL_MAX_PEERNAME.
1307+ * @param port buffer for the port of the associated peer.
1308+ * @return number of bytes received on success,
1309+ * negative number on error,
1310+ * 0 on end-of-file.
1311+ */
1312+int hipl_recvfrom(const hipl_sock_id hsock_id, void *const buf,
1313+ const size_t len, const int flags,
1314+ char *const peername, uint16_t *const port)
1315+{
1316+ struct hipl_sock *hsock = NULL;
1317+ struct msghdr params = { 0 };
1318+ struct iovec iov;
1319+ struct sockaddr_in6 hit;
1320+ int ret;
1321+
1322+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1323+ HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
1324+ return -1;
1325+ }
1326+ if (hsock->sock_proto == IPPROTO_TCP
1327+ && hsock->peer_locator.ss_family == 0) {
1328+ HIP_ERROR("Not connected!\n");
1329+ return -ENOTCONN;
1330+ }
1331+
1332+ iov.iov_base = buf;
1333+ iov.iov_len = len;
1334+ params.msg_name = &hit;
1335+ params.msg_namelen = sizeof(hit);
1336+ params.msg_iovlen = 1;
1337+ params.msg_iov = &iov;
1338+
1339+ if (!hipl_lib_bex_feedback()) {
1340+ fd_set fdset;
1341+ while (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
1342+ FD_ZERO(&fdset);
1343+ FD_SET(hsock->sock_fd, &fdset);
1344+ if (select(hsock->sock_fd + 1, &fdset, NULL, NULL, NULL) < 0) {
1345+ HIP_PERROR("select()");
1346+ }
1347+ ret = hipl_recvmsg_internal(hsock, &params, flags);
1348+ if (ret < 0 && ret != -EWAITBEX && ret != -EBEXESTABLISHED) {
1349+ HIP_ERROR("hipl_recvmsg_internal() failed()\n");
1350+ return ret;
1351+ }
1352+ }
1353+ }
1354+ ret = hipl_recvmsg_internal(hsock, &params, flags);
1355+
1356+ if (peername) {
1357+ inet_ntop(AF_INET6, &hit.sin6_addr, peername, HIPL_MAX_PEERNAME);
1358+ }
1359+ if (port) {
1360+ *port = ntohs(hit.sin6_port);
1361+ }
1362+ return ret;
1363+}
1364+
1365+/**
1366+ * Initiate a connection to a peer.
1367+ *
1368+ * @param hsock_id the ID of the libhipl socket to initiate a connection.
1369+ * @param peername the string representation of the peer.
1370+ * @param port the port number of the peer.
1371+ * @return 0 on success, negative number on error.
1372+ */
1373+int hipl_connect(const hipl_sock_id hsock_id, const char *peername,
1374+ const uint16_t port)
1375+{
1376+ struct hipl_sock *hsock = NULL;
1377+ struct sockaddr_in6 peer;
1378+
1379+ if (peername == NULL || build_peer_hit(peername, port, &peer) < 0) {
1380+ HIP_ERROR("Invalid argument: peername\n");
1381+ return -EINVAL;
1382+ }
1383+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1384+ HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
1385+ return -1;
1386+ }
1387+
1388+ return hipl_connect_internal(hsock, &peer);
1389+}
1390+
1391+/**
1392+ * Wait for an incoming connection.
1393+ *
1394+ * @param hsock_id the ID of the libhipl socket for waiting connections.
1395+ * @return the ID of the accepted libhipl socket, negative number
1396+ * on error.
1397+ */
1398+int hipl_accept(const hipl_sock_id hsock_id)
1399+{
1400+ struct hipl_sock *hsock = NULL;
1401+
1402+ if ((hsock = hipl_hsock_find(hsock_id)) == NULL) {
1403+ HIP_ERROR("ID %d is not a libhipl socket.\n", hsock_id);
1404+ return -1;
1405+ }
1406+
1407+ return hipl_accept_internal(hsock);
1408+}
1409
1410=== added file 'lib/hipl/lhipl.h'
1411--- lib/hipl/lhipl.h 1970-01-01 00:00:00 +0000
1412+++ lib/hipl/lhipl.h 2012-04-17 15:16:21 +0000
1413@@ -0,0 +1,76 @@
1414+/*
1415+ * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
1416+ *
1417+ * Permission is hereby granted, free of charge, to any person
1418+ * obtaining a copy of this software and associated documentation
1419+ * files (the "Software"), to deal in the Software without
1420+ * restriction, including without limitation the rights to use,
1421+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
1422+ * copies of the Software, and to permit persons to whom the
1423+ * Software is furnished to do so, subject to the following
1424+ * conditions:
1425+ *
1426+ * The above copyright notice and this permission notice shall be
1427+ * included in all copies or substantial portions of the Software.
1428+ *
1429+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1430+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1431+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1432+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1433+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1434+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1435+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1436+ * OTHER DEALINGS IN THE SOFTWARE.
1437+ */
1438+
1439+#ifndef HIPL_LIB_HIPL_LHIPL_H
1440+#define HIPL_LIB_HIPL_LHIPL_H
1441+
1442+#include <sys/socket.h>
1443+#include <stdbool.h>
1444+#include <stdint.h>
1445+
1446+
1447+#define EWAITBEX 139000
1448+#define EBEXESTABLISHED 139001
1449+
1450+#define HIPL_MAX_PEERNAME 128
1451+
1452+enum hipl_lib_loglv { HIPL_LIB_LOG_DEBUG, HIPL_LIB_LOG_INFO,
1453+ HIPL_LIB_LOG_ERROR, HIPL_LIB_LOG_NONE };
1454+
1455+typedef uint16_t hipl_sock_id;
1456+
1457+int hipl_lib_init_all(enum hipl_lib_loglv);
1458+
1459+void hipl_lib_set_bex_feedback(bool val);
1460+bool hipl_lib_bex_feedback(void);
1461+
1462+int hipl_lib_set_nonblock(const hipl_sock_id hsock_id, bool on);
1463+int hipl_lib_get_sockfd(const hipl_sock_id hsock_id);
1464+
1465+int hipl_add_peer_info(const char *const hit, const char *const addr);
1466+
1467+int hipl_socket(const int domain, const int type, const int protocol);
1468+
1469+int hipl_close(const hipl_sock_id hsock_id);
1470+
1471+int hipl_listen(const hipl_sock_id hsock_id, const int backlog);
1472+
1473+int hipl_bind(const hipl_sock_id hsock_id, const struct sockaddr *const address,
1474+ const socklen_t address_len);
1475+
1476+int hipl_sendto(const hipl_sock_id hsock_id, const void *const msg,
1477+ const size_t len, const int flags,
1478+ const char *const peername, const uint16_t port);
1479+
1480+int hipl_recvfrom(const hipl_sock_id hsock_id, void *const buf,
1481+ const size_t len, const int flags,
1482+ char *const peername, uint16_t *const port);
1483+
1484+int hipl_connect(const hipl_sock_id hsock_id, const char *const peername,
1485+ const uint16_t port);
1486+
1487+int hipl_accept(const hipl_sock_id hsock_id);
1488+
1489+#endif /* HIPL_LIB_HIPL_LHIPL_H */
1490
1491=== added file 'lib/hipl/lhipl_operations.c'
1492--- lib/hipl/lhipl_operations.c 1970-01-01 00:00:00 +0000
1493+++ lib/hipl/lhipl_operations.c 2012-04-17 15:16:21 +0000
1494@@ -0,0 +1,771 @@
1495+/*
1496+ * Copyright (c) 2012 Aalto University and RWTH Aachen University.
1497+ *
1498+ * Permission is hereby granted, free of charge, to any person
1499+ * obtaining a copy of this software and associated documentation
1500+ * files (the "Software"), to deal in the Software without
1501+ * restriction, including without limitation the rights to use,
1502+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
1503+ * copies of the Software, and to permit persons to whom the
1504+ * Software is furnished to do so, subject to the following
1505+ * conditions:
1506+ *
1507+ * The above copyright notice and this permission notice shall be
1508+ * included in all copies or substantial portions of the Software.
1509+ *
1510+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1511+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
1512+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1513+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1514+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
1515+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1516+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
1517+ * OTHER DEALINGS IN THE SOFTWARE.
1518+ */
1519+
1520+/**
1521+ * @file
1522+ * This file contains the internal implementation of the libhipl socket
1523+ * related operations.
1524+ */
1525+
1526+#define _BSD_SOURCE
1527+
1528+#include <sys/socket.h>
1529+#include <errno.h>
1530+#include <fcntl.h>
1531+#include <stdbool.h>
1532+#include <string.h>
1533+#include <unistd.h>
1534+
1535+#include "lib/core/builder.h"
1536+#include "lib/core/hip_udp.h"
1537+#include "lib/core/ife.h"
1538+#include "lib/core/prefix.h"
1539+#include "lhipl.h"
1540+#include "lhipl_sock.h"
1541+#include "hadb.h"
1542+#include "hidb.h"
1543+#include "input.h"
1544+#include "netdev.h"
1545+#include "output.h"
1546+#include "lhipl_operations.h"
1547+
1548+
1549+/**
1550+ * Automatically bind to a port for a libhipl socket.
1551+ *
1552+ * @param hsock the libhipl socket for port binding.
1553+ * @return 0 on success, -1 on error.
1554+ */
1555+static int auto_bind(struct hipl_sock *const hsock)
1556+{
1557+ struct sockaddr_storage ss = { 0 };
1558+ struct sockaddr_in *addr4;
1559+ struct sockaddr_in6 *addr6;
1560+
1561+ if (hsock->src_port != 0) {
1562+ HIP_DEBUG("A bound port exists, auto_bind stops\n");
1563+ return 0;
1564+ }
1565+
1566+ if (hsock->sock_family == AF_INET) {
1567+ ss.ss_family = AF_INET;
1568+ addr4 = (struct sockaddr_in *) &ss;
1569+ addr4->sin_port = 0;
1570+ return hipl_bind_internal(hsock, (struct sockaddr *) addr4,
1571+ sizeof(ss));
1572+ } else {
1573+ ss.ss_family = AF_INET6;
1574+ addr6 = (struct sockaddr_in6 *) &ss;
1575+ addr6->sin6_port = 0;
1576+ return hipl_bind_internal(hsock, (struct sockaddr *) addr6,
1577+ sizeof(ss));
1578+ }
1579+}
1580+
1581+static uint16_t get_port_from_saddr(const struct sockaddr *const addr)
1582+{
1583+ const struct sockaddr_in *addr4 = (const struct sockaddr_in *) addr;
1584+ const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *) addr;
1585+
1586+ if (addr->sa_family == AF_INET) {
1587+ return addr4->sin_port;
1588+ } else {
1589+ return addr6->sin6_port;
1590+ }
1591+}
1592+
1593+/**
1594+ * Set global variables in order to inter-operate with libhipdeamon.
1595+ *
1596+ * @param sock_fd the socket file descriptor for sending message.
1597+ * @param local_port the local port for sending message.
1598+ * @param remote_port the remote port for receiving message.
1599+ */
1600+static void set_hip_connection_parameters(const int sock_fd,
1601+ const int local_port,
1602+ const int remote_port)
1603+{
1604+ HIP_DEBUG("Set connection params: fd = %d, lport = %d, rport= %d\n",
1605+ sock_fd, local_port, remote_port);
1606+ hip_nat_sock_output_udp = sock_fd;
1607+ hip_raw_sock_output_v4 = sock_fd;
1608+ hip_raw_sock_output_v6 = sock_fd;
1609+ hip_set_local_nat_udp_port(local_port);
1610+ hip_set_peer_nat_udp_port(remote_port);
1611+}
1612+
1613+/**
1614+ * Check whether a received packet is a HIP control packet.
1615+ *
1616+ * @param buf buffer containing the received packet.
1617+ * @param len size of the @c buf.
1618+ * @param hsock the libhipl socket receiving the packet.
1619+ * @return 1 on a control message, 0 on a user message,
1620+ * negative number on error.
1621+ */
1622+static int hipl_is_control_msg(char *const buf, unsigned int len,
1623+ struct hipl_sock *const hsock)
1624+{
1625+ char udp_pad[HIP_UDP_ZERO_BYTES_LEN] = { 0 };
1626+ struct hip_common *msg;
1627+ struct sockaddr_storage src = { 0 };
1628+ socklen_t srclen = sizeof(src);
1629+
1630+ if (len < sizeof(struct hip_common)) {
1631+ return 0;
1632+ }
1633+
1634+ if (!memcmp(udp_pad, buf, HIP_UDP_ZERO_BYTES_LEN)) {
1635+ HIP_DEBUG("Message is padded\n");
1636+ msg = (struct hip_common *) (buf + HIP_UDP_ZERO_BYTES_LEN);
1637+ len -= HIP_UDP_ZERO_BYTES_LEN;
1638+ } else {
1639+ msg = (struct hip_common *) buf;
1640+ }
1641+
1642+ if (getsockname(hsock->sock_fd, (struct sockaddr *) &src, &srclen) < 0) {
1643+ HIP_PERROR("getsockname()");
1644+ return true;
1645+ }
1646+
1647+ return !hip_verify_network_header(msg, (struct sockaddr *) &src,
1648+ (struct sockaddr *) &hsock->peer_locator,
1649+ len);
1650+}
1651+
1652+static void build_packet_context(struct hip_packet_context *const ctx,
1653+ struct sockaddr *ctx_dst, struct sockaddr *ctx_src)
1654+{
1655+ struct sockaddr_in *s4;
1656+ struct sockaddr_in6 *s6;
1657+
1658+ if (ctx_dst->sa_family == AF_INET) {
1659+ s4 = (struct sockaddr_in *) ctx_dst;
1660+ IPV4_TO_IPV6_MAP(&s4->sin_addr, &ctx->dst_addr);
1661+ ctx->msg_ports.dst_port = ntohs(s4->sin_port);
1662+ } else if (ctx_dst->sa_family == AF_INET6) {
1663+ s6 = (struct sockaddr_in6 *) ctx_dst;
1664+ ctx->dst_addr = s6->sin6_addr;
1665+ ctx->msg_ports.dst_port = ntohs(s6->sin6_port);
1666+ }
1667+
1668+ if (ctx_src->sa_family == AF_INET) {
1669+ s4 = (struct sockaddr_in *) ctx_src;
1670+ IPV4_TO_IPV6_MAP(&s4->sin_addr, &ctx->src_addr);
1671+ ctx->msg_ports.src_port = ntohs(s4->sin_port);
1672+ } else if (ctx_src->sa_family == AF_INET6) {
1673+ s6 = (struct sockaddr_in6 *) ctx_src;
1674+ ctx->src_addr = s6->sin6_addr;
1675+ ctx->msg_ports.src_port = ntohs(s6->sin6_port);
1676+ }
1677+}
1678+
1679+/**
1680+ * Receive and pre-process an incoming message.
1681+ *
1682+ * This function discards UDP packet from an unknown peer, identifies
1683+ * user/control packet, eliminates zero padding in control packets and
1684+ * builds the packet context for handling control packets.
1685+ *
1686+ * @param hsock the libhipl socket for receiving message.
1687+ * @param msg buffer to hold the incoming message.
1688+ * @param flags the flags of socket @c recvmsg().
1689+ * @param ctx the HIP packet context to be built.
1690+ * @param is_user_msg true if the message is a user message, false otherwise.
1691+ * @return negative number on errors, 0 on end-of-file, number of
1692+ * bytes received otherwise.
1693+ */
1694+static int recv_msg_wrapper(struct hipl_sock *const hsock,
1695+ struct msghdr *const msg, const int flags,
1696+ struct hip_packet_context *const ctx,
1697+ bool *is_user_msg)
1698+{
1699+ int ret;
1700+ struct sockaddr_storage our_locator = { 0 };
1701+ socklen_t sslen = sizeof(our_locator);
1702+
1703+ *is_user_msg = true;
1704+ if ((ret = recvmsg(hsock->sock_fd, msg, flags)) < 0) {
1705+ HIP_PERROR("recvmsg()");
1706+ return -1;
1707+ }
1708+
1709+ //in UDP mode, we don't know the peer locator until we receive the
1710+ //first message from the peer. Once we get the peer locator, save it
1711+ //to 'hsock'. We should also fill the packet context for UDP.
1712+ if (hsock->sock_proto == IPPROTO_UDP) {
1713+ if (msg->msg_name != NULL && hsock->peer_locator.ss_family == 0) {
1714+ memcpy(&hsock->peer_locator, msg->msg_name,
1715+ sizeof(hsock->peer_locator));
1716+ }
1717+ if (ctx != NULL) {
1718+ if (getsockname(hsock->sock_fd, (struct sockaddr *) &our_locator,
1719+ &sslen) < 0) {
1720+ HIP_PERROR("getsockname()");
1721+ return -1;
1722+ }
1723+ build_packet_context(ctx, (struct sockaddr *) &our_locator,
1724+ (struct sockaddr *) &hsock->peer_locator);
1725+ }
1726+ }
1727+
1728+ char *buf = (char *) msg->msg_iov->iov_base;
1729+ if (hipl_is_control_msg(buf, ret, hsock)) {
1730+ memmove(buf, buf + HIP_UDP_ZERO_BYTES_LEN,
1731+ HIP_MAX_PACKET - HIP_UDP_ZERO_BYTES_LEN);
1732+ ret -= HIP_UDP_ZERO_BYTES_LEN;
1733+ *is_user_msg = false;
1734+ }
1735+
1736+ return ret;
1737+}
1738+
1739+static int nonb_result_check(const int ret, const int err)
1740+{
1741+ if (ret < 0 && err != EWOULDBLOCK && err != EAGAIN) {
1742+ HIP_ERROR("BEX failed, errno = %d, errstr = %s\n", err,
1743+ strerror(err));
1744+ return -1;
1745+ }
1746+ if (ret < 0 && (err == EWOULDBLOCK || err == EAGAIN)) {
1747+ HIP_DEBUG("BEX returns EWOULDBLOCK or EAGAIN\n");
1748+ return -EWAITBEX;
1749+ }
1750+
1751+ return 0;
1752+}
1753+
1754+/**
1755+ * Wait for a HIP I1 packet and continue performing base exchange.
1756+ *
1757+ * @param hsock the libhipl socket waiting for the I1 packet.
1758+ * @param ctx the HIP packet context for HIP packet processing.
1759+ * @return 0 on success, -1 on error, -EWAITBEX when BEX is pending
1760+ */
1761+static int nonb_await_bex(struct hipl_sock *const hsock,
1762+ struct hip_packet_context *const ctx)
1763+{
1764+ struct msghdr params = { 0 };
1765+ struct iovec iov;
1766+ struct sockaddr_storage ss;
1767+ bool is_user_msg;
1768+ int ret = 0;
1769+ int flag;
1770+
1771+ params.msg_name = &ss;
1772+ params.msg_namelen = sizeof(ss);
1773+ params.msg_iovlen = 1;
1774+ iov.iov_base = ctx->input_msg;
1775+ iov.iov_len = HIP_MAX_PACKET;
1776+ params.msg_iov = &iov;
1777+
1778+ flag = fcntl(hsock->sock_fd, F_GETFL, 0);
1779+ fcntl(hsock->sock_fd, F_SETFL, flag | O_NONBLOCK);
1780+
1781+ set_hip_connection_parameters(hsock->sock_fd, hsock->src_port, 0);
1782+ ret = recv_msg_wrapper(hsock, &params, 0, ctx, &is_user_msg);
1783+ if ((ret = nonb_result_check(ret, errno)) != 0) {
1784+ HIP_DEBUG("returns %d\n", ret);
1785+ goto out;
1786+ }
1787+
1788+ if (is_user_msg || hip_receive_control_packet(ctx) < 0) {
1789+ HIP_ERROR("hip_receive_control_packet() failed\n");
1790+ ret = -1;
1791+ }
1792+
1793+out:
1794+ fcntl(hsock->sock_fd, F_SETFL, flag);
1795+ return ret;
1796+}
1797+
1798+/**
1799+ * Trigger BEX in a non-blocking way.
1800+ *
1801+ * @param hsock the libhipl socket to trigger BEX.
1802+ * @param src_hit the source HIT for base exchange.
1803+ * @param dst_hit the destination HIT for base exchange.
1804+ * @param dst_port the destination port.
1805+ * @return -1 on error, -EWAITBEX when the BEX is pending, 0 if sending
1806+ * BEX trigger message successfully.
1807+ */
1808+static int nonb_trigger_bex(struct hipl_sock *hsock, const hip_hit_t *src_hit,
1809+ const hip_hit_t *dst_hit, const int dst_port)
1810+{
1811+ struct in6_addr dst_addr;
1812+ int err = 0, flag;
1813+
1814+ flag = fcntl(hsock->sock_fd, F_GETFL, 0);
1815+ fcntl(hsock->sock_fd, F_SETFL, flag | O_NONBLOCK);
1816+
1817+ err = hip_map_id_to_addr(dst_hit, NULL, &dst_addr);
1818+ HIP_IFEL(err < 0, -1, "failed to match hit to IP\n");
1819+ HIP_IFEL(ipv6_addr_any(&dst_addr), -1, "Couldn't map HIT to IP\n");
1820+
1821+ set_hip_connection_parameters(hsock->sock_fd, hsock->src_port, dst_port);
1822+ err = netdev_trigger_bex(src_hit, dst_hit, NULL, NULL, NULL, &dst_addr);
1823+ HIP_DEBUG("netdev_trigger_bex returns %d, errno = %d\n", err, errno);
1824+ err = nonb_result_check(err, errno);
1825+ if (err == 0) {
1826+ hsock->ha = hip_hadb_find_byhits(src_hit, dst_hit);
1827+ }
1828+
1829+out_err:
1830+ fcntl(hsock->sock_fd, F_SETFL, flag);
1831+ return err;
1832+}
1833+
1834+/**
1835+ * Handle BEX for a libhipl socket.
1836+ *
1837+ * If param @c peer_hit is given, current libhipl socket will be the initiator
1838+ * and trigger the BEX. otherwise, it acts as a responder and waits for an I1
1839+ * message.
1840+ *
1841+ * @param hsock the libhipl socket to handle BEX.
1842+ * @param peer_hit the peer's hit and port.
1843+ * @return -1 on error, -EWAITBEX when the BEX is pending, and
1844+ * -EBEXESTABLISHED when BEX finishes.
1845+ */
1846+static int handle_bex(struct hipl_sock *hsock, struct sockaddr_in6 *peer_hit)
1847+{
1848+ int err = 0;
1849+ struct hip_packet_context ctx = { 0 };
1850+
1851+ // We are the initiator, send I1
1852+ if (hipl_hsock_ha_state(hsock) == HIP_STATE_UNASSOCIATED && peer_hit) {
1853+ hsock->peer_hit = peer_hit->sin6_addr;
1854+
1855+ err = nonb_trigger_bex(hsock, &hsock->src_hit, &peer_hit->sin6_addr,
1856+ ntohs(peer_hit->sin6_port));
1857+ // send I1 successfully, return -EWAITBEX.
1858+ if (err == 0) {
1859+ err = -EWAITBEX;
1860+ }
1861+ return err;
1862+ }
1863+
1864+ // waiting for and handle control messages
1865+ hsock->ha = hip_hadb_find_byhits(&hsock->src_hit, &hsock->peer_hit);
1866+ if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
1867+ ctx.input_msg = hip_msg_alloc();
1868+ ctx.output_msg = hip_msg_alloc();
1869+ HIP_IFEL(!ctx.input_msg || !ctx.output_msg, -ENOMEM,
1870+ "hip_msg_alloc() failed\n");
1871+
1872+ err = nonb_await_bex(hsock, &ctx);
1873+ HIP_DEBUG("nonb_await_bex returns %d\n", err);
1874+ if (err < 0) { /* -1 or -EWAITBEX */
1875+ goto out_err;
1876+ }
1877+ hsock->peer_hit = ctx.input_msg->hit_sender;
1878+ hsock->ha = hip_hadb_find_byhits(&hsock->src_hit, &hsock->peer_hit);
1879+ }
1880+
1881+ if (hipl_hsock_ha_state(hsock) == HIP_STATE_ESTABLISHED) {
1882+ err = -EBEXESTABLISHED;
1883+ } else {
1884+ err = -EWAITBEX;
1885+ }
1886+
1887+out_err:
1888+ free(ctx.input_msg);
1889+ free(ctx.output_msg);
1890+ return err;
1891+}
1892+
1893+static int validate_udp_peer_addr(const struct hipl_sock *const hsock,
1894+ const struct sockaddr_storage *const saddr)
1895+{
1896+ const struct in6_addr *paddr;
1897+ struct in6_addr peer_addr;
1898+
1899+ if (hsock->sock_proto != IPPROTO_UDP) {
1900+ return 0;
1901+ }
1902+
1903+ switch (saddr->ss_family) {
1904+ case AF_INET:
1905+ IPV4_TO_IPV6_MAP(&((const struct sockaddr_in *) saddr)->sin_addr,
1906+ &peer_addr);
1907+ paddr = &peer_addr;
1908+ break;
1909+
1910+ case AF_INET6:
1911+ paddr = &((const struct sockaddr_in6 *) saddr)->sin6_addr;
1912+ break;
1913+
1914+ default:
1915+ HIP_DEBUG("Unsupported family: %d\n", saddr->ss_family);
1916+ return -1;
1917+ }
1918+
1919+ if (ipv6_addr_cmp(&hsock->ha->peer_addr, paddr)) {
1920+ HIP_DEBUG("Packet not from associated address. Dropping.\n");
1921+ HIP_DEBUG_IN6ADDR("expected", &hsock->ha->peer_addr);
1922+ HIP_DEBUG_IN6ADDR("got", paddr);
1923+ return -1;
1924+ }
1925+
1926+ return 0;
1927+}
1928+
1929+/**
1930+ * Build a @c sockaddr_storage from a given IPv6 address and a port number.
1931+ *
1932+ * If the address is V4MAPPED, the storage family will be @c AF_INET,
1933+ * otherwise the storage family will be @c AF_INET6.
1934+ *
1935+ * @param addr a V6 address or a V4MAPPED address.
1936+ * @param port the port number.
1937+ * @param ss the @c sockaddr_storage to be filled.
1938+ */
1939+void hipl_build_addrstorage(const struct in6_addr *const addr,
1940+ const uint16_t port,
1941+ struct sockaddr_storage *const ss)
1942+{
1943+ HIP_ASSERT(addr && ss);
1944+ memset(ss, 0, sizeof(*ss));
1945+
1946+ if (IN6_IS_ADDR_V4MAPPED(addr)) {
1947+ struct sockaddr_in *const in = (struct sockaddr_in *) ss;
1948+ in->sin_family = AF_INET;
1949+ IPV6_TO_IPV4_MAP(addr, &in->sin_addr);
1950+ in->sin_port = htons(port);
1951+ } else {
1952+ struct sockaddr_in6 *const in6 = (struct sockaddr_in6 *) ss;
1953+ in6->sin6_family = AF_INET6;
1954+ ipv6_addr_copy(&in6->sin6_addr, addr);
1955+ in6->sin6_port = htons(port);
1956+ }
1957+}
1958+
1959+/**
1960+ * Create a libhipl socket.
1961+ *
1962+ * @param family the communications domain of the libhipl socket
1963+ * @param type the socket type of the libhipl socket
1964+ * @param protocol the protocol of the libhipl socket
1965+ * @return the ID of the new libhipl socket on success, negative
1966+ * number otherwise
1967+ */
1968+int hipl_socket_internal(const int family, const int type, const int protocol)
1969+{
1970+ int sock;
1971+ int on = 1, off = 0;
1972+ struct hipl_sock *hsock = NULL;
1973+
1974+ //TODO support IPV6
1975+ if (family == AF_INET6) {
1976+ HIP_ERROR("No IPv6 support yet.\n");
1977+ return -ENOTSUP;
1978+ }
1979+
1980+ sock = socket(family, type, protocol);
1981+ if (family == AF_INET) {
1982+ setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
1983+ setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
1984+ setsockopt(sock, IPPROTO_IP, IP_RECVERR, &off, sizeof(off));
1985+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1986+ } else {
1987+ setsockopt(sock, IPPROTO_IPV6, IPV6_RECVERR, &off, sizeof(off));
1988+ setsockopt(sock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on));
1989+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1990+ }
1991+ if ((hsock = hipl_hsock_new(family, type, protocol)) == NULL) {
1992+ HIP_ERROR("Failed to create libhipl socket.\n");
1993+ close(sock);
1994+ return -1;
1995+ }
1996+ hsock->sock_fd = sock;
1997+ hip_get_default_hit(&hsock->src_hit);
1998+
1999+ return hsock->sid;
2000+}
2001+
2002+/**
2003+ * Bind a libhipl socket to a local address.
2004+ *
2005+ * @param hsock the libhipl socket for address binding.
2006+ * @param address the IP address to be bound.
2007+ * @param address_len the length of the @c address.
2008+ * @return 0 on success, -1 on error.
2009+ */
2010+int hipl_bind_internal(struct hipl_sock *const hsock,
2011+ const struct sockaddr *const address,
2012+ const socklen_t address_len)
2013+{
2014+ struct sockaddr_storage laddr = { 0 };
2015+ socklen_t laddr_len = sizeof(laddr);
2016+ uint16_t request_port;
2017+
2018+ request_port = get_port_from_saddr(address);
2019+ if (bind(hsock->sock_fd, address, address_len) < 0) {
2020+ HIP_PERROR("bind error:");
2021+ return -1;
2022+ }
2023+
2024+ /* Ask OS for the assigned port number */
2025+ if (request_port == 0) {
2026+ if (0 > getsockname(hsock->sock_fd, (struct sockaddr *) &laddr,
2027+ &laddr_len)) {
2028+ HIP_PERROR("getsockname() error: ");
2029+ return -1;
2030+ }
2031+ request_port = get_port_from_saddr((struct sockaddr *) &laddr);
2032+ }
2033+
2034+ hsock->src_port = ntohs(request_port);
2035+ HIP_DEBUG("bind to port %d\n", hsock->src_port);
2036+
2037+ return 0;
2038+}
2039+
2040+/**
2041+ * Initiate a connection to a peer.
2042+ *
2043+ * @param hsock the libhipl socket to initiate the connection.
2044+ * @param peer the peer's HIT and port number.
2045+ * @return 0 on success, -1 on error.
2046+ */
2047+int hipl_connect_internal(struct hipl_sock *const hsock,
2048+ const struct sockaddr_in6 *const peer)
2049+{
2050+ struct in6_addr dst_addr = { { { 0 } } };
2051+ struct sockaddr_storage ss;
2052+
2053+ if (ipv6_addr_any(&peer->sin6_addr)) {
2054+ HIP_ERROR("Invalid argument: dst_hit.\n");
2055+ return -1;
2056+ }
2057+
2058+ if (hip_map_id_to_addr(&peer->sin6_addr, NULL, &dst_addr) < 0) {
2059+ return -1;
2060+ }
2061+ if (ipv6_addr_any(&dst_addr)) {
2062+ HIP_ERROR("Couldn't map HIT to IP\n");
2063+ return -1;
2064+ }
2065+
2066+ HIP_DEBUG_IN6ADDR("Dest locator is: ", &dst_addr);
2067+ HIP_DEBUG("Dest locator is V4MAPPED: %d\n", IN6_IS_ADDR_V4MAPPED(&dst_addr));
2068+ hipl_build_addrstorage(&dst_addr, ntohs(peer->sin6_port), &ss);
2069+
2070+ if (connect(hsock->sock_fd, (struct sockaddr *) &ss, sizeof(ss)) < 0) {
2071+ HIP_ERROR("connect(): %s\n", strerror(errno));
2072+ return -1;
2073+ }
2074+
2075+ /* Save related information into hsock */
2076+ hsock->peer_hit = peer->sin6_addr;
2077+ hsock->peer_locator = ss;
2078+ if (hsock->src_port == 0) {
2079+ socklen_t taddr_len = sizeof(ss);
2080+
2081+ if (getsockname(hsock->sock_fd, (struct sockaddr *) &ss,
2082+ &taddr_len) < 0) {
2083+ HIP_PERROR("getsockname() error: ");
2084+ return -1;
2085+ }
2086+ hsock->src_port = ntohs(get_port_from_saddr((struct sockaddr *) &ss));
2087+ }
2088+
2089+ return 0;
2090+}
2091+
2092+/**
2093+ * Wait for an incoming connection on a libhipl socket.
2094+ *
2095+ * @param hsock the libhipl socket waiting for the connection.
2096+ * @return the ID of the accepted libhipl socket on success, -1 on error.
2097+ */
2098+int hipl_accept_internal(struct hipl_sock *const hsock)
2099+{
2100+ int new_fd;
2101+ struct hipl_sock *hsock_new = NULL;
2102+ struct sockaddr_storage ss = { 0 };
2103+ socklen_t ss_len = sizeof(ss);
2104+
2105+ new_fd = accept(hsock->sock_fd, (struct sockaddr *) &ss, &ss_len);
2106+ if (new_fd < 0) {
2107+ HIP_PERROR("accept(): ");
2108+ return -1;
2109+ }
2110+
2111+ hsock_new = hipl_hsock_new(hsock->sock_family, hsock->sock_type,
2112+ hsock->sock_proto);
2113+ hsock_new->src_port = hsock->src_port;
2114+ hsock_new->src_hit = hsock->src_hit;
2115+ hsock_new->sock_fd = new_fd;
2116+ hsock_new->peer_locator = ss;
2117+
2118+ return hsock_new->sid;
2119+}
2120+
2121+/**
2122+ * Receive data from a remote peer.
2123+ *
2124+ * Wait for base exchange if no host association exists.
2125+ * @note Data is currently sent unencrypted.
2126+ * @note Scatter read is not supported yet.
2127+ *
2128+ * @param hsock the libhipl socket for receiving data.
2129+ * @param msg the buffer to hold data and peer information.
2130+ * @param flags the flags of the socket function @c recvmsg().
2131+ * @return number of bytes received on success,
2132+ * 0 on end-of-file,
2133+ * -EWAITBEX when the BEX is pending,
2134+ * -EBEXESTABLISHED when BEX finishes,
2135+ * other negative numbers on error.
2136+ */
2137+ssize_t hipl_recvmsg_internal(struct hipl_sock *const hsock,
2138+ struct msghdr *const msg,
2139+ const int flags)
2140+{
2141+ struct hip_packet_context ctx = { 0 };
2142+ struct msghdr params = { 0 };
2143+ struct iovec iov;
2144+ struct sockaddr_storage recv_remote_addr;
2145+ int err = 0;
2146+ bool is_user_msg;
2147+
2148+ if (msg->msg_iovlen != 1) {
2149+ HIP_ERROR("Invalid iovlen: %d, scatter read is not supported yet\n",
2150+ msg->msg_iovlen);
2151+ return -ENOTSUP;
2152+ }
2153+
2154+ /* Bind to an ephemeral port if the src port hasn't been bound yet */
2155+ if (auto_bind(hsock)) {
2156+ HIP_ERROR("Fail to bind the hip socket.\n");
2157+ return -1;
2158+ }
2159+
2160+ /* Handle BEX if HA hasn't established */
2161+ if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED
2162+ && hipl_hsock_ha_state(hsock) != HIP_STATE_CLOSING) {
2163+ return handle_bex(hsock, NULL);
2164+ }
2165+
2166+ ctx.input_msg = hip_msg_alloc();
2167+ ctx.output_msg = hip_msg_alloc();
2168+ HIP_IFEL(!ctx.input_msg || !ctx.output_msg, -ENOMEM,
2169+ "hip_msg_alloc() failed\n");
2170+ params.msg_name = &recv_remote_addr;
2171+ params.msg_namelen = sizeof(recv_remote_addr);
2172+ params.msg_iovlen = 1;
2173+ iov.iov_base = ctx.input_msg;
2174+ iov.iov_len = HIP_MAX_PACKET;
2175+ params.msg_iov = &iov;
2176+
2177+ err = recv_msg_wrapper(hsock, &params, flags, &ctx, &is_user_msg);
2178+ HIP_IFEL(err < 0, -1, "recv_msg_wrapper() failed\n");
2179+
2180+ if (validate_udp_peer_addr(hsock, &recv_remote_addr) < 0) {
2181+ HIP_IFEL(true, -EAGAIN,
2182+ "Received a packet with invalid peer address, dropping.\n");
2183+ }
2184+ if (!is_user_msg) {
2185+ HIP_DEBUG("receive a hip control message.\n");
2186+ hip_receive_control_packet(&ctx);
2187+ if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
2188+ HIP_DEBUG("HA state change to %d, return 0.\n", hsock->ha->state);
2189+ return 0;
2190+ }
2191+ } else {
2192+ HIP_DEBUG("receive a user message.\n");
2193+ // TODO, if buffer size is too small, we should save it to a internal buffer
2194+ // and only return content with length specified by user's buffer (TCP).
2195+ // return error for UDP in this case.
2196+ struct iovec *iovp;
2197+ struct sockaddr_in6 *hitp;
2198+ hitp = msg->msg_name;
2199+ iovp = msg->msg_iov;
2200+ HIP_IFEL(iovp->iov_len < (unsigned int) err, -1,
2201+ "buffer size too small\n");
2202+ HIP_DEBUG_HIT("ha->hit_peer:", &hsock->ha->hit_peer);
2203+ hitp->sin6_family = AF_INET6;
2204+ hitp->sin6_port = get_port_from_saddr((const struct sockaddr *) &hsock->peer_locator);
2205+ HIP_DEBUG("hitp port: %d\n", ntohs(hitp->sin6_port));
2206+ hitp->sin6_addr = hsock->ha->hit_peer;
2207+ memcpy(iovp->iov_base, ctx.input_msg, err);
2208+ }
2209+
2210+out_err:
2211+ free(ctx.input_msg);
2212+ free(ctx.output_msg);
2213+ return err;
2214+}
2215+
2216+/**
2217+ * Send data to a peer.
2218+ *
2219+ * Trigger base exchange if no host association exists.
2220+ * @note Data is currently sent unencrypted.
2221+ * @note Gather write is not supported yet.
2222+ *
2223+ * @param hsock the libhipl socket for sending data.
2224+ * @param msg containing data, and peer information.
2225+ * @param flags the flags of the socket function @c sendmsg().
2226+ * @return number of bytes sent on success,
2227+ * -EWAITBEX if the BEX is pending,
2228+ * -EBEXESTABLISHED if the BEX finishes,
2229+ * other negative number on error.
2230+ */
2231+ssize_t hipl_sendmsg_internal(struct hipl_sock *const hsock,
2232+ struct msghdr *const msg,
2233+ const int flags)
2234+{
2235+ int fd = hsock->sock_fd;
2236+
2237+ /* Gather write is not supported yet */
2238+ if (msg->msg_iovlen > 1) {
2239+ HIP_ERROR("Invalid iovlen: %d, gather write is not supported\n",
2240+ msg->msg_iovlen);
2241+ return -ENOTSUP;
2242+ }
2243+
2244+ /* Bind to an ephemeral port if the src port hasn't been bound yet */
2245+ if (auto_bind(hsock)) {
2246+ HIP_ERROR("Fail to bind the hip socket.\n");
2247+ return -1;
2248+ }
2249+
2250+ /* Start BEX if HA hasn't established */
2251+ if (hipl_hsock_ha_state(hsock) != HIP_STATE_ESTABLISHED) {
2252+ return handle_bex(hsock, msg->msg_name);
2253+ }
2254+
2255+ /* Determine peer's locator and send out the message */
2256+ HIP_DEBUG("BEX ok, start to send user data\n");
2257+ if (hsock->peer_locator.ss_family == 0) {
2258+ hipl_build_addrstorage(&hsock->ha->peer_addr,
2259+ hsock->ha->peer_udp_port,
2260+ &hsock->peer_locator);
2261+ }
2262+ msg->msg_namelen = sizeof(hsock->peer_locator);
2263+ memcpy(msg->msg_name, &hsock->peer_locator, msg->msg_namelen);
2264+ return sendmsg(fd, msg, flags);
2265+}
2266
2267=== added file 'lib/hipl/lhipl_operations.h'
2268--- lib/hipl/lhipl_operations.h 1970-01-01 00:00:00 +0000
2269+++ lib/hipl/lhipl_operations.h 2012-04-17 15:16:21 +0000
2270@@ -0,0 +1,55 @@
2271+/*
2272+ * Copyright (c) 2012 Aalto University and RWTH Aachen University.
2273+ *
2274+ * Permission is hereby granted, free of charge, to any person
2275+ * obtaining a copy of this software and associated documentation
2276+ * files (the "Software"), to deal in the Software without
2277+ * restriction, including without limitation the rights to use,
2278+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
2279+ * copies of the Software, and to permit persons to whom the
2280+ * Software is furnished to do so, subject to the following
2281+ * conditions:
2282+ *
2283+ * The above copyright notice and this permission notice shall be
2284+ * included in all copies or substantial portions of the Software.
2285+ *
2286+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2287+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
2288+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2289+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2290+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2291+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2292+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2293+ * OTHER DEALINGS IN THE SOFTWARE.
2294+ */
2295+
2296+#ifndef HIPL_LIB_HIPL_LHIPL_OPERATIONS_H
2297+#define HIPL_LIB_HIPL_LHIPL_OPERATIONS_H
2298+
2299+#include "lib/hipl/lhipl_sock.h"
2300+
2301+
2302+int hipl_socket_internal(const int family, const int type, const int protocol);
2303+
2304+int hipl_bind_internal(struct hipl_sock *const hsock,
2305+ const struct sockaddr *const address,
2306+ const socklen_t address_len);
2307+
2308+int hipl_connect_internal(struct hipl_sock *const hsock,
2309+ const struct sockaddr_in6 *const addr);
2310+
2311+int hipl_accept_internal(struct hipl_sock *const hsock);
2312+
2313+ssize_t hipl_recvmsg_internal(struct hipl_sock *const hsock,
2314+ struct msghdr *const msg,
2315+ const int flags);
2316+
2317+ssize_t hipl_sendmsg_internal(struct hipl_sock *const hsock,
2318+ struct msghdr *const msg,
2319+ const int flags);
2320+
2321+void hipl_build_addrstorage(const struct in6_addr *const addr,
2322+ const uint16_t port,
2323+ struct sockaddr_storage *const ss);
2324+
2325+#endif /* HIPL_LIB_HIPL_LHIPL_OPERATIONS_H */
2326
2327=== added file 'lib/hipl/lhipl_sock.c'
2328--- lib/hipl/lhipl_sock.c 1970-01-01 00:00:00 +0000
2329+++ lib/hipl/lhipl_sock.c 2012-04-17 15:16:21 +0000
2330@@ -0,0 +1,150 @@
2331+/*
2332+ * Copyright (c) 2012 Aalto University and RWTH Aachen University.
2333+ *
2334+ * Permission is hereby granted, free of charge, to any person
2335+ * obtaining a copy of this software and associated documentation
2336+ * files (the "Software"), to deal in the Software without
2337+ * restriction, including without limitation the rights to use,
2338+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
2339+ * copies of the Software, and to permit persons to whom the
2340+ * Software is furnished to do so, subject to the following
2341+ * conditions:
2342+ *
2343+ * The above copyright notice and this permission notice shall be
2344+ * included in all copies or substantial portions of the Software.
2345+ *
2346+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2347+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
2348+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2349+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2350+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2351+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2352+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2353+ * OTHER DEALINGS IN THE SOFTWARE.
2354+ */
2355+
2356+/**
2357+ * @file
2358+ * This file contains functions for maintaining libhipl sockets.
2359+ */
2360+
2361+#define _BSD_SOURCE
2362+
2363+#include <sys/socket.h>
2364+#include <string.h>
2365+#include <unistd.h>
2366+
2367+#include "lib/core/debug.h"
2368+#include "lib/core/hashtable.h"
2369+#include "lhipl_sock.h"
2370+
2371+
2372+/* A hashtable to record all opening libhipl sockets */
2373+static HIP_HASHTABLE *hsocks = NULL;
2374+
2375+static unsigned long hipl_sk_hash(const struct hipl_sock *hsock)
2376+{
2377+ return hsock->sid;
2378+}
2379+
2380+STATIC_IMPLEMENT_LHASH_HASH_FN(hipl_sk, struct hipl_sock)
2381+
2382+static int hipl_sk_cmp(const struct hipl_sock *hsock1,
2383+ const struct hipl_sock *hsock2)
2384+{
2385+ return memcmp(&hsock1->sid, &hsock2->sid, sizeof(hsock1->sid));
2386+}
2387+
2388+STATIC_IMPLEMENT_LHASH_COMP_FN(hipl_sk, struct hipl_sock)
2389+
2390+static uint32_t hsock_generate_id(void)
2391+{
2392+ static uint32_t id_generator = HIPL_LIB_HSOCK_ID_MIN;
2393+
2394+ if (id_generator == HIPL_LIB_HSOCK_ID_MAX) {
2395+ id_generator = HIPL_LIB_HSOCK_ID_MIN;
2396+ } else {
2397+ id_generator += 1;
2398+ }
2399+
2400+ return id_generator;
2401+}
2402+
2403+/**
2404+ * Initialize the libhipl socket hashtable.
2405+ */
2406+void hipl_hsock_init(void)
2407+{
2408+ hsocks = hip_ht_init(LHASH_HASH_FN(hipl_sk), LHASH_COMP_FN(hipl_sk));
2409+}
2410+
2411+/**
2412+ * Create a new libhipl socket and save it to the libhipl socket hashtable.
2413+ *
2414+ * @param family the address family of the libhipl socket (INET or INET6).
2415+ * @param type the type of the protocol.
2416+ * @param protocol the protocol of the libhipl socket (TCP or UDP).
2417+ * @return pointer to the created libhipl socket on success, NULL on
2418+ * error.
2419+ */
2420+struct hipl_sock *hipl_hsock_new(const int family, const int type,
2421+ const int protocol)
2422+{
2423+ struct hipl_sock *hsock = NULL;
2424+
2425+ hsock = calloc(sizeof(struct hipl_sock), sizeof(uint8_t));
2426+ if (hsock == NULL) {
2427+ HIP_ERROR("calloc() failed.\n");
2428+ return NULL;
2429+ }
2430+
2431+ hsock->sid = hsock_generate_id();
2432+ hsock->sock_family = family;
2433+ hsock->sock_type = type;
2434+ hsock->sock_proto = protocol;
2435+ hip_ht_add(hsocks, hsock);
2436+ return hsock;
2437+}
2438+
2439+/**
2440+ * Get a libhipl socket by its ID.
2441+ *
2442+ * @param hsock_id the ID of the libhipl socket.
2443+ * @return pointer to the libhipl socket on success, or NULL if the
2444+ * given ID doesn't match any record.
2445+ */
2446+struct hipl_sock *hipl_hsock_find(const uint16_t hsock_id)
2447+{
2448+ struct hipl_sock hsock;
2449+
2450+ hsock.sid = hsock_id;
2451+ return hip_ht_find(hsocks, &hsock);
2452+}
2453+
2454+/**
2455+ * Delete a libhipl socket and free the memory it occupies.
2456+ *
2457+ * @param hsock pointer to the libhipl socket to be deleted.
2458+ */
2459+void hipl_hsock_delete_and_free(struct hipl_sock *const hsock)
2460+{
2461+ struct hipl_sock *deleted_item;
2462+
2463+ deleted_item = hip_ht_delete(hsocks, hsock);
2464+ free(deleted_item);
2465+}
2466+
2467+/**
2468+ * Get the HIP association state of a given libhipl socket.
2469+ *
2470+ * @param hsock the libhipl socket.
2471+ * @return the HIP association state of the libhipl socket.
2472+ */
2473+enum hip_state hipl_hsock_ha_state(const struct hipl_sock *const hsock)
2474+{
2475+ if (!hsock->ha) {
2476+ return HIP_STATE_UNASSOCIATED;
2477+ } else {
2478+ return hsock->ha->state;
2479+ }
2480+}
2481
2482=== added file 'lib/hipl/lhipl_sock.h'
2483--- lib/hipl/lhipl_sock.h 1970-01-01 00:00:00 +0000
2484+++ lib/hipl/lhipl_sock.h 2012-04-17 15:16:21 +0000
2485@@ -0,0 +1,67 @@
2486+/*
2487+ * Copyright (c) 2012 Aalto University and RWTH Aachen University.
2488+ *
2489+ * Permission is hereby granted, free of charge, to any person
2490+ * obtaining a copy of this software and associated documentation
2491+ * files (the "Software"), to deal in the Software without
2492+ * restriction, including without limitation the rights to use,
2493+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
2494+ * copies of the Software, and to permit persons to whom the
2495+ * Software is furnished to do so, subject to the following
2496+ * conditions:
2497+ *
2498+ * The above copyright notice and this permission notice shall be
2499+ * included in all copies or substantial portions of the Software.
2500+ *
2501+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2502+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
2503+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2504+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2505+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2506+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2507+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2508+ * OTHER DEALINGS IN THE SOFTWARE.
2509+ */
2510+
2511+#ifndef HIPL_LIB_HIPL_LHIPL_SOCK_H
2512+#define HIPL_LIB_HIPL_LHIPL_SOCK_H
2513+
2514+#include <limits.h>
2515+
2516+#include "lib/core/protodefs.h"
2517+#include "lib/core/state.h"
2518+
2519+
2520+#define HIPL_LIB_HSOCK_ID_MIN 1
2521+#define HIPL_LIB_HSOCK_ID_MAX USHRT_MAX
2522+#define HIPL_LIB_HSOCK_MAX 1024
2523+
2524+/* This struct contains internal information about each libhipl socket.
2525+ *
2526+ * It is generated when a new libhipl socket is created.
2527+ */
2528+struct hipl_sock {
2529+ uint16_t sid; /* libhipl socket ID */
2530+ struct hip_hadb_state *ha;
2531+ hip_hit_t peer_hit;
2532+ struct sockaddr_storage peer_locator;
2533+ hip_hit_t src_hit; /* our HIT */
2534+ int src_port; /* our port number */
2535+ int sock_fd; /* underlying socket */
2536+ int sock_family;
2537+ int sock_type;
2538+ int sock_proto;
2539+};
2540+
2541+void hipl_hsock_init(void);
2542+
2543+enum hip_state hipl_hsock_ha_state(const struct hipl_sock *const hsock);
2544+
2545+struct hipl_sock *hipl_hsock_new(const int family, const int type,
2546+ const int protocol);
2547+
2548+struct hipl_sock *hipl_hsock_find(const uint16_t hsock_id);
2549+
2550+void hipl_hsock_delete_and_free(struct hipl_sock *const hsock);
2551+
2552+#endif /* HIPL_LIB_HIPL_LHIPL_SOCK_H */
2553
2554=== renamed file 'hipd/lsidb.c' => 'lib/hipl/lsidb.c'
2555=== renamed file 'hipd/lsidb.h' => 'lib/hipl/lsidb.h'
2556=== renamed file 'hipd/maintenance.c' => 'lib/hipl/maintenance.c'
2557=== renamed file 'hipd/maintenance.h' => 'lib/hipl/maintenance.h'
2558=== renamed file 'hipd/nat.c' => 'lib/hipl/nat.c'
2559=== renamed file 'hipd/nat.h' => 'lib/hipl/nat.h'
2560=== renamed file 'hipd/netdev.c' => 'lib/hipl/netdev.c'
2561=== renamed file 'hipd/netdev.h' => 'lib/hipl/netdev.h'
2562=== renamed file 'hipd/nsupdate.c' => 'lib/hipl/nsupdate.c'
2563=== renamed file 'hipd/nsupdate.h' => 'lib/hipl/nsupdate.h'
2564=== renamed file 'hipd/opp_mode.c' => 'lib/hipl/opp_mode.c'
2565=== renamed file 'hipd/opp_mode.h' => 'lib/hipl/opp_mode.h'
2566=== renamed file 'hipd/output.c' => 'lib/hipl/output.c'
2567--- hipd/output.c 2012-04-16 14:47:42 +0000
2568+++ lib/hipl/output.c 2012-04-17 15:16:21 +0000
2569@@ -848,7 +848,8 @@
2570 HIP_ASSERT(!hit_is_opportunistic_hit(&ctx->input_msg->hit_receiver));
2571
2572 /* Case: I ----->IPv4---> RVS ---IPv6---> R */
2573- if (IN6_IS_ADDR_V4MAPPED(r1_src_addr) !=
2574+ if (!hipl_is_libhip_mode() &&
2575+ IN6_IS_ADDR_V4MAPPED(r1_src_addr) !=
2576 IN6_IS_ADDR_V4MAPPED(r1_dst_addr)) {
2577 HIP_DEBUG_IN6ADDR("r1_src_addr", r1_src_addr);
2578 HIP_DEBUG_IN6ADDR("r1_dst_addr", r1_dst_addr);
2579@@ -1217,6 +1218,9 @@
2580 goto out_err;
2581 }
2582
2583+ if (hipl_is_libhip_mode()) {
2584+ udp = 1;
2585+ }
2586 dst_is_ipv4 = IN6_IS_ADDR_V4MAPPED(peer_addr);
2587 len = hip_get_msg_total_len(msg);
2588
2589@@ -1245,13 +1249,16 @@
2590 if (local_addr) {
2591 HIP_DEBUG("local address given\n");
2592 memcpy(&my_addr, local_addr, sizeof(struct in6_addr));
2593- } else {
2594+ } else if (!hipl_is_libhip_mode()) {
2595 HIP_DEBUG("no local address, selecting one\n");
2596 HIP_IFEL(hip_select_source_address(&my_addr, peer_addr), -1,
2597 "Cannot find source address\n");
2598+ } else {
2599+ memset(&my_addr, 0, sizeof(my_addr));
2600 }
2601
2602- src_is_ipv4 = IN6_IS_ADDR_V4MAPPED(&my_addr);
2603+ src_is_ipv4 = IN6_IS_ADDR_V4MAPPED(&my_addr) ||
2604+ (dst_is_ipv4 && ipv6_addr_any(&my_addr));
2605
2606 if (src_is_ipv4) {
2607 IPV6_TO_IPV4_MAP(&my_addr, &src4->sin_addr);
2608@@ -1305,9 +1312,10 @@
2609
2610 /* Handover may cause e.g. on-link duplicate address detection
2611 * which may cause bind to fail. */
2612-
2613- HIP_IFEL(bind(hip_raw_sock_output, (struct sockaddr *) &src, sa_size),
2614- -1, "Binding to raw sock failed\n");
2615+ if (!hipl_is_libhip_mode()) {
2616+ HIP_IFEL(bind(hip_raw_sock_output, (struct sockaddr *) &src, sa_size),
2617+ -1, "Binding to raw sock failed\n");
2618+ }
2619
2620 #if (HIP_SIMULATE_PACKET_LOSS_PROBABILITY > 0)
2621 if (HIP_SIMULATE_PACKET_LOSS && HIP_SIMULATE_PACKET_IS_LOST()) {
2622@@ -1324,18 +1332,25 @@
2623 len = hip_get_msg_total_len(msg);
2624
2625 if (udp) {
2626- struct udphdr *uh = (struct udphdr *) msg;
2627-
2628- /* Insert 32 bits of zero bytes between UDP and HIP */
2629- memmove((char *) msg + HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr), msg, len);
2630- memset(msg, 0, HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr));
2631- len += HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr);
2632-
2633- uh->source = htons(src_port);
2634- uh->dest = htons(dst_port);
2635- uh->len = htons(len);
2636- uh->check = 0;
2637- memmoved = 1;
2638+ if (!hipl_is_libhip_mode()) {
2639+ /* Insert 32 bits of zero bytes between UDP and HIP */
2640+ memmove((char *) msg + HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr), msg, len);
2641+ memset(msg, 0, HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr));
2642+ len += HIP_UDP_ZERO_BYTES_LEN + sizeof(struct udphdr);
2643+
2644+ struct udphdr *uh = (struct udphdr *) msg;
2645+ uh->source = htons(src_port);
2646+ uh->dest = htons(dst_port);
2647+ uh->len = htons(len);
2648+ uh->check = 0;
2649+ } else {
2650+ memmove((char *) msg + HIP_UDP_ZERO_BYTES_LEN, msg, len);
2651+ memset(msg, 0, HIP_UDP_ZERO_BYTES_LEN);
2652+ len += HIP_UDP_ZERO_BYTES_LEN;
2653+
2654+ dst4->sin_port = htons(dst_port);
2655+ }
2656+ memmoved = 1;
2657 }
2658
2659 sent = sendto(hip_raw_sock_output, msg, len, 0,
2660
2661=== renamed file 'hipd/output.h' => 'lib/hipl/output.h'
2662=== renamed file 'hipd/pkt_handling.c' => 'lib/hipl/pkt_handling.c'
2663=== renamed file 'hipd/pkt_handling.h' => 'lib/hipl/pkt_handling.h'
2664=== renamed file 'hipd/registration.c' => 'lib/hipl/registration.c'
2665=== renamed file 'hipd/registration.h' => 'lib/hipl/registration.h'
2666=== renamed file 'hipd/user.c' => 'lib/hipl/user.c'
2667=== renamed file 'hipd/user.h' => 'lib/hipl/user.h'
2668=== renamed file 'hipd/user_ipsec_hipd_msg.c' => 'lib/hipl/user_ipsec_hipd_msg.c'
2669=== renamed file 'hipd/user_ipsec_hipd_msg.h' => 'lib/hipl/user_ipsec_hipd_msg.h'
2670=== renamed file 'hipd/user_ipsec_sadb_api.c' => 'lib/hipl/user_ipsec_sadb_api.c'
2671=== renamed file 'hipd/user_ipsec_sadb_api.h' => 'lib/hipl/user_ipsec_sadb_api.h'
2672=== modified file 'modules/cert/hipd/cert.c'
2673--- modules/cert/hipd/cert.c 2012-03-08 09:38:56 +0000
2674+++ modules/cert/hipd/cert.c 2012-04-17 15:16:21 +0000
2675@@ -33,13 +33,13 @@
2676 #include <stdlib.h>
2677 #include <string.h>
2678
2679-#include "hipd/hipd.h"
2680-#include "hipd/pkt_handling.h"
2681 #include "lib/core/builder.h"
2682 #include "lib/core/cert.h"
2683 #include "lib/core/debug.h"
2684 #include "lib/core/ife.h"
2685 #include "lib/core/protodefs.h"
2686+#include "lib/hipl/hipd.h"
2687+#include "lib/hipl/pkt_handling.h"
2688 #include "modules/midauth/hipd/midauth.h"
2689 #include "modules/update/hipd/update.h"
2690 #include "cert.h"
2691
2692=== modified file 'modules/heartbeat/hipd/heartbeat.c'
2693--- modules/heartbeat/hipd/heartbeat.c 2012-03-21 13:14:54 +0000
2694+++ modules/heartbeat/hipd/heartbeat.c 2012-04-17 15:16:21 +0000
2695@@ -65,15 +65,6 @@
2696 #include <sys/types.h>
2697 #include <sys/socket.h>
2698
2699-#include "hipd/close.h"
2700-#include "hipd/hadb.h"
2701-#include "hipd/init.h"
2702-#include "hipd/hip_socket.h"
2703-#include "hipd/maintenance.h"
2704-#include "hipd/nat.h"
2705-#include "hipd/output.h"
2706-#include "hipd/pkt_handling.h"
2707-#include "hipd/user.h"
2708 #include "lib/core/common.h"
2709 #include "lib/core/debug.h"
2710 #include "lib/core/icomm.h"
2711@@ -84,6 +75,15 @@
2712 #include "lib/core/straddr.h"
2713 #include "lib/core/modularization.h"
2714 #include "lib/core/gpl/nlink.h"
2715+#include "lib/hipl/close.h"
2716+#include "lib/hipl/hadb.h"
2717+#include "lib/hipl/hip_socket.h"
2718+#include "lib/hipl/init.h"
2719+#include "lib/hipl/maintenance.h"
2720+#include "lib/hipl/nat.h"
2721+#include "lib/hipl/output.h"
2722+#include "lib/hipl/pkt_handling.h"
2723+#include "lib/hipl/user.h"
2724 #include "heartbeat.h"
2725
2726 #define HIP_MAX_ICMP_PACKET 512
2727
2728=== modified file 'modules/heartbeat_update/hipd/hb_update.c'
2729--- modules/heartbeat_update/hipd/hb_update.c 2012-03-21 13:14:54 +0000
2730+++ modules/heartbeat_update/hipd/hb_update.c 2012-04-17 15:16:21 +0000
2731@@ -1,5 +1,5 @@
2732 /*
2733- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
2734+ * Copyright (c) 2010, 2012 Aalto University and RWTH Aachen University.
2735 *
2736 * Permission is hereby granted, free of charge, to any person
2737 * obtaining a copy of this software and associated documentation
2738@@ -40,12 +40,12 @@
2739 #include <stdint.h>
2740 #include <stdlib.h>
2741
2742-#include "hipd/hadb.h"
2743-#include "hipd/maintenance.h"
2744 #include "lib/core/builder.h"
2745 #include "lib/core/common.h"
2746 #include "lib/core/debug.h"
2747 #include "lib/core/protodefs.h"
2748+#include "lib/hipl/hadb.h"
2749+#include "lib/hipl/maintenance.h"
2750 #include "modules/update/hipd/update.h"
2751 #include "modules/update/hipd/update_locator.h"
2752 #include "hb_update.h"
2753
2754=== modified file 'modules/midauth/hipd/midauth.c'
2755--- modules/midauth/hipd/midauth.c 2012-04-17 11:20:20 +0000
2756+++ modules/midauth/hipd/midauth.c 2012-04-17 15:16:21 +0000
2757@@ -33,8 +33,6 @@
2758 #include <stdint.h>
2759 #include <string.h>
2760
2761-#include "hipd/hidb.h"
2762-#include "hipd/pkt_handling.h"
2763 #include "lib/core/builder.h"
2764 #include "lib/core/common.h"
2765 #include "lib/core/ife.h"
2766@@ -42,6 +40,8 @@
2767 #include "lib/core/protodefs.h"
2768 #include "lib/core/solve.h"
2769 #include "lib/core/state.h"
2770+#include "lib/hipl/hidb.h"
2771+#include "lib/hipl/pkt_handling.h"
2772 #include "modules/midauth/lib/midauth_builder.h"
2773 #include "modules/update/hipd/update.h"
2774 #include "midauth.h"
2775
2776=== modified file 'modules/update/hipd/update.c'
2777--- modules/update/hipd/update.c 2012-03-20 12:52:49 +0000
2778+++ modules/update/hipd/update.c 2012-04-17 15:16:21 +0000
2779@@ -37,17 +37,6 @@
2780 #include <string.h>
2781
2782 #include "config.h"
2783-#include "hipd/cookie.h"
2784-#include "hipd/hadb.h"
2785-#include "hipd/hidb.h"
2786-#include "hipd/hipd.h"
2787-#include "hipd/input.h"
2788-#include "hipd/maintenance.h"
2789-#include "hipd/netdev.h"
2790-#include "hipd/nsupdate.h"
2791-#include "hipd/output.h"
2792-#include "hipd/pkt_handling.h"
2793-#include "hipd/user.h"
2794 #include "lib/core/builder.h"
2795 #include "lib/core/debug.h"
2796 #include "lib/core/hip_udp.h"
2797@@ -57,6 +46,17 @@
2798 #include "lib/core/prefix.h"
2799 #include "lib/core/state.h"
2800 #include "lib/core/performance.h"
2801+#include "lib/hipl/cookie.h"
2802+#include "lib/hipl/hadb.h"
2803+#include "lib/hipl/hidb.h"
2804+#include "lib/hipl/hipd.h"
2805+#include "lib/hipl/input.h"
2806+#include "lib/hipl/maintenance.h"
2807+#include "lib/hipl/netdev.h"
2808+#include "lib/hipl/nsupdate.h"
2809+#include "lib/hipl/output.h"
2810+#include "lib/hipl/pkt_handling.h"
2811+#include "lib/hipl/user.h"
2812 #include "update_builder.h"
2813 #include "update_locator.h"
2814 #include "update_param_handling.h"
2815
2816=== modified file 'modules/update/hipd/update_builder.c'
2817--- modules/update/hipd/update_builder.c 2012-04-17 11:20:20 +0000
2818+++ modules/update/hipd/update_builder.c 2012-04-17 15:16:21 +0000
2819@@ -34,12 +34,12 @@
2820 #include <string.h>
2821 #include <errno.h>
2822
2823-#include "hipd/hadb.h"
2824-#include "hipd/netdev.h"
2825 #include "lib/core/builder.h"
2826 #include "lib/core/ife.h"
2827 #include "lib/core/list.h"
2828 #include "lib/core/prefix.h"
2829+#include "lib/hipl/hadb.h"
2830+#include "lib/hipl/netdev.h"
2831 #include "update_builder.h"
2832
2833 enum hip_locator_traffic_type {
2834
2835=== modified file 'modules/update/hipd/update_locator.c'
2836--- modules/update/hipd/update_locator.c 2011-12-12 14:18:05 +0000
2837+++ modules/update/hipd/update_locator.c 2012-04-17 15:16:21 +0000
2838@@ -1,5 +1,5 @@
2839 /*
2840- * Copyright (c) 2010 Aalto University and RWTH Aachen University.
2841+ * Copyright (c) 2010, 2012 Aalto University and RWTH Aachen University.
2842 *
2843 * Permission is hereby granted, free of charge, to any person
2844 * obtaining a copy of this software and associated documentation
2845@@ -34,11 +34,11 @@
2846 #include <string.h>
2847 #include <openssl/lhash.h>
2848
2849-#include "hipd/maintenance.h"
2850 #include "lib/core/builder.h"
2851 #include "lib/core/debug.h"
2852 #include "lib/core/ife.h"
2853 #include "lib/core/protodefs.h"
2854+#include "lib/hipl/maintenance.h"
2855 #include "update_builder.h"
2856 #include "update.h"
2857 #include "update_locator.h"
2858
2859=== added file 'test/check_libhipl.c'
2860--- test/check_libhipl.c 1970-01-01 00:00:00 +0000
2861+++ test/check_libhipl.c 2012-04-17 15:16:21 +0000
2862@@ -0,0 +1,216 @@
2863+/*
2864+ * Copyright (c) 2012 Aalto University and RWTH Aachen University.
2865+ *
2866+ * Permission is hereby granted, free of charge, to any person
2867+ * obtaining a copy of this software and associated documentation
2868+ * files (the "Software"), to deal in the Software without
2869+ * restriction, including without limitation the rights to use,
2870+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
2871+ * copies of the Software, and to permit persons to whom the
2872+ * Software is furnished to do so, subject to the following
2873+ * conditions:
2874+ *
2875+ * The above copyright notice and this permission notice shall be
2876+ * included in all copies or substantial portions of the Software.
2877+ *
2878+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2879+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
2880+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
2881+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
2882+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2883+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2884+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2885+ * OTHER DEALINGS IN THE SOFTWARE.
2886+ */
2887+
2888+/**
2889+ * @file
2890+ * @brief Tests of libhipl on localhost (see doc/HACKING on unit tests).
2891+ */
2892+
2893+#include <arpa/inet.h>
2894+#include <check.h>
2895+#include <errno.h>
2896+#include <stdbool.h>
2897+#include <stdio.h>
2898+#include <stdlib.h>
2899+#include <sys/select.h>
2900+#include <unistd.h>
2901+
2902+#include "lib/hipl/hidb.h"
2903+#include "lib/hipl/lhipl.h"
2904+
2905+#ifndef max
2906+#define max(a, b) (((a) > (b)) ? (a) : (b))
2907+#endif
2908+
2909+#define LO_IP "127.0.0.1"
2910+#define TEST_MSG "Hello Sailor!"
2911+#define SEND_PORT 22345
2912+#define RECV_PORT 22300
2913+
2914+static struct in6_addr lo_hit;
2915+static char peername[HIPL_MAX_PEERNAME];
2916+static struct sockaddr_in send_addr;
2917+static struct sockaddr_in recv_addr;
2918+
2919+static int sender;
2920+static int receiver;
2921+
2922+static void test_libhipl_lo_init(int proto)
2923+{
2924+ if (hipl_lib_init_all(HIPL_LIB_LOG_NONE) < 0) {
2925+ fail("hipl_lib_init_all");
2926+ }
2927+
2928+ fail_if(hip_get_default_hit(&lo_hit) < 0, "Failed to load local hit");
2929+ inet_ntop(AF_INET6, &lo_hit, peername, HIPL_MAX_PEERNAME);
2930+ fail_if(hipl_add_peer_info(peername, LO_IP) < 0,
2931+ "Failed to insert peer info");
2932+
2933+ send_addr.sin_family = AF_INET;
2934+ inet_pton(AF_INET, LO_IP, &send_addr.sin_addr);
2935+ send_addr.sin_port = htons(SEND_PORT);
2936+ recv_addr.sin_family = AF_INET;
2937+ inet_pton(AF_INET, LO_IP, &recv_addr.sin_addr);
2938+ recv_addr.sin_port = htons(RECV_PORT);
2939+
2940+ if (proto == IPPROTO_TCP) {
2941+ sender = hipl_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2942+ receiver = hipl_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2943+ } else if (proto == IPPROTO_UDP) {
2944+ sender = hipl_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2945+ receiver = hipl_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2946+ }
2947+ fail_if(sender <= 0 || receiver <= 0);
2948+
2949+ if (hipl_bind(sender, (struct sockaddr *) &send_addr,
2950+ sizeof(send_addr)) < 0) {
2951+ fail("hipl_bind() for sender");
2952+ }
2953+ if (hipl_bind(receiver, (struct sockaddr *) &recv_addr,
2954+ sizeof(recv_addr)) < 0) {
2955+ fail("hipl_bind() for receiver");
2956+ }
2957+
2958+ hipl_lib_set_bex_feedback(true);
2959+}
2960+
2961+static void test_libhipl_lo_main_loop(int send_hid, int recv_hid)
2962+{
2963+ char peer[HIPL_MAX_PEERNAME];
2964+ uint16_t peer_port;
2965+ char buf[1024];
2966+ fd_set rset;
2967+ int ret = 0;
2968+ int maxfd = max(hipl_lib_get_sockfd(send_hid),
2969+ hipl_lib_get_sockfd(recv_hid));
2970+
2971+ //trigger BEX
2972+ ret = hipl_sendto(send_hid, TEST_MSG, strlen(TEST_MSG), 0,
2973+ peername, RECV_PORT);
2974+ fail_if(ret != -EWAITBEX);
2975+
2976+ while (1) {
2977+ FD_ZERO(&rset);
2978+ FD_SET(hipl_lib_get_sockfd(send_hid), &rset);
2979+ FD_SET(hipl_lib_get_sockfd(recv_hid), &rset);
2980+ fail_if(select(maxfd + 1, &rset, NULL, NULL, NULL) < 0);
2981+
2982+ if (FD_ISSET(hipl_lib_get_sockfd(recv_hid), &rset)) {
2983+ ret = hipl_recvfrom(recv_hid, buf, 1024, 0, peer, &peer_port);
2984+ fail_if(ret < 0 && ret != -EWAITBEX && ret != -EBEXESTABLISHED);
2985+ fail_if(ret > 0 && ret != strlen(TEST_MSG));
2986+
2987+ if (ret == strlen(TEST_MSG)) {
2988+ buf[ret] = '\0';
2989+ fail_if(strcmp(buf, TEST_MSG) != 0);
2990+ fail_if(strcmp(peername, peer) != 0);
2991+ fail_if(peer_port != SEND_PORT);
2992+ return;
2993+ }
2994+ }
2995+ if (FD_ISSET(hipl_lib_get_sockfd(send_hid), &rset)) {
2996+ ret = hipl_sendto(send_hid, TEST_MSG, strlen(TEST_MSG), 0,
2997+ peername, RECV_PORT);
2998+ fail_if(ret < 0 && ret != -EWAITBEX && ret != -EBEXESTABLISHED);
2999+ fail_if(ret > 0 && ret != strlen(TEST_MSG));
3000+ }
3001+ }
3002+}
3003+
3004+START_TEST(test_libhipl_lo_tcp)
3005+{
3006+ fd_set wset, rset;
3007+ int maxfd, recv_slave = 0;
3008+
3009+ test_libhipl_lo_init(IPPROTO_TCP);
3010+
3011+ // Setup TCP connection
3012+ maxfd = max(hipl_lib_get_sockfd(sender), hipl_lib_get_sockfd(receiver));
3013+ if (hipl_listen(receiver, 5) < 0) {
3014+ fail("hipl_listen()");
3015+ }
3016+ fail_if(hipl_lib_set_nonblock(sender, true) < 0);
3017+ fail_if(hipl_lib_set_nonblock(receiver, true) < 0);
3018+ hipl_accept(receiver);
3019+ hipl_connect(sender, peername, RECV_PORT);
3020+ while (recv_slave <= 0) {
3021+ FD_ZERO(&wset);
3022+ FD_ZERO(&rset);
3023+ FD_SET(hipl_lib_get_sockfd(sender), &wset);
3024+ FD_SET(hipl_lib_get_sockfd(receiver), &rset);
3025+ fail_if(select(maxfd + 1, &rset, &wset, NULL, NULL) < 0);
3026+ if (FD_ISSET(hipl_lib_get_sockfd(receiver), &rset)) {
3027+ if ((recv_slave = hipl_accept(receiver)) < 0) {
3028+ fail("hipl_accept(), %s", strerror(errno));
3029+ }
3030+ }
3031+ if (FD_ISSET(hipl_lib_get_sockfd(sender), &wset)) {
3032+ if (hipl_connect(sender, peername, RECV_PORT) < 0
3033+ && errno != EINPROGRESS && errno != EISCONN) {
3034+ fail("hipl_connect() %s", strerror(errno));
3035+ }
3036+ }
3037+ }
3038+ fail_if(hipl_connect(sender, peername, RECV_PORT) < 0 && errno != EISCONN);
3039+ fail_if(hipl_lib_set_nonblock(sender, false) < 0);
3040+
3041+ // Process base exchange and user data
3042+ test_libhipl_lo_main_loop(sender, recv_slave);
3043+}
3044+END_TEST
3045+
3046+START_TEST(test_libhipl_lo_udp)
3047+{
3048+ test_libhipl_lo_init(IPPROTO_UDP);
3049+ test_libhipl_lo_main_loop(sender, receiver);
3050+}
3051+END_TEST
3052+
3053+static Suite *hipnc_suite(void)
3054+{
3055+ Suite *s = suite_create("libhipl");
3056+
3057+ TCase *tc_libhipl_lo = tcase_create("libhipl_lo");
3058+ tcase_add_test(tc_libhipl_lo, test_libhipl_lo_udp);
3059+ tcase_add_test(tc_libhipl_lo, test_libhipl_lo_tcp);
3060+ suite_add_tcase(s, tc_libhipl_lo);
3061+
3062+ return s;
3063+}
3064+
3065+int main(void)
3066+{
3067+ int number_failed;
3068+ Suite *s = hipnc_suite();
3069+ SRunner *sr = srunner_create(NULL);
3070+
3071+ srunner_add_suite(sr, s);
3072+ srunner_run_all(sr, CK_NORMAL);
3073+
3074+ number_failed = srunner_ntests_failed(sr);
3075+ srunner_free(sr);
3076+
3077+ return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
3078+}
3079
3080=== modified file 'test/hipd/lsidb.c'
3081--- test/hipd/lsidb.c 2012-01-18 21:09:47 +0000
3082+++ test/hipd/lsidb.c 2012-04-17 15:16:21 +0000
3083@@ -26,7 +26,7 @@
3084 #include <check.h>
3085 #include <stdlib.h>
3086
3087-#include "hipd/lsidb.c"
3088+#include "lib/hipl/lsidb.c"
3089 #include "test_suites.h"
3090
3091 START_TEST(test_lsidb_allocate_lsi_valid)

Subscribers

People subscribed via source and target branches

to all changes: