Index: tcp_input.c =================================================================== RCS file: /cvs/src/sys/netinet/tcp_input.c,v retrieving revision 1.297 diff -u -p -r1.297 tcp_input.c --- tcp_input.c 16 Jul 2015 16:12:15 -0000 1.297 +++ tcp_input.c 31 Jul 2015 06:50:01 -0000 @@ -96,6 +96,8 @@ #include #include +#include + #if NPF > 0 #include #endif @@ -3277,43 +3279,66 @@ tcp_mss_adv(struct ifnet *ifp, int af) */ u_long syn_cache_count; -u_int32_t syn_hash1, syn_hash2; +SIPHASH_KEY tcp_syn_cache_key; + +uint64_t tcp_syn_hash4(const struct sockaddr_in *, + const struct sockaddr_in *); -#define SYN_HASH(sa, sp, dp) \ - ((((sa)->s_addr^syn_hash1)*(((((u_int32_t)(dp))<<16) + \ - ((u_int32_t)(sp)))^syn_hash2))) #ifndef INET6 #define SYN_HASHALL(hash, src, dst) \ do { \ - hash = SYN_HASH(&((struct sockaddr_in *)(src))->sin_addr, \ - ((struct sockaddr_in *)(src))->sin_port, \ - ((struct sockaddr_in *)(dst))->sin_port); \ + hash = tcp_syn_hash4((struct sockaddr_in *)(src), \ + (struct sockaddr_in *)(dst)); \ } while (/*CONSTCOND*/ 0) #else -#define SYN_HASH6(sa, sp, dp) \ - ((((sa)->s6_addr32[0] ^ (sa)->s6_addr32[3] ^ syn_hash1) * \ - (((((u_int32_t)(dp))<<16) + ((u_int32_t)(sp)))^syn_hash2)) \ - & 0x7fffffff) +uint64_t tcp_syn_hash6(const struct sockaddr_in6 *, + const struct sockaddr_in6 *); #define SYN_HASHALL(hash, src, dst) \ do { \ switch ((src)->sa_family) { \ case AF_INET: \ - hash = SYN_HASH(&((struct sockaddr_in *)(src))->sin_addr, \ - ((struct sockaddr_in *)(src))->sin_port, \ - ((struct sockaddr_in *)(dst))->sin_port); \ + hash = tcp_syn_hash4((struct sockaddr_in *)(src), \ + (struct sockaddr_in *)(dst)); \ break; \ case AF_INET6: \ - hash = SYN_HASH6(&((struct sockaddr_in6 *)(src))->sin6_addr, \ - ((struct sockaddr_in6 *)(src))->sin6_port, \ - ((struct sockaddr_in6 *)(dst))->sin6_port); \ + hash = tcp_syn_hash6((struct sockaddr_in6 *)(src), \ + (struct sockaddr_in6 *)(dst)); \ break; \ default: \ hash = 0; \ } \ } while (/*CONSTCOND*/0) + +uint64_t +tcp_syn_hash6(const struct sockaddr_in6 *src, const struct sockaddr_in6 *dst) +{ + SIPHASH_CTX ctx; + + SipHash24_Init(&ctx, &tcp_syn_cache_key); + SipHash24_Update(&ctx, &src->sin6_family, sizeof(src->sin6_family)); + SipHash24_Update(&ctx, &src->sin6_addr, sizeof(src->sin6_addr)); + SipHash24_Update(&ctx, &src->sin6_port, sizeof(src->sin6_port)); + SipHash24_Update(&ctx, &dst->sin6_port, sizeof(dst->sin6_port)); + + return (SipHash24_End(&ctx)); +} #endif /* INET6 */ +uint64_t +tcp_syn_hash4(const struct sockaddr_in *src, const struct sockaddr_in *dst) +{ + SIPHASH_CTX ctx; + + SipHash24_Init(&ctx, &tcp_syn_cache_key); + SipHash24_Update(&ctx, &src->sin_family, sizeof(src->sin_family)); + SipHash24_Update(&ctx, &src->sin_addr, sizeof(src->sin_addr)); + SipHash24_Update(&ctx, &src->sin_port, sizeof(src->sin_port)); + SipHash24_Update(&ctx, &dst->sin_port, sizeof(dst->sin_port)); + + return (SipHash24_End(&ctx)); +} + void syn_cache_rm(struct syn_cache *sc) { @@ -3363,6 +3388,8 @@ syn_cache_init() { int i; + arc4random_buf(&tcp_syn_cache_key, sizeof(tcp_syn_cache_key)); + /* Initialize the hash buckets. */ for (i = 0; i < tcp_syn_cache_size; i++) TAILQ_INIT(&tcp_syn_cache[i].sch_bucket); @@ -3378,15 +3405,6 @@ syn_cache_insert(struct syn_cache *sc, s struct syn_cache_head *scp; struct syn_cache *sc2; int s; - - /* - * If there are no entries in the hash table, reinitialize - * the hash secrets. - */ - if (syn_cache_count == 0) { - syn_hash1 = arc4random(); - syn_hash2 = arc4random(); - } SYN_HASHALL(sc->sc_hash, &sc->sc_src.sa, &sc->sc_dst.sa); sc->sc_bucketidx = sc->sc_hash % tcp_syn_cache_size;