../svn-commit.tmp

This commit is contained in:
Martin Willi
2006-04-05 12:10:50 +00:00
parent 3dbbbf3e16
commit 6862128151
171 changed files with 674 additions and 1355 deletions
+48
View File
@@ -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 $@ $<
+445
View File
@@ -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 */
+324
View File
@@ -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_*/
+365
View File
@@ -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;
}
}
+225
View File
@@ -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_*/
+291
View File
@@ -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);
}
+211
View File
@@ -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, "[email protected]". 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. [email protected]) 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_ */
+153
View File
@@ -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_*/
+729
View File
@@ -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));
}
+203
View File
@@ -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_*/
+360
View File
@@ -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;
}
+199
View File
@@ -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_*/
+212
View File
@@ -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;
}
+155
View File
@@ -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_*/
+165
View File
@@ -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);
}
+110
View File
@@ -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_*/
+257
View File
@@ -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);
}
+148
View File
@@ -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_*/