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 
31 typedef 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 */
40 typedef struct StorageList_ {
42  int id;
43  struct StorageList_ *next;
45 
46 static StorageList *storage_list = NULL;
47 static int storage_max_id[STORAGE_MAX];
48 static int storage_registration_closed = 0;
49 static StorageMapping **storage_map = NULL;
50 
51 static 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 
70 void 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 
78 void StorageCleanup(void)
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 
102 int 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 
215 void *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 
226 int 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 
256 void StorageFreeById(Storage *storage, StorageEnum type, int id)
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 }
StorageMapping_
Definition: util-storage.c:31
StorageFreeAll
void StorageFreeAll(Storage *storage, StorageEnum type)
Definition: util-storage.c:278
StorageInit
void StorageInit(void)
Definition: util-storage.c:70
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
StorageList_::next
struct StorageList_ * next
Definition: util-storage.c:43
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
StorageCleanup
void StorageCleanup(void)
Definition: util-storage.c:78
STORAGE_IPPAIR
@ STORAGE_IPPAIR
Definition: util-storage.h:32
StorageEnum
enum StorageEnum_ StorageEnum
m
SCMutex m
Definition: flow-hash.h:6
STORAGE_HOST
@ STORAGE_HOST
Definition: util-storage.h:30
util-unittest.h
StorageList_::id
int id
Definition: util-storage.c:42
Storage
Definition: util-storage.h:40
STORAGE_DEVICE
@ STORAGE_DEVICE
Definition: util-storage.h:33
util-debug.h
STORAGE_THREAD
@ STORAGE_THREAD
Definition: util-storage.h:34
Storage::ptr
void * ptr
Definition: util-storage.h:41
StorageMapping_::Free
void(* Free)(void *)
Definition: util-storage.c:36
STORAGE_FLOW
@ STORAGE_FLOW
Definition: util-storage.h:31
StorageList_::map
StorageMapping map
Definition: util-storage.c:41
StorageList
struct StorageList_ StorageList
list of StorageMapping used at registration time
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
StorageMapping_::name
const char * name
Definition: util-storage.c:32
type
uint16_t type
Definition: decode-vlan.c:107
STORAGE_MAX
@ STORAGE_MAX
Definition: util-storage.h:36
StorageMapping_::type
StorageEnum type
Definition: util-storage.c:33
StorageFinalize
int StorageFinalize(void)
Definition: util-storage.c:140
StorageGetCnt
unsigned int StorageGetCnt(StorageEnum type)
Definition: util-storage.c:199
suricata-common.h
StorageSetById
int StorageSetById(Storage *storage, const StorageEnum type, const int id, void *ptr)
set storage for id
Definition: util-storage.c:226
StorageAllocByIdPrealloc
void * StorageAllocByIdPrealloc(Storage *storage, StorageEnum type, int id)
AllocById func for prealloc'd base storage (storage ptrs are part of another memory block)
Definition: util-storage.c:238
StorageFreeById
void StorageFreeById(Storage *storage, StorageEnum type, int id)
Definition: util-storage.c:256
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
StorageMapping_::size
unsigned int size
Definition: util-storage.c:34
StorageGetById
void * StorageGetById(const Storage *storage, const StorageEnum type, const int id)
get storage for id
Definition: util-storage.c:215
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
StorageMapping_::Alloc
void *(* Alloc)(unsigned int)
Definition: util-storage.c:35
StorageGetSize
unsigned int StorageGetSize(StorageEnum type)
get the size of the void array used to store the pointers
Definition: util-storage.c:210
util-storage.h
StorageRegister
int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, void *(*Alloc)(unsigned int), void(*Free)(void *))
Register new storage.
Definition: util-storage.c:102
StorageMapping
struct StorageMapping_ StorageMapping
StorageList_
list of StorageMapping used at registration time
Definition: util-storage.c:40