summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r--src/libstrongswan/utils/backtrace.c2
-rw-r--r--src/libstrongswan/utils/blocking_queue.c129
-rw-r--r--src/libstrongswan/utils/blocking_queue.h97
-rw-r--r--src/libstrongswan/utils/capabilities.c2
-rw-r--r--src/libstrongswan/utils/chunk.c690
-rw-r--r--src/libstrongswan/utils/chunk.h318
-rw-r--r--src/libstrongswan/utils/debug.c112
-rw-r--r--src/libstrongswan/utils/debug.h154
-rw-r--r--src/libstrongswan/utils/enum.c81
-rw-r--r--src/libstrongswan/utils/enum.h136
-rw-r--r--src/libstrongswan/utils/enumerator.c560
-rw-r--r--src/libstrongswan/utils/enumerator.h159
-rw-r--r--src/libstrongswan/utils/hashtable.c444
-rw-r--r--src/libstrongswan/utils/hashtable.h138
-rw-r--r--src/libstrongswan/utils/host.c616
-rw-r--r--src/libstrongswan/utils/host.h220
-rw-r--r--src/libstrongswan/utils/identification.h4
-rw-r--r--src/libstrongswan/utils/integrity_checker.c321
-rw-r--r--src/libstrongswan/utils/integrity_checker.h110
-rw-r--r--src/libstrongswan/utils/leak_detective.c4
-rw-r--r--src/libstrongswan/utils/linked_list.c615
-rw-r--r--src/libstrongswan/utils/linked_list.h319
-rw-r--r--src/libstrongswan/utils/optionsfrom.c16
-rw-r--r--src/libstrongswan/utils/packet.c163
-rw-r--r--src/libstrongswan/utils/packet.h121
-rw-r--r--src/libstrongswan/utils/printf_hook.c511
-rw-r--r--src/libstrongswan/utils/printf_hook.h247
-rw-r--r--src/libstrongswan/utils/settings.c1227
-rw-r--r--src/libstrongswan/utils/settings.h313
-rw-r--r--src/libstrongswan/utils/tun_device.c461
-rw-r--r--src/libstrongswan/utils/tun_device.h112
-rw-r--r--src/libstrongswan/utils/utils.c570
-rw-r--r--src/libstrongswan/utils/utils.h699
33 files changed, 5503 insertions, 4168 deletions
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index b6015fb35..0b6683233 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -54,7 +54,7 @@ struct private_backtrace_t {
#ifdef HAVE_BFD_H
#include <bfd.h>
-#include <utils/hashtable.h>
+#include <collections/hashtable.h>
#include <threading/mutex.h>
/**
diff --git a/src/libstrongswan/utils/blocking_queue.c b/src/libstrongswan/utils/blocking_queue.c
deleted file mode 100644
index c70184198..000000000
--- a/src/libstrongswan/utils/blocking_queue.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * Copyright (C) 2012 Giuliano Grassi
- * Copyright (C) 2012 Ralf Sager
- * 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.
- */
-
-#include "blocking_queue.h"
-
-#include <threading/mutex.h>
-#include <threading/thread.h>
-#include <threading/condvar.h>
-#include <utils/linked_list.h>
-
-typedef struct private_blocking_queue_t private_blocking_queue_t;
-
-/**
- * Private data of a blocking_queue_t object.
- */
-struct private_blocking_queue_t {
-
- /**
- * Public part
- */
- blocking_queue_t public;
-
- /**
- * Linked list containing all items in the queue
- */
- linked_list_t *list;
-
- /**
- * Mutex used to synchronize access to the queue
- */
- mutex_t *mutex;
-
- /**
- * Condvar used to wait for items
- */
- condvar_t *condvar;
-
-};
-
-METHOD(blocking_queue_t, enqueue, void,
- private_blocking_queue_t *this, void *item)
-{
- this->mutex->lock(this->mutex);
- this->list->insert_first(this->list, item);
- this->condvar->signal(this->condvar);
- this->mutex->unlock(this->mutex);
-}
-
-METHOD(blocking_queue_t, dequeue, void*,
- private_blocking_queue_t *this)
-{
- bool oldstate;
- void *item;
-
-
- this->mutex->lock(this->mutex);
- thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
- /* ensure that a canceled thread does not dequeue any items */
- thread_cancellation_point();
- while (this->list->remove_last(this->list, &item) != SUCCESS)
- {
- oldstate = thread_cancelability(TRUE);
- this->condvar->wait(this->condvar, this->mutex);
- thread_cancelability(oldstate);
- }
- thread_cleanup_pop(TRUE);
- return item;
-}
-
-METHOD(blocking_queue_t, destroy, void,
- private_blocking_queue_t *this)
-{
- this->list->destroy(this->list);
- this->condvar->destroy(this->condvar);
- this->mutex->destroy(this->mutex);
- free(this);
-}
-
-METHOD(blocking_queue_t, destroy_offset, void,
- private_blocking_queue_t *this, size_t offset)
-{
- this->list->invoke_offset(this->list, offset);
- destroy(this);
-}
-
-METHOD(blocking_queue_t, destroy_function, void,
- private_blocking_queue_t *this, void (*fn)(void*))
-{
- this->list->invoke_function(this->list, (linked_list_invoke_t)fn);
- destroy(this);
-}
-
-/*
- * Described in header.
- */
-blocking_queue_t *blocking_queue_create()
-{
- private_blocking_queue_t *this;
-
- INIT(this,
- .public = {
- .enqueue = _enqueue,
- .dequeue = _dequeue,
- .destroy = _destroy,
- .destroy_offset = _destroy_offset,
- .destroy_function = _destroy_function,
- },
- .list = linked_list_create(),
- .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
- .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
- );
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/utils/blocking_queue.h b/src/libstrongswan/utils/blocking_queue.h
deleted file mode 100644
index cf2712cf4..000000000
--- a/src/libstrongswan/utils/blocking_queue.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * Copyright (C) 2012 Giuliano Grassi
- * Copyright (C) 2012 Ralf Sager
- * 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 blocking_queue blocking_queue
- * @{ @ingroup utils
- */
-
-#ifndef BLOCKING_QUEUE_H_
-#define BLOCKING_QUEUE_H_
-
-typedef struct blocking_queue_t blocking_queue_t;
-
-#include <library.h>
-
-/**
- * Class implementing a synchronized blocking queue based on linked_list_t
- */
-struct blocking_queue_t {
-
- /**
- * Inserts a new item at the tail of the queue
- *
- * @param item item to insert in queue
- */
- void (*enqueue)(blocking_queue_t *this, void *item);
-
- /**
- * Removes the first item in the queue and returns its value.
- * If the queue is empty, this call blocks until a new item is inserted.
- *
- * @note This is a thread cancellation point
- *
- * @return removed item
- */
- void *(*dequeue)(blocking_queue_t *this);
-
- /**
- * Destroys a blocking_queue_t object.
- *
- * @note No thread must wait in dequeue() when this function is called
- */
- void (*destroy)(blocking_queue_t *this);
-
- /**
- * Destroys a queue and its objects using the given destructor.
- *
- * If a queue and the contained objects should be destroyed, use
- * destroy_offset. The supplied offset specifies the destructor to
- * call on each object. The offset may be calculated using the offsetof
- * macro, e.g.: queue->destroy_offset(queue, offsetof(object_t, destroy));
- *
- * @note No thread must wait in dequeue() when this function is called
- *
- * @param offset offset of the objects destructor
- */
- void (*destroy_offset)(blocking_queue_t *this, size_t offset);
-
- /**
- * Destroys a queue and its objects using a cleanup function.
- *
- * If a queue and its contents should get destroyed using a specific
- * cleanup function, use destroy_function. This is useful when the
- * list contains malloc()-ed blocks which should get freed,
- * e.g.: queue->destroy_function(queue, free);
- *
- * @note No thread must wait in dequeue() when this function is called
- *
- * @param function function to call on each object
- */
- void (*destroy_function)(blocking_queue_t *this, void (*)(void*));
-
-};
-
-/**
- * Creates an empty queue object.
- *
- * @return blocking_queue_t object.
- */
-blocking_queue_t *blocking_queue_create();
-
-#endif /** BLOCKING_QUEUE_H_ @}*/
-
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c
index 34128d010..c36a76efe 100644
--- a/src/libstrongswan/utils/capabilities.c
+++ b/src/libstrongswan/utils/capabilities.c
@@ -27,7 +27,7 @@
# include <sys/prctl.h>
#endif /* HAVE_PRCTL */
-#include <debug.h>
+#include <utils/debug.h>
#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETGRNAM_R)
# include <threading/mutex.h>
diff --git a/src/libstrongswan/utils/chunk.c b/src/libstrongswan/utils/chunk.c
new file mode 100644
index 000000000..d7f1c31d9
--- /dev/null
+++ b/src/libstrongswan/utils/chunk.c
@@ -0,0 +1,690 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * 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.
+ */
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "chunk.h"
+#include "debug.h"
+
+/* required for chunk_hash */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__))
+#define get16bits(d) (*((const u_int16_t*)(d)))
+#endif
+#if !defined (get16bits)
+#define get16bits(d) ((((u_int32_t)(((const u_int8_t*)(d))[1])) << 8)\
+ + (u_int32_t)(((const u_int8_t*)(d))[0]) )
+#endif
+
+/**
+ * Empty chunk.
+ */
+chunk_t chunk_empty = { NULL, 0 };
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
+{
+ chunk_t clone = chunk_empty;
+
+ if (chunk.ptr && chunk.len > 0)
+ {
+ clone.ptr = ptr;
+ clone.len = chunk.len;
+ memcpy(clone.ptr, chunk.ptr, chunk.len);
+ }
+
+ return clone;
+}
+
+/**
+ * Described in header.
+ */
+size_t chunk_length(const char* mode, ...)
+{
+ va_list chunks;
+ size_t length = 0;
+
+ va_start(chunks, mode);
+ while (TRUE)
+ {
+ switch (*mode++)
+ {
+ case 'm':
+ case 'c':
+ case 's':
+ {
+ chunk_t ch = va_arg(chunks, chunk_t);
+ length += ch.len;
+ continue;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ va_end(chunks);
+ return length;
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
+{
+ va_list chunks;
+ chunk_t construct = chunk_create(ptr, 0);
+
+ va_start(chunks, mode);
+ while (TRUE)
+ {
+ bool free_chunk = FALSE, clear_chunk = FALSE;
+ chunk_t ch;
+
+ switch (*mode++)
+ {
+ case 's':
+ clear_chunk = TRUE;
+ /* FALL */
+ case 'm':
+ free_chunk = TRUE;
+ /* FALL */
+ case 'c':
+ ch = va_arg(chunks, chunk_t);
+ memcpy(ptr, ch.ptr, ch.len);
+ ptr += ch.len;
+ construct.len += ch.len;
+ if (clear_chunk)
+ {
+ chunk_clear(&ch);
+ }
+ else if (free_chunk)
+ {
+ free(ch.ptr);
+ }
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+ va_end(chunks);
+
+ return construct;
+}
+
+/**
+ * Described in header.
+ */
+void chunk_split(chunk_t chunk, const char *mode, ...)
+{
+ va_list chunks;
+ u_int len;
+ chunk_t *ch;
+
+ va_start(chunks, mode);
+ while (TRUE)
+ {
+ if (*mode == '\0')
+ {
+ break;
+ }
+ len = va_arg(chunks, u_int);
+ ch = va_arg(chunks, chunk_t*);
+ /* a null chunk means skip len bytes */
+ if (ch == NULL)
+ {
+ chunk = chunk_skip(chunk, len);
+ continue;
+ }
+ switch (*mode++)
+ {
+ case 'm':
+ {
+ ch->len = min(chunk.len, len);
+ if (ch->len)
+ {
+ ch->ptr = chunk.ptr;
+ }
+ else
+ {
+ ch->ptr = NULL;
+ }
+ chunk = chunk_skip(chunk, ch->len);
+ continue;
+ }
+ case 'a':
+ {
+ ch->len = min(chunk.len, len);
+ if (ch->len)
+ {
+ ch->ptr = malloc(ch->len);
+ memcpy(ch->ptr, chunk.ptr, ch->len);
+ }
+ else
+ {
+ ch->ptr = NULL;
+ }
+ chunk = chunk_skip(chunk, ch->len);
+ continue;
+ }
+ case 'c':
+ {
+ ch->len = min(ch->len, chunk.len);
+ ch->len = min(ch->len, len);
+ if (ch->len)
+ {
+ memcpy(ch->ptr, chunk.ptr, ch->len);
+ }
+ else
+ {
+ ch->ptr = NULL;
+ }
+ chunk = chunk_skip(chunk, ch->len);
+ continue;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ va_end(chunks);
+}
+
+/**
+ * Described in header.
+ */
+bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force)
+{
+ mode_t oldmask;
+ FILE *fd;
+ bool good = FALSE;
+
+ if (!force && access(path, F_OK) == 0)
+ {
+ DBG1(DBG_LIB, " %s file '%s' already exists", label, path);
+ return FALSE;
+ }
+ oldmask = umask(mask);
+ fd = fopen(path, "w");
+ if (fd)
+ {
+ if (fwrite(chunk.ptr, sizeof(u_char), chunk.len, fd) == chunk.len)
+ {
+ DBG1(DBG_LIB, " written %s file '%s' (%d bytes)",
+ label, path, chunk.len);
+ good = TRUE;
+ }
+ else
+ {
+ DBG1(DBG_LIB, " writing %s file '%s' failed: %s",
+ label, path, strerror(errno));
+ }
+ fclose(fd);
+ }
+ else
+ {
+ DBG1(DBG_LIB, " could not open %s file '%s': %s", label, path,
+ strerror(errno));
+ }
+ umask(oldmask);
+ return good;
+}
+
+
+/** hex conversion digits */
+static char hexdig_upper[] = "0123456789ABCDEF";
+static char hexdig_lower[] = "0123456789abcdef";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase)
+{
+ int i, len;
+ char *hexdig = hexdig_lower;
+
+ if (uppercase)
+ {
+ hexdig = hexdig_upper;
+ }
+
+ len = chunk.len * 2;
+ if (!buf)
+ {
+ buf = malloc(len + 1);
+ }
+ buf[len] = '\0';
+
+ for (i = 0; i < chunk.len; i++)
+ {
+ buf[i*2] = hexdig[(chunk.ptr[i] >> 4) & 0xF];
+ buf[i*2+1] = hexdig[(chunk.ptr[i] ) & 0xF];
+ }
+ return chunk_create(buf, len);
+}
+
+/**
+ * convert a signle hex character to its binary value
+ */
+static char hex2bin(char hex)
+{
+ switch (hex)
+ {
+ case '0' ... '9':
+ return hex - '0';
+ case 'A' ... 'F':
+ return hex - 'A' + 10;
+ case 'a' ... 'f':
+ return hex - 'a' + 10;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_from_hex(chunk_t hex, char *buf)
+{
+ int i, len;
+ u_char *ptr;
+ bool odd = FALSE;
+
+ /* subtract the number of optional ':' separation characters */
+ len = hex.len;
+ ptr = hex.ptr;
+ for (i = 0; i < hex.len; i++)
+ {
+ if (*ptr++ == ':')
+ {
+ len--;
+ }
+ }
+
+ /* compute the number of binary bytes */
+ if (len % 2)
+ {
+ odd = TRUE;
+ len++;
+ }
+ len /= 2;
+
+ /* allocate buffer memory unless provided by caller */
+ if (!buf)
+ {
+ buf = malloc(len);
+ }
+
+ /* buffer is filled from the right */
+ memset(buf, 0, len);
+ hex.ptr += hex.len;
+
+ for (i = len - 1; i >= 0; i--)
+ {
+ /* skip separation characters */
+ if (*(--hex.ptr) == ':')
+ {
+ --hex.ptr;
+ }
+ buf[i] = hex2bin(*hex.ptr);
+ if (i > 0 || !odd)
+ {
+ buf[i] |= hex2bin(*(--hex.ptr)) << 4;
+ }
+ }
+ return chunk_create(buf, len);
+}
+
+/** base 64 conversion digits */
+static char b64digits[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_base64(chunk_t chunk, char *buf)
+{
+ int i, len;
+ char *pos;
+
+ len = chunk.len + ((3 - chunk.len % 3) % 3);
+ if (!buf)
+ {
+ buf = malloc(len * 4 / 3 + 1);
+ }
+ pos = buf;
+ for (i = 0; i < len; i+=3)
+ {
+ *pos++ = b64digits[chunk.ptr[i] >> 2];
+ if (i+1 >= chunk.len)
+ {
+ *pos++ = b64digits[(chunk.ptr[i] & 0x03) << 4];
+ *pos++ = '=';
+ *pos++ = '=';
+ break;
+ }
+ *pos++ = b64digits[((chunk.ptr[i] & 0x03) << 4) | (chunk.ptr[i+1] >> 4)];
+ if (i+2 >= chunk.len)
+ {
+ *pos++ = b64digits[(chunk.ptr[i+1] & 0x0F) << 2];
+ *pos++ = '=';
+ break;
+ }
+ *pos++ = b64digits[((chunk.ptr[i+1] & 0x0F) << 2) | (chunk.ptr[i+2] >> 6)];
+ *pos++ = b64digits[chunk.ptr[i+2] & 0x3F];
+ }
+ *pos = '\0';
+ return chunk_create(buf, len * 4 / 3);
+}
+
+/**
+ * convert a base 64 digit to its binary form (inversion of b64digits array)
+ */
+static int b642bin(char b64)
+{
+ switch (b64)
+ {
+ case 'A' ... 'Z':
+ return b64 - 'A';
+ case 'a' ... 'z':
+ return ('Z' - 'A' + 1) + b64 - 'a';
+ case '0' ... '9':
+ return ('Z' - 'A' + 1) + ('z' - 'a' + 1) + b64 - '0';
+ case '+':
+ case '-':
+ return 62;
+ case '/':
+ case '_':
+ return 63;
+ case '=':
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_from_base64(chunk_t base64, char *buf)
+{
+ u_char *pos, byte[4];
+ int i, j, len, outlen;
+
+ len = base64.len / 4 * 3;
+ if (!buf)
+ {
+ buf = malloc(len);
+ }
+ pos = base64.ptr;
+ outlen = 0;
+ for (i = 0; i < len; i+=3)
+ {
+ outlen += 3;
+ for (j = 0; j < 4; j++)
+ {
+ if (*pos == '=')
+ {
+ outlen--;
+ }
+ byte[j] = b642bin(*pos++);
+ }
+ buf[i] = (byte[0] << 2) | (byte[1] >> 4);
+ buf[i+1] = (byte[1] << 4) | (byte[2] >> 2);
+ buf[i+2] = (byte[2] << 6) | (byte[3]);
+ }
+ return chunk_create(buf, outlen);
+}
+
+/** base 32 conversion digits */
+static char b32digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_base32(chunk_t chunk, char *buf)
+{
+ int i, len;
+ char *pos;
+
+ len = chunk.len + ((5 - chunk.len % 5) % 5);
+ if (!buf)
+ {
+ buf = malloc(len * 8 / 5 + 1);
+ }
+ pos = buf;
+ for (i = 0; i < len; i+=5)
+ {
+ *pos++ = b32digits[chunk.ptr[i] >> 3];
+ if (i+1 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i] & 0x07) << 2];
+ memset(pos, '=', 6);
+ pos += 6;
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i] & 0x07) << 2) |
+ (chunk.ptr[i+1] >> 6)];
+ *pos++ = b32digits[(chunk.ptr[i+1] & 0x3E) >> 1];
+ if (i+2 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i+1] & 0x01) << 4];
+ memset(pos, '=', 4);
+ pos += 4;
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i+1] & 0x01) << 4) |
+ (chunk.ptr[i+2] >> 4)];
+ if (i+3 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i+2] & 0x0F) << 1];
+ memset(pos, '=', 3);
+ pos += 3;
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i+2] & 0x0F) << 1) |
+ (chunk.ptr[i+3] >> 7)];
+ *pos++ = b32digits[(chunk.ptr[i+3] & 0x7F) >> 2];
+ if (i+4 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i+3] & 0x03) << 3];
+ *pos++ = '=';
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i+3] & 0x03) << 3) |
+ (chunk.ptr[i+4] >> 5)];
+ *pos++ = b32digits[chunk.ptr[i+4] & 0x1F];
+ }
+ *pos = '\0';
+ return chunk_create(buf, len * 8 / 5);
+}
+
+/**
+ * Described in header.
+ */
+int chunk_compare(chunk_t a, chunk_t b)
+{
+ int compare_len = a.len - b.len;
+ int len = (compare_len < 0)? a.len : b.len;
+
+ if (compare_len != 0 || len == 0)
+ {
+ return compare_len;
+ }
+ return memcmp(a.ptr, b.ptr, len);
+};
+
+
+/**
+ * Described in header.
+ */
+bool chunk_increment(chunk_t chunk)
+{
+ int i;
+
+ for (i = chunk.len - 1; i >= 0; i--)
+ {
+ if (++chunk.ptr[i] != 0)
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Remove non-printable characters from a chunk.
+ */
+bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace)
+{
+ bool printable = TRUE;
+ int i;
+
+ if (sane)
+ {
+ *sane = chunk_clone(chunk);
+ }
+ for (i = 0; i < chunk.len; i++)
+ {
+ if (!isprint(chunk.ptr[i]))
+ {
+ if (sane)
+ {
+ sane->ptr[i] = replace;
+ }
+ printable = FALSE;
+ }
+ }
+ return printable;
+}
+
+/**
+ * Described in header.
+ *
+ * The implementation is based on Paul Hsieh's SuperFastHash:
+ * http://www.azillionmonkeys.com/qed/hash.html
+ */
+u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
+{
+ u_char *data = chunk.ptr;
+ size_t len = chunk.len;
+ u_int32_t tmp;
+ int rem;
+
+ if (!len || data == NULL)
+ {
+ return 0;
+ }
+
+ rem = len & 3;
+ len >>= 2;
+
+ /* Main loop */
+ for (; len > 0; --len)
+ {
+ hash += get16bits(data);
+ tmp = (get16bits(data + 2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2 * sizeof(u_int16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem)
+ {
+ case 3:
+ {
+ hash += get16bits(data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof(u_int16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ }
+ case 2:
+ {
+ hash += get16bits(data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ }
+ case 1:
+ {
+ hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ break;
+ }
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
+
+/**
+ * Described in header.
+ */
+u_int32_t chunk_hash(chunk_t chunk)
+{
+ return chunk_hash_inc(chunk, chunk.len);
+}
+
+/**
+ * Described in header.
+ */
+int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ chunk_t *chunk = *((chunk_t**)(args[0]));
+ bool first = TRUE;
+ chunk_t copy = *chunk;
+ int written = 0;
+
+ if (!spec->hash)
+ {
+ u_int chunk_len = chunk->len;
+ const void *new_args[] = {&chunk->ptr, &chunk_len};
+ return mem_printf_hook(data, spec, new_args);
+ }
+
+ while (copy.len > 0)
+ {
+ if (first)
+ {
+ first = FALSE;
+ }
+ else
+ {
+ written += print_in_hook(data, ":");
+ }
+ written += print_in_hook(data, "%02x", *copy.ptr++);
+ copy.len--;
+ }
+ return written;
+}
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h
new file mode 100644
index 000000000..67848eec1
--- /dev/null
+++ b/src/libstrongswan/utils/chunk.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2008-2009 Tobias Brunner
+ * Copyright (C) 2005-2008 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 chunk chunk
+ * @{ @ingroup utils
+ */
+
+#ifndef CHUNK_H_
+#define CHUNK_H_
+
+#include <string.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+typedef struct chunk_t chunk_t;
+
+/**
+ * General purpose pointer/length abstraction.
+ */
+struct chunk_t {
+ /** Pointer to start of data */
+ u_char *ptr;
+ /** Length of data in bytes */
+ size_t len;
+};
+
+#include "utils.h"
+
+/**
+ * A { NULL, 0 }-chunk handy for initialization.
+ */
+extern chunk_t chunk_empty;
+
+/**
+ * Create a new chunk pointing to "ptr" with length "len"
+ */
+static inline chunk_t chunk_create(u_char *ptr, size_t len)
+{
+ chunk_t chunk = {ptr, len};
+ return chunk;
+}
+
+/**
+ * Create a clone of a chunk pointing to "ptr"
+ */
+chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk);
+
+/**
+ * Calculate length of multiple chunks
+ */
+size_t chunk_length(const char *mode, ...);
+
+/**
+ * Concatenate chunks into a chunk pointing to "ptr".
+ *
+ * The mode string specifies the number of chunks, and how to handle each of
+ * them with a single character: 'c' for copy (allocate new chunk), 'm' for move
+ * (free given chunk) or 's' for sensitive-move (clear given chunk, then free).
+ */
+chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...);
+
+/**
+ * Split up a chunk into parts, "mode" is a string of "a" (alloc),
+ * "c" (copy) and "m" (move). Each letter say for the corresponding chunk if
+ * it should get allocated on heap, copied into existing chunk, or the chunk
+ * should point into "chunk". The length of each part is an argument before
+ * each target chunk. E.g.:
+ * chunk_split(chunk, "mcac", 3, &a, 7, &b, 5, &c, d.len, &d);
+ */
+void chunk_split(chunk_t chunk, const char *mode, ...);
+
+/**
+ * Write the binary contents of a chunk_t to a file
+ *
+ * @param chunk contents to write to file
+ * @param path path where file is written to
+ * @param label label specifying file type
+ * @param mask file mode creation mask
+ * @param force overwrite existing file by force
+ * @return TRUE if write operation was successful
+ */
+bool chunk_write(chunk_t chunk, char *path, char *label, mode_t mask, bool force);
+
+/**
+ * Convert a chunk of data to hex encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 2 + 1).
+ *
+ * @param chunk data to convert to hex encoding
+ * @param buf buffer to write to, NULL to malloc
+ * @param uppercase TRUE to use uppercase letters
+ * @return chunk of encoded data
+ */
+chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase);
+
+/**
+ * Convert a hex encoded in a binary chunk.
+ *
+ * If buf is supplied, it must hold at least (hex.len / 2) + (hex.len % 2)
+ * bytes. It is filled by the right to give correct values for short inputs.
+ *
+ * @param hex hex encoded input data
+ * @param buf buffer to write decoded data, NULL to malloc
+ * @return converted data
+ */
+chunk_t chunk_from_hex(chunk_t hex, char *buf);
+
+/**
+ * Convert a chunk of data to its base64 encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold at least (chunk.len * 4 / 3 + 1).
+ *
+ * @param chunk data to convert
+ * @param buf buffer to write to, NULL to malloc
+ * @return chunk of encoded data
+ */
+chunk_t chunk_to_base64(chunk_t chunk, char *buf);
+
+/**
+ * Convert a base64 in a binary chunk.
+ *
+ * If buf is supplied, it must hold at least (base64.len / 4 * 3).
+ *
+ * @param base64 base64 encoded input data
+ * @param buf buffer to write decoded data, NULL to malloc
+ * @return converted data
+ */
+chunk_t chunk_from_base64(chunk_t base64, char *buf);
+
+/**
+ * Convert a chunk of data to its base32 encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
+ *
+ * @param chunk data to convert
+ * @param buf buffer to write to, NULL to malloc
+ * @return chunk of encoded data
+ */
+chunk_t chunk_to_base32(chunk_t chunk, char *buf);
+
+/**
+ * Free contents of a chunk
+ */
+static inline void chunk_free(chunk_t *chunk)
+{
+ free(chunk->ptr);
+ *chunk = chunk_empty;
+}
+
+/**
+ * Overwrite the contents of a chunk and free it
+ */
+static inline void chunk_clear(chunk_t *chunk)
+{
+ if (chunk->ptr)
+ {
+ memwipe(chunk->ptr, chunk->len);
+ chunk_free(chunk);
+ }
+}
+
+/**
+ * Initialize a chunk using a char array
+ */
+#define chunk_from_chars(...) ((chunk_t){(char[]){__VA_ARGS__}, sizeof((char[]){__VA_ARGS__})})
+
+/**
+ * Initialize a chunk to point to a thing
+ */
+#define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing))
+
+/**
+ * Allocate a chunk on the heap
+ */
+#define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);})
+
+/**
+ * Allocate a chunk on the stack
+ */
+#define chunk_alloca(bytes) ({size_t x = (bytes); chunk_create(x ? alloca(x) : NULL, x);})
+
+/**
+ * Clone a chunk on heap
+ */
+#define chunk_clone(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? malloc(x.len) : NULL, x);})
+
+/**
+ * Clone a chunk on stack
+ */
+#define chunk_clonea(chunk) ({chunk_t x = (chunk); chunk_create_clone(x.len ? alloca(x.len) : NULL, x);})
+
+/**
+ * Concatenate chunks into a chunk on heap
+ */
+#define chunk_cat(mode, ...) chunk_create_cat(malloc(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
+
+/**
+ * Concatenate chunks into a chunk on stack
+ */
+#define chunk_cata(mode, ...) chunk_create_cat(alloca(chunk_length(mode, __VA_ARGS__)), mode, __VA_ARGS__)
+
+/**
+ * Skip n bytes in chunk (forward pointer, shorten length)
+ */
+static inline chunk_t chunk_skip(chunk_t chunk, size_t bytes)
+{
+ if (chunk.len > bytes)
+ {
+ chunk.ptr += bytes;
+ chunk.len -= bytes;
+ return chunk;
+ }
+ return chunk_empty;
+}
+
+/**
+ * Skip a leading zero-valued byte
+ */
+static inline chunk_t chunk_skip_zero(chunk_t chunk)
+{
+ if (chunk.len > 1 && *chunk.ptr == 0x00)
+ {
+ chunk.ptr++;
+ chunk.len--;
+ }
+ return chunk;
+}
+
+
+/**
+ * Compare two chunks, returns zero if a equals b
+ * or negative/positive if a is small/greater than b
+ */
+int chunk_compare(chunk_t a, chunk_t b);
+
+/**
+ * Compare two chunks for equality,
+ * NULL chunks are never equal.
+ */
+static inline bool chunk_equals(chunk_t a, chunk_t b)
+{
+ return a.ptr != NULL && b.ptr != NULL &&
+ a.len == b.len && memeq(a.ptr, b.ptr, a.len);
+}
+
+/**
+ * Compare two chunks (given as pointers) for equality (useful as callback),
+ * NULL chunks are never equal.
+ */
+static inline bool chunk_equals_ptr(chunk_t *a, chunk_t *b)
+{
+ return a != NULL && b != NULL && chunk_equals(*a, *b);
+}
+
+/**
+ * Increment a chunk, as it would reprensent a network order integer.
+ *
+ * @param chunk chunk to increment
+ * @return TRUE if an overflow occurred
+ */
+bool chunk_increment(chunk_t chunk);
+
+/**
+ * Check if a chunk has printable characters only.
+ *
+ * If sane is given, chunk is cloned into sane and all non printable characters
+ * get replaced by "replace".
+ *
+ * @param chunk chunk to check for printability
+ * @param sane pointer where sane version is allocated, or NULL
+ * @param replace character to use for replaceing unprintable characters
+ * @return TRUE if all characters in chunk are printable
+ */
+bool chunk_printable(chunk_t chunk, chunk_t *sane, char replace);
+
+/**
+ * Computes a 32 bit hash of the given chunk.
+ * Note: This hash is only intended for hash tables not for cryptographic purposes.
+ */
+u_int32_t chunk_hash(chunk_t chunk);
+
+/**
+ * Incremental version of chunk_hash. Use this to hash two or more chunks.
+ */
+u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash);
+
+/**
+ * printf hook function for chunk_t.
+ *
+ * Arguments are:
+ * chunk_t *chunk
+ * Use #-modifier to print a compact version
+ */
+int chunk_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** CHUNK_H_ @}*/
diff --git a/src/libstrongswan/utils/debug.c b/src/libstrongswan/utils/debug.c
new file mode 100644
index 000000000..e8c9e6b98
--- /dev/null
+++ b/src/libstrongswan/utils/debug.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2006 Martin Willi
+ * 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.
+ */
+
+#include <stdarg.h>
+
+#include "debug.h"
+
+ENUM(debug_names, DBG_DMN, DBG_LIB,
+ "DMN",
+ "MGR",
+ "IKE",
+ "CHD",
+ "JOB",
+ "CFG",
+ "KNL",
+ "NET",
+ "ASN",
+ "ENC",
+ "TNC",
+ "IMC",
+ "IMV",
+ "PTS",
+ "TLS",
+ "APP",
+ "ESP",
+ "LIB",
+);
+
+ENUM(debug_lower_names, DBG_DMN, DBG_LIB,
+ "dmn",
+ "mgr",
+ "ike",
+ "chd",
+ "job",
+ "cfg",
+ "knl",
+ "net",
+ "asn",
+ "enc",
+ "tnc",
+ "imc",
+ "imv",
+ "pts",
+ "tls",
+ "app",
+ "esp",
+ "lib",
+);
+
+/**
+ * level logged by the default logger
+ */
+static level_t default_level = 1;
+
+/**
+ * stream logged to by the default logger
+ */
+static FILE *default_stream = NULL;
+
+/**
+ * default dbg function which printf all to stderr
+ */
+void dbg_default(debug_t group, level_t level, char *fmt, ...)
+{
+ if (!default_stream)
+ {
+ default_stream = stderr;
+ }
+ if (level <= default_level)
+ {
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(default_stream, fmt, args);
+ fprintf(default_stream, "\n");
+ va_end(args);
+ }
+}
+
+/**
+ * set the level logged by the default stderr logger
+ */
+void dbg_default_set_level(level_t level)
+{
+ default_level = level;
+}
+
+/**
+ * set the stream logged by dbg_default() to
+ */
+void dbg_default_set_stream(FILE *stream)
+{
+ default_stream = stream;
+}
+
+/**
+ * The registered debug hook.
+ */
+void (*dbg) (debug_t group, level_t level, char *fmt, ...) = dbg_default;
+
diff --git a/src/libstrongswan/utils/debug.h b/src/libstrongswan/utils/debug.h
new file mode 100644
index 000000000..c46d3fe55
--- /dev/null
+++ b/src/libstrongswan/utils/debug.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2006 Martin Willi
+ * 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 debug debug
+ * @{ @ingroup utils
+ */
+
+#ifndef DEBUG_H_
+#define DEBUG_H_
+
+typedef enum debug_t debug_t;
+typedef enum level_t level_t;
+
+#include <stdio.h>
+
+#include "utils/enum.h"
+
+/**
+ * Debug message group.
+ */
+enum debug_t {
+ /** daemon specific */
+ DBG_DMN,
+ /** IKE_SA_MANAGER */
+ DBG_MGR,
+ /** IKE_SA */
+ DBG_IKE,
+ /** CHILD_SA */
+ DBG_CHD,
+ /** job processing */
+ DBG_JOB,
+ /** configuration backends */
+ DBG_CFG,
+ /** kernel interface */
+ DBG_KNL,
+ /** networking/sockets */
+ DBG_NET,
+ /** low-level encoding/decoding (ASN.1, X.509 etc.) */
+ DBG_ASN,
+ /** message encoding/decoding */
+ DBG_ENC,
+ /** trusted network connect */
+ DBG_TNC,
+ /** integrity measurement client */
+ DBG_IMC,
+ /** integrity measurement verifier */
+ DBG_IMV,
+ /** platform trust service */
+ DBG_PTS,
+ /** libtls */
+ DBG_TLS,
+ /** applications other than daemons */
+ DBG_APP,
+ /** libipsec */
+ DBG_ESP,
+ /** libstrongswan */
+ DBG_LIB,
+ /** number of groups */
+ DBG_MAX,
+ /** pseudo group with all groups */
+ DBG_ANY = DBG_MAX,
+};
+
+/**
+ * short names of debug message group.
+ */
+extern enum_name_t *debug_names;
+
+/**
+ * short names of debug message group, lower case.
+ */
+extern enum_name_t *debug_lower_names;
+
+/**
+ * Debug levels used to control output verbosity.
+ */
+enum level_t {
+ /** absolutely silent */
+ LEVEL_SILENT = -1,
+ /** most important auditing logs */
+ LEVEL_AUDIT = 0,
+ /** control flow */
+ LEVEL_CTRL = 1,
+ /** diagnose problems */
+ LEVEL_DIAG = 2,
+ /** raw binary blobs */
+ LEVEL_RAW = 3,
+ /** including sensitive data (private keys) */
+ LEVEL_PRIVATE = 4,
+};
+
+#ifndef DEBUG_LEVEL
+# define DEBUG_LEVEL 4
+#endif /* DEBUG_LEVEL */
+
+/** debug macros, they call the dbg function hook */
+#if DEBUG_LEVEL >= 0
+# define DBG0(group, fmt, ...) dbg(group, 0, fmt, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL */
+#if DEBUG_LEVEL >= 1
+# define DBG1(group, fmt, ...) dbg(group, 1, fmt, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL */
+#if DEBUG_LEVEL >= 2
+# define DBG2(group, fmt, ...) dbg(group, 2, fmt, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL */
+#if DEBUG_LEVEL >= 3
+# define DBG3(group, fmt, ...) dbg(group, 3, fmt, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL */
+#if DEBUG_LEVEL >= 4
+# define DBG4(group, fmt, ...) dbg(group, 4, fmt, ##__VA_ARGS__)
+#endif /* DEBUG_LEVEL */
+
+#ifndef DBG0
+# define DBG0(...) {}
+#endif
+#ifndef DBG1
+# define DBG1(...) {}
+#endif
+#ifndef DBG2
+# define DBG2(...) {}
+#endif
+#ifndef DBG3
+# define DBG3(...) {}
+#endif
+#ifndef DBG4
+# define DBG4(...) {}
+#endif
+
+/** dbg function hook, uses dbg_default() by default */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/** default logging function */
+void dbg_default(debug_t group, level_t level, char *fmt, ...);
+
+/** set the level logged by dbg_default() */
+void dbg_default_set_level(level_t level);
+
+/** set the stream logged by dbg_default() to */
+void dbg_default_set_stream(FILE *stream);
+
+#endif /** DEBUG_H_ @}*/
diff --git a/src/libstrongswan/utils/enum.c b/src/libstrongswan/utils/enum.c
new file mode 100644
index 000000000..9b3c4d566
--- /dev/null
+++ b/src/libstrongswan/utils/enum.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006 Martin Willi
+ * 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.
+ */
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include <library.h>
+
+#include "enum.h"
+
+/**
+ * See header.
+ */
+char *enum_to_name(enum_name_t *e, int val)
+{
+ do
+ {
+ if (val >= e->first && val <= e->last)
+ {
+ return e->names[val - e->first];
+ }
+ }
+ while ((e = e->next));
+ return NULL;
+}
+
+/**
+ * See header.
+ */
+int enum_from_name(enum_name_t *e, char *name)
+{
+ do
+ {
+ int i, count = e->last - e->first + 1;
+
+ for (i = 0; i < count; i++)
+ {
+ if (strcaseeq(name, e->names[i]))
+ {
+ return e->first + i;
+ }
+ }
+ }
+ while ((e = e->next));
+ return -1;
+}
+
+/**
+ * Described in header.
+ */
+int enum_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ enum_name_t *ed = *((enum_name_t**)(args[0]));
+ int val = *((int*)(args[1]));
+ char *name, buf[32];
+
+ name = enum_to_name(ed, val);
+ if (name == NULL)
+ {
+ snprintf(buf, sizeof(buf), "(%d)", val);
+ name = buf;
+ }
+ if (spec->minus)
+ {
+ return print_in_hook(data, "%-*s", spec->width, name);
+ }
+ return print_in_hook(data, "%*s", spec->width, name);
+}
diff --git a/src/libstrongswan/utils/enum.h b/src/libstrongswan/utils/enum.h
new file mode 100644
index 000000000..df8dbf8c1
--- /dev/null
+++ b/src/libstrongswan/utils/enum.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * 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 enum enum
+ * @{ @ingroup utils
+ */
+
+#ifndef ENUM_H_
+#define ENUM_H_
+
+#include "printf_hook.h"
+
+typedef struct enum_name_t enum_name_t;
+
+/**
+ * Struct to store names for enums.
+ *
+ * To print the string representation of enumeration values, the strings
+ * are stored in these structures. Every enum_name contains a range
+ * of strings, multiple ranges are linked together.
+ * Use the convenience macros to define these linked ranges.
+ *
+ * For a single range, use:
+ * @code
+ ENUM(name, first, last, string1, string2, ...)
+ @endcode
+ * For multiple linked ranges, use:
+ * @code
+ ENUM_BEGIN(name, first, last, string1, string2, ...)
+ ENUM_NEXT(name, first, last, last_from_previous, string3, ...)
+ ENUM_NEXT(name, first, last, last_from_previous, string4, ...)
+ ENUM_END(name, last_from_previous)
+ @endcode
+ * The ENUM and the ENUM_END define a enum_name_t pointer with the name supplied
+ * in "name".
+ *
+ * Resolving of enum names is done using a printf hook. A printf fromat
+ * character %N is replaced by the enum string. Printf needs two arguments to
+ * resolve a %N, the enum_name_t* (the defined name in ENUM_BEGIN) followed
+ * by the numerical enum value.
+ */
+struct enum_name_t {
+ /** value of the first enum string */
+ int first;
+ /** value of the last enum string */
+ int last;
+ /** next enum_name_t in list */
+ enum_name_t *next;
+ /** array of strings containing names from first to last */
+ char *names[];
+};
+
+/**
+ * Begin a new enum_name list.
+ *
+ * @param name name of the enum_name list
+ * @param first enum value of the first enum string
+ * @param last enum value of the last enum string
+ * @param ... a list of strings
+ */
+#define ENUM_BEGIN(name, first, last, ...) static enum_name_t name##last = {first, last, NULL, { __VA_ARGS__ }}
+
+/**
+ * Continue a enum name list startetd with ENUM_BEGIN.
+ *
+ * @param name name of the enum_name list
+ * @param first enum value of the first enum string
+ * @param last enum value of the last enum string
+ * @param prev enum value of the "last" defined in ENUM_BEGIN/previous ENUM_NEXT
+ * @param ... a list of strings
+ */
+#define ENUM_NEXT(name, first, last, prev, ...) static enum_name_t name##last = {first, last, &name##prev, { __VA_ARGS__ }}
+
+/**
+ * Complete enum name list started with ENUM_BEGIN.
+ *
+ * @param name name of the enum_name list
+ * @param prev enum value of the "last" defined in ENUM_BEGIN/previous ENUM_NEXT
+ */
+#define ENUM_END(name, prev) enum_name_t *name = &name##prev;
+
+/**
+ * Define a enum name with only one range.
+ *
+ * This is a convenience macro to use when a enum_name list contains only
+ * one range, and is equal as defining ENUM_BEGIN followed by ENUM_END.
+ *
+ * @param name name of the enum_name list
+ * @param first enum value of the first enum string
+ * @param last enum value of the last enum string
+ * @param ... a list of strings
+ */
+#define ENUM(name, first, last, ...) ENUM_BEGIN(name, first, last, __VA_ARGS__); ENUM_END(name, last)
+
+/**
+ * Convert a enum value to its string representation.
+ *
+ * @param e enum names for this enum value
+ * @param val enum value to get string for
+ * @return string for enum, NULL if not found
+ */
+char *enum_to_name(enum_name_t *e, int val);
+
+/**
+ * Convert a enum string back to its enum value.
+ *
+ * @param e enum names for this enum value
+ * @param name name to get enum value for
+ * @return enum value, -1 if not found
+ */
+int enum_from_name(enum_name_t *e, char *name);
+
+/**
+ * printf hook function for enum_names_t.
+ *
+ * Arguments are:
+ * enum_names_t *names, int value
+ */
+int enum_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** ENUM_H_ @}*/
diff --git a/src/libstrongswan/utils/enumerator.c b/src/libstrongswan/utils/enumerator.c
deleted file mode 100644
index 53c94f9dd..000000000
--- a/src/libstrongswan/utils/enumerator.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright (C) 2008 Tobias Brunner
- * Copyright (C) 2007 Martin Willi
- * 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.
- */
-
-#include "enumerator.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <errno.h>
-#include <string.h>
-
-#include <debug.h>
-
-/**
- * Implementation of enumerator_create_empty().enumerate
- */
-static bool enumerate_empty(enumerator_t *enumerator, ...)
-{
- return FALSE;
-}
-
-/**
- * See header
- */
-enumerator_t* enumerator_create_empty()
-{
- enumerator_t *this = malloc_thing(enumerator_t);
- this->enumerate = enumerate_empty;
- this->destroy = (void*)free;
- return this;
-}
-
-/**
- * Enumerator implementation for directory enumerator
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** directory handle */
- DIR *dir;
- /** absolute path of current file */
- char full[PATH_MAX];
- /** where directory part of full ends and relative file gets written */
- char *full_end;
-} dir_enum_t;
-
-/**
- * Implementation of enumerator_create_directory().destroy
- */
-static void destroy_dir_enum(dir_enum_t *this)
-{
- closedir(this->dir);
- free(this);
-}
-
-/**
- * Implementation of enumerator_create_directory().enumerate
- */
-static bool enumerate_dir_enum(dir_enum_t *this, char **relative,
- char **absolute, struct stat *st)
-{
- struct dirent *entry = readdir(this->dir);
- size_t remaining;
- int len;
-
- if (!entry)
- {
- return FALSE;
- }
- if (streq(entry->d_name, ".") || streq(entry->d_name, ".."))
- {
- return enumerate_dir_enum(this, relative, absolute, st);
- }
- if (relative)
- {
- *relative = entry->d_name;
- }
- if (absolute || st)
- {
- remaining = sizeof(this->full) - (this->full_end - this->full);
- len = snprintf(this->full_end, remaining, "%s", entry->d_name);
- if (len < 0 || len >= remaining)
- {
- DBG1(DBG_LIB, "buffer too small to enumerate file '%s'",
- entry->d_name);
- return FALSE;
- }
- if (absolute)
- {
- *absolute = this->full;
- }
- if (st)
- {
- if (stat(this->full, st))
- {
- DBG1(DBG_LIB, "stat() on '%s' failed: %s", this->full,
- strerror(errno));
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-/**
- * See header
- */
-enumerator_t* enumerator_create_directory(const char *path)
-{
- int len;
- dir_enum_t *this = malloc_thing(dir_enum_t);
- this->public.enumerate = (void*)enumerate_dir_enum;
- this->public.destroy = (void*)destroy_dir_enum;
-
- if (*path == '\0')
- {
- path = "./";
- }
- len = snprintf(this->full, sizeof(this->full)-1, "%s", path);
- if (len < 0 || len >= sizeof(this->full)-1)
- {
- DBG1(DBG_LIB, "path string '%s' too long", path);
- free(this);
- return NULL;
- }
- /* append a '/' if not already done */
- if (this->full[len-1] != '/')
- {
- this->full[len++] = '/';
- this->full[len] = '\0';
- }
- this->full_end = &this->full[len];
-
- this->dir = opendir(path);
- if (this->dir == NULL)
- {
- DBG1(DBG_LIB, "opening directory '%s' failed: %s", path, strerror(errno));
- free(this);
- return NULL;
- }
- return &this->public;
-}
-
-/**
- * Enumerator implementation for directory enumerator
- */
-typedef struct {
- /** implements enumerator_t */
- enumerator_t public;
- /** string to parse */
- char *string;
- /** current position */
- char *pos;
- /** separater chars */
- const char *sep;
- /** trim chars */
- const char *trim;
-} token_enum_t;
-
-/**
- * Implementation of enumerator_create_token().destroy
- */
-static void destroy_token_enum(token_enum_t *this)
-{
- free(this->string);
- free(this);
-}
-
-/**
- * Implementation of enumerator_create_token().enumerate
- */
-static bool enumerate_token_enum(token_enum_t *this, char **token)
-{
- const char *sep, *trim;
- char *pos = NULL, *tmp;
- bool last = FALSE;
-
- /* trim leading characters/separators */
- while (*this->pos)
- {
- trim = this->trim;
- while (*trim)
- {
- if (*trim == *this->pos)
- {
- this->pos++;
- break;
- }
- trim++;
- }
- sep = this->sep;
- while (*sep)
- {
- if (*sep == *this->pos)
- {
- this->pos++;
- break;
- }
- sep++;
- }
- if (!*trim && !*sep)
- {
- break;
- }
- }
-
- switch (*this->pos)
- {
- case '"':
- case '\'':
- {
- /* read quoted token */
- tmp = strchr(this->pos + 1, *this->pos);
- if (tmp)
- {
- *token = this->pos + 1;
- *tmp = '\0';
- this->pos = tmp + 1;
- return TRUE;
- }
- /* unterminated string, FALL-THROUGH */
- }
- default:
- {
- /* find nearest separator */
- sep = this->sep;
- while (*sep)
- {
- tmp = strchr(this->pos, *sep);
- if (tmp && (pos == NULL || tmp < pos))
- {
- pos = tmp;
- }
- sep++;
- }
- *token = this->pos;
- if (pos)
- {
- *pos = '\0';
- this->pos = pos + 1;
- }
- else
- {
- last = TRUE;
- pos = this->pos = strchr(this->pos, '\0');
- }
- break;
- }
- }
-
- /* trim trailing characters/separators */
- pos--;
- while (pos >= *token)
- {
- trim = this->trim;
- while (*trim)
- {
- if (*trim == *pos)
- {
- *(pos--) = '\0';
- break;
- }
- trim++;
- }
- sep = this->sep;
- while (*sep)
- {
- if (*sep == *pos)
- {
- *(pos--) = '\0';
- break;
- }
- sep++;
- }
- if (!*trim && !*sep)
- {
- break;
- }
- }
-
- if (!last || pos >= *token)
- {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * See header
- */
-enumerator_t* enumerator_create_token(const char *string, const char *sep,
- const char *trim)
-{
- token_enum_t *enumerator = malloc_thing(token_enum_t);
-
- enumerator->public.enumerate = (void*)enumerate_token_enum;
- enumerator->public.destroy = (void*)destroy_token_enum;
- enumerator->string = strdup(string);
- enumerator->pos = enumerator->string;
- enumerator->sep = sep;
- enumerator->trim = trim;
-
- return &enumerator->public;
-}
-
-/**
- * enumerator for nested enumerations
- */
-typedef struct {
- /* implements enumerator_t */
- enumerator_t public;
- /* outer enumerator */
- enumerator_t *outer;
- /* inner enumerator */
- enumerator_t *inner;
- /* constructor for inner enumerator */
- enumerator_t *(*create_inner)(void *outer, void *data);
- /* data to pass to constructor above */
- void *data;
- /* destructor for data */
- void (*destroy_data)(void *data);
-} nested_enumerator_t;
-
-
-/**
- * Implementation of enumerator_create_nested().enumerate()
- */
-static bool enumerate_nested(nested_enumerator_t *this, void *v1, void *v2,
- void *v3, void *v4, void *v5)
-{
- while (TRUE)
- {
- while (this->inner == NULL)
- {
- void *outer;
-
- if (!this->outer->enumerate(this->outer, &outer))
- {
- return FALSE;
- }
- this->inner = this->create_inner(outer, this->data);
- }
- if (this->inner->enumerate(this->inner, v1, v2, v3, v4, v5))
- {
- return TRUE;
- }
- this->inner->destroy(this->inner);
- this->inner = NULL;
- }
-}
-
-/**
- * Implementation of enumerator_create_nested().destroy()
- **/
-static void destroy_nested(nested_enumerator_t *this)
-{
- if (this->destroy_data)
- {
- this->destroy_data(this->data);
- }
- DESTROY_IF(this->inner);
- this->outer->destroy(this->outer);
- free(this);
-}
-
-/**
- * See header
- */
-enumerator_t *enumerator_create_nested(enumerator_t *outer,
- enumerator_t *(inner_constructor)(void *outer, void *data),
- void *data, void (*destroy_data)(void *data))
-{
- nested_enumerator_t *enumerator = malloc_thing(nested_enumerator_t);
-
- enumerator->public.enumerate = (void*)enumerate_nested;
- enumerator->public.destroy = (void*)destroy_nested;
- enumerator->outer = outer;
- enumerator->inner = NULL;
- enumerator->create_inner = (void*)inner_constructor;
- enumerator->data = data;
- enumerator->destroy_data = destroy_data;
-
- return &enumerator->public;
-}
-
-/**
- * enumerator for filtered enumerator
- */
-typedef struct {
- enumerator_t public;
- enumerator_t *unfiltered;
- void *data;
- bool (*filter)(void *data, ...);
- void (*destructor)(void *data);
-} filter_enumerator_t;
-
-/**
- * Implementation of enumerator_create_filter().destroy
- */
-static void destroy_filter(filter_enumerator_t *this)
-{
- if (this->destructor)
- {
- this->destructor(this->data);
- }
- this->unfiltered->destroy(this->unfiltered);
- free(this);
-}
-
-/**
- * Implementation of enumerator_create_filter().enumerate
- */
-static bool enumerate_filter(filter_enumerator_t *this, void *o1, void *o2,
- void *o3, void *o4, void *o5)
-{
- void *i1, *i2, *i3, *i4, *i5;
-
- while (this->unfiltered->enumerate(this->unfiltered, &i1, &i2, &i3, &i4, &i5))
- {
- if (this->filter(this->data, &i1, o1, &i2, o2, &i3, o3, &i4, o4, &i5, o5))
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-/**
- * see header
- */
-enumerator_t *enumerator_create_filter(enumerator_t *unfiltered,
- bool (*filter)(void *data, ...),
- void *data, void (*destructor)(void *data))
-{
- filter_enumerator_t *this = malloc_thing(filter_enumerator_t);
-
- this->public.enumerate = (void*)enumerate_filter;
- this->public.destroy = (void*)destroy_filter;
- this->unfiltered = unfiltered;
- this->filter = filter;
- this->data = data;
- this->destructor = destructor;
-
- return &this->public;
-}
-
-/**
- * enumerator for cleaner enumerator
- */
-typedef struct {
- enumerator_t public;
- enumerator_t *wrapped;
- void (*cleanup)(void *data);
- void *data;
-} cleaner_enumerator_t;
-
-/**
- * Implementation of enumerator_create_cleanup().destroy
- */
-static void destroy_cleaner(cleaner_enumerator_t *this)
-{
- this->cleanup(this->data);
- this->wrapped->destroy(this->wrapped);
- free(this);
-}
-
-/**
- * Implementation of enumerator_create_cleaner().enumerate
- */
-static bool enumerate_cleaner(cleaner_enumerator_t *this, void *v1, void *v2,
- void *v3, void *v4, void *v5)
-{
- return this->wrapped->enumerate(this->wrapped, v1, v2, v3, v4, v5);
-}
-
-/**
- * see header
- */
-enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped,
- void (*cleanup)(void *data), void *data)
-{
- cleaner_enumerator_t *this = malloc_thing(cleaner_enumerator_t);
-
- this->public.enumerate = (void*)enumerate_cleaner;
- this->public.destroy = (void*)destroy_cleaner;
- this->wrapped = wrapped;
- this->cleanup = cleanup;
- this->data = data;
-
- return &this->public;
-}
-
-/**
- * enumerator for single enumerator
- */
-typedef struct {
- enumerator_t public;
- void *item;
- void (*cleanup)(void *item);
- bool done;
-} single_enumerator_t;
-
-/**
- * Implementation of enumerator_create_single().destroy
- */
-static void destroy_single(single_enumerator_t *this)
-{
- if (this->cleanup)
- {
- this->cleanup(this->item);
- }
- free(this);
-}
-
-/**
- * Implementation of enumerator_create_single().enumerate
- */
-static bool enumerate_single(single_enumerator_t *this, void **item)
-{
- if (this->done)
- {
- return FALSE;
- }
- *item = this->item;
- this->done = TRUE;
- return TRUE;
-}
-
-/**
- * see header
- */
-enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item))
-{
- single_enumerator_t *this = malloc_thing(single_enumerator_t);
-
- this->public.enumerate = (void*)enumerate_single;
- this->public.destroy = (void*)destroy_single;
- this->item = item;
- this->cleanup = cleanup;
- this->done = FALSE;
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h
deleted file mode 100644
index 8c3d70173..000000000
--- a/src/libstrongswan/utils/enumerator.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2007 Martin Willi
- * 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 enumerator enumerator
- * @{ @ingroup utils
- */
-
-#ifndef ENUMERATOR_H_
-#define ENUMERATOR_H_
-
-typedef struct enumerator_t enumerator_t;
-
-#include "../utils.h"
-
-/**
- * Enumerator interface, allows enumeration over collections.
- */
-struct enumerator_t {
-
- /**
- * Enumerate collection.
- *
- * The enumerate function takes a variable argument list containing
- * pointers where the enumerated values get written.
- *
- * @param ... variable list of enumerated items, implementation dependent
- * @return TRUE if pointers returned
- */
- bool (*enumerate)(enumerator_t *this, ...);
-
- /**
- * Destroy a enumerator instance.
- */
- void (*destroy)(enumerator_t *this);
-};
-
-/**
- * Create an enumerator which enumerates over nothing
- *
- * @return an enumerator over no values
- */
-enumerator_t* enumerator_create_empty();
-
-/**
- * Create an enumerator which enumerates over a single item
- *
- * @param item item to enumerate
- * @param cleanup cleanup function called on destroy with the item
- * @return an enumerator over a single value
- */
-enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item));
-
-/**
- * Create an enumerator over files/subdirectories in a directory.
- *
- * This enumerator_t.enumerate() function returns a (to the directory) relative
- * filename (as a char*), an absolute filename (as a char*) and a file status
- * (to a struct stat), which all may be NULL. "." and ".." entries are
- * skipped. Example:
- *
- * @code
- char *rel, *abs;
- struct stat st;
- enumerator_t *e;
-
- e = enumerator_create_directory("/tmp");
- if (e)
- {
- while (e->enumerate(e, &rel, &abs, &st))
- {
- if (S_ISDIR(st.st_mode) && *rel != '.')
- {
- printf("%s\n", abs);
- }
- }
- e->destroy(e);
- }
- @endcode
- *
- * @param path path of the directory
- * @return the directory enumerator, NULL on failure
- */
-enumerator_t* enumerator_create_directory(const char *path);
-
-/**
- * Create an enumerator over tokens of a string.
- *
- * Tokens are separated by one of the characters in sep and trimmed by the
- * characters in trim.
- *
- * @param string string to parse
- * @param sep separator characters
- * @param trim characters to trim from tokens
- * @return enumerator over char* tokens
- */
-enumerator_t* enumerator_create_token(const char *string, const char *sep,
- const char *trim);
-
-/**
- * Creates an enumerator which enumerates over enumerated enumerators :-).
- *
- * The variable argument list of enumeration values is limit to 5.
- *
- * @param outer outer enumerator
- * @param inner_constructor constructor to inner enumerator
- * @param data data to pass to each inner_constructor call
- * @param destroy_data destructor to pass to data
- * @return the nested enumerator
- */
-enumerator_t *enumerator_create_nested(enumerator_t *outer,
- enumerator_t *(*inner_constructor)(void *outer, void *data),
- void *data, void (*destroy_data)(void *data));
-
-/**
- * Creates an enumerator which filters output of another enumerator.
- *
- * The filter function receives the user supplied "data" followed by a
- * unfiltered enumeration item, followed by an output pointer where to write
- * the filtered data. Then the next input/output pair follows.
- * It returns TRUE to deliver the
- * values to the caller of enumerate(), FALSE to filter this enumeration.
- *
- * The variable argument list of enumeration values is limit to 5.
- *
- * @param unfiltered unfiltered enumerator to wrap, gets destroyed
- * @param filter filter function
- * @param data user data to supply to filter
- * @param destructor destructor function to clean up data after use
- * @return the filtered enumerator
- */
-enumerator_t *enumerator_create_filter(enumerator_t *unfiltered,
- bool (*filter)(void *data, ...),
- void *data, void (*destructor)(void *data));
-
-/**
- * Create an enumerator wrapper which does a cleanup on destroy.
- *
- * @param wrapped wrapped enumerator
- * @param cleanup cleanup function called on destroy
- * @param data user data to supply to cleanup
- * @return the enumerator with cleanup
- */
-enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped,
- void (*cleanup)(void *data), void *data);
-
-#endif /** ENUMERATOR_H_ @}*/
diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c
deleted file mode 100644
index d181d8ec8..000000000
--- a/src/libstrongswan/utils/hashtable.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * Copyright (C) 2008-2012 Tobias Brunner
- * 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.
- */
-
-
-#include "hashtable.h"
-
-/** The maximum capacity of the hash table (MUST be a power of 2) */
-#define MAX_CAPACITY (1 << 30)
-
-typedef struct pair_t pair_t;
-
-/**
- * This pair holds a pointer to the key and value it represents.
- */
-struct pair_t {
- /**
- * Key of a hash table item.
- */
- void *key;
-
- /**
- * Value of a hash table item.
- */
- void *value;
-
- /**
- * 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.
- */
-static inline pair_t *pair_create(void *key, void *value, u_int hash)
-{
- pair_t *this;
-
- INIT(this,
- .key = key,
- .value = value,
- .hash = hash,
- );
-
- return this;
-}
-
-typedef struct private_hashtable_t private_hashtable_t;
-
-/**
- * Private data of a hashtable_t object.
- *
- */
-struct private_hashtable_t {
- /**
- * Public part of hash table.
- */
- hashtable_t public;
-
- /**
- * The number of items in the hash table.
- */
- u_int count;
-
- /**
- * The current capacity of the hash table (always a power of 2).
- */
- u_int capacity;
-
- /**
- * The current mask to calculate the row index (capacity - 1).
- */
- u_int mask;
-
- /**
- * The load factor.
- */
- float load_factor;
-
- /**
- * The actual table.
- */
- pair_t **table;
-
- /**
- * The hashing function.
- */
- hashtable_hash_t hash;
-
- /**
- * The equality function.
- */
- hashtable_equals_t equals;
-};
-
-typedef struct private_enumerator_t private_enumerator_t;
-
-/**
- * hash table enumerator implementation
- */
-struct private_enumerator_t {
-
- /**
- * implements enumerator interface
- */
- enumerator_t enumerator;
-
- /**
- * associated hash table
- */
- private_hashtable_t *table;
-
- /**
- * current row index
- */
- u_int row;
-
- /**
- * number of remaining items in hashtable
- */
- u_int count;
-
- /**
- * current pair
- */
- pair_t *current;
-
- /**
- * previous pair (used by remove_at)
- */
- pair_t *prev;
-
-};
-
-/**
- * This function returns the next-highest power of two for the given number.
- * The algorithm works by setting all bits on the right-hand side of the most
- * significant 1 to 1 and then increments the whole number so it rolls over
- * to the nearest power of two. Note: returns 0 for n == 0
- */
-static u_int get_nearest_powerof2(u_int n)
-{
- u_int i;
-
- --n;
- for (i = 1; i < sizeof(u_int) * 8; i <<= 1)
- {
- n |= n >> i;
- }
- return ++n;
-}
-
-/**
- * Init hash table parameters
- */
-static void init_hashtable(private_hashtable_t *this, u_int capacity)
-{
- capacity = max(1, min(capacity, MAX_CAPACITY));
- this->capacity = get_nearest_powerof2(capacity);
- this->mask = this->capacity - 1;
- this->load_factor = 0.75;
-
- this->table = calloc(this->capacity, sizeof(pair_t*));
-}
-
-/**
- * Double the size of the hash table and rehash all the elements.
- */
-static void rehash(private_hashtable_t *this)
-{
- pair_t **old_table;
- u_int row, old_capacity;
-
- if (this->capacity >= MAX_CAPACITY)
- {
- return;
- }
-
- old_capacity = this->capacity;
- old_table = this->table;
-
- init_hashtable(this, old_capacity << 1);
-
- for (row = 0; row < old_capacity; row++)
- {
- pair_t *pair, *next;
- u_int new_row;
-
- 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);
-}
-
-METHOD(hashtable_t, put, void*,
- private_hashtable_t *this, void *key, void *value)
-{
- void *old_value = NULL;
- pair_t *pair;
- u_int hash, row;
-
- hash = this->hash(key);
- row = hash & this->mask;
- pair = this->table[row];
- while (pair)
- { /* search existing bucket for key */
- if (this->equals(key, pair->key))
- {
- old_value = pair->value;
- pair->value = value;
- pair->key = key;
- break;
- }
- pair = pair->next;
- }
- 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)
- {
- rehash(this);
- }
- return old_value;
-}
-
-static void *get_internal(private_hashtable_t *this, void *key,
- hashtable_equals_t equals)
-{
- void *value = NULL;
- pair_t *pair;
-
- if (!this->count)
- { /* no need to calculate the hash */
- return NULL;
- }
-
- pair = this->table[this->hash(key) & this->mask];
- while (pair)
- {
- if (equals(key, pair->key))
- {
- value = pair->value;
- break;
- }
- pair = pair->next;
- }
- return value;
-}
-
-METHOD(hashtable_t, get, void*,
- private_hashtable_t *this, void *key)
-{
- return get_internal(this, key, this->equals);
-}
-
-METHOD(hashtable_t, get_match, void*,
- private_hashtable_t *this, void *key, hashtable_equals_t match)
-{
- return get_internal(this, key, match);
-}
-
-METHOD(hashtable_t, remove_, void*,
- private_hashtable_t *this, void *key)
-{
- void *value = NULL;
- pair_t *pair, *prev = NULL;
- u_int row;
-
- row = this->hash(key) & this->mask;
- pair = this->table[row];
- while (pair)
- {
- if (this->equals(key, pair->key))
- {
- if (prev)
- {
- prev->next = pair->next;
- }
- else
- {
- this->table[row] = pair->next;
- }
- value = pair->value;
- this->count--;
- free(pair);
- break;
- }
- prev = pair;
- pair = pair->next;
- }
- return value;
-}
-
-METHOD(hashtable_t, remove_at, void,
- private_hashtable_t *this, private_enumerator_t *enumerator)
-{
- if (enumerator->table == this && enumerator->current)
- {
- pair_t *current = enumerator->current;
- if (enumerator->prev)
- {
- enumerator->prev->next = current->next;
- }
- else
- {
- this->table[enumerator->row] = current->next;
- }
- enumerator->current = enumerator->prev;
- free(current);
- this->count--;
- }
-}
-
-METHOD(hashtable_t, get_count, u_int,
- private_hashtable_t *this)
-{
- return this->count;
-}
-
-METHOD(enumerator_t, enumerate, bool,
- private_enumerator_t *this, void **key, void **value)
-{
- while (this->count && this->row < this->table->capacity)
- {
- this->prev = this->current;
- if (this->current)
- {
- this->current = this->current->next;
- }
- else
- {
- this->current = this->table->table[this->row];
- }
- if (this->current)
- {
- if (key)
- {
- *key = this->current->key;
- }
- if (value)
- {
- *value = this->current->value;
- }
- this->count--;
- return TRUE;
- }
- this->row++;
- }
- return FALSE;
-}
-
-METHOD(hashtable_t, create_enumerator, enumerator_t*,
- private_hashtable_t *this)
-{
- private_enumerator_t *enumerator;
-
- INIT(enumerator,
- .enumerator = {
- .enumerate = (void*)_enumerate,
- .destroy = (void*)free,
- },
- .table = this,
- .count = this->count,
- );
-
- return &enumerator->enumerator;
-}
-
-METHOD(hashtable_t, destroy, void,
- private_hashtable_t *this)
-{
- pair_t *pair, *next;
- u_int row;
-
- for (row = 0; row < this->capacity; row++)
- {
- pair = this->table[row];
- while (pair)
- {
- next = pair->next;
- free(pair);
- pair = next;
- }
- }
- free(this->table);
- free(this);
-}
-
-/*
- * Described in header.
- */
-hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
- u_int capacity)
-{
- private_hashtable_t *this;
-
- INIT(this,
- .public = {
- .put = _put,
- .get = _get,
- .get_match = _get_match,
- .remove = _remove_,
- .remove_at = (void*)_remove_at,
- .get_count = _get_count,
- .create_enumerator = _create_enumerator,
- .destroy = _destroy,
- },
- .hash = hash,
- .equals = equals,
- );
-
- init_hashtable(this, capacity);
-
- return &this->public;
-}
-
diff --git a/src/libstrongswan/utils/hashtable.h b/src/libstrongswan/utils/hashtable.h
deleted file mode 100644
index 0a21ca373..000000000
--- a/src/libstrongswan/utils/hashtable.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2008-2012 Tobias Brunner
- * 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 hashtable hashtable
- * @{ @ingroup utils
- */
-
-#ifndef HASHTABLE_H_
-#define HASHTABLE_H_
-
-#include <utils/enumerator.h>
-
-typedef struct hashtable_t hashtable_t;
-
-/**
- * Prototype for a function that computes the hash code from the given key.
- *
- * @param key key to hash
- * @return hash code
- */
-typedef u_int (*hashtable_hash_t)(void *key);
-
-/**
- * Prototype for a function that compares the two keys for equality.
- *
- * @param key first key (the one we are looking for)
- * @param other_key second key
- * @return TRUE if the keys are equal
- */
-typedef bool (*hashtable_equals_t)(void *key, void *other_key);
-
-/**
- * Class implementing a hash table.
- *
- * General purpose hash table. This hash table is not synchronized.
- */
-struct hashtable_t {
-
- /**
- * Create an enumerator over the hash table key/value pairs.
- *
- * @return enumerator over (void *key, void *value)
- */
- enumerator_t *(*create_enumerator) (hashtable_t *this);
-
- /**
- * Adds the given value with the given key to the hash table, if there
- * exists no entry with that key. NULL is returned in this case.
- * Otherwise the existing value is replaced and the function returns the
- * old value.
- *
- * @param key the key to store
- * @param value the value to store
- * @return NULL if no item was replaced, the old value otherwise
- */
- void *(*put) (hashtable_t *this, void *key, void *value);
-
- /**
- * Returns the value with the given key, if the hash table contains such an
- * entry, otherwise NULL is returned.
- *
- * @param key the key of the requested value
- * @return the value, NULL if not found
- */
- void *(*get) (hashtable_t *this, void *key);
-
- /**
- * Returns the value with a matching key, if the hash table contains such an
- * entry, otherwise NULL is returned.
- *
- * Compared to get() the given match function is used to compare the keys
- * for equality. The hash function does have to be deviced properly in
- * order to make this work if the match function compares keys differently
- * than the equals function provided to the constructor. This basically
- * allows to enumerate all entries with the same hash value.
- *
- * @param key the key to match against
- * @param match match function to be used when comparing keys
- * @return the value, NULL if not found
- */
- void *(*get_match) (hashtable_t *this, void *key, hashtable_equals_t match);
-
- /**
- * Removes the value with the given key from the hash table and returns the
- * removed value (or NULL if no such value existed).
- *
- * @param key the key of the value to remove
- * @return the removed value, NULL if not found
- */
- void *(*remove) (hashtable_t *this, void *key);
-
- /**
- * Removes the key and value pair from the hash table at which the given
- * enumerator currently points.
- *
- * @param enumerator enumerator, from create_enumerator
- */
- void (*remove_at) (hashtable_t *this, enumerator_t *enumerator);
-
- /**
- * Gets the number of items in the hash table.
- *
- * @return number of items
- */
- u_int (*get_count) (hashtable_t *this);
-
- /**
- * Destroys a hash table object.
- */
- void (*destroy) (hashtable_t *this);
-
-};
-
-/**
- * Creates an empty hash table object.
- *
- * @param hash hash function
- * @param equals equals function
- * @param capacity initial capacity
- * @return hashtable_t object.
- */
-hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
- u_int capacity);
-
-#endif /** HASHTABLE_H_ @}*/
diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c
deleted file mode 100644
index e17b6ad02..000000000
--- a/src/libstrongswan/utils/host.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
- * Copyright (C) 2006-2009 Tobias Brunner
- * Copyright (C) 2006 Daniel Roethlisberger
- * 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.
- */
-
-#define _GNU_SOURCE
-#include <sys/socket.h>
-#include <netdb.h>
-#include <string.h>
-
-#include "host.h"
-
-#include <debug.h>
-
-#define IPV4_LEN 4
-#define IPV6_LEN 16
-
-typedef struct private_host_t private_host_t;
-
-/**
- * Private Data of a host object.
- */
-struct private_host_t {
- /**
- * Public data
- */
- host_t public;
-
- /**
- * low-lewel structure, which stores the address
- */
- union {
- /** generic type */
- struct sockaddr address;
- /** maximum sockaddr size */
- struct sockaddr_storage address_max;
- /** IPv4 address */
- struct sockaddr_in address4;
- /** IPv6 address */
- struct sockaddr_in6 address6;
- };
- /**
- * length of address structure
- */
- socklen_t socklen;
-};
-
-
-METHOD(host_t, get_sockaddr, sockaddr_t*,
- private_host_t *this)
-{
- return &(this->address);
-}
-
-METHOD(host_t, get_sockaddr_len, socklen_t*,
- private_host_t *this)
-{
- return &(this->socklen);
-}
-
-METHOD(host_t, is_anyaddr, bool,
- private_host_t *this)
-{
- static const u_int8_t zeroes[IPV6_LEN];
-
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN);
- }
- case AF_INET6:
- {
- return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN);
- }
- default:
- {
- return FALSE;
- }
- }
-}
-
-/**
- * Described in header.
- */
-int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args)
-{
- private_host_t *this = *((private_host_t**)(args[0]));
- char buffer[INET6_ADDRSTRLEN + 16];
-
- if (this == NULL)
- {
- snprintf(buffer, sizeof(buffer), "(null)");
- }
- else if (is_anyaddr(this) && !spec->plus)
- {
- snprintf(buffer, sizeof(buffer), "%%any%s",
- this->address.sa_family == AF_INET6 ? "6" : "");
- }
- else
- {
- void *address;
- u_int16_t port;
- int len;
-
- address = &this->address6.sin6_addr;
- port = this->address6.sin6_port;
-
- switch (this->address.sa_family)
- {
- case AF_INET:
- address = &this->address4.sin_addr;
- port = this->address4.sin_port;
- /* fall */
- case AF_INET6:
-
- if (inet_ntop(this->address.sa_family, address,
- buffer, sizeof(buffer)) == NULL)
- {
- snprintf(buffer, sizeof(buffer),
- "(address conversion failed)");
- }
- else if (spec->hash)
- {
- len = strlen(buffer);
- snprintf(buffer + len, sizeof(buffer) - len,
- "[%d]", ntohs(port));
- }
- break;
- default:
- snprintf(buffer, sizeof(buffer), "(family not supported)");
- break;
- }
- }
- if (spec->minus)
- {
- return print_in_hook(data, "%-*s", spec->width, buffer);
- }
- return print_in_hook(data, "%*s", spec->width, buffer);
-}
-
-METHOD(host_t, get_address, chunk_t,
- private_host_t *this)
-{
- chunk_t address = chunk_empty;
-
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- address.ptr = (char*)&(this->address4.sin_addr.s_addr);
- address.len = IPV4_LEN;
- return address;
- }
- case AF_INET6:
- {
- address.ptr = (char*)&(this->address6.sin6_addr.s6_addr);
- address.len = IPV6_LEN;
- return address;
- }
- default:
- {
- /* return empty chunk */
- return address;
- }
- }
-}
-
-METHOD(host_t, get_family, int,
- private_host_t *this)
-{
- return this->address.sa_family;
-}
-
-METHOD(host_t, get_port, u_int16_t,
- private_host_t *this)
-{
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- return ntohs(this->address4.sin_port);
- }
- case AF_INET6:
- {
- return ntohs(this->address6.sin6_port);
- }
- default:
- {
- return 0;
- }
- }
-}
-
-METHOD(host_t, set_port, void,
- private_host_t *this, u_int16_t port)
-{
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- this->address4.sin_port = htons(port);
- break;
- }
- case AF_INET6:
- {
- this->address6.sin6_port = htons(port);
- break;
- }
- default:
- {
- break;
- }
- }
-}
-
-METHOD(host_t, clone_, host_t*,
- private_host_t *this)
-{
- private_host_t *new;
-
- new = malloc_thing(private_host_t);
- memcpy(new, this, sizeof(private_host_t));
-
- return &new->public;
-}
-
-/**
- * Implements host_t.ip_equals
- */
-static bool ip_equals(private_host_t *this, private_host_t *other)
-{
- if (this->address.sa_family != other->address.sa_family)
- {
- /* 0.0.0.0 and 0::0 are equal */
- return (is_anyaddr(this) && is_anyaddr(other));
- }
-
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- return memeq(&this->address4.sin_addr, &other->address4.sin_addr,
- sizeof(this->address4.sin_addr));
- }
- case AF_INET6:
- {
- return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr,
- sizeof(this->address6.sin6_addr));
- }
- default:
- break;
- }
- return FALSE;
-}
-
-/**
- * Implements host_t.get_differences
- */
-static host_diff_t get_differences(host_t *this, host_t *other)
-{
- host_diff_t ret = HOST_DIFF_NONE;
-
- if (!this->ip_equals(this, other))
- {
- ret |= HOST_DIFF_ADDR;
- }
-
- if (this->get_port(this) != other->get_port(other))
- {
- ret |= HOST_DIFF_PORT;
- }
-
- return ret;
-}
-
-/**
- * Implements host_t.equals
- */
-static bool equals(private_host_t *this, private_host_t *other)
-{
- if (!ip_equals(this, other))
- {
- return FALSE;
- }
-
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- return (this->address4.sin_port == other->address4.sin_port);
- }
- case AF_INET6:
- {
- return (this->address6.sin6_port == other->address6.sin6_port);
- }
- default:
- break;
- }
- return FALSE;
-}
-
-METHOD(host_t, destroy, void,
- private_host_t *this)
-{
- free(this);
-}
-
-/**
- * Creates an empty host_t object
- */
-static private_host_t *host_create_empty(void)
-{
- 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;
-}
-
-/*
- * Create a %any host with port
- */
-static host_t *host_create_any_port(int family, u_int16_t port)
-{
- host_t *this;
-
- this = host_create_any(family);
- this->set_port(this, port);
- return this;
-}
-
-/*
- * Described in header.
- */
-host_t *host_create_from_string(char *string, u_int16_t port)
-{
- private_host_t *this;
-
- if (streq(string, "%any"))
- {
- return host_create_any_port(AF_INET, port);
- }
- if (streq(string, "%any6"))
- {
- return host_create_any_port(AF_INET6, port);
- }
-
- this = host_create_empty();
- if (strchr(string, '.'))
- {
- this->address.sa_family = AF_INET;
- }
- else
- {
- this->address.sa_family = AF_INET6;
- }
- switch (this->address.sa_family)
- {
- case AF_INET:
- {
- if (inet_pton(AF_INET, string, &this->address4.sin_addr) <=0)
- {
- break;
- }
- this->address4.sin_port = htons(port);
- this->socklen = sizeof(struct sockaddr_in);
- return &this->public;
- }
- case AF_INET6:
- {
- if (inet_pton(AF_INET6, string, &this->address6.sin6_addr) <=0)
- {
- break;
- }
- this->address6.sin6_port = htons(port);
- this->socklen = sizeof(struct sockaddr_in6);
- return &this->public;
- }
- default:
- {
- break;
- }
- }
- free(this);
- return NULL;
-}
-
-/*
- * Described in header.
- */
-host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
-{
- private_host_t *this = host_create_empty();
-
- switch (sockaddr->sa_family)
- {
- case AF_INET:
- {
- memcpy(&this->address4, (struct sockaddr_in*)sockaddr,
- sizeof(struct sockaddr_in));
- this->socklen = sizeof(struct sockaddr_in);
- return &this->public;
- }
- case AF_INET6:
- {
- memcpy(&this->address6, (struct sockaddr_in6*)sockaddr,
- sizeof(struct sockaddr_in6));
- this->socklen = sizeof(struct sockaddr_in6);
- return &this->public;
- }
- default:
- break;
- }
- free(this);
- return NULL;
-}
-
-/*
- * Described in header.
- */
-host_t *host_create_from_dns(char *string, int af, u_int16_t port)
-{
- private_host_t *this;
- struct addrinfo hints, *result;
- int error;
-
- if (streq(string, "%any"))
- {
- return host_create_any_port(af ? af : AF_INET, port);
- }
- if (streq(string, "%any6"))
- {
- return host_create_any_port(af ? af : AF_INET6, port);
- }
- if (af == AF_INET && strchr(string, ':'))
- { /* do not try to convert v6 addresses for v4 family */
- return NULL;
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = af;
- error = getaddrinfo(string, NULL, &hints, &result);
- if (error != 0)
- {
- DBG1(DBG_LIB, "resolving '%s' failed: %s", string, gai_strerror(error));
- return NULL;
- }
- /* result is a linked list, but we use only the first address */
- this = (private_host_t*)host_create_from_sockaddr(result->ai_addr);
- freeaddrinfo(result);
- if (this)
- {
- switch (this->address.sa_family)
- {
- case AF_INET:
- this->address4.sin_port = htons(port);
- break;
- case AF_INET6:
- this->address6.sin6_port = htons(port);
- break;
- }
- return &this->public;
- }
- return NULL;
-}
-
-/*
- * Described in header.
- */
-host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
-{
- private_host_t *this;
-
- switch (family)
- {
- case AF_INET:
- if (address.len < IPV4_LEN)
- {
- return NULL;
- }
- address.len = IPV4_LEN;
- break;
- case AF_INET6:
- if (address.len < IPV6_LEN)
- {
- return NULL;
- }
- address.len = IPV6_LEN;
- break;
- case AF_UNSPEC:
- switch (address.len)
- {
- case IPV4_LEN:
- family = AF_INET;
- break;
- case IPV6_LEN:
- family = AF_INET6;
- break;
- default:
- return NULL;
- }
- break;
- default:
- return NULL;
- }
- this = host_create_empty();
- this->address.sa_family = family;
- switch (family)
- {
- case AF_INET:
- memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len);
- this->address4.sin_port = htons(port);
- this->socklen = sizeof(struct sockaddr_in);
- break;
- case AF_INET6:
- memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len);
- this->address6.sin6_port = htons(port);
- this->socklen = sizeof(struct sockaddr_in6);
- break;
- }
- return &this->public;
-}
-
-/*
- * Described in header.
- */
-host_t *host_create_from_subnet(char *string, int *bits)
-{
- char *pos, buf[64];
- host_t *net;
-
- pos = strchr(string, '/');
- if (pos)
- {
- if (pos - string >= sizeof(buf))
- {
- return NULL;
- }
- strncpy(buf, string, pos - string);
- buf[pos - string] = '\0';
- *bits = atoi(pos + 1);
- return host_create_from_string(buf, 0);
- }
- net = host_create_from_string(string, 0);
- if (net)
- {
- if (net->get_family(net) == AF_INET)
- {
- *bits = 32;
- }
- else
- {
- *bits = 128;
- }
- }
- return net;
-}
-
-/*
- * Described in header.
- */
-host_t *host_create_any(int family)
-{
- private_host_t *this = host_create_empty();
-
- memset(&this->address_max, 0, sizeof(struct sockaddr_storage));
- this->address.sa_family = family;
-
- switch (family)
- {
- case AF_INET:
- {
- this->socklen = sizeof(struct sockaddr_in);
- return &(this->public);
- }
- case AF_INET6:
- {
- this->socklen = sizeof(struct sockaddr_in6);
- return &this->public;
- }
- default:
- break;
- }
- free(this);
- return NULL;
-}
diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h
deleted file mode 100644
index a8b010544..000000000
--- a/src/libstrongswan/utils/host.h
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2006-2009 Tobias Brunner
- * Copyright (C) 2006 Daniel Roethlisberger
- * Copyright (C) 2005-2008 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 host host
- * @{ @ingroup utils
- */
-
-#ifndef HOST_H_
-#define HOST_H_
-
-typedef enum host_diff_t host_diff_t;
-typedef struct host_t host_t;
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <chunk.h>
-
-/**
- * Differences between two hosts. They differ in
- * address, port, or both.
- */
-enum host_diff_t {
- HOST_DIFF_NONE = 0,
- HOST_DIFF_ADDR = 1,
- HOST_DIFF_PORT = 2,
-};
-
-/**
- * Representates a Host
- *
- * Host object, identifies a address:port pair and defines some
- * useful functions on it.
- */
-struct host_t {
-
- /**
- * Build a clone of this host object.
- *
- * @return cloned host
- */
- host_t *(*clone) (host_t *this);
-
- /**
- * Get a pointer to the internal sockaddr struct.
- *
- * This is used for sending and receiving via sockets.
- *
- * @return pointer to the internal sockaddr structure
- */
- sockaddr_t *(*get_sockaddr) (host_t *this);
-
- /**
- * Get the length of the sockaddr struct.
- *
- * Depending on the family, the length of the sockaddr struct
- * is different. Use this function to get the length of the sockaddr
- * struct returned by get_sock_addr.
- *
- * This is used for sending and receiving via sockets.
- *
- * @return length of the sockaddr struct
- */
- socklen_t *(*get_sockaddr_len) (host_t *this);
-
- /**
- * Gets the family of the address
- *
- * @return family
- */
- int (*get_family) (host_t *this);
-
- /**
- * Checks if the ip address of host is set to default route.
- *
- * @return TRUE if host is 0.0.0.0 or 0::0, FALSE otherwise
- */
- bool (*is_anyaddr) (host_t *this);
-
- /**
- * Get the address of this host as chunk_t
- *
- * Returned chunk points to internal data.
- *
- * @return address string,
- */
- chunk_t (*get_address) (host_t *this);
-
- /**
- * Get the port of this host
- *
- * @return port number
- */
- u_int16_t (*get_port) (host_t *this);
-
- /**
- * Set the port of this host
- *
- * @param port port numer
- */
- void (*set_port) (host_t *this, u_int16_t port);
-
- /**
- * Compare the ips of two hosts hosts.
- *
- * @param other the other to compare
- * @return TRUE if addresses are equal.
- */
- bool (*ip_equals) (host_t *this, host_t *other);
-
- /**
- * Compare two hosts, with port.
- *
- * @param other the other to compare
- * @return TRUE if addresses and ports are equal.
- */
- bool (*equals) (host_t *this, host_t *other);
-
- /**
- * Compare two hosts and return the differences.
- *
- * @param other the other to compare
- * @return differences in a combination of host_diff_t's
- */
- host_diff_t (*get_differences) (host_t *this, host_t *other);
-
- /**
- * Destroy this host object.
- */
- void (*destroy) (host_t *this);
-};
-
-/**
- * Constructor to create a host_t object from an address string.
- *
- * @param string string of an address, such as "152.96.193.130"
- * @param port port number
- * @return host_t, NULL if string not an address.
- */
-host_t *host_create_from_string(char *string, u_int16_t port);
-
-/**
- * Constructor to create a host_t from a DNS name.
- *
- * @param string hostname to resolve
- * @param family family to prefer, 0 for first match
- * @param port port number
- * @return host_t, NULL lookup failed
- */
-host_t *host_create_from_dns(char *string, int family, u_int16_t port);
-
-/**
- * Constructor to create a host_t object from an address chunk.
- *
- * If family is AF_UNSPEC, it is guessed using address.len.
- *
- * @param family Address family, such as AF_INET or AF_INET6
- * @param address address as chunk_t in network order
- * @param port port number
- * @return host_t, NULL if family not supported/chunk invalid
- */
-host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port);
-
-/**
- * Constructor to create a host_t object from a sockaddr struct
- *
- * @param sockaddr sockaddr struct which contains family, address and port
- * @return host_t, NULL if family not supported
- */
-host_t *host_create_from_sockaddr(sockaddr_t *sockaddr);
-
-/**
- * Create a host from a CIDR subnet definition (1.2.3.0/24), return bits.
- *
- * @param string string to parse
- * @param bits gets the number of network bits in CIDR notation
- * @return network start address, NULL on error
- */
-host_t *host_create_from_subnet(char *string, int *bits);
-
-/**
- * Create a host without an address, a "any" host.
- *
- * @param family family of the any host
- * @return host_t, NULL if family not supported
- */
-host_t *host_create_any(int family);
-
-/**
- * printf hook function for host_t.
- *
- * Arguments are:
- * host_t *host
- * Use #-modifier to include port number
- * Use +-modifier to force numeric representation (instead of e.g. %any)
- */
-int host_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args);
-
-#endif /** HOST_H_ @}*/
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index 024fcea4b..cdf229127 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -29,8 +29,8 @@ typedef struct identification_t identification_t;
typedef enum id_match_t id_match_t;
typedef enum id_part_t id_part_t;
-#include <chunk.h>
-#include <utils/enumerator.h>
+#include <utils/chunk.h>
+#include <collections/enumerator.h>
/**
* Matches returned from identification_t.match
diff --git a/src/libstrongswan/utils/integrity_checker.c b/src/libstrongswan/utils/integrity_checker.c
new file mode 100644
index 000000000..e962aba70
--- /dev/null
+++ b/src/libstrongswan/utils/integrity_checker.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include "integrity_checker.h"
+
+#include <dlfcn.h>
+#include <link.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "debug.h"
+#include "library.h"
+
+typedef struct private_integrity_checker_t private_integrity_checker_t;
+
+/**
+ * Private data of an integrity_checker_t object.
+ */
+struct private_integrity_checker_t {
+
+ /**
+ * Public integrity_checker_t interface.
+ */
+ integrity_checker_t public;
+
+ /**
+ * dlopen handle to checksum library
+ */
+ void *handle;
+
+ /**
+ * checksum array
+ */
+ integrity_checksum_t *checksums;
+
+ /**
+ * number of checksums in array
+ */
+ int checksum_count;
+};
+
+METHOD(integrity_checker_t, build_file, u_int32_t,
+ private_integrity_checker_t *this, char *file, size_t *len)
+{
+ u_int32_t checksum;
+ chunk_t contents;
+ struct stat sb;
+ void *addr;
+ int fd;
+
+ fd = open(file, O_RDONLY);
+ if (fd == -1)
+ {
+ DBG1(DBG_LIB, " opening '%s' failed: %s", file, strerror(errno));
+ return 0;
+ }
+
+ if (fstat(fd, &sb) == -1)
+ {
+ DBG1(DBG_LIB, " getting file size of '%s' failed: %s", file,
+ strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ addr = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (addr == MAP_FAILED)
+ {
+ DBG1(DBG_LIB, " mapping '%s' failed: %s", file, strerror(errno));
+ close(fd);
+ return 0;
+ }
+
+ *len = sb.st_size;
+ contents = chunk_create(addr, sb.st_size);
+ checksum = chunk_hash(contents);
+
+ munmap(addr, sb.st_size);
+ close(fd);
+
+ return checksum;
+}
+
+/**
+ * dl_iterate_phdr callback function
+ */
+static int callback(struct dl_phdr_info *dlpi, size_t size, Dl_info *dli)
+{
+ /* We are looking for the dlpi_addr matching the address of our dladdr().
+ * dl_iterate_phdr() returns such an address for other (unknown) objects
+ * in very rare cases (e.g. in a chrooted gentoo, but only if
+ * the checksum_builder is invoked by 'make'). As a workaround, we filter
+ * objects by dlpi_name; valid objects have a library name.
+ */
+ if (dli->dli_fbase == (void*)dlpi->dlpi_addr &&
+ dlpi->dlpi_name && *dlpi->dlpi_name)
+ {
+ int i;
+
+ for (i = 0; i < dlpi->dlpi_phnum; i++)
+ {
+ const ElfW(Phdr) *sgmt = &dlpi->dlpi_phdr[i];
+
+ /* we are interested in the executable LOAD segment */
+ if (sgmt->p_type == PT_LOAD && (sgmt->p_flags & PF_X))
+ {
+ /* safe begin of segment in dli_fbase */
+ dli->dli_fbase = (void*)sgmt->p_vaddr + dlpi->dlpi_addr;
+ /* safe end of segment in dli_saddr */
+ dli->dli_saddr = dli->dli_fbase + sgmt->p_memsz;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+METHOD(integrity_checker_t, build_segment, u_int32_t,
+ private_integrity_checker_t *this, void *sym, size_t *len)
+{
+ chunk_t segment;
+ Dl_info dli;
+
+ if (dladdr(sym, &dli) == 0)
+ {
+ DBG1(DBG_LIB, " unable to locate symbol: %s", dlerror());
+ return 0;
+ }
+ /* we reuse the Dl_info struct as in/out parameter */
+ if (!dl_iterate_phdr((void*)callback, &dli))
+ {
+ DBG1(DBG_LIB, " executable section not found");
+ return 0;
+ }
+
+ segment = chunk_create(dli.dli_fbase, dli.dli_saddr - dli.dli_fbase);
+ *len = segment.len;
+ return chunk_hash(segment);
+}
+
+/**
+ * Find a checksum by its name
+ */
+static integrity_checksum_t *find_checksum(private_integrity_checker_t *this,
+ char *name)
+{
+ int i;
+
+ for (i = 0; i < this->checksum_count; i++)
+ {
+ if (streq(this->checksums[i].name, name))
+ {
+ return &this->checksums[i];
+ }
+ }
+ return NULL;
+}
+
+METHOD(integrity_checker_t, check_file, bool,
+ private_integrity_checker_t *this, char *name, char *file)
+{
+ integrity_checksum_t *cs;
+ u_int32_t sum;
+ size_t len = 0;
+
+ cs = find_checksum(this, name);
+ if (!cs)
+ {
+ DBG1(DBG_LIB, " '%s' file checksum not found", name);
+ return FALSE;
+ }
+ sum = build_file(this, file, &len);
+ if (!sum)
+ {
+ return FALSE;
+ }
+ if (cs->file_len != len)
+ {
+ DBG1(DBG_LIB, " invalid '%s' file size: %u bytes, expected %u bytes",
+ name, len, cs->file_len);
+ return FALSE;
+ }
+ if (cs->file != sum)
+ {
+ DBG1(DBG_LIB, " invalid '%s' file checksum: %08x, expected %08x",
+ name, sum, cs->file);
+ return FALSE;
+ }
+ DBG2(DBG_LIB, " valid '%s' file checksum: %08x", name, sum);
+ return TRUE;
+}
+
+METHOD(integrity_checker_t, check_segment, bool,
+ private_integrity_checker_t *this, char *name, void *sym)
+{
+ integrity_checksum_t *cs;
+ u_int32_t sum;
+ size_t len = 0;
+
+ cs = find_checksum(this, name);
+ if (!cs)
+ {
+ DBG1(DBG_LIB, " '%s' segment checksum not found", name);
+ return FALSE;
+ }
+ sum = build_segment(this, sym, &len);
+ if (!sum)
+ {
+ return FALSE;
+ }
+ if (cs->segment_len != len)
+ {
+ DBG1(DBG_LIB, " invalid '%s' segment size: %u bytes,"
+ " expected %u bytes", name, len, cs->segment_len);
+ return FALSE;
+ }
+ if (cs->segment != sum)
+ {
+ DBG1(DBG_LIB, " invalid '%s' segment checksum: %08x, expected %08x",
+ name, sum, cs->segment);
+ return FALSE;
+ }
+ DBG2(DBG_LIB, " valid '%s' segment checksum: %08x", name, sum);
+ return TRUE;
+}
+
+METHOD(integrity_checker_t, check, bool,
+ private_integrity_checker_t *this, char *name, void *sym)
+{
+ Dl_info dli;
+
+ if (dladdr(sym, &dli) == 0)
+ {
+ DBG1(DBG_LIB, "unable to locate symbol: %s", dlerror());
+ return FALSE;
+ }
+ if (!check_file(this, name, (char*)dli.dli_fname))
+ {
+ return FALSE;
+ }
+ if (!check_segment(this, name, sym))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+METHOD(integrity_checker_t, destroy, void,
+ private_integrity_checker_t *this)
+{
+ if (this->handle)
+ {
+ dlclose(this->handle);
+ }
+ free(this);
+}
+
+/**
+ * See header
+ */
+integrity_checker_t *integrity_checker_create(char *checksum_library)
+{
+ private_integrity_checker_t *this;
+
+ INIT(this,
+ .public = {
+ .check_file = _check_file,
+ .build_file = _build_file,
+ .check_segment = _check_segment,
+ .build_segment = _build_segment,
+ .check = _check,
+ .destroy = _destroy,
+ },
+ );
+
+ if (checksum_library)
+ {
+ this->handle = dlopen(checksum_library, RTLD_LAZY);
+ if (this->handle)
+ {
+ int *checksum_count;
+
+ this->checksums = dlsym(this->handle, "checksums");
+ checksum_count = dlsym(this->handle, "checksum_count");
+ if (this->checksums && checksum_count)
+ {
+ this->checksum_count = *checksum_count;
+ }
+ else
+ {
+ DBG1(DBG_LIB, "checksum library '%s' invalid",
+ checksum_library);
+ }
+ }
+ else
+ {
+ DBG1(DBG_LIB, "loading checksum library '%s' failed",
+ checksum_library);
+ }
+ }
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/utils/integrity_checker.h b/src/libstrongswan/utils/integrity_checker.h
new file mode 100644
index 000000000..afaa114b3
--- /dev/null
+++ b/src/libstrongswan/utils/integrity_checker.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2009 Martin Willi
+ * 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 integrity_checker integrity_checker
+ * @{ @ingroup utils
+ */
+
+#ifndef INTEGRITY_CHECKER_H_
+#define INTEGRITY_CHECKER_H_
+
+#include "utils.h"
+
+typedef struct integrity_checker_t integrity_checker_t;
+typedef struct integrity_checksum_t integrity_checksum_t;
+
+/**
+ * Struct to hold a precalculated checksum, implemented in the checksum library.
+ */
+struct integrity_checksum_t {
+ /* name of the checksum */
+ char *name;
+ /* size in bytes of the file on disk */
+ size_t file_len;
+ /* checksum of the file on disk */
+ u_int32_t file;
+ /* size in bytes of executable segment in memory */
+ size_t segment_len;
+ /* checksum of the executable segment in memory */
+ u_int32_t segment;
+};
+
+/**
+ * Code integrity checker to detect non-malicious file manipulation.
+ *
+ * The integrity checker reads the checksums from a separate library
+ * libchecksum.so to compare the checksums.
+ */
+struct integrity_checker_t {
+
+ /**
+ * Check the integrity of a file on disk.
+ *
+ * @param name name to lookup checksum
+ * @param file path to file
+ * @return TRUE if integrity tested successfully
+ */
+ bool (*check_file)(integrity_checker_t *this, char *name, char *file);
+
+ /**
+ * Build the integrity checksum of a file on disk.
+ *
+ * @param file path to file
+ * @param len return length in bytes of file
+ * @return checksum, 0 on error
+ */
+ u_int32_t (*build_file)(integrity_checker_t *this, char *file, size_t *len);
+
+ /**
+ * Check the integrity of the code segment in memory.
+ *
+ * @param name name to lookup checksum
+ * @param sym a symbol in the segment to check
+ * @return TRUE if integrity tested successfully
+ */
+ bool (*check_segment)(integrity_checker_t *this, char *name, void *sym);
+ /**
+ * Build the integrity checksum of a code segment in memory.
+ *
+ * @param sym a symbol in the segment to check
+ * @param len return length in bytes of code segment in memory
+ * @return checksum, 0 on error
+ */
+ u_int32_t (*build_segment)(integrity_checker_t *this, void *sym, size_t *len);
+
+ /**
+ * Check both, on disk file integrity and loaded segment.
+ *
+ * @param name name to lookup checksum
+ * @param sym a symbol to look up library and segment
+ * @return TRUE if integrity tested successfully
+ */
+ bool (*check)(integrity_checker_t *this, char *name, void *sym);
+
+ /**
+ * Destroy a integrity_checker_t.
+ */
+ void (*destroy)(integrity_checker_t *this);
+};
+
+/**
+ * Create a integrity_checker instance.
+ *
+ * @param checksum_library library containing checksums
+ */
+integrity_checker_t *integrity_checker_create(char *checksum_library);
+
+#endif /** INTEGRITY_CHECKER_H_ @}*/
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index cface0538..2b0be1661 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -32,9 +32,9 @@
#include "leak_detective.h"
#include <library.h>
-#include <debug.h>
+#include <utils/debug.h>
#include <utils/backtrace.h>
-#include <utils/hashtable.h>
+#include <collections/hashtable.h>
typedef struct private_leak_detective_t private_leak_detective_t;
diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c
deleted file mode 100644
index 1ff80999b..000000000
--- a/src/libstrongswan/utils/linked_list.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Copyright (C) 2007-2011 Tobias Brunner
- * 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.
- */
-
-#include <stdlib.h>
-#include <stdarg.h>
-
-#include "linked_list.h"
-
-typedef struct element_t element_t;
-
-/**
- * This element holds a pointer to the value it represents.
- */
-struct element_t {
-
- /**
- * Value of a list item.
- */
- void *value;
-
- /**
- * Previous list element.
- *
- * NULL if first element in list.
- */
- element_t *previous;
-
- /**
- * Next list element.
- *
- * NULL if last element in list.
- */
- element_t *next;
-};
-
-/**
- * Creates an empty linked list object.
- */
-element_t *element_create(void *value)
-{
- element_t *this;
- INIT(this,
- .value = value,
- );
- return this;
-}
-
-
-typedef struct private_linked_list_t private_linked_list_t;
-
-/**
- * Private data of a linked_list_t object.
- *
- */
-struct private_linked_list_t {
- /**
- * Public part of linked list.
- */
- linked_list_t public;
-
- /**
- * Number of items in the list.
- */
- int count;
-
- /**
- * First element in list.
- * NULL if no elements in list.
- */
- element_t *first;
-
- /**
- * Last element in list.
- * NULL if no elements in list.
- */
- element_t *last;
-};
-
-typedef struct private_enumerator_t private_enumerator_t;
-
-/**
- * linked lists enumerator implementation
- */
-struct private_enumerator_t {
-
- /**
- * implements enumerator interface
- */
- enumerator_t enumerator;
-
- /**
- * associated linked list
- */
- private_linked_list_t *list;
-
- /**
- * current item
- */
- element_t *current;
-
- /**
- * enumerator has enumerated all items
- */
- bool finished;
-};
-
-METHOD(enumerator_t, enumerate, bool,
- private_enumerator_t *this, void **item)
-{
- if (this->finished)
- {
- return FALSE;
- }
- if (!this->current)
- {
- this->current = this->list->first;
- }
- else
- {
- this->current = this->current->next;
- }
- if (!this->current)
- {
- this->finished = TRUE;
- return FALSE;
- }
- *item = this->current->value;
- return TRUE;
-}
-
-METHOD(linked_list_t, create_enumerator, enumerator_t*,
- private_linked_list_t *this)
-{
- private_enumerator_t *enumerator;
-
- INIT(enumerator,
- .enumerator = {
- .enumerate = (void*)_enumerate,
- .destroy = (void*)free,
- },
- .list = this,
- );
-
- return &enumerator->enumerator;
-}
-
-METHOD(linked_list_t, reset_enumerator, void,
- private_linked_list_t *this, private_enumerator_t *enumerator)
-{
- enumerator->current = NULL;
- enumerator->finished = FALSE;
-}
-
-METHOD(linked_list_t, has_more, bool,
- private_linked_list_t *this, private_enumerator_t *enumerator)
-{
- if (enumerator->current)
- {
- return enumerator->current->next != NULL;
- }
- return !enumerator->finished && this->first != NULL;
-}
-
-METHOD(linked_list_t, get_count, int,
- private_linked_list_t *this)
-{
- return this->count;
-}
-
-METHOD(linked_list_t, insert_first, void,
- private_linked_list_t *this, void *item)
-{
- element_t *element;
-
- element = element_create(item);
- if (this->count == 0)
- {
- /* first entry in list */
- this->first = element;
- this->last = element;
- }
- else
- {
- element->next = this->first;
- this->first->previous = element;
- this->first = element;
- }
- this->count++;
-}
-
-/**
- * unlink an element form the list, returns following element
- */
-static element_t* remove_element(private_linked_list_t *this,
- element_t *element)
-{
- element_t *next, *previous;
-
- next = element->next;
- previous = element->previous;
- free(element);
- if (next)
- {
- next->previous = previous;
- }
- else
- {
- this->last = previous;
- }
- if (previous)
- {
- previous->next = next;
- }
- else
- {
- this->first = next;
- }
- if (--this->count == 0)
- {
- this->first = NULL;
- this->last = NULL;
- }
- return next;
-}
-
-METHOD(linked_list_t, get_first, status_t,
- private_linked_list_t *this, void **item)
-{
- if (this->count == 0)
- {
- return NOT_FOUND;
- }
- *item = this->first->value;
- return SUCCESS;
-}
-
-METHOD(linked_list_t, remove_first, status_t,
- private_linked_list_t *this, void **item)
-{
- if (get_first(this, item) == SUCCESS)
- {
- remove_element(this, this->first);
- return SUCCESS;
- }
- return NOT_FOUND;
-}
-
-METHOD(linked_list_t, insert_last, void,
- private_linked_list_t *this, void *item)
-{
- element_t *element;
-
- element = element_create(item);
- if (this->count == 0)
- {
- /* first entry in list */
- this->first = element;
- this->last = element;
- }
- else
- {
- element->previous = this->last;
- this->last->next = element;
- this->last = element;
- }
- this->count++;
-}
-
-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)
- {
- return NOT_FOUND;
- }
- *item = this->last->value;
- return SUCCESS;
-}
-
-METHOD(linked_list_t, remove_last, status_t,
- private_linked_list_t *this, void **item)
-{
- if (get_last(this, item) == SUCCESS)
- {
- remove_element(this, this->last);
- return SUCCESS;
- }
- return NOT_FOUND;
-}
-
-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;
-
- while (current)
- {
- if ((compare && compare(current->value, item)) ||
- (!compare && current->value == item))
- {
- removed++;
- current = remove_element(this, current);
- }
- else
- {
- current = current->next;
- }
- }
- return removed;
-}
-
-METHOD(linked_list_t, remove_at, void,
- private_linked_list_t *this, private_enumerator_t *enumerator)
-{
- element_t *current;
-
- if (enumerator->current)
- {
- current = enumerator->current;
- enumerator->current = current->previous;
- remove_element(this, current);
- }
-}
-
-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;
-
- while (current)
- {
- if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
- (!match && item && current->value == *item))
- {
- if (item != NULL)
- {
- *item = current->value;
- }
- return SUCCESS;
- }
- current = current->next;
- }
- return NOT_FOUND;
-}
-
-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;
-
- while (current)
- {
- if ((match && match(current->value, d1, d2, d3, d4, d5)) ||
- (!match && item && current->value == *item))
- {
- if (item != NULL)
- {
- *item = current->value;
- }
- return SUCCESS;
- }
- current = current->previous;
- }
- return NOT_FOUND;
-}
-
-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)
- {
- method = current->value + offset;
- (*method)(current->value, d1, d2, d3, d4, d5);
- current = current->next;
- }
-}
-
-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;
-
- while (current)
- {
- fn(current->value, d1, d2, d3, d4, d5);
- current = current->next;
- }
-}
-
-METHOD(linked_list_t, clone_offset, linked_list_t*,
- private_linked_list_t *this, size_t offset)
-{
- element_t *current = this->first;
- linked_list_t *clone;
-
- clone = linked_list_create();
- while (current)
- {
- void* (**method)(void*) = current->value + offset;
- clone->insert_last(clone, (*method)(current->value));
- current = current->next;
- }
-
- return clone;
-}
-
-METHOD(linked_list_t, clone_function, linked_list_t*,
- private_linked_list_t *this, void* (*fn)(void*))
-{
- 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;
-}
-
-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)
- {
- /* values are not destroyed so memory leaks are possible
- * if list is not empty when deleting */
- }
- free(this);
-}
-
-METHOD(linked_list_t, destroy_offset, void,
- private_linked_list_t *this, size_t offset)
-{
- element_t *current = this->first, *next;
-
- while (current)
- {
- void (**method)(void*) = current->value + offset;
- (*method)(current->value);
- next = current->next;
- free(current);
- current = next;
- }
- free(this);
-}
-
-METHOD(linked_list_t, destroy_function, void,
- private_linked_list_t *this, void (*fn)(void*))
-{
- element_t *current = this->first, *next;
-
- while (current)
- {
- fn(current->value);
- next = current->next;
- free(current);
- current = next;
- }
- free(this);
-}
-
-/*
- * Described in header.
- */
-linked_list_t *linked_list_create()
-{
- 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;
-}
-
-/*
- * See header.
- */
-linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator)
-{
- linked_list_t *list;
- void *item;
-
- list = linked_list_create();
-
- while (enumerator->enumerate(enumerator, &item))
- {
- list->insert_last(list, item);
- }
- enumerator->destroy(enumerator);
-
- return list;
-}
-
-/*
- * See header.
- */
-linked_list_t *linked_list_create_with_items(void *item, ...)
-{
- linked_list_t *list;
- va_list args;
-
- list = linked_list_create();
-
- va_start(args, item);
- while (item)
- {
- list->insert_last(list, item);
- item = va_arg(args, void*);
- }
- va_end(args);
-
- return list;
-}
diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h
deleted file mode 100644
index 1b5518480..000000000
--- a/src/libstrongswan/utils/linked_list.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * Copyright (C) 2007-2011 Tobias Brunner
- * Copyright (C) 2005-2008 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 linked_list linked_list
- * @{ @ingroup utils
- */
-
-#ifndef LINKED_LIST_H_
-#define LINKED_LIST_H_
-
-typedef struct linked_list_t linked_list_t;
-
-#include <utils/enumerator.h>
-
-/**
- * Method to match elements in a linked list (used in find_* functions)
- *
- * @param item current list item
- * @param ... user supplied data (only pointers, at most 5)
- * @return
- * - TRUE, if the item matched
- * - FALSE, otherwise
- */
-typedef bool (*linked_list_match_t)(void *item, ...);
-
-/**
- * Method to be invoked on elements in a linked list (used in invoke_* functions)
- *
- * @param item current list item
- * @param ... user supplied data (only pointers, at most 5)
- */
-typedef void (*linked_list_invoke_t)(void *item, ...);
-
-/**
- * Class implementing a double linked list.
- *
- * General purpose linked list. This list is not synchronized.
- */
-struct linked_list_t {
-
- /**
- * Gets the count of items in the list.
- *
- * @return number of items in list
- */
- int (*get_count) (linked_list_t *this);
-
- /**
- * Create an enumerator over the list.
- *
- * @note The enumerator's position is invalid before the first call
- * to enumerate().
- *
- * @return enumerator over list items
- */
- enumerator_t* (*create_enumerator)(linked_list_t *this);
-
- /**
- * Resets the enumerator's current position to the beginning of the list.
- *
- * @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.
- *
- * @param enumerator enumerator to check
- */
- bool (*has_more)(linked_list_t *this, enumerator_t *enumerator);
-
- /**
- * Inserts a new item at the beginning of the list.
- *
- * @param item item value to insert in list
- */
- void (*insert_first) (linked_list_t *this, void *item);
-
- /**
- * Removes the first item in the list and returns its value.
- *
- * @param item returned value of first item, or NULL
- * @return SUCCESS, or NOT_FOUND if list is empty
- */
- 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
- */
- void (*remove_at)(linked_list_t *this, enumerator_t *enumerator);
-
- /**
- * Remove items from the list matching the given item.
- *
- * If a compare function is given, it is called for each item, with the
- * first parameter being the current list item and the second parameter
- * being the supplied item. Return TRUE from the compare function to remove
- * the item, return FALSE to keep it in the list.
- *
- * If compare is NULL, comparison is done by pointers.
- *
- * @param item item to remove/pass to comparator
- * @param compare compare function, or NULL
- * @return number of removed items
- */
- int (*remove)(linked_list_t *this, void *item, bool (*compare)(void*,void*));
-
- /**
- * Returns the value of the first list item without removing it.
- *
- * @param item returned value of first item
- * @return SUCCESS, NOT_FOUND if list is empty
- */
- status_t (*get_first) (linked_list_t *this, void **item);
-
- /**
- * Inserts a new item at the end of the list.
- *
- * @param item value to insert into list
- */
- void (*insert_last) (linked_list_t *this, void *item);
-
- /**
- * Removes the last item in the list and returns its value.
- *
- * @param item returned value of last item, or NULL
- * @return SUCCESS, NOT_FOUND if list is empty
- */
- status_t (*remove_last) (linked_list_t *this, void **item);
-
- /**
- * Returns the value of the last list item without removing it.
- *
- * @param item returned value of last item
- * @return SUCCESS, NOT_FOUND if list is empty
- */
- status_t (*get_last) (linked_list_t *this, void **item);
-
- /** Find the first matching element in the list.
- *
- * The first object passed to the match function is the current list item,
- * followed by the user supplied data.
- * If the supplied function returns TRUE this function returns SUCCESS, and
- * the current object is returned in the third parameter, otherwise,
- * the next item is checked.
- *
- * If match is NULL, *item and the current object are compared.
- *
- * @warning Only use pointers as user supplied data.
- *
- * @param match comparison function to call on each object, or NULL
- * @param item the list item, if found
- * @param ... user data to supply to match function (limited to 5 arguments)
- * @return SUCCESS if found, NOT_FOUND otherwise
- */
- status_t (*find_first) (linked_list_t *this, linked_list_match_t match,
- void **item, ...);
-
- /** Find the last matching element in the list.
- *
- * The first object passed to the match function is the current list item,
- * followed by the user supplied data.
- * If the supplied function returns TRUE this function returns SUCCESS, and
- * the current object is returned in the third parameter, otherwise,
- * the next item is checked.
- *
- * If match is NULL, *item and the current object are compared.
- *
- * @warning Only use pointers as user supplied data.
- *
- * @param match comparison function to call on each object, or NULL
- * @param item the list item, if found
- * @param ... user data to supply to match function (limited to 5 arguments)
- * @return SUCCESS if found, NOT_FOUND otherwise
- */
- status_t (*find_last) (linked_list_t *this, linked_list_match_t match,
- void **item, ...);
-
- /**
- * Invoke a method on all of the contained objects.
- *
- * If a linked list contains objects with function pointers,
- * invoke() can call a method on each of the objects. The
- * method is specified by an offset of the function pointer,
- * which can be evalutated at compile time using the offsetof
- * macro, e.g.: list->invoke(list, offsetof(object_t, method));
- *
- * @warning Only use pointers as user supplied data.
- *
- * @param offset offset of the method to invoke on objects
- * @param ... user data to supply to called function (limited to 5 arguments)
- */
- void (*invoke_offset) (linked_list_t *this, size_t offset, ...);
-
- /**
- * Invoke a function on all of the contained objects.
- *
- * @warning Only use pointers as user supplied data.
- *
- * @param function offset of the method to invoke on objects
- * @param ... user data to supply to called function (limited to 5 arguments)
- */
- void (*invoke_function) (linked_list_t *this, linked_list_invoke_t function, ...);
-
- /**
- * Clones a list and its objects using the objects' clone method.
- *
- * @param offset offset ot the objects clone function
- * @return cloned list
- */
- linked_list_t *(*clone_offset) (linked_list_t *this, size_t offset);
-
- /**
- * Clones a list and its objects using a given function.
- *
- * @param function function that clones an object
- * @return cloned list
- */
- linked_list_t *(*clone_function) (linked_list_t *this, void*(*)(void*));
-
- /**
- * Destroys a linked_list object.
- */
- void (*destroy) (linked_list_t *this);
-
- /**
- * Destroys a list and its objects using the destructor.
- *
- * If a linked list and the contained objects should be destroyed, use
- * destroy_offset. The supplied offset specifies the destructor to
- * call on each object. The offset may be calculated using the offsetof
- * macro, e.g.: list->destroy_offset(list, offsetof(object_t, destroy));
- *
- * @param offset offset of the objects destructor
- */
- void (*destroy_offset) (linked_list_t *this, size_t offset);
-
- /**
- * Destroys a list and its contents using a a cleanup function.
- *
- * If a linked list and its contents should get destroyed using a specific
- * cleanup function, use destroy_function. This is useful when the
- * list contains malloc()-ed blocks which should get freed,
- * e.g.: list->destroy_function(list, free);
- *
- * @param function function to call on each object
- */
- void (*destroy_function) (linked_list_t *this, void (*)(void*));
-};
-
-/**
- * Creates an empty linked list object.
- *
- * @return linked_list_t object.
- */
-linked_list_t *linked_list_create(void);
-
-/**
- * Creates a linked list from an enumerator.
- *
- * @param enumerator enumerator over void*, gets destroyed
- * @return linked_list_t object, containing enumerated values
- */
-linked_list_t *linked_list_create_from_enumerator(enumerator_t *enumerator);
-
-/**
- * Creates a linked list from a NULL terminated vararg list of items.
- *
- * @param first first item
- * @param ... subsequent items, terminated by NULL
- * @return linked_list_t object, containing passed items
- */
-linked_list_t *linked_list_create_with_items(void *first, ...);
-
-#endif /** LINKED_LIST_H_ @}*/
diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c
index 5fd4cfd4d..117071351 100644
--- a/src/libstrongswan/utils/optionsfrom.c
+++ b/src/libstrongswan/utils/optionsfrom.c
@@ -2,22 +2,22 @@
* Copyright (C) 2007-2008 Andreas Steffen
* Hochschule fuer Technik Rapperswil
*
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Library 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/lgpl.txt>.
+ * 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 library is distributed in the hope that it will be useful, but
+ * 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 Library General Public
- * License for more details.
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
*/
#include <stdio.h>
#include <errno.h>
#include <library.h>
-#include <debug.h>
+#include <utils/debug.h>
#include <utils/lexparser.h>
#include "optionsfrom.h"
diff --git a/src/libstrongswan/utils/packet.c b/src/libstrongswan/utils/packet.c
deleted file mode 100644
index a2c329d60..000000000
--- a/src/libstrongswan/utils/packet.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * 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.
- */
-
-#include "packet.h"
-
-typedef struct private_packet_t private_packet_t;
-
-/**
- * Private data of an packet_t object.
- */
-struct private_packet_t {
-
- /**
- * Public part of a packet_t object.
- */
- packet_t public;
-
- /**
- * source address
- */
- host_t *source;
-
- /**
- * destination address
- */
- host_t *destination;
-
- /**
- * message data
- */
- chunk_t data;
-
- /**
- * actual chunk returned from get_data, adjusted when skip_bytes is called
- */
- chunk_t adjusted_data;
-};
-
-METHOD(packet_t, set_source, void,
- private_packet_t *this, host_t *source)
-{
- DESTROY_IF(this->source);
- this->source = source;
-}
-
-METHOD(packet_t, set_destination, void,
- private_packet_t *this, host_t *destination)
-{
- DESTROY_IF(this->destination);
- this->destination = destination;
-}
-
-METHOD(packet_t, get_source, host_t*,
- private_packet_t *this)
-{
- return this->source;
-}
-
-METHOD(packet_t, get_destination, host_t*,
- private_packet_t *this)
-{
- return this->destination;
-}
-
-METHOD(packet_t, get_data, chunk_t,
- private_packet_t *this)
-{
- return this->adjusted_data;
-}
-
-METHOD(packet_t, set_data, void,
- private_packet_t *this, chunk_t data)
-{
- free(this->data.ptr);
- this->adjusted_data = this->data = data;
-}
-
-METHOD(packet_t, skip_bytes, void,
- private_packet_t *this, size_t bytes)
-{
- this->adjusted_data = chunk_skip(this->adjusted_data, bytes);
-}
-
-METHOD(packet_t, destroy, void,
- private_packet_t *this)
-{
- DESTROY_IF(this->source);
- DESTROY_IF(this->destination);
- free(this->data.ptr);
- free(this);
-}
-
-METHOD(packet_t, clone_, packet_t*,
- private_packet_t *this)
-{
- packet_t *other;
-
- other = packet_create();
- if (this->destination)
- {
- other->set_destination(other,
- this->destination->clone(this->destination));
- }
- if (this->source)
- {
- other->set_source(other, this->source->clone(this->source));
- }
- if (this->data.ptr)
- {
- other->set_data(other, chunk_clone(this->adjusted_data));
- }
- return other;
-}
-
-/**
- * Described in header.
- */
-packet_t *packet_create_from_data(host_t *src, host_t *dst, chunk_t data)
-{
- private_packet_t *this;
-
- INIT(this,
- .public = {
- .set_data = _set_data,
- .get_data = _get_data,
- .set_source = _set_source,
- .get_source = _get_source,
- .set_destination = _set_destination,
- .get_destination = _get_destination,
- .skip_bytes = _skip_bytes,
- .clone = _clone_,
- .destroy = _destroy,
- },
- .source = src,
- .destination = dst,
- .adjusted_data = data,
- .data = data,
- );
-
- return &this->public;
-}
-
-/*
- * Described in header.
- */
-packet_t *packet_create()
-{
- return packet_create_from_data(NULL, NULL, chunk_empty);
-}
diff --git a/src/libstrongswan/utils/packet.h b/src/libstrongswan/utils/packet.h
deleted file mode 100644
index 5c4440115..000000000
--- a/src/libstrongswan/utils/packet.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * 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 packet packet
- * @{ @ingroup utils
- */
-
-#ifndef PACKET_H_
-#define PACKET_H_
-
-typedef struct packet_t packet_t;
-
-#include <library.h>
-#include <utils/host.h>
-
-/**
- * Abstraction of an IP/UDP-Packet, contains data, sender and receiver.
- */
-struct packet_t {
-
- /**
- * Set the source address.
- *
- * @param source address to set as source (gets owned)
- */
- void (*set_source)(packet_t *packet, host_t *source);
-
- /**
- * Set the destination address.
- *
- * @param source address to set as destination (gets owned)
- */
- void (*set_destination)(packet_t *packet, host_t *destination);
-
- /**
- * Get the source address.
- *
- * @return source address (internal data)
- */
- host_t *(*get_source)(packet_t *packet);
-
- /**
- * Get the destination address.
- *
- * @return destination address (internal data)
- */
- host_t *(*get_destination)(packet_t *packet);
-
- /**
- * Get the data from the packet.
- *
- * @return chunk containing the data (internal data)
- */
- chunk_t (*get_data)(packet_t *packet);
-
- /**
- * Set the data in the packet.
- *
- * @param data chunk with data to set (gets owned)
- */
- void (*set_data)(packet_t *packet, chunk_t data);
-
- /**
- * Increase the offset where the actual packet data starts.
- *
- * The total offset applies to future calls of get_data() and clone().
- *
- * @note The offset is reset to 0 when set_data() is called.
- *
- * @param bytes the number of additional bytes to skip
- */
- void (*skip_bytes)(packet_t *packet, size_t bytes);
-
- /**
- * Clones a packet_t object.
- *
- * @note Data is cloned without skipped bytes.
- *
- * @param clone clone of the packet
- */
- packet_t* (*clone)(packet_t *packet);
-
- /**
- * Destroy the packet, freeing contained data.
- */
- void (*destroy)(packet_t *packet);
-};
-
-/**
- * Create an empty packet
- *
- * @return packet_t object
- */
-packet_t *packet_create();
-
-/**
- * Create a packet from the supplied data
- *
- * @param src source address (gets owned)
- * @param dst destination address (gets owned)
- * @param data packet data (gets owned)
- * @return packet_t object
- */
-packet_t *packet_create_from_data(host_t *src, host_t *dst, chunk_t data);
-
-#endif /** PACKET_H_ @}*/
diff --git a/src/libstrongswan/utils/printf_hook.c b/src/libstrongswan/utils/printf_hook.c
new file mode 100644
index 000000000..6e51aa4c3
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook.c
@@ -0,0 +1,511 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * 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.
+ */
+
+#include "printf_hook.h"
+
+#include "utils.h"
+#include "debug.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+typedef struct private_printf_hook_t private_printf_hook_t;
+typedef struct printf_hook_handler_t printf_hook_handler_t;
+
+#define PRINTF_BUF_LEN 8192
+#define ARGS_MAX 3
+
+/**
+ * private data of printf_hook
+ */
+struct private_printf_hook_t {
+
+ /**
+ * public functions
+ */
+ printf_hook_t public;
+};
+
+/**
+ * struct with information about a registered handler
+ */
+struct printf_hook_handler_t {
+
+ /**
+ * callback function
+ */
+ printf_hook_function_t hook;
+
+ /**
+ * number of arguments
+ */
+ int numargs;
+
+ /**
+ * types of the arguments
+ */
+ int argtypes[ARGS_MAX];
+
+#ifdef USE_VSTR
+ /**
+ * name required for Vstr
+ */
+ char *name;
+#endif
+};
+
+/* A-Z | 6 other chars | a-z */
+#define NUM_HANDLERS 58
+static printf_hook_handler_t *printf_hooks[NUM_HANDLERS];
+
+#define SPEC_TO_INDEX(spec) ((int)(spec) - (int)'A')
+#define IS_VALID_SPEC(spec) (SPEC_TO_INDEX(spec) > -1 && SPEC_TO_INDEX(spec) < NUM_HANDLERS)
+
+#if !defined(USE_VSTR) && \
+ (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
+
+/**
+ * Printf hook print function. This is actually of type "printf_function",
+ * however glibc does it typedef to function, but uclibc to a pointer.
+ * So we redefine it here.
+ */
+static int custom_print(FILE *stream, const struct printf_info *info,
+ const void *const *args)
+{
+ printf_hook_spec_t spec;
+ printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
+ printf_hook_data_t data = {
+ .stream = stream,
+ };
+
+ spec.hash = info->alt;
+ spec.plus = info->showsign;
+ spec.minus = info->left;
+ spec.width = info->width;
+
+ return handler->hook(&data, &spec, args);
+}
+
+/**
+ * Printf hook arginfo function, which is actually of type
+ * "printf_arginfo_[size_]function".
+ */
+static int custom_arginfo(const struct printf_info *info, size_t n, int *argtypes
+#ifdef HAVE_PRINTF_SPECIFIER
+ , int *size
+#endif
+ )
+{
+ int i;
+ printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(info->spec)];
+
+ if (handler->numargs <= n)
+ {
+ for (i = 0; i < handler->numargs; ++i)
+ {
+ argtypes[i] = handler->argtypes[i];
+ }
+ }
+ /* we never set "size", as we have no user defined types */
+ return handler->numargs;
+}
+
+#else
+
+#include <errno.h>
+#include <unistd.h> /* for STDOUT_FILENO */
+
+/**
+ * These are used below, whenever the public wrapper functions are called before
+ * initialization or after destruction.
+ */
+#undef vprintf
+#undef vfprintf
+#undef vsnprintf
+
+/**
+ * Vstr custom format specifier callback function.
+ */
+static int custom_fmt_cb(Vstr_base *base, size_t pos, Vstr_fmt_spec *fmt_spec)
+{
+ int i;
+ const void *args[ARGS_MAX];
+ printf_hook_spec_t spec;
+ printf_hook_handler_t *handler = printf_hooks[SPEC_TO_INDEX(fmt_spec->name[0])];
+ printf_hook_data_t data = {
+ .base = base,
+ .pos = pos,
+ };
+
+ for (i = 0; i < handler->numargs; i++)
+ {
+ switch(handler->argtypes[i])
+ {
+ case PRINTF_HOOK_ARGTYPE_INT:
+ args[i] = VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
+ break;
+ case PRINTF_HOOK_ARGTYPE_POINTER:
+ args[i] = &VSTR_FMT_CB_ARG_PTR(fmt_spec, i);
+ break;
+ }
+ }
+
+ spec.hash = fmt_spec->fmt_hash;
+ spec.plus = fmt_spec->fmt_plus;
+ spec.minus = fmt_spec->fmt_minus;
+ spec.width = fmt_spec->fmt_field_width;
+
+ handler->hook(&data, &spec, args);
+ return 1;
+}
+
+/**
+ * Add a custom format handler to the given Vstr_conf object
+ */
+static void vstr_fmt_add_handler(Vstr_conf *conf, printf_hook_handler_t *handler)
+{
+ int *at = handler->argtypes;
+ switch(handler->numargs)
+ {
+ case 1:
+ vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
+ VSTR_TYPE_FMT_END);
+ break;
+ case 2:
+ vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
+ at[1], VSTR_TYPE_FMT_END);
+ break;
+ case 3:
+ vstr_fmt_add(conf, handler->name, custom_fmt_cb, at[0],
+ at[1], at[2], VSTR_TYPE_FMT_END);
+ break;
+ }
+}
+
+/**
+ * Management of thread-specific Vstr_conf objects
+ */
+#include <threading/thread_value.h>
+
+static thread_value_t *vstr_conf = NULL;
+
+static Vstr_conf *create_vstr_conf()
+{
+ int i;
+ Vstr_conf *conf = vstr_make_conf();
+ vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '%');
+ vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_TYPE_GRPALLOC_CACHE,
+ VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR);
+ vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_NUM_BUF_SZ, PRINTF_BUF_LEN);
+ for (i = 0; i < NUM_HANDLERS; ++i)
+ {
+ printf_hook_handler_t *handler = printf_hooks[i];
+ if (handler)
+ {
+ vstr_fmt_add_handler(conf, handler);
+ }
+ }
+ return conf;
+}
+
+static inline Vstr_conf *get_vstr_conf()
+{
+ Vstr_conf *conf = NULL;
+ if (vstr_conf)
+ {
+ conf = (Vstr_conf*)vstr_conf->get(vstr_conf);
+ if (!conf)
+ {
+ conf = create_vstr_conf();
+ vstr_conf->set(vstr_conf, conf);
+ }
+ }
+ return conf;
+}
+
+/**
+ * Described in header
+ */
+size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
+ ...)
+{
+ va_list args;
+ int written;
+
+ va_start(args, fmt);
+ written = vstr_add_vfmt(base, pos, fmt, args);
+ va_end(args);
+ return written;
+}
+
+/**
+ * Wrapper functions for printf and alike
+ */
+int vstr_wrapper_printf(const char *format, ...)
+{
+ int written;
+ va_list args;
+ va_start(args, format);
+ written = vstr_wrapper_vprintf(format, args);
+ va_end(args);
+ return written;
+}
+int vstr_wrapper_fprintf(FILE *stream, const char *format, ...)
+{
+ int written;
+ va_list args;
+ va_start(args, format);
+ written = vstr_wrapper_vfprintf(stream, format, args);
+ va_end(args);
+ return written;
+}
+int vstr_wrapper_sprintf(char *str, const char *format, ...)
+{
+ int written;
+ va_list args;
+ va_start(args, format);
+ written = vstr_wrapper_vsprintf(str, format, args);
+ va_end(args);
+ return written;
+}
+int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...)
+{
+ int written;
+ va_list args;
+ va_start(args, format);
+ written = vstr_wrapper_vsnprintf(str, size, format, args);
+ va_end(args);
+ return written;
+}
+int vstr_wrapper_asprintf(char **str, const char *format, ...)
+{
+ int written;
+ va_list args;
+ va_start(args, format);
+ written = vstr_wrapper_vasprintf(str, format, args);
+ va_end(args);
+ return written;
+}
+static inline int vstr_wrapper_vprintf_internal(Vstr_conf *conf, int fd,
+ const char *format,
+ va_list args)
+{
+ int written;
+ Vstr_base *s = vstr_make_base(conf);
+ vstr_add_vfmt(s, 0, format, args);
+ written = s->len;
+ while (s->len)
+ {
+ if (!vstr_sc_write_fd(s, 1, s->len, fd, NULL))
+ {
+ if (errno != EAGAIN && errno != EINTR)
+ {
+ written -= s->len;
+ break;
+ }
+ }
+ }
+ vstr_free_base(s);
+ return written;
+}
+int vstr_wrapper_vprintf(const char *format, va_list args)
+{
+ Vstr_conf *conf = get_vstr_conf();
+ if (conf)
+ {
+ return vstr_wrapper_vprintf_internal(conf, STDOUT_FILENO, format, args);
+ }
+ return vprintf(format, args);
+}
+int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list args)
+{
+ Vstr_conf *conf = get_vstr_conf();
+ if (conf)
+ {
+ return vstr_wrapper_vprintf_internal(conf, fileno(stream), format,
+ args);
+ }
+ return vfprintf(stream, format, args);
+}
+static inline int vstr_wrapper_vsnprintf_internal(char *str, size_t size,
+ const char *format,
+ va_list args)
+{
+ Vstr_conf *conf = get_vstr_conf();
+ if (conf)
+ {
+ int written;
+ Vstr_base *s = vstr_make_base(conf);
+ vstr_add_vfmt(s, 0, format, args);
+ written = s->len;
+ vstr_export_cstr_buf(s, 1, s->len, str, (size > 0) ? size : s->len + 1);
+ vstr_free_base(s);
+ return written;
+ }
+ return vsnprintf(str, size, format, args);
+}
+int vstr_wrapper_vsprintf(char *str, const char *format, va_list args)
+{
+ return vstr_wrapper_vsnprintf_internal(str, 0, format, args);
+}
+int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format,
+ va_list args)
+{
+ return (size > 0) ? vstr_wrapper_vsnprintf_internal(str, size, format, args) : 0;
+}
+int vstr_wrapper_vasprintf(char **str, const char *format, va_list args)
+{
+ size_t len = 100;
+ int written;
+ *str = malloc(len);
+ while (TRUE)
+ {
+ va_list ac;
+ va_copy(ac, args);
+ written = vstr_wrapper_vsnprintf_internal(*str, len, format, ac);
+ va_end(ac);
+ if (written < len)
+ {
+ break;
+ }
+ len = written + 1;
+ *str = realloc(*str, len);
+ }
+ return written;
+}
+#endif
+
+METHOD(printf_hook_t, add_handler, void,
+ private_printf_hook_t *this, char spec,
+ printf_hook_function_t hook, ...)
+{
+ int i = -1;
+ printf_hook_handler_t *handler;
+ printf_hook_argtype_t argtype;
+ va_list args;
+
+ if (!IS_VALID_SPEC(spec))
+ {
+ DBG1(DBG_LIB, "'%c' is not a valid printf hook specifier, "
+ "not registered!", spec);
+ return;
+ }
+
+ handler = malloc_thing(printf_hook_handler_t);
+ handler->hook = hook;
+
+ va_start(args, hook);
+ while ((argtype = va_arg(args, printf_hook_argtype_t)) != PRINTF_HOOK_ARGTYPE_END)
+ {
+ if (++i >= ARGS_MAX)
+ {
+ DBG1(DBG_LIB, "Too many arguments for printf hook with "
+ "specifier '%c', not registered!", spec);
+ va_end(args);
+ free(handler);
+ return;
+ }
+ handler->argtypes[i] = argtype;
+ }
+ va_end(args);
+
+ handler->numargs = i + 1;
+
+ if (handler->numargs > 0)
+ {
+#if !defined(USE_VSTR) && \
+ (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
+# ifdef HAVE_PRINTF_SPECIFIER
+ register_printf_specifier(spec, custom_print, custom_arginfo);
+# else
+ register_printf_function(spec, custom_print, custom_arginfo);
+# endif
+#else
+ Vstr_conf *conf = get_vstr_conf();
+ handler->name = malloc(2);
+ handler->name[0] = spec;
+ handler->name[1] = '\0';
+ vstr_fmt_add_handler(conf, handler);
+#endif
+ printf_hooks[SPEC_TO_INDEX(spec)] = handler;
+ }
+ else
+ {
+ free(handler);
+ }
+}
+
+METHOD(printf_hook_t, destroy, void,
+ private_printf_hook_t *this)
+{
+ int i;
+#ifdef USE_VSTR
+ Vstr_conf *conf = get_vstr_conf();
+#endif
+
+ for (i = 0; i < NUM_HANDLERS; ++i)
+ {
+ printf_hook_handler_t *handler = printf_hooks[i];
+ if (handler)
+ {
+#ifdef USE_VSTR
+ vstr_fmt_del(conf, handler->name);
+ free(handler->name);
+#endif
+ free(handler);
+ }
+ }
+
+#ifdef USE_VSTR
+ /* freeing the Vstr_conf of the main thread */
+ vstr_conf->destroy(vstr_conf);
+ vstr_conf = NULL;
+ vstr_free_conf(conf);
+ vstr_exit();
+#endif
+ free(this);
+}
+
+/*
+ * see header file
+ */
+printf_hook_t *printf_hook_create()
+{
+ private_printf_hook_t *this;
+
+ INIT(this,
+ .public = {
+ .add_handler = _add_handler,
+ .destroy = _destroy,
+ },
+ );
+
+ memset(printf_hooks, 0, sizeof(printf_hooks));
+
+#ifdef USE_VSTR
+ if (!vstr_init())
+ {
+ DBG1(DBG_LIB, "failed to initialize Vstr library!");
+ free(this);
+ return NULL;
+ }
+ vstr_conf = thread_value_create((thread_cleanup_t)vstr_free_conf);
+#endif
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/utils/printf_hook.h b/src/libstrongswan/utils/printf_hook.h
new file mode 100644
index 000000000..1425910be
--- /dev/null
+++ b/src/libstrongswan/utils/printf_hook.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2006-2008 Martin Willi
+ * 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 printf_hook printf_hook
+ * @{ @ingroup utils
+ */
+
+#ifndef PRINTF_HOOK_H_
+#define PRINTF_HOOK_H_
+
+typedef struct printf_hook_t printf_hook_t;
+typedef struct printf_hook_spec_t printf_hook_spec_t;
+typedef struct printf_hook_data_t printf_hook_data_t;
+typedef enum printf_hook_argtype_t printf_hook_argtype_t;
+
+#if !defined(USE_VSTR) && \
+ !defined(HAVE_PRINTF_FUNCTION) && \
+ !defined(HAVE_PRINTF_SPECIFIER)
+/* assume newer glibc register_printf_specifier if none given */
+#define HAVE_PRINTF_SPECIFIER
+#endif
+
+#if !defined(USE_VSTR) && \
+ (defined(HAVE_PRINTF_FUNCTION) || defined(HAVE_PRINTF_SPECIFIER))
+
+#include <stdio.h>
+#include <printf.h>
+
+enum printf_hook_argtype_t {
+ PRINTF_HOOK_ARGTYPE_END = -1,
+ PRINTF_HOOK_ARGTYPE_INT = PA_INT,
+ PRINTF_HOOK_ARGTYPE_POINTER = PA_POINTER,
+};
+
+/**
+ * Data to pass to a printf hook.
+ */
+struct printf_hook_data_t {
+
+ /**
+ * Output FILE stream
+ */
+ FILE *stream;;
+};
+
+/**
+ * Helper macro to be used in printf hook callbacks.
+ */
+#define print_in_hook(data, fmt, ...) ({\
+ ssize_t _written = fprintf(data->stream, fmt, ##__VA_ARGS__);\
+ if (_written < 0)\
+ {\
+ _written = 0;\
+ }\
+ _written;\
+})
+
+#else
+
+#include <vstr.h>
+
+enum printf_hook_argtype_t {
+ PRINTF_HOOK_ARGTYPE_END = VSTR_TYPE_FMT_END,
+ PRINTF_HOOK_ARGTYPE_INT = VSTR_TYPE_FMT_INT,
+ PRINTF_HOOK_ARGTYPE_POINTER = VSTR_TYPE_FMT_PTR_VOID,
+};
+
+/**
+ * Redefining printf and alike
+ */
+#include <stdio.h>
+#include <stdarg.h>
+
+int vstr_wrapper_printf(const char *format, ...);
+int vstr_wrapper_fprintf(FILE *stream, const char *format, ...);
+int vstr_wrapper_sprintf(char *str, const char *format, ...);
+int vstr_wrapper_snprintf(char *str, size_t size, const char *format, ...);
+int vstr_wrapper_asprintf(char **str, const char *format, ...);
+
+int vstr_wrapper_vprintf(const char *format, va_list ap);
+int vstr_wrapper_vfprintf(FILE *stream, const char *format, va_list ap);
+int vstr_wrapper_vsprintf(char *str, const char *format, va_list ap);
+int vstr_wrapper_vsnprintf(char *str, size_t size, const char *format, va_list ap);
+int vstr_wrapper_vasprintf(char **str, const char *format, va_list ap);
+
+#ifdef printf
+#undef printf
+#endif
+#ifdef fprintf
+#undef fprintf
+#endif
+#ifdef sprintf
+#undef sprintf
+#endif
+#ifdef snprintf
+#undef snprintf
+#endif
+#ifdef asprintf
+#undef asprintf
+#endif
+#ifdef vprintf
+#undef vprintf
+#endif
+#ifdef vfprintf
+#undef vfprintf
+#endif
+#ifdef vsprintf
+#undef vsprintf
+#endif
+#ifdef vsnprintf
+#undef vsnprintf
+#endif
+#ifdef vasprintf
+#undef vasprintf
+#endif
+
+#define printf vstr_wrapper_printf
+#define fprintf vstr_wrapper_fprintf
+#define sprintf vstr_wrapper_sprintf
+#define snprintf vstr_wrapper_snprintf
+#define asprintf vstr_wrapper_asprintf
+
+#define vprintf vstr_wrapper_vprintf
+#define vfprintf vstr_wrapper_vfprintf
+#define vsprintf vstr_wrapper_vsprintf
+#define vsnprintf vstr_wrapper_vsnprintf
+#define vasprintf vstr_wrapper_vasprintf
+
+/**
+ * Data to pass to a printf hook.
+ */
+struct printf_hook_data_t {
+
+ /**
+ * Base to append printf to
+ */
+ Vstr_base *base;
+
+ /**
+ * Position in base to write to
+ */
+ size_t pos;
+};
+
+/**
+ * Wrapper around vstr_add_vfmt(), avoids having to link all users of
+ * print_in_hook() against libvstr.
+ *
+ * @param base Vstr_string to add string to
+ * @param pos position to write to
+ * @param fmt format string
+ * @param ... arguments
+ * @return number of characters written
+ */
+size_t vstr_print_in_hook(struct Vstr_base *base, size_t pos, const char *fmt,
+ ...);
+
+/**
+ * Helper macro to be used in printf hook callbacks.
+ */
+#define print_in_hook(data, fmt, ...) ({\
+ size_t _written; \
+ _written = vstr_print_in_hook(data->base, data->pos, fmt, ##__VA_ARGS__);\
+ data->pos += _written;\
+ _written;\
+})
+
+#endif
+
+/**
+ * Callback function type for printf hooks.
+ *
+ * @param data hook data, to pass to print_in_hook()
+ * @param spec format specifier
+ * @param args arguments array
+ * @return number of characters written
+ */
+typedef int (*printf_hook_function_t)(printf_hook_data_t *data,
+ printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * Properties of the format specifier
+ */
+struct printf_hook_spec_t {
+ /**
+ * TRUE if a '#' was used in the format specifier
+ */
+ int hash;
+
+ /**
+ * TRUE if a '-' was used in the format specifier
+ */
+ int minus;
+
+ /**
+ * TRUE if a '+' was used in the format specifier
+ */
+ int plus;
+
+ /**
+ * The width as given in the format specifier.
+ */
+ int width;
+};
+
+/**
+ * Printf handler management.
+ */
+struct printf_hook_t {
+
+ /**
+ * Register a printf handler.
+ *
+ * @param spec printf hook format character
+ * @param hook hook function
+ * @param ... list of PRINTF_HOOK_ARGTYPE_*, MUST end with PRINTF_HOOK_ARGTYPE_END
+ */
+ void (*add_handler)(printf_hook_t *this, char spec,
+ printf_hook_function_t hook, ...);
+
+ /**
+ * Destroy a printf_hook instance.
+ */
+ void (*destroy)(printf_hook_t *this);
+};
+
+/**
+ * Create a printf_hook instance.
+ */
+printf_hook_t *printf_hook_create();
+
+#endif /** PRINTF_HOOK_H_ @}*/
diff --git a/src/libstrongswan/utils/settings.c b/src/libstrongswan/utils/settings.c
new file mode 100644
index 000000000..712ea6ee2
--- /dev/null
+++ b/src/libstrongswan/utils/settings.c
@@ -0,0 +1,1227 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include <libgen.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif /* HAVE_GLOB_H */
+
+#include "settings.h"
+
+#include "collections/linked_list.h"
+#include "threading/rwlock.h"
+#include "utils/debug.h"
+
+#define MAX_INCLUSION_LEVEL 10
+
+typedef struct private_settings_t private_settings_t;
+typedef struct section_t section_t;
+typedef struct kv_t kv_t;
+
+/**
+ * private data of settings
+ */
+struct private_settings_t {
+
+ /**
+ * public functions
+ */
+ settings_t public;
+
+ /**
+ * top level section
+ */
+ section_t *top;
+
+ /**
+ * contents of loaded files and in-memory settings (char*)
+ */
+ linked_list_t *contents;
+
+ /**
+ * lock to safely access the settings
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * section containing subsections and key value pairs
+ */
+struct section_t {
+
+ /**
+ * name of the section
+ */
+ char *name;
+
+ /**
+ * subsections, as section_t
+ */
+ linked_list_t *sections;
+
+ /**
+ * key value pairs, as kv_t
+ */
+ linked_list_t *kv;
+};
+
+/**
+ * Key value pair
+ */
+struct kv_t {
+
+ /**
+ * key string, relative
+ */
+ char *key;
+
+ /**
+ * value as string
+ */
+ char *value;
+};
+
+/**
+ * create a key/value pair
+ */
+static kv_t *kv_create(char *key, char *value)
+{
+ kv_t *this;
+ INIT(this,
+ .key = strdup(key),
+ .value = value,
+ );
+ return this;
+}
+
+/**
+ * destroy a key/value pair
+ */
+static void kv_destroy(kv_t *this)
+{
+ free(this->key);
+ free(this);
+}
+
+/**
+ * create a section with the given name
+ */
+static section_t *section_create(char *name)
+{
+ section_t *this;
+ INIT(this,
+ .name = strdupnull(name),
+ .sections = linked_list_create(),
+ .kv = linked_list_create(),
+ );
+ return this;
+}
+
+/**
+ * destroy a section
+ */
+static void section_destroy(section_t *this)
+{
+ this->kv->destroy_function(this->kv, (void*)kv_destroy);
+ this->sections->destroy_function(this->sections, (void*)section_destroy);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Purge contents of a section
+ */
+static void section_purge(section_t *this)
+{
+ this->kv->destroy_function(this->kv, (void*)kv_destroy);
+ this->kv = linked_list_create();
+ this->sections->destroy_function(this->sections, (void*)section_destroy);
+ this->sections = linked_list_create();
+}
+
+/**
+ * callback to find a section by name
+ */
+static bool section_find(section_t *this, char *name)
+{
+ return streq(this->name, name);
+}
+
+/**
+ * callback to find a kv pair by key
+ */
+static bool kv_find(kv_t *this, char *key)
+{
+ return streq(this->key, key);
+}
+
+/**
+ * Print a format key, but consume already processed arguments
+ */
+static bool print_key(char *buf, int len, char *start, char *key, va_list args)
+{
+ va_list copy;
+ bool res;
+ char *pos;
+
+ va_copy(copy, args);
+ while (start < key)
+ {
+ pos = strchr(start, '%');
+ if (!pos)
+ {
+ start += strlen(start) + 1;
+ continue;
+ }
+ pos++;
+ switch (*pos)
+ {
+ case 'd':
+ va_arg(copy, int);
+ break;
+ case 's':
+ va_arg(copy, char*);
+ break;
+ case 'N':
+ va_arg(copy, enum_name_t*);
+ va_arg(copy, int);
+ break;
+ case '%':
+ break;
+ default:
+ DBG1(DBG_CFG, "settings with %%%c not supported!", *pos);
+ break;
+ }
+ start = pos;
+ if (*start)
+ {
+ start++;
+ }
+ }
+ res = vsnprintf(buf, len, key, copy) < len;
+ va_end(copy);
+ return res;
+}
+
+/**
+ * Find a section by a given key, using buffered key, reusable buffer.
+ * If "ensure" is TRUE, the sections are created if they don't exist.
+ */
+static section_t *find_section_buffered(section_t *section,
+ char *start, char *key, va_list args, char *buf, int len,
+ bool ensure)
+{
+ char *pos;
+ section_t *found = NULL;
+
+ if (section == NULL)
+ {
+ return NULL;
+ }
+ pos = strchr(key, '.');
+ if (pos)
+ {
+ *pos = '\0';
+ pos++;
+ }
+ if (!print_key(buf, len, start, key, args))
+ {
+ return NULL;
+ }
+ if (section->sections->find_first(section->sections,
+ (linked_list_match_t)section_find,
+ (void**)&found, buf) != SUCCESS)
+ {
+ if (ensure)
+ {
+ found = section_create(buf);
+ section->sections->insert_last(section->sections, found);
+ }
+ }
+ if (found && pos)
+ {
+ return find_section_buffered(found, start, pos, args, buf, len, ensure);
+ }
+ return found;
+}
+
+/**
+ * Find a section by a given key (thread-safe).
+ */
+static section_t *find_section(private_settings_t *this, section_t *section,
+ char *key, va_list args)
+{
+ char buf[128], keybuf[512];
+ section_t *found;
+
+ if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+ {
+ return NULL;
+ }
+ this->lock->read_lock(this->lock);
+ found = find_section_buffered(section, keybuf, keybuf, args, buf,
+ sizeof(buf), FALSE);
+ this->lock->unlock(this->lock);
+ return found;
+}
+
+/**
+ * Ensure that the section with the given key exists (thread-safe).
+ */
+static section_t *ensure_section(private_settings_t *this, section_t *section,
+ char *key, va_list args)
+{
+ char buf[128], keybuf[512];
+ section_t *found;
+
+ if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+ {
+ return NULL;
+ }
+ /* we might have to change the tree */
+ this->lock->write_lock(this->lock);
+ found = find_section_buffered(section, keybuf, keybuf, args, buf,
+ sizeof(buf), TRUE);
+ this->lock->unlock(this->lock);
+ return found;
+}
+
+/**
+ * Find the key/value pair for a key, using buffered key, reusable buffer
+ * If "ensure" is TRUE, the sections (and key/value pair) are created if they
+ * don't exist.
+ */
+static kv_t *find_value_buffered(section_t *section, char *start, char *key,
+ va_list args, char *buf, int len, bool ensure)
+{
+ char *pos;
+ kv_t *kv = NULL;
+ section_t *found = NULL;
+
+ if (section == NULL)
+ {
+ return NULL;
+ }
+
+ pos = strchr(key, '.');
+ if (pos)
+ {
+ *pos = '\0';
+ pos++;
+
+ if (!print_key(buf, len, start, key, args))
+ {
+ return NULL;
+ }
+ if (section->sections->find_first(section->sections,
+ (linked_list_match_t)section_find,
+ (void**)&found, buf) != SUCCESS)
+ {
+ if (!ensure)
+ {
+ return NULL;
+ }
+ found = section_create(buf);
+ section->sections->insert_last(section->sections, found);
+ }
+ return find_value_buffered(found, start, pos, args, buf, len,
+ ensure);
+ }
+ else
+ {
+ if (!print_key(buf, len, start, key, args))
+ {
+ return NULL;
+ }
+ if (section->kv->find_first(section->kv, (linked_list_match_t)kv_find,
+ (void**)&kv, buf) != SUCCESS)
+ {
+ if (ensure)
+ {
+ kv = kv_create(buf, NULL);
+ section->kv->insert_last(section->kv, kv);
+ }
+ }
+ }
+ return kv;
+}
+
+/**
+ * Find the string value for a key (thread-safe).
+ */
+static char *find_value(private_settings_t *this, section_t *section,
+ char *key, va_list args)
+{
+ char buf[128], keybuf[512], *value = NULL;
+ kv_t *kv;
+
+ if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+ {
+ return NULL;
+ }
+ this->lock->read_lock(this->lock);
+ kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
+ FALSE);
+ if (kv)
+ {
+ value = kv->value;
+ }
+ this->lock->unlock(this->lock);
+ return value;
+}
+
+/**
+ * Set a value to a copy of the given string (thread-safe).
+ */
+static void set_value(private_settings_t *this, section_t *section,
+ char *key, va_list args, char *value)
+{
+ char buf[128], keybuf[512];
+ kv_t *kv;
+
+ if (snprintf(keybuf, sizeof(keybuf), "%s", key) >= sizeof(keybuf))
+ {
+ return;
+ }
+ this->lock->write_lock(this->lock);
+ kv = find_value_buffered(section, keybuf, keybuf, args, buf, sizeof(buf),
+ TRUE);
+ if (kv)
+ {
+ if (!value)
+ {
+ kv->value = NULL;
+ }
+ else if (kv->value && (strlen(value) <= strlen(kv->value)))
+ { /* overwrite in-place, if possible */
+ strcpy(kv->value, value);
+ }
+ else
+ { /* otherwise clone the string and store it in the cache */
+ kv->value = strdup(value);
+ this->contents->insert_last(this->contents, kv->value);
+ }
+ }
+ this->lock->unlock(this->lock);
+}
+
+METHOD(settings_t, get_str, char*,
+ private_settings_t *this, char *key, char *def, ...)
+{
+ char *value;
+ va_list args;
+
+ va_start(args, def);
+ value = find_value(this, this->top, key, args);
+ va_end(args);
+ if (value)
+ {
+ return value;
+ }
+ return def;
+}
+
+/**
+ * Described in header
+ */
+inline bool settings_value_as_bool(char *value, bool def)
+{
+ if (value)
+ {
+ if (strcaseeq(value, "1") ||
+ strcaseeq(value, "yes") ||
+ strcaseeq(value, "true") ||
+ strcaseeq(value, "enabled"))
+ {
+ return TRUE;
+ }
+ else if (strcaseeq(value, "0") ||
+ strcaseeq(value, "no") ||
+ strcaseeq(value, "false") ||
+ strcaseeq(value, "disabled"))
+ {
+ return FALSE;
+ }
+ }
+ return def;
+}
+
+METHOD(settings_t, get_bool, bool,
+ private_settings_t *this, char *key, bool def, ...)
+{
+ char *value;
+ va_list args;
+
+ va_start(args, def);
+ value = find_value(this, this->top, key, args);
+ va_end(args);
+ return settings_value_as_bool(value, def);
+}
+
+/**
+ * Described in header
+ */
+inline int settings_value_as_int(char *value, int def)
+{
+ int intval;
+ if (value)
+ {
+ errno = 0;
+ intval = strtol(value, NULL, 10);
+ if (errno == 0)
+ {
+ return intval;
+ }
+ }
+ return def;
+}
+
+METHOD(settings_t, get_int, int,
+ private_settings_t *this, char *key, int def, ...)
+{
+ char *value;
+ va_list args;
+
+ va_start(args, def);
+ value = find_value(this, this->top, key, args);
+ va_end(args);
+ return settings_value_as_int(value, def);
+}
+
+/**
+ * Described in header
+ */
+inline double settings_value_as_double(char *value, double def)
+{
+ double dval;
+ if (value)
+ {
+ errno = 0;
+ dval = strtod(value, NULL);
+ if (errno == 0)
+ {
+ return dval;
+ }
+ }
+ return def;
+}
+
+METHOD(settings_t, get_double, double,
+ private_settings_t *this, char *key, double def, ...)
+{
+ char *value;
+ va_list args;
+
+ va_start(args, def);
+ value = find_value(this, this->top, key, args);
+ va_end(args);
+ return settings_value_as_double(value, def);
+}
+
+/**
+ * Described in header
+ */
+inline u_int32_t settings_value_as_time(char *value, u_int32_t def)
+{
+ char *endptr;
+ u_int32_t timeval;
+ if (value)
+ {
+ errno = 0;
+ timeval = strtoul(value, &endptr, 10);
+ if (errno == 0)
+ {
+ switch (*endptr)
+ {
+ case 'd': /* time in days */
+ timeval *= 24 * 3600;
+ break;
+ case 'h': /* time in hours */
+ timeval *= 3600;
+ break;
+ case 'm': /* time in minutes */
+ timeval *= 60;
+ break;
+ case 's': /* time in seconds */
+ default:
+ break;
+ }
+ return timeval;
+ }
+ }
+ return def;
+}
+
+METHOD(settings_t, get_time, u_int32_t,
+ private_settings_t *this, char *key, u_int32_t def, ...)
+{
+ char *value;
+ va_list args;
+
+ va_start(args, def);
+ value = find_value(this, this->top, key, args);
+ va_end(args);
+ return settings_value_as_time(value, def);
+}
+
+METHOD(settings_t, set_str, void,
+ private_settings_t *this, char *key, char *value, ...)
+{
+ va_list args;
+ va_start(args, value);
+ set_value(this, this->top, key, args, value);
+ va_end(args);
+}
+
+METHOD(settings_t, set_bool, void,
+ private_settings_t *this, char *key, bool value, ...)
+{
+ va_list args;
+ va_start(args, value);
+ set_value(this, this->top, key, args, value ? "1" : "0");
+ va_end(args);
+}
+
+METHOD(settings_t, set_int, void,
+ private_settings_t *this, char *key, int value, ...)
+{
+ char val[16];
+ va_list args;
+ va_start(args, value);
+ if (snprintf(val, sizeof(val), "%d", value) < sizeof(val))
+ {
+ set_value(this, this->top, key, args, val);
+ }
+ va_end(args);
+}
+
+METHOD(settings_t, set_double, void,
+ private_settings_t *this, char *key, double value, ...)
+{
+ char val[64];
+ va_list args;
+ va_start(args, value);
+ if (snprintf(val, sizeof(val), "%f", value) < sizeof(val))
+ {
+ set_value(this, this->top, key, args, val);
+ }
+ va_end(args);
+}
+
+METHOD(settings_t, set_time, void,
+ private_settings_t *this, char *key, u_int32_t value, ...)
+{
+ char val[16];
+ va_list args;
+ va_start(args, value);
+ if (snprintf(val, sizeof(val), "%u", value) < sizeof(val))
+ {
+ set_value(this, this->top, key, args, val);
+ }
+ va_end(args);
+}
+
+/**
+ * Enumerate section names, not sections
+ */
+static bool section_filter(void *null, section_t **in, char **out)
+{
+ *out = (*in)->name;
+ return TRUE;
+}
+
+METHOD(settings_t, create_section_enumerator, enumerator_t*,
+ private_settings_t *this, char *key, ...)
+{
+ section_t *section;
+ va_list args;
+
+ va_start(args, key);
+ section = find_section(this, this->top, key, args);
+ va_end(args);
+
+ if (!section)
+ {
+ return enumerator_create_empty();
+ }
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(
+ section->sections->create_enumerator(section->sections),
+ (void*)section_filter, this->lock, (void*)this->lock->unlock);
+}
+
+/**
+ * Enumerate key and values, not kv_t entries
+ */
+static bool kv_filter(void *null, kv_t **in, char **key,
+ void *none, char **value)
+{
+ *key = (*in)->key;
+ *value = (*in)->value;
+ return TRUE;
+}
+
+METHOD(settings_t, create_key_value_enumerator, enumerator_t*,
+ private_settings_t *this, char *key, ...)
+{
+ section_t *section;
+ va_list args;
+
+ va_start(args, key);
+ section = find_section(this, this->top, key, args);
+ va_end(args);
+
+ if (!section)
+ {
+ return enumerator_create_empty();
+ }
+ this->lock->read_lock(this->lock);
+ return enumerator_create_filter(
+ section->kv->create_enumerator(section->kv),
+ (void*)kv_filter, this->lock, (void*)this->lock->unlock);
+}
+
+/**
+ * parse text, truncate "skip" chars, delimited by term respecting brackets.
+ *
+ * Chars in "skip" are truncated at the beginning and the end of the resulting
+ * token. "term" contains a list of characters to read up to (first match),
+ * while "br" contains bracket counterparts found in "term" to skip.
+ */
+static char parse(char **text, char *skip, char *term, char *br, char **token)
+{
+ char *best = NULL;
+ char best_term = '\0';
+
+ /* skip leading chars */
+ while (strchr(skip, **text))
+ {
+ (*text)++;
+ if (!**text)
+ {
+ return 0;
+ }
+ }
+ /* mark begin of subtext */
+ *token = *text;
+ while (*term)
+ {
+ char *pos = *text;
+ int level = 1;
+
+ /* find terminator */
+ while (*pos)
+ {
+ if (*pos == *term)
+ {
+ level--;
+ }
+ else if (br && *pos == *br)
+ {
+ level++;
+ }
+ if (level == 0)
+ {
+ if (best == NULL || best > pos)
+ {
+ best = pos;
+ best_term = *term;
+ }
+ break;
+ }
+ pos++;
+ }
+ /* try next terminator */
+ term++;
+ if (br)
+ {
+ br++;
+ }
+ }
+ if (best)
+ {
+ /* update input */
+ *text = best;
+ /* null trailing bytes */
+ do
+ {
+ *best = '\0';
+ best--;
+ }
+ while (best >= *token && strchr(skip, *best));
+ /* return found terminator */
+ return best_term;
+ }
+ return 0;
+}
+
+/**
+ * Check if "text" starts with "pattern".
+ * Characters in "skip" are skipped first. If found, TRUE is returned and "text"
+ * is modified to point to the character right after "pattern".
+ */
+static bool starts_with(char **text, char *skip, char *pattern)
+{
+ char *pos = *text;
+ int len = strlen(pattern);
+ while (strchr(skip, *pos))
+ {
+ pos++;
+ if (!*pos)
+ {
+ return FALSE;
+ }
+ }
+ if (strlen(pos) < len || !strneq(pos, pattern, len))
+ {
+ return FALSE;
+ }
+ *text = pos + len;
+ return TRUE;
+}
+
+/**
+ * Check if what follows in "text" is an include statement.
+ * If this function returns TRUE, "text" will point to the character right after
+ * the include pattern, which is returned in "pattern".
+ */
+static bool parse_include(char **text, char **pattern)
+{
+ char *pos = *text;
+ if (!starts_with(&pos, "\n\t ", "include"))
+ {
+ return FALSE;
+ }
+ if (starts_with(&pos, "\t ", "="))
+ { /* ignore "include = value" */
+ return FALSE;
+ }
+ *text = pos;
+ return parse(text, "\t ", "\n", NULL, pattern) != 0;
+}
+
+/**
+ * Forward declaration.
+ */
+static bool parse_files(linked_list_t *contents, char *file, int level,
+ char *pattern, section_t *section);
+
+/**
+ * Parse a section
+ */
+static bool parse_section(linked_list_t *contents, char *file, int level,
+ char **text, section_t *section)
+{
+ bool finished = FALSE;
+ char *key, *value, *inner;
+
+ while (!finished)
+ {
+ if (parse_include(text, &value))
+ {
+ if (!parse_files(contents, file, level, value, section))
+ {
+ DBG1(DBG_LIB, "failed to include '%s'", value);
+ return FALSE;
+ }
+ continue;
+ }
+ switch (parse(text, "\t\n ", "{=#", NULL, &key))
+ {
+ case '{':
+ if (parse(text, "\t ", "}", "{", &inner))
+ {
+ section_t *sub;
+ if (!strlen(key))
+ {
+ DBG1(DBG_LIB, "skipping section without name in '%s'",
+ section->name);
+ continue;
+ }
+ if (section->sections->find_first(section->sections,
+ (linked_list_match_t)section_find,
+ (void**)&sub, key) != SUCCESS)
+ {
+ sub = section_create(key);
+ if (parse_section(contents, file, level, &inner, sub))
+ {
+ section->sections->insert_last(section->sections,
+ sub);
+ continue;
+ }
+ section_destroy(sub);
+ }
+ else
+ { /* extend the existing section */
+ if (parse_section(contents, file, level, &inner, sub))
+ {
+ continue;
+ }
+ }
+ DBG1(DBG_LIB, "parsing subsection '%s' failed", key);
+ break;
+ }
+ DBG1(DBG_LIB, "matching '}' not found near %s", *text);
+ break;
+ case '=':
+ if (parse(text, "\t ", "\n", NULL, &value))
+ {
+ kv_t *kv;
+ if (!strlen(key))
+ {
+ DBG1(DBG_LIB, "skipping value without key in '%s'",
+ section->name);
+ continue;
+ }
+ if (section->kv->find_first(section->kv,
+ (linked_list_match_t)kv_find,
+ (void**)&kv, key) != SUCCESS)
+ {
+ kv = kv_create(key, value);
+ section->kv->insert_last(section->kv, kv);
+ }
+ else
+ { /* replace with the most recently read value */
+ kv->value = value;
+ }
+ continue;
+ }
+ DBG1(DBG_LIB, "parsing value failed near %s", *text);
+ break;
+ case '#':
+ parse(text, "", "\n", NULL, &value);
+ continue;
+ default:
+ finished = TRUE;
+ continue;
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a file and add the settings to the given section.
+ */
+static bool parse_file(linked_list_t *contents, char *file, int level,
+ section_t *section)
+{
+ bool success;
+ char *text, *pos;
+ struct stat st;
+ FILE *fd;
+ int len;
+
+ DBG2(DBG_LIB, "loading config file '%s'", file);
+ if (stat(file, &st) == -1)
+ {
+ if (errno == ENOENT)
+ {
+ DBG2(DBG_LIB, "'%s' does not exist, ignored", file);
+ return TRUE;
+ }
+ DBG1(DBG_LIB, "failed to stat '%s': %s", file, strerror(errno));
+ return FALSE;
+ }
+ else if (!S_ISREG(st.st_mode))
+ {
+ DBG1(DBG_LIB, "'%s' is not a regular file", file);
+ return FALSE;
+ }
+ fd = fopen(file, "r");
+ if (fd == NULL)
+ {
+ DBG1(DBG_LIB, "'%s' is not readable", file);
+ return FALSE;
+ }
+ fseek(fd, 0, SEEK_END);
+ len = ftell(fd);
+ rewind(fd);
+ text = malloc(len + 1);
+ text[len] = '\0';
+ if (fread(text, 1, len, fd) != len)
+ {
+ free(text);
+ fclose(fd);
+ return FALSE;
+ }
+ fclose(fd);
+
+ pos = text;
+ success = parse_section(contents, file, level, &pos, section);
+ if (!success)
+ {
+ free(text);
+ }
+ else
+ {
+ contents->insert_last(contents, text);
+ }
+ return success;
+}
+
+/**
+ * Load the files matching "pattern", which is resolved with glob(3), if
+ * available.
+ * If the pattern is relative, the directory of "file" is used as base.
+ */
+static bool parse_files(linked_list_t *contents, char *file, int level,
+ char *pattern, section_t *section)
+{
+ bool success = TRUE;
+ char pat[PATH_MAX];
+
+ if (level > MAX_INCLUSION_LEVEL)
+ {
+ DBG1(DBG_LIB, "maximum level of %d includes reached, ignored",
+ MAX_INCLUSION_LEVEL);
+ return TRUE;
+ }
+
+ if (!strlen(pattern))
+ {
+ DBG2(DBG_LIB, "empty include pattern, ignored");
+ return TRUE;
+ }
+
+ if (!file || pattern[0] == '/')
+ { /* absolute path */
+ if (snprintf(pat, sizeof(pat), "%s", pattern) >= sizeof(pat))
+ {
+ DBG1(DBG_LIB, "include pattern too long, ignored");
+ return TRUE;
+ }
+ }
+ else
+ { /* base relative paths to the directory of the current file */
+ char *dir = strdup(file);
+ dir = dirname(dir);
+ if (snprintf(pat, sizeof(pat), "%s/%s", dir, pattern) >= sizeof(pat))
+ {
+ DBG1(DBG_LIB, "include pattern too long, ignored");
+ free(dir);
+ return TRUE;
+ }
+ free(dir);
+ }
+#ifdef HAVE_GLOB_H
+ {
+ int status;
+ glob_t buf;
+
+ status = glob(pat, GLOB_ERR, NULL, &buf);
+ if (status == GLOB_NOMATCH)
+ {
+ DBG2(DBG_LIB, "no files found matching '%s', ignored", pat);
+ }
+ else if (status != 0)
+ {
+ DBG1(DBG_LIB, "expanding file pattern '%s' failed", pat);
+ success = FALSE;
+ }
+ else
+ {
+ char **expanded;
+ for (expanded = buf.gl_pathv; *expanded != NULL; expanded++)
+ {
+ success &= parse_file(contents, *expanded, level + 1, section);
+ if (!success)
+ {
+ break;
+ }
+ }
+ }
+ globfree(&buf);
+ }
+#else /* HAVE_GLOB_H */
+ /* if glob(3) is not available, try to load pattern directly */
+ success = parse_file(contents, pat, level + 1, section);
+#endif /* HAVE_GLOB_H */
+ return success;
+}
+
+/**
+ * Recursivly extends "base" with "extension".
+ */
+static void section_extend(section_t *base, section_t *extension)
+{
+ enumerator_t *enumerator;
+ section_t *sec;
+ kv_t *kv;
+
+ enumerator = extension->sections->create_enumerator(extension->sections);
+ while (enumerator->enumerate(enumerator, (void**)&sec))
+ {
+ section_t *found;
+ if (base->sections->find_first(base->sections,
+ (linked_list_match_t)section_find, (void**)&found,
+ sec->name) == SUCCESS)
+ {
+ section_extend(found, sec);
+ }
+ else
+ {
+ extension->sections->remove_at(extension->sections, enumerator);
+ base->sections->insert_last(base->sections, sec);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ enumerator = extension->kv->create_enumerator(extension->kv);
+ while (enumerator->enumerate(enumerator, (void**)&kv))
+ {
+ kv_t *found;
+ if (base->kv->find_first(base->kv, (linked_list_match_t)kv_find,
+ (void**)&found, kv->key) == SUCCESS)
+ {
+ found->value = kv->value;
+ }
+ else
+ {
+ extension->kv->remove_at(extension->kv, enumerator);
+ base->kv->insert_last(base->kv, kv);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Load settings from files matching the given file pattern.
+ * All sections and values are added relative to "parent".
+ * All files (even included ones) have to be loaded successfully.
+ */
+static bool load_files_internal(private_settings_t *this, section_t *parent,
+ char *pattern, bool merge)
+{
+ char *text;
+ linked_list_t *contents;
+ section_t *section;
+
+ if (pattern == NULL)
+ {
+#ifdef STRONGSWAN_CONF
+ pattern = STRONGSWAN_CONF;
+#else
+ return FALSE;
+#endif
+ }
+
+ contents = linked_list_create();
+ section = section_create(NULL);
+
+ if (!parse_files(contents, NULL, 0, pattern, section))
+ {
+ contents->destroy_function(contents, (void*)free);
+ section_destroy(section);
+ return FALSE;
+ }
+
+ this->lock->write_lock(this->lock);
+ if (!merge)
+ {
+ section_purge(parent);
+ }
+ /* extend parent section */
+ section_extend(parent, section);
+ /* move contents of loaded files to main store */
+ while (contents->remove_first(contents, (void**)&text) == SUCCESS)
+ {
+ this->contents->insert_last(this->contents, text);
+ }
+ this->lock->unlock(this->lock);
+
+ section_destroy(section);
+ contents->destroy(contents);
+ return TRUE;
+}
+
+METHOD(settings_t, load_files, bool,
+ private_settings_t *this, char *pattern, bool merge)
+{
+ return load_files_internal(this, this->top, pattern, merge);
+}
+
+METHOD(settings_t, load_files_section, bool,
+ private_settings_t *this, char *pattern, bool merge, char *key, ...)
+{
+ section_t *section;
+ va_list args;
+
+ va_start(args, key);
+ section = ensure_section(this, this->top, key, args);
+ va_end(args);
+
+ if (!section)
+ {
+ return FALSE;
+ }
+ return load_files_internal(this, section, pattern, merge);
+}
+
+METHOD(settings_t, destroy, void,
+ private_settings_t *this)
+{
+ section_destroy(this->top);
+ this->contents->destroy_function(this->contents, (void*)free);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+settings_t *settings_create(char *file)
+{
+ private_settings_t *this;
+
+ INIT(this,
+ .public = {
+ .get_str = _get_str,
+ .get_int = _get_int,
+ .get_double = _get_double,
+ .get_time = _get_time,
+ .get_bool = _get_bool,
+ .set_str = _set_str,
+ .set_int = _set_int,
+ .set_double = _set_double,
+ .set_time = _set_time,
+ .set_bool = _set_bool,
+ .create_section_enumerator = _create_section_enumerator,
+ .create_key_value_enumerator = _create_key_value_enumerator,
+ .load_files = _load_files,
+ .load_files_section = _load_files_section,
+ .destroy = _destroy,
+ },
+ .top = section_create(NULL),
+ .contents = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ load_files(this, file, FALSE);
+
+ return &this->public;
+}
+
diff --git a/src/libstrongswan/utils/settings.h b/src/libstrongswan/utils/settings.h
new file mode 100644
index 000000000..a861325f5
--- /dev/null
+++ b/src/libstrongswan/utils/settings.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * 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 settings settings
+ * @{ @ingroup utils
+ */
+
+#ifndef SETTINGS_H_
+#define SETTINGS_H_
+
+typedef struct settings_t settings_t;
+
+#include "utils.h"
+#include "collections/enumerator.h"
+
+/**
+ * Convert a string value returned by a key/value enumerator to a boolean.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_bool()
+ * @param value the string value
+ * @param def the default value, if value is NULL or invalid
+ */
+bool settings_value_as_bool(char *value, bool def);
+
+/**
+ * Convert a string value returned by a key/value enumerator to an integer.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_int()
+ * @param value the string value
+ * @param def the default value, if value is NULL or invalid
+ */
+int settings_value_as_int(char *value, int def);
+
+/**
+ * Convert a string value returned by a key/value enumerator to a double.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_double()
+ * @param value the string value
+ * @param def the default value, if value is NULL or invalid
+ */
+double settings_value_as_double(char *value, double def);
+
+/**
+ * Convert a string value returned by a key/value enumerator to a time value.
+ *
+ * @see settings_t.create_key_value_enumerator()
+ * @see settings_t.get_time()
+ * @param value the string value
+ * @param def the default value, if value is NULL or invalid
+ */
+u_int32_t settings_value_as_time(char *value, u_int32_t def);
+
+/**
+ * Generic configuration options read from a config file.
+ *
+ * The syntax is quite simple:
+ * @code
+ * settings := (section|keyvalue)*
+ * section := name { settings }
+ * keyvalue := key = value\n
+ * @endcode
+ * E.g.:
+ * @code
+ a = b
+ section-one {
+ somevalue = asdf
+ subsection {
+ othervalue = xxx
+ }
+ yetanother = zz
+ }
+ section-two {
+ }
+ @endcode
+ *
+ * The values are accessed using the get() functions using dotted keys, e.g.
+ * section-one.subsection.othervalue
+ *
+ * Currently only a limited set of printf format specifiers are supported
+ * (namely %s, %d and %N, see implementation for details).
+ *
+ * \section includes Including other files
+ * Other files can be included, using the include statement e.g.
+ * @code
+ * include /somepath/subconfig.conf
+ * @endcode
+ * Shell patterns like *.conf are possible.
+ *
+ * If the path is relative, the directory of the file containing the include
+ * statement is used as base.
+ *
+ * Sections loaded from included files extend previously loaded sections,
+ * already existing values are replaced.
+ *
+ * All settings included from files are added relative to the section the
+ * include statement is in.
+ *
+ * The following files result in the same final config as above:
+ *
+ * @code
+ a = b
+ section-one {
+ somevalue = before include
+ include include.conf
+ }
+ include two.conf
+ @endcode
+ * include.conf
+ * @code
+ somevalue = asdf
+ subsection {
+ othervalue = yyy
+ }
+ yetanother = zz
+ @endcode
+ * two.conf
+ * @code
+ section-one {
+ subsection {
+ othervalue = xxx
+ }
+ }
+ section-two {
+ }
+ @endcode
+ */
+struct settings_t {
+
+ /**
+ * Get a settings value as a string.
+ *
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
+ * @return value pointing to internal string
+ */
+ char* (*get_str)(settings_t *this, char *key, char *def, ...);
+
+ /**
+ * Get a boolean yes|no, true|false value.
+ *
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
+ * @return value of the key
+ */
+ bool (*get_bool)(settings_t *this, char *key, bool def, ...);
+
+ /**
+ * Get an integer value.
+ *
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
+ * @return value of the key
+ */
+ int (*get_int)(settings_t *this, char *key, int def, ...);
+
+ /**
+ * Get an double value.
+ *
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
+ * @return value of the key
+ */
+ double (*get_double)(settings_t *this, char *key, double def, ...);
+
+ /**
+ * Get a time value.
+ *
+ * @param key key including sections, printf style format
+ * @param def value returned if key not found
+ * @param ... argument list for key
+ * @return value of the key (in seconds)
+ */
+ u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...);
+
+ /**
+ * Set a string value.
+ *
+ * @param key key including sections, printf style format
+ * @param value value to set (gets cloned)
+ * @param ... argument list for key
+ */
+ void (*set_str)(settings_t *this, char *key, char *value, ...);
+
+ /**
+ * Set a boolean value.
+ *
+ * @param key key including sections, printf style format
+ * @param value value to set
+ * @param ... argument list for key
+ */
+ void (*set_bool)(settings_t *this, char *key, bool value, ...);
+
+ /**
+ * Set an integer value.
+ *
+ * @param key key including sections, printf style format
+ * @param value value to set
+ * @param ... argument list for key
+ */
+ void (*set_int)(settings_t *this, char *key, int value, ...);
+
+ /**
+ * Set an double value.
+ *
+ * @param key key including sections, printf style format
+ * @param value value to set
+ * @param ... argument list for key
+ */
+ void (*set_double)(settings_t *this, char *key, double value, ...);
+
+ /**
+ * Set a time value.
+ *
+ * @param key key including sections, printf style format
+ * @param def value to set
+ * @param ... argument list for key
+ */
+ void (*set_time)(settings_t *this, char *key, u_int32_t value, ...);
+
+ /**
+ * Create an enumerator over subsection names of a section.
+ *
+ * @param section section including parents, printf style format
+ * @param ... argument list for key
+ * @return enumerator over subsection names
+ */
+ enumerator_t* (*create_section_enumerator)(settings_t *this,
+ char *section, ...);
+
+ /**
+ * Create an enumerator over key/value pairs in a section.
+ *
+ * @param section section name to list key/value pairs of, printf style
+ * @param ... argument list for section
+ * @return enumerator over (char *key, char *value)
+ */
+ enumerator_t* (*create_key_value_enumerator)(settings_t *this,
+ char *section, ...);
+
+ /**
+ * Load settings from the files matching the given pattern.
+ *
+ * If merge is TRUE, existing sections are extended, existing values
+ * replaced, by those found in the loaded files. If it is FALSE, existing
+ * sections are purged before reading the new config.
+ *
+ * @note If any of the files matching the pattern fails to load, no settings
+ * are added at all. So, it's all or nothing.
+ *
+ * @param pattern file pattern
+ * @param merge TRUE to merge config with existing values
+ * @return TRUE, if settings were loaded successfully
+ */
+ bool (*load_files)(settings_t *this, char *pattern, bool merge);
+
+ /**
+ * Load settings from the files matching the given pattern.
+ *
+ * If merge is TRUE, existing sections are extended, existing values
+ * replaced, by those found in the loaded files. If it is FALSE, existing
+ * sections are purged before reading the new config.
+ *
+ * All settings are loaded relative to the given section. The section is
+ * created, if it does not yet exist.
+ *
+ * @note If any of the files matching the pattern fails to load, no settings
+ * are added at all. So, it's all or nothing.
+ *
+ * @param pattern file pattern
+ * @param merge TRUE to merge config with existing values
+ * @param section section name of parent section, printf style
+ * @param ... argument list for section
+ * @return TRUE, if settings were loaded successfully
+ */
+ bool (*load_files_section)(settings_t *this, char *pattern, bool merge,
+ char *section, ...);
+
+ /**
+ * Destroy a settings instance.
+ */
+ void (*destroy)(settings_t *this);
+};
+
+/**
+ * Load settings from a file.
+ *
+ * @param file file to read settings from, NULL for default
+ * @return settings object
+ */
+settings_t *settings_create(char *file);
+
+#endif /** SETTINGS_H_ @}*/
diff --git a/src/libstrongswan/utils/tun_device.c b/src/libstrongswan/utils/tun_device.c
deleted file mode 100644
index 36f3359c0..000000000
--- a/src/libstrongswan/utils/tun_device.c
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * Copyright (C) 2012 Giuliano Grassi
- * Copyright (C) 2012 Ralf Sager
- * Hochschule fuer Technik Rapperswil
- * Copyright (C) 2012 Martin Willi
- *
- * 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.
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <net/if.h>
-
-#ifdef __APPLE__
-#include <net/if_utun.h>
-#include <netinet/in_var.h>
-#include <sys/kern_control.h>
-#elif defined(__linux__)
-#include <linux/if_tun.h>
-#else
-#include <net/if_tun.h>
-#endif
-
-#include "tun_device.h"
-
-#include <library.h>
-#include <debug.h>
-#include <threading/thread.h>
-
-#define TUN_DEFAULT_MTU 1500
-
-typedef struct private_tun_device_t private_tun_device_t;
-
-struct private_tun_device_t {
-
- /**
- * Public interface
- */
- tun_device_t public;
-
- /**
- * The TUN device's file descriptor
- */
- int tunfd;
-
- /**
- * Name of the TUN device
- */
- char if_name[IFNAMSIZ];
-
- /**
- * Socket used for ioctl() to set interface addr, ...
- */
- int sock;
-
- /**
- * The current MTU
- */
- int mtu;
-};
-
-/**
- * Set the sockaddr_t from the given netmask
- */
-static void set_netmask(struct ifreq *ifr, int family, u_int8_t netmask)
-{
- int len, bytes, bits;
- char *target;
-
- switch (family)
- {
- case AF_INET:
- {
- struct sockaddr_in *addr = (struct sockaddr_in*)&ifr->ifr_addr;
- addr->sin_family = AF_INET;
- target = (char*)&addr->sin_addr;
- len = 4;
- break;
- }
- case AF_INET6:
- {
- struct sockaddr_in6 *addr = (struct sockaddr_in6*)&ifr->ifr_addr;
- addr->sin6_family = AF_INET6;
- target = (char*)&addr->sin6_addr;
- len = 16;
- break;
- }
- default:
- return;
- }
-
- bytes = (netmask + 7) / 8;
- bits = (bytes * 8) - netmask;
-
- memset(target, 0xff, bytes);
- memset(target + bytes, 0x00, len - bytes);
- target[bytes - 1] = bits ? (u_int8_t)(0xff << bits) : 0xff;
-}
-
-METHOD(tun_device_t, set_address, bool,
- private_tun_device_t *this, host_t *addr, u_int8_t netmask)
-{
- struct ifreq ifr;
- int family;
-
- family = addr->get_family(addr);
- if ((netmask > 32 && family == AF_INET) || netmask > 128)
- {
- DBG1(DBG_LIB, "failed to set address on %s: invalid netmask",
- this->if_name);
- return FALSE;
- }
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
- memcpy(&ifr.ifr_addr, addr->get_sockaddr(addr), sizeof(sockaddr_t));
-
- if (ioctl(this->sock, SIOCSIFADDR, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to set address on %s: %s",
- this->if_name, strerror(errno));
- return FALSE;
- }
-#ifdef __APPLE__
- if (ioctl(this->sock, SIOCSIFDSTADDR, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to set dest address on %s: %s",
- this->if_name, strerror(errno));
- return FALSE;
- }
-#endif /* __APPLE__ */
-
- set_netmask(&ifr, family, netmask);
-
- if (ioctl(this->sock, SIOCSIFNETMASK, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to set netmask on %s: %s",
- this->if_name, strerror(errno));
- return FALSE;
- }
- return TRUE;
-}
-
-METHOD(tun_device_t, up, bool,
- private_tun_device_t *this)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
-
- if (ioctl(this->sock, SIOCGIFFLAGS, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to get interface flags for %s: %s", this->if_name,
- strerror(errno));
- return FALSE;
- }
-
- ifr.ifr_flags |= IFF_RUNNING | IFF_UP;
-
- if (ioctl(this->sock, SIOCSIFFLAGS, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to set interface flags on %s: %s", this->if_name,
- strerror(errno));
- return FALSE;
- }
- return TRUE;
-}
-
-METHOD(tun_device_t, set_mtu, bool,
- private_tun_device_t *this, int mtu)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
- ifr.ifr_mtu = mtu;
-
- if (ioctl(this->sock, SIOCSIFMTU, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to set MTU on %s: %s", this->if_name,
- strerror(errno));
- return FALSE;
- }
- this->mtu = mtu;
- return TRUE;
-}
-
-METHOD(tun_device_t, get_mtu, int,
- private_tun_device_t *this)
-{
- struct ifreq ifr;
-
- if (this->mtu > 0)
- {
- return this->mtu;
- }
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
- this->mtu = TUN_DEFAULT_MTU;
-
- if (ioctl(this->sock, SIOCGIFMTU, &ifr) == 0)
- {
- this->mtu = ifr.ifr_mtu;
- }
- return this->mtu;
-}
-
-METHOD(tun_device_t, get_name, char*,
- private_tun_device_t *this)
-{
- return this->if_name;
-}
-
-METHOD(tun_device_t, write_packet, bool,
- private_tun_device_t *this, chunk_t packet)
-{
- ssize_t s;
-
- s = write(this->tunfd, packet.ptr, packet.len);
- if (s < 0)
- {
- DBG1(DBG_LIB, "failed to write packet to TUN device %s: %s",
- this->if_name, strerror(errno));
- return FALSE;
- }
- else if (s != packet.len)
- {
- return FALSE;
- }
- return TRUE;
-}
-
-METHOD(tun_device_t, read_packet, bool,
- private_tun_device_t *this, chunk_t *packet)
-{
- ssize_t len;
- fd_set set;
- bool old;
-
- FD_ZERO(&set);
- FD_SET(this->tunfd, &set);
-
- old = thread_cancelability(TRUE);
- len = select(this->tunfd + 1, &set, NULL, NULL, NULL);
- thread_cancelability(old);
-
- if (len < 0)
- {
- DBG1(DBG_LIB, "select on TUN device %s failed: %s", this->if_name,
- strerror(errno));
- return FALSE;
- }
- /* FIXME: this is quite expensive for lots of small packets, copy from
- * local buffer instead? */
- *packet = chunk_alloc(get_mtu(this));
- len = read(this->tunfd, packet->ptr, packet->len);
- if (len < 0)
- {
- DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
- strerror(errno));
- chunk_free(packet);
- return FALSE;
- }
- packet->len = len;
- return TRUE;
-}
-
-METHOD(tun_device_t, destroy, void,
- private_tun_device_t *this)
-{
- if (this->tunfd > 0)
- {
- close(this->tunfd);
-#ifdef __FreeBSD__
- /* tun(4) says the following: "These network interfaces persist until
- * the if_tun.ko module is unloaded, or until removed with the
- * ifconfig(8) command." So simply closing the FD is not enough. */
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
- if (ioctl(this->sock, SIOCIFDESTROY, &ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to destroy %s: %s", this->if_name,
- strerror(errno));
- }
-#endif /* __FreeBSD__ */
- }
- if (this->sock > 0)
- {
- close(this->sock);
- }
- free(this);
-}
-
-/**
- * Initialize the tun device
- */
-static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
-{
-#ifdef __APPLE__
-
- struct ctl_info info;
- struct sockaddr_ctl addr;
- socklen_t size = IFNAMSIZ;
-
- memset(&info, 0, sizeof(info));
- memset(&addr, 0, sizeof(addr));
-
- this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
- if (this->tunfd < 0)
- {
- DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
- strerror(errno));
- return FALSE;
- }
-
- /* get a control identifier for the utun kernel extension */
- strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
- if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
- {
- DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
- close(this->tunfd);
- return FALSE;
- }
-
- addr.sc_id = info.ctl_id;
- addr.sc_len = sizeof(addr);
- addr.sc_family = AF_SYSTEM;
- addr.ss_sysaddr = AF_SYS_CONTROL;
- /* allocate identifier dynamically */
- addr.sc_unit = 0;
-
- if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
- {
- DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
- close(this->tunfd);
- return FALSE;
- }
- if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
- this->if_name, &size) < 0)
- {
- DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
- close(this->tunfd);
- return FALSE;
- }
- return TRUE;
-
-#elif defined(IFF_TUN)
-
- struct ifreq ifr;
-
- strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
- this->if_name[IFNAMSIZ-1] = '\0';
-
- this->tunfd = open("/dev/net/tun", O_RDWR);
- if (this->tunfd < 0)
- {
- DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
- return FALSE;
- }
-
- memset(&ifr, 0, sizeof(ifr));
-
- /* TUN device, no packet info */
- ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
-
- strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
- if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
- {
- DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
- close(this->tunfd);
- return FALSE;
- }
- strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
- return TRUE;
-
-#else /* !IFF_TUN */
-
- /* this works on FreeBSD and might also work on Linux with older TUN
- * driver versions (no IFF_TUN) */
- char devname[IFNAMSIZ];
- int i;
-
- if (name_tmpl)
- {
- DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
- }
-
- for (i = 0; i < 256; i++)
- {
- snprintf(devname, IFNAMSIZ, "/dev/tun%d", i);
- this->tunfd = open(devname, O_RDWR);
- if (this->tunfd > 0)
- { /* for ioctl(2) calls only the interface name is used */
- snprintf(this->if_name, IFNAMSIZ, "tun%d", i);
- break;
- }
- DBG1(DBG_LIB, "failed to open %s: %s", this->if_name, strerror(errno));
- }
- return this->tunfd > 0;
-
-#endif /* !__APPLE__ */
-}
-
-/*
- * Described in header
- */
-tun_device_t *tun_device_create(const char *name_tmpl)
-{
- private_tun_device_t *this;
-
- INIT(this,
- .public = {
- .read_packet = _read_packet,
- .write_packet = _write_packet,
- .get_mtu = _get_mtu,
- .set_mtu = _set_mtu,
- .get_name = _get_name,
- .set_address = _set_address,
- .up = _up,
- .destroy = _destroy,
- },
- .tunfd = -1,
- .sock = -1,
- );
-
- if (!init_tun(this, name_tmpl))
- {
- free(this);
- return NULL;
- }
- DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
-
- this->sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (this->sock < 0)
- {
- DBG1(DBG_LIB, "failed to open socket to configure TUN device");
- destroy(this);
- return NULL;
- }
- return &this->public;
-}
diff --git a/src/libstrongswan/utils/tun_device.h b/src/libstrongswan/utils/tun_device.h
deleted file mode 100644
index 71af0386b..000000000
--- a/src/libstrongswan/utils/tun_device.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2012 Tobias Brunner
- * Copyright (C) 2012 Giuliano Grassi
- * Copyright (C) 2012 Ralf Sager
- * 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 tun_device tun_device
- * @{ @ingroup utils
- */
-
-#ifndef TUN_DEVICE_H_
-#define TUN_DEVICE_H_
-
-#include <library.h>
-#include <utils/host.h>
-
-typedef struct tun_device_t tun_device_t;
-
-/**
- * Class to create TUN devices
- *
- * Creating such a device requires the CAP_NET_ADMIN capability.
- *
- * @note The implementation is currently very Linux specific
- */
-struct tun_device_t {
-
- /**
- * Read a packet from the TUN device
- *
- * @note This call blocks until a packet is available. It is a thread
- * cancellation point.
- *
- * @param packet the packet read from the device
- * @return TRUE if successful
- */
- bool (*read_packet)(tun_device_t *this, chunk_t *packet);
-
- /**
- * Write a packet to the TUN device
- *
- * @param packet the packet to write to the TUN device
- * @return TRUE if successful
- */
- bool (*write_packet)(tun_device_t *this, chunk_t packet);
-
- /**
- * Set the IP address of the device
- *
- * @param addr the desired interface address
- * @param netmask the netmask to use
- * @return TRUE if operation successful
- */
- bool (*set_address)(tun_device_t *this, host_t *addr, u_int8_t netmask);
-
- /**
- * Bring the TUN device up
- *
- * @return TRUE if operation successful
- */
- bool (*up)(tun_device_t *this);
-
- /**
- * Set the MTU for this TUN device
- *
- * @param mtu new MTU
- * @return TRUE if operation successful
- */
- bool (*set_mtu)(tun_device_t *this, int mtu);
-
- /**
- * Get the current MTU for this TUN device
- *
- * @return current MTU
- */
- int (*get_mtu)(tun_device_t *this);
-
- /**
- * Get the interface name of this device
- *
- * @return interface name
- */
- char *(*get_name)(tun_device_t *this);
-
- /**
- * Destroy a tun_device_t
- */
- void (*destroy)(tun_device_t *this);
-
-};
-
-/**
- * Create a TUN device using the given name template.
- *
- * @param name_tmpl name template, defaults to "tun%d" if not given
- * @return TUN device
- */
-tun_device_t *tun_device_create(const char *name_tmpl);
-
-#endif /** TUN_DEVICE_H_ @}*/
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
new file mode 100644
index 000000000..bf0224c5f
--- /dev/null
+++ b/src/libstrongswan/utils/utils.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * 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.
+ */
+
+#include "utils.h"
+
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <limits.h>
+#include <dirent.h>
+#include <time.h>
+#include <pthread.h>
+
+#include "collections/enumerator.h"
+#include "utils/debug.h"
+
+ENUM(status_names, SUCCESS, NEED_MORE,
+ "SUCCESS",
+ "FAILED",
+ "OUT_OF_RES",
+ "ALREADY_DONE",
+ "NOT_SUPPORTED",
+ "INVALID_ARG",
+ "NOT_FOUND",
+ "PARSE_ERROR",
+ "VERIFY_ERROR",
+ "INVALID_STATE",
+ "DESTROY_ME",
+ "NEED_MORE",
+);
+
+/**
+ * Described in header.
+ */
+void *clalloc(void * pointer, size_t size)
+{
+ void *data;
+ data = malloc(size);
+
+ memcpy(data, pointer, size);
+
+ return (data);
+}
+
+/**
+ * Described in header.
+ */
+void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
+{
+ int m, i;
+
+ /* byte wise XOR until dst aligned */
+ for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
+ {
+ dst[i] ^= src[i];
+ }
+ /* try to use words if src shares an aligment with dst */
+ switch (((uintptr_t)&src[i] % sizeof(long)))
+ {
+ case 0:
+ for (m = n - sizeof(long); i <= m; i += sizeof(long))
+ {
+ *(long*)&dst[i] ^= *(long*)&src[i];
+ }
+ break;
+ case sizeof(int):
+ for (m = n - sizeof(int); i <= m; i += sizeof(int))
+ {
+ *(int*)&dst[i] ^= *(int*)&src[i];
+ }
+ break;
+ case sizeof(short):
+ for (m = n - sizeof(short); i <= m; i += sizeof(short))
+ {
+ *(short*)&dst[i] ^= *(short*)&src[i];
+ }
+ break;
+ default:
+ break;
+ }
+ /* byte wise XOR of the rest */
+ for (; i < n; i++)
+ {
+ dst[i] ^= src[i];
+ }
+}
+
+/**
+ * Described in header.
+ */
+void memwipe_noinline(void *ptr, size_t n)
+{
+ memwipe_inline(ptr, n);
+}
+
+/**
+ * Described in header.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n)
+{
+ unsigned const char *pos = haystack;
+ size_t l = strlen(needle);
+ for (; n >= l; ++pos, --n)
+ {
+ if (memeq(pos, needle, l))
+ {
+ return (void*)pos;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Described in header.
+ */
+char* translate(char *str, const char *from, const char *to)
+{
+ char *pos = str;
+ if (strlen(from) != strlen(to))
+ {
+ return str;
+ }
+ while (pos && *pos)
+ {
+ char *match;
+ if ((match = strchr(from, *pos)) != NULL)
+ {
+ *pos = to[match - from];
+ }
+ pos++;
+ }
+ return str;
+}
+
+/**
+ * Described in header.
+ */
+bool mkdir_p(const char *path, mode_t mode)
+{
+ int len;
+ char *pos, full[PATH_MAX];
+ pos = full;
+ if (!path || *path == '\0')
+ {
+ return TRUE;
+ }
+ len = snprintf(full, sizeof(full)-1, "%s", path);
+ if (len < 0 || len >= sizeof(full)-1)
+ {
+ DBG1(DBG_LIB, "path string %s too long", path);
+ return FALSE;
+ }
+ /* ensure that the path ends with a '/' */
+ if (full[len-1] != '/')
+ {
+ full[len++] = '/';
+ full[len] = '\0';
+ }
+ /* skip '/' at the beginning */
+ while (*pos == '/')
+ {
+ pos++;
+ }
+ while ((pos = strchr(pos, '/')))
+ {
+ *pos = '\0';
+ if (access(full, F_OK) < 0)
+ {
+ if (mkdir(full, mode) < 0)
+ {
+ DBG1(DBG_LIB, "failed to create directory %s", full);
+ return FALSE;
+ }
+ }
+ *pos = '/';
+ pos++;
+ }
+ return TRUE;
+}
+
+
+/**
+ * The size of the thread-specific error buffer
+ */
+#define STRERROR_BUF_LEN 256
+
+/**
+ * Key to store thread-specific error buffer
+ */
+static pthread_key_t strerror_buf_key;
+
+/**
+ * Only initialize the key above once
+ */
+static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
+
+/**
+ * Create the key used for the thread-specific error buffer
+ */
+static void create_strerror_buf_key()
+{
+ pthread_key_create(&strerror_buf_key, free);
+}
+
+/**
+ * Retrieve the error buffer assigned to the current thread (or create it)
+ */
+static inline char *get_strerror_buf()
+{
+ char *buf;
+
+ pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
+ buf = pthread_getspecific(strerror_buf_key);
+ if (!buf)
+ {
+ buf = malloc(STRERROR_BUF_LEN);
+ pthread_setspecific(strerror_buf_key, buf);
+ }
+ return buf;
+}
+
+#ifdef HAVE_STRERROR_R
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ char *buf = get_strerror_buf(), *msg;
+
+#ifdef STRERROR_R_CHAR_P
+ /* char* version which may or may not return the original buffer */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
+#else
+ /* int version returns 0 on success */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
+#endif
+ return msg;
+}
+#else /* HAVE_STRERROR_R */
+/* we actually wan't to call strerror(3) below */
+#undef strerror
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ char *buf = get_strerror_buf();
+
+ /* use a mutex to ensure calling strerror(3) is thread-safe */
+ pthread_mutex_lock(&mutex);
+ strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
+ pthread_mutex_unlock(&mutex);
+ buf[STRERROR_BUF_LEN - 1] = '\0';
+ return buf;
+}
+#endif /* HAVE_STRERROR_R */
+
+
+#ifndef HAVE_CLOSEFROM
+/**
+ * Described in header.
+ */
+void closefrom(int lowfd)
+{
+ char fd_dir[PATH_MAX];
+ int maxfd, fd, len;
+
+ /* try to close only open file descriptors on Linux... */
+ len = snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", getpid());
+ if (len > 0 && len < sizeof(fd_dir) && access(fd_dir, F_OK) == 0)
+ {
+ enumerator_t *enumerator = enumerator_create_directory(fd_dir);
+ if (enumerator)
+ {
+ char *rel;
+ while (enumerator->enumerate(enumerator, &rel, NULL, NULL))
+ {
+ fd = atoi(rel);
+ if (fd >= lowfd)
+ {
+ close(fd);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return;
+ }
+ }
+
+ /* ...fall back to closing all fds otherwise */
+ maxfd = (int)sysconf(_SC_OPEN_MAX);
+ if (maxfd < 0)
+ {
+ maxfd = 256;
+ }
+ for (fd = lowfd; fd < maxfd; fd++)
+ {
+ close(fd);
+ }
+}
+#endif /* HAVE_CLOSEFROM */
+
+/**
+ * Return monotonic time
+ */
+time_t time_monotonic(timeval_t *tv)
+{
+#if defined(HAVE_CLOCK_GETTIME) && \
+ (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
+ defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+ /* as we use time_monotonic() for condvar operations, we use the
+ * monotonic time source only if it is also supported by pthread. */
+ timespec_t ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ {
+ if (tv)
+ {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+ return ts.tv_sec;
+ }
+#endif /* HAVE_CLOCK_GETTIME && (...) */
+ /* Fallback to non-monotonic timestamps:
+ * On MAC OS X, creating monotonic timestamps is rather difficult. We
+ * could use mach_absolute_time() and catch sleep/wakeup notifications.
+ * We stick to the simpler (non-monotonic) gettimeofday() for now.
+ * But keep in mind: we need the same time source here as in condvar! */
+ if (!tv)
+ {
+ return time(NULL);
+ }
+ if (gettimeofday(tv, NULL) != 0)
+ { /* should actually never fail if passed pointers are valid */
+ return -1;
+ }
+ return tv->tv_sec;
+}
+
+/**
+ * return null
+ */
+void *return_null()
+{
+ return NULL;
+}
+
+/**
+ * returns TRUE
+ */
+bool return_true()
+{
+ return TRUE;
+}
+
+/**
+ * returns FALSE
+ */
+bool return_false()
+{
+ return FALSE;
+}
+
+/**
+ * returns FAILED
+ */
+status_t return_failed()
+{
+ return FAILED;
+}
+
+/**
+ * nop operation
+ */
+void nop()
+{
+}
+
+#ifndef HAVE_GCC_ATOMIC_OPERATIONS
+
+/**
+ * We use a single mutex for all refcount variables.
+ */
+static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Increase refcount
+ */
+void ref_get(refcount_t *ref)
+{
+ pthread_mutex_lock(&ref_mutex);
+ (*ref)++;
+ pthread_mutex_unlock(&ref_mutex);
+}
+
+/**
+ * Decrease refcount
+ */
+bool ref_put(refcount_t *ref)
+{
+ bool more_refs;
+
+ pthread_mutex_lock(&ref_mutex);
+ more_refs = --(*ref) > 0;
+ pthread_mutex_unlock(&ref_mutex);
+ return !more_refs;
+}
+
+/**
+ * Single mutex for all compare and swap operations.
+ */
+static pthread_mutex_t cas_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Compare and swap if equal to old value
+ */
+#define _cas_impl(name, type) \
+bool cas_##name(type *ptr, type oldval, type newval) \
+{ \
+ bool swapped; \
+ pthread_mutex_lock(&cas_mutex); \
+ if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
+ pthread_mutex_unlock(&cas_mutex); \
+ return swapped; \
+}
+
+_cas_impl(bool, bool)
+_cas_impl(ptr, void*)
+
+#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * Described in header.
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ static const char* months[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+ time_t *time = *((time_t**)(args[0]));
+ bool utc = *((bool*)(args[1]));;
+ struct tm t;
+
+ if (time == UNDEFINED_TIME)
+ {
+ return print_in_hook(data, "--- -- --:--:--%s----",
+ utc ? " UTC " : " ");
+ }
+ if (utc)
+ {
+ gmtime_r(time, &t);
+ }
+ else
+ {
+ localtime_r(time, &t);
+ }
+ return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
+ months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
+ t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
+}
+
+/**
+ * Described in header.
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ char* unit = "second";
+ time_t *arg1 = *((time_t**)(args[0]));
+ time_t *arg2 = *((time_t**)(args[1]));
+ u_int64_t delta = llabs(*arg1 - *arg2);
+
+ if (delta > 2 * 60 * 60 * 24)
+ {
+ delta /= 60 * 60 * 24;
+ unit = "day";
+ }
+ else if (delta > 2 * 60 * 60)
+ {
+ delta /= 60 * 60;
+ unit = "hour";
+ }
+ else if (delta > 2 * 60)
+ {
+ delta /= 60;
+ unit = "minute";
+ }
+ return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
+ (delta == 1) ? "" : "s");
+}
+
+/**
+ * Number of bytes per line to dump raw data
+ */
+#define BYTES_PER_LINE 16
+
+static char hexdig_upper[] = "0123456789ABCDEF";
+
+/**
+ * Described in header.
+ */
+int mem_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args)
+{
+ char *bytes = *((void**)(args[0]));
+ u_int len = *((int*)(args[1]));
+
+ char buffer[BYTES_PER_LINE * 3];
+ char ascii_buffer[BYTES_PER_LINE + 1];
+ char *buffer_pos = buffer;
+ char *bytes_pos = bytes;
+ char *bytes_roof = bytes + len;
+ int line_start = 0;
+ int i = 0;
+ int written = 0;
+
+ written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
+
+ while (bytes_pos < bytes_roof)
+ {
+ *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
+ *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
+
+ ascii_buffer[i++] =
+ (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
+
+ if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
+ {
+ int padding = 3 * (BYTES_PER_LINE - i);
+
+ while (padding--)
+ {
+ *buffer_pos++ = ' ';
+ }
+ *buffer_pos++ = '\0';
+ ascii_buffer[i] = '\0';
+
+ written += print_in_hook(data, "\n%4d: %s %s",
+ line_start, buffer, ascii_buffer);
+
+ buffer_pos = buffer;
+ line_start += BYTES_PER_LINE;
+ i = 0;
+ }
+ else
+ {
+ *buffer_pos++ = ' ';
+ }
+ }
+ return written;
+}
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
new file mode 100644
index 000000000..7b1beb93a
--- /dev/null
+++ b/src/libstrongswan/utils/utils.h
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * 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 utils_i utils
+ * @{ @ingroup utils
+ */
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "enum.h"
+
+/**
+ * strongSwan program return codes
+ */
+#define SS_RC_LIBSTRONGSWAN_INTEGRITY 64
+#define SS_RC_DAEMON_INTEGRITY 65
+#define SS_RC_INITIALIZATION_FAILED 66
+
+#define SS_RC_FIRST SS_RC_LIBSTRONGSWAN_INTEGRITY
+#define SS_RC_LAST SS_RC_INITIALIZATION_FAILED
+
+/**
+ * Number of bits in a byte
+ */
+#define BITS_PER_BYTE 8
+
+/**
+ * Default length for various auxiliary text buffers
+ */
+#define BUF_LEN 512
+
+/**
+ * General purpose boolean type.
+ */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# ifndef HAVE__BOOL
+# define _Bool signed char
+# endif /* HAVE__BOOL */
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif /* HAVE_STDBOOL_H */
+#ifndef FALSE
+# define FALSE false
+#endif /* FALSE */
+#ifndef TRUE
+# define TRUE true
+#endif /* TRUE */
+
+/**
+ * Helper function that compares two strings for equality
+ */
+static inline bool streq(const char *x, const char *y)
+{
+ return strcmp(x, y) == 0;
+}
+
+/**
+ * Macro compares two strings for equality, length limited
+ */
+#define strneq(x,y,len) (strncmp(x, y, len) == 0)
+
+/**
+ * Helper function that compares two strings for equality ignoring case
+ */
+static inline bool strcaseeq(const char *x, const char *y)
+{
+ return strcasecmp(x, y) == 0;
+}
+
+/**
+ * Macro compares two strings for equality ignoring case, length limited
+ */
+#define strncaseeq(x,y,len) (strncasecmp(x, y, len) == 0)
+
+/**
+ * NULL-safe strdup variant
+ */
+static inline char *strdupnull(const char *s)
+{
+ return s ? strdup(s) : NULL;
+}
+
+/**
+ * Macro compares two binary blobs for equality
+ */
+#define memeq(x,y,len) (memcmp(x, y, len) == 0)
+
+/**
+ * Macro gives back larger of two values.
+ */
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ _x > _y ? _x : _y; })
+
+
+/**
+ * Macro gives back smaller of two values.
+ */
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ _x < _y ? _x : _y; })
+
+/**
+ * Call destructor of an object, if object != NULL
+ */
+#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
+
+/**
+ * Call offset destructor of an object, if object != NULL
+ */
+#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
+
+/**
+ * Call function destructor of an object, if object != NULL
+ */
+#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
+
+/**
+ * Debug macro to follow control flow
+ */
+#define POS printf("%s, line %d\n", __FILE__, __LINE__)
+
+/**
+ * Object allocation/initialization macro, using designated initializer.
+ */
+#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
+
+/**
+ * Method declaration/definition macro, providing private and public interface.
+ *
+ * Defines a method name with this as first parameter and a return value ret,
+ * and an alias for this method with a _ prefix, having the this argument
+ * safely casted to the public interface iface.
+ * _name is provided a function pointer, but will get optimized out by GCC.
+ */
+#define METHOD(iface, name, ret, this, ...) \
+ static ret name(union {iface *_public; this;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(name) *_##name = (typeof(name)*)name; \
+ static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Same as METHOD(), but is defined for two public interfaces.
+ */
+#define METHOD2(iface1, iface2, name, ret, this, ...) \
+ static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(name) *_##name = (typeof(name)*)name; \
+ static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Architecture independent bitfield definition helpers (at least with GCC).
+ *
+ * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
+ * BITFIELD2(u_int8_t,
+ * low: 4,
+ * high: 4,
+ * ) flags;
+ * The member defined first placed at bit 0.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
+#elif BYTE_ORDER == BIG_ENDIAN
+#define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
+#endif
+
+/**
+ * Macro to allocate a sized type.
+ */
+#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
+
+/**
+ * Get the number of elements in an array
+ */
+#define countof(array) (sizeof(array)/sizeof(array[0]))
+
+/**
+ * Ignore result of functions tagged with warn_unused_result attributes
+ */
+#define ignore_result(call) { if(call){}; }
+
+/**
+ * Assign a function as a class method
+ */
+#define ASSIGN(method, function) (method = (typeof(method))function)
+
+/**
+ * time_t not defined
+ */
+#define UNDEFINED_TIME 0
+
+/**
+ * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
+ */
+#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
+
+/**
+ * define some missing fixed width int types on OpenSolaris.
+ * TODO: since the uintXX_t types are defined by the C99 standard we should
+ * probably use those anyway
+ */
+#ifdef __sun
+ #include <stdint.h>
+ typedef uint8_t u_int8_t;
+ typedef uint16_t u_int16_t;
+ typedef uint32_t u_int32_t;
+ typedef uint64_t u_int64_t;
+#endif
+
+typedef enum status_t status_t;
+
+/**
+ * Return values of function calls.
+ */
+enum status_t {
+ /**
+ * Call succeeded.
+ */
+ SUCCESS,
+
+ /**
+ * Call failed.
+ */
+ FAILED,
+
+ /**
+ * Out of resources.
+ */
+ OUT_OF_RES,
+
+ /**
+ * The suggested operation is already done
+ */
+ ALREADY_DONE,
+
+ /**
+ * Not supported.
+ */
+ NOT_SUPPORTED,
+
+ /**
+ * One of the arguments is invalid.
+ */
+ INVALID_ARG,
+
+ /**
+ * Something could not be found.
+ */
+ NOT_FOUND,
+
+ /**
+ * Error while parsing.
+ */
+ PARSE_ERROR,
+
+ /**
+ * Error while verifying.
+ */
+ VERIFY_ERROR,
+
+ /**
+ * Object in invalid state.
+ */
+ INVALID_STATE,
+
+ /**
+ * Destroy object which called method belongs to.
+ */
+ DESTROY_ME,
+
+ /**
+ * Another call to the method is required.
+ */
+ NEED_MORE,
+};
+
+/**
+ * enum_names for type status_t.
+ */
+extern enum_name_t *status_names;
+
+/**
+ * deprecated pluto style return value:
+ * error message, NULL for success
+ */
+typedef const char *err_t;
+
+/**
+ * Handle struct timeval like an own type.
+ */
+typedef struct timeval timeval_t;
+
+/**
+ * Handle struct timespec like an own type.
+ */
+typedef struct timespec timespec_t;
+
+/**
+ * Handle struct chunk_t like an own type.
+ */
+typedef struct sockaddr sockaddr_t;
+
+/**
+ * Clone a data to a newly allocated buffer
+ */
+void *clalloc(void *pointer, size_t size);
+
+/**
+ * Same as memcpy, but XORs src into dst instead of copy
+ */
+void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
+ */
+void memwipe_noinline(void *ptr, size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
+ */
+static inline void memwipe_inline(void *ptr, size_t n)
+{
+ volatile char *c = (volatile char*)ptr;
+ size_t m, i;
+
+ /* byte wise until long aligned */
+ for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
+ {
+ c[i] = 0;
+ }
+ /* word wise */
+ if (n >= sizeof(long))
+ {
+ for (m = n - sizeof(long); i <= m; i += sizeof(long))
+ {
+ *(volatile long*)&c[i] = 0;
+ }
+ }
+ /* byte wise of the rest */
+ for (; i < n; i++)
+ {
+ c[i] = 0;
+ }
+}
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
+ */
+static inline void memwipe(void *ptr, size_t n)
+{
+ if (__builtin_constant_p(n))
+ {
+ memwipe_inline(ptr, n);
+ }
+ else
+ {
+ memwipe_noinline(ptr, n);
+ }
+}
+
+/**
+ * A variant of strstr with the characteristics of memchr, where haystack is not
+ * a null-terminated string but simply a memory area of length n.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n);
+
+/**
+ * Translates the characters in the given string, searching for characters
+ * in 'from' and mapping them to characters in 'to'.
+ * The two characters sets 'from' and 'to' must contain the same number of
+ * characters.
+ */
+char *translate(char *str, const char *from, const char *to);
+
+/**
+ * Creates a directory and all required parent directories.
+ *
+ * @param path path to the new directory
+ * @param mode permissions of the new directory/directories
+ * @return TRUE on success
+ */
+bool mkdir_p(const char *path, mode_t mode);
+
+/**
+ * Thread-safe wrapper around strerror and strerror_r.
+ *
+ * This is required because the first is not thread-safe (on some platforms)
+ * and the second uses two different signatures (POSIX/GNU) and is impractical
+ * to use anyway.
+ *
+ * @param errnum error code (i.e. errno)
+ * @return error message
+ */
+const char *safe_strerror(int errnum);
+
+/**
+ * Replace usages of strerror(3) with thread-safe variant.
+ */
+#define strerror(errnum) safe_strerror(errnum)
+
+#ifndef HAVE_CLOSEFROM
+/**
+ * Close open file descriptors greater than or equal to lowfd.
+ *
+ * @param lowfd start closing file descriptoros from here
+ */
+void closefrom(int lowfd);
+#endif
+
+/**
+ * Get a timestamp from a monotonic time source.
+ *
+ * While the time()/gettimeofday() functions are affected by leap seconds
+ * and system time changes, this function returns ever increasing monotonic
+ * time stamps.
+ *
+ * @param tv timeval struct receiving monotonic timestamps, or NULL
+ * @return monotonic timestamp in seconds
+ */
+time_t time_monotonic(timeval_t *tv);
+
+/**
+ * Add the given number of milliseconds to the given timeval struct
+ *
+ * @param tv timeval struct to modify
+ * @param ms number of milliseconds
+ */
+static inline void timeval_add_ms(timeval_t *tv, u_int ms)
+{
+ tv->tv_usec += ms * 1000;
+ while (tv->tv_usec > 1000000 /* 1s */)
+ {
+ tv->tv_usec -= 1000000;
+ tv->tv_sec++;
+ }
+}
+
+/**
+ * returns null
+ */
+void *return_null();
+
+/**
+ * No-Operation function
+ */
+void nop();
+
+/**
+ * returns TRUE
+ */
+bool return_true();
+
+/**
+ * returns FALSE
+ */
+bool return_false();
+
+/**
+ * returns FAILED
+ */
+status_t return_failed();
+
+/**
+ * Write a 16-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 16-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun16(void *network, u_int16_t host)
+{
+ char *unaligned = (char*)network;
+
+ host = htons(host);
+ memcpy(unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 32-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 32-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun32(void *network, u_int32_t host)
+{
+ char *unaligned = (char*)network;
+
+ host = htonl(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 64-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 64-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun64(void *network, u_int64_t host)
+{
+ char *unaligned = (char*)network;
+
+#ifdef be64toh
+ host = htobe64(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+#else
+ u_int32_t high_part, low_part;
+
+ high_part = host >> 32;
+ high_part = htonl(high_part);
+ low_part = host & 0xFFFFFFFFLL;
+ low_part = htonl(low_part);
+
+ memcpy(unaligned, &high_part, sizeof(high_part));
+ unaligned += sizeof(high_part);
+ memcpy(unaligned, &low_part, sizeof(low_part));
+#endif
+}
+
+/**
+ * Read a 16-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int16_t untoh16(void *network)
+{
+ char *unaligned = (char*)network;
+ u_int16_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return ntohs(tmp);
+}
+
+/**
+ * Read a 32-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int32_t untoh32(void *network)
+{
+ char *unaligned = (char*)network;
+ u_int32_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return ntohl(tmp);
+}
+
+/**
+ * Read a 64-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int64_t untoh64(void *network)
+{
+ char *unaligned = (char*)network;
+
+#ifdef be64toh
+ u_int64_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return be64toh(tmp);
+#else
+ u_int32_t high_part, low_part;
+
+ memcpy(&high_part, unaligned, sizeof(high_part));
+ unaligned += sizeof(high_part);
+ memcpy(&low_part, unaligned, sizeof(low_part));
+
+ high_part = ntohl(high_part);
+ low_part = ntohl(low_part);
+
+ return (((u_int64_t)high_part) << 32) + low_part;
+#endif
+}
+
+/**
+ * Special type to count references
+ */
+typedef volatile u_int refcount_t;
+
+
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+
+#define ref_get(ref) {__sync_fetch_and_add(ref, 1); }
+#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
+
+#define cas_bool(ptr, oldval, newval) \
+ (__sync_bool_compare_and_swap(ptr, oldval, newval))
+#define cas_ptr(ptr, oldval, newval) \
+ (__sync_bool_compare_and_swap(ptr, oldval, newval))
+
+#else /* !HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * Get a new reference.
+ *
+ * Increments the reference counter atomic.
+ *
+ * @param ref pointer to ref counter
+ */
+void ref_get(refcount_t *ref);
+
+/**
+ * Put back a unused reference.
+ *
+ * Decrements the reference counter atomic and
+ * says if more references available.
+ *
+ * @param ref pointer to ref counter
+ * @return TRUE if no more references counted
+ */
+bool ref_put(refcount_t *ref);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr pointer to variable
+ * @param oldval old value of the variable
+ * @param newval new value set if possible
+ * @return TRUE if value equaled oldval and newval was written
+ */
+bool cas_bool(bool *ptr, bool oldval, bool newval);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr pointer to variable
+ * @param oldval old value of the variable
+ * @param newval new value set if possible
+ * @return TRUE if value equaled oldval and newval was written
+ */
+bool cas_ptr(void **ptr, void *oldval, void *newval);
+
+#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * printf hook for time_t.
+ *
+ * Arguments are:
+ * time_t* time, bool utc
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * printf hook for time_t deltas.
+ *
+ * Arguments are:
+ * time_t* begin, time_t* end
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * printf hook for memory areas.
+ *
+ * Arguments are:
+ * u_char *ptr, u_int len
+ */
+int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** UTILS_H_ @}*/