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;

Reply via email to