suricata
util-storage.c
Go to the documentation of this file.
1/* Copyright (C) 2007-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 Victor Julien <victor@inliniac.net>
22 *
23 * Storage API
24 */
25
26#include "suricata-common.h"
27#include "util-unittest.h"
28#include "util-storage.h"
29#include "util-debug.h"
30
31typedef struct StorageMapping_ {
32 const char *name;
33 StorageEnum type; // host, flow, tx, stream, ssn, etc
34 unsigned int size;
35 void *(*Alloc)(unsigned int);
36 void (*Free)(void *);
38
39/** \brief list of StorageMapping used at registration time */
45
46static StorageList *storage_list = NULL;
47static int storage_max_id[STORAGE_MAX];
48static int storage_registration_closed = 0;
49static StorageMapping **storage_map = NULL;
50
51static const char *StoragePrintType(StorageEnum type)
52{
53 switch(type) {
54 case STORAGE_HOST:
55 return "host";
56 case STORAGE_FLOW:
57 return "flow";
58 case STORAGE_IPPAIR:
59 return "ippair";
60 case STORAGE_DEVICE:
61 return "livedevice";
62 case STORAGE_THREAD:
63 return "thread";
64 case STORAGE_MAX:
65 return "max";
66 }
67 return "invalid";
68}
69
70void StorageInit(void)
71{
72 memset(&storage_max_id, 0x00, sizeof(storage_max_id));
73 storage_list = NULL;
74 storage_map = NULL;
75 storage_registration_closed = 0;
76}
77
79{
80 if (storage_map) {
81 int i;
82 for (i = 0; i < STORAGE_MAX; i++) {
83 if (storage_map[i] != NULL) {
84 SCFree(storage_map[i]);
85 storage_map[i] = NULL;
86 }
87 }
88 SCFree(storage_map);
89 storage_map = NULL;
90 }
91
92 StorageList *entry = storage_list;
93 while (entry) {
94 StorageList *next = entry->next;
95 SCFree(entry);
96 entry = next;
97 }
98
99 storage_list = NULL;
100}
101
102int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void (*Free)(void *))
103{
104 if (storage_registration_closed)
105 return -1;
106
107 if (type >= STORAGE_MAX || name == NULL || strlen(name) == 0 ||
108 size == 0 || (size != sizeof(void *) && Alloc == NULL) || Free == NULL)
109 return -1;
110
111 StorageList *list = storage_list;
112 while (list) {
113 if (strcmp(name, list->map.name) == 0 && type == list->map.type) {
114 SCLogError("storage for type \"%s\" with "
115 "name \"%s\" already registered",
116 StoragePrintType(type), name);
117 return -1;
118 }
119
120 list = list->next;
121 }
122
123 StorageList *entry = SCCalloc(1, sizeof(StorageList));
124 if (unlikely(entry == NULL))
125 return -1;
126
127 entry->map.type = type;
128 entry->map.name = name;
129 entry->map.size = size;
130 entry->map.Alloc = Alloc;
131 entry->map.Free = Free;
132
133 entry->id = storage_max_id[type]++;
134 entry->next = storage_list;
135 storage_list = entry;
136
137 return entry->id;
138}
139
141{
142 int count = 0;
143 int i;
144
145 storage_registration_closed = 1;
146
147 for (i = 0; i < STORAGE_MAX; i++) {
148 if (storage_max_id[i] > 0)
149 count++;
150 }
151 if (count == 0)
152 return 0;
153
154 storage_map = SCCalloc(STORAGE_MAX, sizeof(StorageMapping *));
155 if (unlikely(storage_map == NULL)) {
156 return -1;
157 }
158
159 for (i = 0; i < STORAGE_MAX; i++) {
160 if (storage_max_id[i] > 0) {
161 storage_map[i] = SCCalloc(storage_max_id[i], sizeof(StorageMapping));
162 if (storage_map[i] == NULL)
163 return -1;
164 }
165 }
166
167 StorageList *entry = storage_list;
168 while (entry) {
169 if (storage_map[entry->map.type] != NULL) {
170 storage_map[entry->map.type][entry->id].name = entry->map.name;
171 storage_map[entry->map.type][entry->id].type = entry->map.type;
172 storage_map[entry->map.type][entry->id].size = entry->map.size;
173 storage_map[entry->map.type][entry->id].Alloc = entry->map.Alloc;
174 storage_map[entry->map.type][entry->id].Free = entry->map.Free;
175 }
176
177 StorageList *next = entry->next;
178 SCFree(entry);
179 entry = next;
180 };
181 storage_list = NULL;
182
183#ifdef DEBUG
184 for (i = 0; i < STORAGE_MAX; i++) {
185 if (storage_map[i] == NULL)
186 continue;
187
188 int j;
189 for (j = 0; j < storage_max_id[i]; j++) {
190 StorageMapping *m = &storage_map[i][j];
191 SCLogDebug("type \"%s\" name \"%s\" size \"%"PRIuMAX"\"",
192 StoragePrintType(m->type), m->name, (uintmax_t)m->size);
193 }
194 }
195#endif
196 return 0;
197}
198
200{
201 return storage_max_id[type];
202}
203
204/** \brief get the size of the void array used to store
205 * the pointers
206 * \retval size size in bytes, can return 0 if not storage is needed
207 *
208 * \todo we could return -1 when registration isn't closed yet, however
209 * this will break lots of tests currently, so not doing it now */
211{
212 return storage_max_id[type] * sizeof(void *);
213}
214
215void *StorageGetById(const Storage *storage, const StorageEnum type, const int id)
216{
217#ifdef DEBUG
218 BUG_ON(!storage_registration_closed);
219#endif
220 SCLogDebug("storage %p id %d", storage, id);
221 if (storage == NULL)
222 return NULL;
223 return storage[id].ptr;
224}
225
226int StorageSetById(Storage *storage, const StorageEnum type, const int id, void *ptr)
227{
228#ifdef DEBUG
229 BUG_ON(!storage_registration_closed);
230#endif
231 SCLogDebug("storage %p id %d", storage, id);
232 if (storage == NULL)
233 return -1;
234 storage[id].ptr = ptr;
235 return 0;
236}
237
239{
240#ifdef DEBUG
241 BUG_ON(!storage_registration_closed);
242#endif
243 SCLogDebug("storage %p id %d", storage, id);
244
245 StorageMapping *map = &storage_map[type][id];
246 if (storage[id].ptr == NULL && map->Alloc != NULL) {
247 storage[id].ptr = map->Alloc(map->size);
248 if (storage[id].ptr == NULL) {
249 return NULL;
250 }
251 }
252
253 return storage[id].ptr;
254}
255
257{
258#ifdef DEBUG
259 BUG_ON(!storage_registration_closed);
260#endif
261#ifdef UNITTESTS
262 if (storage_map == NULL)
263 return;
264#endif
265 SCLogDebug("storage %p id %d", storage, id);
266
267 Storage *store = storage;
268 if (store != NULL) {
269 SCLogDebug("store %p", store);
270 if (store[id].ptr != NULL) {
271 StorageMapping *map = &storage_map[type][id];
272 map->Free(store[id].ptr);
273 store[id].ptr = NULL;
274 }
275 }
276}
277
279{
280 if (storage == NULL)
281 return;
282#ifdef DEBUG
283 BUG_ON(!storage_registration_closed);
284#endif
285#ifdef UNITTESTS
286 if (storage_map == NULL)
287 return;
288#endif
289
290 Storage *store = storage;
291 int i;
292 for (i = 0; i < storage_max_id[type]; i++) {
293 if (store[i].ptr != NULL) {
294 StorageMapping *map = &storage_map[type][i];
295 map->Free(store[i].ptr);
296 store[i].ptr = NULL;
297 }
298 }
299}
struct HtpBodyChunk_ * next
uint16_t type
uint32_t id
SCMutex m
Definition flow-hash.h:6
list of StorageMapping used at registration time
struct StorageList_ * next
StorageMapping map
void(* Free)(void *)
const char * name
unsigned int size
StorageEnum type
void *(* Alloc)(unsigned int)
void * ptr
#define BUG_ON(x)
const char * name
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCFree(p)
Definition util-mem.h:61
#define SCCalloc(nm, sz)
Definition util-mem.h:53
#define unlikely(expr)
void * StorageGetById(const Storage *storage, const StorageEnum type, const int id)
get storage for id
unsigned int StorageGetCnt(StorageEnum type)
void StorageCleanup(void)
int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Register new storage.
unsigned int StorageGetSize(StorageEnum type)
get the size of the void array used to store the pointers
void StorageFreeAll(Storage *storage, StorageEnum type)
struct StorageList_ StorageList
list of StorageMapping used at registration time
void StorageFreeById(Storage *storage, StorageEnum type, int id)
int StorageFinalize(void)
int StorageSetById(Storage *storage, const StorageEnum type, const int id, void *ptr)
set storage for id
struct StorageMapping_ StorageMapping
void StorageInit(void)
void * StorageAllocByIdPrealloc(Storage *storage, StorageEnum type, int id)
AllocById func for prealloc'd base storage (storage ptrs are part of another memory block)
enum StorageEnum_ StorageEnum
@ STORAGE_THREAD
@ STORAGE_HOST
@ STORAGE_MAX
@ STORAGE_FLOW
@ STORAGE_IPPAIR
@ STORAGE_DEVICE