Merge lp:~stefan.goetz-deactivatedaccount/hipl/esp-destination-addresses into lp:hipl

Proposed by Stefan Götz
Status: Superseded
Proposed branch: lp:~stefan.goetz-deactivatedaccount/hipl/esp-destination-addresses
Merge into: lp:hipl
Diff against target: 449 lines (+162/-119)
2 files modified
firewall/conntrack.c (+161/-118)
firewall/firewall_defines.h (+1/-1)
To merge this branch: bzr merge lp:~stefan.goetz-deactivatedaccount/hipl/esp-destination-addresses
Reviewer Review Type Date Requested Status
Christof Mroz Needs Fixing
Diego Biurrun Approve
Review via email: mp+55259@code.launchpad.net

This proposal has been superseded by a proposal from 2011-03-30.

Description of the change

Remove memory leaks and unchecked allocations from the firewall. Refactor the list of destination addresses associated with an ESP rule to use the hip_ll instead of the slist list implementation. Update all code handling this list so that memory allocations are checked, memory leaks are prevented, an error handling is performed properly.

For reviewing, the commits on this branch are fairly tidy and break down the changes nicely.

To post a comment you must log in.
Revision history for this message
Diego Biurrun (diego-biurrun) wrote :

 review approve

On Tue, Mar 29, 2011 at 12:44:48AM +0000, Stefan Götz wrote:
>
> Remove memory leaks and unchecked allocations from the firewall.
> Refactor the list of destination addresses associated with an ESP rule
> to use the hip_ll instead of the slist list implementation. Update all
> code handling this list so that memory allocations are checked, memory
> leaks are prevented, an error handling is performed properly.

Does this get rid of all instances of hslist? Yay for getting rid of
one of the duplicated list implementations.

> For reviewing, the commits on this branch are fairly tidy and break
> down the changes nicely.

Indeed they are, thanks. The merge proposal is fine with me, below
are just some minor comments - apply at your own discretion.

If you wish to make this even simpler, you could push r5796 and r5797
from your branch to trunk right away. They are trivial and I hereby
approve them.

> --- firewall/conntrack.c 2011-03-24 17:34:21 +0000
> +++ firewall/conntrack.c 2011-03-29 00:44:44 +0000
> @@ -288,20 +287,19 @@
> -static struct esp_address *get_esp_address(const struct slist *addr_list,
> - const struct in6_addr *addr)
> +static struct esp_address *get_esp_address(const struct hip_ll *const addresses,
> + const struct in6_addr *const addr)

I think you could just push such constifications to trunk directly,
that would make your branches even smaller...

> @@ -321,42 +319,49 @@
>
> - if (!addr_list) {
> - HIP_DEBUG("Esp slist is empty\n");
> - }

I'd say the same for such annoying debug output that we have such
abundant amounts of in HIPL.

> @@ -626,79 +625,104 @@
> + HIP_ASSERT(esp_info);
> + HIP_ASSERT(locator);
> + HIP_ASSERT(seq);
> + HIP_ASSERT(tuple);

nit: Maybe

HIP_ASSERT(esp_info || locator || seq || tuple ||
           esp_info->new_spi == esp_info->old_spi);

?

