Here's a version without malloc'ing the key.
Index: usr.sbin/relayd/parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/parse.y,v
retrieving revision 1.195
diff -u -p -r1.195 parse.y
--- usr.sbin/relayd/parse.y 20 Nov 2014 05:51:20 -0000 1.195
+++ usr.sbin/relayd/parse.y 10 Dec 2014 02:12:02 -0000
@@ -30,7 +30,6 @@
#include <sys/stat.h>
#include <sys/queue.h>
#include <sys/ioctl.h>
-#include <sys/hash.h>
#include <net/if.h>
#include <net/pfvar.h>
@@ -52,6 +51,7 @@
#include <string.h>
#include <ifaddrs.h>
#include <syslog.h>
+#include <siphash.h>
#include <openssl/ssl.h>
Index: usr.sbin/relayd/relay.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay.c,v
retrieving revision 1.181
diff -u -p -r1.181 relay.c
--- usr.sbin/relayd/relay.c 19 Nov 2014 10:24:40 -0000 1.181
+++ usr.sbin/relayd/relay.c 10 Dec 2014 02:12:02 -0000
@@ -41,6 +41,7 @@
#include <pwd.h>
#include <event.h>
#include <fnmatch.h>
+#include <siphash.h>
#include <openssl/dh.h>
#include <openssl/ssl.h>
@@ -72,7 +73,7 @@ int relay_socket_connect(struct sockad
void relay_accept(int, short, void *);
void relay_input(struct rsession *);
-u_int32_t relay_hash_addr(struct sockaddr_storage *, u_int32_t);
+void relay_hash_addr(struct sockaddr_storage *, SIPHASH_CTX *);
DH * relay_ssl_get_dhparams(int);
void relay_ssl_callback_info(const SSL *, int, int);
@@ -441,16 +442,21 @@ relay_launch(void)
switch (rlt->rlt_mode) {
case RELAY_DSTMODE_ROUNDROBIN:
case RELAY_DSTMODE_RANDOM:
- rlt->rlt_key = 0;
+ rlt->rlt_rr_key = 0;
break;
case RELAY_DSTMODE_LOADBALANCE:
case RELAY_DSTMODE_HASH:
case RELAY_DSTMODE_SRCHASH:
- rlt->rlt_key =
- hash32_str(rlay->rl_conf.name, HASHINIT);
- rlt->rlt_key =
- hash32_str(rlt->rlt_table->conf.name,
- rlt->rlt_key);
+ if (sip_key == NULL) {
+ sip_key = malloc(SIPHASH_KEY_LENGTH);
+ arc4random_buf(sip_key,
SIPHASH_KEY_LENGTH);
+ }
+ SipHash24_Init(&rlt->rlt_ctx, sip_key);
+ SipHash24_Update(&rlt->rlt_ctx,
rlay->rl_conf.name,
+ strlen(rlay->rl_conf.name));
+ SipHash24_Update(&rlt->rlt_ctx,
+ rlt->rlt_table->conf.name,
+ strlen(rlt->rlt_table->conf.name));
break;
}
rlt->rlt_nhosts = 0;
@@ -1180,23 +1186,20 @@ relay_accept(int fd, short event, void *
}
}
-u_int32_t
-relay_hash_addr(struct sockaddr_storage *ss, u_int32_t p)
+void
+relay_hash_addr(struct sockaddr_storage *ss, SIPHASH_CTX *ctxp)
{
struct sockaddr_in *sin4;
struct sockaddr_in6 *sin6;
if (ss->ss_family == AF_INET) {
sin4 = (struct sockaddr_in *)ss;
- p = hash32_buf(&sin4->sin_addr,
- sizeof(struct in_addr), p);
+ SipHash24_Update(ctxp, &sin4->sin_addr, sizeof(struct in_addr));
} else {
sin6 = (struct sockaddr_in6 *)ss;
- p = hash32_buf(&sin6->sin6_addr,
- sizeof(struct in6_addr), p);
+ SipHash24_Update(ctxp, &sin6->sin6_addr,
+ sizeof(struct in6_addr));
}
-
- return (p);
}
int
@@ -1206,7 +1209,7 @@ relay_from_table(struct rsession *con)
struct host *host;
struct relay_table *rlt = NULL;
struct table *table = NULL;
- u_int32_t p = con->se_hashkey;
+ SIPHASH_CTX ctx = con->se_hashctx;
int idx = -1;
/* the table is already selected */
@@ -1234,16 +1237,16 @@ relay_from_table(struct rsession *con)
__func__, con->se_id);
return (-1);
}
- if (!con->se_hashkeyset) {
- p = con->se_hashkey = rlt->rlt_key;
- con->se_hashkeyset = 1;
+ if (!con->se_hashctxset) {
+ ctx = con->se_hashctx = rlt->rlt_ctx;
+ con->se_hashctxset = 1;
}
switch (rlt->rlt_mode) {
case RELAY_DSTMODE_ROUNDROBIN:
- if ((int)rlt->rlt_key >= rlt->rlt_nhosts)
- rlt->rlt_key = 0;
- idx = (int)rlt->rlt_key;
+ if ((int)rlt->rlt_rr_key >= rlt->rlt_nhosts)
+ rlt->rlt_rr_key = 0;
+ idx = (int)rlt->rlt_rr_key;
break;
case RELAY_DSTMODE_RANDOM:
idx = (int)arc4random_uniform(rlt->rlt_nhosts);
@@ -1251,21 +1254,22 @@ relay_from_table(struct rsession *con)
case RELAY_DSTMODE_SRCHASH:
case RELAY_DSTMODE_LOADBALANCE:
/* Source IP address without port */
- p = relay_hash_addr(&con->se_in.ss, p);
+ relay_hash_addr(&con->se_in.ss, &ctx);
if (rlt->rlt_mode == RELAY_DSTMODE_SRCHASH)
break;
/* FALLTHROUGH */
case RELAY_DSTMODE_HASH:
/* Local "destination" IP address and port */
- p = relay_hash_addr(&rlay->rl_conf.ss, p);
- p = hash32_buf(&rlay->rl_conf.port,
- sizeof(rlay->rl_conf.port), p);
+ relay_hash_addr(&rlay->rl_conf.ss, &ctx);
+ SipHash24_Update(&ctx, &rlay->rl_conf.port,
+ sizeof(rlay->rl_conf.port));
break;
default:
fatalx("relay_from_table: unsupported mode");
/* NOTREACHED */
}
- if (idx == -1 && (idx = p % rlt->rlt_nhosts) >= RELAY_MAXHOSTS)
+ if (idx == -1 && (idx = SipHash24_End(&ctx) % rlt->rlt_nhosts)
+ >= RELAY_MAXHOSTS)
return (-1);
host = rlt->rlt_host[idx];
DPRINTF("%s: session %d: table %s host %s, p 0x%08x, idx %d",
@@ -1289,7 +1293,7 @@ relay_from_table(struct rsession *con)
found:
if (rlt->rlt_mode == RELAY_DSTMODE_ROUNDROBIN)
- rlt->rlt_key = host->idx + 1;
+ rlt->rlt_rr_key = host->idx + 1;
con->se_retry = host->conf.retry;
con->se_out.port = table->conf.port;
bcopy(&host->conf.ss, &con->se_out.ss, sizeof(con->se_out.ss));
Index: usr.sbin/relayd/relay_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v
retrieving revision 1.35
diff -u -p -r1.35 relay_http.c
--- usr.sbin/relayd/relay_http.c 25 Oct 2014 03:23:49 -0000 1.35
+++ usr.sbin/relayd/relay_http.c 10 Dec 2014 02:12:03 -0000
@@ -41,6 +41,7 @@
#include <pwd.h>
#include <event.h>
#include <fnmatch.h>
+#include <siphash.h>
#include <openssl/ssl.h>
@@ -1487,12 +1488,19 @@ relay_apply_actions(struct ctl_relay_eve
value = match->kv_value;
break;
}
- if (!con->se_hashkeyset)
- con->se_hashkey = HASHINIT;
- con->se_hashkey = hash32_str(value, con->se_hashkey);
- con->se_hashkeyset = 1;
+ if (!con->se_hashctxset) {
+ if (sip_key == NULL) {
+ sip_key = malloc(SIPHASH_KEY_LENGTH);
+ arc4random_buf(sip_key,
SIPHASH_KEY_LENGTH);
+ }
+ }
+ SipHash_Init(&con->se_hashctx, sip_key);
+ SipHash24_Update(&con->se_hashctx, value,
strlen(value));
+ con->se_hashctxset = 1;
+ /*
log_debug("%s: hashkey 0x%04x", __func__,
- con->se_hashkey);
+ con->se_hashctx);
+ */
break;
case KEY_OPTION_LOG:
/* perform this later */
Index: usr.sbin/relayd/relay_udp.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay_udp.c,v
retrieving revision 1.34
diff -u -p -r1.34 relay_udp.c
--- usr.sbin/relayd/relay_udp.c 19 Nov 2014 10:24:40 -0000 1.34
+++ usr.sbin/relayd/relay_udp.c 10 Dec 2014 02:12:03 -0000
@@ -23,7 +23,6 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/tree.h>
-#include <sys/hash.h>
#include <net/if.h>
#include <netinet/in.h>
Index: usr.sbin/relayd/relayd.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v
retrieving revision 1.133
diff -u -p -r1.133 relayd.c
--- usr.sbin/relayd/relayd.c 22 Nov 2014 00:24:22 -0000 1.133
+++ usr.sbin/relayd/relayd.c 10 Dec 2014 02:12:03 -0000
@@ -22,7 +22,6 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/resource.h>
-#include <sys/hash.h>
#include <net/if.h>
#include <netinet/in.h>
Index: usr.sbin/relayd/relayd.h
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.197
diff -u -p -r1.197 relayd.h
--- usr.sbin/relayd/relayd.h 19 Nov 2014 10:24:40 -0000 1.197
+++ usr.sbin/relayd/relayd.h 10 Dec 2014 02:12:03 -0000
@@ -26,6 +26,7 @@
#include <sys/param.h> /* MAXHOSTNAMELEN */
#include <limits.h>
#include <imsg.h>
+#include <siphash.h> /* SIPHASH_KEY, SIPHASH_CTX */
#ifndef nitems
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
@@ -515,8 +516,8 @@ struct rsession {
struct ctl_relay_event se_in;
struct ctl_relay_event se_out;
void *se_priv;
- u_int32_t se_hashkey;
- int se_hashkeyset;
+ SIPHASH_CTX se_hashctx;
+ int se_hashctxset;
struct relay_table *se_table;
struct event se_ev;
struct timeval se_timeout;
@@ -695,11 +696,14 @@ struct protocol {
};
TAILQ_HEAD(protolist, protocol);
+SIPHASH_KEY *sip_key;
+
struct relay_table {
struct table *rlt_table;
u_int32_t rlt_flags;
int rlt_mode;
- u_int32_t rlt_key;
+ u_int32_t rlt_rr_key; /* round-robin */
+ SIPHASH_CTX rlt_ctx;
struct host *rlt_host[RELAY_MAXHOSTS];
int rlt_nhosts;
TAILQ_ENTRY(relay_table) rlt_entry;