aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2015-04-16 16:50:27 +0200
committerMartin Willi <martin@revosec.ch>2015-04-16 16:50:27 +0200
commitd49330a9a877027d8976a5cafc0b4f0ad0da4ff7 (patch)
treef297ac6cbb25d9fc712dd719954160799e539ec1
parent31a171f5c4bf4bd6076bf1542c5660f0690c42ba (diff)
parent882c993b8937303f540605811b0bfd090b4f3ca1 (diff)
downloadstrongswan-d49330a9a877027d8976a5cafc0b4f0ad0da4ff7.tar.bz2
strongswan-d49330a9a877027d8976a5cafc0b4f0ad0da4ff7.tar.xz
Merge branch 'utils-split'
Split up the almighty utils.[ch] to separate files in the utils/utils subfolder. These are not meant to include manually, but bring back some order to all this functionality included through utils.h. Additionally give some love to apidoc generation.
-rw-r--r--Doxyfile.in4
-rw-r--r--Makefile.am6
-rw-r--r--src/libstrongswan/Android.mk5
-rw-r--r--src/libstrongswan/Makefile.am10
-rw-r--r--src/libstrongswan/utils/utils.c802
-rw-r--r--src/libstrongswan/utils/utils.h979
-rw-r--r--src/libstrongswan/utils/utils/align.c62
-rw-r--r--src/libstrongswan/utils/utils/align.h86
-rw-r--r--src/libstrongswan/utils/utils/atomics.c112
-rw-r--r--src/libstrongswan/utils/utils/atomics.h130
-rw-r--r--src/libstrongswan/utils/utils/byteorder.h161
-rw-r--r--src/libstrongswan/utils/utils/memory.c237
-rw-r--r--src/libstrongswan/utils/utils/memory.h183
-rw-r--r--src/libstrongswan/utils/utils/object.h126
-rw-r--r--src/libstrongswan/utils/utils/path.c168
-rw-r--r--src/libstrongswan/utils/utils/path.h77
-rw-r--r--src/libstrongswan/utils/utils/status.c48
-rw-r--r--src/libstrongswan/utils/utils/status.h72
-rw-r--r--src/libstrongswan/utils/utils/strerror.h3
-rw-r--r--src/libstrongswan/utils/utils/string.c91
-rw-r--r--src/libstrongswan/utils/utils/string.h103
-rw-r--r--src/libstrongswan/utils/utils/time.c143
-rw-r--r--src/libstrongswan/utils/utils/time.h91
-rw-r--r--src/libstrongswan/utils/utils/tty.c86
-rw-r--r--src/libstrongswan/utils/utils/tty.h65
-rw-r--r--src/libstrongswan/utils/utils/types.h87
26 files changed, 2180 insertions, 1757 deletions
diff --git a/Doxyfile.in b/Doxyfile.in
index eaf02d7de..7608ffef1 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -416,7 +416,7 @@ EXTRACT_PACKAGE = NO
# included in the documentation.
# The default value is: NO.
-EXTRACT_STATIC = NO
+EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO
@@ -683,7 +683,7 @@ CITE_BIB_FILES =
# messages are off.
# The default value is: NO.
-QUIET = NO
+QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
diff --git a/Makefile.am b/Makefile.am
index bea4ba7c0..f9e6452a2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,9 @@ Doxyfile : Doxyfile.in
$(srcdir)/$@.in > $@
apidoc : Doxyfile
- doxygen
+ @test -d apidoc || doxygen
+ @! find Doxyfile src/ -name '*.h' -o -name '*.md' , -newer apidoc | \
+ grep -q '' || doxygen && touch apidoc
cov-reset-common:
@rm -rf $(top_builddir)/coverage
@@ -75,4 +77,4 @@ clean-local: cov-reset-common
@find $(top_builddir)/src $(top_builddir)/scripts -name "*.gcno" -delete
@rm -rf apidoc
-.PHONY: cov-reset-common cov-reset cov-report coverage
+.PHONY: cov-reset-common cov-reset cov-report coverage apidoc
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index b137b73f9..d019d96e1 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -39,7 +39,10 @@ selectors/traffic_selector.c settings/settings.c settings/settings_types.c \
settings/settings_parser.c settings/settings_lexer.c utils/cpu_feature.c \
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
-utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c
+utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c \
+utils/utils/atomics.c utils/utils/string.c utils/utils/memory.c \
+utils/utils/tty.c utils/utils/path.c utils/utils/status.c utils/utils/time.c \
+utils/utils/align.c
libstrongswan_la_SOURCES += \
threading/thread.c \
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 462c34bb2..b3636cfb8 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -37,7 +37,10 @@ selectors/traffic_selector.c settings/settings.c settings/settings_types.c \
settings/settings_parser.y settings/settings_lexer.l utils/cpu_feature.c \
utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
-utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c
+utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c \
+utils/utils/atomics.c utils/utils/string.c utils/utils/memory.c \
+utils/utils/tty.c utils/utils/path.c utils/utils/status.c utils/utils/time.c \
+utils/utils/align.c
if !USE_WINDOWS
libstrongswan_la_SOURCES += \
@@ -106,7 +109,10 @@ utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
utils/cpu_feature.h utils/leak_detective.h utils/printf_hook/printf_hook.h \
utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/process.h \
-utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h
+utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h \
+utils/utils/atomics.h utils/utils/types.h utils/utils/byteorder.h \
+utils/utils/string.h utils/utils/memory.h utils/utils/tty.h utils/utils/path.h \
+utils/utils/status.h utils/utils/object.h utils/utils/time.h utils/utils/align.h
endif
library.lo : $(top_builddir)/config.status
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 119c6563a..9b516accd 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -14,284 +14,22 @@
* for more details.
*/
-#define _GNU_SOURCE /* for memrchr */
-#ifdef WIN32
-/* for GetTickCount64, Windows 7 */
-# define _WIN32_WINNT 0x0601
-#endif
-
#include "utils.h"
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
#include <unistd.h>
-#include <inttypes.h>
-#include <stdint.h>
#include <limits.h>
-#include <dirent.h>
-#include <time.h>
#ifndef WIN32
# include <signal.h>
#endif
#include <library.h>
-#include <utils/debug.h>
-#include <utils/chunk.h>
#include <collections/enumerator.h>
-#include <threading/spinlock.h>
-#include <threading/mutex.h>
-#include <threading/condvar.h>
-
-ENUM(status_names, SUCCESS, NEED_MORE,
- "SUCCESS",
- "FAILED",
- "OUT_OF_RES",
- "ALREADY_DONE",
- "NOT_SUPPORTED",
- "INVALID_ARG",
- "NOT_FOUND",
- "PARSE_ERROR",
- "VERIFY_ERROR",
- "INVALID_STATE",
- "DESTROY_ME",
- "NEED_MORE",
-);
-
-/**
- * Described in header.
- */
-void* malloc_align(size_t size, u_int8_t align)
-{
- u_int8_t pad;
- void *ptr;
-
- if (align == 0)
- {
- align = 1;
- }
- ptr = malloc(align + sizeof(pad) + size);
- if (!ptr)
- {
- return NULL;
- }
- /* store padding length just before data, down to the allocation boundary
- * to do some verification during free_align() */
- pad = align - ((uintptr_t)ptr % align);
- memset(ptr, pad, pad);
- return ptr + pad;
-}
-
-/**
- * Described in header.
- */
-void free_align(void *ptr)
-{
- u_int8_t pad, *pos;
-
- pos = ptr - 1;
- /* verify padding to check any corruption */
- for (pad = *pos; (void*)pos >= ptr - pad; pos--)
- {
- if (*pos != pad)
- {
- DBG1(DBG_LIB, "!!!! invalid free_align() !!!!");
- return;
- }
- }
- free(ptr - pad);
-}
-
-/**
- * Described in header.
- */
-void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
-{
- int m, i;
-
- /* byte wise XOR until dst aligned */
- for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
- {
- dst[i] ^= src[i];
- }
- /* try to use words if src shares an aligment with dst */
- switch (((uintptr_t)&src[i] % sizeof(long)))
- {
- case 0:
- for (m = n - sizeof(long); i <= m; i += sizeof(long))
- {
- *(long*)&dst[i] ^= *(long*)&src[i];
- }
- break;
- case sizeof(int):
- for (m = n - sizeof(int); i <= m; i += sizeof(int))
- {
- *(int*)&dst[i] ^= *(int*)&src[i];
- }
- break;
- case sizeof(short):
- for (m = n - sizeof(short); i <= m; i += sizeof(short))
- {
- *(short*)&dst[i] ^= *(short*)&src[i];
- }
- break;
- default:
- break;
- }
- /* byte wise XOR of the rest */
- for (; i < n; i++)
- {
- dst[i] ^= src[i];
- }
-}
-
-/**
- * Described in header.
- */
-void memwipe_noinline(void *ptr, size_t n)
-{
- memwipe_inline(ptr, n);
-}
-
-/**
- * Described in header.
- */
-bool memeq_const(const void *x, const void *y, size_t len)
-{
- const u_char *a, *b;
- u_int bad = 0;
- size_t i;
-
- a = (const u_char*)x;
- b = (const u_char*)y;
-
- for (i = 0; i < len; i++)
- {
- bad |= a[i] != b[i];
- }
- return !bad;
-}
-
-/**
- * Described in header.
- */
-void *memstr(const void *haystack, const char *needle, size_t n)
-{
- const u_char *pos = haystack;
- size_t l;
-
- if (!haystack || !needle || (l = strlen(needle)) == 0)
- {
- return NULL;
- }
- for (; n >= l; ++pos, --n)
- {
- if (memeq(pos, needle, l))
- {
- return (void*)pos;
- }
- }
- return NULL;
-}
-
-/**
- * Described in header.
- */
-void *utils_memrchr(const void *s, int c, size_t n)
-{
- const u_char *pos;
-
- if (!s || !n)
- {
- return NULL;
- }
-
- for (pos = s + n - 1; pos >= (u_char*)s; pos--)
- {
- if (*pos == (u_char)c)
- {
- return (void*)pos;
- }
- }
- return NULL;
-}
-
-/**
- * Described in header.
- */
-char* translate(char *str, const char *from, const char *to)
-{
- char *pos = str;
- if (strlen(from) != strlen(to))
- {
- return str;
- }
- while (pos && *pos)
- {
- char *match;
- if ((match = strchr(from, *pos)) != NULL)
- {
- *pos = to[match - from];
- }
- pos++;
- }
- return str;
-}
-
-/**
- * Described in header.
- */
-char* strreplace(const char *str, const char *search, const char *replace)
-{
- size_t len, slen, rlen, count = 0;
- char *res, *pos, *found, *dst;
-
- if (!str || !*str || !search || !*search || !replace)
- {
- return (char*)str;
- }
- slen = strlen(search);
- rlen = strlen(replace);
- if (slen != rlen)
- {
- for (pos = (char*)str; (pos = strstr(pos, search)); pos += slen)
- {
- found = pos;
- count++;
- }
- if (!count)
- {
- return (char*)str;
- }
- len = (found - str) + strlen(found) + count * (rlen - slen);
- }
- else
- {
- len = strlen(str);
- }
- found = strstr(str, search);
- if (!found)
- {
- return (char*)str;
- }
- dst = res = malloc(len + 1);
- pos = (char*)str;
- do
- {
- len = found - pos;
- memcpy(dst, pos, len);
- dst += len;
- memcpy(dst, replace, rlen);
- dst += rlen;
- pos = found + slen;
- }
- while ((found = strstr(pos, search)));
- strcpy(dst, pos);
- return res;
-}
#ifdef WIN32
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+
/**
* Flag to indicate signaled wait_sigint()
*/
@@ -368,216 +106,6 @@ void wait_sigint()
#endif
-/**
- * Described in header.
- */
-char* path_dirname(const char *path)
-{
- char *pos;
-
- pos = path ? strrchr(path, DIRECTORY_SEPARATOR[0]) : NULL;
-
- if (pos && !pos[1])
- { /* if path ends with slashes we have to look beyond them */
- while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
- { /* skip trailing slashes */
- pos--;
- }
- pos = memrchr(path, DIRECTORY_SEPARATOR[0], pos - path + 1);
- }
- if (!pos)
- {
-#ifdef WIN32
- if (path && strlen(path))
- {
- if ((isalpha(path[0]) && path[1] == ':'))
- { /* if just a drive letter given, return that as dirname */
- return chunk_clone(chunk_from_chars(path[0], ':', 0)).ptr;
- }
- }
-#endif
- return strdup(".");
- }
- while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
- { /* skip superfluous slashes */
- pos--;
- }
- return strndup(path, pos - path + 1);
-}
-
-/**
- * Described in header.
- */
-char* path_basename(const char *path)
-{
- char *pos, *trail = NULL;
-
- if (!path || !*path)
- {
- return strdup(".");
- }
- pos = strrchr(path, DIRECTORY_SEPARATOR[0]);
- if (pos && !pos[1])
- { /* if path ends with slashes we have to look beyond them */
- while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
- { /* skip trailing slashes */
- pos--;
- }
- if (pos == path && *pos == DIRECTORY_SEPARATOR[0])
- { /* contains only slashes */
- return strdup(DIRECTORY_SEPARATOR);
- }
- trail = pos + 1;
- pos = memrchr(path, DIRECTORY_SEPARATOR[0], trail - path);
- }
- pos = pos ? pos + 1 : (char*)path;
- return trail ? strndup(pos, trail - pos) : strdup(pos);
-}
-
-/**
- * Described in header.
- */
-bool path_absolute(const char *path)
-{
- if (!path)
- {
- return FALSE;
- }
-#ifdef WIN32
- if (strpfx(path, "\\\\"))
- { /* UNC */
- return TRUE;
- }
- if (strlen(path) && isalpha(path[0]) && path[1] == ':')
- { /* drive letter */
- return TRUE;
- }
-#else /* !WIN32 */
- if (path[0] == DIRECTORY_SEPARATOR[0])
- {
- return TRUE;
- }
-#endif
- return FALSE;
-}
-
-/**
- * Described in header.
- */
-bool mkdir_p(const char *path, mode_t mode)
-{
- int len;
- char *pos, full[PATH_MAX];
- pos = full;
- if (!path || *path == '\0')
- {
- return TRUE;
- }
- len = snprintf(full, sizeof(full)-1, "%s", path);
- if (len < 0 || len >= sizeof(full)-1)
- {
- DBG1(DBG_LIB, "path string %s too long", path);
- return FALSE;
- }
- /* ensure that the path ends with a '/' */
- if (full[len-1] != '/')
- {
- full[len++] = '/';
- full[len] = '\0';
- }
- /* skip '/' at the beginning */
- while (*pos == '/')
- {
- pos++;
- }
- while ((pos = strchr(pos, '/')))
- {
- *pos = '\0';
- if (access(full, F_OK) < 0)
- {
-#ifdef WIN32
- if (_mkdir(full) < 0)
-#else
- if (mkdir(full, mode) < 0)
-#endif
- {
- DBG1(DBG_LIB, "failed to create directory %s", full);
- return FALSE;
- }
- }
- *pos = '/';
- pos++;
- }
- return TRUE;
-}
-
-ENUM(tty_color_names, TTY_RESET, TTY_BG_DEF,
- "\e[0m",
- "\e[1m",
- "\e[4m",
- "\e[5m",
- "\e[30m",
- "\e[31m",
- "\e[32m",
- "\e[33m",
- "\e[34m",
- "\e[35m",
- "\e[36m",
- "\e[37m",
- "\e[39m",
- "\e[40m",
- "\e[41m",
- "\e[42m",
- "\e[43m",
- "\e[44m",
- "\e[45m",
- "\e[46m",
- "\e[47m",
- "\e[49m",
-);
-
-/**
- * Get the escape string for a given TTY color, empty string on non-tty FILE
- */
-char* tty_escape_get(int fd, tty_escape_t escape)
-{
- if (!isatty(fd))
- {
- return "";
- }
- switch (escape)
- {
- case TTY_RESET:
- case TTY_BOLD:
- case TTY_UNDERLINE:
- case TTY_BLINKING:
-#ifdef WIN32
- return "";
-#endif
- case TTY_FG_BLACK:
- case TTY_FG_RED:
- case TTY_FG_GREEN:
- case TTY_FG_YELLOW:
- case TTY_FG_BLUE:
- case TTY_FG_MAGENTA:
- case TTY_FG_CYAN:
- case TTY_FG_WHITE:
- case TTY_FG_DEF:
- case TTY_BG_BLACK:
- case TTY_BG_RED:
- case TTY_BG_GREEN:
- case TTY_BG_YELLOW:
- case TTY_BG_BLUE:
- case TTY_BG_MAGENTA:
- case TTY_BG_CYAN:
- case TTY_BG_WHITE:
- case TTY_BG_DEF:
- return enum_to_name(tty_color_names, escape);
- /* warn if a escape code is missing */
- }
- return "";
-}
-
#ifndef HAVE_CLOSEFROM
/**
* Described in header.
@@ -626,58 +154,6 @@ void closefrom(int lowfd)
#endif /* HAVE_CLOSEFROM */
/**
- * Return monotonic time
- */
-time_t time_monotonic(timeval_t *tv)
-{
-#ifdef WIN32
- ULONGLONG ms;
- time_t s;
-
- ms = GetTickCount64();
- s = ms / 1000;
- if (tv)
- {
- tv->tv_sec = s;
- tv->tv_usec = (ms - (s * 1000)) * 1000;
- }
- return s;
-#else /* !WIN32 */
-#if defined(HAVE_CLOCK_GETTIME) && \
- (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
- defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
- /* as we use time_monotonic() for condvar operations, we use the
- * monotonic time source only if it is also supported by pthread. */
- timespec_t ts;
-
- if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
- {
- if (tv)
- {
- tv->tv_sec = ts.tv_sec;
- tv->tv_usec = ts.tv_nsec / 1000;
- }
- return ts.tv_sec;
- }
-#endif /* HAVE_CLOCK_GETTIME && (...) */
- /* Fallback to non-monotonic timestamps:
- * On MAC OS X, creating monotonic timestamps is rather difficult. We
- * could use mach_absolute_time() and catch sleep/wakeup notifications.
- * We stick to the simpler (non-monotonic) gettimeofday() for now.
- * But keep in mind: we need the same time source here as in condvar! */
- if (!tv)
- {
- return time(NULL);
- }
- if (gettimeofday(tv, NULL) != 0)
- { /* should actually never fail if passed pointers are valid */
- return -1;
- }
- return tv->tv_sec;
-#endif /* !WIN32 */
-}
-
-/**
* return null
*/
void *return_null()
@@ -702,144 +178,12 @@ bool return_false()
}
/**
- * returns FAILED
- */
-status_t return_failed()
-{
- return FAILED;
-}
-
-/**
- * returns SUCCESS
- */
-status_t return_success()
-{
- return SUCCESS;
-}
-
-/**
* nop operation
*/
void nop()
{
}
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-
-/**
- * Spinlock for ref_get/put
- */
-static spinlock_t *ref_lock;
-
-/**
- * Increase refcount
- */
-refcount_t ref_get(refcount_t *ref)
-{
- refcount_t current;
-
- ref_lock->lock(ref_lock);
- current = ++(*ref);
- ref_lock->unlock(ref_lock);
-
- return current;
-}
-
-/**
- * Decrease refcount
- */
-bool ref_put(refcount_t *ref)
-{
- bool more_refs;
-
- ref_lock->lock(ref_lock);
- more_refs = --(*ref) > 0;
- ref_lock->unlock(ref_lock);
- return !more_refs;
-}
-
-/**
- * Current refcount
- */
-refcount_t ref_cur(refcount_t *ref)
-{
- refcount_t current;
-
- ref_lock->lock(ref_lock);
- current = *ref;
- ref_lock->unlock(ref_lock);
-
- return current;
-}
-
-/**
- * Spinlock for all compare and swap operations.
- */
-static spinlock_t *cas_lock;
-
-/**
- * Compare and swap if equal to old value
- */
-#define _cas_impl(name, type) \
-bool cas_##name(type *ptr, type oldval, type newval) \
-{ \
- bool swapped; \
- cas_lock->lock(cas_lock); \
- if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
- cas_lock->unlock(cas_lock); \
- return swapped; \
-}
-
-_cas_impl(bool, bool)
-_cas_impl(ptr, void*)
-
-#endif /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
-
-
-#ifdef HAVE_FMEMOPEN_FALLBACK
-
-static int fmemread(chunk_t *cookie, char *buf, int size)
-{
- int len;
-
- len = min(size, cookie->len);
- memcpy(buf, cookie->ptr, len);
- *cookie = chunk_skip(*cookie, len);
-
- return len;
-}
-
-static int fmemwrite(chunk_t *cookie, const char *buf, int size)
-{
- int len;
-
- len = min(size, cookie->len);
- memcpy(cookie->ptr, buf, len);
- *cookie = chunk_skip(*cookie, len);
-
- return len;
-}
-
-static int fmemclose(void *cookie)
-{
- free(cookie);
- return 0;
-}
-
-FILE *fmemopen(void *buf, size_t size, const char *mode)
-{
- chunk_t *cookie;
-
- INIT(cookie,
- .ptr = buf,
- .len = size,
- );
-
- return funopen(cookie, (void*)fmemread, (void*)fmemwrite, NULL, fmemclose);
-}
-
-#endif /* FMEMOPEN fallback*/
-
/**
* See header
*/
@@ -848,12 +192,7 @@ void utils_init()
#ifdef WIN32
windows_init();
#endif
-
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
- ref_lock = spinlock_create();
- cas_lock = spinlock_create();
-#endif
-
+ atomics_init();
strerror_init();
}
@@ -865,137 +204,6 @@ void utils_deinit()
#ifdef WIN32
windows_deinit();
#endif
-
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
- ref_lock->destroy(ref_lock);
- cas_lock->destroy(cas_lock);
-#endif
-
+ atomics_deinit();
strerror_deinit();
}
-
-/**
- * Described in header.
- */
-int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args)
-{
- static const char* months[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- time_t *time = *((time_t**)(args[0]));
- bool utc = *((int*)(args[1]));
- struct tm t, *ret = NULL;
-
- if (*time != UNDEFINED_TIME)
- {
- if (utc)
- {
- ret = gmtime_r(time, &t);
- }
- else
- {
- ret = localtime_r(time, &t);
- }
- }
- if (ret == NULL)
- {
- return print_in_hook(data, "--- -- --:--:--%s----",
- utc ? " UTC " : " ");
- }
- return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
- months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
- t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
-}
-
-/**
- * Described in header.
- */
-int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args)
-{
- char* unit = "second";
- time_t *arg1 = *((time_t**)(args[0]));
- time_t *arg2 = *((time_t**)(args[1]));
- u_int64_t delta = llabs(*arg1 - *arg2);
-
- if (delta > 2 * 60 * 60 * 24)
- {
- delta /= 60 * 60 * 24;
- unit = "day";
- }
- else if (delta > 2 * 60 * 60)
- {
- delta /= 60 * 60;
- unit = "hour";
- }
- else if (delta > 2 * 60)
- {
- delta /= 60;
- unit = "minute";
- }
- return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
- (delta == 1) ? "" : "s");
-}
-
-/**
- * Number of bytes per line to dump raw data
- */
-#define BYTES_PER_LINE 16
-
-static char hexdig_upper[] = "0123456789ABCDEF";
-
-/**
- * Described in header.
- */
-int mem_printf_hook(printf_hook_data_t *data,
- printf_hook_spec_t *spec, const void *const *args)
-{
- char *bytes = *((void**)(args[0]));
- u_int len = *((int*)(args[1]));
-
- char buffer[BYTES_PER_LINE * 3];
- char ascii_buffer[BYTES_PER_LINE + 1];
- char *buffer_pos = buffer;
- char *bytes_pos = bytes;
- char *bytes_roof = bytes + len;
- int line_start = 0;
- int i = 0;
- int written = 0;
-
- written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
-
- while (bytes_pos < bytes_roof)
- {
- *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
- *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
-
- ascii_buffer[i++] =
- (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
-
- if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
- {
- int padding = 3 * (BYTES_PER_LINE - i);
-
- while (padding--)
- {
- *buffer_pos++ = ' ';
- }
- *buffer_pos++ = '\0';
- ascii_buffer[i] = '\0';
-
- written += print_in_hook(data, "\n%4d: %s %s",
- line_start, buffer, ascii_buffer);
-
- buffer_pos = buffer;
- line_start += BYTES_PER_LINE;
- i = 0;
- }
- else
- {
- *buffer_pos++ = ' ';
- }
- }
- return written;
-}
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index c42f88168..acc15c42a 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -40,6 +40,33 @@
# include <poll.h>
#endif
+#include "utils/types.h"
+#include "enum.h"
+#include "utils/atomics.h"
+#include "utils/align.h"
+#include "utils/byteorder.h"
+#include "utils/string.h"
+#include "utils/memory.h"
+#include "utils/strerror.h"
+#include "utils/status.h"
+#include "utils/object.h"
+#include "utils/path.h"
+#include "utils/time.h"
+#include "utils/tty.h"
+#ifdef __APPLE__
+# include "compat/apple.h"
+#endif
+
+/**
+ * Initialize utility functions
+ */
+void utils_init();
+
+/**
+ * Deinitialize utility functions
+ */
+void utils_deinit();
+
/**
* strongSwan program return codes
*/
@@ -75,285 +102,11 @@
BUILD_ASSERT(!__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])))
/**
- * General purpose boolean type.
- */
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-# ifndef HAVE__BOOL
-# define _Bool signed char
-# endif /* HAVE__BOOL */
-# define bool _Bool
-# define false 0
-# define true 1
-# define __bool_true_false_are_defined 1
-#endif /* HAVE_STDBOOL_H */
-#ifndef FALSE
-# define FALSE false
-#endif /* FALSE */
-#ifndef TRUE
-# define TRUE true
-#endif /* TRUE */
-
-#include "enum.h"
-#include "utils/strerror.h"
-#ifdef __APPLE__
-# include "compat/apple.h"
-#endif
-
-/**
- * Directory separator character in paths on this platform
- */
-#ifdef WIN32
-# define DIRECTORY_SEPARATOR "\\"
-#else
-# define DIRECTORY_SEPARATOR "/"
-#endif
-
-/**
- * Initialize utility functions
- */
-void utils_init();
-
-/**
- * Deinitialize utility functions
- */
-void utils_deinit();
-
-/**
- * Helper function that compares two strings for equality
- */
-static inline bool streq(const char *x, const char *y)
-{
- return strcmp(x, y) == 0;
-}
-
-/**
- * Helper function that compares two strings for equality, length limited
- */
-static inline bool strneq(const char *x, const char *y, size_t len)
-{
- return strncmp(x, y, len) == 0;
-}
-
-/**
- * Helper function that checks if a string starts with a given prefix
- */
-static inline bool strpfx(const char *x, const char *prefix)
-{
- return strneq(x, prefix, strlen(prefix));
-}
-
-/**
- * Helper function that compares two strings for equality ignoring case
- */
-static inline bool strcaseeq(const char *x, const char *y)
-{
- return strcasecmp(x, y) == 0;
-}
-
-/**
- * Helper function that compares two strings for equality ignoring case, length limited
- */
-static inline bool strncaseeq(const char *x, const char *y, size_t len)
-{
- return strncasecmp(x, y, len) == 0;
-}
-
-/**
- * Helper function that checks if a string starts with a given prefix
- */
-static inline bool strcasepfx(const char *x, const char *prefix)
-{
- return strncaseeq(x, prefix, strlen(prefix));
-}
-
-/**
- * NULL-safe strdup variant
- */
-static inline char *strdupnull(const char *s)
-{
- return s ? strdup(s) : NULL;
-}
-
-/**
- * Helper function that compares two binary blobs for equality
- */
-static inline bool memeq(const void *x, const void *y, size_t len)
-{
- return memcmp(x, y, len) == 0;
-}
-
-/**
- * Same as memeq(), but with a constant runtime, safe for cryptographic use.
- */
-bool memeq_const(const void *x, const void *y, size_t len);
-
-/**
- * Calling memcpy() with NULL pointers, even with n == 0, results in undefined
- * behavior according to the C standard. This version is guaranteed to not
- * access the pointers if n is 0.
- */
-static inline void *memcpy_noop(void *dst, const void *src, size_t n)
-{
- return n ? memcpy(dst, src, n) : dst;
-}
-#ifdef memcpy
-# undef memcpy
-#endif
-#define memcpy(d,s,n) memcpy_noop(d,s,n)
-
-/**
- * Calling memmove() with NULL pointers, even with n == 0, results in undefined
- * behavior according to the C standard. This version is guaranteed to not
- * access the pointers if n is 0.
- */
-static inline void *memmove_noop(void *dst, const void *src, size_t n)
-{
- return n ? memmove(dst, src, n) : dst;
-}
-#ifdef memmove
-# undef memmove
-#endif
-#define memmove(d,s,n) memmove_noop(d,s,n)
-
-/**
- * Calling memset() with a NULL pointer, even with n == 0, results in undefined
- * behavior according to the C standard. This version is guaranteed to not
- * access the pointer if n is 0.
- */
-static inline void *memset_noop(void *s, int c, size_t n)
-{
- return n ? memset(s, c, n) : s;
-}
-#ifdef memset
-# undef memset
-#endif
-#define memset(s,c,n) memset_noop(s,c,n)
-
-/**
- * Macro gives back larger of two values.
- */
-#define max(x,y) ({ \
- typeof(x) _x = (x); \
- typeof(y) _y = (y); \
- _x > _y ? _x : _y; })
-
-/**
- * Macro gives back smaller of two values.
- */
-#define min(x,y) ({ \
- typeof(x) _x = (x); \
- typeof(y) _y = (y); \
- _x < _y ? _x : _y; })
-
-/**
- * Call destructor of an object, if object != NULL
- */
-#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
-
-/**
- * Call offset destructor of an object, if object != NULL
- */
-#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
-
-/**
- * Call function destructor of an object, if object != NULL
- */
-#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
-
-/**
* Debug macro to follow control flow
*/
#define POS printf("%s, line %d\n", __FILE__, __LINE__)
/**
- * Object allocation/initialization macro, using designated initializer.
- */
-#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
- *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
-
-/**
- * Aligning version of INIT().
- *
- * The returned pointer must be freed using free_align(), not free().
- *
- * @param this object to allocate/initialize
- * @param align alignment for allocation, in bytes
- * @param ... initializer
- */
-#define INIT_ALIGN(this, align, ...) { \
- (this) = malloc_align(sizeof(*(this)), align); \
- *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
-
-/**
- * Object allocation/initialization macro, with extra allocated bytes at tail.
- *
- * The extra space gets zero-initialized.
- *
- * @param this pointer to object to allocate memory for
- * @param extra number of bytes to allocate at end of this
- * @param ... initializer
- */
-#define INIT_EXTRA(this, extra, ...) { \
- typeof(extra) _extra = (extra); \
- (this) = malloc(sizeof(*(this)) + _extra); \
- *(this) = (typeof(*(this))){ __VA_ARGS__ }; \
- memset((this) + 1, 0, _extra); }
-
-/**
- * Aligning version of INIT_EXTRA().
- *
- * The returned pointer must be freed using free_align(), not free().
- *
- * @param this object to allocate/initialize
- * @param extra number of bytes to allocate at end of this
- * @param align alignment for allocation, in bytes
- * @param ... initializer
- */
-#define INIT_EXTRA_ALIGN(this, extra, align, ...) { \
- typeof(extra) _extra = (extra); \
- (this) = malloc_align(sizeof(*(this)) + _extra, align); \
- *(this) = (typeof(*(this))){ __VA_ARGS__ }; \
- memset((this) + 1, 0, _extra); }
-
-/**
- * Method declaration/definition macro, providing private and public interface.
- *
- * Defines a method name with this as first parameter and a return value ret,
- * and an alias for this method with a _ prefix, having the this argument
- * safely casted to the public interface iface.
- * _name is provided a function pointer, but will get optimized out by GCC.
- */
-#define METHOD(iface, name, ret, this, ...) \
- static ret name(union {iface *_public; this;} \
- __attribute__((transparent_union)), ##__VA_ARGS__); \
- static typeof(name) *_##name = (typeof(name)*)name; \
- static ret name(this, ##__VA_ARGS__)
-
-/**
- * Same as METHOD(), but is defined for two public interfaces.
- */
-#define METHOD2(iface1, iface2, name, ret, this, ...) \
- static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
- __attribute__((transparent_union)), ##__VA_ARGS__); \
- static typeof(name) *_##name = (typeof(name)*)name; \
- static ret name(this, ##__VA_ARGS__)
-
-/**
- * Callback declaration/definition macro, allowing casted first parameter.
- *
- * This is very similar to METHOD, but instead of casting the first parameter
- * to a public interface, it uses a void*. This allows type safe definition
- * of a callback function, while using the real type for the first parameter.
- */
-#define CALLBACK(name, ret, param1, ...) \
- static ret _cb_##name(union {void *_generic; param1;} \
- __attribute__((transparent_union)), ##__VA_ARGS__); \
- static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
- static ret _cb_##name(param1, ##__VA_ARGS__)
-
-/**
* This macro allows counting the number of arguments passed to a macro.
* Combined with the VA_ARGS_DISPATCH() macro this can be used to implement
* macro overloading based on the number of arguments.
@@ -380,28 +133,6 @@ static inline void *memset_noop(void *s, int c, size_t n)
#define __VA_ARGS_DISPATCH(func, num) func ## num
/**
- * Architecture independent bitfield definition helpers (at least with GCC).
- *
- * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
- * BITFIELD2(u_int8_t,
- * low: 4,
- * high: 4,
- * ) flags;
- * The member defined first placed at bit 0.
- */
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
-#define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
-#define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
-#define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
-#elif BYTE_ORDER == BIG_ENDIAN
-#define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
-#define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
-#define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
-#define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
-#endif
-
-/**
* Macro to allocate a sized type.
*/
#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
@@ -418,348 +149,10 @@ static inline void *memset_noop(void *s, int c, size_t n)
#define ignore_result(call) { if(call){}; }
/**
- * Assign a function as a class method
- */
-#define ASSIGN(method, function) (method = (typeof(method))function)
-
-/**
- * time_t not defined
- */
-#define UNDEFINED_TIME 0
-
-/**
- * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
- */
-#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
-
-/**
- * define some missing fixed width int types on OpenSolaris.
- * TODO: since the uintXX_t types are defined by the C99 standard we should
- * probably use those anyway
- */
-#if defined __sun || defined WIN32
- #include <stdint.h>
- typedef uint8_t u_int8_t;
- typedef uint16_t u_int16_t;
- typedef uint32_t u_int32_t;
- typedef uint64_t u_int64_t;
-#endif
-
-#ifdef HAVE_INT128
-/**
- * 128 bit wide signed integer, if supported
- */
-typedef __int128 int128_t;
-/**
- * 128 bit wide unsigned integer, if supported
- */
-typedef unsigned __int128 u_int128_t;
-
-# define MAX_INT_TYPE int128_t
-# define MAX_UINT_TYPE u_int128_t
-#else
-# define MAX_INT_TYPE int64_t
-# define MAX_UINT_TYPE u_int64_t
-#endif
-
-typedef enum status_t status_t;
-
-/**
- * Return values of function calls.
- */
-enum status_t {
- /**
- * Call succeeded.
- */
- SUCCESS,
-
- /**
- * Call failed.
- */
- FAILED,
-
- /**
- * Out of resources.
- */
- OUT_OF_RES,
-
- /**
- * The suggested operation is already done
- */
- ALREADY_DONE,
-
- /**
- * Not supported.
- */
- NOT_SUPPORTED,
-
- /**
- * One of the arguments is invalid.
- */
- INVALID_ARG,
-
- /**
- * Something could not be found.
- */
- NOT_FOUND,
-
- /**
- * Error while parsing.
- */
- PARSE_ERROR,
-
- /**
- * Error while verifying.
- */
- VERIFY_ERROR,
-
- /**
- * Object in invalid state.
- */
- INVALID_STATE,
-
- /**
- * Destroy object which called method belongs to.
- */
- DESTROY_ME,
-
- /**
- * Another call to the method is required.
- */
- NEED_MORE,
-};
-
-/**
- * enum_names for type status_t.
- */
-extern enum_name_t *status_names;
-
-typedef enum tty_escape_t tty_escape_t;
-
-/**
- * Excape codes for tty colors
- */
-enum tty_escape_t {
- /** text properties */
- TTY_RESET,
- TTY_BOLD,
- TTY_UNDERLINE,
- TTY_BLINKING,
-
- /** foreground colors */
- TTY_FG_BLACK,
- TTY_FG_RED,
- TTY_FG_GREEN,
- TTY_FG_YELLOW,
- TTY_FG_BLUE,
- TTY_FG_MAGENTA,
- TTY_FG_CYAN,
- TTY_FG_WHITE,
- TTY_FG_DEF,
-
- /** background colors */
- TTY_BG_BLACK,
- TTY_BG_RED,
- TTY_BG_GREEN,
- TTY_BG_YELLOW,
- TTY_BG_BLUE,
- TTY_BG_MAGENTA,
- TTY_BG_CYAN,
- TTY_BG_WHITE,
- TTY_BG_DEF,
-};
-
-/**
- * Get the escape string for a given TTY color, empty string on non-tty fd
- */
-char* tty_escape_get(int fd, tty_escape_t escape);
-
-/**
- * deprecated pluto style return value:
- * error message, NULL for success
- */
-typedef const char *err_t;
-
-/**
- * Handle struct timeval like an own type.
- */
-typedef struct timeval timeval_t;
-
-/**
- * Handle struct timespec like an own type.
- */
-typedef struct timespec timespec_t;
-
-/**
- * Handle struct chunk_t like an own type.
- */
-typedef struct sockaddr sockaddr_t;
-
-/**
- * malloc(), but returns aligned memory.
- *
- * The returned pointer must be freed using free_align(), not free().
- *
- * @param size size of allocated data
- * @param align alignment, up to 255 bytes, usually a power of 2
- * @return allocated hunk, aligned to align bytes
- */
-void* malloc_align(size_t size, u_int8_t align);
-
-/**
- * Free a hunk allocated by malloc_align().
- *
- * @param ptr hunk to free
- */
-void free_align(void *ptr);
-
-/**
- * Same as memcpy, but XORs src into dst instead of copy
- */
-void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
-
-/**
- * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
- */
-void memwipe_noinline(void *ptr, size_t n);
-
-/**
- * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
- */
-static inline void memwipe_inline(void *ptr, size_t n)
-{
- volatile char *c = (volatile char*)ptr;
- size_t m, i;
-
- /* byte wise until long aligned */
- for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
- {
- c[i] = 0;
- }
- /* word wise */
- if (n >= sizeof(long))
- {
- for (m = n - sizeof(long); i <= m; i += sizeof(long))
- {
- *(volatile long*)&c[i] = 0;
- }
- }
- /* byte wise of the rest */
- for (; i < n; i++)
- {
- c[i] = 0;
- }
-}
-
-/**
- * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
- */
-static inline void memwipe(void *ptr, size_t n)
-{
- if (!ptr)
- {
- return;
- }
- if (__builtin_constant_p(n))
- {
- memwipe_inline(ptr, n);
- }
- else
- {
- memwipe_noinline(ptr, n);
- }
-}
-
-/**
- * A variant of strstr with the characteristics of memchr, where haystack is not
- * a null-terminated string but simply a memory area of length n.
- */
-void *memstr(const void *haystack, const char *needle, size_t n);
-
-/**
- * Replacement for memrchr(3) if it is not provided by the C library.
- *
- * @param s start of the memory area to search
- * @param c character to search
- * @param n length of memory area to search
- * @return pointer to the found character or NULL
- */
-void *utils_memrchr(const void *s, int c, size_t n);
-
-#ifndef HAVE_MEMRCHR
-#define memrchr(s,c,n) utils_memrchr(s,c,n)
-#endif
-
-/**
- * Translates the characters in the given string, searching for characters
- * in 'from' and mapping them to characters in 'to'.
- * The two characters sets 'from' and 'to' must contain the same number of
- * characters.
- */
-char *translate(char *str, const char *from, const char *to);
-
-/**
- * Replaces all occurrences of search in the given string with replace.
- *
- * Allocates memory only if anything is replaced in the string. The original
- * string is also returned if any of the arguments are invalid (e.g. if search
- * is empty or any of them are NULL).
- *
- * @param str original string
- * @param search string to search for and replace
- * @param replace string to replace found occurrences with
- * @return allocated string, if anything got replaced, str otherwise
- */
-char *strreplace(const char *str, const char *search, const char *replace);
-
-/**
* Portable function to wait for SIGINT/SIGTERM (or equivalent).
*/
void wait_sigint();
-/**
- * Like dirname(3) returns the directory part of the given null-terminated
- * pathname, up to but not including the final '/' (or '.' if no '/' is found).
- * Trailing '/' are not counted as part of the pathname.
- *
- * The difference is that it does this in a thread-safe manner (i.e. it does not
- * use static buffers) and does not modify the original path.
- *
- * @param path original pathname
- * @return allocated directory component
- */
-char *path_dirname(const char *path);
-
-/**
- * Like basename(3) returns the filename part of the given null-terminated path,
- * i.e. the part following the final '/' (or '.' if path is empty or NULL).
- * Trailing '/' are not counted as part of the pathname.
- *
- * The difference is that it does this in a thread-safe manner (i.e. it does not
- * use static buffers) and does not modify the original path.
- *
- * @param path original pathname
- * @return allocated filename component
- */
-char *path_basename(const char *path);
-
-/**
- * Check if a given path is absolute.
- *
- * @param path path to check
- * @return TRUE if absolute, FALSE if relative
- */
-bool path_absolute(const char *path);
-
-/**
- * Creates a directory and all required parent directories.
- *
- * @param path path to the new directory
- * @param mode permissions of the new directory/directories
- * @return TRUE on success
- */
-bool mkdir_p(const char *path, mode_t mode);
-
#ifndef HAVE_CLOSEFROM
/**
* Close open file descriptors greater than or equal to lowfd.
@@ -770,34 +163,6 @@ void closefrom(int lowfd);
#endif
/**
- * Get a timestamp from a monotonic time source.
- *
- * While the time()/gettimeofday() functions are affected by leap seconds
- * and system time changes, this function returns ever increasing monotonic
- * time stamps.
- *
- * @param tv timeval struct receiving monotonic timestamps, or NULL
- * @return monotonic timestamp in seconds
- */
-time_t time_monotonic(timeval_t *tv);
-
-/**
- * Add the given number of milliseconds to the given timeval struct
- *
- * @param tv timeval struct to modify
- * @param ms number of milliseconds
- */
-static inline void timeval_add_ms(timeval_t *tv, u_int ms)
-{
- tv->tv_usec += ms * 1000;
- while (tv->tv_usec >= 1000000 /* 1s */)
- {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
- }
-}
-
-/**
* returns null
*/
void *return_null();
@@ -817,294 +182,4 @@ bool return_true();
*/
bool return_false();
-/**
- * returns FAILED
- */
-status_t return_failed();
-
-/**
- * returns SUCCESS
- */
-status_t return_success();
-
-/**
- * Write a 16-bit host order value in network order to an unaligned address.
- *
- * @param host host order 16-bit value
- * @param network unaligned address to write network order value to
- */
-static inline void htoun16(void *network, u_int16_t host)
-{
- char *unaligned = (char*)network;
-
- host = htons(host);
- memcpy(unaligned, &host, sizeof(host));
-}
-
-/**
- * Write a 32-bit host order value in network order to an unaligned address.
- *
- * @param host host order 32-bit value
- * @param network unaligned address to write network order value to
- */
-static inline void htoun32(void *network, u_int32_t host)
-{
- char *unaligned = (char*)network;
-
- host = htonl(host);
- memcpy((char*)unaligned, &host, sizeof(host));
-}
-
-/**
- * Write a 64-bit host order value in network order to an unaligned address.
- *
- * @param host host order 64-bit value
- * @param network unaligned address to write network order value to
- */
-static inline void htoun64(void *network, u_int64_t host)
-{
- char *unaligned = (char*)network;
-
-#ifdef be64toh
- host = htobe64(host);
- memcpy((char*)unaligned, &host, sizeof(host));
-#else
- u_int32_t high_part, low_part;
-
- high_part = host >> 32;
- high_part = htonl(high_part);
- low_part = host & 0xFFFFFFFFLL;
- low_part = htonl(low_part);
-
- memcpy(unaligned, &high_part, sizeof(high_part));
- unaligned += sizeof(high_part);
- memcpy(unaligned, &low_part, sizeof(low_part));
-#endif
-}
-
-/**
- * Read a 16-bit value in network order from an unaligned address to host order.
- *
- * @param network unaligned address to read network order value from
- * @return host order value
- */
-static inline u_int16_t untoh16(void *network)
-{
- char *unaligned = (char*)network;
- u_int16_t tmp;
-
- memcpy(&tmp, unaligned, sizeof(tmp));
- return ntohs(tmp);
-}
-
-/**
- * Read a 32-bit value in network order from an unaligned address to host order.
- *
- * @param network unaligned address to read network order value from
- * @return host order value
- */
-static inline u_int32_t untoh32(void *network)
-{
- char *unaligned = (char*)network;
- u_int32_t tmp;
-
- memcpy(&tmp, unaligned, sizeof(tmp));
- return ntohl(tmp);
-}
-
-/**
- * Read a 64-bit value in network order from an unaligned address to host order.
- *
- * @param network unaligned address to read network order value from
- * @return host order value
- */
-static inline u_int64_t untoh64(void *network)
-{
- char *unaligned = (char*)network;
-
-#ifdef be64toh
- u_int64_t tmp;
-
- memcpy(&tmp, unaligned, sizeof(tmp));
- return be64toh(tmp);
-#else
- u_int32_t high_part, low_part;
-
- memcpy(&high_part, unaligned, sizeof(high_part));
- unaligned += sizeof(high_part);
- memcpy(&low_part, unaligned, sizeof(low_part));
-
- high_part = ntohl(high_part);
- low_part = ntohl(low_part);
-
- return (((u_int64_t)high_part) << 32) + low_part;
-#endif
-}
-
-/**
- * Get the padding required to make size a multiple of alignment
- */
-static inline size_t pad_len(size_t size, size_t alignment)
-{
- size_t remainder;
-
- remainder = size % alignment;
- return remainder ? alignment - remainder : 0;
-}
-
-/**
- * Round up size to be multiple of alignment
- */
-static inline size_t round_up(size_t size, size_t alignment)
-{
- return size + pad_len(size, alignment);
-}
-
-/**
- * Round down size to be a multiple of alignment
- */
-static inline size_t round_down(size_t size, size_t alignment)
-{
- return size - (size % alignment);
-}
-
-/**
- * Special type to count references
- */
-typedef u_int refcount_t;
-
-/* use __atomic* built-ins with GCC 4.7 and newer */
-#ifdef __GNUC__
-# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-# define HAVE_GCC_ATOMIC_OPERATIONS
-# endif
-#endif
-
-#ifdef HAVE_GCC_ATOMIC_OPERATIONS
-
-#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
-/* The relaxed memory model works fine for increments as these (usually) don't
- * change the state of refcounted objects. But here we have to ensure that we
- * free the right stuff if ref counted objects are mutable. So we have to sync
- * with other threads that call ref_put(). It would be sufficient to use
- * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
- * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
- * of ref_put() we have to make sure. */
-#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
-#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
-
-#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
- __atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
- __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
-#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
-#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
-
-#elif defined(HAVE_GCC_SYNC_OPERATIONS)
-
-#define ref_get(ref) __sync_add_and_fetch(ref, 1)
-#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
-#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
-
-#define cas_bool(ptr, oldval, newval) \
- (__sync_bool_compare_and_swap(ptr, oldval, newval))
-#define cas_ptr(ptr, oldval, newval) \
- (__sync_bool_compare_and_swap(ptr, oldval, newval))
-
-#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
-
-/**
- * Get a new reference.
- *
- * Increments the reference counter atomically.
- *
- * @param ref pointer to ref counter
- * @return new value of ref
- */
-refcount_t ref_get(refcount_t *ref);
-
-/**
- * Put back a unused reference.
- *
- * Decrements the reference counter atomically and
- * says if more references available.
- *
- * @param ref pointer to ref counter
- * @return TRUE if no more references counted
- */
-bool ref_put(refcount_t *ref);
-
-/**
- * Get the current value of the reference counter.
- *
- * @param ref pointer to ref counter
- * @return current value of ref
- */
-refcount_t ref_cur(refcount_t *ref);
-
-/**
- * Atomically replace value of ptr with newval if it currently equals oldval.
- *
- * @param ptr pointer to variable
- * @param oldval old value of the variable
- * @param newval new value set if possible
- * @return TRUE if value equaled oldval and newval was written
- */
-bool cas_bool(bool *ptr, bool oldval, bool newval);
-
-/**
- * Atomically replace value of ptr with newval if it currently equals oldval.
- *
- * @param ptr pointer to variable
- * @param oldval old value of the variable
- * @param newval new value set if possible
- * @return TRUE if value equaled oldval and newval was written
- */
-bool cas_ptr(void **ptr, void *oldval, void *newval);
-
-#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
-
-#ifndef HAVE_FMEMOPEN
-# ifdef HAVE_FUNOPEN
-# define HAVE_FMEMOPEN
-# define HAVE_FMEMOPEN_FALLBACK
-# include <stdio.h>
-/**
- * fmemopen(3) fallback using BSD funopen.
- *
- * We could also provide one using fopencookie(), but should we have it we
- * most likely have fmemopen().
- *
- * fseek() is currently not supported.
- */
-FILE *fmemopen(void *buf, size_t size, const char *mode);
-# endif /* FUNOPEN */
-#endif /* FMEMOPEN */
-
-/**
- * printf hook for time_t.
- *
- * Arguments are:
- * time_t* time, bool utc
- */
-int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args);
-
-/**
- * printf hook for time_t deltas.
- *
- * Arguments are:
- * time_t* begin, time_t* end
- */
-int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args);
-
-/**
- * printf hook for memory areas.
- *
- * Arguments are:
- * u_char *ptr, u_int len
- */
-int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
- const void *const *args);
-
#endif /** UTILS_H_ @}*/
diff --git a/src/libstrongswan/utils/utils/align.c b/src/libstrongswan/utils/utils/align.c
new file mode 100644
index 000000000..29f110ff1
--- /dev/null
+++ b/src/libstrongswan/utils/utils/align.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+#include <utils/debug.h>
+
+/**
+ * Described in header.
+ */
+void* malloc_align(size_t size, u_int8_t align)
+{
+ u_int8_t pad;
+ void *ptr;
+
+ if (align == 0)
+ {
+ align = 1;
+ }
+ ptr = malloc(align + sizeof(pad) + size);
+ if (!ptr)
+ {
+ return NULL;
+ }
+ /* store padding length just before data, down to the allocation boundary
+ * to do some verification during free_align() */
+ pad = align - ((uintptr_t)ptr % align);
+ memset(ptr, pad, pad);
+ return ptr + pad;
+}
+
+/**
+ * Described in header.
+ */
+void free_align(void *ptr)
+{
+ u_int8_t pad, *pos;
+
+ pos = ptr - 1;
+ /* verify padding to check any corruption */
+ for (pad = *pos; (void*)pos >= ptr - pad; pos--)
+ {
+ if (*pos != pad)
+ {
+ DBG1(DBG_LIB, "!!!! invalid free_align() !!!!");
+ return;
+ }
+ }
+ free(ptr - pad);
+}
diff --git a/src/libstrongswan/utils/utils/align.h b/src/libstrongswan/utils/utils/align.h
new file mode 100644
index 000000000..39cde10c8
--- /dev/null
+++ b/src/libstrongswan/utils/utils/align.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup align_i align
+ * @{ @ingroup utils_i
+ */
+
+#ifndef ALIGN_H_
+#define ALIGN_H_
+
+/**
+ * Macro gives back larger of two values.
+ */
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ _x > _y ? _x : _y; })
+
+/**
+ * Macro gives back smaller of two values.
+ */
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ _x < _y ? _x : _y; })
+
+/**
+ * Get the padding required to make size a multiple of alignment
+ */
+static inline size_t pad_len(size_t size, size_t alignment)
+{
+ size_t remainder;
+
+ remainder = size % alignment;
+ return remainder ? alignment - remainder : 0;
+}
+
+/**
+ * Round up size to be multiple of alignment
+ */
+static inline size_t round_up(size_t size, size_t alignment)
+{
+ return size + pad_len(size, alignment);
+}
+
+/**
+ * Round down size to be a multiple of alignment
+ */
+static inline size_t round_down(size_t size, size_t alignment)
+{
+ return size - (size % alignment);
+}
+
+/**
+ * malloc(), but returns aligned memory.
+ *
+ * The returned pointer must be freed using free_align(), not free().
+ *
+ * @param size size of allocated data
+ * @param align alignment, up to 255 bytes, usually a power of 2
+ * @return allocated hunk, aligned to align bytes
+ */
+void* malloc_align(size_t size, u_int8_t align);
+
+/**
+ * Free a hunk allocated by malloc_align().
+ *
+ * @param ptr hunk to free
+ */
+void free_align(void *ptr);
+
+#endif /** ALIGN_H_ @} */
diff --git a/src/libstrongswan/utils/utils/atomics.c b/src/libstrongswan/utils/utils/atomics.c
new file mode 100644
index 000000000..17e823e70
--- /dev/null
+++ b/src/libstrongswan/utils/utils/atomics.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+
+#include <threading/spinlock.h>
+
+/**
+ * Spinlock for ref_get/put
+ */
+static spinlock_t *ref_lock;
+
+/**
+ * Increase refcount
+ */
+refcount_t ref_get(refcount_t *ref)
+{
+ refcount_t current;
+
+ ref_lock->lock(ref_lock);
+ current = ++(*ref);
+ ref_lock->unlock(ref_lock);
+
+ return current;
+}
+
+/**
+ * Decrease refcount
+ */
+bool ref_put(refcount_t *ref)
+{
+ bool more_refs;
+
+ ref_lock->lock(ref_lock);
+ more_refs = --(*ref) > 0;
+ ref_lock->unlock(ref_lock);
+ return !more_refs;
+}
+
+/**
+ * Current refcount
+ */
+refcount_t ref_cur(refcount_t *ref)
+{
+ refcount_t current;
+
+ ref_lock->lock(ref_lock);
+ current = *ref;
+ ref_lock->unlock(ref_lock);
+
+ return current;
+}
+
+/**
+ * Spinlock for all compare and swap operations.
+ */
+static spinlock_t *cas_lock;
+
+/**
+ * Compare and swap if equal to old value
+ */
+#define _cas_impl(name, type) \
+bool cas_##name(type *ptr, type oldval, type newval) \
+{ \
+ bool swapped; \
+ cas_lock->lock(cas_lock); \
+ if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
+ cas_lock->unlock(cas_lock); \
+ return swapped; \
+}
+
+_cas_impl(bool, bool)
+_cas_impl(ptr, void*)
+
+#endif /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
+
+/**
+ * See header
+ */
+void atomics_init()
+{
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+ ref_lock = spinlock_create();
+ cas_lock = spinlock_create();
+#endif
+}
+
+/**
+ * See header
+ */
+void atomics_deinit()
+{
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+ ref_lock->destroy(ref_lock);
+ cas_lock->destroy(cas_lock);
+#endif
+}
diff --git a/src/libstrongswan/utils/utils/atomics.h b/src/libstrongswan/utils/utils/atomics.h
new file mode 100644
index 000000000..e5db0a1cb
--- /dev/null
+++ b/src/libstrongswan/utils/utils/atomics.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup atomics_i atomics
+ * @{ @ingroup utils_i
+ */
+
+#ifndef ATOMICS_H_
+#define ATOMICS_H_
+
+/**
+ * Special type to count references
+ */
+typedef u_int refcount_t;
+
+/* use __atomic* built-ins with GCC 4.7 and newer */
+#ifdef __GNUC__
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+# define HAVE_GCC_ATOMIC_OPERATIONS
+# endif
+#endif
+
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+
+#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
+/* The relaxed memory model works fine for increments as these (usually) don't
+ * change the state of refcounted objects. But here we have to ensure that we
+ * free the right stuff if ref counted objects are mutable. So we have to sync
+ * with other threads that call ref_put(). It would be sufficient to use
+ * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
+ * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
+ * of ref_put() we have to make sure. */
+#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
+#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
+
+#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
+ __atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
+ __ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
+#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
+#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
+
+#elif defined(HAVE_GCC_SYNC_OPERATIONS)
+
+#define ref_get(ref) __sync_add_and_fetch(ref, 1)
+#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
+#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
+
+#define cas_bool(ptr, oldval, newval) \
+ (__sync_bool_compare_and_swap(ptr, oldval, newval))
+#define cas_ptr(ptr, oldval, newval) \
+ (__sync_bool_compare_and_swap(ptr, oldval, newval))
+
+#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
+
+/**
+ * Get a new reference.
+ *
+ * Increments the reference counter atomically.
+ *
+ * @param ref pointer to ref counter
+ * @return new value of ref
+ */
+refcount_t ref_get(refcount_t *ref);
+
+/**
+ * Put back a unused reference.
+ *
+ * Decrements the reference counter atomically and
+ * says if more references available.
+ *
+ * @param ref pointer to ref counter
+ * @return TRUE if no more references counted
+ */
+bool ref_put(refcount_t *ref);
+
+/**
+ * Get the current value of the reference counter.
+ *
+ * @param ref pointer to ref counter
+ * @return current value of ref
+ */
+refcount_t ref_cur(refcount_t *ref);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr pointer to variable
+ * @param oldval old value of the variable
+ * @param newval new value set if possible
+ * @return TRUE if value equaled oldval and newval was written
+ */
+bool cas_bool(bool *ptr, bool oldval, bool newval);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr pointer to variable
+ * @param oldval old value of the variable
+ * @param newval new value set if possible
+ * @return TRUE if value equaled oldval and newval was written
+ */
+bool cas_ptr(void **ptr, void *oldval, void *newval);
+
+#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * Initialize atomics utility functions
+ */
+void atomics_init();
+
+/**
+ * Clean up atomics utility functions
+ */
+void atomics_deinit();
+
+#endif /** ATOMICS_H_ @} */
diff --git a/src/libstrongswan/utils/utils/byteorder.h b/src/libstrongswan/utils/utils/byteorder.h
new file mode 100644
index 000000000..48cf1d526
--- /dev/null
+++ b/src/libstrongswan/utils/utils/byteorder.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup byteorder_i byteorder
+ * @{ @ingroup utils_i
+ */
+
+#ifndef BYTEORDER_H_
+#define BYTEORDER_H_
+
+/**
+ * Architecture independent bitfield definition helpers (at least with GCC).
+ *
+ * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
+ * BITFIELD2(u_int8_t,
+ * low: 4,
+ * high: 4,
+ * ) flags;
+ * The member defined first placed at bit 0.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
+#elif BYTE_ORDER == BIG_ENDIAN
+#define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
+#endif
+
+/**
+ * Write a 16-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 16-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun16(void *network, u_int16_t host)
+{
+ char *unaligned = (char*)network;
+
+ host = htons(host);
+ memcpy(unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 32-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 32-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun32(void *network, u_int32_t host)
+{
+ char *unaligned = (char*)network;
+
+ host = htonl(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 64-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 64-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun64(void *network, u_int64_t host)
+{
+ char *unaligned = (char*)network;
+
+#ifdef be64toh
+ host = htobe64(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+#else
+ u_int32_t high_part, low_part;
+
+ high_part = host >> 32;
+ high_part = htonl(high_part);
+ low_part = host & 0xFFFFFFFFLL;
+ low_part = htonl(low_part);
+
+ memcpy(unaligned, &high_part, sizeof(high_part));
+ unaligned += sizeof(high_part);
+ memcpy(unaligned, &low_part, sizeof(low_part));
+#endif
+}
+
+/**
+ * Read a 16-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int16_t untoh16(void *network)
+{
+ char *unaligned = (char*)network;
+ u_int16_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return ntohs(tmp);
+}
+
+/**
+ * Read a 32-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int32_t untoh32(void *network)
+{
+ char *unaligned = (char*)network;
+ u_int32_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return ntohl(tmp);
+}
+
+/**
+ * Read a 64-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int64_t untoh64(void *network)
+{
+ char *unaligned = (char*)network;
+
+#ifdef be64toh
+ u_int64_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return be64toh(tmp);
+#else
+ u_int32_t high_part, low_part;
+
+ memcpy(&high_part, unaligned, sizeof(high_part));
+ unaligned += sizeof(high_part);
+ memcpy(&low_part, unaligned, sizeof(low_part));
+
+ high_part = ntohl(high_part);
+ low_part = ntohl(low_part);
+
+ return (((u_int64_t)high_part) << 32) + low_part;
+#endif
+}
+
+#endif /** BYTEORDER_H_ @} */
diff --git a/src/libstrongswan/utils/utils/memory.c b/src/libstrongswan/utils/utils/memory.c
new file mode 100644
index 000000000..a15371518
--- /dev/null
+++ b/src/libstrongswan/utils/utils/memory.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+#include <utils/chunk.h>
+
+/**
+ * Described in header.
+ */
+void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
+{
+ int m, i;
+
+ /* byte wise XOR until dst aligned */
+ for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
+ {
+ dst[i] ^= src[i];
+ }
+ /* try to use words if src shares an aligment with dst */
+ switch (((uintptr_t)&src[i] % sizeof(long)))
+ {
+ case 0:
+ for (m = n - sizeof(long); i <= m; i += sizeof(long))
+ {
+ *(long*)&dst[i] ^= *(long*)&src[i];
+ }
+ break;
+ case sizeof(int):
+ for (m = n - sizeof(int); i <= m; i += sizeof(int))
+ {
+ *(int*)&dst[i] ^= *(int*)&src[i];
+ }
+ break;
+ case sizeof(short):
+ for (m = n - sizeof(short); i <= m; i += sizeof(short))
+ {
+ *(short*)&dst[i] ^= *(short*)&src[i];
+ }
+ break;
+ default:
+ break;
+ }
+ /* byte wise XOR of the rest */
+ for (; i < n; i++)
+ {
+ dst[i] ^= src[i];
+ }
+}
+
+/**
+ * Described in header.
+ */
+void memwipe_noinline(void *ptr, size_t n)
+{
+ memwipe_inline(ptr, n);
+}
+
+/**
+ * Described in header.
+ */
+bool memeq_const(const void *x, const void *y, size_t len)
+{
+ const u_char *a, *b;
+ u_int bad = 0;
+ size_t i;
+
+ a = (const u_char*)x;
+ b = (const u_char*)y;
+
+ for (i = 0; i < len; i++)
+ {
+ bad |= a[i] != b[i];
+ }
+ return !bad;
+}
+
+/**
+ * Described in header.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n)
+{
+ const u_char *pos = haystack;
+ size_t l;
+
+ if (!haystack || !needle || (l = strlen(needle)) == 0)
+ {
+ return NULL;
+ }
+ for (; n >= l; ++pos, --n)
+ {
+ if (memeq(pos, needle, l))
+ {
+ return (void*)pos;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Described in header.
+ */
+void *utils_memrchr(const void *s, int c, size_t n)
+{
+ const u_char *pos;
+
+ if (!s || !n)
+ {
+ return NULL;
+ }
+
+ for (pos = s + n - 1; pos >= (u_char*)s; pos--)
+ {
+ if (*pos == (u_char)c)
+ {
+ return (void*)pos;
+ }
+ }
+ return NULL;
+}
+
+#ifdef HAVE_FMEMOPEN_FALLBACK
+
+static int fmemread(chunk_t *cookie, char *buf, int size)
+{
+ int len;
+
+ len = min(size, cookie->len);
+ memcpy(buf, cookie->ptr, len);
+ *cookie = chunk_skip(*cookie, len);
+
+ return len;
+}
+
+static int fmemwrite(chunk_t *cookie, const char *buf, int size)
+{
+ int len;
+
+ len = min(size, cookie->len);
+ memcpy(cookie->ptr, buf, len);
+ *cookie = chunk_skip(*cookie, len);
+
+ return len;
+}
+
+static int fmemclose(void *cookie)
+{
+ free(cookie);
+ return 0;
+}
+
+FILE *fmemopen(void *buf, size_t size, const char *mode)
+{
+ chunk_t *cookie;
+
+ INIT(cookie,
+ .ptr = buf,
+ .len = size,
+ );
+
+ return funopen(cookie, (void*)fmemread, (void*)fmemwrite, NULL, fmemclose);
+}
+
+#endif /* FMEMOPEN fallback*/
+
+/**
+ * Number of bytes per line to dump raw data
+ */
+#define BYTES_PER_LINE 16
+
+static char hexdig_upper[] = "0123456789ABCDEF";
+
+/**
+ * Described in header.
+ */
+int mem_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args)
+{
+ char *bytes = *((void**)(args[0]));
+ u_int len = *((int*)(args[1]));
+
+ char buffer[BYTES_PER_LINE * 3];
+ char ascii_buffer[BYTES_PER_LINE + 1];
+ char *buffer_pos = buffer;
+ char *bytes_pos = bytes;
+ char *bytes_roof = bytes + len;
+ int line_start = 0;
+ int i = 0;
+ int written = 0;
+
+ written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
+
+ while (bytes_pos < bytes_roof)
+ {
+ *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
+ *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
+
+ ascii_buffer[i++] =
+ (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
+
+ if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
+ {
+ int padding = 3 * (BYTES_PER_LINE - i);
+
+ while (padding--)
+ {
+ *buffer_pos++ = ' ';
+ }
+ *buffer_pos++ = '\0';
+ ascii_buffer[i] = '\0';
+
+ written += print_in_hook(data, "\n%4d: %s %s",
+ line_start, buffer, ascii_buffer);
+
+ buffer_pos = buffer;
+ line_start += BYTES_PER_LINE;
+ i = 0;
+ }
+ else
+ {
+ *buffer_pos++ = ' ';
+ }
+ }
+ return written;
+}
diff --git a/src/libstrongswan/utils/utils/memory.h b/src/libstrongswan/utils/utils/memory.h
new file mode 100644
index 000000000..aef318f6c
--- /dev/null
+++ b/src/libstrongswan/utils/utils/memory.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup memory_i memory
+ * @{ @ingroup utils_i
+ */
+
+#ifndef MEMORY_H_
+#define MEMORY_H_
+
+/**
+ * Helper function that compares two binary blobs for equality
+ */
+static inline bool memeq(const void *x, const void *y, size_t len)
+{
+ return memcmp(x, y, len) == 0;
+}
+
+/**
+ * Same as memeq(), but with a constant runtime, safe for cryptographic use.
+ */
+bool memeq_const(const void *x, const void *y, size_t len);
+
+/**
+ * Calling memcpy() with NULL pointers, even with n == 0, results in undefined
+ * behavior according to the C standard. This version is guaranteed to not
+ * access the pointers if n is 0.
+ */
+static inline void *memcpy_noop(void *dst, const void *src, size_t n)
+{
+ return n ? memcpy(dst, src, n) : dst;
+}
+#ifdef memcpy
+# undef memcpy
+#endif
+#define memcpy(d,s,n) memcpy_noop(d,s,n)
+
+/**
+ * Calling memmove() with NULL pointers, even with n == 0, results in undefined
+ * behavior according to the C standard. This version is guaranteed to not
+ * access the pointers if n is 0.
+ */
+static inline void *memmove_noop(void *dst, const void *src, size_t n)
+{
+ return n ? memmove(dst, src, n) : dst;
+}
+#ifdef memmove
+# undef memmove
+#endif
+#define memmove(d,s,n) memmove_noop(d,s,n)
+
+/**
+ * Calling memset() with a NULL pointer, even with n == 0, results in undefined
+ * behavior according to the C standard. This version is guaranteed to not
+ * access the pointer if n is 0.
+ */
+static inline void *memset_noop(void *s, int c, size_t n)
+{
+ return n ? memset(s, c, n) : s;
+}
+#ifdef memset
+# undef memset
+#endif
+#define memset(s,c,n) memset_noop(s,c,n)
+
+/**
+ * Same as memcpy, but XORs src into dst instead of copy
+ */
+void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
+ */
+void memwipe_noinline(void *ptr, size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
+ */
+static inline void memwipe_inline(void *ptr, size_t n)
+{
+ volatile char *c = (volatile char*)ptr;
+ size_t m, i;
+
+ /* byte wise until long aligned */
+ for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
+ {
+ c[i] = 0;
+ }
+ /* word wise */
+ if (n >= sizeof(long))
+ {
+ for (m = n - sizeof(long); i <= m; i += sizeof(long))
+ {
+ *(volatile long*)&c[i] = 0;
+ }
+ }
+ /* byte wise of the rest */
+ for (; i < n; i++)
+ {
+ c[i] = 0;
+ }
+}
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
+ */
+static inline void memwipe(void *ptr, size_t n)
+{
+ if (!ptr)
+ {
+ return;
+ }
+ if (__builtin_constant_p(n))
+ {
+ memwipe_inline(ptr, n);
+ }
+ else
+ {
+ memwipe_noinline(ptr, n);
+ }
+}
+
+/**
+ * A variant of strstr with the characteristics of memchr, where haystack is not
+ * a null-terminated string but simply a memory area of length n.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n);
+
+/**
+ * Replacement for memrchr(3) if it is not provided by the C library.
+ *
+ * @param s start of the memory area to search
+ * @param c character to search
+ * @param n length of memory area to search
+ * @return pointer to the found character or NULL
+ */
+void *utils_memrchr(const void *s, int c, size_t n);
+
+#ifndef HAVE_MEMRCHR
+#define memrchr(s,c,n) utils_memrchr(s,c,n)
+#endif
+
+#ifndef HAVE_FMEMOPEN
+# ifdef HAVE_FUNOPEN
+# define HAVE_FMEMOPEN
+# define HAVE_FMEMOPEN_FALLBACK
+# include <stdio.h>
+/**
+ * fmemopen(3) fallback using BSD funopen.
+ *
+ * We could also provide one using fopencookie(), but should we have it we
+ * most likely have fmemopen().
+ *
+ * fseek() is currently not supported.
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode);
+# endif /* FUNOPEN */
+#endif /* FMEMOPEN */
+
+/**
+ * printf hook for memory areas.
+ *
+ * Arguments are:
+ * u_char *ptr, u_int len
+ */
+int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** MEMORY_H_ @} */
diff --git a/src/libstrongswan/utils/utils/object.h b/src/libstrongswan/utils/utils/object.h
new file mode 100644
index 000000000..301fb6685
--- /dev/null
+++ b/src/libstrongswan/utils/utils/object.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup object_i object
+ * @{ @ingroup utils_i
+ */
+
+#ifndef OBJECT_H_
+#define OBJECT_H_
+
+/**
+ * Call destructor of an object, if object != NULL
+ */
+#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
+
+/**
+ * Call offset destructor of an object, if object != NULL
+ */
+#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
+
+/**
+ * Call function destructor of an object, if object != NULL
+ */
+#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
+
+/**
+ * Object allocation/initialization macro, using designated initializer.
+ */
+#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
+
+/**
+ * Aligning version of INIT().
+ *
+ * The returned pointer must be freed using free_align(), not free().
+ *
+ * @param this object to allocate/initialize
+ * @param align alignment for allocation, in bytes
+ * @param ... initializer
+ */
+#define INIT_ALIGN(this, align, ...) { \
+ (this) = malloc_align(sizeof(*(this)), align); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
+
+/**
+ * Object allocation/initialization macro, with extra allocated bytes at tail.
+ *
+ * The extra space gets zero-initialized.
+ *
+ * @param this pointer to object to allocate memory for
+ * @param extra number of bytes to allocate at end of this
+ * @param ... initializer
+ */
+#define INIT_EXTRA(this, extra, ...) { \
+ typeof(extra) _extra = (extra); \
+ (this) = malloc(sizeof(*(this)) + _extra); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; \
+ memset((this) + 1, 0, _extra); }
+
+/**
+ * Aligning version of INIT_EXTRA().
+ *
+ * The returned pointer must be freed using free_align(), not free().
+ *
+ * @param this object to allocate/initialize
+ * @param extra number of bytes to allocate at end of this
+ * @param align alignment for allocation, in bytes
+ * @param ... initializer
+ */
+#define INIT_EXTRA_ALIGN(this, extra, align, ...) { \
+ typeof(extra) _extra = (extra); \
+ (this) = malloc_align(sizeof(*(this)) + _extra, align); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; \
+ memset((this) + 1, 0, _extra); }
+
+/**
+ * Method declaration/definition macro, providing private and public interface.
+ *
+ * Defines a method name with this as first parameter and a return value ret,
+ * and an alias for this method with a _ prefix, having the this argument
+ * safely casted to the public interface iface.
+ * _name is provided a function pointer, but will get optimized out by GCC.
+ */
+#define METHOD(iface, name, ret, this, ...) \
+ static ret name(union {iface *_public; this;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(name) *_##name = (typeof(name)*)name; \
+ static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Same as METHOD(), but is defined for two public interfaces.
+ */
+#define METHOD2(iface1, iface2, name, ret, this, ...) \
+ static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(name) *_##name = (typeof(name)*)name; \
+ static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Callback declaration/definition macro, allowing casted first parameter.
+ *
+ * This is very similar to METHOD, but instead of casting the first parameter
+ * to a public interface, it uses a void*. This allows type safe definition
+ * of a callback function, while using the real type for the first parameter.
+ */
+#define CALLBACK(name, ret, param1, ...) \
+ static ret _cb_##name(union {void *_generic; param1;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
+ static ret _cb_##name(param1, ##__VA_ARGS__)
+
+#endif /** OBJECT_H_ @} */
diff --git a/src/libstrongswan/utils/utils/path.c b/src/libstrongswan/utils/utils/path.c
new file mode 100644
index 000000000..3abbe77ed
--- /dev/null
+++ b/src/libstrongswan/utils/utils/path.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for memrchr */
+#include <utils/utils.h>
+#include <utils/debug.h>
+#include <utils/chunk.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/**
+ * Described in header.
+ */
+char* path_dirname(const char *path)
+{
+ char *pos;
+
+ pos = path ? strrchr(path, DIRECTORY_SEPARATOR[0]) : NULL;
+
+ if (pos && !pos[1])
+ { /* if path ends with slashes we have to look beyond them */
+ while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
+ { /* skip trailing slashes */
+ pos--;
+ }
+ pos = memrchr(path, DIRECTORY_SEPARATOR[0], pos - path + 1);
+ }
+ if (!pos)
+ {
+#ifdef WIN32
+ if (path && strlen(path))
+ {
+ if ((isalpha(path[0]) && path[1] == ':'))
+ { /* if just a drive letter given, return that as dirname */
+ return chunk_clone(chunk_from_chars(path[0], ':', 0)).ptr;
+ }
+ }
+#endif
+ return strdup(".");
+ }
+ while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
+ { /* skip superfluous slashes */
+ pos--;
+ }
+ return strndup(path, pos - path + 1);
+}
+
+/**
+ * Described in header.
+ */
+char* path_basename(const char *path)
+{
+ char *pos, *trail = NULL;
+
+ if (!path || !*path)
+ {
+ return strdup(".");
+ }
+ pos = strrchr(path, DIRECTORY_SEPARATOR[0]);
+ if (pos && !pos[1])
+ { /* if path ends with slashes we have to look beyond them */
+ while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
+ { /* skip trailing slashes */
+ pos--;
+ }
+ if (pos == path && *pos == DIRECTORY_SEPARATOR[0])
+ { /* contains only slashes */
+ return strdup(DIRECTORY_SEPARATOR);
+ }
+ trail = pos + 1;
+ pos = memrchr(path, DIRECTORY_SEPARATOR[0], trail - path);
+ }
+ pos = pos ? pos + 1 : (char*)path;
+ return trail ? strndup(pos, trail - pos) : strdup(pos);
+}
+
+/**
+ * Described in header.
+ */
+bool path_absolute(const char *path)
+{
+ if (!path)
+ {
+ return FALSE;
+ }
+#ifdef WIN32
+ if (strpfx(path, "\\\\"))
+ { /* UNC */
+ return TRUE;
+ }
+ if (strlen(path) && isalpha(path[0]) && path[1] == ':')
+ { /* drive letter */
+ return TRUE;
+ }
+#else /* !WIN32 */
+ if (path[0] == DIRECTORY_SEPARATOR[0])
+ {
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+bool mkdir_p(const char *path, mode_t mode)
+{
+ int len;
+ char *pos, full[PATH_MAX];
+ pos = full;
+ if (!path || *path == '\0')
+ {
+ return TRUE;
+ }
+ len = snprintf(full, sizeof(full)-1, "%s", path);
+ if (len < 0 || len >= sizeof(full)-1)
+ {
+ DBG1(DBG_LIB, "path string %s too long", path);
+ return FALSE;
+ }
+ /* ensure that the path ends with a '/' */
+ if (full[len-1] != '/')
+ {
+ full[len++] = '/';
+ full[len] = '\0';
+ }
+ /* skip '/' at the beginning */
+ while (*pos == '/')
+ {
+ pos++;
+ }
+ while ((pos = strchr(pos, '/')))
+ {
+ *pos = '\0';
+ if (access(full, F_OK) < 0)
+ {
+#ifdef WIN32
+ if (_mkdir(full) < 0)
+#else
+ if (mkdir(full, mode) < 0)
+#endif
+ {
+ DBG1(DBG_LIB, "failed to create directory %s", full);
+ return FALSE;
+ }
+ }
+ *pos = '/';
+ pos++;
+ }
+ return TRUE;
+}
diff --git a/src/libstrongswan/utils/utils/path.h b/src/libstrongswan/utils/utils/path.h
new file mode 100644
index 000000000..838ce73e6
--- /dev/null
+++ b/src/libstrongswan/utils/utils/path.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup path_i path
+ * @{ @ingroup utils_i
+ */
+
+#ifndef PATH_H_
+#define PATH_H_
+
+/**
+ * Directory separator character in paths on this platform
+ */
+#ifdef WIN32
+# define DIRECTORY_SEPARATOR "\\"
+#else
+# define DIRECTORY_SEPARATOR "/"
+#endif
+
+/**
+ * Like dirname(3) returns the directory part of the given null-terminated
+ * pathname, up to but not including the final '/' (or '.' if no '/' is found).
+ * Trailing '/' are not counted as part of the pathname.
+ *
+ * The difference is that it does this in a thread-safe manner (i.e. it does not
+ * use static buffers) and does not modify the original path.
+ *
+ * @param path original pathname
+ * @return allocated directory component
+ */
+char *path_dirname(const char *path);
+
+/**
+ * Like basename(3) returns the filename part of the given null-terminated path,
+ * i.e. the part following the final '/' (or '.' if path is empty or NULL).
+ * Trailing '/' are not counted as part of the pathname.
+ *
+ * The difference is that it does this in a thread-safe manner (i.e. it does not
+ * use static buffers) and does not modify the original path.
+ *
+ * @param path original pathname
+ * @return allocated filename component
+ */
+char *path_basename(const char *path);
+
+/**
+ * Check if a given path is absolute.
+ *
+ * @param path path to check
+ * @return TRUE if absolute, FALSE if relative
+ */
+bool path_absolute(const char *path);
+
+/**
+ * Creates a directory and all required parent directories.
+ *
+ * @param path path to the new directory
+ * @param mode permissions of the new directory/directories
+ * @return TRUE on success
+ */
+bool mkdir_p(const char *path, mode_t mode);
+
+#endif /** PATH_H_ @} */
diff --git a/src/libstrongswan/utils/utils/status.c b/src/libstrongswan/utils/utils/status.c
new file mode 100644
index 000000000..4a97d846c
--- /dev/null
+++ b/src/libstrongswan/utils/utils/status.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+ENUM(status_names, SUCCESS, NEED_MORE,
+ "SUCCESS",
+ "FAILED",
+ "OUT_OF_RES",
+ "ALREADY_DONE",
+ "NOT_SUPPORTED",
+ "INVALID_ARG",
+ "NOT_FOUND",
+ "PARSE_ERROR",
+ "VERIFY_ERROR",
+ "INVALID_STATE",
+ "DESTROY_ME",
+ "NEED_MORE",
+);
+
+/**
+ * returns FAILED
+ */
+status_t return_failed()
+{
+ return FAILED;
+}
+
+/**
+ * returns SUCCESS
+ */
+status_t return_success()
+{
+ return SUCCESS;
+}
diff --git a/src/libstrongswan/utils/utils/status.h b/src/libstrongswan/utils/utils/status.h
new file mode 100644
index 000000000..c96eebd44
--- /dev/null
+++ b/src/libstrongswan/utils/utils/status.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup status_i status
+ * @{ @ingroup utils_i
+ */
+
+#ifndef STATUS_H_
+#define STATUS_H_
+
+typedef enum status_t status_t;
+
+/**
+ * Return values of function calls.
+ */
+enum status_t {
+ /** Call succeeded */
+ SUCCESS,
+ /** Call failed */
+ FAILED,
+ /** Out of resources */
+ OUT_OF_RES,
+ /** The suggested operation is already done */
+ ALREADY_DONE,
+ /** Not supported */
+ NOT_SUPPORTED,
+ /** One of the arguments is invalid */
+ INVALID_ARG,
+ /** Something could not be found */
+ NOT_FOUND,
+ /** Error while parsing */
+ PARSE_ERROR,
+ /** Error while verifying */
+ VERIFY_ERROR,
+ /** Object in invalid state */
+ INVALID_STATE,
+ /** Destroy object which called method belongs to */
+ DESTROY_ME,
+ /** Another call to the method is required */
+ NEED_MORE,
+};
+
+/**
+ * enum_names for type status_t.
+ */
+extern enum_name_t *status_names;
+
+/**
+ * returns FAILED
+ */
+status_t return_failed();
+
+/**
+ * returns SUCCESS
+ */
+status_t return_success();
+
+#endif /** STATUS_H_ @} */
diff --git a/src/libstrongswan/utils/utils/strerror.h b/src/libstrongswan/utils/utils/strerror.h
index e1b063842..f59649c2a 100644
--- a/src/libstrongswan/utils/utils/strerror.h
+++ b/src/libstrongswan/utils/utils/strerror.h
@@ -14,7 +14,8 @@
*/
/**
- * @{ @ingroup utils
+ * @defgroup strerror_i strerror
+ * @{ @ingroup utils_i
*/
#ifndef STRERROR_H_
diff --git a/src/libstrongswan/utils/utils/string.c b/src/libstrongswan/utils/utils/string.c
new file mode 100644
index 000000000..14087e765
--- /dev/null
+++ b/src/libstrongswan/utils/utils/string.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+/**
+ * Described in header.
+ */
+char* translate(char *str, const char *from, const char *to)
+{
+ char *pos = str;
+ if (strlen(from) != strlen(to))
+ {
+ return str;
+ }
+ while (pos && *pos)
+ {
+ char *match;
+ if ((match = strchr(from, *pos)) != NULL)
+ {
+ *pos = to[match - from];
+ }
+ pos++;
+ }
+ return str;
+}
+
+/**
+ * Described in header.
+ */
+char* strreplace(const char *str, const char *search, const char *replace)
+{
+ size_t len, slen, rlen, count = 0;
+ char *res, *pos, *found, *dst;
+
+ if (!str || !*str || !search || !*search || !replace)
+ {
+ return (char*)str;
+ }
+ slen = strlen(search);
+ rlen = strlen(replace);
+ if (slen != rlen)
+ {
+ for (pos = (char*)str; (pos = strstr(pos, search)); pos += slen)
+ {
+ found = pos;
+ count++;
+ }
+ if (!count)
+ {
+ return (char*)str;
+ }
+ len = (found - str) + strlen(found) + count * (rlen - slen);
+ }
+ else
+ {
+ len = strlen(str);
+ }
+ found = strstr(str, search);
+ if (!found)
+ {
+ return (char*)str;
+ }
+ dst = res = malloc(len + 1);
+ pos = (char*)str;
+ do
+ {
+ len = found - pos;
+ memcpy(dst, pos, len);
+ dst += len;
+ memcpy(dst, replace, rlen);
+ dst += rlen;
+ pos = found + slen;
+ }
+ while ((found = strstr(pos, search)));
+ strcpy(dst, pos);
+ return res;
+}
diff --git a/src/libstrongswan/utils/utils/string.h b/src/libstrongswan/utils/utils/string.h
new file mode 100644
index 000000000..60eaaae22
--- /dev/null
+++ b/src/libstrongswan/utils/utils/string.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup string_i string
+ * @{ @ingroup utils_i
+ */
+
+#ifndef STRING_H_
+#define STRING_H_
+
+/**
+ * Helper function that compares two strings for equality
+ */
+static inline bool streq(const char *x, const char *y)
+{
+ return strcmp(x, y) == 0;
+}
+
+/**
+ * Helper function that compares two strings for equality, length limited
+ */
+static inline bool strneq(const char *x, const char *y, size_t len)
+{
+ return strncmp(x, y, len) == 0;
+}
+
+/**
+ * Helper function that checks if a string starts with a given prefix
+ */
+static inline bool strpfx(const char *x, const char *prefix)
+{
+ return strneq(x, prefix, strlen(prefix));
+}
+
+/**
+ * Helper function that compares two strings for equality ignoring case
+ */
+static inline bool strcaseeq(const char *x, const char *y)
+{
+ return strcasecmp(x, y) == 0;
+}
+
+/**
+ * Helper function that compares two strings for equality ignoring case, length limited
+ */
+static inline bool strncaseeq(const char *x, const char *y, size_t len)
+{
+ return strncasecmp(x, y, len) == 0;
+}
+
+/**
+ * Helper function that checks if a string starts with a given prefix
+ */
+static inline bool strcasepfx(const char *x, const char *prefix)
+{
+ return strncaseeq(x, prefix, strlen(prefix));
+}
+
+/**
+ * NULL-safe strdup variant
+ */
+static inline char *strdupnull(const char *s)
+{
+ return s ? strdup(s) : NULL;
+}
+
+/**
+ * Translates the characters in the given string, searching for characters
+ * in 'from' and mapping them to characters in 'to'.
+ * The two characters sets 'from' and 'to' must contain the same number of
+ * characters.
+ */
+char *translate(char *str, const char *from, const char *to);
+
+/**
+ * Replaces all occurrences of search in the given string with replace.
+ *
+ * Allocates memory only if anything is replaced in the string. The original
+ * string is also returned if any of the arguments are invalid (e.g. if search
+ * is empty or any of them are NULL).
+ *
+ * @param str original string
+ * @param search string to search for and replace
+ * @param replace string to replace found occurrences with
+ * @return allocated string, if anything got replaced, str otherwise
+ */
+char *strreplace(const char *str, const char *search, const char *replace);
+
+#endif /** STRING_H_ @} */
diff --git a/src/libstrongswan/utils/utils/time.c b/src/libstrongswan/utils/utils/time.c
new file mode 100644
index 000000000..c67ae93f2
--- /dev/null
+++ b/src/libstrongswan/utils/utils/time.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifdef WIN32
+/* for GetTickCount64, Windows 7 */
+# define _WIN32_WINNT 0x0601
+#endif
+
+#define _GNU_SOURCE
+#include <utils/utils.h>
+
+#include <inttypes.h>
+#include <time.h>
+
+/**
+ * Return monotonic time
+ */
+time_t time_monotonic(timeval_t *tv)
+{
+#ifdef WIN32
+ ULONGLONG ms;
+ time_t s;
+
+ ms = GetTickCount64();
+ s = ms / 1000;
+ if (tv)
+ {
+ tv->tv_sec = s;
+ tv->tv_usec = (ms - (s * 1000)) * 1000;
+ }
+ return s;
+#else /* !WIN32 */
+#if defined(HAVE_CLOCK_GETTIME) && \
+ (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
+ defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+ /* as we use time_monotonic() for condvar operations, we use the
+ * monotonic time source only if it is also supported by pthread. */
+ timespec_t ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ {
+ if (tv)
+ {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+ return ts.tv_sec;
+ }
+#endif /* HAVE_CLOCK_GETTIME && (...) */
+ /* Fallback to non-monotonic timestamps:
+ * On MAC OS X, creating monotonic timestamps is rather difficult. We
+ * could use mach_absolute_time() and catch sleep/wakeup notifications.
+ * We stick to the simpler (non-monotonic) gettimeofday() for now.
+ * But keep in mind: we need the same time source here as in condvar! */
+ if (!tv)
+ {
+ return time(NULL);
+ }
+ if (gettimeofday(tv, NULL) != 0)
+ { /* should actually never fail if passed pointers are valid */
+ return -1;
+ }
+ return tv->tv_sec;
+#endif /* !WIN32 */
+}
+
+/**
+ * Described in header.
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ static const char* months[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+ time_t *time = *((time_t**)(args[0]));
+ bool utc = *((int*)(args[1]));
+ struct tm t, *ret = NULL;
+
+ if (*time != UNDEFINED_TIME)
+ {
+ if (utc)
+ {
+ ret = gmtime_r(time, &t);
+ }
+ else
+ {
+ ret = localtime_r(time, &t);
+ }
+ }
+ if (ret == NULL)
+ {
+ return print_in_hook(data, "--- -- --:--:--%s----",
+ utc ? " UTC " : " ");
+ }
+ return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
+ months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
+ t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
+}
+
+/**
+ * Described in header.
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ char* unit = "second";
+ time_t *arg1 = *((time_t**)(args[0]));
+ time_t *arg2 = *((time_t**)(args[1]));
+ u_int64_t delta = llabs(*arg1 - *arg2);
+
+ if (delta > 2 * 60 * 60 * 24)
+ {
+ delta /= 60 * 60 * 24;
+ unit = "day";
+ }
+ else if (delta > 2 * 60 * 60)
+ {
+ delta /= 60 * 60;
+ unit = "hour";
+ }
+ else if (delta > 2 * 60)
+ {
+ delta /= 60;
+ unit = "minute";
+ }
+ return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
+ (delta == 1) ? "" : "s");
+}
diff --git a/src/libstrongswan/utils/utils/time.h b/src/libstrongswan/utils/utils/time.h
new file mode 100644
index 000000000..2626d9a33
--- /dev/null
+++ b/src/libstrongswan/utils/utils/time.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup time_i time
+ * @{ @ingroup utils_i
+ */
+
+#ifndef TIME_H_
+#define TIME_H_
+
+/**
+ * time_t not defined
+ */
+#define UNDEFINED_TIME 0
+
+/**
+ * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
+ */
+#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
+
+/**
+ * Handle struct timeval like an own type.
+ */
+typedef struct timeval timeval_t;
+
+/**
+ * Handle struct timespec like an own type.
+ */
+typedef struct timespec timespec_t;
+
+/**
+ * Get a timestamp from a monotonic time source.
+ *
+ * While the time()/gettimeofday() functions are affected by leap seconds
+ * and system time changes, this function returns ever increasing monotonic
+ * time stamps.
+ *
+ * @param tv timeval struct receiving monotonic timestamps, or NULL
+ * @return monotonic timestamp in seconds
+ */
+time_t time_monotonic(timeval_t *tv);
+
+/**
+ * Add the given number of milliseconds to the given timeval struct
+ *
+ * @param tv timeval struct to modify
+ * @param ms number of milliseconds
+ */
+static inline void timeval_add_ms(timeval_t *tv, u_int ms)
+{
+ tv->tv_usec += ms * 1000;
+ while (tv->tv_usec >= 1000000 /* 1s */)
+ {
+ tv->tv_usec -= 1000000;
+ tv->tv_sec++;
+ }
+}
+
+/**
+ * printf hook for time_t.
+ *
+ * Arguments are:
+ * time_t* time, bool utc
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * printf hook for time_t deltas.
+ *
+ * Arguments are:
+ * time_t* begin, time_t* end
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** TIME_H_ @} */
diff --git a/src/libstrongswan/utils/utils/tty.c b/src/libstrongswan/utils/utils/tty.c
new file mode 100644
index 000000000..7cce71dc5
--- /dev/null
+++ b/src/libstrongswan/utils/utils/tty.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+#include <unistd.h>
+
+ENUM(tty_color_names, TTY_RESET, TTY_BG_DEF,
+ "\e[0m",
+ "\e[1m",
+ "\e[4m",
+ "\e[5m",
+ "\e[30m",
+ "\e[31m",
+ "\e[32m",
+ "\e[33m",
+ "\e[34m",
+ "\e[35m",
+ "\e[36m",
+ "\e[37m",
+ "\e[39m",
+ "\e[40m",
+ "\e[41m",
+ "\e[42m",
+ "\e[43m",
+ "\e[44m",
+ "\e[45m",
+ "\e[46m",
+ "\e[47m",
+ "\e[49m",
+);
+
+/**
+ * Get the escape string for a given TTY color, empty string on non-tty FILE
+ */
+char* tty_escape_get(int fd, tty_escape_t escape)
+{
+ if (!isatty(fd))
+ {
+ return "";
+ }
+ switch (escape)
+ {
+ case TTY_RESET:
+ case TTY_BOLD:
+ case TTY_UNDERLINE:
+ case TTY_BLINKING:
+#ifdef WIN32
+ return "";
+#endif
+ case TTY_FG_BLACK:
+ case TTY_FG_RED:
+ case TTY_FG_GREEN:
+ case TTY_FG_YELLOW:
+ case TTY_FG_BLUE:
+ case TTY_FG_MAGENTA:
+ case TTY_FG_CYAN:
+ case TTY_FG_WHITE:
+ case TTY_FG_DEF:
+ case TTY_BG_BLACK:
+ case TTY_BG_RED:
+ case TTY_BG_GREEN:
+ case TTY_BG_YELLOW:
+ case TTY_BG_BLUE:
+ case TTY_BG_MAGENTA:
+ case TTY_BG_CYAN:
+ case TTY_BG_WHITE:
+ case TTY_BG_DEF:
+ return enum_to_name(tty_color_names, escape);
+ /* warn if a escape code is missing */
+ }
+ return "";
+}
diff --git a/src/libstrongswan/utils/utils/tty.h b/src/libstrongswan/utils/utils/tty.h
new file mode 100644
index 000000000..6cd285a9a
--- /dev/null
+++ b/src/libstrongswan/utils/utils/tty.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tty_i tty
+ * @{ @ingroup utils_i
+ */
+
+#ifndef TTY_H_
+#define TTY_H_
+
+typedef enum tty_escape_t tty_escape_t;
+
+/**
+ * Excape codes for tty colors
+ */
+enum tty_escape_t {
+ /** text properties */
+ TTY_RESET,
+ TTY_BOLD,
+ TTY_UNDERLINE,
+ TTY_BLINKING,
+
+ /** foreground colors */
+ TTY_FG_BLACK,
+ TTY_FG_RED,
+ TTY_FG_GREEN,
+ TTY_FG_YELLOW,
+ TTY_FG_BLUE,
+ TTY_FG_MAGENTA,
+ TTY_FG_CYAN,
+ TTY_FG_WHITE,
+ TTY_FG_DEF,
+
+ /** background colors */
+ TTY_BG_BLACK,
+ TTY_BG_RED,
+ TTY_BG_GREEN,
+ TTY_BG_YELLOW,
+ TTY_BG_BLUE,
+ TTY_BG_MAGENTA,
+ TTY_BG_CYAN,
+ TTY_BG_WHITE,
+ TTY_BG_DEF,
+};
+
+/**
+ * Get the escape string for a given TTY color, empty string on non-tty fd
+ */
+char* tty_escape_get(int fd, tty_escape_t escape);
+
+#endif /** TTY_H_ @} */
diff --git a/src/libstrongswan/utils/utils/types.h b/src/libstrongswan/utils/utils/types.h
new file mode 100644
index 000000000..056c2e0c2
--- /dev/null
+++ b/src/libstrongswan/utils/utils/types.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup types_i types
+ * @{ @ingroup utils_i
+ */
+
+#ifndef TYPES_H_
+#define TYPES_H_
+
+/**
+ * General purpose boolean type.
+ */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# ifndef HAVE__BOOL
+# define _Bool signed char
+# endif /* HAVE__BOOL */
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif /* HAVE_STDBOOL_H */
+#ifndef FALSE
+# define FALSE false
+#endif /* FALSE */
+#ifndef TRUE
+# define TRUE true
+#endif /* TRUE */
+
+/**
+ * define some missing fixed width int types on OpenSolaris.
+ * TODO: since the uintXX_t types are defined by the C99 standard we should
+ * probably use those anyway
+ */
+#if defined __sun || defined WIN32
+#include <stdint.h>
+typedef uint8_t u_int8_t;
+typedef uint16_t u_int16_t;
+typedef uint32_t u_int32_t;
+typedef uint64_t u_int64_t;
+#endif
+
+#ifdef HAVE_INT128
+/**
+ * 128 bit wide signed integer, if supported
+ */
+typedef __int128 int128_t;
+/**
+ * 128 bit wide unsigned integer, if supported
+ */
+typedef unsigned __int128 u_int128_t;
+
+# define MAX_INT_TYPE int128_t
+# define MAX_UINT_TYPE u_int128_t
+#else
+# define MAX_INT_TYPE int64_t
+# define MAX_UINT_TYPE u_int64_t
+#endif
+
+/**
+ * deprecated pluto style return value:
+ * error message, NULL for success
+ */
+typedef const char *err_t;
+
+/**
+ * Handle struct sockaddr as a simpler sockaddr_t type.
+ */
+typedef struct sockaddr sockaddr_t;
+
+#endif /** TYPES_H_ @} */