aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/chunk.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2008-11-25 13:16:05 +0000
committerTobias Brunner <tobias@strongswan.org>2008-11-25 13:16:05 +0000
commited6146ffbe3c798a49ff178d4448548240cbeb38 (patch)
treedbdf7166dcebbb1d121b9da89f5802cd1d6c1472 /src/libstrongswan/chunk.c
parent28dd27be64d5a22fb37e95d9bf0358aa8b7ce024 (diff)
downloadstrongswan-ed6146ffbe3c798a49ff178d4448548240cbeb38.tar.bz2
strongswan-ed6146ffbe3c798a49ff178d4448548240cbeb38.tar.xz
performance optimization for the DOS protection.
* half-open SAs per peer are tracked in a hash table * charon.dos_protection setting replaced with charon.cookie_threshold and charon.block_threshold * chunk_hash function added
Diffstat (limited to 'src/libstrongswan/chunk.c')
-rw-r--r--src/libstrongswan/chunk.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
index 4cd2c573e..e23450259 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
@@ -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.
*/
@@ -251,7 +262,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)
@@ -483,6 +494,75 @@ bool chunk_equals(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(chunk_t chunk)
+{
+ u_char *data = chunk.ptr;
+ size_t len = chunk.len;
+ u_int32_t hash = len, 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;
+}
+
+/**
* output handler in printf() for chunks
*/
static int chunk_print(FILE *stream, const struct printf_info *info,