aboutsummaryrefslogtreecommitdiffstats
path: root/Source/lib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'Source/lib/utils')
-rw-r--r--Source/lib/utils/Makefile.utils48
-rw-r--r--Source/lib/utils/allocator.c445
-rw-r--r--Source/lib/utils/allocator.h324
-rw-r--r--Source/lib/utils/host.c365
-rw-r--r--Source/lib/utils/host.h225
-rw-r--r--Source/lib/utils/identification.c291
-rw-r--r--Source/lib/utils/identification.h211
-rw-r--r--Source/lib/utils/iterator.h153
-rw-r--r--Source/lib/utils/linked_list.c729
-rw-r--r--Source/lib/utils/linked_list.h203
-rw-r--r--Source/lib/utils/logger.c360
-rw-r--r--Source/lib/utils/logger.h199
-rw-r--r--Source/lib/utils/logger_manager.c212
-rw-r--r--Source/lib/utils/logger_manager.h155
-rw-r--r--Source/lib/utils/randomizer.c165
-rw-r--r--Source/lib/utils/randomizer.h110
-rw-r--r--Source/lib/utils/tester.c257
-rw-r--r--Source/lib/utils/tester.h148
18 files changed, 4600 insertions, 0 deletions
diff --git a/Source/lib/utils/Makefile.utils b/Source/lib/utils/Makefile.utils
new file mode 100644
index 000000000..ab513ff7a
--- /dev/null
+++ b/Source/lib/utils/Makefile.utils
@@ -0,0 +1,48 @@
+# Copyright (C) 2005 Jan Hutter, 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.
+#
+
+UTILS_DIR= $(LIB_DIR)utils/
+
+
+LIB_OBJS+= $(BUILD_DIR)allocator.o
+$(BUILD_DIR)allocator.o : $(UTILS_DIR)allocator.c $(UTILS_DIR)allocator.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)linked_list.o
+$(BUILD_DIR)linked_list.o : $(UTILS_DIR)linked_list.c $(UTILS_DIR)linked_list.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)logger.o
+$(BUILD_DIR)logger.o : $(UTILS_DIR)logger.c $(UTILS_DIR)logger.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)logger_manager.o
+$(BUILD_DIR)logger_manager.o : $(UTILS_DIR)logger_manager.c $(UTILS_DIR)logger_manager.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)randomizer.o
+$(BUILD_DIR)randomizer.o : $(UTILS_DIR)randomizer.c $(UTILS_DIR)randomizer.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)tester.o
+$(BUILD_DIR)tester.o : $(UTILS_DIR)tester.c $(UTILS_DIR)tester.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)identification.o
+$(BUILD_DIR)identification.o : $(UTILS_DIR)identification.c $(UTILS_DIR)identification.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+LIB_OBJS+= $(BUILD_DIR)host.o
+$(BUILD_DIR)host.o : $(UTILS_DIR)host.c $(UTILS_DIR)host.h
+ $(CC) $(CFLAGS) -c -o $@ $<
diff --git a/Source/lib/utils/allocator.c b/Source/lib/utils/allocator.c
new file mode 100644
index 000000000..0ed197c62
--- /dev/null
+++ b/Source/lib/utils/allocator.c
@@ -0,0 +1,445 @@
+/**
+ * @file allocator.c
+ *
+ * @brief Implementation of allocator_t.
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+#include <gmp.h>
+
+#include "allocator.h"
+
+
+#ifdef LEAK_DETECTIVE
+
+typedef union memory_hdr_t memory_hdr_t;
+
+/**
+ * @brief Header of each allocated memory area.
+ *
+ * Ideas stolen from pluto's defs.c.
+ *
+ * Used to detect memory leaks.
+ */
+union memory_hdr_t {
+ /**
+ * Informations.
+ */
+ struct {
+ /**
+ * Filename withing memory was allocated.
+ */
+ const char *filename;
+ /**
+ * Line number in given file.
+ */
+ size_t line;
+ /**
+ * Allocated memory size. Needed for reallocation.
+ */
+ size_t size_of_memory;
+ /**
+ * Link to the previous and next memory area.
+ */
+ memory_hdr_t *older, *newer;
+ } info;
+ /**
+ * Force maximal alignment ?
+ *
+ */
+ unsigned long junk;
+};
+
+typedef struct private_allocator_t private_allocator_t;
+
+/**
+ * @brief Private allocator_t object.
+ *
+ * Contains private variables of allocator_t object.
+ */
+struct private_allocator_t
+{
+ /**
+ * Public part of an allocator_t object.
+ */
+ allocator_t public;
+
+ /**
+ * Global list of allocations.
+ *
+ * Thread-save through mutex.
+ */
+ memory_hdr_t *allocations;
+
+ /**
+ * Mutex used to make sure, all functions are thread-save.
+ */
+ pthread_mutex_t mutex;
+
+ /**
+ * Number of allocations done
+ */
+ u_int32_t allocs;
+
+ /**
+ * Number of frees done
+ */
+ u_int32_t frees;
+
+ /**
+ * Allocates memory with LEAK_DETECTION and
+ * returns an empty data area filled with zeros.
+ *
+ * @param this private_allocator_t object
+ * @param bytes number of bytes to allocate
+ * @param file filename from which the memory is allocated
+ * @param line line number in specific file
+ * @param use_mutex if FALSE no mutex is used for allocation
+ * @return pointer to allocated memory area
+ */
+ void * (*allocate_special) (private_allocator_t *this,size_t bytes, char * file,int line, bool use_mutex);
+};
+
+/**
+ * Implementation of private_allocator_t.allocate_special.
+ */
+static void *allocate_special(private_allocator_t *this,size_t bytes, char * file,int line, bool use_mutex)
+{
+ memory_hdr_t *allocated_memory = malloc(sizeof(memory_hdr_t) + bytes);
+
+ this->allocs++;
+
+ if (allocated_memory == NULL)
+ {
+ /* TODO LOG this case */
+ exit(-1);
+ }
+
+ if (use_mutex)
+ {
+ pthread_mutex_lock( &(this->mutex));
+ }
+
+ allocated_memory->info.line = line;
+ allocated_memory->info.filename = file;
+ allocated_memory->info.size_of_memory = bytes;
+ allocated_memory->info.older = this->allocations;
+ if (this->allocations != NULL)
+ {
+ this->allocations->info.newer = allocated_memory;
+ }
+ this->allocations = allocated_memory;
+ allocated_memory->info.newer = NULL;
+
+ /* fill memory with zero's */
+ memset(allocated_memory+1, '\0', bytes);
+ if (use_mutex)
+ {
+ pthread_mutex_unlock(&(this->mutex));
+ }
+
+ /* real memory starts after header */
+ return (allocated_memory+1);
+}
+
+/**
+ * Implementation of allocator_t.allocate.
+ */
+static void * allocate(allocator_t *allocator,size_t bytes, char * file,int line)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+ return (this->allocate_special(this,bytes, file,line,TRUE));
+}
+
+/**
+ * Implementation of allocator_t.allocate_as_chunk.
+ */
+static chunk_t allocate_as_chunk(allocator_t *allocator,size_t bytes, char * file,int line)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+ chunk_t new_chunk;
+ new_chunk.ptr = this->allocate_special(this,bytes, file,line,TRUE);
+ new_chunk.len = (new_chunk.ptr == NULL) ? 0 : bytes;
+ return new_chunk;
+}
+
+/**
+ * Implementation of allocator_t.free_pointer.
+ */
+static void free_pointer(allocator_t *allocator, void * pointer)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+ memory_hdr_t *allocated_memory;
+
+
+ if (pointer == NULL)
+ {
+ return;
+ }
+ this->frees++;
+ pthread_mutex_lock( &(this->mutex));
+ allocated_memory = ((memory_hdr_t *)pointer) - 1;
+
+ if (allocated_memory->info.older != NULL)
+ {
+ assert(allocated_memory->info.older->info.newer == allocated_memory);
+ allocated_memory->info.older->info.newer = allocated_memory->info.newer;
+ }
+ if (allocated_memory->info.newer == NULL)
+ {
+ assert(allocated_memory == this->allocations);
+ this->allocations = allocated_memory->info.older;
+ }
+ else
+ {
+ assert(allocated_memory->info.newer->info.older == allocated_memory);
+ allocated_memory->info.newer->info.older = allocated_memory->info.older;
+ }
+ pthread_mutex_unlock(&(this->mutex));
+ free(allocated_memory);
+}
+
+/**
+ * Implementation of allocator_t.reallocate.
+ */
+static void * reallocate(allocator_t *allocator, void * old, size_t bytes, char * file,int line)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+ memory_hdr_t *allocated_memory;
+
+
+ pthread_mutex_lock( &(this->mutex));
+ allocated_memory = ((memory_hdr_t *)old) - 1;
+
+ void *new_space = this->allocate_special(this,bytes,file,line,FALSE);
+
+ if (old != NULL)
+ {
+ /* the smaller size is copied to avoid overflows */
+ memcpy(new_space,old,(allocated_memory->info.size_of_memory < bytes) ? allocated_memory->info.size_of_memory : bytes);
+ }
+ pthread_mutex_unlock(&(this->mutex));
+ this->public.free_pointer(&(this->public),old);
+
+ return new_space;
+}
+
+/**
+ * Implementation of allocator_t.clone_bytes.
+ */
+static void * clone_bytes(allocator_t *allocator,void * to_clone, size_t bytes, char * file, int line)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+
+ if (to_clone == NULL)
+ {
+ return NULL;
+ }
+
+
+ void *new_space = this->allocate_special(this,bytes,file,line,TRUE);
+
+ if (new_space == NULL)
+ {
+ return NULL;
+ }
+
+ memcpy(new_space,to_clone,bytes);
+
+ return new_space;
+}
+
+/**
+ * Implementation of allocator_t.clone_chunk.
+ */
+static chunk_t clone_chunk(allocator_t *allocator, chunk_t chunk, char * file, int line)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+ chunk_t clone = CHUNK_INITIALIZER;
+
+ if (chunk.ptr && chunk.len > 0)
+ {
+ clone.ptr = this->allocate_special(this,chunk.len,file,line,TRUE);
+ clone.len = chunk.len;
+ memcpy(clone.ptr, chunk.ptr, chunk.len);
+ }
+
+ return clone;
+}
+
+/**
+ * Implementation of allocator_t.allocator_report_memory_leaks.
+ */
+static void allocator_report_memory_leaks(allocator_t *allocator)
+{
+ private_allocator_t *this = (private_allocator_t *) allocator;
+ memory_hdr_t *p = this->allocations;
+ memory_hdr_t *pprev = NULL;
+ unsigned long n = 0;
+
+ pthread_mutex_lock(&(this->mutex));
+
+ while (p != NULL)
+ {
+ assert(pprev == p->info.newer);
+ pprev = p;
+ p = p->info.older;
+ n++;
+ if (p == NULL || pprev->info.filename != p->info.filename)
+ {
+ if (n != 1)
+ fprintf(stderr,"LEAK: \"%lu * %s, line %d\"\n", n, pprev->info.filename,pprev->info.line);
+ else
+ fprintf(stderr,"LEAK: \"%s, line %d\"\n", pprev->info.filename,pprev->info.line);
+ n = 0;
+ }
+ }
+ pthread_mutex_unlock( &(this->mutex));
+ fprintf(stderr, "Allocator statistics: %d allocs, %d frees\n", this->allocs, this->frees);
+}
+
+/**
+ * Only Initiation of allocator object.
+ *
+ * All allocation macros use this object.
+ */
+static private_allocator_t allocator = {
+ public: {allocate: allocate,
+ allocate_as_chunk: allocate_as_chunk,
+ free_pointer: free_pointer,
+ reallocate: reallocate,
+ clone_bytes : clone_bytes,
+ clone_chunk : clone_chunk,
+ report_memory_leaks: allocator_report_memory_leaks},
+ allocations: NULL,
+ allocate_special : allocate_special,
+ mutex: PTHREAD_MUTEX_INITIALIZER,
+ allocs: 0,
+ frees: 0
+};
+
+
+allocator_t *global_allocator = &(allocator.public);
+
+/*
+ * Alloc function for gmp.
+ */
+void *gmp_alloc(size_t bytes)
+{
+ return allocator.allocate_special(&allocator, bytes, "[ gmp internal ]", 0 , TRUE);
+}
+
+/*
+ * Realloc function for gmp.
+ */
+void *gmp_realloc(void *old, size_t old_bytes, size_t new_bytes)
+{
+ return global_allocator->reallocate(global_allocator, old, new_bytes, "[ gmp internal ]", 0);
+}
+/*
+ * Free function for gmp.
+ */
+void gmp_free(void *ptr, size_t bytes)
+{
+ free_pointer(global_allocator, ptr);
+}
+
+/*
+ * Described in header
+ */
+void allocator_init()
+{
+ mp_set_memory_functions (gmp_alloc, gmp_realloc, gmp_free);
+}
+
+#else /* !LEAK_DETECTION */
+
+/*
+ * Described in header.
+ */
+chunk_t allocator_alloc_as_chunk(size_t bytes)
+{
+ chunk_t new_chunk;
+ new_chunk.ptr = malloc(bytes);
+ if (new_chunk.ptr == NULL)
+ {
+ exit(-1);
+ }
+ new_chunk.len = bytes;
+ return new_chunk;
+
+}
+
+/*
+ * Described in header.
+ */
+void * allocator_realloc(void * old, size_t newsize)
+{
+ void *data = realloc(old,newsize);
+ return data;
+}
+
+/*
+ * Described in header.
+ */
+void * allocator_clone_bytes(void * pointer, size_t size)
+{
+
+ void *data;
+ data = malloc(size);
+
+ if (data == NULL){exit(-1);}
+ memmove(data,pointer,size);
+
+ return (data);
+}
+
+/**
+ * Described in header.
+ */
+chunk_t allocator_clone_chunk(chunk_t chunk)
+{
+ chunk_t clone = CHUNK_INITIALIZER;
+
+ if (chunk.ptr && chunk.len > 0)
+ {
+ clone.ptr = malloc(chunk.len);
+ if (clone.ptr == NULL) {exit(-1);}
+ clone.len = chunk.len;
+ memcpy(clone.ptr, chunk.ptr, chunk.len);
+ }
+
+ return clone;
+}
+
+/*
+ * Described in header.
+ */
+void allocator_free_chunk(chunk_t *chunk)
+{
+ free(chunk->ptr);
+ chunk->ptr = NULL;
+ chunk->len = 0;
+}
+
+#endif /* LEAK_DETECTION */
diff --git a/Source/lib/utils/allocator.h b/Source/lib/utils/allocator.h
new file mode 100644
index 000000000..5b00496f6
--- /dev/null
+++ b/Source/lib/utils/allocator.h
@@ -0,0 +1,324 @@
+/**
+ * @file allocator.h
+ *
+ * @brief Interface of allocator_t.
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef ALLOCATOR_H_
+#define ALLOCATOR_H_
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+
+#include <types.h>
+
+
+/**
+ * Macro to allocate a special type.
+ *
+ * @param thing object on which a sizeof is performed
+ * @return pointer to allocated memory
+ *
+ * @ingroup utils
+ */
+#define allocator_alloc_thing_as_chunk(thing) (allocator_alloc_as_chunk(sizeof(thing)))
+
+/**
+ * Macro to allocate a special type as chunk_t.
+ *
+ * @param thing object on which a sizeof is performed
+ * @return chunk_t pointing to allocated memory
+ *
+ * @ingroup utils
+ */
+#define allocator_alloc_thing(thing) (allocator_alloc(sizeof(thing)))
+
+#ifdef LEAK_DETECTIVE
+
+ typedef struct allocator_t allocator_t;
+
+ /**
+ *@brief Allocater object use to detect memory leaks.
+ *
+ * @ingroup utils
+ */
+ struct allocator_t {
+
+ /**
+ * Allocates memory with LEAK_DETECTION and
+ * returns an empty data area filled with zeros.
+ *
+ * @warning Use this function not directly, only with assigned macros
+ * #allocator_alloc and #allocator_alloc_thing.
+ *
+ * @param this allocator_t object
+ * @param bytes number of bytes to allocate
+ * @param file filename from which the memory is allocated
+ * @param line line number in specific file
+ * @return pointer to allocated memory area
+ */
+ void * (*allocate) (allocator_t *this,size_t bytes, char * file,int line);
+
+ /**
+ * Allocates memory with LEAK_DETECTION and
+ * returns an chunk pointing to an empy data area filled with zeros.
+ *
+ * @warning Use this function not directly, only with assigned
+ * macros #allocator_alloc_as_chunk and
+ * #allocator_alloc_thing_as_chunk.
+ *
+ * @param this allocator_t object
+ * @param bytes number of bytes to allocate
+ * @param file filename from which the memory is allocated
+ * @param line line number in specific file
+ * @return pointer to allocated memory area
+ */
+ chunk_t (*allocate_as_chunk) (allocator_t *this,size_t bytes, char * file,int line);
+
+ /**
+ * Reallocates memory with LEAK_DETECTION and
+ * returns an empty data area filled with zeros.
+ *
+ * @warning Use this function not directly, only with assigned macro
+ * #allocator_realloc.
+ *
+ * @param this allocator_t object
+ * @param old pointer to the old data area
+ * @param bytes number of bytes to allocate
+ * @param file filename from which the memory is allocated
+ * @param line line number in specific file
+ * @return pointer to reallocated memory area
+ */
+ void * (*reallocate) (allocator_t *this,void * old, size_t bytes, char * file, int line);
+
+ /**
+ * Clones memory with LEAK_DETECTION and returns a cloned data area.
+ *
+ * @warning Use this function not directly, only with assigned macro
+ * #allocator_clone_bytes.
+ *
+ * @param this allocator_t object
+ * @param old pointer to the old data area
+ * @param bytes number of bytes to allocate
+ * @param file filename from which the memory is allocated
+ * @param line line number in specific file
+ * @return pointer to reallocated memory area
+ */
+ void * (*clone_bytes) (allocator_t *this,void * to_clone, size_t bytes, char * file, int line);
+
+ /**
+ * Clones a chunk with LEAK_DETECTION and returns a cloned chunk.
+ *
+ * @warning Use this function not directly, only with assigned macro
+ * #allocator_clone_chunk-
+ *
+ * @param this allocator_t object
+ * @param chunk chunk to clone
+ * @param file filename from which the memory is allocated
+ * @param line line number in specific file
+ * @return pointer to reallocated memory
+ */
+ chunk_t (*clone_chunk) (allocator_t *this, chunk_t chunk, char * file, int line);
+
+ /**
+ * Frees memory with LEAK_DETECTION.
+ *
+ * @warning Use this function not directly, only with assigned macro
+ * #allocator_free.
+ *
+ * @param this allocator_t object
+ * @param pointer pointer to the data area to free
+ */
+ void (*free_pointer) (allocator_t *this,void * pointer);
+
+ /**
+ * Report memory leaks to stderr.
+ *
+ * @warning Use this function not directly, only with assigned macro
+ * #report_memory_leaks
+ *
+ * @param this allocator_t object
+ */
+ void (*report_memory_leaks) (allocator_t *this);
+ };
+
+
+ /**
+ * @brief Initialize the allocator.
+ *
+ * Setup the allocator (set allocation functions for libgmp)
+ */
+ void allocator_init();
+
+ /**
+ * @brief Global allocater_t object.
+ *
+ * Only accessed over macros.
+ */
+ extern allocator_t *global_allocator;
+
+
+ /**
+ * Macro to allocate some memory.
+ *
+ * See #allocator_t.allocate for description.
+ *
+ * @ingroup utils
+ */
+ #define allocator_alloc(bytes) (global_allocator->allocate(global_allocator,bytes,__FILE__,__LINE__))
+
+ /**
+ * Macro to allocate some memory for a chunk_t.
+ *
+ * See #allocator_t.allocate_as_chunk for description.
+ *
+ * @ingroup utils
+ */
+ #define allocator_alloc_as_chunk(bytes) (global_allocator->allocate_as_chunk(global_allocator,bytes,__FILE__,__LINE__))
+
+ /**
+ * Macro to reallocate some memory.
+ *
+ * See #allocator_t.reallocate for description.
+ *
+ * @ingroup utils
+ */
+ #define allocator_realloc(old,bytes) (global_allocator->reallocate(global_allocator,old,bytes,__FILE__, __LINE__))
+
+ /**
+ * Macro to clone some memory.
+ *
+ * See #allocator_t.*clone_bytes for description.
+ *
+ * @ingroup utils
+ */
+ #define allocator_clone_bytes(old,bytes) (global_allocator->clone_bytes(global_allocator,old,bytes,__FILE__, __LINE__))
+
+ /**
+ * Macro to clone a chunk and its contents
+ *
+ * See #allocator_t.clone_chunk for description.
+ *
+ * @ingroup utils
+ */
+ #define allocator_clone_chunk(chunk) (global_allocator->clone_chunk(global_allocator,chunk,__FILE__, __LINE__))
+
+ /**
+ * Macro to free some memory.
+ *
+ * See #allocator_t.free_pointer for description.
+ *
+ * @ingroup utils
+ */
+ #define allocator_free(pointer) (global_allocator->free_pointer(global_allocator,pointer))
+
+ /**
+ * Macro to free a chunk.
+ */
+ #define allocator_free_chunk(chunk){ \
+ global_allocator->free_pointer(global_allocator,(chunk)->ptr); \
+ (chunk)->ptr = NULL; \
+ (chunk)->len = 0; \
+ }
+
+ /**
+ * Macro to report memory leaks.
+ *
+ * See #allocator_s.report_memory_leaks for description.
+ *
+ * @ingroup utils
+ */
+ #define report_memory_leaks(void) (global_allocator->report_memory_leaks(global_allocator))
+#else
+
+ /**
+ * Macro to allocate some memory.
+ *
+ * @ingroup utils
+ */
+ #define allocator_alloc(bytes) (malloc(bytes))
+
+ /**
+ * Allocate some memory as chunk.
+ *
+ * @ingroup utils
+ */
+ chunk_t allocator_alloc_as_chunk(size_t bytes);
+
+ /**
+ * Reallocate some memory.
+ *
+ * @ingroup utils
+ */
+ void * allocator_realloc(void * old, size_t newsize);
+
+ /**
+ * Free allocated memory.
+ *
+ * @ingroup utils
+ */
+ #define allocator_free(pointer) (free(pointer))
+
+ /**
+ * Clone bytes.
+ *
+ *
+ * @param pointer pointer to read data from
+ * @param size number of bytes to clone
+ *
+ * @ingroup utils
+ */
+ void * allocator_clone_bytes(void * pointer, size_t size);
+
+ /**
+ * Clone a chunk and its contents.
+ *
+ *
+ * @param chunk chunk to clone
+ * @return cloned chunk
+ *
+ * @ingroup utils
+ */
+ chunk_t allocator_clone_chunk(chunk_t chunk);
+
+ /**
+ * Frees memory used by chunk.
+ *
+ * @param chunk pointer of chunk to free
+ *
+ * @ingroup utils
+ */
+ void allocator_free_chunk(chunk_t *chunk);
+
+ /**
+ * Report memory leaks.
+ *
+ * @ingroup utils
+ */
+ #define report_memory_leaks() {}
+
+ /**
+ * Initialize the allocator.
+ *
+ * @ingroup utils
+ */
+ #define allocator_init() {}
+#endif
+
+#endif /*ALLOCATOR_H_*/
diff --git a/Source/lib/utils/host.c b/Source/lib/utils/host.c
new file mode 100644
index 000000000..245df8b05
--- /dev/null
+++ b/Source/lib/utils/host.c
@@ -0,0 +1,365 @@
+/**
+ * @file host.c
+ *
+ * @brief Implementation of host_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 "host.h"
+
+#include <utils/allocator.h>
+
+
+typedef struct private_host_t private_host_t;
+
+/**
+ * @brief Private Data of a host object.
+ */
+struct private_host_t {
+ /**
+ * Public data
+ */
+ host_t public;
+
+ /**
+ * Address family to use, such as AF_INET or AF_INET6
+ */
+ int family;
+
+ /**
+ * string representation of host
+ */
+ char *string;
+
+ /**
+ * low-lewel structure, wich stores the address
+ */
+ union {
+ struct sockaddr address;
+ struct sockaddr_in address4;
+ };
+ /**
+ * length of address structure
+ */
+ socklen_t socklen;
+};
+
+
+/**
+ * implements host_t.get_sockaddr
+ */
+static sockaddr_t *get_sockaddr(private_host_t *this)
+{
+ return &(this->address);
+}
+
+/**
+ * implements host_t.get_sockaddr_len
+ */
+static socklen_t *get_sockaddr_len(private_host_t *this)
+{
+ return &(this->socklen);
+}
+
+/**
+ * Implementation of host_t.is_default_route.
+ */
+static bool is_default_route (private_host_t *this)
+{
+ switch (this->family)
+ {
+ case AF_INET:
+ {
+ static u_int8_t default_route[4] = {0x00,0x00,0x00,0x00};
+
+ if (memcmp(default_route,&(this->address4.sin_addr.s_addr),4) == 0)
+ {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ default:
+ {
+ /* empty chunk is returned */
+ return FALSE;
+ }
+ }
+}
+
+/**
+ * implements host_t.get_address
+ */
+static char *get_address(private_host_t *this)
+{
+ switch (this->family)
+ {
+ case AF_INET:
+ {
+ char *string;
+ /* we need to clone it, since inet_ntoa overwrites
+ * internal buffer on subsequent calls
+ */
+ allocator_free(this->string);
+ string = inet_ntoa(this->address4.sin_addr);
+ this->string = allocator_alloc(strlen(string)+1);
+ strcpy(this->string, string);
+ return this->string;
+ }
+ default:
+ {
+ return "(family not supported)";
+ }
+ }
+}
+
+/**
+ * Implementation of host_t.get_address_as_chunk.
+ */
+static chunk_t get_address_as_chunk(private_host_t *this)
+{
+ chunk_t address = CHUNK_INITIALIZER;
+
+ switch (this->family)
+ {
+ case AF_INET:
+ {
+ /* allocate 4 bytes for IPV4 address*/
+ address.ptr = allocator_alloc(4);
+ address.len = 4;
+ memcpy(address.ptr,&(this->address4.sin_addr.s_addr),4);
+ }
+ default:
+ {
+ /* empty chunk is returned */
+ return address;
+ }
+ }
+}
+
+static xfrm_address_t get_xfrm_addr(private_host_t *this)
+{
+ switch (this->family)
+ {
+ case AF_INET:
+ {
+ return (xfrm_address_t)(this->address4.sin_addr.s_addr);
+ }
+ default:
+ {
+ /* todo */
+ return (xfrm_address_t)(this->address4.sin_addr.s_addr);
+ }
+ }
+}
+
+static int get_family(private_host_t *this)
+{
+ return this->family;
+}
+
+/**
+ * implements host_t.get_port
+ */
+static u_int16_t get_port(private_host_t *this)
+{
+ switch (this->family)
+ {
+ case AF_INET:
+ {
+ return ntohs(this->address4.sin_port);
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+
+/**
+ * Implements host_t.clone.
+ */
+static private_host_t *clone(private_host_t *this)
+{
+ private_host_t *new = allocator_alloc_thing(private_host_t);
+
+
+ memcpy(new, this, sizeof(private_host_t));
+ if (this->string)
+ {
+ new->string = allocator_alloc(strlen(this->string)+1);
+ strcpy(new->string, this->string);
+ }
+ return new;
+}
+
+/**
+ * Impelements host_t.ip_equals
+ */
+static bool ip_equals(private_host_t *this, private_host_t *other)
+{
+ switch (this->family)
+ {
+ /* IPv4 */
+ case AF_INET:
+ {
+ if ((this->address4.sin_family == other->address4.sin_family) &&
+ (this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr))
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Impelements host_t.equals
+ */
+static bool equals(private_host_t *this, private_host_t *other)
+{
+ switch (this->family)
+ {
+ /* IPv4 */
+ case AF_INET:
+ {
+ if ((this->address4.sin_family == other->address4.sin_family) &&
+ (this->address4.sin_addr.s_addr == other->address4.sin_addr.s_addr) &&
+ (this->address4.sin_port == other->address4.sin_port))
+ {
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Implements host_t.destroy
+ */
+static void destroy(private_host_t *this)
+{
+ allocator_free(this->string);
+ allocator_free(this);
+}
+
+/**
+ * Creates an empty host_t object
+ */
+static private_host_t *host_create_empty()
+{
+ private_host_t *this = allocator_alloc_thing(private_host_t);
+
+ this->public.get_sockaddr = (sockaddr_t* (*) (host_t*))get_sockaddr;
+ this->public.get_sockaddr_len = (socklen_t*(*) (host_t*))get_sockaddr_len;
+ this->public.clone = (host_t* (*) (host_t*))clone;
+ this->public.get_family = (int (*) (host_t*))get_family;
+ this->public.get_xfrm_addr = (xfrm_address_t (*) (host_t *))get_xfrm_addr;
+ this->public.get_address = (char* (*) (host_t *))get_address;
+ this->public.get_address_as_chunk = (chunk_t (*) (host_t *)) get_address_as_chunk;
+ this->public.get_port = (u_int16_t (*) (host_t *))get_port;
+ this->public.ip_equals = (bool (*) (host_t *,host_t *)) ip_equals;
+ this->public.equals = (bool (*) (host_t *,host_t *)) equals;
+ this->public.is_default_route = (bool (*) (host_t *)) is_default_route;
+ this->public.destroy = (void (*) (host_t*))destroy;
+
+ this->string = NULL;
+
+ return this;
+}
+
+/*
+ * Described in header.
+ */
+host_t *host_create(int family, char *address, u_int16_t port)
+{
+ private_host_t *this = host_create_empty();
+
+ this->family = family;
+
+ switch (family)
+ {
+ /* IPv4 */
+ case AF_INET:
+ {
+ this->address4.sin_family = AF_INET;
+ this->address4.sin_addr.s_addr = inet_addr(address);
+ this->address4.sin_port = htons(port);
+ this->socklen = sizeof(struct sockaddr_in);
+ return &(this->public);
+ }
+ default:
+ {
+ allocator_free(this);
+ return NULL;
+
+ }
+ }
+
+}
+
+/*
+ * Described in header.
+ */
+host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port)
+{
+ private_host_t *this = host_create_empty();
+
+ this->family = family;
+ switch (family)
+ {
+ /* IPv4 */
+ case AF_INET:
+ {
+ if (address.len != 4)
+ {
+ break;
+ }
+ this->address4.sin_family = AF_INET;
+ memcpy(&(this->address4.sin_addr.s_addr),address.ptr,4);
+ this->address4.sin_port = htons(port);
+ this->socklen = sizeof(struct sockaddr_in);
+ return &(this->public);
+ }
+ }
+ allocator_free(this);
+ return NULL;
+}
+
+/*
+ * Described in header.
+ */
+host_t *host_create_from_sockaddr(sockaddr_t *sockaddr)
+{
+ chunk_t address;
+
+ switch (sockaddr->sa_family)
+ {
+ /* IPv4 */
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sockaddr;
+ address.ptr = (void*)&(sin->sin_addr.s_addr);
+ address.len = 4;
+ return host_create_from_chunk(AF_INET, address, ntohs(sin->sin_port));
+ }
+ default:
+ return NULL;
+ }
+}
+
diff --git a/Source/lib/utils/host.h b/Source/lib/utils/host.h
new file mode 100644
index 000000000..d81efffa6
--- /dev/null
+++ b/Source/lib/utils/host.h
@@ -0,0 +1,225 @@
+/**
+ * @file host.h
+ *
+ * @brief Interface of host_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef HOST_H_
+#define HOST_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <linux/xfrm.h>
+
+#include <types.h>
+
+
+typedef struct host_t host_t;
+
+/**
+ * @brief Representates a Host
+ *
+ * Host object, identifies a address:port pair and defines some
+ * useful functions on it.
+ *
+ * @b Constructors:
+ * - host_create()
+ * - host_create_from_chunk()
+ * - host_create_from_sockaddr()
+ *
+ * @todo Add IPv6 support
+ *
+ * @ingroup network
+ */
+struct host_t {
+
+ /**
+ * @brief Build a clone of this host object.
+ *
+ * @param this object to clone
+ * @return cloned host
+ */
+ host_t *(*clone) (host_t *this);
+
+ /**
+ * @brief Get a pointer to the internal sockaddr struct.
+ *
+ * This is used for sending and receiving via sockets.
+ *
+ * @param this object to clone
+ * @return pointer to the internal sockaddr structure
+ */
+ sockaddr_t *(*get_sockaddr) (host_t *this);
+
+ /**
+ * @brief Get the length of the sockaddr struct.
+ *
+ * Sepending 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.
+ *
+ * @param this object to clone
+ * @return length of the sockaddr struct
+ */
+ socklen_t *(*get_sockaddr_len) (host_t *this);
+
+ /**
+ * @brief Gets the address as xfrm_address_t.
+ *
+ * This function allows the conversion to an
+ * xfrm_address_t, used for netlink communication
+ * with the kernel.
+ *
+ * @see kernel_interface_t.
+ *
+ * @param this calling object
+ * @return address in xfrm_address_t format
+ */
+ xfrm_address_t (*get_xfrm_addr) (host_t *this);
+
+ /**
+ * @brief Gets the family of the address
+ *
+ * @param this calling object
+ * @return family
+ */
+ int (*get_family) (host_t *this);
+
+ /**
+ * @brief get the address of this host
+ *
+ * Mostly used for debugging purposes.
+ * @warning string must NOT be freed
+ *
+ * @param this object
+ * @return address string,
+ */
+ char* (*get_address) (host_t *this);
+
+ /**
+ * @brief Checks if the ip address of host is set to default route.
+ *
+ * @param this calling object
+ * @return
+ * - TRUE if host has IP 0.0.0.0 for default route
+ * - FALSE otherwise
+ */
+ bool (*is_default_route) (host_t *this);
+
+ /**
+ * @brief get the address of this host as chunk_t
+ *
+ * @warning returned chunk has to get destroyed by caller.
+ *
+ * @param this object
+ * @return address string,
+ */
+ chunk_t (*get_address_as_chunk) (host_t *this);
+
+ /**
+ * @brief get the port of this host
+ *
+ * Mostly used for debugging purposes.
+ *
+ * @param this object to clone
+ * @return port number
+ */
+ u_int16_t (*get_port) (host_t *this);
+
+ /**
+ * @brief Compare the ips of two hosts hosts.
+ *
+ * @param this object to compare
+ * @param other the other to compare
+ * @return TRUE if addresses are equal.
+ */
+ bool (*ip_equals) (host_t *this, host_t *other);
+
+ /**
+ * @brief Compare two hosts, with port.
+ *
+ * @param this object to compare
+ * @param other the other to compare
+ * @return TRUE if addresses and ports are equal.
+ */
+ bool (*equals) (host_t *this, host_t *other);
+
+ /**
+ * @brief Destroy this host object
+ *
+ * @param this calling
+ * @return SUCCESS in any case
+ */
+ void (*destroy) (host_t *this);
+};
+
+/**
+ * @brief Constructor to create a host_t object from an address string
+ *
+ * Currently supports only IPv4!
+ *
+ * @param family Address family to use for this object, such as AF_INET or AF_INET6
+ * @param address string of an address, such as "152.96.193.130"
+ * @param port port number
+ * @return
+ * - host_t object
+ * - NULL, if family not supported.
+ *
+ * @ingroup network
+ */
+host_t *host_create(int family, char *address, u_int16_t port);
+
+/**
+ * @brief Constructor to create a host_t object from an address chunk
+ *
+ * Currently supports only IPv4!
+ *
+ * @param family Address family to use for this object, such as AF_INET or AF_INET6
+ * @param address address as 4 byte chunk_t in networ order
+ * @param port port number
+ * @return
+ * - host_t object
+ * - NULL, if family not supported or chunk_t length not 4 bytes.
+ *
+ * @ingroup network
+ */
+host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port);
+
+/**
+ * @brief Constructor to create a host_t object from a sockaddr struct
+ *
+ * Currently supports only IPv4!
+ *
+ * @param sockaddr sockaddr struct which contains family, address and port
+ * @return
+ * - host_t object
+ * - NULL, if family not supported.
+ *
+ * @ingroup network
+ */
+host_t *host_create_from_sockaddr(sockaddr_t *sockaddr);
+
+
+#endif /*HOST_H_*/
diff --git a/Source/lib/utils/identification.c b/Source/lib/utils/identification.c
new file mode 100644
index 000000000..72d1610af
--- /dev/null
+++ b/Source/lib/utils/identification.c
@@ -0,0 +1,291 @@
+/**
+ * @file identification.c
+ *
+ * @brief Implementation of identification_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "identification.h"
+
+#include <utils/allocator.h>
+
+/**
+ * String mappings for id_type_t.
+ */
+mapping_t id_type_m[] = {
+ {ID_IPV4_ADDR, "ID_IPV4_ADDR"},
+ {ID_FQDN, "ID_FQDN"},
+ {ID_RFC822_ADDR, "ID_RFC822_ADDR"},
+ {ID_IPV6_ADDR, "ID_IPV6_ADDR"},
+ {ID_DER_ASN1_DN, "ID_DER_ASN1_DN"},
+ {ID_DER_ASN1_GN, "ID_DER_ASN1_GN"},
+ {ID_KEY_ID, "ID_KEY_ID"},
+ {MAPPING_END, NULL}
+};
+
+
+typedef struct private_identification_t private_identification_t;
+
+/**
+ * Private data of an identification_t object.
+ */
+struct private_identification_t {
+ /**
+ * Public interface.
+ */
+ identification_t public;
+
+ /**
+ * String representation of this ID.
+ */
+ char *string;
+
+ /**
+ * Encoded representation of this ID.
+ */
+ chunk_t encoded;
+
+ /**
+ * Type of this ID.
+ */
+ id_type_t type;
+};
+
+static private_identification_t *identification_create();
+
+/**
+ * Implementation of identification_t.get_encoding.
+ */
+static chunk_t get_encoding(private_identification_t *this)
+{
+ return this->encoded;
+}
+
+/**
+ * Implementation of identification_t.get_type.
+ */
+static id_type_t get_type(private_identification_t *this)
+{
+ return this->type;
+}
+
+/**
+ * Implementation of identification_t.get_string.
+ */
+static char *get_string(private_identification_t *this)
+{
+ return this->string;
+}
+
+/**
+ * Implementation of identification_t.equals.
+ */
+static bool equals (private_identification_t *this,private_identification_t *other)
+{
+ if (this->type == other->type)
+ {
+ if (this->encoded.len != other->encoded.len)
+ {
+ return FALSE;
+ }
+ if (memcmp(this->encoded.ptr,other->encoded.ptr,this->encoded.len) == 0)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of identification_t.belongs_to.
+ */
+static bool belongs_to(private_identification_t *this, private_identification_t *other)
+{
+ if (this->public.equals(&this->public, &other->public))
+ {
+ return TRUE;
+ }
+
+ if (this->type == other->type && this->type == ID_IPV4_ADDR)
+ {
+ /* is this %any (0.0.0.0)?*/
+ if (*((u_int32_t*)this->encoded.ptr) == 0)
+ {
+ return TRUE;
+ }
+ /* TODO: Do we need subnet support? */
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of identification_t.clone.
+ */
+static identification_t *clone(private_identification_t *this)
+{
+ private_identification_t *clone = identification_create();
+
+ clone->type = this->type;
+ clone->encoded = allocator_clone_chunk(this->encoded);
+ clone->string = allocator_alloc(strlen(this->string) + 1);
+ strcpy(clone->string, this->string);
+
+ return &clone->public;
+}
+
+/**
+ * Implementation of identification_t.destroy.
+ */
+static void destroy(private_identification_t *this)
+{
+ allocator_free(this->string);
+ allocator_free(this->encoded.ptr);
+ allocator_free(this);
+}
+
+/*
+ * Generic constructor used for the other constructors.
+ *
+ * @return private_identification_t object
+ */
+static private_identification_t *identification_create()
+{
+ private_identification_t *this = allocator_alloc_thing(private_identification_t);
+
+ this->public.equals = (bool (*) (identification_t*,identification_t*))equals;
+ this->public.belongs_to = (bool (*) (identification_t*,identification_t*))belongs_to;
+ this->public.get_encoding = (chunk_t (*) (identification_t*))get_encoding;
+ this->public.get_type = (id_type_t (*) (identification_t*))get_type;
+ this->public.get_string = (char* (*) (identification_t*))get_string;
+ this->public.clone = (identification_t* (*) (identification_t*))clone;
+ this->public.destroy = (void (*) (identification_t*))destroy;
+
+ this->string = NULL;
+ this->encoded = CHUNK_INITIALIZER;
+
+ return this;
+}
+
+
+/*
+ * Described in header.
+ */
+identification_t *identification_create_from_string(id_type_t type, char *string)
+{
+ private_identification_t *this = identification_create();
+
+ this->type = type;
+ switch (type)
+ {
+ case ID_IPV4_ADDR:
+ {
+ /* convert string */
+ this->encoded.len = 4;
+ this->encoded.ptr = allocator_alloc(this->encoded.len);
+ if (inet_aton(string, ((struct in_addr*)(this->encoded.ptr))) == 0)
+ {
+ allocator_free(this->encoded.ptr);
+ allocator_free(this);
+ return NULL;
+ }
+ /* clone string */
+ this->string = allocator_alloc(strlen(string)+1);
+ strcpy(this->string, string);
+ return &(this->public);
+ }
+ case ID_IPV6_ADDR:
+ case ID_FQDN:
+ case ID_RFC822_ADDR:
+ case ID_DER_ASN1_DN:
+ case ID_DER_ASN1_GN:
+ case ID_KEY_ID:
+ default:
+ {
+ /* not supported */
+ allocator_free(this);
+ return NULL;
+ }
+ }
+}
+
+/*
+ * Described in header.
+ */
+identification_t *identification_create_from_encoding(id_type_t type, chunk_t encoded)
+{
+ char *string;
+ private_identification_t *this = identification_create();
+
+ this->encoded = allocator_clone_chunk(encoded);
+
+ this->type = type;
+ switch (type)
+ {
+ case ID_IPV4_ADDR:
+ {
+ string = inet_ntoa(*((struct in_addr*)(encoded.ptr)));
+ break;
+ }
+ case ID_IPV6_ADDR:
+ {
+ string = "[ID_IPV6_ADDR]";
+ break;
+ }
+ case ID_FQDN:
+ {
+ string = "[ID_FQDN]";
+ break;
+ }
+ case ID_RFC822_ADDR:
+ {
+ string = "[ID_RFC822_ADDR]";
+ break;
+ }
+ case ID_DER_ASN1_DN:
+ {
+ string = "[ID_DER_ASN1_DN]";
+ break;
+ }
+ case ID_DER_ASN1_GN:
+ {
+ string = "[ID_DER_ASN1_GN]";
+ break;
+ }
+ case ID_KEY_ID:
+ {
+ string = "[ID_KEY_ID]";
+ break;
+ }
+ default:
+ {
+ string = "[unknown id_type_t]";
+ }
+ }
+
+ /* build string, must be cloned since
+ * inet_ntoa points to a subsequently
+ * overwritten buffer */
+ this->string = allocator_alloc(strlen(string)+1);
+ strcpy(this->string, string);
+
+ return &(this->public);
+}
diff --git a/Source/lib/utils/identification.h b/Source/lib/utils/identification.h
new file mode 100644
index 000000000..b973da9a4
--- /dev/null
+++ b/Source/lib/utils/identification.h
@@ -0,0 +1,211 @@
+/**
+ * @file identification.h
+ *
+ * @brief Interface of identification_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+
+#ifndef IDENTIFICATION_H_
+#define IDENTIFICATION_H_
+
+
+#include "types.h"
+
+typedef enum id_type_t id_type_t;
+
+/**
+ * @brief ID Types in a ID payload.
+ *
+ * @see
+ * - identification_t
+ * - id_payload_t
+ *
+ * @ingroup utils
+ */
+enum id_type_t {
+
+ /**
+ * ID data is a single four (4) octet IPv4 address.
+ */
+ ID_IPV4_ADDR = 1,
+
+ /**
+ * ID data is a fully-qualified domain name string.
+ * An example of a ID_FQDN is, "example.com".
+ * The string MUST not contain any terminators (e.g., NULL, CR, etc.).
+ */
+ ID_FQDN = 2,
+
+ /**
+ * ID data is a fully-qualified RFC822 email address string, An example of
+ * a ID_RFC822_ADDR is, "jsmith@example.com". The string MUST
+ * not contain any terminators.
+ */
+ ID_RFC822_ADDR = 3,
+
+ /**
+ * ID data is a single sixteen (16) octet IPv6 address.
+ */
+ ID_IPV6_ADDR = 5,
+
+ /**
+ * ID data is the binary DER encoding of an ASN.1 X.500 Distinguished Name
+ * [X.501].
+ */
+ ID_DER_ASN1_DN = 9,
+
+ /**
+ * ID data is the binary DER encoding of an ASN.1 X.500 GeneralName
+ * [X.509].
+ */
+ ID_DER_ASN1_GN = 10,
+
+ /**
+ * ID data is an opaque octet stream which may be used to pass vendor-
+ * specific information necessary to do certain proprietary
+ * types of identification.
+ */
+ ID_KEY_ID = 11
+};
+
+/**
+ * String mappings for id_type_t.
+ */
+extern mapping_t id_type_m[];
+
+typedef struct identification_t identification_t;
+
+/**
+ * @brief Generic identification, such as used in ID payload.
+ *
+ * The following types are possible:
+ * - ID_IPV4_ADDR
+ * - ID_FQDN*
+ * - ID_RFC822_ADDR*
+ * - ID_IPV6_ADDR*
+ * - ID_DER_ASN1_DN*
+ * - ID_DER_ASN1_GN*
+ * - ID_KEY_ID*
+ * (* = string conversion not supported)
+ *
+ * @b Constructors:
+ * - identification_create_from_string()
+ * - identification_create_from_encoding()
+ *
+ * @todo Support for other ID types then ID_IPV4_ADDR.
+ *
+ * @ingroup utils
+ */
+struct identification_t {
+
+ /**
+ * @brief Get the encoding of this id, to send over
+ * the network.
+ *
+ * @warning Result points to internal data, do NOT free!
+ *
+ * @param this the identification_t object
+ * @return a chunk containing the encoded bytes
+ */
+ chunk_t (*get_encoding) (identification_t *this);
+
+ /**
+ * @brief Get the type of this identification.
+ *
+ * @param this the identification_t object
+ * @return id_type_t
+ */
+ id_type_t (*get_type) (identification_t *this);
+
+ /**
+ * @brief Get a string representation of this id.
+ *
+ * @warning Result points to internal data, do NOT free!
+ *
+ * @param this the identification_t object
+ * @return string
+ */
+ char *(*get_string) (identification_t *this);
+
+ /**
+ * @brief Check if two identification_t objects are equal.
+ *
+ * @param this the identification_t object
+ * @param other other identification_t object
+ * @return TRUE if the IDs are equal
+ */
+ bool (*equals) (identification_t *this,identification_t *other);
+
+ /**
+ * @brief Check if an ID belongs to a wildcard ID.
+ *
+ * An identification_t may contain wildcards, such as
+ * *@strongswan.org. This call checks if a given ID
+ * (e.g. tester@strongswan.org) belongs to a such wildcard
+ * ID. Returns TRUE if IDs are identical.
+ *
+ * @param this the ID containing a wildcard
+ * @param other the ID without wildcard
+ * @return TRUE if other belongs to this
+ */
+ bool (*belongs_to) (identification_t *this, identification_t *other);
+
+ /**
+ * @brief Clone a identification_t instance.
+ *
+ * @param this the identification_t object to clone
+ * @return clone of this
+ */
+ identification_t *(*clone) (identification_t *this);
+
+ /**
+ * @brief Destroys a identification_t object.
+ *
+ * @param this identification_t object
+ */
+ void (*destroy) (identification_t *this);
+};
+
+/**
+ * @brief Creates an identification_t object from a string.
+ *
+ * @param type type of this id, such as ID_IPV4_ADDR
+ * @param string input string, which will be converted
+ * @return
+ * - created identification_t object, or
+ * - NULL if type not supported.
+ *
+ * @ingroup utils
+ */
+identification_t * identification_create_from_string(id_type_t type, char *string);
+
+
+/**
+ * @brief Creates an identification_t object from an encoded chunk.
+ *
+ * @param type type of this id, such as ID_IPV4_ADDR
+ * @param encoded encoded bytes, such as from identification_t.get_encoding
+ * @return identification_t object
+ *
+ * @ingroup utils
+ */
+identification_t * identification_create_from_encoding(id_type_t type, chunk_t encoded);
+
+
+#endif /* IDENTIFICATION_H_ */
diff --git a/Source/lib/utils/iterator.h b/Source/lib/utils/iterator.h
new file mode 100644
index 000000000..de81db8e9
--- /dev/null
+++ b/Source/lib/utils/iterator.h
@@ -0,0 +1,153 @@
+/**
+ * @file iterator.h
+ *
+ * @brief Interface iterator_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef ITERATOR_H_
+#define ITERATOR_H_
+
+typedef struct iterator_t iterator_t;
+
+/**
+ * @brief Iterator interface, allows iteration over collections.
+ *
+ * iterator_t defines an interface for iterating over collections.
+ * It allows searching, deleting, updating and inserting.
+ *
+ * Thanks to JMP for iterator lessons :-)
+ *
+ * @b Constructors:
+ * - via linked_list_t.create_iterator, or
+ * - any other class which supports the iterator_t interface
+ *
+ * @see linked_list_t
+ *
+ * @ingroup utils
+ */
+struct iterator_t {
+
+ /**
+ * @brief Iterate over all items.
+ *
+ * The easy way to iterate over items.
+ *
+ * @param this calling object
+ * @param[out] value item
+ * @return
+ * - TRUE, if more elements are avaiable,
+ * - FALSE otherwise
+ */
+ bool (*iterate) (iterator_t *this, void** value);
+
+ /**
+ * @brief Moves to the next element, if available.
+ *
+ * A newly created iterator_t object doesn't point to any item.
+ * Call iterator_t.has_next first to point it to the first item.
+ *
+ * @param this calling object
+ * @return
+ * - TRUE, if more elements are avaiable,
+ * - FALSE otherwise
+ */
+ bool (*has_next) (iterator_t *this);
+
+ /**
+ * @brief Returns the current value at the iterator position.
+ *
+ * @param this calling object
+ * @param[out] value value is set to the current value at iterator position
+ * @return
+ * - SUCCESS
+ * - FAILED if iterator on an invalid position
+ */
+ status_t (*current) (iterator_t *this, void **value);
+
+ /**
+ * @brief Inserts a new item before the given iterator position.
+ *
+ * The iterator position is not changed after inserting
+ *
+ * @param this calling iterator
+ * @param[in] item value to insert in list
+ */
+ void (*insert_before) (iterator_t *this, void *item);
+
+ /**
+ * @brief Inserts a new item after the given iterator position.
+ *
+ * The iterator position is not changed after inserting.
+ *
+ * @param this calling iterator
+ * @param[in] item value to insert in list
+ */
+ void (*insert_after) (iterator_t *this, void *item);
+
+ /**
+ * @brief Replace the current item at current iterator position.
+ *
+ * The iterator position is not changed after replacing.
+ *
+ * @param this calling iterator
+ * @param[out] old_item old value will be written here(can be NULL)
+ * @param[in] new_item new value
+ *
+ * @return
+ * - SUCCESS
+ * - FAILED if iterator is on an invalid position
+ */
+ status_t (*replace) (iterator_t *this, void **old_item, void *new_item);
+
+ /**
+ * @brief Removes an element from list at the given iterator position.
+ *
+ * The position of the iterator is set in the following order:
+ * - to the item before, if available
+ * - otherwise to the item after, if available
+ * - otherwise it gets reseted
+ *
+ * @param linked_list calling object
+ * @return
+ * - SUCCESS
+ * - FAILED if iterator is on an invalid position
+ */
+ status_t (*remove) (iterator_t *iterator);
+
+ /**
+ * @brief Resets the iterator position.
+ *
+ * After reset, the iterator_t objects doesn't point to an element.
+ * A call to iterator_t.has_next is necessary to do any other operations
+ * with the resetted iterator.
+ *
+ * @param this calling object
+ */
+ void (*reset) (iterator_t *this);
+
+ /**
+ * @brief Destroys an iterator.
+ *
+ * @param this iterator to destroy
+ *
+ */
+ void (*destroy) (iterator_t *this);
+};
+
+#endif /*ITERATOR_H_*/
diff --git a/Source/lib/utils/linked_list.c b/Source/lib/utils/linked_list.c
new file mode 100644
index 000000000..407065d24
--- /dev/null
+++ b/Source/lib/utils/linked_list.c
@@ -0,0 +1,729 @@
+/**
+ * @file linked_list.c
+ *
+ * @brief Implementation of linked_list_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 <stdlib.h>
+
+#include "linked_list.h"
+
+#include <utils/allocator.h>
+
+
+
+typedef struct linked_list_element_t linked_list_element_t;
+
+/**
+ * @brief Element in a linked list.
+ *
+ * This element holds a pointer to the value it represents.
+ */
+struct linked_list_element_t {
+
+ /**
+ * Value of a list item.
+ */
+ void *value;
+
+ /**
+ * Previous list element.
+ *
+ * NULL if first element in list.
+ */
+ linked_list_element_t *previous;
+
+ /**
+ * Next list element.
+ *
+ * NULL if last element in list.
+ */
+ linked_list_element_t *next;
+
+ /**
+ * Destroys a linked_list_element object.
+ *
+ * @param linked_list_element_t calling object
+ */
+ void (*destroy) (linked_list_element_t *this);
+};
+
+/**
+ * Implementation of linked_list_element_t.destroy.
+ */
+static void linked_list_element_destroy(linked_list_element_t *this)
+{
+ allocator_free(this);
+}
+
+/**
+ * @brief Creates an empty linked list object.
+ *
+ * @warning Only the pointer to the value is stored.
+ *
+ * @param[in] value value of item to be set
+ * @return linked_list_element_t object
+ */
+
+linked_list_element_t *linked_list_element_create(void *value)
+{
+ linked_list_element_t *this = allocator_alloc_thing(linked_list_element_t);
+
+ this->destroy = linked_list_element_destroy;
+
+ this->previous=NULL;
+ this->next=NULL;
+ 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.
+ */
+ linked_list_element_t *first;
+
+ /**
+ * Last element in list.
+ * NULL if no elements in list.
+ */
+ linked_list_element_t *last;
+};
+
+
+typedef struct private_iterator_t private_iterator_t;
+
+/**
+ * Private variables and functions of linked list iterator.
+ */
+struct private_iterator_t {
+ /**
+ * Public part of linked list iterator.
+ */
+ iterator_t public;
+
+ /**
+ * Associated linked list.
+ */
+ private_linked_list_t * list;
+
+ /**
+ * Current element of the iterator.
+ */
+ linked_list_element_t *current;
+
+ /**
+ * Direction of iterator.
+ */
+ bool forward;
+};
+
+/**
+ * Implementation of iterator_t.has_next.
+ */
+static bool iterate(private_iterator_t *this, void** value)
+{
+ if (this->list->count == 0)
+ {
+ return FALSE;
+ }
+ if (this->current == NULL)
+ {
+ this->current = (this->forward) ? this->list->first : this->list->last;
+ *value = this->current->value;
+ return TRUE;
+ }
+ if (this->forward)
+ {
+ if (this->current->next == NULL)
+ {
+ return FALSE;
+ }
+ this->current = this->current->next;
+ *value = this->current->value;
+ return TRUE;
+ }
+ /* backward */
+ if (this->current->previous == NULL)
+ {
+ return FALSE;
+ }
+ this->current = this->current->previous;
+ *value = this->current->value;
+ return TRUE;
+}
+
+/**
+ * Implementation of iterator_t.has_next.
+ */
+static bool iterator_has_next(private_iterator_t *this)
+{
+ if (this->list->count == 0)
+ {
+ return FALSE;
+ }
+ if (this->current == NULL)
+ {
+ this->current = (this->forward) ? this->list->first : this->list->last;
+ return TRUE;
+ }
+ if (this->forward)
+ {
+ if (this->current->next == NULL)
+ {
+ return FALSE;
+ }
+ this->current = this->current->next;
+ return TRUE;
+ }
+ /* backward */
+ if (this->current->previous == NULL)
+ {
+ return FALSE;
+ }
+ this->current = this->current->previous;
+ return TRUE;
+}
+
+/**
+ * Implementation of iterator_t.current.
+ */
+static status_t iterator_current(private_iterator_t *this, void **value)
+{
+ if (this->current == NULL)
+ {
+ return NOT_FOUND;
+ }
+ *value = this->current->value;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of iterator_t.reset.
+ */
+static void iterator_reset(private_iterator_t *this)
+{
+ this->current = NULL;
+}
+
+/**
+ * Implementation of iterator_t.remove.
+ */
+static status_t remove(private_iterator_t *this)
+{
+ linked_list_element_t *new_current;
+
+ if (this->current == NULL)
+ {
+ return NOT_FOUND;
+ }
+
+ if (this->list->count == 0)
+ {
+ return NOT_FOUND;
+ }
+ /* find out the new iterator position */
+ if (this->current->previous != NULL)
+ {
+ new_current = this->current->previous;
+ }
+ else if (this->current->next != NULL)
+ {
+ new_current = this->current->next;
+ }
+ else
+ {
+ new_current = NULL;
+ }
+
+ /* now delete the entry :-) */
+ if (this->current->previous == NULL)
+ {
+ if (this->current->next == NULL)
+ {
+ this->list->first = NULL;
+ this->list->last = NULL;
+ }
+ else
+ {
+ this->current->next->previous = NULL;
+ this->list->first = this->current->next;
+ }
+ }
+ else if (this->current->next == NULL)
+ {
+ this->current->previous->next = NULL;
+ this->list->last = this->current->previous;
+ }
+ else
+ {
+ this->current->previous->next = this->current->next;
+ this->current->next->previous = this->current->previous;
+ }
+
+ this->list->count--;
+ this->current->destroy(this->current);
+ /* set the new iterator position */
+ this->current = new_current;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of iterator_t.insert_before.
+ */
+static void insert_before(private_iterator_t * iterator, void *item)
+{
+ if (iterator->current == NULL)
+ {
+ iterator->list->public.insert_first(&(iterator->list->public), item);
+ }
+
+ linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
+
+ if (iterator->current->previous == NULL)
+ {
+ iterator->current->previous = element;
+ element->next = iterator->current;
+ iterator->list->first = element;
+ }
+ else
+ {
+ iterator->current->previous->next = element;
+ element->previous = iterator->current->previous;
+ iterator->current->previous = element;
+ element->next = iterator->current;
+ }
+
+ iterator->list->count++;
+}
+
+/**
+ * Implementation of iterator_t.replace.
+ */
+static status_t replace (private_iterator_t *this, void **old_item, void *new_item)
+{
+ if (this->current == NULL)
+ {
+ return NOT_FOUND;
+ }
+ if (old_item != NULL)
+ {
+ *old_item = this->current->value;
+ }
+ this->current->value = new_item;
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of iterator_t.insert_after.
+ */
+static void insert_after(private_iterator_t * iterator, void *item)
+{
+ if (iterator->current == NULL)
+ {
+ iterator->list->public.insert_first(&(iterator->list->public),item);
+ return;
+ }
+
+ linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
+
+ if (iterator->current->next == NULL)
+ {
+ iterator->current->next = element;
+ element->previous = iterator->current;
+ iterator->list->last = element;
+ }
+ else
+ {
+ iterator->current->next->previous = element;
+ element->next = iterator->current->next;
+ iterator->current->next = element;
+ element->previous = iterator->current;
+ }
+ iterator->list->count++;
+}
+
+/**
+ * Implementation of iterator_t.destroy.
+ */
+static void iterator_destroy(private_iterator_t *this)
+{
+ allocator_free(this);
+}
+
+/**
+ * Implementation of linked_list_t.get_count.
+ */
+static int get_count(private_linked_list_t *this)
+{
+ return this->count;
+}
+
+/**
+ * Implementation of linked_list_t.call_on_items.
+ */
+static void call_on_items(private_linked_list_t *this, void(*func)(void*))
+{
+ iterator_t *iterator;
+ void *item;
+
+ iterator = this->public.create_iterator(&(this->public),TRUE);
+
+ while (iterator->has_next(iterator))
+ {
+ iterator->current(iterator, &item);
+ (*func)(item);
+ }
+ iterator->destroy(iterator);
+}
+
+/**
+ * Implementation of linked_list_t.insert_first.
+ */
+static void insert_first(private_linked_list_t *this, void *item)
+{
+ linked_list_element_t *element;
+
+ element =(linked_list_element_t *) linked_list_element_create(item);
+
+ if (this->count == 0)
+ {
+ /* first entry in list */
+ this->first = element;
+ this->last = element;
+ element->previous = NULL;
+ element->next = NULL;
+ }
+ else
+ {
+ linked_list_element_t *old_first_element = this->first;
+ element->next = old_first_element;
+ element->previous = NULL;
+ old_first_element->previous = element;
+ this->first = element;
+ }
+
+ this->count++;
+}
+
+/**
+ * Implementation of linked_list_t.remove_first.
+ */
+static status_t remove_first(private_linked_list_t *this, void **item)
+{
+ if (this->count == 0)
+ {
+ return NOT_FOUND;
+ }
+
+ linked_list_element_t *element = this->first;
+
+ if (element->next != NULL)
+ {
+ element->next->previous = NULL;
+ }
+ this->first = element->next;
+
+ if (item != NULL)
+ {
+ *item = element->value;
+ }
+
+ this->count--;
+
+ element->destroy(element);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of linked_list_t.get_first.
+ */
+static status_t get_first(private_linked_list_t *this, void **item)
+{
+ if (this->count == 0)
+ {
+ return NOT_FOUND;
+ }
+
+ *item = this->first->value;
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of linked_list_t.insert_last.
+ */
+static void insert_last(private_linked_list_t *this, void *item)
+{
+ linked_list_element_t *element = (linked_list_element_t *) linked_list_element_create(item);
+
+ if (this->count == 0)
+ {
+ /* first entry in list */
+ this->first = element;
+ this->last = element;
+ element->previous = NULL;
+ element->next = NULL;
+ }
+ else
+ {
+
+ linked_list_element_t *old_last_element = this->last;
+ element->previous = old_last_element;
+ element->next = NULL;
+ old_last_element->next = element;
+ this->last = element;
+ }
+
+ this->count++;
+}
+
+/**
+ * Implementation of linked_list_t.remove_last.
+ */
+static status_t remove_last(private_linked_list_t *this, void **item)
+{
+ if (this->count == 0)
+ {
+ return NOT_FOUND;
+ }
+
+ linked_list_element_t *element = this->last;
+
+ if (element->previous != NULL)
+ {
+ element->previous->next = NULL;
+ }
+ this->last = element->previous;
+
+ if (item != NULL)
+ {
+ *item = element->value;
+ }
+
+ this->count--;
+
+ element->destroy(element);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of linked_list_t.insert_at_position.
+ */
+static status_t insert_at_position (private_linked_list_t *this,size_t position, void *item)
+{
+ linked_list_element_t *current_element;
+ int i;
+
+ if (this->count <= position)
+ {
+ return INVALID_ARG;
+ }
+
+ current_element = this->first;
+
+ for (i = 0; i < position;i++)
+ {
+ current_element = current_element->next;
+ }
+
+ if (current_element == NULL)
+ {
+ this->public.insert_last(&(this->public),item);
+ return SUCCESS;
+ }
+
+ linked_list_element_t *element =(linked_list_element_t *) linked_list_element_create(item);
+
+
+ if (current_element->previous == NULL)
+ {
+ current_element->previous = element;
+ element->next = current_element;
+ this->first = element;
+ }
+ else
+ {
+ current_element->previous->next = element;
+ element->previous = current_element->previous;
+ current_element->previous = element;
+ element->next = current_element;
+ }
+
+
+ this->count++;
+ return SUCCESS;
+}
+
+/**
+ * Implementation of linked_list_t.remove_at_position.
+ */
+static status_t remove_at_position (private_linked_list_t *this,size_t position, void **item)
+{
+ iterator_t *iterator;
+ int i;
+
+ if (this->count <= position)
+ {
+ return INVALID_ARG;
+ }
+
+ iterator = this->public.create_iterator(&(this->public),TRUE);
+
+ iterator->has_next(iterator);
+ for (i = 0; i < position;i++)
+ {
+ iterator->has_next(iterator);
+ }
+ iterator->current(iterator,item);
+ iterator->remove(iterator);
+ iterator->destroy(iterator);
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of linked_list_t.get_at_position.
+ */
+static status_t get_at_position (private_linked_list_t *this,size_t position, void **item)
+{
+ int i;
+ iterator_t *iterator;
+ status_t status;
+ if (this->count <= position)
+ {
+ return INVALID_ARG;
+ }
+
+ iterator = this->public.create_iterator(&(this->public),TRUE);
+
+ iterator->has_next(iterator);
+ for (i = 0; i < position;i++)
+ {
+ iterator->has_next(iterator);
+ }
+ status = iterator->current(iterator,item);
+ iterator->destroy(iterator);
+ return status;
+}
+
+/**
+ * Implementation of linked_list_t.get_last.
+ */
+static status_t get_last(private_linked_list_t *this, void **item)
+{
+ if (this->count == 0)
+ {
+ return NOT_FOUND;
+ }
+
+ *item = this->last->value;
+
+ return SUCCESS;
+}
+
+/**
+ * Implementation of linked_list_t.create_iterator.
+ */
+static iterator_t *create_iterator (private_linked_list_t *linked_list,bool forward)
+{
+ private_iterator_t *this = allocator_alloc_thing(private_iterator_t);
+
+ this->public.iterate = (bool (*) (iterator_t *this, void **value)) iterate;
+ this->public.has_next = (bool (*) (iterator_t *this)) iterator_has_next;
+ this->public.current = (status_t (*) (iterator_t *this, void **value)) iterator_current;
+ this->public.insert_before = (void (*) (iterator_t *this, void *item)) insert_before;
+ this->public.insert_after = (void (*) (iterator_t *this, void *item)) insert_after;
+ this->public.replace = (status_t (*) (iterator_t *, void **, void *)) replace;
+ this->public.remove = (status_t (*) (iterator_t *this)) remove;
+ this->public.reset = (void (*) (iterator_t *this)) iterator_reset;
+ this->public.destroy = (void (*) (iterator_t *this)) iterator_destroy;
+
+ this->forward = forward;
+ this->current = NULL;
+ this->list = linked_list;
+
+ return &(this->public);
+}
+
+/**
+ * Implementation of linked_list_t.destroy.
+ */
+static void linked_list_destroy(private_linked_list_t *this)
+{
+ void * value;
+ /* Remove all list items before destroying list */
+ while (this->public.remove_first(&(this->public),&value) != NOT_FOUND)
+ {
+ /* values are not destroyed so memory leaks are possible
+ * if list is not empty when deleting */
+ }
+ allocator_free(this);
+}
+
+/*
+ * Described in header.
+ */
+linked_list_t *linked_list_create()
+{
+ private_linked_list_t *this = allocator_alloc_thing(private_linked_list_t);
+
+ this->public.get_count = (int (*) (linked_list_t *)) get_count;
+ this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool )) create_iterator;
+ this->public.call_on_items = (void (*) (linked_list_t *, void(*func)(void*)))call_on_items;
+ this->public.get_first = (status_t (*) (linked_list_t *, void **item)) get_first;
+ this->public.get_last = (status_t (*) (linked_list_t *, void **item)) get_last;
+ this->public.insert_first = (void (*) (linked_list_t *, void *item)) insert_first;
+ this->public.insert_last = (void (*) (linked_list_t *, void *item)) insert_last;
+ this->public.remove_first = (status_t (*) (linked_list_t *, void **item)) remove_first;
+ this->public.remove_last = (status_t (*) (linked_list_t *, void **item)) remove_last;
+ this->public.insert_at_position =(status_t (*) (linked_list_t *,size_t, void *)) insert_at_position;
+ this->public.remove_at_position =(status_t (*) (linked_list_t *,size_t, void **)) remove_at_position;
+ this->public.get_at_position =(status_t (*) (linked_list_t *,size_t, void **)) get_at_position;
+
+ this->public.destroy = (void (*) (linked_list_t *)) linked_list_destroy;
+
+ this->count = 0;
+ this->first = NULL;
+ this->last = NULL;
+
+ return (&(this->public));
+}
diff --git a/Source/lib/utils/linked_list.h b/Source/lib/utils/linked_list.h
new file mode 100644
index 000000000..8647f064d
--- /dev/null
+++ b/Source/lib/utils/linked_list.h
@@ -0,0 +1,203 @@
+/**
+ * @file linked_list.h
+ *
+ * @brief Interface of linked_list_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef LINKED_LIST_H_
+#define LINKED_LIST_H_
+
+#include <types.h>
+#include <utils/iterator.h>
+
+
+typedef struct linked_list_t linked_list_t;
+
+/**
+ * @brief Class implementing a double linked list (named only as linked list).
+ *
+ * @warning Access to an object of this type is not thread-save.
+ *
+ * @b Costructors:
+ * - linked_list_create()
+ *
+ * @see
+ * - job_queue_t
+ * - event_queue_t
+ * - send_queue_t
+ *
+ * @ingroup utils
+ */
+struct linked_list_t {
+
+ /**
+ * @brief Gets the count of items in the list.
+ *
+ * @param linked_list calling object
+ * @return number of items in list
+ */
+ int (*get_count) (linked_list_t *linked_list);
+
+ /**
+ * @brief Creates a iterator for the given list.
+ *
+ * @warning Created iterator_t object has to get destroyed by the caller.
+ *
+ * @param linked_list calling object
+ * @param forward iterator direction (TRUE: front to end)
+ * @return new iterator_t object
+ */
+ iterator_t * (*create_iterator) (linked_list_t *linked_list, bool forward);
+
+ /**
+ * @brief Call a function with list element as argument.
+ *
+ * This method accepts a function, which will be called for
+ * each list element once. The function must accept the list
+ * element as the first argument. Handy for destruction of
+ * list elements.
+ *
+ * @todo Additional vararg which are passed to the
+ * function would be nice...
+ *
+ * @param linked_list calling object
+ * @param func function to call
+ */
+ void (*call_on_items) (linked_list_t *linked_list, void(*func)(void*));
+
+ /**
+ * @brief Inserts a new item at the beginning of the list.
+ *
+ * @param linked_list calling object
+ * @param[in] item item value to insert in list
+ */
+ void (*insert_first) (linked_list_t *linked_list, void *item);
+
+ /**
+ * @brief Removes the first item in the list and returns its value.
+ *
+ * @param linked_list calling object
+ * @param[out] item returned value of first item, or NULL
+ * @return
+ * - SUCCESS
+ * - NOT_FOUND, if list is empty
+ */
+ status_t (*remove_first) (linked_list_t *linked_list, void **item);
+
+ /**
+ * @brief Returns the value of the first list item without removing it.
+ *
+ * @param linked_list calling object
+ * @param[out] item item returned value of first item
+ * @return
+ * - SUCCESS
+ * - NOT_FOUND, if list is empty
+ */
+ status_t (*get_first) (linked_list_t *linked_list, void **item);
+
+ /**
+ * @brief Inserts a new item at the end of the list.
+ *
+ * @param linked_list calling object
+ * @param[in] item item value to insert into list
+ */
+ void (*insert_last) (linked_list_t *linked_list, void *item);
+
+ /**
+ * @brief Inserts a new item at a given position in the list.
+ *
+ * @param linked_list calling object
+ * @param position position starting at 0 to insert new entry
+ * @param[in] item item value to insert into list
+ * @return
+ * - SUCCESS
+ * - INVALID_ARG if position not existing
+ */
+ status_t (*insert_at_position) (linked_list_t *linked_list,size_t position, void *item);
+
+ /**
+ * @brief Removes an item from a given position in the list.
+ *
+ * @param linked_list calling object
+ * @param position position starting at 0 to remove entry from
+ * @param[out] item removed item will be stored at this location
+ * @return
+ * - SUCCESS
+ * - INVALID_ARG if position not existing
+ */
+ status_t (*remove_at_position) (linked_list_t *linked_list,size_t position, void **item);
+
+ /**
+ * @brief Get an item from a given position in the list.
+ *
+ * @param linked_list calling object
+ * @param position position starting at 0 to get entry from
+ * @param[out] item item will be stored at this location
+ * @return
+ * - SUCCESS
+ * - INVALID_ARG if position not existing
+ */
+ status_t (*get_at_position) (linked_list_t *linked_list,size_t position, void **item);
+
+ /**
+ * @brief Removes the last item in the list and returns its value.
+ *
+ * @param linked_list calling object
+ * @param[out] item returned value of last item, or NULL
+ * @return
+ * - SUCCESS
+ * - NOT_FOUND if list is empty
+ */
+ status_t (*remove_last) (linked_list_t *linked_list, void **item);
+
+ /**
+ * @brief Returns the value of the last list item without removing it.
+ *
+ * @param linked_list calling object
+ * @param[out] item returned value of last item
+ * @return
+ * - SUCCESS
+ * - NOT_FOUND if list is empty
+ */
+ status_t (*get_last) (linked_list_t *linked_list, void **item);
+
+ /**
+ * @brief Destroys a linked_list object.
+ *
+ * @warning All items are removed before deleting the list. The
+ * associated values are NOT destroyed.
+ * Destroying an list which is not empty may cause
+ * memory leaks!
+ *
+ * @param linked_list calling object
+ */
+ void (*destroy) (linked_list_t *linked_list);
+};
+
+/**
+ * @brief Creates an empty linked list object.
+ *
+ * @return linked_list_t object.
+ *
+ * @ingroup utils
+ */
+linked_list_t *linked_list_create();
+
+
+#endif /*LINKED_LIST_H_*/
diff --git a/Source/lib/utils/logger.c b/Source/lib/utils/logger.c
new file mode 100644
index 000000000..c66de481e
--- /dev/null
+++ b/Source/lib/utils/logger.c
@@ -0,0 +1,360 @@
+/**
+ * @file logger.c
+ *
+ * @brief Implementation of logger_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 <syslog.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+
+#include "logger.h"
+
+#include <daemon.h>
+#include <utils/allocator.h>
+
+/**
+ * Maximum length of a log entry (only used for logger_s.log).
+ */
+#define MAX_LOG 8192
+
+
+typedef struct private_logger_t private_logger_t;
+
+/**
+ * @brief Private data of a logger_t object.
+ */
+struct private_logger_t {
+ /**
+ * Public data.
+ */
+ logger_t public;
+ /**
+ * Detail-level of logger.
+ */
+ log_level_t level;
+ /**
+ * Name of logger.
+ */
+ char *name;
+ /**
+ * File to write log output to.
+ * NULL for syslog.
+ */
+ FILE *output;
+
+ /**
+ * Should a thread_id be included in the log?
+ */
+ bool log_thread_id;
+
+ /**
+ * Applies a prefix to string and stores it in buffer.
+ *
+ * @warning: buffer must be at least have MAX_LOG size.
+ */
+ void (*prepend_prefix) (private_logger_t *this, log_level_t loglevel, char *string, char *buffer);
+};
+
+/**
+ * Implementation of private_logger_t.prepend_prefix.
+ */
+static void prepend_prefix(private_logger_t *this, log_level_t loglevel, char *string, char *buffer)
+{
+ char log_type, log_details;
+ if (loglevel & CONTROL)
+ {
+ log_type = '~';
+ }
+ else if (loglevel & ERROR)
+ {
+ log_type = '!';
+ }
+ else if (loglevel & RAW)
+ {
+ log_type = '#';
+ }
+ else if (loglevel & PRIVATE)
+ {
+ log_type = '?';
+ }
+ else if (loglevel & AUDIT)
+ {
+ log_type = '>';
+ }
+ else
+ {
+ log_type = '-';
+ }
+
+ if (loglevel & (LEVEL3 - LEVEL2))
+ {
+ log_details = '3';
+ }
+ else if (loglevel & (LEVEL2 - LEVEL1))
+ {
+ log_details = '2';
+ }
+ else if (loglevel & LEVEL1)
+ {
+ log_details = '1';
+ }
+ else
+ {
+ log_details = '0';
+ }
+
+ if (this->log_thread_id)
+ {
+ snprintf(buffer, MAX_LOG, "[%c%c] [%s] @%u %s", log_type, log_details, this->name, (int)pthread_self(), string);
+ }
+ else
+ {
+ snprintf(buffer, MAX_LOG, "[%c%c] [%s] %s", log_type, log_details, this->name, string);
+ }
+}
+
+/**
+ * Implementation of logger_t.log.
+ *
+ * Yes, logg is wrong written :-).
+ */
+static void logg(private_logger_t *this, log_level_t loglevel, char *format, ...)
+{
+ if ((this->level & loglevel) == loglevel)
+ {
+ char buffer[MAX_LOG];
+ va_list args;
+
+
+ if (this->output == NULL)
+ {
+ /* syslog */
+ this->prepend_prefix(this, loglevel, format, buffer);
+ va_start(args, format);
+ vsyslog(LOG_INFO, buffer, args);
+ va_end(args);
+ }
+ else
+ {
+ /* File output */
+ this->prepend_prefix(this, loglevel, format, buffer);
+ va_start(args, format);
+ vfprintf(this->output, buffer, args);
+ va_end(args);
+ fprintf(this->output, "\n");
+ }
+
+ }
+}
+
+/**
+ * Implementation of logger_t.log_bytes.
+ */
+static void log_bytes(private_logger_t *this, log_level_t loglevel, char *label, char *bytes, size_t len)
+{
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+
+ if ((this->level & loglevel) == loglevel)
+ {
+ char buffer[MAX_LOG];
+ char ascii_buffer[17];
+ char *format;
+ char *buffer_pos;
+ char *bytes_pos, *bytes_roof;
+ int i;
+ int line_start = 0;
+
+ /* since me can't do multi-line output to syslog,
+ * we must do multiple syslogs. To avoid
+ * problems in output order, lock this by a mutex.
+ */
+ pthread_mutex_lock(&mutex);
+
+
+ format = "%s (%d bytes @%p)";
+ this->prepend_prefix(this, loglevel, format, buffer);
+
+ if (this->output == NULL)
+ {
+ syslog(LOG_INFO, buffer, label, len);
+ }
+ else
+ {
+ fprintf(this->output, buffer, label, len, bytes);
+ fprintf(this->output, "\n");
+ }
+
+ bytes_pos = bytes;
+ bytes_roof = bytes + len;
+ buffer_pos = buffer;
+ memset(ascii_buffer, 0, 17);
+
+ for (i = 1; bytes_pos < bytes_roof; i++)
+ {
+ static char hexdig[] = "0123456789ABCDEF";
+ *buffer_pos++ = hexdig[(*bytes_pos >> 4) & 0xF];
+ *buffer_pos++ = hexdig[ *bytes_pos & 0xF];
+ if ((i % 16) == 0)
+ {
+ *buffer_pos++ = '\0';
+ buffer_pos = buffer;
+ if (this->output == NULL)
+ {
+ syslog(LOG_INFO, "[=>] [%5d ] %s %s", line_start, buffer, ascii_buffer);
+ }
+ else
+ {
+ fprintf(this->output, "[=>] [%5d ] %s %s\n", line_start, buffer, ascii_buffer);
+ }
+ memset(ascii_buffer, 0, 16);
+ line_start += 16;
+ }
+ else if ((i % 4) == 0)
+ {
+ *buffer_pos++ = ' ';
+ // *buffer_pos++ = ' ';
+ }
+ else
+ {
+ *buffer_pos++ = ' ';
+ }
+
+ if (*bytes_pos > 31 && *bytes_pos < 127)
+ {
+ ascii_buffer[(i % 16)] = *bytes_pos;
+ }
+ else
+ {
+ ascii_buffer[(i % 16)] = '*';
+ }
+
+ bytes_pos++;
+ }
+
+ *buffer_pos++ = '\0';
+ if (buffer_pos > buffer + 1)
+ {
+ buffer_pos = buffer;
+ if (this->output == NULL)
+ {
+ syslog(LOG_INFO, "[=>] [%5d ] %s %16s", line_start, buffer, ascii_buffer);
+ }
+ else
+ {
+ fprintf(this->output, "[=>] [%5d ] %s %16s\n", line_start, buffer, ascii_buffer);
+ }
+ }
+ pthread_mutex_unlock(&mutex);
+ }
+}
+
+/**
+ * Implementation of logger_t.log_chunk.
+ */
+static void log_chunk(logger_t *this, log_level_t loglevel, char *label, chunk_t chunk)
+{
+ this->log_bytes(this, loglevel, label, chunk.ptr, chunk.len);
+}
+
+/**
+ * Implementation of logger_t.enable_level.
+ */
+static void enable_level(private_logger_t *this, log_level_t log_level)
+{
+ this->level |= log_level;
+}
+
+/**
+ * Implementation of logger_t.disable_level.
+ */
+static void disable_level(private_logger_t *this, log_level_t log_level)
+{
+ this->level &= ~log_level;
+}
+
+/**
+ * Implementation of logger_t.set_output.
+ */
+static void set_output(private_logger_t *this, FILE * output)
+{
+ this->output = output;
+}
+
+/**
+ * Implementation of logger_t.get_level.
+ */
+static log_level_t get_level(private_logger_t *this)
+{
+ return this->level;
+}
+
+/**
+ * Implementation of logger_t.destroy.
+ */
+static void destroy(private_logger_t *this)
+{
+ allocator_free(this->name);
+ allocator_free(this);
+}
+
+/*
+ * Described in header.
+ */
+logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output)
+{
+ private_logger_t *this = allocator_alloc_thing(private_logger_t);
+
+ /* public functions */
+ this->public.log = (void(*)(logger_t*,log_level_t,char*,...))logg;
+ this->public.log_bytes = (void(*)(logger_t*, log_level_t, char*,char*,size_t))log_bytes;
+ this->public.log_chunk = log_chunk;
+ this->public.enable_level = (void(*)(logger_t*,log_level_t))enable_level;
+ this->public.disable_level = (void(*)(logger_t*,log_level_t))disable_level;
+ this->public.get_level = (log_level_t(*)(logger_t*))get_level;
+ this->public.set_output = (void(*)(logger_t*,FILE*))set_output;
+ this->public.destroy = (void(*)(logger_t*))destroy;
+
+ /* private functions */
+ this->prepend_prefix = prepend_prefix;
+
+ if (logger_name == NULL)
+ {
+ logger_name = "";
+ }
+
+ /* private variables */
+ this->level = log_level;
+ this->log_thread_id = log_thread_id;
+ this->name = allocator_alloc(strlen(logger_name) + 1);
+
+ strcpy(this->name,logger_name);
+ this->output = output;
+
+ if (output == NULL)
+ {
+ openlog(DAEMON_NAME, 0, LOG_DAEMON);
+ }
+
+ return (logger_t*)this;
+}
diff --git a/Source/lib/utils/logger.h b/Source/lib/utils/logger.h
new file mode 100644
index 000000000..637915e8b
--- /dev/null
+++ b/Source/lib/utils/logger.h
@@ -0,0 +1,199 @@
+/**
+ * @file logger.h
+ *
+ * @brief Interface of logger_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+#include <stdio.h>
+
+#include <types.h>
+
+
+typedef enum log_level_t log_level_t;
+
+/**
+ * @brief Log Levels supported by the logger object.
+ *
+ * Logleves are devided in two different kinds:
+ * - levels to specify the type of the log
+ * - levels to specify the detail-level of the log
+ *
+ * Use combinations of these to build detailed loglevels, such
+ * as CONTROL|MORE fore a detailed cotrol level, or
+ * use RAW to see all raw data dumps (except private).
+ *
+ * @ingroup utils
+ */
+enum log_level_t {
+ /**
+ * Control flow.
+ */
+ CONTROL = 1,
+ /**
+ * Error reporting.
+ */
+ ERROR = 2,
+ /**
+ * Logs important for the sysadmin.
+ */
+ AUDIT = 4,
+ /**
+ * Raw data dumps.
+ */
+ RAW = 8,
+ /**
+ * Private data dumps.
+ */
+ PRIVATE = 16,
+
+ /**
+ * Log most important output, can be omitted.
+ */
+ LEVEL0 = 0,
+ /**
+ * Log more detailed output.
+ */
+ LEVEL1 = 32,
+ /**
+ * Log even more detailed output.
+ */
+ LEVEL2 = LEVEL1 + 64,
+ /**
+ * Use maximum detailed output.
+ */
+ LEVEL3 = LEVEL2 + 128,
+
+ /**
+ * Summary for all types with all detail-levels.
+ */
+ FULL = LEVEL3 + CONTROL + ERROR + RAW + PRIVATE + AUDIT
+};
+
+typedef struct logger_t logger_t;
+
+/**
+ * @brief Class to simplify logging.
+ *
+ * @b Constructors:
+ * - logger_create()
+ *
+ * @ingroup utils
+ */
+struct logger_t {
+
+ /**
+ * @brief Log an entry, using printf()-like params.
+ *
+ * All specified loglevels must be activated that
+ * the log is done.
+ *
+ * @param this logger_t object
+ * @param loglevel or'ed set of log_level_t's
+ * @param format printf like format string
+ * @param ... printf like parameters
+ */
+ void (*log) (logger_t *this, log_level_t log_level, char *format, ...);
+
+ /**
+ * @brief Log some bytes, useful for debugging.
+ *
+ * All specified loglevels must be activated that
+ * the log is done.
+ *
+ * @param this logger_t object
+ * @param loglevel or'ed set of log_level_t's
+ * @param label a labeling name, logged with the bytes
+ * @param bytes pointer to the bytes to dump
+ * @param len number of bytes to dump
+ */
+ void (*log_bytes) (logger_t *this, log_level_t loglevel, char *label, char *bytes, size_t len);
+
+ /**
+ * @brief Log a chunk, useful for debugging.
+ *
+ * All specified loglevels must be activated that
+ * the log is done.
+ *
+ * @param this logger_t object
+ * @param loglevel or'ed set of log_level_t's
+ * @param label a labeling name, logged with the bytes
+ * @param chunk chunk to log
+ */
+ void (*log_chunk) (logger_t *this, log_level_t loglevel, char *label, chunk_t chunk);
+
+ /**
+ * @brief Enables a loglevel for the current logger_t object.
+ *
+ * @param this logger_t object
+ * @param log_level loglevel to enable
+ */
+ void (*enable_level) (logger_t *this, log_level_t log_level);
+
+ /**
+ * @brief Disables a loglevel for the current logger_t object.
+ *
+ * @param this logger_t object
+ * @param log_level loglevel to enable
+ */
+ void (*disable_level) (logger_t *this, log_level_t log_level);
+
+ /**
+ * @brief Set the output of the logger.
+ *
+ * Use NULL for syslog.
+ *
+ * @param this logger_t object
+ * @param output file, where log output should be written
+ */
+ void (*set_output) (logger_t *this, FILE *output);
+
+ /**
+ * @brief Get the currently used loglevel.
+ *
+ * @param this logger_t object
+ * @return currently used loglevel
+ */
+ log_level_t (*get_level) (logger_t *this);
+
+ /**
+ * @brief Destroys a logger_t object.
+ *
+ * @param this logger_t object
+ */
+ void (*destroy) (logger_t *this);
+};
+
+/**
+ * @brief Constructor to create a logger_t object.
+ *
+ * @param logger_name name for the logger_t object
+ * @param log_level or'ed set of log_levels to assign to the new logger_t object
+ * @param log_thread_id TRUE if thread id should also be logged
+ * @param output FILE * if log has to go on a file output, NULL for syslog
+ * @return logger_t object
+ *
+ * @ingroup utils
+ */
+logger_t *logger_create(char *logger_name, log_level_t log_level, bool log_thread_id, FILE * output);
+
+
+#endif /*LOGGER_H_*/
diff --git a/Source/lib/utils/logger_manager.c b/Source/lib/utils/logger_manager.c
new file mode 100644
index 000000000..8270191a9
--- /dev/null
+++ b/Source/lib/utils/logger_manager.c
@@ -0,0 +1,212 @@
+/**
+ * @file logger_manager.c
+ *
+ * @brief Implementation of logger_manager_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 "logger_manager.h"
+
+#include <daemon.h>
+#include <definitions.h>
+#include <utils/allocator.h>
+#include <utils/linked_list.h>
+
+/**
+ * String mappings for logger_context_t
+ */
+mapping_t logger_context_t_mappings[] = {
+ {PARSER, "PARSER"},
+ {GENERATOR, "GENERATOR"},
+ {IKE_SA, "IKE_SA"},
+ {IKE_SA_MANAGER, "IKE_SA_MANAGER"},
+ {CHILD_SA, "CHILD_SA"},
+ {MESSAGE, "MESSAGE"},
+ {THREAD_POOL, "THREAD_POOL"},
+ {WORKER, "WORKER"},
+ {SCHEDULER, "SCHEDULER"},
+ {SENDER, "SENDER"},
+ {RECEIVER, "RECEIVER"},
+ {SOCKET, "SOCKET"},
+ {TESTER, "TESTER"},
+ {DAEMON, "DAEMON"},
+ {CONFIG, "CONFIG"},
+ {ENCRYPTION_PAYLOAD, "ENCRYPTION_PAYLOAD"},
+ {PAYLOAD, "PAYLOAD"},
+ {DER_DECODER, "DER_DECODER"},
+ {DER_ENCODER, "DER_ENCODER"},
+ {MAPPING_END, NULL},
+};
+
+#define DEFAULT_OUTPUT NULL
+
+struct {
+ char *name;
+ log_level_t level;
+ bool log_thread_ids;
+ FILE *output;
+} logger_defaults[] = {
+ { "PARSR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* PARSER */
+ { "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* GENERATOR */
+ { "IKESA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* IKE_SA */
+ { "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* IKE_SA_MANAGER */
+ { "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* CHILD_SA */
+ { "MESSG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* MESSAGE */
+ { "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* THREAD_POOL */
+ { "WORKR", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* WORKER */
+ { "SCHED", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SCHEDULER */
+ { "SENDR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SENDER */
+ { "RECVR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* RECEIVER */
+ { "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* SOCKET */
+ { "TESTR", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* TESTER */
+ { "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0, FALSE, DEFAULT_OUTPUT}, /* DAEMON */
+ { "CONFG", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* CONFIG */
+ { "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* ENCRYPTION_PAYLOAD */
+ { "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* PAYLOAD */
+ { "DERDC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* DER_DECODER */
+ { "DEREC", ERROR|CONTROL|AUDIT|LEVEL0, TRUE, DEFAULT_OUTPUT}, /* DER_ENCODER */
+};
+
+
+typedef struct private_logger_manager_t private_logger_manager_t;
+
+/**
+ * Private data of logger_manager_t object.
+ */
+struct private_logger_manager_t {
+ /**
+ * Public data.
+ */
+ logger_manager_t public;
+
+ /**
+ * Array of loggers, one for each context
+ */
+ logger_t *loggers[LOGGER_CONTEXT_ROOF];
+
+};
+
+/**
+ * Implementation of logger_manager_t.get_logger.
+ */
+static logger_t *get_logger(private_logger_manager_t *this, logger_context_t context)
+{
+ return this->loggers[context];
+}
+
+/**
+ * Implementation of logger_manager_t.get_log_level.
+ */
+static log_level_t get_log_level (private_logger_manager_t *this, logger_context_t context)
+{
+ return this->loggers[context]->get_level(this->loggers[context]);
+}
+
+/**
+ * Implementation of private_logger_manager_t.enable_log_level.
+ */
+static void enable_log_level(private_logger_manager_t *this, logger_context_t context, log_level_t level)
+{
+ if (context == ALL_LOGGERS)
+ {
+ for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
+ {
+ this->loggers[context]->enable_level(this->loggers[context], level);
+ }
+ }
+ else
+ {
+ this->loggers[context]->enable_level(this->loggers[context], level);
+ }
+}
+
+/**
+ * Implementation of private_logger_manager_t.disable_log_level.
+ */
+static void disable_log_level(private_logger_manager_t *this, logger_context_t context, log_level_t level)
+{
+ if (context == ALL_LOGGERS)
+ {
+ for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
+ {
+ this->loggers[context]->disable_level(this->loggers[context], level);
+ }
+ }
+ else
+ {
+ this->loggers[context]->disable_level(this->loggers[context], level);
+ }
+}
+
+/**
+ * Implementation of private_logger_manager_t.set_output.
+ */
+static void set_output(private_logger_manager_t *this, logger_context_t context, FILE *output)
+{
+ if (context == ALL_LOGGERS)
+ {
+ for (context = 0; context < LOGGER_CONTEXT_ROOF; context++)
+ {
+ this->loggers[context]->set_output(this->loggers[context], output);
+ }
+ }
+ else
+ {
+ this->loggers[context]->set_output(this->loggers[context], output);
+ }
+}
+
+
+/**
+ * Implementation of logger_manager_t.destroy.
+ */
+static void destroy(private_logger_manager_t *this)
+{
+ int i;
+ for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
+ {
+ this->loggers[i]->destroy(this->loggers[i]);
+ }
+ allocator_free(this);
+}
+
+/*
+ * Described in header.
+ */
+logger_manager_t *logger_manager_create(log_level_t default_log_level)
+{
+ private_logger_manager_t *this = allocator_alloc_thing(private_logger_manager_t);
+ int i;
+
+ this->public.get_logger = (logger_t *(*)(logger_manager_t*,logger_context_t context))get_logger;
+ this->public.get_log_level = (log_level_t (*)(logger_manager_t *, logger_context_t)) get_log_level;
+ this->public.enable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) enable_log_level;
+ this->public.disable_log_level = (void (*)(logger_manager_t *, logger_context_t, log_level_t)) disable_log_level;
+ this->public.set_output = (void (*)(logger_manager_t *, logger_context_t, FILE*)) set_output;
+ this->public.destroy = (void(*)(logger_manager_t*))destroy;
+
+ for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
+ {
+ this->loggers[i] = logger_create(logger_defaults[i].name, logger_defaults[i].level,
+ logger_defaults[i].log_thread_ids, stdout);//logger_defaults[i].output);
+ }
+
+ return &this->public;
+}
+
diff --git a/Source/lib/utils/logger_manager.h b/Source/lib/utils/logger_manager.h
new file mode 100644
index 000000000..bc8f0e62f
--- /dev/null
+++ b/Source/lib/utils/logger_manager.h
@@ -0,0 +1,155 @@
+/**
+ * @file logger_manager.h
+ *
+ * @brief Interface of logger_manager_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef LOGGER_MANAGER_H_
+#define LOGGER_MANAGER_H_
+
+#include <pthread.h>
+
+#include <utils/logger.h>
+
+
+typedef enum logger_context_t logger_context_t;
+
+/**
+ * @brief Context of a specific logger.
+ *
+ * @ingroup utils
+ */
+enum logger_context_t {
+ ALL_LOGGERS = -1,
+ PARSER = 0,
+ GENERATOR,
+ IKE_SA,
+ IKE_SA_MANAGER,
+ CHILD_SA,
+ MESSAGE,
+ THREAD_POOL,
+ WORKER,
+ SCHEDULER,
+ SENDER,
+ RECEIVER,
+ SOCKET,
+ TESTER,
+ DAEMON,
+ CONFIG,
+ ENCRYPTION_PAYLOAD,
+ PAYLOAD,
+ DER_DECODER,
+ DER_ENCODER,
+ LOGGER_CONTEXT_ROOF,
+};
+
+
+typedef struct logger_manager_t logger_manager_t;
+
+/**
+ * @brief Class to manage logger_t objects.
+ *
+ * The logger manager manages all logger_t object in a list and
+ * allows their manipulation. Via a logger_context_t, the loglevel
+ * of a specific logging type can be adjusted at runtime.
+ *
+ * @b Constructors:
+ * - logger_manager_create()
+ *
+ * @see logger_t
+ *
+ * @ingroup utils
+ */
+struct logger_manager_t {
+
+ /**
+ * @brief Gets a logger_t object for a specific logger context.
+ *
+ * @param this logger_manager_t object
+ * @param context logger_context to use the logger for
+ * @param name name for the new logger. Context name is already included
+ * and has not to be specified (so NULL is allowed)
+ * @return logger_t object
+ */
+ logger_t *(*get_logger) (logger_manager_t *this, logger_context_t context);
+
+ /**
+ * @brief Returns the set log_level of a specific context.
+ *
+ * @param this calling object
+ * @param context context to check level
+ * @return log_level for the given logger_context
+ */
+ log_level_t (*get_log_level) (logger_manager_t *this, logger_context_t context);
+
+ /**
+ * @brief Enables a logger level of a specific context.
+ *
+ * Use context ALL_LOGGERS to manipulate all loggers.
+ *
+ * @param this calling object
+ * @param context context to set level
+ * @param log_level logger level to eanble
+ */
+ void (*enable_log_level) (logger_manager_t *this, logger_context_t context,log_level_t log_level);
+
+ /**
+ * @brief Disables a logger level of a specific context.
+ *
+ * Use context ALL_LOGGERS to manipulate all loggers.
+ *
+ * @param this calling object
+ * @param context context to set level
+ * @param log_level logger level to disable
+ */
+ void (*disable_log_level) (logger_manager_t *this, logger_context_t context,log_level_t log_level);
+
+ /**
+ * @brief Sets the output of a logger.
+ *
+ * Use context ALL_LOGGERS to redirect all loggers.
+ *
+ * @param this calling object
+ * @param context context to set output
+ * @param log_level logger level to disable
+ */
+ void (*set_output) (logger_manager_t *this, logger_context_t context, FILE *output);
+
+ /**
+ * @brief Destroys a logger_manager_t object.
+ *
+ * All managed logger_t objects are also destroyed.
+ *
+ * @param this logger_manager_t object
+ */
+ void (*destroy) (logger_manager_t *this);
+};
+
+/**
+ * @brief Constructor to create a logger_manager_t object.
+ *
+ * @param default_log_level default log level for all context
+ * @return logger_manager_t object
+ *
+ * @ingroup utils
+ */
+logger_manager_t *logger_manager_create(log_level_t default_log_level);
+
+
+#endif /*LOGGER_MANAGER_H_*/
diff --git a/Source/lib/utils/randomizer.c b/Source/lib/utils/randomizer.c
new file mode 100644
index 000000000..efe51af71
--- /dev/null
+++ b/Source/lib/utils/randomizer.c
@@ -0,0 +1,165 @@
+/**
+ * @file randomizer.c
+ *
+ * @brief Implementation of randomizer_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "randomizer.h"
+
+#include <utils/allocator.h>
+
+typedef struct private_randomizer_t private_randomizer_t;
+
+/**
+ * Private data of an randomizer_t object.
+ */
+struct private_randomizer_t {
+
+ /**
+ * Public randomizer_t interface.
+ */
+ randomizer_t public;
+
+ /**
+ * @brief Reads a specific number of bytes from random or pseudo random device.
+ *
+ * @param this calling object
+ * @param pseudo_random TRUE, if from pseudo random bytes should be read,
+ * FALSE for true random bytes
+ * @param bytes number of bytes to read
+ * @param[out] buffer pointer to buffer where to write the data in.
+ * Size of buffer has to be at least bytes.
+ */
+ status_t (*get_bytes_from_device) (private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer);
+};
+
+
+/**
+ * Implementation of private_randomizer_t.get_bytes_from_device.
+ */
+static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer)
+{
+ size_t ndone;
+ int device;
+ size_t got;
+ char * device_name;
+
+ device_name = pseudo_random ? RANDOM_DEVICE : PSEUDO_RANDOM_DEVICE;
+
+ device = open(device_name, 0);
+ if (device < 0) {
+ return FAILED;
+ }
+ ndone = 0;
+
+ /* read until nbytes are read */
+ while (ndone < bytes)
+ {
+ got = read(device, buffer + ndone, bytes - ndone);
+ if (got <= 0) {
+ close(device);
+ return FAILED;
+ }
+ ndone += got;
+ }
+ close(device);
+ return SUCCESS;
+}
+
+/**
+ * Implementation of randomizer_t.get_random_bytes.
+ */
+static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
+{
+ return this->get_bytes_from_device(this, FALSE, bytes, buffer);
+}
+
+/**
+ * Implementation of randomizer_t.allocate_random_bytes.
+ */
+static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
+{
+ status_t status;
+ chunk->len = bytes;
+ chunk->ptr = allocator_alloc(bytes);
+ status = this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr);
+ if (status != SUCCESS)
+ {
+ allocator_free(chunk->ptr);
+ }
+ return status;
+}
+
+/**
+ * Implementation of randomizer_t.get_pseudo_random_bytes.
+ */
+static status_t get_pseudo_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer)
+{
+ return (this->get_bytes_from_device(this, TRUE, bytes, buffer));
+}
+
+/**
+ * Implementation of randomizer_t.allocate_pseudo_random_bytes.
+ */
+static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk)
+{
+ status_t status;
+ chunk->len = bytes;
+ chunk->ptr = allocator_alloc(bytes);
+ status = this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr);
+ if (status != SUCCESS)
+ {
+ allocator_free(chunk->ptr);
+ }
+ return status;
+}
+
+/**
+ * Implementation of randomizer_t.destroy.
+ */
+static void destroy(private_randomizer_t *this)
+{
+ allocator_free(this);
+}
+
+/*
+ * Described in header.
+ */
+randomizer_t *randomizer_create(void)
+{
+ private_randomizer_t *this = allocator_alloc_thing(private_randomizer_t);
+
+ /* public functions */
+ this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes;
+ this->public.allocate_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_random_bytes;
+ this->public.get_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_pseudo_random_bytes;
+ this->public.allocate_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_pseudo_random_bytes;
+ this->public.destroy = (void (*) (randomizer_t *))destroy;
+
+ /* private functions */
+ this->get_bytes_from_device = get_bytes_from_device;
+
+ return &(this->public);
+}
diff --git a/Source/lib/utils/randomizer.h b/Source/lib/utils/randomizer.h
new file mode 100644
index 000000000..55519550e
--- /dev/null
+++ b/Source/lib/utils/randomizer.h
@@ -0,0 +1,110 @@
+/**
+ * @file randomizer.h
+ *
+ * @brief Interface of randomizer_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef RANDOMIZER_H_
+#define RANDOMIZER_H_
+
+#include <types.h>
+
+
+/**
+ * Device to read real random bytes
+ */
+#define RANDOM_DEVICE "/dev/random"
+
+/**
+ * Device to read pseudo random bytes
+ */
+#define PSEUDO_RANDOM_DEVICE "/dev/urandom"
+
+typedef struct randomizer_t randomizer_t;
+
+/**
+ * @brief Class used to get random and pseudo random values.
+ *
+ * @b Constructors:
+ * - randomizer_create()
+ *
+ * @ingroup utils
+ */
+struct randomizer_t {
+
+ /**
+ * @brief Reads a specific number of bytes from random device.
+ *
+ * @param this calling randomizer_t object
+ * @param bytes number of bytes to read
+ * @param[out] buffer pointer to buffer where to write the data in.
+ * Size of buffer has to be at least bytes.
+ * @return SUCCESS, or FAILED
+ */
+ status_t (*get_random_bytes) (randomizer_t *this, size_t bytes, u_int8_t *buffer);
+
+ /**
+ * @brief Allocates space and writes in random bytes.
+ *
+ * @param this calling randomizer_t object
+ * @param bytes number of bytes to allocate
+ * @param[out] chunk chunk which will hold the allocated random bytes
+ * @return SUCCESS, or FAILED
+ */
+ status_t (*allocate_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk);
+
+ /**
+ * @brief Reads a specific number of bytes from pseudo random device.
+ *
+ * @param this calling randomizer_t object
+ * @param bytes number of bytes to read
+ * @param[out] buffer pointer to buffer where to write the data in.
+ * size of buffer has to be at least bytes.
+ * @return SUCCESS, or FAILED
+ */
+ status_t (*get_pseudo_random_bytes) (randomizer_t *this,size_t bytes, u_int8_t *buffer);
+
+ /**
+ * @brief Allocates space and writes in pseudo random bytes.
+ *
+ * @param this calling randomizer_t object
+ * @param bytes number of bytes to allocate
+ * @param[out] chunk chunk which will hold the allocated random bytes
+ * @return SUCCESS, or FAILED
+ */
+ status_t (*allocate_pseudo_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk);
+
+ /**
+ * @brief Destroys a randomizer_t object.
+ *
+ * @param this randomizer_t object to destroy
+ */
+ void (*destroy) (randomizer_t *this);
+};
+
+/**
+ * @brief Creates a randomizer_t object.
+ *
+ * @return created randomizer_t, or
+ *
+ * @ingroup utils
+ */
+randomizer_t *randomizer_create();
+
+#endif /*RANDOMIZER_H_*/
diff --git a/Source/lib/utils/tester.c b/Source/lib/utils/tester.c
new file mode 100644
index 000000000..20dea2e82
--- /dev/null
+++ b/Source/lib/utils/tester.c
@@ -0,0 +1,257 @@
+/**
+ * @file tester.c
+ *
+ * @brief Implementation of tester_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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 <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/time.h>
+
+#include "tester.h"
+
+#include <utils/allocator.h>
+#include <utils/linked_list.h>
+#include <queues/job_queue.h>
+
+
+typedef struct private_tester_t private_tester_t;
+
+/**
+ * @brief Private Data of tester_t class.
+ *
+ */
+struct private_tester_t {
+
+ /**
+ * Protected interface of tester_t.
+ */
+ protected_tester_t protected;
+
+ /**
+ * Runs a specific test.
+ *
+ * @param tester associated tester object
+ * @param test_function test function to perform
+ * @param test_name name for the given test
+ */
+ void (*run_test) (private_tester_t *tester, void (*test_function) (protected_tester_t * tester), char * test_name);
+
+ /**
+ * Returns the difference of to timeval structs in microseconds.
+ *
+ * @warning this function is also defined in the event queue
+ * in later improvements, this function can be added to a general
+ * class type!
+ *
+ * @param end_time end time
+ * @param start_time start time
+ *
+ * @TODO make object function or move to utils!
+ *
+ * @return difference in microseconds
+ */
+ long (*time_difference) (private_tester_t *tester,struct timeval *end_time, struct timeval *start_time);
+
+ /**
+ * Output is written into this file.
+ */
+ FILE* output;
+
+ /**
+ * Number of already performed tests.
+ */
+ int tests_count;
+
+ /**
+ * Number of failed tests.
+ */
+ int failed_tests_count;
+
+ /**
+ * Number of failed asserts in current test.
+ */
+ int failed_asserts_count;
+
+ /**
+ * TRUE if also succeeded asserts should be written to output.
+ */
+ bool display_succeeded_asserts;
+
+ /**
+ * Mutex to make this class thread-save.
+ */
+ pthread_mutex_t mutex;
+};
+
+/**
+ * Implementation of tester_t.perform_tests.
+ */
+static void perform_tests(private_tester_t *this,test_t **tests)
+{
+ int current_test = 0;
+ fprintf(this->output,"\nStart testing...\n\n");
+ fprintf(this->output,"_____________________________________________________________________\n");
+ fprintf(this->output,"Testname | running time\n");
+ fprintf(this->output,"_______________________________________________________|_____________\n");
+
+ while (tests[current_test] != NULL)
+ {
+ this->run_test(this,tests[current_test]->test_function,tests[current_test]->test_name);
+ current_test++;
+ }
+ fprintf(this->output,"=====================================================================\n");
+ fprintf(this->output,"End testing. %d of %d tests succeeded\n",this->tests_count - this->failed_tests_count,this->tests_count);
+ fprintf(this->output,"=====================================================================\n");
+}
+
+/**
+ * Implementation of tester_t.perform_test.
+ */
+static void perform_test(private_tester_t *this, test_t *test)
+{
+ test_t *tests[] = {test, NULL};
+ return (perform_tests(this,tests));
+}
+
+/**
+ * Returns the difference of to timeval structs in microseconds.
+ *
+ * @warning this function is also defined in the event queue
+ * in later improvements, this function can be added to a general
+ * class type!
+ *
+ * @param end_time end time
+ * @param start_time start time
+ *
+ * @TODO make object function or move to utils!
+ *
+ * @return difference in microseconds
+ */
+static long time_difference(private_tester_t *this,struct timeval *end_time, struct timeval *start_time)
+{
+ long seconds, microseconds;
+
+ seconds = (end_time->tv_sec - start_time->tv_sec);
+ microseconds = (end_time->tv_usec - start_time->tv_usec);
+ return ((seconds * 1000000) + microseconds);
+}
+
+
+/**
+ * Implementation of private_tester_t.run_test.
+ */
+static void run_test(private_tester_t *this, void (*test_function) (protected_tester_t * tester), char * test_name)
+{
+ struct timeval start_time, end_time;
+ long timediff;
+ this->tests_count++;
+ this->failed_asserts_count = 0;
+ fprintf(this->output,"%-55s\n", test_name);
+ gettimeofday(&start_time,NULL);
+ test_function(&(this->protected));
+ gettimeofday(&end_time,NULL);
+ timediff = this->time_difference(this,&end_time, &start_time);
+
+ if (this->failed_asserts_count > 0)
+ {
+ fprintf(this->output," => Test failed: %-37s|%10ld us\n",test_name,timediff);
+ }else
+ {
+ fprintf(this->output,"\033[1A\033[55C|%10ld us\033[1B\033[80D",timediff);
+ }
+ if (this->failed_asserts_count > 0)
+ {
+ this->failed_tests_count++;
+ }
+}
+
+
+/**
+ * Implementation of tester_t.assert_true.
+ */
+static void assert_true(private_tester_t *this, bool to_be_true,char * assert_name)
+{
+ if (assert_name == NULL)
+ {
+ assert_name = "unknown";
+ }
+
+ pthread_mutex_lock(&(this->mutex));
+ if (!to_be_true)
+ {
+ this->failed_asserts_count++;
+ fprintf(this->output," check '%s' failed!\n", assert_name);
+ }else
+ {
+ if (this->display_succeeded_asserts)
+ {
+ fprintf(this->output," check '%s' succeeded\n", assert_name);
+ }
+ }
+ pthread_mutex_unlock(&(this->mutex));
+}
+
+/**
+ * Implementation of tester_t.assert_false.
+ */
+static void assert_false(private_tester_t *this, bool to_be_false,char * assert_name)
+{
+ this->protected.assert_true(&(this->protected),(!to_be_false),assert_name);
+}
+
+/**
+ * Implementation of tester_t.destroy.
+ */
+static void destroy(private_tester_t *tester)
+{
+ private_tester_t *this = (private_tester_t*) tester;
+ pthread_mutex_destroy(&(this->mutex));
+ allocator_free(this);
+}
+
+/*
+ * Described in header.
+ */
+tester_t *tester_create(FILE *output, bool display_succeeded_asserts)
+{
+ private_tester_t *this = allocator_alloc_thing(private_tester_t);
+
+ /* public functions */
+ this->protected.public.destroy = (void (*) (tester_t *))destroy;
+ this->protected.public.perform_tests = (void (*) (tester_t *, test_t**)) perform_tests;
+ this->protected.public.perform_test = (void (*) (tester_t *, test_t*))perform_test;
+ this->protected.assert_true = (void (*) (protected_tester_t *, bool, char*)) assert_true;
+ this->protected.assert_false = (void (*) (protected_tester_t *, bool, char*)) assert_false;
+
+ /* private functions */
+ this->run_test = run_test;
+ this->time_difference = time_difference;
+
+ /* private data */
+ this->display_succeeded_asserts = display_succeeded_asserts;
+ this->failed_tests_count = 0;
+ this->tests_count = 0;
+ this->output = output;
+ pthread_mutex_init(&(this->mutex),NULL);
+
+ return &(this->protected.public);
+}
diff --git a/Source/lib/utils/tester.h b/Source/lib/utils/tester.h
new file mode 100644
index 000000000..3decb2039
--- /dev/null
+++ b/Source/lib/utils/tester.h
@@ -0,0 +1,148 @@
+/**
+ * @file tester.h
+ *
+ * @brief Interface of tester_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#ifndef TESTER_H_
+#define TESTER_H_
+
+#include <stdio.h>
+
+#include <types.h>
+
+
+/* must be defined here cause it is used in test_t */
+typedef struct protected_tester_t protected_tester_t;
+
+typedef struct test_t test_t;
+
+/**
+ * @brief Representing a specified test.
+ *
+ * @ingroup utils
+ */
+struct test_t {
+ /**
+ * Testfunction called for this test.
+ *
+ * @param tester associated tester_t object
+ */
+ void (*test_function) (protected_tester_t * tester);
+
+ /**
+ * Name of the test.
+ */
+ char * test_name;
+};
+
+
+typedef struct tester_t tester_t;
+
+/**
+ * @brief A class to perform tests.
+ *
+ * @b Constructors:
+ * - tester_create()
+ *
+ * @ingroup utils
+ */
+struct tester_t {
+ /**
+ * @brief Test all testcases in array tests with specific tester_t object.
+ *
+ * @param tester tester_t object
+ * @param tests pointer to an array of test_t-pointers.
+ * The last item has to be NULL to mark end of array.
+ */
+ void (*perform_tests) (tester_t *tester,test_t **tests);
+
+ /**
+ * @brief Run a specific test case.
+ *
+ * @param this tester_t object
+ * @param test pointer to a test_t object which will be performed
+ */
+ void (*perform_test) (tester_t *tester, test_t *test);
+
+ /**
+ * @brief Destroys a tester_t object.
+ *
+ * @param tester tester_t object
+ */
+ void (*destroy) (tester_t *tester);
+};
+
+
+/**
+ * @brief A class used in a specific testcase.
+ *
+ * For each testcase an object of this type is passed to the testfunction. The testfunction uses this
+ * object to check specific asserts with protected_tester_t.assert_true and protected_tester_t.assert_false.
+ *
+ * @b Constructors:
+ * - tester_create()
+ *
+ * @ingroup utils
+ */
+struct protected_tester_t {
+
+ /**
+ * Public functions of a tester_t object
+ */
+ tester_t public;
+
+ /**
+ * @brief Is called in a testcase to check a specific situation for TRUE.
+ *
+ * Log-Values to the tester output are protected from multiple access.
+ *
+ * @param this tester_t object
+ * @param to_be_true assert which has to be TRUE
+ * @param assert_name name of the assertion
+ */
+ void (*assert_true) (protected_tester_t *tester, bool to_be_true, char *assert_name);
+
+ /**
+ * @brief Is called in a testcase to check a specific situation for FALSE.
+ *
+ * Log-Values to the tester output are protected from multiple access.
+ *
+ * @param this tester_t object
+ * @param to_be_false assert which has to be FALSE
+ * @param assert_name name of the assertion
+ */
+ void (*assert_false) (protected_tester_t *tester, bool to_be_false, char *assert_name);
+};
+
+
+/**
+ * @brief Creates a tester_t object used to perform tests with.
+ *
+ * @param output test output is written to this output.
+ * @param display_succeeded_asserts has to be TRUE, if all asserts should be displayed,
+ * FALSE otherwise
+ *
+ * @return tester_t object
+ *
+ * @ingroup utils
+ */
+tester_t *tester_create(FILE *output, bool display_succeeded_asserts);
+
+#endif /*TESTER_H_*/