use siphash for pf_lb. for ipv6, we stretch it out a bit, but good enough.
authortedu <tedu@openbsd.org>
Thu, 18 Dec 2014 19:02:56 +0000 (19:02 +0000)
committertedu <tedu@openbsd.org>
Thu, 18 Dec 2014 19:02:56 +0000 (19:02 +0000)
ok reyk

sys/net/pf_lb.c

index 392fa85..bbaa298 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_lb.c,v 1.36 2014/11/18 02:37:31 tedu Exp $ */
+/*     $OpenBSD: pf_lb.c,v 1.37 2014/12/18 19:02:56 tedu Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -53,6 +53,7 @@
 #include <sys/syslog.h>
 #include <sys/stdint.h>
 
+#include <crypto/siphash.h>
 #include <crypto/md5.h>
 
 #include <net/if.h>
@@ -103,19 +104,6 @@ int                         pf_map_addr_sticky(sa_family_t, struct pf_rule *,
                            struct pf_src_node **, struct pf_pool *,
                            enum pf_sn_types);
 
-#define mix(a,b,c) \
-       do {                                    \
-               a -= b; a -= c; a ^= (c >> 13); \
-               b -= c; b -= a; b ^= (a << 8);  \
-               c -= a; c -= b; c ^= (b >> 13); \
-               a -= b; a -= c; a ^= (c >> 12); \
-               b -= c; b -= a; b ^= (a << 16); \
-               c -= a; c -= b; c ^= (b >> 5);  \
-               a -= b; a -= c; a ^= (c >> 3);  \
-               b -= c; b -= a; b ^= (a << 10); \
-               c -= a; c -= b; c ^= (b >> 15); \
-       } while (0)
-
 /*
  * hash function based on bridge_hash in if_bridge.c
  */
@@ -123,38 +111,32 @@ void
 pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
     struct pf_poolhashkey *key, sa_family_t af)
 {
-       u_int32_t       a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
+#ifdef INET6
+       union {
+               uint64_t hash64;
+               uint32_t hash32[2];
+       } h;
+#endif
 
        switch (af) {
 #ifdef INET
        case AF_INET:
-               a += inaddr->addr32[0];
-               b += key->key32[1];
-               mix(a, b, c);
-               hash->addr32[0] = c + key->key32[2];
+               hash->addr32[0] = SipHash24((SIPHASH_KEY *)key,
+                   &inaddr->addr32[0], sizeof(inaddr->addr32[0]));
                break;
 #endif /* INET */
 #ifdef INET6
        case AF_INET6:
-               a += inaddr->addr32[0];
-               b += inaddr->addr32[2];
-               mix(a, b, c);
-               hash->addr32[0] = c;
-               a += inaddr->addr32[1];
-               b += inaddr->addr32[3];
-               c += key->key32[1];
-               mix(a, b, c);
-               hash->addr32[1] = c;
-               a += inaddr->addr32[2];
-               b += inaddr->addr32[1];
-               c += key->key32[2];
-               mix(a, b, c);
-               hash->addr32[2] = c;
-               a += inaddr->addr32[3];
-               b += inaddr->addr32[0];
-               c += key->key32[3];
-               mix(a, b, c);
-               hash->addr32[3] = c;
+               h.hash64 = SipHash24((SIPHASH_KEY *)key, &inaddr->addr32[0],
+                   4 * sizeof(inaddr->addr32[0]));
+               hash->addr32[0] = h.hash32[0];
+               hash->addr32[1] = h.hash32[1];
+               /*
+                * siphash isn't big enough, but flipping it around is
+                * good enough here.
+                */
+               hash->addr32[2] = ~h.hash32[1];
+               hash->addr32[3] = ~h.hash32[0];
                break;
 #endif /* INET6 */
        }