1 /****************************************************************************
2  *
3  * Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
4  * Copyright (C) 2003-2013 Sourcefire, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License Version 2 as
8  * published by the Free Software Foundation.  You may not use, modify or
9  * distribute this program under any other version of the GNU General
10  * Public License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *
21  ****************************************************************************/
22 
23 /*
24      sfhashfcn.c
25 
26      Each hash table must allocate it's own SFGHASH struct, this is because
27      sfghash_new uses the number of rows in the hash table to modulo the random
28      values.
29 
30      Updates:
31 
32      8/31/2006 - man - changed to use sfprimetable.c
33 */
34 
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 
39 #include "sf_types.h"
40 
41 
42 #ifndef MODULUS_HASH
43 # include "snort.h"
44 #endif
45 
46 #include "sfhashfcn.h"
47 #include "sfprimetable.h"
48 
49 
sfhashfcn_new(int m)50 SFHASHFCN * sfhashfcn_new( int m )
51 {
52     SFHASHFCN * p;
53     static int one=1;
54 
55     if( one ) /* one time init */
56     {
57         srand( (unsigned) time(0) );
58         one = 0;
59     }
60 
61     // This can make all of the hashing static for testing.
62     //#define rand() 0
63 
64     p = (SFHASHFCN*) calloc( 1,sizeof(SFHASHFCN) );
65     if( !p )
66         return 0;
67 
68 #ifndef MODULUS_HASH
69 #ifndef DYNAMIC_PREPROC_CONTEXT
70     if (ScStaticHash())
71     {
72         sfhashfcn_static(p);
73     }
74     else
75 #endif
76 #endif
77     {
78         p->seed     = sf_nearest_prime( (rand()%m)+3191 );
79         p->scale    = sf_nearest_prime( (rand()%m)+709 );
80         p->hardener = (rand()*rand()) + 133824503;
81     }
82 
83     p->hash_fcn   = &sfhashfcn_hash;
84     p->keycmp_fcn = &memcmp;
85 
86     return p;
87 }
88 
sfhashfcn_free(SFHASHFCN * p)89 void sfhashfcn_free( SFHASHFCN * p )
90 {
91    if( p )
92    {
93        free( p);
94    }
95 }
96 
sfhashfcn_static(SFHASHFCN * p)97 void sfhashfcn_static( SFHASHFCN * p )
98 {
99     p->seed     = 3193;
100     p->scale    = 719;
101     p->hardener = 133824503;
102 }
103 
sfhashfcn_hash(SFHASHFCN * p,unsigned char * d,int n)104 unsigned sfhashfcn_hash( SFHASHFCN * p, unsigned char *d, int n )
105 {
106     unsigned hash = p->seed;
107     while( n )
108     {
109         hash *=  p->scale;
110         hash += *d++;
111         n--;
112     }
113     return hash ^ p->hardener;
114 }
115 
116 /**
117  * Make sfhashfcn use a separate set of operators for the backend.
118  *
119  * @param h sfhashfcn ptr
120  * @param hash_fcn user specified hash function
121  * @param keycmp_fcn user specified key comparisoin function
122  */
sfhashfcn_set_keyops(SFHASHFCN * h,unsigned (* hash_fcn)(SFHASHFCN * p,unsigned char * d,int n),int (* keycmp_fcn)(const void * s1,const void * s2,size_t n))123 int sfhashfcn_set_keyops( SFHASHFCN *h,
124                           unsigned (*hash_fcn)( SFHASHFCN * p,
125                                                 unsigned char *d,
126                                                 int n),
127                           int (*keycmp_fcn)( const void *s1,
128                                              const void *s2,
129                                              size_t n))
130 {
131     if(h && hash_fcn && keycmp_fcn)
132     {
133         h->hash_fcn   = hash_fcn;
134         h->keycmp_fcn = keycmp_fcn;
135 
136         return 0;
137     }
138 
139     return -1;
140 }
141 
142