memory: Move memory manipulation related functions to separate files
authorMartin Willi <martin@revosec.ch>
Wed, 15 Apr 2015 14:15:32 +0000 (16:15 +0200)
committerMartin Willi <martin@revosec.ch>
Thu, 16 Apr 2015 12:50:02 +0000 (14:50 +0200)
src/libstrongswan/Android.mk
src/libstrongswan/Makefile.am
src/libstrongswan/utils/utils.c
src/libstrongswan/utils/utils.h
src/libstrongswan/utils/utils/memory.c [new file with mode: 0644]
src/libstrongswan/utils/utils/memory.h [new file with mode: 0644]

index 8ead333..7111218 100644 (file)
@@ -40,7 +40,7 @@ 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/utils/atomics.c utils/utils/string.c
+utils/utils/atomics.c utils/utils/string.c utils/utils/memory.c
 
 libstrongswan_la_SOURCES += \
     threading/thread.c \
index dda4a88..95e2b82 100644 (file)
@@ -38,7 +38,7 @@ 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/utils/atomics.c utils/utils/string.c
+utils/utils/atomics.c utils/utils/string.c utils/utils/memory.c
 
 if !USE_WINDOWS
   libstrongswan_la_SOURCES += \
@@ -109,7 +109,7 @@ 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/atomics.h utils/utils/types.h utils/utils/byteorder.h \
-utils/utils/string.h
+utils/utils/string.h utils/utils/memory.h
 endif
 
 library.lo :   $(top_builddir)/config.status
index 14eff33..497e051 100644 (file)
@@ -101,120 +101,6 @@ void free_align(void *ptr)
        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;
-}
-
 #ifdef WIN32
 
 /**
@@ -649,50 +535,6 @@ void nop()
 {
 }
 
-#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
  */
@@ -781,64 +623,3 @@ int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
        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;
-}
index 138d5e9..19d5a5f 100644 (file)
@@ -79,6 +79,7 @@
 #include "utils/atomics.h"
 #include "utils/byteorder.h"
 #include "utils/string.h"
+#include "utils/memory.h"
 #include "utils/strerror.h"
 #ifdef __APPLE__
 # include "compat/apple.h"
@@ -104,61 +105,6 @@ void utils_init();
 void utils_deinit();
 
 /**
- * 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) ({ \
@@ -478,83 +424,6 @@ void* malloc_align(size_t size, u_int8_t align);
 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
-
-/**
  * Portable function to wait for SIGINT/SIGTERM (or equivalent).
  */
 void wait_sigint();
@@ -696,23 +565,6 @@ static inline size_t round_down(size_t size, size_t alignment)
        return size - (size % alignment);
 }
 
-#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.
  *
@@ -731,13 +583,4 @@ int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
 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/memory.c b/src/libstrongswan/utils/utils/memory.c
new file mode 100644 (file)
index 0000000..a153715
--- /dev/null
@@ -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 (file)
index 0000000..aef318f
--- /dev/null
@@ -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_ @} */