aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils')
-rw-r--r--src/libstrongswan/utils/chunk.h2
-rw-r--r--src/libstrongswan/utils/integrity_checker.h2
-rw-r--r--src/libstrongswan/utils/settings.h2
-rw-r--r--src/libstrongswan/utils/utils.c570
-rw-r--r--src/libstrongswan/utils/utils.h699
5 files changed, 1272 insertions, 3 deletions
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h
index 865c1b82f..67848eec1 100644
--- a/src/libstrongswan/utils/chunk.h
+++ b/src/libstrongswan/utils/chunk.h
@@ -42,7 +42,7 @@ struct chunk_t {
size_t len;
};
-#include "../utils.h"
+#include "utils.h"
/**
* A { NULL, 0 }-chunk handy for initialization.
diff --git a/src/libstrongswan/utils/integrity_checker.h b/src/libstrongswan/utils/integrity_checker.h
index f999b9a29..afaa114b3 100644
--- a/src/libstrongswan/utils/integrity_checker.h
+++ b/src/libstrongswan/utils/integrity_checker.h
@@ -21,7 +21,7 @@
#ifndef INTEGRITY_CHECKER_H_
#define INTEGRITY_CHECKER_H_
-#include "../utils.h"
+#include "utils.h"
typedef struct integrity_checker_t integrity_checker_t;
typedef struct integrity_checksum_t integrity_checksum_t;
diff --git a/src/libstrongswan/utils/settings.h b/src/libstrongswan/utils/settings.h
index ae4e719e8..a861325f5 100644
--- a/src/libstrongswan/utils/settings.h
+++ b/src/libstrongswan/utils/settings.h
@@ -24,7 +24,7 @@
typedef struct settings_t settings_t;
-#include "../utils.h"
+#include "utils.h"
#include "collections/enumerator.h"
/**
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
new file mode 100644
index 000000000..bf0224c5f
--- /dev/null
+++ b/src/libstrongswan/utils/utils.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "utils.h"
+
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <limits.h>
+#include <dirent.h>
+#include <time.h>
+#include <pthread.h>
+
+#include "collections/enumerator.h"
+#include "utils/debug.h"
+
+ENUM(status_names, SUCCESS, NEED_MORE,
+ "SUCCESS",
+ "FAILED",
+ "OUT_OF_RES",
+ "ALREADY_DONE",
+ "NOT_SUPPORTED",
+ "INVALID_ARG",
+ "NOT_FOUND",
+ "PARSE_ERROR",
+ "VERIFY_ERROR",
+ "INVALID_STATE",
+ "DESTROY_ME",
+ "NEED_MORE",
+);
+
+/**
+ * Described in header.
+ */
+void *clalloc(void * pointer, size_t size)
+{
+ void *data;
+ data = malloc(size);
+
+ memcpy(data, pointer, size);
+
+ return (data);
+}
+
+/**
+ * Described in header.
+ */
+void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
+{
+ int m, i;
+
+ /* byte wise XOR until dst aligned */
+ for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
+ {
+ dst[i] ^= src[i];
+ }
+ /* try to use words if src shares an aligment with dst */
+ switch (((uintptr_t)&src[i] % sizeof(long)))
+ {
+ case 0:
+ for (m = n - sizeof(long); i <= m; i += sizeof(long))
+ {
+ *(long*)&dst[i] ^= *(long*)&src[i];
+ }
+ break;
+ case sizeof(int):
+ for (m = n - sizeof(int); i <= m; i += sizeof(int))
+ {
+ *(int*)&dst[i] ^= *(int*)&src[i];
+ }
+ break;
+ case sizeof(short):
+ for (m = n - sizeof(short); i <= m; i += sizeof(short))
+ {
+ *(short*)&dst[i] ^= *(short*)&src[i];
+ }
+ break;
+ default:
+ break;
+ }
+ /* byte wise XOR of the rest */
+ for (; i < n; i++)
+ {
+ dst[i] ^= src[i];
+ }
+}
+
+/**
+ * Described in header.
+ */
+void memwipe_noinline(void *ptr, size_t n)
+{
+ memwipe_inline(ptr, n);
+}
+
+/**
+ * Described in header.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n)
+{
+ unsigned const char *pos = haystack;
+ size_t l = strlen(needle);
+ for (; n >= l; ++pos, --n)
+ {
+ if (memeq(pos, needle, l))
+ {
+ return (void*)pos;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Described in header.
+ */
+char* translate(char *str, const char *from, const char *to)
+{
+ char *pos = str;
+ if (strlen(from) != strlen(to))
+ {
+ return str;
+ }
+ while (pos && *pos)
+ {
+ char *match;
+ if ((match = strchr(from, *pos)) != NULL)
+ {
+ *pos = to[match - from];
+ }
+ pos++;
+ }
+ return str;
+}
+
+/**
+ * Described in header.
+ */
+bool mkdir_p(const char *path, mode_t mode)
+{
+ int len;
+ char *pos, full[PATH_MAX];
+ pos = full;
+ if (!path || *path == '\0')
+ {
+ return TRUE;
+ }
+ len = snprintf(full, sizeof(full)-1, "%s", path);
+ if (len < 0 || len >= sizeof(full)-1)
+ {
+ DBG1(DBG_LIB, "path string %s too long", path);
+ return FALSE;
+ }
+ /* ensure that the path ends with a '/' */
+ if (full[len-1] != '/')
+ {
+ full[len++] = '/';
+ full[len] = '\0';
+ }
+ /* skip '/' at the beginning */
+ while (*pos == '/')
+ {
+ pos++;
+ }
+ while ((pos = strchr(pos, '/')))
+ {
+ *pos = '\0';
+ if (access(full, F_OK) < 0)
+ {
+ if (mkdir(full, mode) < 0)
+ {
+ DBG1(DBG_LIB, "failed to create directory %s", full);
+ return FALSE;
+ }
+ }
+ *pos = '/';
+ pos++;
+ }
+ return TRUE;
+}
+
+
+/**
+ * The size of the thread-specific error buffer
+ */
+#define STRERROR_BUF_LEN 256
+
+/**
+ * Key to store thread-specific error buffer
+ */
+static pthread_key_t strerror_buf_key;
+
+/**
+ * Only initialize the key above once
+ */
+static pthread_once_t strerror_buf_key_once = PTHREAD_ONCE_INIT;
+
+/**
+ * Create the key used for the thread-specific error buffer
+ */
+static void create_strerror_buf_key()
+{
+ pthread_key_create(&strerror_buf_key, free);
+}
+
+/**
+ * Retrieve the error buffer assigned to the current thread (or create it)
+ */
+static inline char *get_strerror_buf()
+{
+ char *buf;
+
+ pthread_once(&strerror_buf_key_once, create_strerror_buf_key);
+ buf = pthread_getspecific(strerror_buf_key);
+ if (!buf)
+ {
+ buf = malloc(STRERROR_BUF_LEN);
+ pthread_setspecific(strerror_buf_key, buf);
+ }
+ return buf;
+}
+
+#ifdef HAVE_STRERROR_R
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ char *buf = get_strerror_buf(), *msg;
+
+#ifdef STRERROR_R_CHAR_P
+ /* char* version which may or may not return the original buffer */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN);
+#else
+ /* int version returns 0 on success */
+ msg = strerror_r(errnum, buf, STRERROR_BUF_LEN) ? "Unknown error" : buf;
+#endif
+ return msg;
+}
+#else /* HAVE_STRERROR_R */
+/* we actually wan't to call strerror(3) below */
+#undef strerror
+/*
+ * Described in header.
+ */
+const char *safe_strerror(int errnum)
+{
+ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ char *buf = get_strerror_buf();
+
+ /* use a mutex to ensure calling strerror(3) is thread-safe */
+ pthread_mutex_lock(&mutex);
+ strncpy(buf, strerror(errnum), STRERROR_BUF_LEN);
+ pthread_mutex_unlock(&mutex);
+ buf[STRERROR_BUF_LEN - 1] = '\0';
+ return buf;
+}
+#endif /* HAVE_STRERROR_R */
+
+
+#ifndef HAVE_CLOSEFROM
+/**
+ * Described in header.
+ */
+void closefrom(int lowfd)
+{
+ char fd_dir[PATH_MAX];
+ int maxfd, fd, len;
+
+ /* try to close only open file descriptors on Linux... */
+ len = snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", getpid());
+ if (len > 0 && len < sizeof(fd_dir) && access(fd_dir, F_OK) == 0)
+ {
+ enumerator_t *enumerator = enumerator_create_directory(fd_dir);
+ if (enumerator)
+ {
+ char *rel;
+ while (enumerator->enumerate(enumerator, &rel, NULL, NULL))
+ {
+ fd = atoi(rel);
+ if (fd >= lowfd)
+ {
+ close(fd);
+ }
+ }
+ enumerator->destroy(enumerator);
+ return;
+ }
+ }
+
+ /* ...fall back to closing all fds otherwise */
+ maxfd = (int)sysconf(_SC_OPEN_MAX);
+ if (maxfd < 0)
+ {
+ maxfd = 256;
+ }
+ for (fd = lowfd; fd < maxfd; fd++)
+ {
+ close(fd);
+ }
+}
+#endif /* HAVE_CLOSEFROM */
+
+/**
+ * Return monotonic time
+ */
+time_t time_monotonic(timeval_t *tv)
+{
+#if defined(HAVE_CLOCK_GETTIME) && \
+ (defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
+ defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+ /* as we use time_monotonic() for condvar operations, we use the
+ * monotonic time source only if it is also supported by pthread. */
+ timespec_t ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ {
+ if (tv)
+ {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+ return ts.tv_sec;
+ }
+#endif /* HAVE_CLOCK_GETTIME && (...) */
+ /* Fallback to non-monotonic timestamps:
+ * On MAC OS X, creating monotonic timestamps is rather difficult. We
+ * could use mach_absolute_time() and catch sleep/wakeup notifications.
+ * We stick to the simpler (non-monotonic) gettimeofday() for now.
+ * But keep in mind: we need the same time source here as in condvar! */
+ if (!tv)
+ {
+ return time(NULL);
+ }
+ if (gettimeofday(tv, NULL) != 0)
+ { /* should actually never fail if passed pointers are valid */
+ return -1;
+ }
+ return tv->tv_sec;
+}
+
+/**
+ * return null
+ */
+void *return_null()
+{
+ return NULL;
+}
+
+/**
+ * returns TRUE
+ */
+bool return_true()
+{
+ return TRUE;
+}
+
+/**
+ * returns FALSE
+ */
+bool return_false()
+{
+ return FALSE;
+}
+
+/**
+ * returns FAILED
+ */
+status_t return_failed()
+{
+ return FAILED;
+}
+
+/**
+ * nop operation
+ */
+void nop()
+{
+}
+
+#ifndef HAVE_GCC_ATOMIC_OPERATIONS
+
+/**
+ * We use a single mutex for all refcount variables.
+ */
+static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Increase refcount
+ */
+void ref_get(refcount_t *ref)
+{
+ pthread_mutex_lock(&ref_mutex);
+ (*ref)++;
+ pthread_mutex_unlock(&ref_mutex);
+}
+
+/**
+ * Decrease refcount
+ */
+bool ref_put(refcount_t *ref)
+{
+ bool more_refs;
+
+ pthread_mutex_lock(&ref_mutex);
+ more_refs = --(*ref) > 0;
+ pthread_mutex_unlock(&ref_mutex);
+ return !more_refs;
+}
+
+/**
+ * Single mutex for all compare and swap operations.
+ */
+static pthread_mutex_t cas_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * Compare and swap if equal to old value
+ */
+#define _cas_impl(name, type) \
+bool cas_##name(type *ptr, type oldval, type newval) \
+{ \
+ bool swapped; \
+ pthread_mutex_lock(&cas_mutex); \
+ if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
+ pthread_mutex_unlock(&cas_mutex); \
+ return swapped; \
+}
+
+_cas_impl(bool, bool)
+_cas_impl(ptr, void*)
+
+#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * Described in header.
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ static const char* months[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+ time_t *time = *((time_t**)(args[0]));
+ bool utc = *((bool*)(args[1]));;
+ struct tm t;
+
+ if (time == UNDEFINED_TIME)
+ {
+ return print_in_hook(data, "--- -- --:--:--%s----",
+ utc ? " UTC " : " ");
+ }
+ if (utc)
+ {
+ gmtime_r(time, &t);
+ }
+ else
+ {
+ localtime_r(time, &t);
+ }
+ return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
+ months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
+ t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
+}
+
+/**
+ * Described in header.
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args)
+{
+ char* unit = "second";
+ time_t *arg1 = *((time_t**)(args[0]));
+ time_t *arg2 = *((time_t**)(args[1]));
+ u_int64_t delta = llabs(*arg1 - *arg2);
+
+ if (delta > 2 * 60 * 60 * 24)
+ {
+ delta /= 60 * 60 * 24;
+ unit = "day";
+ }
+ else if (delta > 2 * 60 * 60)
+ {
+ delta /= 60 * 60;
+ unit = "hour";
+ }
+ else if (delta > 2 * 60)
+ {
+ delta /= 60;
+ unit = "minute";
+ }
+ return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
+ (delta == 1) ? "" : "s");
+}
+
+/**
+ * Number of bytes per line to dump raw data
+ */
+#define BYTES_PER_LINE 16
+
+static char hexdig_upper[] = "0123456789ABCDEF";
+
+/**
+ * Described in header.
+ */
+int mem_printf_hook(printf_hook_data_t *data,
+ printf_hook_spec_t *spec, const void *const *args)
+{
+ char *bytes = *((void**)(args[0]));
+ u_int len = *((int*)(args[1]));
+
+ char buffer[BYTES_PER_LINE * 3];
+ char ascii_buffer[BYTES_PER_LINE + 1];
+ char *buffer_pos = buffer;
+ char *bytes_pos = bytes;
+ char *bytes_roof = bytes + len;
+ int line_start = 0;
+ int i = 0;
+ int written = 0;
+
+ written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
+
+ while (bytes_pos < bytes_roof)
+ {
+ *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
+ *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
+
+ ascii_buffer[i++] =
+ (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
+
+ if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
+ {
+ int padding = 3 * (BYTES_PER_LINE - i);
+
+ while (padding--)
+ {
+ *buffer_pos++ = ' ';
+ }
+ *buffer_pos++ = '\0';
+ ascii_buffer[i] = '\0';
+
+ written += print_in_hook(data, "\n%4d: %s %s",
+ line_start, buffer, ascii_buffer);
+
+ buffer_pos = buffer;
+ line_start += BYTES_PER_LINE;
+ i = 0;
+ }
+ else
+ {
+ *buffer_pos++ = ' ';
+ }
+ }
+ return written;
+}
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
new file mode 100644
index 000000000..7b1beb93a
--- /dev/null
+++ b/src/libstrongswan/utils/utils.h
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup utils_i utils
+ * @{ @ingroup utils
+ */
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include "enum.h"
+
+/**
+ * strongSwan program return codes
+ */
+#define SS_RC_LIBSTRONGSWAN_INTEGRITY 64
+#define SS_RC_DAEMON_INTEGRITY 65
+#define SS_RC_INITIALIZATION_FAILED 66
+
+#define SS_RC_FIRST SS_RC_LIBSTRONGSWAN_INTEGRITY
+#define SS_RC_LAST SS_RC_INITIALIZATION_FAILED
+
+/**
+ * Number of bits in a byte
+ */
+#define BITS_PER_BYTE 8
+
+/**
+ * Default length for various auxiliary text buffers
+ */
+#define BUF_LEN 512
+
+/**
+ * General purpose boolean type.
+ */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# ifndef HAVE__BOOL
+# define _Bool signed char
+# endif /* HAVE__BOOL */
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif /* HAVE_STDBOOL_H */
+#ifndef FALSE
+# define FALSE false
+#endif /* FALSE */
+#ifndef TRUE
+# define TRUE true
+#endif /* TRUE */
+
+/**
+ * Helper function that compares two strings for equality
+ */
+static inline bool streq(const char *x, const char *y)
+{
+ return strcmp(x, y) == 0;
+}
+
+/**
+ * Macro compares two strings for equality, length limited
+ */
+#define strneq(x,y,len) (strncmp(x, y, len) == 0)
+
+/**
+ * Helper function that compares two strings for equality ignoring case
+ */
+static inline bool strcaseeq(const char *x, const char *y)
+{
+ return strcasecmp(x, y) == 0;
+}
+
+/**
+ * Macro compares two strings for equality ignoring case, length limited
+ */
+#define strncaseeq(x,y,len) (strncasecmp(x, y, len) == 0)
+
+/**
+ * NULL-safe strdup variant
+ */
+static inline char *strdupnull(const char *s)
+{
+ return s ? strdup(s) : NULL;
+}
+
+/**
+ * Macro compares two binary blobs for equality
+ */
+#define memeq(x,y,len) (memcmp(x, y, len) == 0)
+
+/**
+ * Macro gives back larger of two values.
+ */
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ _x > _y ? _x : _y; })
+
+
+/**
+ * Macro gives back smaller of two values.
+ */
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ _x < _y ? _x : _y; })
+
+/**
+ * Call destructor of an object, if object != NULL
+ */
+#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
+
+/**
+ * Call offset destructor of an object, if object != NULL
+ */
+#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
+
+/**
+ * Call function destructor of an object, if object != NULL
+ */
+#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
+
+/**
+ * Debug macro to follow control flow
+ */
+#define POS printf("%s, line %d\n", __FILE__, __LINE__)
+
+/**
+ * Object allocation/initialization macro, using designated initializer.
+ */
+#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
+ *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
+
+/**
+ * Method declaration/definition macro, providing private and public interface.
+ *
+ * Defines a method name with this as first parameter and a return value ret,
+ * and an alias for this method with a _ prefix, having the this argument
+ * safely casted to the public interface iface.
+ * _name is provided a function pointer, but will get optimized out by GCC.
+ */
+#define METHOD(iface, name, ret, this, ...) \
+ static ret name(union {iface *_public; this;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(name) *_##name = (typeof(name)*)name; \
+ static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Same as METHOD(), but is defined for two public interfaces.
+ */
+#define METHOD2(iface1, iface2, name, ret, this, ...) \
+ static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
+ __attribute__((transparent_union)), ##__VA_ARGS__); \
+ static typeof(name) *_##name = (typeof(name)*)name; \
+ static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Architecture independent bitfield definition helpers (at least with GCC).
+ *
+ * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
+ * BITFIELD2(u_int8_t,
+ * low: 4,
+ * high: 4,
+ * ) flags;
+ * The member defined first placed at bit 0.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define BITFIELD2(t, a, b,...) struct { t a; t b; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...) struct { t a; t b; t c; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...) struct { t a; t b; t c; t d; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...) struct { t a; t b; t c; t d; t e; __VA_ARGS__}
+#elif BYTE_ORDER == BIG_ENDIAN
+#define BITFIELD2(t, a, b,...) struct { t b; t a; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...) struct { t c; t b; t a; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...) struct { t d; t c; t b; t a; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...) struct { t e; t d; t c; t b; t a; __VA_ARGS__}
+#endif
+
+/**
+ * Macro to allocate a sized type.
+ */
+#define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
+
+/**
+ * Get the number of elements in an array
+ */
+#define countof(array) (sizeof(array)/sizeof(array[0]))
+
+/**
+ * Ignore result of functions tagged with warn_unused_result attributes
+ */
+#define ignore_result(call) { if(call){}; }
+
+/**
+ * Assign a function as a class method
+ */
+#define ASSIGN(method, function) (method = (typeof(method))function)
+
+/**
+ * time_t not defined
+ */
+#define UNDEFINED_TIME 0
+
+/**
+ * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
+ */
+#define TIME_32_BIT_SIGNED_MAX 0x7fffffff
+
+/**
+ * define some missing fixed width int types on OpenSolaris.
+ * TODO: since the uintXX_t types are defined by the C99 standard we should
+ * probably use those anyway
+ */
+#ifdef __sun
+ #include <stdint.h>
+ typedef uint8_t u_int8_t;
+ typedef uint16_t u_int16_t;
+ typedef uint32_t u_int32_t;
+ typedef uint64_t u_int64_t;
+#endif
+
+typedef enum status_t status_t;
+
+/**
+ * Return values of function calls.
+ */
+enum status_t {
+ /**
+ * Call succeeded.
+ */
+ SUCCESS,
+
+ /**
+ * Call failed.
+ */
+ FAILED,
+
+ /**
+ * Out of resources.
+ */
+ OUT_OF_RES,
+
+ /**
+ * The suggested operation is already done
+ */
+ ALREADY_DONE,
+
+ /**
+ * Not supported.
+ */
+ NOT_SUPPORTED,
+
+ /**
+ * One of the arguments is invalid.
+ */
+ INVALID_ARG,
+
+ /**
+ * Something could not be found.
+ */
+ NOT_FOUND,
+
+ /**
+ * Error while parsing.
+ */
+ PARSE_ERROR,
+
+ /**
+ * Error while verifying.
+ */
+ VERIFY_ERROR,
+
+ /**
+ * Object in invalid state.
+ */
+ INVALID_STATE,
+
+ /**
+ * Destroy object which called method belongs to.
+ */
+ DESTROY_ME,
+
+ /**
+ * Another call to the method is required.
+ */
+ NEED_MORE,
+};
+
+/**
+ * enum_names for type status_t.
+ */
+extern enum_name_t *status_names;
+
+/**
+ * deprecated pluto style return value:
+ * error message, NULL for success
+ */
+typedef const char *err_t;
+
+/**
+ * Handle struct timeval like an own type.
+ */
+typedef struct timeval timeval_t;
+
+/**
+ * Handle struct timespec like an own type.
+ */
+typedef struct timespec timespec_t;
+
+/**
+ * Handle struct chunk_t like an own type.
+ */
+typedef struct sockaddr sockaddr_t;
+
+/**
+ * Clone a data to a newly allocated buffer
+ */
+void *clalloc(void *pointer, size_t size);
+
+/**
+ * Same as memcpy, but XORs src into dst instead of copy
+ */
+void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
+ */
+void memwipe_noinline(void *ptr, size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
+ */
+static inline void memwipe_inline(void *ptr, size_t n)
+{
+ volatile char *c = (volatile char*)ptr;
+ size_t m, i;
+
+ /* byte wise until long aligned */
+ for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
+ {
+ c[i] = 0;
+ }
+ /* word wise */
+ if (n >= sizeof(long))
+ {
+ for (m = n - sizeof(long); i <= m; i += sizeof(long))
+ {
+ *(volatile long*)&c[i] = 0;
+ }
+ }
+ /* byte wise of the rest */
+ for (; i < n; i++)
+ {
+ c[i] = 0;
+ }
+}
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
+ */
+static inline void memwipe(void *ptr, size_t n)
+{
+ if (__builtin_constant_p(n))
+ {
+ memwipe_inline(ptr, n);
+ }
+ else
+ {
+ memwipe_noinline(ptr, n);
+ }
+}
+
+/**
+ * A variant of strstr with the characteristics of memchr, where haystack is not
+ * a null-terminated string but simply a memory area of length n.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n);
+
+/**
+ * Translates the characters in the given string, searching for characters
+ * in 'from' and mapping them to characters in 'to'.
+ * The two characters sets 'from' and 'to' must contain the same number of
+ * characters.
+ */
+char *translate(char *str, const char *from, const char *to);
+
+/**
+ * Creates a directory and all required parent directories.
+ *
+ * @param path path to the new directory
+ * @param mode permissions of the new directory/directories
+ * @return TRUE on success
+ */
+bool mkdir_p(const char *path, mode_t mode);
+
+/**
+ * Thread-safe wrapper around strerror and strerror_r.
+ *
+ * This is required because the first is not thread-safe (on some platforms)
+ * and the second uses two different signatures (POSIX/GNU) and is impractical
+ * to use anyway.
+ *
+ * @param errnum error code (i.e. errno)
+ * @return error message
+ */
+const char *safe_strerror(int errnum);
+
+/**
+ * Replace usages of strerror(3) with thread-safe variant.
+ */
+#define strerror(errnum) safe_strerror(errnum)
+
+#ifndef HAVE_CLOSEFROM
+/**
+ * Close open file descriptors greater than or equal to lowfd.
+ *
+ * @param lowfd start closing file descriptoros from here
+ */
+void closefrom(int lowfd);
+#endif
+
+/**
+ * Get a timestamp from a monotonic time source.
+ *
+ * While the time()/gettimeofday() functions are affected by leap seconds
+ * and system time changes, this function returns ever increasing monotonic
+ * time stamps.
+ *
+ * @param tv timeval struct receiving monotonic timestamps, or NULL
+ * @return monotonic timestamp in seconds
+ */
+time_t time_monotonic(timeval_t *tv);
+
+/**
+ * Add the given number of milliseconds to the given timeval struct
+ *
+ * @param tv timeval struct to modify
+ * @param ms number of milliseconds
+ */
+static inline void timeval_add_ms(timeval_t *tv, u_int ms)
+{
+ tv->tv_usec += ms * 1000;
+ while (tv->tv_usec > 1000000 /* 1s */)
+ {
+ tv->tv_usec -= 1000000;
+ tv->tv_sec++;
+ }
+}
+
+/**
+ * returns null
+ */
+void *return_null();
+
+/**
+ * No-Operation function
+ */
+void nop();
+
+/**
+ * returns TRUE
+ */
+bool return_true();
+
+/**
+ * returns FALSE
+ */
+bool return_false();
+
+/**
+ * returns FAILED
+ */
+status_t return_failed();
+
+/**
+ * Write a 16-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 16-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun16(void *network, u_int16_t host)
+{
+ char *unaligned = (char*)network;
+
+ host = htons(host);
+ memcpy(unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 32-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 32-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun32(void *network, u_int32_t host)
+{
+ char *unaligned = (char*)network;
+
+ host = htonl(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 64-bit host order value in network order to an unaligned address.
+ *
+ * @param host host order 64-bit value
+ * @param network unaligned address to write network order value to
+ */
+static inline void htoun64(void *network, u_int64_t host)
+{
+ char *unaligned = (char*)network;
+
+#ifdef be64toh
+ host = htobe64(host);
+ memcpy((char*)unaligned, &host, sizeof(host));
+#else
+ u_int32_t high_part, low_part;
+
+ high_part = host >> 32;
+ high_part = htonl(high_part);
+ low_part = host & 0xFFFFFFFFLL;
+ low_part = htonl(low_part);
+
+ memcpy(unaligned, &high_part, sizeof(high_part));
+ unaligned += sizeof(high_part);
+ memcpy(unaligned, &low_part, sizeof(low_part));
+#endif
+}
+
+/**
+ * Read a 16-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int16_t untoh16(void *network)
+{
+ char *unaligned = (char*)network;
+ u_int16_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return ntohs(tmp);
+}
+
+/**
+ * Read a 32-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int32_t untoh32(void *network)
+{
+ char *unaligned = (char*)network;
+ u_int32_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return ntohl(tmp);
+}
+
+/**
+ * Read a 64-bit value in network order from an unaligned address to host order.
+ *
+ * @param network unaligned address to read network order value from
+ * @return host order value
+ */
+static inline u_int64_t untoh64(void *network)
+{
+ char *unaligned = (char*)network;
+
+#ifdef be64toh
+ u_int64_t tmp;
+
+ memcpy(&tmp, unaligned, sizeof(tmp));
+ return be64toh(tmp);
+#else
+ u_int32_t high_part, low_part;
+
+ memcpy(&high_part, unaligned, sizeof(high_part));
+ unaligned += sizeof(high_part);
+ memcpy(&low_part, unaligned, sizeof(low_part));
+
+ high_part = ntohl(high_part);
+ low_part = ntohl(low_part);
+
+ return (((u_int64_t)high_part) << 32) + low_part;
+#endif
+}
+
+/**
+ * Special type to count references
+ */
+typedef volatile u_int refcount_t;
+
+
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+
+#define ref_get(ref) {__sync_fetch_and_add(ref, 1); }
+#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
+
+#define cas_bool(ptr, oldval, newval) \
+ (__sync_bool_compare_and_swap(ptr, oldval, newval))
+#define cas_ptr(ptr, oldval, newval) \
+ (__sync_bool_compare_and_swap(ptr, oldval, newval))
+
+#else /* !HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * Get a new reference.
+ *
+ * Increments the reference counter atomic.
+ *
+ * @param ref pointer to ref counter
+ */
+void ref_get(refcount_t *ref);
+
+/**
+ * Put back a unused reference.
+ *
+ * Decrements the reference counter atomic and
+ * says if more references available.
+ *
+ * @param ref pointer to ref counter
+ * @return TRUE if no more references counted
+ */
+bool ref_put(refcount_t *ref);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr pointer to variable
+ * @param oldval old value of the variable
+ * @param newval new value set if possible
+ * @return TRUE if value equaled oldval and newval was written
+ */
+bool cas_bool(bool *ptr, bool oldval, bool newval);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr pointer to variable
+ * @param oldval old value of the variable
+ * @param newval new value set if possible
+ * @return TRUE if value equaled oldval and newval was written
+ */
+bool cas_ptr(void **ptr, void *oldval, void *newval);
+
+#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * printf hook for time_t.
+ *
+ * Arguments are:
+ * time_t* time, bool utc
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * printf hook for time_t deltas.
+ *
+ * Arguments are:
+ * time_t* begin, time_t* end
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+/**
+ * printf hook for memory areas.
+ *
+ * Arguments are:
+ * u_char *ptr, u_int len
+ */
+int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+ const void *const *args);
+
+#endif /** UTILS_H_ @}*/