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