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  void (*Free)(void *);
36 
37 /** \brief list of StorageMapping used at registration time */
38 typedef struct StorageList_ {
40  int id;
41  struct StorageList_ *next;
43 
44 static StorageList *storage_list = NULL;
45 static int storage_max_id[STORAGE_MAX];
46 static int storage_registration_closed = 0;
47 static StorageMapping **storage_map = NULL;
48 
49 static const char *StoragePrintType(StorageEnum type)
50 {
51  switch(type) {
52  case STORAGE_HOST:
53  return "host";
54  case STORAGE_FLOW:
55  return "flow";
56  case STORAGE_IPPAIR:
57  return "ippair";
58  case STORAGE_DEVICE:
59  return "livedevice";
60  case STORAGE_THREAD:
61  return "thread";
62  case STORAGE_MAX:
63  return "max";
64  }
65  return "invalid";
66 }
67 
68 void SCStorageInit(void)
69 {
70  memset(&storage_max_id, 0x00, sizeof(storage_max_id));
71  storage_list = NULL;
72  storage_map = NULL;
73  storage_registration_closed = 0;
74 }
75 
76 void SCStorageCleanup(void)
77 {
78  if (storage_map) {
79  int i;
80  for (i = 0; i < STORAGE_MAX; i++) {
81  if (storage_map[i] != NULL) {
82  SCFree(storage_map[i]);
83  storage_map[i] = NULL;
84  }
85  }
86  SCFree(storage_map);
87  storage_map = NULL;
88  }
89 
90  StorageList *entry = storage_list;
91  while (entry) {
92  StorageList *next = entry->next;
93  SCFree(entry);
94  entry = next;
95  }
96 
97  storage_list = NULL;
98 }
99 
100 int SCStorageRegister(const StorageEnum type, const char *name, void (*Free)(void *))
101 {
102  if (storage_registration_closed)
103  return -1;
104 
105  if (type >= STORAGE_MAX || name == NULL || strlen(name) == 0 || Free == NULL)
106  return -1;
107 
108  StorageList *list = storage_list;
109  while (list) {
110  if (strcmp(name, list->map.name) == 0 && type == list->map.type) {
111  SCLogError("storage for type \"%s\" with "
112  "name \"%s\" already registered",
113  StoragePrintType(type), name);
114  return -1;
115  }
116 
117  list = list->next;
118  }
119 
120  StorageList *entry = SCCalloc(1, sizeof(StorageList));
121  if (unlikely(entry == NULL))
122  return -1;
123 
124  entry->map.type = type;
125  entry->map.name = name;
126  entry->map.Free = Free;
127 
128  entry->id = storage_max_id[type]++;
129  entry->next = storage_list;
130  storage_list = entry;
131 
132  return entry->id;
133 }
134 
136 {
137  int count = 0;
138  int i;
139 
140  storage_registration_closed = 1;
141 
142  for (i = 0; i < STORAGE_MAX; i++) {
143  if (storage_max_id[i] > 0)
144  count++;
145  }
146  if (count == 0)
147  return 0;
148 
149  storage_map = SCCalloc(STORAGE_MAX, sizeof(StorageMapping *));
150  if (unlikely(storage_map == NULL)) {
151  return -1;
152  }
153 
154  for (i = 0; i < STORAGE_MAX; i++) {
155  if (storage_max_id[i] > 0) {
156  storage_map[i] = SCCalloc(storage_max_id[i], sizeof(StorageMapping));
157  if (storage_map[i] == NULL)
158  return -1;
159  }
160  }
161 
162  StorageList *entry = storage_list;
163  while (entry) {
164  if (storage_map[entry->map.type] != NULL) {
165  storage_map[entry->map.type][entry->id].name = entry->map.name;
166  storage_map[entry->map.type][entry->id].type = entry->map.type;
167  storage_map[entry->map.type][entry->id].Free = entry->map.Free;
168  }
169 
170  StorageList *next = entry->next;
171  SCFree(entry);
172  entry = next;
173  };
174  storage_list = NULL;
175 
176 #ifdef DEBUG
177  for (i = 0; i < STORAGE_MAX; i++) {
178  if (storage_map[i] == NULL)
179  continue;
180 
181  int j;
182  for (j = 0; j < storage_max_id[i]; j++) {
183  StorageMapping *m = &storage_map[i][j];
184  SCLogDebug("type \"%s\" name \"%s\"", StoragePrintType(m->type), m->name);
185  }
186  }
187 #endif
188  return 0;
189 }
190 
192 {
193  return storage_max_id[type];
194 }
195 
196 /** \brief get the size of the void array used to store
197  * the pointers
198  * \retval size size in bytes, can return 0 if not storage is needed
199  *
200  * \todo we could return -1 when registration isn't closed yet, however
201  * this will break lots of tests currently, so not doing it now */
203 {
204  return storage_max_id[type] * sizeof(void *);
205 }
206 
207 void *SCStorageGetById(const Storage *storage, const StorageEnum type, const int id)
208 {
209 #ifdef DEBUG
210  BUG_ON(!storage_registration_closed);
211 #endif
212  SCLogDebug("storage %p id %d", storage, id);
213  if (storage == NULL)
214  return NULL;
215  return storage[id].ptr;
216 }
217 
218 int SCStorageSetById(Storage *storage, const StorageEnum type, const int id, void *ptr)
219 {
220 #ifdef DEBUG
221  BUG_ON(!storage_registration_closed);
222 #endif
223  SCLogDebug("storage %p id %d", storage, id);
224  if (storage == NULL)
225  return -1;
226  storage[id].ptr = ptr;
227  return 0;
228 }
229 
230 void SCStorageFreeById(Storage *storage, StorageEnum type, int id)
231 {
232 #ifdef DEBUG
233  BUG_ON(!storage_registration_closed);
234 #endif
235 #ifdef UNITTESTS
236  if (storage_map == NULL)
237  return;
238 #endif
239  SCLogDebug("storage %p id %d", storage, id);
240 
241  Storage *store = storage;
242  if (store != NULL) {
243  SCLogDebug("store %p", store);
244  if (store[id].ptr != NULL) {
245  StorageMapping *map = &storage_map[type][id];
246  map->Free(store[id].ptr);
247  store[id].ptr = NULL;
248  }
249  }
250 }
251 
253 {
254  if (storage == NULL)
255  return;
256 #ifdef DEBUG
257  BUG_ON(!storage_registration_closed);
258 #endif
259 #ifdef UNITTESTS
260  if (storage_map == NULL)
261  return;
262 #endif
263 
264  Storage *store = storage;
265  int i;
266  for (i = 0; i < storage_max_id[type]; i++) {
267  if (store[i].ptr != NULL) {
268  StorageMapping *map = &storage_map[type][i];
269  map->Free(store[i].ptr);
270  store[i].ptr = NULL;
271  }
272  }
273 }
SCStorageGetCnt
unsigned int SCStorageGetCnt(StorageEnum type)
Definition: util-storage.c:191
StorageMapping_
Definition: util-storage.c:31
SCStorageInit
void SCStorageInit(void)
Definition: util-storage.c:68
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
StorageList_::next
struct StorageList_ * next
Definition: util-storage.c:41
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
name
const char * name
Definition: detect-engine-proto.c:48
SCStorageFreeById
void SCStorageFreeById(Storage *storage, StorageEnum type, int id)
Definition: util-storage.c:230
STORAGE_IPPAIR
@ STORAGE_IPPAIR
Definition: util-storage.h:32
SCStorageSetById
int SCStorageSetById(Storage *storage, const StorageEnum type, const int id, void *ptr)
set storage for id
Definition: util-storage.c:218
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:40
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:34
STORAGE_FLOW
@ STORAGE_FLOW
Definition: util-storage.h:31
StorageList_::map
StorageMapping map
Definition: util-storage.c:39
StorageList
struct StorageList_ StorageList
list of StorageMapping used at registration time
SCStorageGetById
void * SCStorageGetById(const Storage *storage, const StorageEnum type, const int id)
get storage for id
Definition: util-storage.c:207
SCStorageRegister
int SCStorageRegister(const StorageEnum type, const char *name, void(*Free)(void *))
Register new storage.
Definition: util-storage.c:100
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:317
StorageMapping_::name
const char * name
Definition: util-storage.c:32
type
uint16_t type
Definition: decode-vlan.c:106
STORAGE_MAX
@ STORAGE_MAX
Definition: util-storage.h:36
StorageMapping_::type
StorageEnum type
Definition: util-storage.c:33
SCStorageGetSize
unsigned int SCStorageGetSize(StorageEnum type)
get the size of the void array used to store the pointers
Definition: util-storage.c:202
suricata-common.h
SCStorageFreeAll
void SCStorageFreeAll(Storage *storage, StorageEnum type)
Definition: util-storage.c:252
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:274
SCFree
#define SCFree(p)
Definition: util-mem.h:61
SCStorageCleanup
void SCStorageCleanup(void)
Definition: util-storage.c:76
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-storage.h
StorageMapping
struct StorageMapping_ StorageMapping
SCStorageFinalize
int SCStorageFinalize(void)
Definition: util-storage.c:135
StorageList_
list of StorageMapping used at registration time
Definition: util-storage.c:38