> + for (unsigned idx = 0; idx < addresses_in_locator; idx += 1) {

Hmmm, declarations inside for loops - I think we generally avoid this.

> + HIP_IFEL(hip_ll_add_first(&new_esp->dst_addresses, esp_address)
> + != 0, -1,

nit: That looks weird, keep it on one line please.

> + HIP_ASSERT(esp_info);
> + HIP_ASSERT(addr);
> + HIP_ASSERT(tuple);

see above

Diego

review: Approve
Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :

Hi Diego!

> Does this get rid of all instances of hslist?

Not yet. More hslist killer branches will follow.

> I think you could just push such constifications to trunk directly,
> that would make your branches even smaller...

Thanks for the tip. It made me commit a broken code to trunk. And you'll get rice cake for it - bastard ;-)

> > @@ -626,79 +625,104 @@
> > + HIP_ASSERT(esp_info);
> > + HIP_ASSERT(locator);
> > + HIP_ASSERT(seq);
> > + HIP_ASSERT(tuple);
>
> nit: Maybe
>
> HIP_ASSERT(esp_info || locator || seq || tuple ||
> esp_info->new_spi == esp_info->old_spi);
>
> ?

Not a fan: you lose the information, which pointer exactly was NULL which could aid debugging a lot.

> > + for (unsigned idx = 0; idx < addresses_in_locator; idx += 1) {
>
> Hmmm, declarations inside for loops - I think we generally avoid this.

But, but, but they are nice! Because then they have exactly the scope and visibility that they should have. Is there a con? In doc/HACKING, I found example code that declares such variables outside the for() scope, but there is no explicit rule about it.

> > + HIP_IFEL(hip_ll_add_first(&new_esp->dst_addresses, esp_address)
> > + != 0, -1,
>
> nit: That looks weird, keep it on one line please.

I agree that it looks weird, but where exactly does the weirdness to line-length tradeoff lie? I'm never quite sure how aggressively I should keep lines below 80 columns...

Stefan

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

On Tue, Mar 29, 2011 at 06:07:29PM +0000, Stefan Götz wrote:
>
> > Does this get rid of all instances of hslist?
>
> Not yet. More hslist killer branches will follow.

I'm looking forward to them :)

> > I think you could just push such constifications to trunk directly,
> > that would make your branches even smaller...
>
> Thanks for the tip. It made me commit a broken code to trunk. And
> you'll get rice cake for it - bastard ;-)

Your feeble attempt at passing blame around fails miserably ;-p

Splitting off sensible parts from larger changes and pushing them into
trunk is a high art. I'm sure you will learn it eventually, but beware
- the road to mastery is littered with rice cakes ;-p

> > > @@ -626,79 +625,104 @@
> > > + HIP_ASSERT(esp_info);
> > > + HIP_ASSERT(locator);
> > > + HIP_ASSERT(seq);
> > > + HIP_ASSERT(tuple);
> >
> > nit: Maybe
> >
> > HIP_ASSERT(esp_info || locator || seq || tuple ||
> > esp_info->new_spi == esp_info->old_spi);
> >
> > ?
>
> Not a fan: you lose the information, which pointer exactly was NULL
> which could aid debugging a lot.

Yeah, you guys convinced me...

> > > + for (unsigned idx = 0; idx < addresses_in_locator; idx += 1) {
> >
> > Hmmm, declarations inside for loops - I think we generally avoid this.
>
> But, but, but they are nice! Because then they have exactly the scope
> and visibility that they should have. Is there a con? In doc/HACKING,
> I found example code that declares such variables outside the for()
> scope, but there is no explicit rule about it.

Since we dropped the idea of -Wdeclaration-after-statement I guess we
can allow them.

> > > + HIP_IFEL(hip_ll_add_first(&new_esp->dst_addresses, esp_address)
> > > + != 0, -1,
> >
> > nit: That looks weird, keep it on one line please.
>
> I agree that it looks weird, but where exactly does the weirdness to
> line-length tradeoff lie? I'm never quite sure how aggressively I
> should keep lines below 80 columns...

Not that aggressively :)

I don't consider it a hard rule, but it sure helps readability if used
with a measure of flexibility. Keeping such expressions together is
where I'd let a line get longer...

Diego

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

Hi Stefan, thanks for sane linked list handling, at last.

Unfortunately, `hipfw -kd` segfaults during a ping test:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000404e1d in update_esp_address (addresses=0x6d5720,
    addr=0x7fffffffe920, upd_id=0x0) at firewall/conntrack.c:354
354 *esp_addr->update_id = *upd_id;
(gdb) bt
#0 0x0000000000404e1d in update_esp_address (addresses=0x6d5720,
    addr=0x7fffffffe920, upd_id=0x0) at firewall/conntrack.c:354
#1 0x0000000000406ca4 in handle_i2 (common=0x7fffffffd9a0,
    tuple=0x6d45c0, ctx=0x7fffffffe910)
    at firewall/conntrack.c:1066
#2 0x00000000004080c8 in check_packet (ip6_src=0x7fffffffe920,
    ip6_dst=0x7fffffffe930, common=0x7fffffffd9a0, tuple=0x6d45c0,
    verify_responder=0, accept_mobile=1, ctx=0x7fffffffe910)
    at firewall/conntrack.c:1647
#3 0x0000000000408e45 in conntrack (ip6_src=0x7fffffffe920,
    ip6_dst=0x7fffffffe930, buf=0x7fffffffd9a0, ctx=0x7fffffffe910)
    at firewall/conntrack.c:1958
#4 0x0000000000414198 in filter_hip (ip6_src=0x7fffffffe920,
    ip6_dst=0x7fffffffe930, buf=0x7fffffffd9a0, hook=2,
    in_if=0x7fffffffd944 "eth1", out_if=0x7fffffffd954 "eth2",
    ctx=0x7fffffffe910) at firewall/firewall.c:1042
#5 0x0000000000414218 in hip_fw_handle_hip_output (
    ctx=0x7fffffffe910) at firewall/firewall.c:1062
#6 0x0000000000414472 in hip_fw_handle_hip_forward (
    ctx=0x7fffffffe910) at firewall/firewall.c:1172
#7 0x000000000041541b in hip_fw_handle_packet (
    buf=0x7fffffffd910 "\360\002", hndl=0x6b12d0, ip_version=4,
    ctx=0x7fffffffe910) at firewall/firewall.c:1644
#8 0x0000000000415fcd in hipfw_main (rule_file=0x0,
    kill_old=true, limit_capabilities=false)
    at firewall/firewall.c:1881
