diff --git a/src/host-storage.c b/src/host-storage.c index 3bcbfbe556..0e028a739a 100644 --- a/src/host-storage.c +++ b/src/host-storage.c @@ -25,30 +25,36 @@ #include "suricata-common.h" #include "host-storage.h" -#include "util-unittests.h" +#include "util-unittest.h" + +unsigned int HostStorageSize(void) { + return StorageGetSize(STORAGE_HOST); +} void *HostGetStorageById(Host *h, int id) { - return StorageGetById(h->storage, STORAGE_HOST, id); + return StorageGetById((Storage *)(h + HostStorageSize()), STORAGE_HOST, id); } void *HostAllocStorageById(Host *h, int id) { - return StorageAllocById(&h->storage, STORAGE_HOST, id); + return StorageAllocById((Storage **)&h + HostStorageSize(), STORAGE_HOST, id); } void HostFreeStorageById(Host *h, int id) { - StorageFreeById(h->storage, STORAGE_HOST, id); + StorageFreeById((Storage *)(h + HostStorageSize()), STORAGE_HOST, id); } void HostFreeStorage(Host *h) { - StorageFree(&h->storage, STORAGE_HOST); + StorageFreeAll((Storage *)(h + HostStorageSize()), STORAGE_HOST); } #ifdef UNITTESTS - +static int HostStorageTest01(void) { + return 1; +} #endif void RegisterHostStorageTests(void) { #ifdef UNITTESTS - + UtRegisterTest("HostStorageTest01", HostStorageTest01, 1); #endif } diff --git a/src/host-storage.h b/src/host-storage.h index 4905744d71..bc43d31566 100644 --- a/src/host-storage.h +++ b/src/host-storage.h @@ -23,11 +23,20 @@ * Host wrapper around storage api */ +#ifndef __HOST_STORAGE_H__ +#define __HOST_STORAGE_H__ + #include "util-storage.h" #include "host.h" +unsigned int HostStorageSize(void); + void *HostGetStorageById(Host *h, int id); void *HostAllocStorageById(Host *h, int id); void HostFreeStorageById(Host *h, int id); void HostFreeStorage(Host *h); + +void RegisterHostStorageTests(void); + +#endif /* __HOST_STORAGE_H__ */ diff --git a/src/host.c b/src/host.c index a159df82bf..4661ca589c 100644 --- a/src/host.c +++ b/src/host.c @@ -28,6 +28,7 @@ #include "util-debug.h" #include "host.h" +#include "host-storage.h" #include "util-random.h" #include "util-misc.h" @@ -55,17 +56,19 @@ void HostMoveToSpare(Host *h) { } Host *HostAlloc(void) { - if (!(HOST_CHECK_MEMCAP(sizeof(Host)))) { + size_t size = sizeof(Host) + HostStorageSize(); + + if (!(HOST_CHECK_MEMCAP(size))) { return NULL; } - (void) SC_ATOMIC_ADD(host_memuse, sizeof(Host)); + (void) SC_ATOMIC_ADD(host_memuse, size); - Host *h = SCMalloc(sizeof(Host)); + Host *h = SCMalloc(size); if (unlikely(h == NULL)) goto error; - memset(h, 0x00, sizeof(Host)); + memset(h, 0x00, size); SCMutexInit(&h->m, NULL); SC_ATOMIC_INIT(h->use_cnt); @@ -82,7 +85,7 @@ void HostFree(Host *h) { SC_ATOMIC_DESTROY(h->use_cnt); SCMutexDestroy(&h->m); SCFree(h); - (void) SC_ATOMIC_SUB(host_memuse, sizeof(Host)); + (void) SC_ATOMIC_SUB(host_memuse, (sizeof(Host) + HostStorageSize())); } } @@ -113,6 +116,9 @@ void HostClearMemory(Host *h) { SCFree(h->iprep); h->iprep = NULL; } + + if (HostStorageSize() > 0) + HostFreeStorage(h); } #define HOST_DEFAULT_HASHSIZE 4096 @@ -673,4 +679,7 @@ static Host *HostGetUsedHost(void) { return NULL; } +void HostRegisterUnittests(void) { + RegisterHostStorageTests(); +} diff --git a/src/util-storage.c b/src/util-storage.c index c829905d75..934ff799ee 100644 --- a/src/util-storage.c +++ b/src/util-storage.c @@ -31,7 +31,7 @@ typedef struct StorageMapping_ { const char *name; StorageEnum type; // host, flow, tx, stream, ssn, etc unsigned int size; - int (*Init)(void *); + void *(*Init)(unsigned int); void (*Free)(void *); } StorageMapping; @@ -89,7 +89,7 @@ void StorageCleanup(void) { storage_list = NULL; } -int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, int (*Init)(void *), void (*Free)(void *)) { +int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, void *(*Init)(unsigned int), void (*Free)(void *)) { if (storage_registraton_closed) return -1; @@ -185,7 +185,21 @@ int StorageFinalize(void) { return 0; } -void *StorageGetById(Storage *storage, StorageEnum type, int id) { +unsigned int StorageGetCnt(StorageEnum type) { + return storage_max_id[type]; +} + +/** \brief get the size of the void array used to store + * the pointers + * \retval size size in bytes, can return 0 if not storage is needed + * + * \todo we could return -1 when registration isn't closed yet, however + * this will break lots of tests currently, so not doing it now */ +unsigned int StorageGetSize(StorageEnum type) { + return storage_max_id[type] * sizeof(void *); +} + +void *StorageGetById(const Storage *storage, const StorageEnum type, const int id) { SCLogDebug("storage %p id %d", storage, id); if (storage == NULL) return NULL; @@ -206,7 +220,7 @@ void *StorageAllocById(Storage **storage, StorageEnum type, int id) { SCLogDebug("store %p", store); if (store[id] == NULL) { - store[id] = SCMalloc(map->size); + store[id] = map->Init(map->size); if (store[id] == NULL) { SCFree(store); *storage = NULL; @@ -214,12 +228,6 @@ void *StorageAllocById(Storage **storage, StorageEnum type, int id) { } } - if (map->Init(store[id]) < 0) { - SCFree(store); - *storage = NULL; - return NULL; - } - *storage = store; return store[id]; } @@ -233,12 +241,26 @@ void StorageFreeById(Storage *storage, StorageEnum type, int id) { SCLogDebug("store %p", store); if (store[id] != NULL) { map->Free(store[id]); - SCFree(store[id]); store[id] = NULL; } } } +void StorageFreeAll(Storage *storage, StorageEnum type) { + if (*storage == NULL) + return; + + Storage *store = storage; + int i; + for (i = 0; i < storage_max_id[type]; i++) { + StorageMapping *map = &storage_map[type][i]; + if (store[i] != NULL) { + map->Free(store[i]); + store[i] = NULL; + } + } +} + void StorageFree(Storage **storage, StorageEnum type) { if (*storage == NULL) return; @@ -249,7 +271,6 @@ void StorageFree(Storage **storage, StorageEnum type) { StorageMapping *map = &storage_map[type][i]; if (store[i] != NULL) { map->Free(store[i]); - SCFree(store[i]); store[i] = NULL; } } @@ -259,10 +280,13 @@ void StorageFree(Storage **storage, StorageEnum type) { #ifdef UNITTESTS -static int StorageTestInit(void *x) { - return 0; +static void *StorageTestInit(unsigned int size) { + void *x = SCMalloc(size); + return x; } void StorageTestFree(void *x) { + if (x) + SCFree(x); } static int StorageTest01(void) { @@ -292,10 +316,11 @@ struct StorageTest02Data { int abc; }; -static int StorageTest02Init(void *x) { - struct StorageTest02Data *data = (struct StorageTest02Data *)x; - data->abc = 1234; - return 0; +static void *StorageTest02Init(unsigned int size) { + struct StorageTest02Data *data = (struct StorageTest02Data *)SCMalloc(size); + if (data != NULL) + data->abc = 1234; + return (void *)data; } static int StorageTest02(void) { diff --git a/src/util-storage.h b/src/util-storage.h index 785c4d02a8..2e4061beaa 100644 --- a/src/util-storage.h +++ b/src/util-storage.h @@ -38,13 +38,17 @@ typedef void* Storage; void StorageInit(void); void StorageCleanup(void); -int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, int (*Init)(void *), void (*Free)(void *)); +int StorageRegister(const StorageEnum type, const char *name, const unsigned int size, void *(*Init)(unsigned int), void (*Free)(void *)); int StorageFinalize(void); -void *StorageGetById(Storage *storage, StorageEnum type, int id); -void *StorageAllocById(Storage **storage, StorageEnum type, int id); -void StorageFreeById(Storage *storage, StorageEnum type, int id); -void StorageFree(Storage **storage, StorageEnum type); +unsigned int StorageGetCnt(const StorageEnum type); +unsigned int StorageGetSize(const StorageEnum type); + +void *StorageGetById(const Storage *storage, const StorageEnum type, const int id); +void *StorageAllocById(Storage **storage, const StorageEnum type, const int id); +void StorageFreeById(Storage *storage, const StorageEnum type, const int id); +void StorageFreeAll(Storage *storage, const StorageEnum type); +void StorageFree(Storage **storage, const StorageEnum type); void StorageRegisterTests(void); #endif