1 /* Copyright (C) 2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Eric Leblond <eric@regit.org>
22  *
23  * based on host-storage by Victor Julien <victor@inliniac.net>
24  *
25  * Flow wrapper around storage api
26  */
27 
28 #include "suricata-common.h"
29 #include "flow-storage.h"
30 #include "flow-hash.h"
31 #include "flow-util.h"
32 #include "util-unittest.h"
33 
FlowStorageSize(void)34 unsigned int FlowStorageSize(void)
35 {
36     return StorageGetSize(STORAGE_FLOW);
37 }
38 
FlowGetStorageById(Flow * f,int id)39 void *FlowGetStorageById(Flow *f, int id)
40 {
41     return StorageGetById((Storage *)((void *)f + sizeof(Flow)), STORAGE_FLOW, id);
42 }
43 
FlowSetStorageById(Flow * f,int id,void * ptr)44 int FlowSetStorageById(Flow *f, int id, void *ptr)
45 {
46     return StorageSetById((Storage *)((void *)f + sizeof(Flow)), STORAGE_FLOW, id, ptr);
47 }
48 
FlowAllocStorageById(Flow * f,int id)49 void *FlowAllocStorageById(Flow *f, int id)
50 {
51     return StorageAllocByIdPrealloc((Storage *)((void *)f + sizeof(Flow)), STORAGE_FLOW, id);
52 }
53 
FlowFreeStorageById(Flow * f,int id)54 void FlowFreeStorageById(Flow *f, int id)
55 {
56     StorageFreeById((Storage *)((void *)f + sizeof(Flow)), STORAGE_FLOW, id);
57 }
58 
FlowFreeStorage(Flow * f)59 void FlowFreeStorage(Flow *f)
60 {
61     if (FlowStorageSize() > 0)
62         StorageFreeAll((Storage *)((void *)f + sizeof(Flow)), STORAGE_FLOW);
63 }
64 
FlowStorageRegister(const char * name,const unsigned int size,void * (* Alloc)(unsigned int),void (* Free)(void *))65 int FlowStorageRegister(const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void (*Free)(void *)) {
66     return StorageRegister(STORAGE_FLOW, name, size, Alloc, Free);
67 }
68 
69 #ifdef UNITTESTS
70 
StorageTestAlloc(unsigned int size)71 static void *StorageTestAlloc(unsigned int size)
72 {
73     void *x = SCMalloc(size);
74     return x;
75 }
StorageTestFree(void * x)76 static void StorageTestFree(void *x)
77 {
78     if (x)
79         SCFree(x);
80 }
81 
FlowStorageTest01(void)82 static int FlowStorageTest01(void)
83 {
84     Flow *f = NULL;
85 
86     StorageInit();
87 
88     int id1 = FlowStorageRegister("test", 8, StorageTestAlloc, StorageTestFree);
89     if (id1 < 0)
90         goto error;
91     int id2 = FlowStorageRegister("variable", 24, StorageTestAlloc, StorageTestFree);
92     if (id2 < 0)
93         goto error;
94     int id3 = FlowStorageRegister("store", sizeof(void *), StorageTestAlloc, StorageTestFree);
95     if (id3 < 0)
96         goto error;
97 
98     if (StorageFinalize() < 0)
99         goto error;
100 
101     FlowInitConfig(FLOW_QUIET);
102 
103     f = FlowAlloc();
104     if (f == NULL) {
105         goto error;
106     }
107 
108     void *ptr = FlowGetStorageById(f, id1);
109     if (ptr != NULL) {
110         goto error;
111     }
112     ptr = FlowGetStorageById(f, id2);
113     if (ptr != NULL) {
114         goto error;
115     }
116     ptr = FlowGetStorageById(f, id3);
117     if (ptr != NULL) {
118         goto error;
119     }
120 
121     void *ptr1a = FlowAllocStorageById(f, id1);
122     if (ptr1a == NULL) {
123         goto error;
124     }
125     void *ptr2a = FlowAllocStorageById(f, id2);
126     if (ptr2a == NULL) {
127         goto error;
128     }
129     void *ptr3a = FlowAllocStorageById(f, id3);
130     if (ptr3a == NULL) {
131         goto error;
132     }
133 
134     void *ptr1b = FlowGetStorageById(f, id1);
135     if (ptr1a != ptr1b) {
136         goto error;
137     }
138     void *ptr2b = FlowGetStorageById(f, id2);
139     if (ptr2a != ptr2b) {
140         goto error;
141     }
142     void *ptr3b = FlowGetStorageById(f, id3);
143     if (ptr3a != ptr3b) {
144         goto error;
145     }
146 
147     FlowClearMemory(f, 0);
148     FlowFree(f);
149     FlowShutdown();
150     StorageCleanup();
151     return 1;
152 error:
153     if (f != NULL) {
154         FlowClearMemory(f, 0);
155         FlowFree(f);
156     }
157     FlowShutdown();
158     StorageCleanup();
159     return 0;
160 }
161 
FlowStorageTest02(void)162 static int FlowStorageTest02(void)
163 {
164     Flow *f = NULL;
165 
166     StorageInit();
167 
168     int id1 = FlowStorageRegister("test", sizeof(void *), NULL, StorageTestFree);
169     if (id1 < 0)
170         goto error;
171 
172     if (StorageFinalize() < 0)
173         goto error;
174 
175     FlowInitConfig(FLOW_QUIET);
176     f = FlowAlloc();
177     if (f == NULL) {
178         goto error;
179     }
180 
181     void *ptr = FlowGetStorageById(f, id1);
182     if (ptr != NULL) {
183         goto error;
184     }
185 
186     void *ptr1a = SCMalloc(128);
187     if (unlikely(ptr1a == NULL)) {
188         goto error;
189     }
190     FlowSetStorageById(f, id1, ptr1a);
191 
192     void *ptr1b = FlowGetStorageById(f, id1);
193     if (ptr1a != ptr1b) {
194         goto error;
195     }
196 
197 
198     FlowClearMemory(f, 0);
199     FlowFree(f);
200     FlowShutdown();
201     StorageCleanup();
202     return 1;
203 error:
204     if (f != NULL) {
205         FlowClearMemory(f, 0);
206         FlowFree(f);
207     }
208     FlowShutdown();
209     StorageCleanup();
210     return 0;
211 }
212 
FlowStorageTest03(void)213 static int FlowStorageTest03(void)
214 {
215     Flow *f = NULL;
216 
217     StorageInit();
218 
219     int id1 = FlowStorageRegister("test1", sizeof(void *), NULL, StorageTestFree);
220     if (id1 < 0)
221         goto error;
222     int id2 = FlowStorageRegister("test2", sizeof(void *), NULL, StorageTestFree);
223     if (id2 < 0)
224         goto error;
225     int id3 = FlowStorageRegister("test3", 32, StorageTestAlloc, StorageTestFree);
226     if (id3 < 0)
227         goto error;
228 
229     if (StorageFinalize() < 0)
230         goto error;
231 
232     FlowInitConfig(FLOW_QUIET);
233     f = FlowAlloc();
234     if (f == NULL) {
235         goto error;
236     }
237 
238     void *ptr = FlowGetStorageById(f, id1);
239     if (ptr != NULL) {
240         goto error;
241     }
242 
243     void *ptr1a = SCMalloc(128);
244     if (unlikely(ptr1a == NULL)) {
245         goto error;
246     }
247     FlowSetStorageById(f, id1, ptr1a);
248 
249     void *ptr2a = SCMalloc(256);
250     if (unlikely(ptr2a == NULL)) {
251         goto error;
252     }
253     FlowSetStorageById(f, id2, ptr2a);
254 
255     void *ptr3a = FlowAllocStorageById(f, id3);
256     if (ptr3a == NULL) {
257         goto error;
258     }
259 
260     void *ptr1b = FlowGetStorageById(f, id1);
261     if (ptr1a != ptr1b) {
262         goto error;
263     }
264     void *ptr2b = FlowGetStorageById(f, id2);
265     if (ptr2a != ptr2b) {
266         goto error;
267     }
268     void *ptr3b = FlowGetStorageById(f, id3);
269     if (ptr3a != ptr3b) {
270         goto error;
271     }
272 
273     FlowClearMemory(f, 0);
274     FlowFree(f);
275     FlowShutdown();
276     StorageCleanup();
277     return 1;
278 error:
279     if (f != NULL) {
280         FlowClearMemory(f, 0);
281         FlowFree(f);
282     }
283     FlowShutdown();
284     StorageCleanup();
285     return 0;
286 }
287 #endif
288 
RegisterFlowStorageTests(void)289 void RegisterFlowStorageTests(void)
290 {
291 #ifdef UNITTESTS
292     UtRegisterTest("FlowStorageTest01", FlowStorageTest01);
293     UtRegisterTest("FlowStorageTest02", FlowStorageTest02);
294     UtRegisterTest("FlowStorageTest03", FlowStorageTest03);
295 #endif
296 }
297