#9 0x000000000042187e in main (argc=2, argv=0x7fffffffeac8)
    at firewall/main.c:188
(gdb) p esp_addr
$1 = (struct esp_address *) 0x6d50a0
(gdb) p upd_id
$2 = (const uint32_t * const) 0x0
(gdb)

More about that below. Apart from that, the rest is either unrelated or nitpicking.

> === modified file 'firewall/conntrack.c'
> [...]
> @@ -288,20 +287,19 @@
> [...]
> - while (list) {
> - esp_addr = list->data;
> + while (node) {
> + struct esp_address *const esp_addr = node->ptr;

const struct esp_address *const

> + if ((esp_addr = malloc(sizeof(*esp_addr)))) {
> + esp_addr->dst_addr = *addr;
> esp_addr->update_id = NULL;
> + if (upd_id == NULL || (esp_addr->update_id = malloc(sizeof(*esp_addr->update_id)))) {
> + *esp_addr->update_id = *upd_id;

Looks like if upd_id == NULL, the branch will be entered and a NULL dereference triggered.
Also, the return value of malloc() is not checked for NULL.

Did you find out why the update ID is dynamically allocated in the first place?

> + addr = hip_ll_del_first(&esp_tuple->dst_addresses, NULL);
> + while (addr) {
> free(addr->update_id);
> free(addr);
> -
> - free(list);
> - list = esp_tuple->dst_addr_list;
> + addr = hip_ll_del_first(&esp_tuple->dst_addresses, NULL);
> }

Code duplication can be avoided via

while (addr = hip_ll_del_first(......

Read more...

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

On Tue, Mar 29, 2011 at 06:38:23PM +0000, Christof Mroz wrote:
> Review: Needs Fixing
> Hi Stefan, thanks for sane linked list handling, at last.
>
> Unfortunately, `hipfw -kd` segfaults during a ping test:

You actually tested somebody else's merge proposal?
10 points for Gryffindor :-)

Diego

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :

Hi Diego!

> Splitting off sensible parts from larger changes and pushing them into
> trunk is a high art.  I'm sure you will learn it eventually, but beware
> - the road to mastery is littered with rice cakes ;-p

Oooh, the rice cake strong in this one is.

>> > Hmmm, declarations inside for loops - I think we generally avoid this.
>>
>> But, but, but they are nice! Because then they have exactly the scope
>> and visibility that they should have. Is there a con? In doc/HACKING,
>> I found example code that declares such variables outside the for()
>> scope, but there is no explicit rule about it.
>
> Since we dropped the idea of -Wdeclaration-after-statement I guess we
> can allow them.

Awesome!

>> I agree that it looks weird, but where exactly does the weirdness to
>> line-length tradeoff lie? I'm never quite sure how aggressively I
>> should keep lines below 80 columns...
>
> Not that aggressively :)
>
> I don't consider it a hard rule, but it sure helps readability if used
> with a measure of flexibility.  Keeping such expressions together is
> where I'd let a line get longer...

I'll try to read your mind better from now on ;-)

Stefan

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :
Download full text (3.8 KiB)

Hi Christof!

Thanks so much for testing - I really appreciate it!

Wasn't there a plan about some automated testbed? What happened to
that? It'd be fairly cool if one could inject one's branches into such
a testbed for this kind of testing...

>> +    while (node) {
>> +        struct esp_address *const esp_addr = node->ptr;
>
> const struct esp_address *const

ok

>> +    if ((esp_addr = malloc(sizeof(*esp_addr)))) {
>> +        esp_addr->dst_addr  = *addr;
>>          esp_addr->update_id = NULL;
>> +        if (upd_id == NULL || (esp_addr->update_id = malloc(sizeof(*esp_addr->update_id)))) {
>> +            *esp_addr->update_id = *upd_id;
>
> Looks like if upd_id == NULL, the branch will be entered and a NULL dereference triggered.
> Also, the return value of malloc() is not checked for NULL.

ok - obviously, I got the logic wrong there.

> Did you find out why the update ID is dynamically allocated in the first place?

Yes: the update_id for a given destination address may be known or
not. Its value range occupies 32 bits and no magic value is reserved
to indicate the 'unknown' state. Thus, a VCP (very clever person)
decided to encode the 'unknown' state as a NULL pointer. If the
pointer is not NULL, it points to the actual known update ID.

I planned to replace this memory-leak infested mess in a different branch.

> Code duplication can be avoided via
>
> while (addr = hip_ll_del_first(...)) { ... }

Doh - of course!

>> +    HIP_ASSERT(esp_info);
>> +    HIP_ASSERT(locator);
>> +    HIP_ASSERT(seq);
>> +    HIP_ASSERT(tuple);
>> +    HIP_ASSERT(esp_info->new_spi == esp_info->old_spi);
>
> That last assertion looks odd: could this be handled gracefully? I don't know what the RFC says on this though.

The way I understand the code, this is indeed an assertion about code
consistency, i.e. no outsider can trigger this assertion, only someone
who messes up the code in an unintended way.

>> +        HIP_IFEL((new_esp = calloc(1, sizeof(*new_esp))) == NULL, -1,
>> +                 "Allocating esp_tuple object failed");
>>          new_esp->spi   = ntohl(esp_info->new_spi);
>>          new_esp->tuple = tuple;
>> +        hip_ll_init(&new_esp->dst_addresses);
>
> Is this still the state of the art, with your newly added initializer macro?

Yes - the initializer macro is only for static initializations.

>> +        for (unsigned idx = 0; idx < addresses_in_locator; idx += 1) {
>
> Now I'm even more confused about the C99 thing... Please, please tell me that this declaration is allowed :)

Diego just gave it his blessing :)

>> +            struct esp_address *const esp_address =
>> +                malloc(sizeof(*esp_address));
>> +            HIP_IFEL(esp_address == NULL, -1,
>> +                     "Allocating esp_address object for address %i failed",
>> +                     idx);
>> +            esp_address->dst_addr = addresses[idx].address;
>> +            HIP_IFEL(hip_ll_add_first(&new_esp->dst_addresses, esp_address)
>> +                     != 0, -1,
>> +                     "Appending esp_address object %i to list of destination addresses in ESP tuple failed",
>> +                     idx);
>> +            HIP_IFEL((esp_address->u...

Read more...

5803. By Stefan Götz

Pulled trunk rev 5810

5804. By Stefan Götz

Reformat long lines for readability.

5805. By Stefan Götz

Add a 'const' qualifier to a local variable to improve correctness. Add a comment that explains an unintuitive return statement.

5806. By Stefan Götz

Fix NULL pointer access bug. In the old code, upd_id was dereferenced even if it was NULL. The new code handles errors via HIP_IFEL(), its control flow is more intuitive and thus the error handling is better manageable.

5807. By Stefan Götz

Remove unnecessary code duplication.

5808. By Stefan Götz

Fix a memory leak bug. In the old code, the memory for a 'struct esp_address'
object was not freed when the subsequent call to 'hip_ll_add_first()' failed.
The new code handles failures in initializing a 'struct esp_address' ojbect
more explicitly and contains the necessary de-allocations in case of a
failure.

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

On Tue, Mar 29, 2011 at 11:13:28PM +0000, Stefan Götz wrote:
>
> > Splitting off sensible parts from larger changes and pushing them into
> > trunk is a high art.  I'm sure you will learn it eventually, but beware
> > - the road to mastery is littered with rice cakes ;-p
>
> Oooh, the rice cake strong in this one is.

Indeed, my number one spot in the eternal rice cake table will likely
remain uncontested for eons to come ;-)

Diego

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

On Tue, Mar 29, 2011 at 09:08:34PM +0200, Diego Biurrun wrote:
> On Tue, Mar 29, 2011 at 06:38:23PM +0000, Christof Mroz wrote:
> > Review: Needs Fixing
> > Hi Stefan, thanks for sane linked list handling, at last.
> >
> > Unfortunately, `hipfw -kd` segfaults during a ping test:
>
> You actually tested somebody else's merge proposal?
> 10 points for Gryffindor :-)

Oh, and many thanks for helping with reviews - we can use all the extra
eyes we can get. It's great to not have to rely on my puny C skills to
keep HIPL in a good shape :)

Diego

Revision history for this message
Stefan Götz (stefan.goetz-deactivatedaccount) wrote :

Hi Christof!

>> +            struct esp_address *const esp_address =
>> +                malloc(sizeof(*esp_address));
>> +            HIP_IFEL(esp_address == NULL, -1,
>> +                     "Allocating esp_address object for address %i failed",
>> +                     idx);
>> +            esp_address->dst_addr = addresses[idx].address;
>> +            HIP_IFEL(hip_ll_add_first(&new_esp->dst_addresses, esp_address)
>> +                     != 0, -1,
>> +                     "Appending esp_address object %i to list of destination addresses in ESP tuple failed",
>> +                     idx);
>> +            HIP_IFEL((esp_address->update_id =
>> +                          malloc(sizeof(*esp_address->update_id))) == NULL, -1,
>> +                     "Allocating update_id object for address %i failed",
>> +                     idx);
>> +            *esp_address->update_id = seq->update_id;
>>          }
>> +
>> +        return new_esp;
>>      }
>> -    return new_esp;
>> +
>> +out_err:
>> +    free_esp_tuple(new_esp);
>> +    return NULL;
>>  }
>
> It's also easier to follow IMO if you deallocated it explicitly and not relied on free_esp_tuple() to clean up a half-initialized item.

I changed my mind: the esp_tuple is always in a state that
free_esp_tuple() can handle so it makes sense to use free_esp_tuple()
instead of re-implementing it.

Stefan

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

On Wed, 30 Mar 2011 23:28:31 +0200, Stefan Götz
<email address hidden> wrote:

>> It's also easier to follow IMO if you deallocated it explicitly and not
>> relied on free_esp_tuple() to clean up a half-initialized item.
>
> I changed my mind: the esp_tuple is always in a state that
> free_esp_tuple() can handle so it makes sense to use free_esp_tuple()
> instead of re-implementing it.

OK, but it took me a while to understand where the memory is deallocated
(if at all) in case of an error, so a comment would be nice.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'firewall/conntrack.c'
2--- firewall/conntrack.c 2011-03-29 23:02:26 +0000
3+++ firewall/conntrack.c 2011-03-30 11:11:01 +0000
4@@ -91,22 +91,21 @@
5 /**
6 * prints out the list of addresses of esp_addr_list
7 *
8- * @param addr_list list of addresses
9+ * @param addresses list of addresses
10 *
11 */
12-static void print_esp_addr_list(const struct slist *addr_list)
13+static void print_esp_addresses(const struct hip_ll *const addresses)
14 {
15- const struct slist *list = addr_list;
16- struct esp_address *addr = NULL;
17+ const struct hip_ll_node *node = addresses->head;
18
19 HIP_DEBUG("ESP dst addr list:\n");
20- while (list) {
21- addr = list->data;
22+ while (node) {
23+ const struct esp_address *const addr = node->ptr;
24 HIP_DEBUG("addr: %s\n", addr_to_numeric(&addr->dst_addr));
25 if (addr && addr->update_id != NULL) {
26 HIP_DEBUG("upd id: %d\n", *addr->update_id);
27 }
28- list = list->next;
29+ node = node->next;
30 }
31 HIP_DEBUG("\n");
32 }
33@@ -135,7 +134,7 @@
34 esp_tuple->spi, esp_tuple->new_spi, esp_tuple->spi_update_id,
35 esp_tuple->tuple->direction);
36
37- print_esp_addr_list(esp_tuple->dst_addr_list);
38+ print_esp_addresses(&esp_tuple->dst_addresses);
39 }
40
41 /**
42@@ -288,20 +287,19 @@
43 /**
44 * Find an entry from the given list that matches to the given address
45 *
46- * @param addr_list the list to be searched for
47+ * @param addresses the list to be searched for
48 * @param addr the address to matched from the list
49 * @return the entry from the list that matched to the given address, or NULL if not found
50 */
51-static struct esp_address *get_esp_address(const struct slist *addr_list,
52- const struct in6_addr *addr)
53+static struct esp_address *get_esp_address(const struct hip_ll *const addresses,
54+ const struct in6_addr *const addr)
55 {
56- const struct slist *list = addr_list;
57- struct esp_address *esp_addr = NULL;
58+ const struct hip_ll_node *node = addresses->head;
59
60 HIP_DEBUG("get_esp_address\n");
61
62- while (list) {
63- esp_addr = list->data;
64+ while (node) {
65+ const struct esp_address *const esp_addr = node->ptr;
66 HIP_DEBUG("addr: %s \n", addr_to_numeric(&esp_addr->dst_addr));
67
68 HIP_DEBUG_HIT("111", &esp_addr->dst_addr);
69@@ -309,9 +307,15 @@
70
71 if (IN6_ARE_ADDR_EQUAL(&esp_addr->dst_addr, addr)) {
72 HIP_DEBUG("addr found\n");
73- return esp_addr;
74+ /* cannot return esp_addr because
75+ * a) it is const but this function's return type is not
76+ * b) it is const for good reason: we do not intend to modify it
77+ * c) casting esp_addr to 'struct esp_address*' causes a compiler
78+ * error.
79+ */
80+ return node->ptr;
81 }
82- list = list->next;
83+ node = node->next;
84 }
85 HIP_DEBUG("get_esp_address: addr %s not found\n", addr_to_numeric(addr));
86 return NULL;
87@@ -321,42 +325,53 @@
88 * Insert an address into a list of addresses. If same address exists already,
89 * the update_id is replaced with the new value.
90 *
91- * @param addr_list the address list
92+ * @param addresses the address list
93 * @param addr the address to be added
94 * @param upd_id update id
95 *
96- * @return the address list
97+ * @return true on success, false if insufficient memory is available for a new
98+ * esp address object.
99 */
100-static struct slist *update_esp_address(struct slist *addr_list,
101- const struct in6_addr *addr,
102- const uint32_t *upd_id)
103+static bool update_esp_address(struct hip_ll *const addresses,
104+ const struct in6_addr *const addr,
105+ const uint32_t *const upd_id)
106 {
107- struct esp_address *esp_addr = get_esp_address(addr_list, addr);
108- HIP_DEBUG("update_esp_address: address: %s \n", addr_to_numeric(addr));
109+ bool remove_esp_addr = false;
110+ int err = 0;
111+ struct esp_address *esp_addr = get_esp_address(addresses, addr);
112+ HIP_DEBUG("address: %s \n", addr_to_numeric(addr));
113
114- if (!addr_list) {
115- HIP_DEBUG("Esp slist is empty\n");
116+ // if necessary, allocate a new esp_address object
117+ if (!esp_addr) {
118+ HIP_IFEL(!(esp_addr = malloc(sizeof(*esp_addr))), -1,
119+ "Allocating esp_address object failed");
120+ remove_esp_addr = true;
121+ esp_addr->dst_addr = *addr;
122+ esp_addr->update_id = NULL; // gets set below
123+ HIP_IFEL(hip_ll_add_first(addresses, esp_addr) != 0, -1,
124+ "Inserting ESP address object into list of destination addresses failed");
125 }
126- if (esp_addr != NULL) {
127- if (upd_id != NULL) {
128- if (esp_addr->update_id == NULL) {
129- esp_addr->update_id = malloc(sizeof(uint32_t));
130- }
131- *esp_addr->update_id = *upd_id;
132+
133+ // update the update ID
134+ if (upd_id) {
135+ if (!esp_addr->update_id) {
136+ HIP_IFEL(!(esp_addr->update_id = malloc(sizeof(*esp_addr->update_id))),
137+ -1, "Allocating update ID object failed");
138 }
139- HIP_DEBUG("update_esp_address: found and updated\n");
140- return addr_list;
141- }
142- esp_addr = malloc(sizeof(struct esp_address));
143- memcpy(&esp_addr->dst_addr, addr, sizeof(struct in6_addr));
144- if (upd_id != NULL) {
145- esp_addr->update_id = malloc(sizeof(uint32_t));
146 *esp_addr->update_id = *upd_id;
147- } else {
148- esp_addr->update_id = NULL;
149- }
150- HIP_DEBUG("update_esp_address: addr created and added\n");
151- return append_to_slist(addr_list, esp_addr);
152+ }
153+
154+ return true;
155+
156+out_err:
157+ if (esp_addr && remove_esp_addr) {
158+ if (hip_ll_get(addresses, 0) == esp_addr) {
159+ hip_ll_del_first(addresses, NULL);
160+ }
161+ free(esp_addr->update_id);
162+ free(esp_addr);
163+ }
164+ return false;
165 }
166
167 /**
168@@ -377,7 +392,7 @@
169 while (list) {
170 struct esp_tuple *tuple = list->data;
171 if (spi == tuple->spi) {
172- if (dst_addr && get_esp_address(tuple->dst_addr_list, dst_addr) != NULL) {
173+ if (dst_addr && get_esp_address(&tuple->dst_addresses, dst_addr) != NULL) {
174 HIP_DEBUG("connection found by esp\n");
175 return tuple->tuple;
176 } else if (!dst_addr) {
177@@ -524,23 +539,15 @@
178 static void free_esp_tuple(struct esp_tuple *esp_tuple)
179 {
180 if (esp_tuple) {
181- struct slist *list = esp_tuple->dst_addr_list;
182 struct esp_address *addr = NULL;
183
184 // remove eventual cached anchor elements for this esp tuple
185 esp_prot_conntrack_remove_state(esp_tuple);
186
187 // remove all associated addresses
188- while (list) {
189- esp_tuple->dst_addr_list = remove_link_slist(esp_tuple->dst_addr_list,
190- list);
191- addr = list->data;
192-
193+ while ((addr = hip_ll_del_first(&esp_tuple->dst_addresses, NULL))) {
194 free(addr->update_id);
195 free(addr);
196-
197- free(list);
198- list = esp_tuple->dst_addr_list;
199 }
200
201 esp_tuple->tuple = NULL;
202@@ -618,7 +625,7 @@
203 }
204
205 /**
206- * create new ESP tuple based on the given parameters
207+ * Create an ESP tuple based on the parameters from a HIP message.
208 *
209 * @param esp_info a pointer to the ESP info parameter in the control message
210 * @param locator a pointer to the locator
211@@ -626,79 +633,109 @@
212 * @param tuple a pointer to the corresponding tuple
213 * @return the created tuple (caller frees) or NULL on failure (e.g. SPIs do not match)
214 */
215-static struct esp_tuple *esp_tuple_from_esp_info_locator(const struct hip_esp_info *esp_info,
216- const struct hip_locator *locator,
217- const struct hip_seq *seq,
218- struct tuple *tuple)
219+static struct esp_tuple *esp_tuple_from_esp_info_locator(const struct hip_esp_info *const esp_info,
220+ const struct hip_locator *const locator,
221+ const struct hip_seq *const seq,
222+ struct tuple *const tuple)
223 {
224- struct esp_tuple *new_esp = NULL;
225- const struct hip_locator_info_addr_item *locator_addr = NULL;
226- int n = 0;
227-
228- if (esp_info && locator && esp_info->new_spi == esp_info->old_spi) {
229- HIP_DEBUG("esp_tuple_from_esp_info_locator: new spi 0x%lx\n", esp_info->new_spi);
230- /* check that old spi is found */
231- new_esp = calloc(1, sizeof(struct esp_tuple));
232+ int err = 0;
233+ struct esp_tuple *new_esp = NULL;
234+
235+ HIP_ASSERT(esp_info);
236+ HIP_ASSERT(locator);
237+ HIP_ASSERT(seq);
238+ HIP_ASSERT(tuple);
239+ HIP_ASSERT(esp_info->new_spi == esp_info->old_spi);
240+
241+ HIP_DEBUG("new spi 0x%lx\n", esp_info->new_spi);
242+
243+ const unsigned addresses_in_locator =
244+ (hip_get_param_total_len(locator) - sizeof(struct hip_locator)) /
245+ sizeof(struct hip_locator_info_addr_item);
246+ HIP_DEBUG("%d addresses in locator\n", addresses_in_locator);
247+ if (addresses_in_locator > 0) {
248+ const struct hip_locator_info_addr_item *const addresses =
249+ (const struct hip_locator_info_addr_item *) (locator + 1);
250+
251+ HIP_IFEL((new_esp = calloc(1, sizeof(*new_esp))) == NULL, -1,
252+ "Allocating esp_tuple object failed");
253 new_esp->spi = ntohl(esp_info->new_spi);
254 new_esp->tuple = tuple;
255+ hip_ll_init(&new_esp->dst_addresses);
256
257- n = (hip_get_param_total_len(locator) - sizeof(struct hip_locator)) /
258- sizeof(struct hip_locator_info_addr_item);
259- HIP_DEBUG("esp_tuple_from_esp_info_locator: %d addresses in locator\n", n);
260- if (n > 0) {
261- locator_addr = (const struct hip_locator_info_addr_item *)
262- (locator + 1);
263- while (n > 0) {
264- struct esp_address *esp_address = malloc(sizeof(struct esp_address));
265- memcpy(&esp_address->dst_addr,
266- &locator_addr->address,
267- sizeof(struct in6_addr));
268- esp_address->update_id = malloc(sizeof(uint32_t));
269- *esp_address->update_id = seq->update_id;
270- new_esp->dst_addr_list = append_to_slist(new_esp->dst_addr_list,
271- esp_address);
272- n--;
273- if (n > 0) {
274- locator_addr++;
275+ for (unsigned idx = 0; idx < addresses_in_locator; idx += 1) {
276+ struct esp_address *const esp_address =
277+ malloc(sizeof(*esp_address));
278+ if (esp_address) {
279+ esp_address->dst_addr = addresses[idx].address;
280+ if ((esp_address->update_id = malloc(sizeof(*esp_address->update_id)))) {
281+ *esp_address->update_id = seq->update_id;
282+ if (hip_ll_add_first(&new_esp->dst_addresses, esp_address) == 0) {
283+ continue;
284+ } else {
285+ HIP_ERROR("Appending esp_address object %i to list of destination addresses in ESP tuple failed", idx);
286+ }
287+ free(esp_address->update_id);
288+ } else {
289+ HIP_OUT_ERR(-1, "Allocating update_id object for address %i failed", idx);
290 }
291+ free(esp_address);
292+ } else {
293+ HIP_ERROR("Allocating esp_address object for address %i failed", idx);
294 }
295- } else {
296- free(new_esp);
297- new_esp = NULL;
298+ goto out_err;
299 }
300+
301+ return new_esp;
302 }
303- return new_esp;
304+
305+out_err:
306+ free_esp_tuple(new_esp);
307+ return NULL;
308 }
309
310 /**
311- * create a new esp_tuple from the given parameters
312+ * Create an esp_tuple object from an esp_info message parameter and with a
313+ * specific destination address.
314 *
315 * @param esp_info a pointer to an ESP info parameter in the control message
316 * @param addr a pointer to an address
317 * @param tuple a pointer to a tuple structure
318 * @return the created ESP tuple (caller frees) or NULL on failure (e.g. SPIs don't match)
319 */
320-static struct esp_tuple *esp_tuple_from_esp_info(const struct hip_esp_info *esp_info,
321- const struct in6_addr *addr,
322- struct tuple *tuple)
323+static struct esp_tuple *esp_tuple_from_esp_info(const struct hip_esp_info *const esp_info,
324+ const struct in6_addr *const addr,
325+ struct tuple *const tuple)
326 {
327- struct esp_address *esp_address;
328- struct esp_tuple *new_esp = NULL;
329+ HIP_ASSERT(esp_info);
330+ HIP_ASSERT(addr);
331+ HIP_ASSERT(tuple);
332
333- if (esp_info) {
334- new_esp = calloc(1, sizeof(struct esp_tuple));
335+ struct esp_tuple *const new_esp = calloc(1, sizeof(*new_esp));
336+ if (new_esp) {
337 new_esp->spi = ntohl(esp_info->new_spi);
338 new_esp->tuple = tuple;
339-
340- esp_address = malloc(sizeof(struct esp_address));
341-
342- memcpy(&esp_address->dst_addr, addr, sizeof(struct in6_addr));
343-
344- esp_address->update_id = NULL;
345- new_esp->dst_addr_list = append_to_slist(new_esp->dst_addr_list,
346- esp_address);
347+ hip_ll_init(&new_esp->dst_addresses);
348+
349+ struct esp_address *const esp_address = malloc(sizeof(*esp_address));
350+ if (esp_address) {
351+ esp_address->dst_addr = *addr;
352+ esp_address->update_id = NULL;
353+ if (hip_ll_add_first(&new_esp->dst_addresses, esp_address) == 0) {
354+ return new_esp;
355+ } else {
356+ HIP_ERROR("Inserting esp_address object into ESP destination address list failed");
357+ }
358+ } else {
359+ HIP_ERROR("Allocating esp_address object failed");
360+ }
361+ free(esp_address);
362+ } else {
363+ HIP_ERROR("Allocating esp_tuple object failed");
364 }
365- return new_esp;
366+ free(new_esp);
367+
368+ return NULL;
369 }
370
371 /**
372@@ -1061,9 +1098,9 @@
373 esp_tuple->spi = ntohl(spi->new_spi);
374 esp_tuple->new_spi = 0;
375 esp_tuple->spi_update_id = 0;
376- esp_tuple->dst_addr_list = NULL;
377- esp_tuple->dst_addr_list = update_esp_address(esp_tuple->dst_addr_list,
378- ip6_src, NULL);
379+ hip_ll_init(&esp_tuple->dst_addresses);
380+ HIP_IFEL(!update_esp_address(&esp_tuple->dst_addresses, ip6_src, NULL),
381+ -1, "adding or updating ESP destination address failed");
382 esp_tuple->tuple = other_dir;
383
384 other_dir->esp_tuples = append_to_slist(other_dir->esp_tuples, esp_tuple);
385@@ -1132,9 +1169,9 @@
386 esp_tuple->spi = ntohl(spi->new_spi);
387 esp_tuple->new_spi = 0;
388 esp_tuple->spi_update_id = 0;
389- esp_tuple->dst_addr_list = NULL;
390- esp_tuple->dst_addr_list = update_esp_address(esp_tuple->dst_addr_list,
391- ip6_src, NULL);
392+ hip_ll_init(&esp_tuple->dst_addresses);
393+ HIP_IFEL(!update_esp_address(&esp_tuple->dst_addresses, ip6_src, NULL),
394+ -1, "adding or updating ESP destination address failed");
395 esp_tuple->tuple = other_dir;
396
397 insert_esp_tuple(esp_tuple);
398@@ -1210,9 +1247,10 @@
399 (locator + 1);
400
401 while (n > 0) {
402- esp_tuple->dst_addr_list = update_esp_address(esp_tuple->dst_addr_list,
403- &locator_addr->address,
404- &seq->update_id);
405+ HIP_IFEL(!update_esp_address(&esp_tuple->dst_addresses,
406+ &locator_addr->address,
407+ &seq->update_id), 0,
408+ "adding or updating ESP destination address failed");
409 n--;
410
411 if (n > 0) {
412@@ -1252,9 +1290,10 @@
413 print_esp_tuple(esp_tuple);
414
415 while (n > 0) {
416- esp_tuple->dst_addr_list = update_esp_address(esp_tuple->dst_addr_list,
417- &locator_addr->address,
418- &seq->update_id);
419+ HIP_IFEL(!update_esp_address(&esp_tuple->dst_addresses,
420+ &locator_addr->address,
421+ &seq->update_id), 0,
422+ "adding or updating ESP destination address failed");
423 n--;
424
425 if (n > 0) {
426@@ -1345,6 +1384,10 @@
427
428 /* we have to consider the src ip address in case of cascading NATs (see above FIXME) */
429 esp_tuple = esp_tuple_from_esp_info(esp_info, ip6_src, other_dir_tuple);
430+ if (!esp_tuple) {
431+ free(data);
432+ HIP_OUT_ERR(0, "Unable to create esp_tuple object from update message");
433+ }
434
435 other_dir_tuple->esp_tuples = append_to_slist(other_dir_esps,
436 esp_tuple);
437
438=== modified file 'firewall/firewall_defines.h'
439--- firewall/firewall_defines.h 2011-01-11 13:59:46 +0000
440+++ firewall/firewall_defines.h 2011-03-30 11:11:01 +0000
441@@ -82,7 +82,7 @@
442 uint32_t spi;
443 uint32_t new_spi;
444 uint32_t spi_update_id;
445- struct slist *dst_addr_list;
446+ struct hip_ll dst_addresses;
447 struct tuple *tuple;
448 /* tracking of the ESP SEQ number */
449 uint32_t seq_no;

Subscribers

People subscribed via source and target branches

to all changes: