summaryrefslogtreecommitdiff
path: root/src/libstrongswan/chunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/chunk.c')
-rw-r--r--src/libstrongswan/chunk.c135
1 files changed, 86 insertions, 49 deletions
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
index 565f48fb0..681581af9 100644
--- a/src/libstrongswan/chunk.c
+++ b/src/libstrongswan/chunk.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2008 Tobias Brunner
* Copyright (C) 2005-2006 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -13,7 +14,7 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
- * $Id: chunk.c 4276 2008-08-22 10:44:51Z martin $
+ * $Id: chunk.c 4784 2008-12-10 13:43:51Z tobias $
*/
#include <stdio.h>
@@ -26,6 +27,16 @@
#include <debug.h>
#include <printf_hook.h>
+/* required for chunk_hash */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__))
+#define get16bits(d) (*((const u_int16_t*)(d)))
+#endif
+#if !defined (get16bits)
+#define get16bits(d) ((((u_int32_t)(((const u_int8_t*)(d))[1])) << 8)\
+ + (u_int32_t)(((const u_int8_t*)(d))[0]) )
+#endif
+
/**
* Empty chunk.
*/
@@ -34,15 +45,6 @@ chunk_t chunk_empty = { NULL, 0 };
/**
* Described in header.
*/
-chunk_t chunk_create(u_char *ptr, size_t len)
-{
- chunk_t chunk = {ptr, len};
- return chunk;
-}
-
-/**
- * Described in header.
- */
chunk_t chunk_create_clone(u_char *ptr, chunk_t chunk)
{
chunk_t clone = chunk_empty;
@@ -132,7 +134,7 @@ chunk_t chunk_create_cat(u_char *ptr, const char* mode, ...)
void chunk_split(chunk_t chunk, const char *mode, ...)
{
va_list chunks;
- size_t len;
+ u_int len;
chunk_t *ch;
va_start(chunks, mode);
@@ -142,7 +144,7 @@ void chunk_split(chunk_t chunk, const char *mode, ...)
{
break;
}
- len = va_arg(chunks, size_t);
+ len = va_arg(chunks, u_int);
ch = va_arg(chunks, chunk_t*);
/* a null chunk means skip len bytes */
if (ch == NULL)
@@ -251,7 +253,7 @@ static char hexdig_lower[] = "0123456789abcdef";
*/
chunk_t chunk_to_hex(chunk_t chunk, char *buf, bool uppercase)
{
- int i, len;;
+ int i, len;
char *hexdig = hexdig_lower;
if (uppercase)
@@ -428,39 +430,6 @@ chunk_t chunk_from_base64(chunk_t base64, char *buf)
/**
* Described in header.
*/
-void chunk_free(chunk_t *chunk)
-{
- free(chunk->ptr);
- chunk->ptr = NULL;
- chunk->len = 0;
-}
-
-/**
- * Described in header.
- */
-void chunk_clear(chunk_t *chunk)
-{
- memset(chunk->ptr, 0, chunk->len);
- chunk_free(chunk);
-}
-
-/**
- * Described in header.
- */
-chunk_t chunk_skip(chunk_t chunk, size_t bytes)
-{
- if (chunk.len > bytes)
- {
- chunk.ptr += bytes;
- chunk.len -= bytes;
- return chunk;
- }
- return chunk_empty;
-}
-
-/**
- * Described in header.
- */
int chunk_compare(chunk_t a, chunk_t b)
{
int compare_len = a.len - b.len;
@@ -475,11 +444,79 @@ int chunk_compare(chunk_t a, chunk_t b)
/**
* Described in header.
+ *
+ * The implementation is based on Paul Hsieh's SuperFastHash:
+ * http://www.azillionmonkeys.com/qed/hash.html
+ */
+u_int32_t chunk_hash_inc(chunk_t chunk, u_int32_t hash)
+{
+ u_char *data = chunk.ptr;
+ size_t len = chunk.len;
+ u_int32_t tmp;
+ int rem;
+
+ if (!len || data == NULL)
+ {
+ return 0;
+ }
+
+ rem = len & 3;
+ len >>= 2;
+
+ /* Main loop */
+ for (; len > 0; --len)
+ {
+ hash += get16bits(data);
+ tmp = (get16bits(data + 2) << 11) ^ hash;
+ hash = (hash << 16) ^ tmp;
+ data += 2 * sizeof(u_int16_t);
+ hash += hash >> 11;
+ }
+
+ /* Handle end cases */
+ switch (rem)
+ {
+ case 3:
+ {
+ hash += get16bits(data);
+ hash ^= hash << 16;
+ hash ^= data[sizeof(u_int16_t)] << 18;
+ hash += hash >> 11;
+ break;
+ }
+ case 2:
+ {
+ hash += get16bits(data);
+ hash ^= hash << 11;
+ hash += hash >> 17;
+ break;
+ }
+ case 1:
+ {
+ hash += *data;
+ hash ^= hash << 10;
+ hash += hash >> 1;
+ break;
+ }
+ }
+
+ /* Force "avalanching" of final 127 bits */
+ hash ^= hash << 3;
+ hash += hash >> 5;
+ hash ^= hash << 4;
+ hash += hash >> 17;
+ hash ^= hash << 25;
+ hash += hash >> 6;
+
+ return hash;
+}
+
+/**
+ * Described in header.
*/
-bool chunk_equals(chunk_t a, chunk_t b)
+u_int32_t chunk_hash(chunk_t chunk)
{
- return a.ptr != NULL && b.ptr != NULL &&
- a.len == b.len && memeq(a.ptr, b.ptr, a.len);
+ return chunk_hash_inc(chunk, chunk.len);
}
/**