/* * 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 . * * 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 #include #include #include #include #include #include "enum.h" #include "utils/strerror.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 #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; } /** * 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; } /** * 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 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; 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; /** * 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); /** * 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); /** * 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. * * @param lowfd start closing file descriptors 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(); /** * 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 /** * 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_ @}*/