summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils
diff options
context:
space:
mode:
authorYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
committerYves-Alexis Perez <corsac@corsac.net>2012-06-28 21:16:07 +0200
commitb34738ed08c2227300d554b139e2495ca5da97d6 (patch)
tree62f33b52820f2e49f0e53c0f8c636312037c8054 /src/libstrongswan/utils
parent0a9d51a49042a68daa15b0c74a2b7f152f52606b (diff)
downloadvyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.tar.gz
vyos-strongswan-b34738ed08c2227300d554b139e2495ca5da97d6.zip
Imported Upstream version 4.6.4
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r--src/libstrongswan/utils/backtrace.c87
-rw-r--r--src/libstrongswan/utils/backtrace.h14
-rw-r--r--src/libstrongswan/utils/enumerator.h4
-rw-r--r--src/libstrongswan/utils/hashtable.c225
-rw-r--r--src/libstrongswan/utils/host.c98
-rw-r--r--src/libstrongswan/utils/identification.c2
-rw-r--r--src/libstrongswan/utils/identification.h6
-rw-r--r--src/libstrongswan/utils/iterator.h114
-rw-r--r--src/libstrongswan/utils/leak_detective.c224
-rw-r--r--src/libstrongswan/utils/leak_detective.h7
-rw-r--r--src/libstrongswan/utils/linked_list.c547
-rw-r--r--src/libstrongswan/utils/linked_list.h60
-rw-r--r--src/libstrongswan/utils/optionsfrom.c10
13 files changed, 635 insertions, 763 deletions
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index 5744439f8..cb83d9830 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -50,10 +50,8 @@ struct private_backtrace_t {
void *frames[];
};
-/**
- * Implementation of backtrace_t.log
- */
-static void log_(private_backtrace_t *this, FILE *file, bool detailed)
+METHOD(backtrace_t, log_, void,
+ private_backtrace_t *this, FILE *file, bool detailed)
{
#ifdef HAVE_BACKTRACE
size_t i;
@@ -129,11 +127,8 @@ static void log_(private_backtrace_t *this, FILE *file, bool detailed)
#endif /* HAVE_BACKTRACE */
}
-/**
- * Implementation of backtrace_t.contains_function
- */
-static bool contains_function(private_backtrace_t *this,
- char *function[], int count)
+METHOD(backtrace_t, contains_function, bool,
+ private_backtrace_t *this, char *function[], int count)
{
#ifdef HAVE_DLADDR
int i, j;
@@ -157,10 +152,70 @@ static bool contains_function(private_backtrace_t *this,
return FALSE;
}
+METHOD(backtrace_t, equals, bool,
+ private_backtrace_t *this, backtrace_t *other_public)
+{
+ private_backtrace_t *other = (private_backtrace_t*)other_public;
+ int i;
+
+ if (this == other)
+ {
+ return TRUE;
+ }
+ if (this->frame_count != other->frame_count)
+ {
+ return FALSE;
+ }
+ for (i = 0; i < this->frame_count; i++)
+ {
+ if (this->frames[i] != other->frames[i])
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
/**
- * Implementation of backtrace_t.destroy.
+ * Frame enumerator
*/
-static void destroy(private_backtrace_t *this)
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** reference to backtrace */
+ private_backtrace_t *bt;
+ /** current position */
+ int i;
+} frame_enumerator_t;
+
+METHOD(enumerator_t, frame_enumerate, bool,
+ frame_enumerator_t *this, void **addr)
+{
+ if (this->i < this->bt->frame_count)
+ {
+ *addr = this->bt->frames[this->i++];
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(backtrace_t, create_frame_enumerator, enumerator_t*,
+ private_backtrace_t *this)
+{
+ frame_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_frame_enumerate,
+ .destroy = (void*)free,
+ },
+ .bt = this,
+ );
+ return &enumerator->public;
+}
+
+METHOD(backtrace_t, destroy, void,
+ private_backtrace_t *this)
{
free(this);
}
@@ -182,9 +237,13 @@ backtrace_t *backtrace_create(int skip)
memcpy(this->frames, frames + skip, frame_count * sizeof(void*));
this->frame_count = frame_count;
- this->public.log = (void(*)(backtrace_t*,FILE*,bool))log_;
- this->public.contains_function = (bool(*)(backtrace_t*, char *function[], int count))contains_function;
- this->public.destroy = (void(*)(backtrace_t*))destroy;
+ this->public = (backtrace_t) {
+ .log = _log_,
+ .contains_function = _contains_function,
+ .equals = _equals,
+ .create_frame_enumerator = _create_frame_enumerator,
+ .destroy = _destroy,
+ };
return &this->public;
}
diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h
index e8ccfc1bd..9d59d2503 100644
--- a/src/libstrongswan/utils/backtrace.h
+++ b/src/libstrongswan/utils/backtrace.h
@@ -50,6 +50,20 @@ struct backtrace_t {
bool (*contains_function)(backtrace_t *this, char *function[], int count);
/**
+ * Check two backtraces for equality.
+ *
+ * @param other backtrace to compare to this
+ * @return TRUE if backtraces are equal
+ */
+ bool (*equals)(backtrace_t *this, backtrace_t *other);
+ /**
+ * Create an enumerator over the stack frame addresses.
+ *
+ * @return enumerator_t over void*
+ */
+ enumerator_t* (*create_frame_enumerator)(backtrace_t *this);
+
+ /**
* Destroy a backtrace instance.
*/
void (*destroy)(backtrace_t *this);
diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h
index 537bf69e1..12b5712ae 100644
--- a/src/libstrongswan/utils/enumerator.h
+++ b/src/libstrongswan/utils/enumerator.h
@@ -26,7 +26,7 @@ typedef struct enumerator_t enumerator_t;
#include "../utils.h"
/**
- * Enumerate is simpler, but more flexible than iterator.
+ * Enumerator interface, allows enumeration over collections.
*/
struct enumerator_t {
@@ -36,7 +36,7 @@ struct enumerator_t {
* The enumerate function takes a variable argument list containing
* pointers where the enumerated values get written.
*
- * @param ... variable list of enumerated items, implementation dependant
+ * @param ... variable list of enumerated items, implementation dependent
* @return TRUE if pointers returned
*/
bool (*enumerate)(enumerator_t *this, ...);
diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c
index 49b0bb68c..33f645170 100644
--- a/src/libstrongswan/utils/hashtable.c
+++ b/src/libstrongswan/utils/hashtable.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2010 Tobias Brunner
+ * Copyright (C) 2008-2011 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,7 +13,6 @@
* for more details.
*/
-#include <utils/linked_list.h>
#include "hashtable.h"
@@ -40,12 +39,17 @@ struct pair_t {
* Cached hash (used in case of a resize).
*/
u_int hash;
+
+ /**
+ * Next pair in an overflow list.
+ */
+ pair_t *next;
};
/**
* Creates an empty pair object.
*/
-pair_t *pair_create(void *key, void *value, u_int hash)
+static inline pair_t *pair_create(void *key, void *value, u_int hash)
{
pair_t *this;
@@ -93,7 +97,7 @@ struct private_hashtable_t {
/**
* The actual table.
*/
- linked_list_t **table;
+ pair_t **table;
/**
* The hashing function.
@@ -129,23 +133,21 @@ struct private_enumerator_t {
u_int row;
/**
+ * number of remaining items in hashtable
+ */
+ u_int count;
+
+ /**
* current pair
*/
- pair_t *pair;
+ pair_t *current;
/**
- * enumerator for the current row
+ * previous pair (used by remove_at)
*/
- enumerator_t *current;
-};
+ pair_t *prev;
-/**
- * Compare a pair in a list with the given key.
- */
-static inline bool pair_equals(pair_t *pair, private_hashtable_t *this, void *key)
-{
- return this->equals(key, pair->key);
-}
+};
/**
* This function returns the next-highest power of two for the given number.
@@ -175,7 +177,7 @@ static void init_hashtable(private_hashtable_t *this, u_int capacity)
this->mask = this->capacity - 1;
this->load_factor = 0.75;
- this->table = calloc(this->capacity, sizeof(linked_list_t*));
+ this->table = calloc(this->capacity, sizeof(pair_t*));
}
/**
@@ -183,7 +185,7 @@ static void init_hashtable(private_hashtable_t *this, u_int capacity)
*/
static void rehash(private_hashtable_t *this)
{
- linked_list_t **old_table;
+ pair_t **old_table;
u_int row, old_capacity;
if (this->capacity >= MAX_CAPACITY)
@@ -198,29 +200,17 @@ static void rehash(private_hashtable_t *this)
for (row = 0; row < old_capacity; row++)
{
- enumerator_t *enumerator;
- linked_list_t *list, *new_list;
- pair_t *pair;
+ pair_t *pair, *next;
u_int new_row;
- list = old_table[row];
- if (list)
- {
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &pair))
- {
- new_row = pair->hash & this->mask;
-
- list->remove_at(list, enumerator);
- new_list = this->table[new_row];
- if (!new_list)
- {
- new_list = this->table[new_row] = linked_list_create();
- }
- new_list->insert_last(new_list, pair);
- }
- enumerator->destroy(enumerator);
- list->destroy(list);
+ pair = old_table[row];
+ while (pair)
+ { /* insert pair at the front of new bucket*/
+ next = pair->next;
+ new_row = pair->hash & this->mask;
+ pair->next = this->table[new_row];
+ this->table[new_row] = pair;
+ pair = next;
}
}
free(old_table);
@@ -230,38 +220,28 @@ METHOD(hashtable_t, put, void*,
private_hashtable_t *this, void *key, void *value)
{
void *old_value = NULL;
- linked_list_t *list;
- u_int hash;
- u_int row;
+ pair_t *pair;
+ u_int hash, row;
hash = this->hash(key);
row = hash & this->mask;
- list = this->table[row];
- if (list)
- {
- enumerator_t *enumerator;
- pair_t *pair;
-
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &pair))
+ pair = this->table[row];
+ while (pair)
+ { /* search existing bucket for key */
+ if (this->equals(key, pair->key))
{
- if (pair_equals(pair, this, key))
- {
- old_value = pair->value;
- pair->value = value;
- pair->key = key;
- break;
- }
+ old_value = pair->value;
+ pair->value = value;
+ pair->key = key;
+ break;
}
- enumerator->destroy(enumerator);
- }
- else
- {
- list = this->table[row] = linked_list_create();
+ pair = pair->next;
}
- if (!old_value)
- {
- list->insert_last(list, pair_create(key, value, hash));
+ if (!pair)
+ { /* insert at the front of bucket */
+ pair = pair_create(key, value, hash);
+ pair->next = this->table[row];
+ this->table[row] = pair;
this->count++;
}
if (this->count >= this->capacity * this->load_factor)
@@ -275,17 +255,17 @@ METHOD(hashtable_t, get, void*,
private_hashtable_t *this, void *key)
{
void *value = NULL;
- linked_list_t *list;
pair_t *pair;
- list = this->table[this->hash(key) & this->mask];
- if (list)
+ pair = this->table[this->hash(key) & this->mask];
+ while (pair)
{
- if (list->find_first(list, (linked_list_match_t)pair_equals,
- (void**)&pair, this, key) == SUCCESS)
+ if (this->equals(key, pair->key))
{
value = pair->value;
+ break;
}
+ pair = pair->next;
}
return value;
}
@@ -294,27 +274,30 @@ METHOD(hashtable_t, remove_, void*,
private_hashtable_t *this, void *key)
{
void *value = NULL;
- linked_list_t *list;
+ pair_t *pair, *prev = NULL;
+ u_int row;
- list = this->table[this->hash(key) & this->mask];
- if (list)
+ row = this->hash(key) & this->mask;
+ pair = this->table[row];
+ while (pair)
{
- enumerator_t *enumerator;
- pair_t *pair;
-
- enumerator = list->create_enumerator(list);
- while (enumerator->enumerate(enumerator, &pair))
+ if (this->equals(key, pair->key))
{
- if (pair_equals(pair, this, key))
+ if (prev)
{
- list->remove_at(list, enumerator);
- value = pair->value;
- this->count--;
- free(pair);
- break;
+ prev->next = pair->next;
}
+ else
+ {
+ this->table[row] = pair->next;
+ }
+ value = pair->value;
+ this->count--;
+ free(pair);
+ break;
}
- enumerator->destroy(enumerator);
+ prev = pair;
+ pair = pair->next;
}
return value;
}
@@ -324,14 +307,18 @@ METHOD(hashtable_t, remove_at, void,
{
if (enumerator->table == this && enumerator->current)
{
- linked_list_t *list;
- list = this->table[enumerator->row];
- if (list)
+ pair_t *current = enumerator->current;
+ if (enumerator->prev)
{
- list->remove_at(list, enumerator->current);
- free(enumerator->pair);
- this->count--;
+ enumerator->prev->next = current->next;
+ }
+ else
+ {
+ this->table[enumerator->row] = current->next;
}
+ enumerator->current = enumerator->prev;
+ free(current);
+ this->count--;
}
}
@@ -344,50 +331,35 @@ METHOD(hashtable_t, get_count, u_int,
METHOD(enumerator_t, enumerate, bool,
private_enumerator_t *this, void **key, void **value)
{
- while (this->row < this->table->capacity)
+ while (this->count && this->row < this->table->capacity)
{
+ this->prev = this->current;
if (this->current)
{
- if (this->current->enumerate(this->current, &this->pair))
- {
- if (key)
- {
- *key = this->pair->key;
- }
- if (value)
- {
- *value = this->pair->value;
- }
- return TRUE;
- }
- this->current->destroy(this->current);
- this->current = NULL;
+ this->current = this->current->next;
}
else
{
- linked_list_t *list;
- list = this->table->table[this->row];
- if (list)
+ this->current = this->table->table[this->row];
+ }
+ if (this->current)
+ {
+ if (key)
{
- this->current = list->create_enumerator(list);
- continue;
+ *key = this->current->key;
}
+ if (value)
+ {
+ *value = this->current->value;
+ }
+ this->count--;
+ return TRUE;
}
this->row++;
}
return FALSE;
}
-METHOD(enumerator_t, enumerator_destroy, void,
- private_enumerator_t *this)
-{
- if (this->current)
- {
- this->current->destroy(this->current);
- }
- free(this);
-}
-
METHOD(hashtable_t, create_enumerator, enumerator_t*,
private_hashtable_t *this)
{
@@ -396,9 +368,10 @@ METHOD(hashtable_t, create_enumerator, enumerator_t*,
INIT(enumerator,
.enumerator = {
.enumerate = (void*)_enumerate,
- .destroy = (void*)_enumerator_destroy,
+ .destroy = (void*)free,
},
.table = this,
+ .count = this->count,
);
return &enumerator->enumerator;
@@ -407,15 +380,17 @@ METHOD(hashtable_t, create_enumerator, enumerator_t*,
METHOD(hashtable_t, destroy, void,
private_hashtable_t *this)
{
- linked_list_t *list;
+ pair_t *pair, *next;
u_int row;
for (row = 0; row < this->capacity; row++)
{
- list = this->table[row];
- if (list)
+ pair = this->table[row];
+ while (pair)
{
- list->destroy_function(list, free);
+ next = pair->next;
+ free(pair);
+ pair = next;
}
}
free(this->table);
diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c
index 615d85c95..d3020a5d0 100644
--- a/src/libstrongswan/utils/host.c
+++ b/src/libstrongswan/utils/host.c
@@ -40,7 +40,7 @@ struct private_host_t {
host_t public;
/**
- * low-lewel structure, wich stores the address
+ * low-lewel structure, which stores the address
*/
union {
/** generic type */
@@ -59,26 +59,20 @@ struct private_host_t {
};
-/**
- * implements host_t.get_sockaddr
- */
-static sockaddr_t *get_sockaddr(private_host_t *this)
+METHOD(host_t, get_sockaddr, sockaddr_t*,
+ private_host_t *this)
{
return &(this->address);
}
-/**
- * implements host_t.get_sockaddr_len
- */
-static socklen_t *get_sockaddr_len(private_host_t *this)
+METHOD(host_t, get_sockaddr_len, socklen_t*,
+ private_host_t *this)
{
return &(this->socklen);
}
-/**
- * Implementation of host_t.is_anyaddr.
- */
-static bool is_anyaddr(private_host_t *this)
+METHOD(host_t, is_anyaddr, bool,
+ private_host_t *this)
{
switch (this->address.sa_family)
{
@@ -163,10 +157,8 @@ int host_printf_hook(char *dst, size_t dstlen, printf_hook_spec_t *spec,
return print_in_hook(dst, dstlen, "%*s", spec->width, buffer);
}
-/**
- * Implementation of host_t.get_address.
- */
-static chunk_t get_address(private_host_t *this)
+METHOD(host_t, get_address, chunk_t,
+ private_host_t *this)
{
chunk_t address = chunk_empty;
@@ -192,18 +184,14 @@ static chunk_t get_address(private_host_t *this)
}
}
-/**
- * implements host_t.get_family
- */
-static int get_family(private_host_t *this)
+METHOD(host_t, get_family, int,
+ private_host_t *this)
{
return this->address.sa_family;
}
-/**
- * implements host_t.get_port
- */
-static u_int16_t get_port(private_host_t *this)
+METHOD(host_t, get_port, u_int16_t,
+ private_host_t *this)
{
switch (this->address.sa_family)
{
@@ -222,10 +210,8 @@ static u_int16_t get_port(private_host_t *this)
}
}
-/**
- * implements host_t.set_port
- */
-static void set_port(private_host_t *this, u_int16_t port)
+METHOD(host_t, set_port, void,
+ private_host_t *this, u_int16_t port)
{
switch (this->address.sa_family)
{
@@ -246,19 +232,19 @@ static void set_port(private_host_t *this, u_int16_t port)
}
}
-/**
- * Implements host_t.clone.
- */
-static private_host_t *clone_(private_host_t *this)
+METHOD(host_t, clone_, host_t*,
+ private_host_t *this)
{
- private_host_t *new = malloc_thing(private_host_t);
+ private_host_t *new;
+ new = malloc_thing(private_host_t);
memcpy(new, this, sizeof(private_host_t));
- return new;
+
+ return &new->public;
}
/**
- * Impelements host_t.ip_equals
+ * Implements host_t.ip_equals
*/
static bool ip_equals(private_host_t *this, private_host_t *other)
{
@@ -332,10 +318,8 @@ static bool equals(private_host_t *this, private_host_t *other)
return FALSE;
}
-/**
- * Implements host_t.destroy
- */
-static void destroy(private_host_t *this)
+METHOD(host_t, destroy, void,
+ private_host_t *this)
{
free(this);
}
@@ -345,20 +329,24 @@ static void destroy(private_host_t *this)
*/
static private_host_t *host_create_empty(void)
{
- private_host_t *this = malloc_thing(private_host_t);
-
- this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
- this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
- this->public.clone = (host_t* (*) (host_t*))clone_;
- this->public.get_family = (int (*) (host_t*))get_family;
- this->public.get_address = (chunk_t (*) (host_t *)) get_address;
- this->public.get_port = (u_int16_t (*) (host_t *))get_port;
- this->public.set_port = (void (*) (host_t *,u_int16_t))set_port;
- this->public.get_differences = get_differences;
- this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
- this->public.equals = (bool (*) (host_t *,host_t *)) equals;
- this->public.is_anyaddr = (bool (*) (host_t *)) is_anyaddr;
- this->public.destroy = (void (*) (host_t*))destroy;
+ private_host_t *this;
+
+ INIT(this,
+ .public = {
+ .get_sockaddr = _get_sockaddr,
+ .get_sockaddr_len = _get_sockaddr_len,
+ .clone = _clone_,
+ .get_family = _get_family,
+ .get_address = _get_address,
+ .get_port = _get_port,
+ .set_port = _set_port,
+ .get_differences = get_differences,
+ .ip_equals = (bool (*)(host_t *,host_t *))ip_equals,
+ .equals = (bool (*)(host_t *,host_t *)) equals,
+ .is_anyaddr = _is_anyaddr,
+ .destroy = _destroy,
+ },
+ );
return this;
}
@@ -585,7 +573,7 @@ host_t *host_create_from_subnet(char *string, int *bits)
*bits = atoi(pos + 1);
return host_create_from_string(buf, 0);
}
- net = host_create_from_string(buf, 0);
+ net = host_create_from_string(string, 0);
if (net)
{
if (net->get_family(net) == AF_INET)
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 252cfa28e..9f0007f78 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -81,6 +81,7 @@ static const x501rdn_t x501rdns[] = {
{"N", OID_NAME, ASN1_PRINTABLESTRING},
{"G", OID_GIVEN_NAME, ASN1_PRINTABLESTRING},
{"I", OID_INITIALS, ASN1_PRINTABLESTRING},
+ {"dnQualifier", OID_DN_QUALIFIER, ASN1_PRINTABLESTRING},
{"ID", OID_UNIQUE_IDENTIFIER, ASN1_PRINTABLESTRING},
{"EN", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
{"employeeNumber", OID_EMPLOYEE_NUMBER, ASN1_PRINTABLESTRING},
@@ -219,6 +220,7 @@ METHOD(enumerator_t, rdn_part_enumerate, bool,
{OID_NAME, ID_PART_RDN_N},
{OID_GIVEN_NAME, ID_PART_RDN_G},
{OID_INITIALS, ID_PART_RDN_I},
+ {OID_DN_QUALIFIER, ID_PART_RDN_DNQ},
{OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
{OID_EMAIL_ADDRESS, ID_PART_RDN_E},
{OID_EMPLOYEE_NUMBER, ID_PART_RDN_EN},
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index c463b0274..3978b23f3 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -171,6 +171,8 @@ enum id_part_t {
ID_PART_RDN_G,
/** Initials RDN of a DN */
ID_PART_RDN_I,
+ /** DN Qualifier RDN of a DN */
+ ID_PART_RDN_DNQ,
/** UniqueIdentifier RDN of a DN */
ID_PART_RDN_ID,
/** Locality RDN of a DN */
@@ -293,12 +295,12 @@ struct identification_t {
*
* In favour of pluto, domainnames are prepended with an @, since
* pluto resolves domainnames without an @ to IPv4 addresses. Since
- * we use a seperate host_t class for addresses, this doesn't
+ * we use a separate host_t class for addresses, this doesn't
* make sense for us.
*
* A distinguished name may contain one or more of the following RDNs:
* ND, UID, DC, CN, S, SN, serialNumber, C, L, ST, O, OU, T, D,
- * N, G, I, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
+ * N, G, I, dnQualifier, ID, EN, EmployeeNumber, E, Email, emailAddress, UN,
* unstructuredName, TCGID.
*
* This constructor never returns NULL. If it does not find a suitable
diff --git a/src/libstrongswan/utils/iterator.h b/src/libstrongswan/utils/iterator.h
deleted file mode 100644
index 9be65b229..000000000
--- a/src/libstrongswan/utils/iterator.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Martin Willi
- * Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * @defgroup iterator iterator
- * @{ @ingroup utils
- */
-
-#ifndef ITERATOR_H_
-#define ITERATOR_H_
-
-#include <library.h>
-
-
-typedef struct iterator_t iterator_t;
-
-/**
- * Iterator interface, allows iteration over collections.
- *
- * iterator_t defines an interface for iterating over collections.
- * It allows searching, deleting, updating and inserting.
- *
- * @deprecated Use enumerator instead.
- */
-struct iterator_t {
-
- /**
- * Return number of list items.
- *
- * @return number of list items
- */
- int (*get_count) (iterator_t *this);
-
- /**
- * Iterate over all items.
- *
- * The easy way to iterate over items.
- *
- * @param value item
- * @return TRUE, if there was an element available, FALSE otherwise
- */
- bool (*iterate) (iterator_t *this, void** value);
-
- /**
- * Inserts a new item before the given iterator position.
- *
- * The iterator position is not changed after inserting
- *
- * @param item value to insert in list
- */
- void (*insert_before) (iterator_t *this, void *item);
-
- /**
- * Inserts a new item after the given iterator position.
- *
- * The iterator position is not changed after inserting.
- *
- * @param this calling iterator
- * @param item value to insert in list
- */
- void (*insert_after) (iterator_t *this, void *item);
-
- /**
- * Replace the current item at current iterator position.
- *
- * The iterator position is not changed after replacing.
- *
- * @param this calling iterator
- * @param old old value will be written here(can be NULL)
- * @param new new value
- * @return SUCCESS, FAILED if iterator is on an invalid position
- */
- status_t (*replace) (iterator_t *this, void **old, void *new);
-
- /**
- * Removes an element from list at the given iterator position.
- *
- * The iterator is set the the following position:
- * - to the item before, if available
- * - it gets reseted, otherwise
- *
- * @return SUCCESS, FAILED if iterator is on an invalid position
- */
- status_t (*remove) (iterator_t *this);
-
- /**
- * Resets the iterator position.
- *
- * After reset, the iterator_t objects doesn't point to an element.
- * A call to iterator_t.has_next is necessary to do any other operations
- * with the resetted iterator.
- */
- void (*reset) (iterator_t *this);
-
- /**
- * Destroys an iterator.
- */
- void (*destroy) (iterator_t *this);
-};
-
-#endif /** ITERATOR_H_ @}*/
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index 39505d3f3..0a8789335 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -34,6 +34,7 @@
#include <library.h>
#include <debug.h>
#include <utils/backtrace.h>
+#include <utils/hashtable.h>
typedef struct private_leak_detective_t private_leak_detective_t;
@@ -92,11 +93,6 @@ typedef struct memory_tail_t memory_tail_t;
struct memory_header_t {
/**
- * Number of bytes following after the header
- */
- u_int bytes;
-
- /**
* Pointer to previous entry in linked list
*/
memory_header_t *previous;
@@ -112,6 +108,11 @@ struct memory_header_t {
backtrace_t *backtrace;
/**
+ * Number of bytes following after the header
+ */
+ u_int32_t bytes;
+
+ /**
* magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC
*/
u_int32_t magic;
@@ -148,6 +149,37 @@ static memory_header_t first_header = {
static bool installed = FALSE;
/**
+ * Installs the malloc hooks, enables leak detection
+ */
+static void install_hooks()
+{
+ if (!installed)
+ {
+ old_malloc_hook = __malloc_hook;
+ old_realloc_hook = __realloc_hook;
+ old_free_hook = __free_hook;
+ __malloc_hook = malloc_hook;
+ __realloc_hook = realloc_hook;
+ __free_hook = free_hook;
+ installed = TRUE;
+ }
+}
+
+/**
+ * Uninstalls the malloc hooks, disables leak detection
+ */
+static void uninstall_hooks()
+{
+ if (installed)
+ {
+ __malloc_hook = old_malloc_hook;
+ __free_hook = old_free_hook;
+ __realloc_hook = old_realloc_hook;
+ installed = FALSE;
+ }
+}
+
+/**
* Leak report white list
*
* List of functions using static allocation buffers or should be suppressed
@@ -162,6 +194,7 @@ char *whitelist[] = {
"__pthread_setspecific",
/* glibc functions */
"mktime",
+ "ctime",
"__gmtime_r",
"localtime_r",
"tzset",
@@ -172,6 +205,7 @@ char *whitelist[] = {
"getprotobynumber",
"getservbyport",
"getservbyname",
+ "gethostbyname",
"gethostbyname2",
"gethostbyname_r",
"gethostbyname2_r",
@@ -187,6 +221,9 @@ char *whitelist[] = {
"getaddrinfo",
"setlocale",
"getpass",
+ "getpwent_r",
+ "setpwent",
+ "endpwent",
/* ignore dlopen, as we do not dlclose to get proper leak reports */
"dlopen",
"dlerror",
@@ -236,31 +273,109 @@ char *whitelist[] = {
"gnutls_global_init",
};
+
/**
- * Report leaks at library destruction
+ * Hashtable hash function
*/
-static void report(private_leak_detective_t *this, bool detailed)
+static u_int hash(backtrace_t *key)
{
- if (lib->leak_detective)
+ enumerator_t *enumerator;
+ void *addr;
+ u_int hash = 0;
+
+ enumerator = key->create_frame_enumerator(key);
+ while (enumerator->enumerate(enumerator, &addr))
{
- memory_header_t *hdr;
- int leaks = 0, whitelisted = 0;
+ hash = chunk_hash_inc(chunk_from_thing(addr), hash);
+ }
+ enumerator->destroy(enumerator);
+
+ return hash;
+}
+
+/**
+ * Hashtable equals function
+ */
+static bool equals(backtrace_t *a, backtrace_t *b)
+{
+ return a->equals(a, b);
+}
- for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
+/**
+ * Summarize and print backtraces
+ */
+static int print_traces(private_leak_detective_t *this,
+ FILE *out, int thresh, bool detailed, int *whitelisted)
+{
+ int leaks = 0;
+ memory_header_t *hdr;
+ enumerator_t *enumerator;
+ hashtable_t *entries;
+ struct {
+ /** associated backtrace */
+ backtrace_t *backtrace;
+ /** total size of all allocations */
+ size_t bytes;
+ /** number of allocations */
+ u_int count;
+ } *entry;
+
+ uninstall_hooks();
+
+ entries = hashtable_create((hashtable_hash_t)hash,
+ (hashtable_equals_t)equals, 1024);
+ for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
+ {
+ if (whitelisted &&
+ hdr->backtrace->contains_function(hdr->backtrace,
+ whitelist, countof(whitelist)))
{
- if (hdr->backtrace->contains_function(hdr->backtrace,
- whitelist, countof(whitelist)))
- {
- whitelisted++;
- }
- else
- {
- fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1);
- /* skip the first frame, contains leak detective logic */
- hdr->backtrace->log(hdr->backtrace, stderr, detailed);
- leaks++;
- }
+ (*whitelisted)++;
+ continue;
+ }
+ entry = entries->get(entries, hdr->backtrace);
+ if (entry)
+ {
+ entry->bytes += hdr->bytes;
+ entry->count++;
+ }
+ else
+ {
+ INIT(entry,
+ .backtrace = hdr->backtrace,
+ .bytes = hdr->bytes,
+ .count = 1,
+ );
+ entries->put(entries, hdr->backtrace, entry);
}
+ leaks++;
+ }
+ enumerator = entries->create_enumerator(entries);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ if (!thresh || entry->bytes >= thresh)
+ {
+ fprintf(out, "%d bytes total, %d allocations, %d bytes average:\n",
+ entry->bytes, entry->count, entry->bytes / entry->count);
+ entry->backtrace->log(entry->backtrace, out, detailed);
+ }
+ free(entry);
+ }
+ enumerator->destroy(enumerator);
+ entries->destroy(entries);
+
+ install_hooks();
+ return leaks;
+}
+
+METHOD(leak_detective_t, report, void,
+ private_leak_detective_t *this, bool detailed)
+{
+ if (lib->leak_detective)
+ {
+ int leaks = 0, whitelisted = 0;
+
+ leaks = print_traces(this, stderr, 0, detailed, &whitelisted);
switch (leaks)
{
case 0:
@@ -281,35 +396,26 @@ static void report(private_leak_detective_t *this, bool detailed)
}
}
-/**
- * Installs the malloc hooks, enables leak detection
- */
-static void install_hooks()
+METHOD(leak_detective_t, usage, void,
+ private_leak_detective_t *this, FILE *out)
{
- if (!installed)
- {
- old_malloc_hook = __malloc_hook;
- old_realloc_hook = __realloc_hook;
- old_free_hook = __free_hook;
- __malloc_hook = malloc_hook;
- __realloc_hook = realloc_hook;
- __free_hook = free_hook;
- installed = TRUE;
- }
-}
+ int oldpolicy, thresh;
+ bool detailed;
+ pthread_t thread_id = pthread_self();
+ struct sched_param oldparams, params;
-/**
- * Uninstalls the malloc hooks, disables leak detection
- */
-static void uninstall_hooks()
-{
- if (installed)
- {
- __malloc_hook = old_malloc_hook;
- __free_hook = old_free_hook;
- __realloc_hook = old_realloc_hook;
- installed = FALSE;
- }
+ thresh = lib->settings->get_int(lib->settings,
+ "libstrongswan.leak_detective.usage_threshold", 10240);
+ detailed = lib->settings->get_bool(lib->settings,
+ "libstrongswan.leak_detective.detailed", TRUE);
+
+ pthread_getschedparam(thread_id, &oldpolicy, &oldparams);
+ params.__sched_priority = sched_get_priority_max(SCHED_FIFO);
+ pthread_setschedparam(thread_id, SCHED_FIFO, &params);
+
+ print_traces(this, out, thresh, detailed, NULL);
+
+ pthread_setschedparam(thread_id, oldpolicy, &oldparams);
}
/**
@@ -492,10 +598,8 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
return hdr + 1;
}
-/**
- * Implementation of leak_detective_t.destroy
- */
-static void destroy(private_leak_detective_t *this)
+METHOD(leak_detective_t, destroy, void,
+ private_leak_detective_t *this)
{
if (installed)
{
@@ -509,10 +613,15 @@ static void destroy(private_leak_detective_t *this)
*/
leak_detective_t *leak_detective_create()
{
- private_leak_detective_t *this = malloc_thing(private_leak_detective_t);
+ private_leak_detective_t *this;
- this->public.report = (void(*)(leak_detective_t*,bool))report;
- this->public.destroy = (void(*)(leak_detective_t*))destroy;
+ INIT(this,
+ .public = {
+ .report = _report,
+ .usage = _usage,
+ .destroy = _destroy,
+ },
+ );
if (getenv("LEAK_DETECTIVE_DISABLE") == NULL)
{
@@ -526,7 +635,6 @@ leak_detective_t *leak_detective_create()
fprintf(stderr, "setting CPU affinity failed: %m");
}
- lib->leak_detective = TRUE;
install_hooks();
}
return &this->public;
diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h
index fa45a6076..8c80d2532 100644
--- a/src/libstrongswan/utils/leak_detective.h
+++ b/src/libstrongswan/utils/leak_detective.h
@@ -43,6 +43,13 @@ struct leak_detective_t {
void (*report)(leak_detective_t *this, bool detailed);
/**
+ * Report current memory usage to out.
+ *
+ * @param out target to write usage report to
+ */
+ void (*usage)(leak_detective_t *this, FILE *out);
+
+ /**
* Destroy a leak_detective instance.
*/
void (*destroy)(leak_detective_t *this);
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c
index 9b37359dc..59d416f2f 100644
--- a/src/libstrongswan/utils/linked_list.c
+++ b/src/libstrongswan/utils/linked_list.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2008 Tobias Brunner
+ * Copyright (C) 2007-2011 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -51,13 +51,11 @@ struct element_t {
*/
element_t *element_create(void *value)
{
- element_t *this = malloc_thing(element_t);
-
- this->previous = NULL;
- this->next = NULL;
- this->value = value;
-
- return (this);
+ element_t *this;
+ INIT(this,
+ .value = value,
+ );
+ return this;
}
@@ -91,34 +89,6 @@ struct private_linked_list_t {
element_t *last;
};
-
-typedef struct private_iterator_t private_iterator_t;
-
-/**
- * Private variables and functions of linked list iterator.
- */
-struct private_iterator_t {
- /**
- * Public part of linked list iterator.
- */
- iterator_t public;
-
- /**
- * Associated linked list.
- */
- private_linked_list_t * list;
-
- /**
- * Current element of the iterator.
- */
- element_t *current;
-
- /**
- * Direction of iterator.
- */
- bool forward;
-};
-
typedef struct private_enumerator_t private_enumerator_t;
/**
@@ -140,241 +110,78 @@ struct private_enumerator_t {
* current item
*/
element_t *current;
+
+ /**
+ * enumerator has enumerated all items
+ */
+ bool finished;
};
-/**
- * Implementation of private_enumerator_t.enumerator.enumerate.
- */
-static bool enumerate(private_enumerator_t *this, void **item)
+METHOD(enumerator_t, enumerate, bool,
+ private_enumerator_t *this, void **item)
{
+ if (this->finished)
+ {
+ return FALSE;
+ }
if (!this->current)
{
- if (!this->list->first)
- {
- return FALSE;
- }
this->current = this->list->first;
}
else
{
- if (!this->current->next)
- {
- return FALSE;
- }
this->current = this->current->next;
}
- *item = this->current->value;
- return TRUE;
-}
-
-/**
- * Implementation of linked_list_t.create_enumerator.
- */
-static enumerator_t* create_enumerator(private_linked_list_t *this)
-{
- private_enumerator_t *enumerator = malloc_thing(private_enumerator_t);
-
- enumerator->enumerator.enumerate = (void*)enumerate;
- enumerator->enumerator.destroy = (void*)free;
- enumerator->list = this;
- enumerator->current = NULL;
-
- return &enumerator->enumerator;
-}
-
-/**
- * Implementation of iterator_t.get_count.
- */
-static int get_list_count(private_iterator_t *this)
-{
- return this->list->count;
-}
-
-/**
- * Implementation of iterator_t.iterate.
- */
-static bool iterate(private_iterator_t *this, void** value)
-{
- if (this->forward)
- {
- this->current = this->current ? this->current->next : this->list->first;
- }
- else
- {
- this->current = this->current ? this->current->previous : this->list->last;
- }
- if (this->current == NULL)
+ if (!this->current)
{
+ this->finished = TRUE;
return FALSE;
}
- *value = this->current->value;
+ *item = this->current->value;
return TRUE;
}
-/**
- * Implementation of iterator_t.reset.
- */
-static void iterator_reset(private_iterator_t *this)
+METHOD(linked_list_t, create_enumerator, enumerator_t*,
+ private_linked_list_t *this)
{
- this->current = NULL;
-}
+ private_enumerator_t *enumerator;
-/**
- * Implementation of iterator_t.remove.
- */
-static status_t iterator_remove(private_iterator_t *this)
-{
- element_t *new_current;
+ INIT(enumerator,
+ .enumerator = {
+ .enumerate = (void*)_enumerate,
+ .destroy = (void*)free,
+ },
+ .list = this,
+ );
- if (this->current == NULL)
- {
- return NOT_FOUND;
- }
-
- if (this->list->count == 0)
- {
- return NOT_FOUND;
- }
- /* find out the new iterator position, depending on iterator direction */
- if (this->forward && this->current->previous != NULL)
- {
- new_current = this->current->previous;
- }
- else if (!this->forward && this->current->next != NULL)
- {
- new_current = this->current->next;
- }
- else
- {
- new_current = NULL;
- }
-
- /* now delete the entry :-) */
- if (this->current->previous == NULL)
- {
- if (this->current->next == NULL)
- {
- this->list->first = NULL;
- this->list->last = NULL;
- }
- else
- {
- this->current->next->previous = NULL;
- this->list->first = this->current->next;
- }
- }
- else if (this->current->next == NULL)
- {
- this->current->previous->next = NULL;
- this->list->last = this->current->previous;
- }
- else
- {
- this->current->previous->next = this->current->next;
- this->current->next->previous = this->current->previous;
- }
-
- this->list->count--;
- free(this->current);
- /* set the new iterator position */
- this->current = new_current;
- return SUCCESS;
-}
-
-/**
- * Implementation of iterator_t.insert_before.
- */
-static void insert_before(private_iterator_t * iterator, void *item)
-{
- if (iterator->current == NULL)
- {
- iterator->list->public.insert_first(&(iterator->list->public), item);
- return;
- }
-
- element_t *element = element_create(item);
- if (iterator->current->previous == NULL)
- {
- iterator->current->previous = element;
- element->next = iterator->current;
- iterator->list->first = element;
- }
- else
- {
- iterator->current->previous->next = element;
- element->previous = iterator->current->previous;
- iterator->current->previous = element;
- element->next = iterator->current;
- }
- iterator->list->count++;
+ return &enumerator->enumerator;
}
-/**
- * Implementation of iterator_t.replace.
- */
-static status_t replace(private_iterator_t *this, void **old_item, void *new_item)
+METHOD(linked_list_t, reset_enumerator, void,
+ private_linked_list_t *this, private_enumerator_t *enumerator)
{
- if (this->current == NULL)
- {
- return NOT_FOUND;
- }
- if (old_item != NULL)
- {
- *old_item = this->current->value;
- }
- this->current->value = new_item;
-
- return SUCCESS;
+ enumerator->current = NULL;
+ enumerator->finished = FALSE;
}
-/**
- * Implementation of iterator_t.insert_after.
- */
-static void insert_after(private_iterator_t *iterator, void *item)
+METHOD(linked_list_t, has_more, bool,
+ private_linked_list_t *this, private_enumerator_t *enumerator)
{
- if (iterator->current == NULL)
- {
- iterator->list->public.insert_first(&(iterator->list->public),item);
- return;
- }
-
- element_t *element = element_create(item);
- if (iterator->current->next == NULL)
- {
- iterator->current->next = element;
- element->previous = iterator->current;
- iterator->list->last = element;
- }
- else
+ if (enumerator->current)
{
- iterator->current->next->previous = element;
- element->next = iterator->current->next;
- iterator->current->next = element;
- element->previous = iterator->current;
+ return enumerator->current->next != NULL;
}
- iterator->list->count++;
+ return !enumerator->finished && this->first != NULL;
}
-/**
- * Implementation of iterator_t.destroy.
- */
-static void iterator_destroy(private_iterator_t *this)
-{
- free(this);
-}
-
-/**
- * Implementation of linked_list_t.get_count.
- */
-static int get_count(private_linked_list_t *this)
+METHOD(linked_list_t, get_count, int,
+ private_linked_list_t *this)
{
return this->count;
}
-/**
- * Implementation of linked_list_t.insert_first.
- */
-static void insert_first(private_linked_list_t *this, void *item)
+METHOD(linked_list_t, insert_first, void,
+ private_linked_list_t *this, void *item)
{
element_t *element;
@@ -384,15 +191,11 @@ static void insert_first(private_linked_list_t *this, void *item)
/* first entry in list */
this->first = element;
this->last = element;
- element->previous = NULL;
- element->next = NULL;
}
else
{
- element_t *old_first_element = this->first;
- element->next = old_first_element;
- element->previous = NULL;
- old_first_element->previous = element;
+ element->next = this->first;
+ this->first->previous = element;
this->first = element;
}
this->count++;
@@ -401,7 +204,8 @@ static void insert_first(private_linked_list_t *this, void *item)
/**
* unlink an element form the list, returns following element
*/
-static element_t* remove_element(private_linked_list_t *this, element_t *element)
+static element_t* remove_element(private_linked_list_t *this,
+ element_t *element)
{
element_t *next, *previous;
@@ -432,10 +236,8 @@ static element_t* remove_element(private_linked_list_t *this, element_t *element
return next;
}
-/**
- * Implementation of linked_list_t.get_first.
- */
-static status_t get_first(private_linked_list_t *this, void **item)
+METHOD(linked_list_t, get_first, status_t,
+ private_linked_list_t *this, void **item)
{
if (this->count == 0)
{
@@ -445,10 +247,8 @@ static status_t get_first(private_linked_list_t *this, void **item)
return SUCCESS;
}
-/**
- * Implementation of linked_list_t.remove_first.
- */
-static status_t remove_first(private_linked_list_t *this, void **item)
+METHOD(linked_list_t, remove_first, status_t,
+ private_linked_list_t *this, void **item)
{
if (get_first(this, item) == SUCCESS)
{
@@ -458,36 +258,79 @@ static status_t remove_first(private_linked_list_t *this, void **item)
return NOT_FOUND;
}
-/**
- * Implementation of linked_list_t.insert_last.
- */
-static void insert_last(private_linked_list_t *this, void *item)
+METHOD(linked_list_t, insert_last, void,
+ private_linked_list_t *this, void *item)
{
- element_t *element = element_create(item);
+ element_t *element;
+ element = element_create(item);
if (this->count == 0)
{
/* first entry in list */
this->first = element;
this->last = element;
- element->previous = NULL;
- element->next = NULL;
}
else
{
- element_t *old_last_element = this->last;
- element->previous = old_last_element;
- element->next = NULL;
- old_last_element->next = element;
+ element->previous = this->last;
+ this->last->next = element;
this->last = element;
}
this->count++;
}
-/**
- * Implementation of linked_list_t.get_last.
- */
-static status_t get_last(private_linked_list_t *this, void **item)
+METHOD(linked_list_t, insert_before, void,
+ private_linked_list_t *this, private_enumerator_t *enumerator,
+ void *item)
+{
+ element_t *current, *element;
+
+ current = enumerator->current;
+ if (!current)
+ {
+ if (enumerator->finished)
+ {
+ this->public.insert_last(&this->public, item);
+ }
+ else
+ {
+ this->public.insert_first(&this->public, item);
+ }
+ return;
+ }
+ element = element_create(item);
+ if (current->previous)
+ {
+ current->previous->next = element;
+ element->previous = current->previous;
+ current->previous = element;
+ element->next = current;
+ }
+ else
+ {
+ current->previous = element;
+ element->next = current;
+ this->first = element;
+ }
+ this->count++;
+}
+
+METHOD(linked_list_t, replace, void*,
+ private_linked_list_t *this, private_enumerator_t *enumerator,
+ void *item)
+{
+ void *old = NULL;
+
+ if (enumerator->current)
+ {
+ old = enumerator->current->value;
+ enumerator->current->value = item;
+ }
+ return old;
+}
+
+METHOD(linked_list_t, get_last, status_t,
+ private_linked_list_t *this, void **item)
{
if (this->count == 0)
{
@@ -497,10 +340,8 @@ static status_t get_last(private_linked_list_t *this, void **item)
return SUCCESS;
}
-/**
- * Implementation of linked_list_t.remove_last.
- */
-static status_t remove_last(private_linked_list_t *this, void **item)
+METHOD(linked_list_t, remove_last, status_t,
+ private_linked_list_t *this, void **item)
{
if (get_last(this, item) == SUCCESS)
{
@@ -510,11 +351,8 @@ static status_t remove_last(private_linked_list_t *this, void **item)
return NOT_FOUND;
}
-/**
- * Implementation of linked_list_t.remove.
- */
-static int remove_(private_linked_list_t *this, void *item,
- bool (*compare)(void *,void*))
+METHOD(linked_list_t, remove_, int,
+ private_linked_list_t *this, void *item, bool (*compare)(void*,void*))
{
element_t *current = this->first;
int removed = 0;
@@ -535,10 +373,8 @@ static int remove_(private_linked_list_t *this, void *item,
return removed;
}
-/**
- * Implementation of linked_list_t.remove_at.
- */
-static void remove_at(private_linked_list_t *this, private_enumerator_t *enumerator)
+METHOD(linked_list_t, remove_at, void,
+ private_linked_list_t *this, private_enumerator_t *enumerator)
{
element_t *current;
@@ -550,11 +386,9 @@ static void remove_at(private_linked_list_t *this, private_enumerator_t *enumera
}
}
-/**
- * Implementation of linked_list_t.find_first.
- */
-static status_t find_first(private_linked_list_t *this, linked_list_match_t match,
- void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
+METHOD(linked_list_t, find_first, status_t,
+ private_linked_list_t *this, linked_list_match_t match,
+ void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->first;
@@ -574,11 +408,9 @@ static status_t find_first(private_linked_list_t *this, linked_list_match_t matc
return NOT_FOUND;
}
-/**
- * Implementation of linked_list_t.find_last.
- */
-static status_t find_last(private_linked_list_t *this, linked_list_match_t match,
- void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
+METHOD(linked_list_t, find_last, status_t,
+ private_linked_list_t *this, linked_list_match_t match,
+ void **item, void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->last;
@@ -598,27 +430,24 @@ static status_t find_last(private_linked_list_t *this, linked_list_match_t match
return NOT_FOUND;
}
-/**
- * Implementation of linked_list_t.invoke_offset.
- */
-static void invoke_offset(private_linked_list_t *this, size_t offset,
- void *d1, void *d2, void *d3, void *d4, void *d5)
+METHOD(linked_list_t, invoke_offset, void,
+ private_linked_list_t *this, size_t offset,
+ void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->first;
+ linked_list_invoke_t *method;
while (current)
{
- linked_list_invoke_t *method = current->value + offset;
+ method = current->value + offset;
(*method)(current->value, d1, d2, d3, d4, d5);
current = current->next;
}
}
-/**
- * Implementation of linked_list_t.invoke_function.
- */
-static void invoke_function(private_linked_list_t *this, linked_list_invoke_t fn,
- void *d1, void *d2, void *d3, void *d4, void *d5)
+METHOD(linked_list_t, invoke_function, void,
+ private_linked_list_t *this, linked_list_invoke_t fn,
+ void *d1, void *d2, void *d3, void *d4, void *d5)
{
element_t *current = this->first;
@@ -629,14 +458,13 @@ static void invoke_function(private_linked_list_t *this, linked_list_invoke_t fn
}
}
-/**
- * Implementation of linked_list_t.clone_offset
- */
-static linked_list_t *clone_offset(private_linked_list_t *this, size_t offset)
+METHOD(linked_list_t, clone_offset, linked_list_t*,
+ private_linked_list_t *this, size_t offset)
{
- linked_list_t *clone = linked_list_create();
element_t *current = this->first;
+ linked_list_t *clone;
+ clone = linked_list_create();
while (current)
{
void* (**method)(void*) = current->value + offset;
@@ -647,29 +475,26 @@ static linked_list_t *clone_offset(private_linked_list_t *this, size_t offset)
return clone;
}
-/**
- * Implementation of linked_list_t.clone_function
- */
-static linked_list_t *clone_function(private_linked_list_t *this, void* (*fn)(void*))
+METHOD(linked_list_t, clone_function, linked_list_t*,
+ private_linked_list_t *this, void* (*fn)(void*))
{
- linked_list_t *clone = linked_list_create();
element_t *current = this->first;
+ linked_list_t *clone;
+ clone = linked_list_create();
while (current)
{
clone->insert_last(clone, fn(current->value));
current = current->next;
}
-
return clone;
}
-/**
- * Implementation of linked_list_t.destroy.
- */
-static void destroy(private_linked_list_t *this)
+METHOD(linked_list_t, destroy, void,
+ private_linked_list_t *this)
{
void *value;
+
/* Remove all list items before destroying list */
while (remove_first(this, &value) == SUCCESS)
{
@@ -679,10 +504,8 @@ static void destroy(private_linked_list_t *this)
free(this);
}
-/**
- * Implementation of linked_list_t.destroy_offset.
- */
-static void destroy_offset(private_linked_list_t *this, size_t offset)
+METHOD(linked_list_t, destroy_offset, void,
+ private_linked_list_t *this, size_t offset)
{
element_t *current = this->first, *next;
@@ -697,10 +520,8 @@ static void destroy_offset(private_linked_list_t *this, size_t offset)
free(this);
}
-/**
- * Implementation of linked_list_t.destroy_function.
- */
-static void destroy_function(private_linked_list_t *this, void (*fn)(void*))
+METHOD(linked_list_t, destroy_function, void,
+ private_linked_list_t *this, void (*fn)(void*))
{
element_t *current = this->first, *next;
@@ -714,60 +535,40 @@ static void destroy_function(private_linked_list_t *this, void (*fn)(void*))
free(this);
}
-/**
- * Implementation of linked_list_t.create_iterator.
- */
-static iterator_t *create_iterator(private_linked_list_t *linked_list, bool forward)
-{
- private_iterator_t *this = malloc_thing(private_iterator_t);
-
- this->public.get_count = (int (*) (iterator_t*)) get_list_count;
- this->public.iterate = (bool (*) (iterator_t*, void **value)) iterate;
- this->public.insert_before = (void (*) (iterator_t*, void *item)) insert_before;
- this->public.insert_after = (void (*) (iterator_t*, void *item)) insert_after;
- this->public.replace = (status_t (*) (iterator_t*, void **, void *)) replace;
- this->public.remove = (status_t (*) (iterator_t*)) iterator_remove;
- this->public.reset = (void (*) (iterator_t*)) iterator_reset;
- this->public.destroy = (void (*) (iterator_t*)) iterator_destroy;
-
- this->forward = forward;
- this->current = NULL;
- this->list = linked_list;
-
- return &this->public;
-}
-
/*
* Described in header.
*/
linked_list_t *linked_list_create()
{
- private_linked_list_t *this = malloc_thing(private_linked_list_t);
-
- this->public.get_count = (int (*) (linked_list_t *)) get_count;
- this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool))create_iterator;
- this->public.create_enumerator = (enumerator_t*(*)(linked_list_t*))create_enumerator;
- this->public.get_first = (status_t (*) (linked_list_t *, void **item))get_first;
- this->public.get_last = (status_t (*) (linked_list_t *, void **item))get_last;
- this->public.find_first = (status_t (*) (linked_list_t *, linked_list_match_t,void**,...))find_first;
- this->public.find_last = (status_t (*) (linked_list_t *, linked_list_match_t,void**,...))find_last;
- this->public.insert_first = (void (*) (linked_list_t *, void *item))insert_first;
- this->public.insert_last = (void (*) (linked_list_t *, void *item))insert_last;
- this->public.remove_first = (status_t (*) (linked_list_t *, void **item))remove_first;
- this->public.remove_last = (status_t (*) (linked_list_t *, void **item))remove_last;
- this->public.remove = (int(*)(linked_list_t*, void *item, bool (*compare)(void *,void*)))remove_;
- this->public.remove_at = (void(*)(linked_list_t*, enumerator_t *enumerator))remove_at;
- this->public.invoke_offset = (void (*)(linked_list_t*,size_t,...))invoke_offset;
- this->public.invoke_function = (void (*)(linked_list_t*,linked_list_invoke_t,...))invoke_function;
- this->public.clone_offset = (linked_list_t * (*)(linked_list_t*,size_t))clone_offset;
- this->public.clone_function = (linked_list_t * (*)(linked_list_t*,void*(*)(void*)))clone_function;
- this->public.destroy = (void (*) (linked_list_t *))destroy;
- this->public.destroy_offset = (void (*) (linked_list_t *,size_t))destroy_offset;
- this->public.destroy_function = (void (*)(linked_list_t*,void(*)(void*)))destroy_function;
-
- this->count = 0;
- this->first = NULL;
- this->last = NULL;
+ private_linked_list_t *this;
+
+ INIT(this,
+ .public = {
+ .get_count = _get_count,
+ .create_enumerator = _create_enumerator,
+ .reset_enumerator = (void*)_reset_enumerator,
+ .has_more = (void*)_has_more,
+ .get_first = _get_first,
+ .get_last = _get_last,
+ .find_first = (void*)_find_first,
+ .find_last = (void*)_find_last,
+ .insert_first = _insert_first,
+ .insert_last = _insert_last,
+ .insert_before = (void*)_insert_before,
+ .replace = (void*)_replace,
+ .remove_first = _remove_first,
+ .remove_last = _remove_last,
+ .remove = _remove_,
+ .remove_at = (void*)_remove_at,
+ .invoke_offset = (void*)_invoke_offset,
+ .invoke_function = (void*)_invoke_function,
+ .clone_offset = _clone_offset,
+ .clone_function = _clone_function,
+ .destroy = _destroy,
+ .destroy_offset = _destroy_offset,
+ .destroy_function = _destroy_function,
+ },
+ );
return &this->public;
}
diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h
index 1444c93fc..293ca8661 100644
--- a/src/libstrongswan/utils/linked_list.h
+++ b/src/libstrongswan/utils/linked_list.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2008 Tobias Brunner
+ * Copyright (C) 2007-2011 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -25,7 +25,6 @@
typedef struct linked_list_t linked_list_t;
-#include <utils/iterator.h>
#include <utils/enumerator.h>
/**
@@ -62,27 +61,29 @@ struct linked_list_t {
int (*get_count) (linked_list_t *this);
/**
- * Creates a iterator for the given list.
- *
- * @warning Created iterator_t object has to get destroyed by the caller.
+ * Create an enumerator over the list.
*
- * @deprecated Iterator is obsolete and will disappear, it is too
- * complicated to implement. Use enumerator instead.
+ * @note The enumerator's position is invalid before the first call
+ * to enumerate().
*
- * @param forward iterator direction (TRUE: front to end)
- * @return new iterator_t object
+ * @return enumerator over list items
*/
- iterator_t *(*create_iterator) (linked_list_t *this, bool forward);
+ enumerator_t* (*create_enumerator)(linked_list_t *this);
/**
- * Create an enumerator over the list.
+ * Resets the enumerator's current position to the beginning of the list.
*
- * The enumerator is a "lightweight" iterator. It only has two methods
- * and should therefore be much easier to implement.
+ * @param enumerator enumerator to reset
+ */
+ void (*reset_enumerator)(linked_list_t *this, enumerator_t *enumerator);
+
+ /**
+ * Checks if there are more elements following after the enumerator's
+ * current position.
*
- * @return enumerator over list items
+ * @param enumerator enumerator to check
*/
- enumerator_t* (*create_enumerator)(linked_list_t *this);
+ bool (*has_more)(linked_list_t *this, enumerator_t *enumerator);
/**
* Inserts a new item at the beginning of the list.
@@ -100,6 +101,32 @@ struct linked_list_t {
status_t (*remove_first) (linked_list_t *this, void **item);
/**
+ * Inserts a new item before the item the enumerator currently points to.
+ *
+ * If this method is called before starting the enumeration the item is
+ * inserted first. If it is called after all items have been enumerated
+ * the item is inserted last. This is helpful when inserting items into
+ * a sorted list.
+ *
+ * @note The position of the enumerator is not changed.
+ *
+ * @param enumerator enumerator with position
+ * @param item item value to insert in list
+ */
+ void (*insert_before)(linked_list_t *this, enumerator_t *enumerator,
+ void *item);
+
+ /**
+ * Replaces the item the enumerator currently points to with the given item.
+ *
+ * @param enumerator enumerator with position
+ * @param item item value to replace current item with
+ * @return current item or NULL if the enumerator is at an
+ * invalid position
+ */
+ void *(*replace)(linked_list_t *this, enumerator_t *enumerator, void *item);
+
+ /**
* Remove an item from the list where the enumerator points to.
*
* @param enumerator enumerator with position
@@ -125,7 +152,6 @@ struct linked_list_t {
/**
* Returns the value of the first list item without removing it.
*
- * @param this calling object
* @param item returned value of first item
* @return SUCCESS, NOT_FOUND if list is empty
*/
@@ -141,7 +167,6 @@ struct linked_list_t {
/**
* Removes the last item in the list and returns its value.
*
- * @param this calling object
* @param item returned value of last item, or NULL
* @return SUCCESS, NOT_FOUND if list is empty
*/
@@ -150,7 +175,6 @@ struct linked_list_t {
/**
* Returns the value of the last list item without removing it.
*
- * @param this calling object
* @param item returned value of last item
* @return SUCCESS, NOT_FOUND if list is empty
*/
diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c
index e51780290..5fd4cfd4d 100644
--- a/src/libstrongswan/utils/optionsfrom.c
+++ b/src/libstrongswan/utils/optionsfrom.c
@@ -67,7 +67,6 @@ METHOD(options_t, from, bool,
int newargc;
int next; /* place for next argument */
char **newargv;
- size_t bytes;
chunk_t src, line, token;
bool good = TRUE;
int linepos = 0;
@@ -99,7 +98,14 @@ METHOD(options_t, from, bool,
src.ptr = this->buffers[this->nuses] = malloc(src.len + 1);
/* read the whole file into a chunk */
- bytes = fread(src.ptr, 1, src.len, fd);
+ if (fread(src.ptr, 1, src.len, fd) != src.len)
+ {
+ DBG1(DBG_LIB, "optionsfrom: unable to read file '%s': %s",
+ filename, strerror(errno));
+ free(src.ptr);
+ fclose(fd);
+ return FALSE;
+ }
fclose(fd);
if (this->room)