diff options
author | Tobias Brunner <tobias@strongswan.org> | 2008-11-25 13:16:05 +0000 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2008-11-25 13:16:05 +0000 |
commit | ed6146ffbe3c798a49ff178d4448548240cbeb38 (patch) | |
tree | dbdf7166dcebbb1d121b9da89f5802cd1d6c1472 /src/libstrongswan/chunk.c | |
parent | 28dd27be64d5a22fb37e95d9bf0358aa8b7ce024 (diff) | |
download | strongswan-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.c | 82 |
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, |