this uses siphash to protect the in_pcb hashes. this is pretty much
a textbook example of what siphash should be used for.
tests? ok?
Index: conf/files
===================================================================
RCS file: /cvs/src/sys/conf/files,v
retrieving revision 1.583
diff -u -p -r1.583 files
--- conf/files 20 Oct 2014 00:38:50 -0000 1.583
+++ conf/files 4 Nov 2014 04:47:11 -0000
@@ -873,6 +873,7 @@ file crypto/hmac.c wlan | (softraid &
file crypto/gmac.c (inet & ipsec) | crypto
file crypto/key_wrap.c wlan
file crypto/idgen.c inet6 | nfsclient | nfsserver
+file crypto/siphash.c
file netmpls/mpls_input.c mpls
file netmpls/mpls_output.c mpls
file netmpls/mpls_proto.c mpls
Index: netinet/in_pcb.c
===================================================================
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.160
diff -u -p -r1.160 in_pcb.c
--- netinet/in_pcb.c 14 Oct 2014 09:52:26 -0000 1.160
+++ netinet/in_pcb.c 4 Nov 2014 04:47:11 -0000
@@ -91,6 +91,7 @@
#include <netinet/ip_var.h>
#include <dev/rndvar.h>
+
#include <sys/mount.h>
#include <nfs/nfsproto.h>
@@ -121,17 +122,68 @@ int in_pcbresize (struct inpcbtable *, i
#define INPCBHASH_LOADFACTOR(_x) (((_x) * 3) / 4)
+struct inpcbhead *in_pcbhash(struct inpcbtable *, int,
+ const struct in_addr *, u_short, const struct in_addr *, u_short);
+struct inpcbhead *in6_pcbhash(struct inpcbtable *, int,
+ const struct in6_addr *, u_short, const struct in6_addr *, u_short);
+struct inpcbhead *in_pcblhash(struct inpcbtable *, int, u_short);
+
+struct inpcbhead *
+in_pcbhash(struct inpcbtable *table, int rdom,
+ const struct in_addr *faddr, u_short fport,
+ const struct in_addr *laddr, u_short lport)
+{
+ SIPHASH_CTX ctx;
+ u_int32_t nrdom = htonl(rdom);
+
+ SipHash24_Init(&ctx, &table->inpt_key);
+ SipHash24_Update(&ctx, &nrdom, sizeof(nrdom));
+ SipHash24_Update(&ctx, faddr, sizeof(*faddr));
+ SipHash24_Update(&ctx, &fport, sizeof(fport));
+ SipHash24_Update(&ctx, laddr, sizeof(*laddr));
+ SipHash24_Update(&ctx, &lport, sizeof(lport));
+
+ return (&table->inpt_hashtbl[SipHash24_End(&ctx) & table->inpt_hash]);
+}
+
#define INPCBHASH(table, faddr, fport, laddr, lport, rdom) \
- &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \
- ntohs((fport)) + ntohs((lport)) + (rdom)) & (table->inpt_hash)]
+ in_pcbhash(table, rdom, faddr, fport, laddr, lport)
+
+struct inpcbhead *
+in6_pcbhash(struct inpcbtable *table, int rdom,
+ const struct in6_addr *faddr, u_short fport,
+ const struct in6_addr *laddr, u_short lport)
+{
+ SIPHASH_CTX ctx;
+ u_int32_t nrdom = htonl(rdom);
+
+ SipHash24_Init(&ctx, &table->inpt_key);
+ SipHash24_Update(&ctx, &nrdom, sizeof(nrdom));
+ SipHash24_Update(&ctx, faddr, sizeof(*faddr));
+ SipHash24_Update(&ctx, &fport, sizeof(fport));
+ SipHash24_Update(&ctx, laddr, sizeof(*laddr));
+ SipHash24_Update(&ctx, &lport, sizeof(lport));
+
+ return (&table->inpt_hashtbl[SipHash24_End(&ctx) & table->inpt_hash]);
+}
#define IN6PCBHASH(table, faddr, fport, laddr, lport, rdom) \
- &(table)->inpt_hashtbl[(ntohl((faddr)->s6_addr32[0] ^ \
- (faddr)->s6_addr32[3]) + ntohs((fport)) + ntohs((lport)) + (rdom)) & \
- (table->inpt_hash)]
+ in6_pcbhash(table, rdom, faddr, fport, laddr, lport)
+
+struct inpcbhead *
+in_pcblhash(struct inpcbtable *table, int rdom, u_short lport)
+{
+ SIPHASH_CTX ctx;
+ u_int32_t nrdom = htonl(rdom);
+
+ SipHash24_Init(&ctx, &table->inpt_key);
+ SipHash24_Update(&ctx, &nrdom, sizeof(nrdom));
+ SipHash24_Update(&ctx, &lport, sizeof(lport));
+
+ return (&table->inpt_lhashtbl[SipHash24_End(&ctx) & table->inpt_lhash]);
+}
-#define INPCBLHASH(table, lport, rdom) \
- &(table)->inpt_lhashtbl[(ntohs((lport)) + (rdom)) & table->inpt_lhash]
+#define INPCBLHASH(table, lport, rdom) in_pcblhash(table, rdom, lport)
void
in_pcbinit(struct inpcbtable *table, int hashsize)
@@ -148,6 +200,7 @@ in_pcbinit(struct inpcbtable *table, int
panic("in_pcbinit: hashinit failed for lport");
table->inpt_lastport = 0;
table->inpt_count = 0;
+ arc4random_buf(&table->inpt_key, sizeof(table->inpt_key));
}
/*
@@ -914,6 +967,7 @@ in_pcbresize(struct inpcbtable *table, i
table->inpt_lhashtbl = nlhashtbl;
table->inpt_hash = nhash;
table->inpt_lhash = nlhash;
+ arc4random_buf(&table->inpt_key, sizeof(table->inpt_key));
TAILQ_FOREACH_SAFE(inp0, &table->inpt_queue, inp_queue, inp1) {
in_pcbrehash(inp0);
Index: netinet/in_pcb.h
===================================================================
RCS file: /cvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.86
diff -u -p -r1.86 in_pcb.h
--- netinet/in_pcb.h 12 Jul 2014 21:06:34 -0000 1.86
+++ netinet/in_pcb.h 4 Nov 2014 04:47:11 -0000
@@ -70,6 +70,8 @@
#include <netinet/icmp6.h>
#include <netinet/ip_ipsp.h>
+#include <crypto/siphash.h>
+
struct pf_state_key;
union inpaddru {
@@ -153,9 +155,12 @@ struct inpcb {
int inp_divertfl; /* divert flags */
};
+LIST_HEAD(inpcbhead, inpcb);
+
struct inpcbtable {
TAILQ_HEAD(inpthead, inpcb) inpt_queue;
- LIST_HEAD(inpcbhead, inpcb) *inpt_hashtbl, *inpt_lhashtbl;
+ struct inpcbhead *inpt_hashtbl, *inpt_lhashtbl;
+ SIPHASH_KEY inpt_key;
u_long inpt_hash, inpt_lhash;
u_int16_t inpt_lastport;
int inpt_count;