
/*
 * Copyright (c) 2012-2014 Frank Denis <j at pureftpd dot org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

diff -urN djbdns-1.05/Makefile djbdns-1.05-jedi/Makefile
--- djbdns-1.05/Makefile	2001-02-11 13:11:45.000000000 -0800
+++ djbdns-1.05-jedi/Makefile	2012-06-26 23:47:51.000000000 -0700
@@ -153,8 +153,8 @@
 	./compile cache.c
 
 cachetest: \
-load cachetest.o cache.o libtai.a buffer.a alloc.a unix.a byte.a
-	./load cachetest cache.o libtai.a buffer.a alloc.a unix.a \
+load cachetest.o siphash.o cache.o dns_random.o libtai.a buffer.a alloc.a unix.a byte.a
+	./load cachetest siphash.o cache.o dns_random.o libtai.a buffer.a alloc.a unix.a \
 	byte.a 
 
 cachetest.o: \
@@ -318,10 +318,10 @@
 	./compile dns_txt.c
 
 dnscache: \
-load dnscache.o droproot.o okclient.o log.o cache.o query.o \
+load dnscache.o droproot.o okclient.o log.o siphash.o cache.o dns_random.o query.o \
 response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \
 libtai.a unix.a byte.a socket.lib
-	./load dnscache droproot.o okclient.o log.o cache.o \
+	./load dnscache droproot.o okclient.o log.o siphash.o cache.o dns_random.o \
 	query.o response.o dd.o roots.o iopause.o prot.o dns.a \
 	env.a alloc.a buffer.a libtai.a unix.a byte.a  `cat \
 	socket.lib`
diff -urN djbdns-1.05/cache.c djbdns-1.05-jedi/cache.c
--- djbdns-1.05/cache.c	2001-02-11 13:11:45.000000000 -0800
+++ djbdns-1.05-jedi/cache.c	2012-06-27 00:02:19.000000000 -0700
@@ -1,12 +1,16 @@
 #include "alloc.h"
 #include "byte.h"
+#include "dns.h"
 #include "uint32.h"
+#include "uint64.h"
 #include "exit.h"
 #include "tai.h"
 #include "cache.h"
+#include "siphash.h"
 
 uint64 cache_motion = 0;
 
+static unsigned char siphash_key[16];
 static char *x = 0;
 static uint32 size;
 static uint32 hsize;
@@ -64,17 +68,11 @@
 
 static unsigned int hash(const char *key,unsigned int keylen)
 {
-  unsigned int result = 5381;
+  uint64 h;    
+  siphash24((unsigned char *) &h,
+            (const unsigned char *) key, keylen, siphash_key);
 
-  while (keylen) {
-    result = (result << 5) + result;
-    result ^= (unsigned char) *key;
-    ++key;
-    --keylen;
-  }
-  result <<= 2;
-  result &= hsize - 4;
-  return result;
+  return ((uint32) h) & (hsize - 4);
 }
 
 char *cache_get(const char *key,unsigned int keylen,unsigned int *datalen,uint32 *ttl)
@@ -183,6 +181,10 @@
 
 int cache_init(unsigned int cachesize)
 {
+  unsigned int i = 0U;
+  do {
+    siphash_key[i] = (unsigned char) dns_random(0x100);
+  } while (++i < sizeof siphash_key);
   if (x) {
     alloc_free(x);
     x = 0;
diff -urN djbdns-1.05/siphash.c djbdns-1.05-jedi/siphash.c
--- djbdns-1.05/siphash.c	1969-12-31 16:00:00.000000000 -0800
+++ djbdns-1.05-jedi/siphash.c	2012-06-26 23:57:48.000000000 -0700
@@ -0,0 +1,100 @@
+ 
+#include <stdio.h>
+#include <string.h>
+#include "uint32.h"
+#include "uint64.h"
+#include "siphash.h"
+
+typedef uint64 u64;
+typedef uint32 u32;
+typedef unsigned char u8;
+
+#define ROTL(x,b) (u64)( ((x) << (b)) | ( (x) >> (64 - (b))) )
+
+#define U32TO8_LE(p, v)         \
+    (p)[0] = (u8)((v)      ); (p)[1] = (u8)((v) >>  8); \
+    (p)[2] = (u8)((v) >> 16); (p)[3] = (u8)((v) >> 24);
+
+#define U64TO8_LE(p, v)         \
+  U32TO8_LE((p),     (u32)((v)      ));   \
+  U32TO8_LE((p) + 4, (u32)((v) >> 32));
+
+#define U8TO64_LE(p) \
+  (((u64)((p)[0])      ) | \
+   ((u64)((p)[1]) <<  8) | \
+   ((u64)((p)[2]) << 16) | \
+   ((u64)((p)[3]) << 24) | \
+   ((u64)((p)[4]) << 32) | \
+   ((u64)((p)[5]) << 40) | \
+   ((u64)((p)[6]) << 48) | \
+   ((u64)((p)[7]) << 56))
+
+#define SIPROUND            \
+  do {              \
+    x0 += x1; x1=ROTL(x1,13); x1 ^= x0; x0=ROTL(x0,32); \
+    x2 += x3; x3=ROTL(x3,16); x3 ^= x2;     \
+    x0 += x3; x3=ROTL(x3,21); x3 ^= x0;     \
+    x2 += x1; x1=ROTL(x1,17); x1 ^= x2; x2=ROTL(x2,32); \
+  } while(0)
+
+/* SipHash-2-4 */
+int siphash24( unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k )
+{
+  /* "somepseudorandomlygeneratedbytes" */
+  u64 x0 = 0x736f6d6570736575ULL;
+  u64 x1 = 0x646f72616e646f6dULL;
+  u64 x2 = 0x6c7967656e657261ULL;
+  u64 x3 = 0x7465646279746573ULL;
+  u64 b;
+  u64 k0 = U8TO64_LE( k );
+  u64 k1 = U8TO64_LE( k + 8 );
+  u64 m;
+  const u8 *end = in + inlen - ( inlen % sizeof( u64 ) );
+  const int left = inlen & 7;
+  b = ( ( u64 )inlen ) << 56;
+  x3 ^= k1;
+  x2 ^= k0;
+  x1 ^= k1;
+  x0 ^= k0;
+
+  for ( ; in != end; in += 8 )
+  {
+    m = U8TO64_LE( in );
+    x3 ^= m;
+    SIPROUND;
+    SIPROUND;
+    x0 ^= m;
+  }
+
+  switch( left )
+  {
+  case 7: b |= ( ( u64 )in[ 6] )  << 48;
+
+  case 6: b |= ( ( u64 )in[ 5] )  << 40;
+
+  case 5: b |= ( ( u64 )in[ 4] )  << 32;
+
+  case 4: b |= ( ( u64 )in[ 3] )  << 24;
+
+  case 3: b |= ( ( u64 )in[ 2] )  << 16;
+
+  case 2: b |= ( ( u64 )in[ 1] )  <<  8;
+
+  case 1: b |= ( ( u64 )in[ 0] ); break;
+
+  case 0: break;
+  }
+
+  x3 ^= b;
+  SIPROUND;
+  SIPROUND;
+  x0 ^= b;
+  x2 ^= 0xff;
+  SIPROUND;
+  SIPROUND;
+  SIPROUND;
+  SIPROUND;
+  b = x0 ^ x1 ^ x2  ^ x3;
+  U64TO8_LE( out, b );
+  return 0;
+}
diff -urN djbdns-1.05/siphash.h djbdns-1.05-jedi/siphash.h
--- djbdns-1.05/siphash.h	1969-12-31 16:00:00.000000000 -0800
+++ djbdns-1.05-jedi/siphash.h	2012-06-26 23:57:44.000000000 -0700
@@ -0,0 +1,7 @@
+
+#ifndef SIPHASH_H
+#define SIPHASH_H
+
+int siphash24( unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *k );
+
+#endif
