diff --git a/src/detect-engine-siggroup.c b/src/detect-engine-siggroup.c index 20435b2510..b52e22c707 100644 --- a/src/detect-engine-siggroup.c +++ b/src/detect-engine-siggroup.c @@ -1,6 +1,5 @@ -/* sig group - * - * +/** Copyright (c) 2009 Open Information Security Foundation. + * \author Victor Julien */ #include "eidps-common.h" @@ -12,6 +11,7 @@ #include "util-unittest.h" #include "detect.h" +#include "detect-parse.h" #include "detect-engine.h" #include "detect-engine-address.h" #include "detect-engine-mpm.h" @@ -23,6 +23,7 @@ #include "util-hash.h" #include "util-hashlist.h" +#include "util-error.h" #include "util-debug.h" /* prototypes */ @@ -71,16 +72,19 @@ void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid) { } /** - * \brief Alloc a sig group head and it's sig_array + * \brief Alloc a SigGroupHead and its signature bit_array. * - * \param size Size of the sig array - - * \retval sgh Pointer to newly init SigGroupHead on succuess; or NULL in case - * of error + * \param size Size of the sig_array that has to be created for this + * SigGroupHead. + * + * \retval sgh Pointer to the newly init SigGroupHead on success; or NULL in + * case of error. */ -static SigGroupHead *SigGroupHeadAlloc(uint32_t size) { +static SigGroupHead *SigGroupHeadAlloc(uint32_t size) +{ SigGroupHead *sgh = malloc(sizeof(SigGroupHead)); if (sgh == NULL) { + SCLogDebug(SC_ERR_MEM_ALLOC, "Error allocating memory"); return NULL; } memset(sgh, 0, sizeof(SigGroupHead)); @@ -94,29 +98,35 @@ static SigGroupHead *SigGroupHeadAlloc(uint32_t size) { /* initialize the signature bitarray */ sgh->sig_size = size; - sgh->sig_array = malloc(sgh->sig_size); - if (sgh->sig_array == NULL) + if ( (sgh->sig_array = malloc(sgh->sig_size)) == NULL) { + SCLogDebug(SC_ERR_MEM_ALLOC, "Error allocating memory"); goto error; + } memset(sgh->sig_array, 0, sgh->sig_size); detect_siggroup_sigarray_init_cnt++; detect_siggroup_sigarray_memory += sgh->sig_size; return sgh; + error: if (sgh != NULL) SigGroupHeadFree(sgh); return NULL; } -/** \brief Free a sgh - * \param sgh the sig group head to free */ -void SigGroupHeadFree(SigGroupHead *sgh) { - SCLogDebug("sgh %p", sgh); - +/** + * \brief Free a SigGroupHead and its members. + * + * \param sgh Pointer to the SigGroupHead that has to be freed. + */ +void SigGroupHeadFree(SigGroupHead *sgh) +{ if (sgh == NULL) return; + SCLogDebug("sgh %p", sgh); + PatternMatchDestroyGroup(sgh); if (sgh->sig_array != NULL) { @@ -143,251 +153,571 @@ void SigGroupHeadFree(SigGroupHead *sgh) { detect_siggroup_head_free_cnt++; detect_siggroup_head_memory -= sizeof(SigGroupHead); + + return; } -/* - * initialization hashes +/** + * \brief The hash function to be the used by the mpm SigGroupHead hash table - + * DetectEngineCtx->sgh_mpm_hash_table. + * + * \param ht Pointer to the hash table. + * \param data Pointer to the SigGroupHead. + * \param datalen Not used in our case. + * + * \retval hash The generated hash value. */ - -/* mpm sgh hash */ -uint32_t SigGroupHeadMpmHashFunc(HashListTable *ht, void *data, uint16_t datalen) { +uint32_t SigGroupHeadMpmHashFunc(HashListTable *ht, void *data, uint16_t datalen) +{ SigGroupHead *sgh = (SigGroupHead *)data; uint32_t hash = 0; + uint32_t b = 0; - uint32_t b; - for (b = 0; b < sgh->init->content_size; b+=1) { + for (b = 0; b < sgh->init->content_size; b++) hash += sgh->init->content_array[b]; - } + return hash % ht->array_size; } -char SigGroupHeadMpmCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2) { +/** + * \brief The Compare function to be used by the mpm SigGroupHead hash table - + * DetectEngineCtx->sgh_mpm_hash_table. + * + * \param data1 Pointer to the first SigGroupHead. + * \param len1 Not used. + * \param data2 Pointer to the second SigGroupHead. + * \param len2 Not used. + * + * \retval 1 If the 2 SigGroupHeads sent as args match. + * \retval 0 If the 2 SigGroupHeads sent as args do not match. + */ +char SigGroupHeadMpmCompareFunc(void *data1, uint16_t len1, void *data2, + uint16_t len2) +{ SigGroupHead *sgh1 = (SigGroupHead *)data1; SigGroupHead *sgh2 = (SigGroupHead *)data2; if (sgh1->init->content_size != sgh2->init->content_size) return 0; - if (memcmp(sgh1->init->content_array,sgh2->init->content_array,sgh1->init->content_size) != 0) + if (memcmp(sgh1->init->content_array, sgh2->init->content_array, + sgh1->init->content_size) != 0) { return 0; + } return 1; } -int SigGroupHeadMpmHashInit(DetectEngineCtx *de_ctx) { - de_ctx->sgh_mpm_hash_table = HashListTableInit(4096, SigGroupHeadMpmHashFunc, SigGroupHeadMpmCompareFunc, NULL); +/** + * \brief Initializes the SigGroupHead mpm hash table to be used by the detection + * engine context. + * + * \param de_ctx Pointer to the detection engine context. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int SigGroupHeadMpmHashInit(DetectEngineCtx *de_ctx) +{ + de_ctx->sgh_mpm_hash_table = HashListTableInit(4096, SigGroupHeadMpmHashFunc, + SigGroupHeadMpmCompareFunc, + NULL); + if (de_ctx->sgh_mpm_hash_table == NULL) goto error; return 0; + error: return -1; } -int SigGroupHeadMpmHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - return HashListTableAdd(de_ctx->sgh_mpm_hash_table, (void *)sgh, 0); +/** + * \brief Adds a SigGroupHead to the detection engine context SigGroupHead + * mpm hash table. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval ret 0 on Successfully adding the argument sgh; -1 on failure. + */ +int SigGroupHeadMpmHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + int ret = HashListTableAdd(de_ctx->sgh_mpm_hash_table, (void *)sgh, 0); + + return ret; } -SigGroupHead *SigGroupHeadMpmHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_hash_table, (void *)sgh, 0); +/** + * \brief Used to lookup a SigGroupHead from the detection engine context + * SigGroupHead mpm hash table. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is + * found in the hash table; NULL on failure. + */ +SigGroupHead *SigGroupHeadMpmHashLookup(DetectEngineCtx *de_ctx, + SigGroupHead *sgh) +{ + SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_hash_table, + (void *)sgh, 0); + return rsgh; } -void SigGroupHeadMpmHashFree(DetectEngineCtx *de_ctx) { +/** + * \brief Frees the hash table - DetectEngineCtx->sgh_mpm_hash_table, allocated by + * SigGroupHeadMpmHashInit() function. + * + * \param de_ctx Pointer to the detection engine context. + */ +void SigGroupHeadMpmHashFree(DetectEngineCtx *de_ctx) +{ if (de_ctx->sgh_mpm_hash_table == NULL) return; HashListTableFree(de_ctx->sgh_mpm_hash_table); de_ctx->sgh_mpm_hash_table = NULL; -} -/* mpm uri sgh hash */ + return; +} -uint32_t SigGroupHeadMpmUriHashFunc(HashListTable *ht, void *data, uint16_t datalen) { +/** + * \brief The hash function to be the used by the mpm uri SigGroupHead hash + * table - DetectEngineCtx->sgh_mpm_uri_hash_table. + * + * \param ht Pointer to the hash table. + * \param data Pointer to the SigGroupHead. + * \param datalen Not used in our case. + * + * \retval hash The generated hash value. + */ +uint32_t SigGroupHeadMpmUriHashFunc(HashListTable *ht, void *data, uint16_t datalen) +{ SigGroupHead *sgh = (SigGroupHead *)data; uint32_t hash = 0; + uint32_t b = 0; - uint32_t b; - for (b = 0; b < sgh->init->uri_content_size; b+=1) { + for (b = 0; b < sgh->init->uri_content_size; b++) hash += sgh->init->uri_content_array[b]; - } + return hash % ht->array_size; } -char SigGroupHeadMpmUriCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2) { +/** + * \brief The Compare function to be used by the mpm uri SigGroupHead hash + * table - DetectEngineCtx->sgh_mpm_uri_hash_table. + * + * \param data1 Pointer to the first SigGroupHead. + * \param len1 Not used. + * \param data2 Pointer to the second SigGroupHead. + * \param len2 Not used. + * + * \retval 1 If the 2 SigGroupHeads sent as args match. + * \retval 0 If the 2 SigGroupHeads sent as args do not match. + */ +char SigGroupHeadMpmUriCompareFunc(void *data1, uint16_t len1, void *data2, + uint16_t len2) +{ SigGroupHead *sgh1 = (SigGroupHead *)data1; SigGroupHead *sgh2 = (SigGroupHead *)data2; if (sgh1->init->uri_content_size != sgh2->init->uri_content_size) return 0; - if (memcmp(sgh1->init->uri_content_array,sgh2->init->uri_content_array,sgh1->init->uri_content_size) != 0) + if (memcmp(sgh1->init->uri_content_array, sgh2->init->uri_content_array, + sgh1->init->uri_content_size) != 0) { return 0; + } return 1; } -int SigGroupHeadMpmUriHashInit(DetectEngineCtx *de_ctx) { - de_ctx->sgh_mpm_uri_hash_table = HashListTableInit(4096, SigGroupHeadMpmUriHashFunc, SigGroupHeadMpmUriCompareFunc, NULL); +/** + * \brief Initializes the mpm uri hash table to be used by the detection engine + * context. + * + * \param de_ctx Pointer to the detection engine context. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int SigGroupHeadMpmUriHashInit(DetectEngineCtx *de_ctx) +{ + de_ctx->sgh_mpm_uri_hash_table = HashListTableInit(4096, + SigGroupHeadMpmUriHashFunc, + SigGroupHeadMpmUriCompareFunc, + NULL); if (de_ctx->sgh_mpm_uri_hash_table == NULL) goto error; return 0; + error: return -1; } -int SigGroupHeadMpmUriHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - return HashListTableAdd(de_ctx->sgh_mpm_uri_hash_table, (void *)sgh, 0); +/** + * \brief Adds a SigGroupHead to the detection engine context SigGroupHead + * mpm uri hash table. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval ret 0 on Successfully adding the argument sgh and -1 on failure. + */ +int SigGroupHeadMpmUriHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + int ret = HashListTableAdd(de_ctx->sgh_mpm_uri_hash_table, (void *)sgh, 0); + + return ret; } -SigGroupHead *SigGroupHeadMpmUriHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_uri_hash_table, (void *)sgh, 0); +/** + * \brief Used to lookup a SigGroupHead from the detection engine context + * SigGroupHead mpm uri hash table. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is + * found in the hash table; NULL on failure. + */ +SigGroupHead *SigGroupHeadMpmUriHashLookup(DetectEngineCtx *de_ctx, + SigGroupHead *sgh) +{ + SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_uri_hash_table, + (void *)sgh, 0); + return rsgh; } -void SigGroupHeadMpmUriHashFree(DetectEngineCtx *de_ctx) { +/** + * \brief Frees the hash table - DetectEngineCtx->sgh_mpm_uri_hash_table, + * allocated by SigGroupHeadMpmUriHashInit() function. + * + * \param de_ctx Pointer to the detection engine context. + */ +void SigGroupHeadMpmUriHashFree(DetectEngineCtx *de_ctx) +{ if (de_ctx->sgh_mpm_uri_hash_table == NULL) return; HashListTableFree(de_ctx->sgh_mpm_uri_hash_table); de_ctx->sgh_mpm_uri_hash_table = NULL; -} -/* non-port sgh hash */ + return; +} -uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen) { +/** + * \brief The hash function to be the used by the hash table - + * DetectEngineCtx->sgh_hash_table. + * + * \param ht Pointer to the hash table. + * \param data Pointer to the SigGroupHead. + * \param datalen Not used in our case. + * + * \retval hash The generated hash value. + */ +uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen) +{ SigGroupHead *sgh = (SigGroupHead *)data; uint32_t hash = 0; + uint32_t b = 0; + SCLogDebug("hashing sgh %p", sgh); - uint32_t b; - for (b = 0; b < sgh->sig_size; b+=1) { - hash += sgh->sig_array[b]; - } + for (b = 0; b < sgh->init->sig_size; b++) + hash += sgh->init->sig_array[b]; hash %= ht->array_size; SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->sig_size); return hash; } -char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2) { +/** + * \brief The Compare function to be used by the SigGroupHead hash table - + * DetectEngineCtx->sgh_hash_table. + * + * \param data1 Pointer to the first SigGroupHead. + * \param len1 Not used. + * \param data2 Pointer to the second SigGroupHead. + * \param len2 Not used. + * + * \retval 1 If the 2 SigGroupHeads sent as args match. + * \retval 0 If the 2 SigGroupHeads sent as args do not match. + */ +char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2, + uint16_t len2) +{ SigGroupHead *sgh1 = (SigGroupHead *)data1; SigGroupHead *sgh2 = (SigGroupHead *)data2; + if (data1 == NULL || data2 == NULL) + return 0; + if (sgh1->sig_size != sgh2->sig_size) return 0; - if (memcmp(sgh1->sig_array,sgh2->sig_array,sgh1->sig_size) != 0) + if (memcmp(sgh1->sig_array, sgh2->sig_array, sgh1->sig_size) != 0) return 0; return 1; } -/* sgh */ - -int SigGroupHeadHashInit(DetectEngineCtx *de_ctx) { - de_ctx->sgh_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc, SigGroupHeadCompareFunc, NULL); +/** + * \brief Initializes the hash table in the detection engine context to hold the + * SigGroupHeads. + * + * \param de_ctx Pointer to the detection engine context. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int SigGroupHeadHashInit(DetectEngineCtx *de_ctx) +{ + de_ctx->sgh_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc, + SigGroupHeadCompareFunc, NULL); if (de_ctx->sgh_hash_table == NULL) goto error; return 0; + error: return -1; } -int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - return HashListTableAdd(de_ctx->sgh_hash_table, (void *)sgh, 0); +/** + * \brief Adds a SigGroupHead to the detection engine context SigGroupHead + * hash table. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval ret 0 on Successfully adding the SigGroupHead; -1 on failure. + */ +int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + int ret = HashListTableAdd(de_ctx->sgh_hash_table, (void *)sgh, 0); + + return ret; } int SigGroupHeadHashRemove(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { return HashListTableRemove(de_ctx->sgh_hash_table, (void *)sgh, 0); } -SigGroupHead *SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_hash_table, (void *)sgh, 0); +/** + * \brief Used to lookup a SigGroupHead hash from the detection engine context + * SigGroupHead hash table. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is + * found in the hash table; NULL on failure. + */ +SigGroupHead *SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_hash_table, + (void *)sgh, 0); + return rsgh; } -void SigGroupHeadHashFree(DetectEngineCtx *de_ctx) { +/** + * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by + * SigGroupHeadHashInit() function. + * + * \param de_ctx Pointer to the detection engine context. + */ +void SigGroupHeadHashFree(DetectEngineCtx *de_ctx) +{ if (de_ctx->sgh_hash_table == NULL) return; HashListTableFree(de_ctx->sgh_hash_table); de_ctx->sgh_hash_table = NULL; -} -/* port based sgh hash */ - -/* dport */ + return; +} -int SigGroupHeadDPortHashInit(DetectEngineCtx *de_ctx) { - de_ctx->sgh_dport_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc, SigGroupHeadCompareFunc, NULL); +/** + * \brief Initializes the dport based SigGroupHead hash table to hold the + * SigGroupHeads. The hash table that would be initialized is + * DetectEngineCtx->sgh_dport_hash_table. + * + * \param de_ctx Pointer to the detection engine context. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int SigGroupHeadDPortHashInit(DetectEngineCtx *de_ctx) +{ + de_ctx->sgh_dport_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc, + SigGroupHeadCompareFunc, + NULL); if (de_ctx->sgh_dport_hash_table == NULL) goto error; return 0; + error: return -1; } -int SigGroupHeadDPortHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - return HashListTableAdd(de_ctx->sgh_dport_hash_table, (void *)sgh, 0); +/** + * \brief Adds a SigGroupHead to the detection engine context dport based + * SigGroupHead hash table(DetectEngineCtx->sgh_dport_hash_table). + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval ret 0 on Successfully adding the argument sgh and -1 on failure. + */ +int SigGroupHeadDPortHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + int ret = HashListTableAdd(de_ctx->sgh_dport_hash_table, (void *)sgh, 0); + + return ret; } -SigGroupHead *SigGroupHeadDPortHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_dport_hash_table, (void *)sgh, 0); +/** + * \brief Used to lookup a SigGroupHead hash from the detection engine ctx dport + * based SigGroupHead hash table(DetectEngineCtx->sgh_dport_hash_table). + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is + * found in the hash table; NULL on failure. + */ +SigGroupHead *SigGroupHeadDPortHashLookup(DetectEngineCtx *de_ctx, + SigGroupHead *sgh) +{ + SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_dport_hash_table, + (void *)sgh, 0); + return rsgh; } -void SigGroupHeadDPortHashFree(DetectEngineCtx *de_ctx) { +/** + * \brief Frees the hash table - DetectEngineCtx->sgh_dport_hash_table, + * allocated by the SigGroupHeadDPortHashInit() function. + * + * \param de_ctx Pointer to the detection engine context. + */ +void SigGroupHeadDPortHashFree(DetectEngineCtx *de_ctx) +{ if (de_ctx->dport_hash_table == NULL) return; HashListTableFree(de_ctx->sgh_dport_hash_table); de_ctx->sgh_dport_hash_table = NULL; -} -/* sport */ + return; +} -int SigGroupHeadSPortHashInit(DetectEngineCtx *de_ctx) { - de_ctx->sgh_sport_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc, SigGroupHeadCompareFunc, NULL); +/** + * \brief Initializes the sport based SigGroupHead hash table to hold the + * SigGroupHeads. The hash table that would be initialized is + * DetectEngineCtx->sgh_sport_hash_table. + * + * \param de_ctx Pointer to the detection engine context. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int SigGroupHeadSPortHashInit(DetectEngineCtx *de_ctx) +{ + de_ctx->sgh_sport_hash_table = HashListTableInit(4096, + SigGroupHeadHashFunc, + SigGroupHeadCompareFunc, + NULL); if (de_ctx->sgh_sport_hash_table == NULL) goto error; return 0; + error: return -1; } -int SigGroupHeadSPortHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - return HashListTableAdd(de_ctx->sgh_sport_hash_table, (void *)sgh, 0); +/** + * \brief Adds a SigGroupHead to the detection engine context dport based + * SigGroupHead hash table(DetectEngineCtx->sgh_sport_hash_table). + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval ret 0 on Successfully adding the argument sgh and -1 on failure. + */ +int SigGroupHeadSPortHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + int ret = HashListTableAdd(de_ctx->sgh_sport_hash_table, (void *)sgh, 0); + + return ret; } int SigGroupHeadSPortHashRemove(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { return HashListTableRemove(de_ctx->sgh_sport_hash_table, (void *)sgh, 0); } -SigGroupHead *SigGroupHeadSPortHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_sport_hash_table, (void *)sgh, 0); +/** + * \brief Used to lookup a SigGroupHead hash from the detection engine ctx sport + * based SigGroupHead hash table(DetectEngineCtx->sgh_dport_hash_table). + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is + * found in the hash table; NULL on failure. + */ +SigGroupHead *SigGroupHeadSPortHashLookup(DetectEngineCtx *de_ctx, + SigGroupHead *sgh) +{ + SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_sport_hash_table, + (void *)sgh, 0); + return rsgh; } -void SigGroupHeadSPortHashFree(DetectEngineCtx *de_ctx) { +/** + * \brief Frees the hash table - DetectEngineCtx->sgh_sport_hash_table, + * allocated by the SigGroupHeadSPortHashInit() function. + * + * \param de_ctx Pointer to the detection engine context. + */ +void SigGroupHeadSPortHashFree(DetectEngineCtx *de_ctx) +{ if (de_ctx->sport_hash_table == NULL) return; HashListTableFree(de_ctx->sgh_sport_hash_table); de_ctx->sgh_sport_hash_table = NULL; -} -/* end hashes */ + return; +} -static void SigGroupHeadFreeSigArraysHash2(DetectEngineCtx *de_ctx, HashListTable *ht) { +/** + * \brief Used to free the signature array, content_array and uri_content_array + * members from the SigGroupHeads in the HashListTable. + * + * \param de_ctx Pointer to the detection engine context. + * \param ht Pointer to the HashListTable + */ +static void SigGroupHeadFreeSigArraysHash2(DetectEngineCtx *de_ctx, + HashListTable *ht) +{ HashListTableBucket *htb = NULL; + SigGroupHead *sgh = NULL; - for (htb = HashListTableGetListHead(ht); htb != NULL; htb = HashListTableGetListNext(htb)) { - SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb); + for (htb = HashListTableGetListHead(ht); + htb != NULL; + htb = HashListTableGetListNext(htb)) { + sgh = (SigGroupHead *)HashListTableGetListData(htb); if (sgh->sig_array != NULL) { detect_siggroup_sigarray_free_cnt++; @@ -403,13 +733,27 @@ static void SigGroupHeadFreeSigArraysHash2(DetectEngineCtx *de_ctx, HashListTabl sgh->init = NULL; } } + + return; } -static void SigGroupHeadFreeSigArraysHash(DetectEngineCtx *de_ctx, HashListTable *ht) { +/** + * \brief Used to free the sig_array member of the SigGroupHeads present + * in the HashListTable. + * + * \param de_ctx Pointer to the detection engine context. + * \param ht Pointer to the HashListTable + */ +static void SigGroupHeadFreeSigArraysHash(DetectEngineCtx *de_ctx, + HashListTable *ht) +{ HashListTableBucket *htb = NULL; + SigGroupHead *sgh = NULL; - for (htb = HashListTableGetListHead(ht); htb != NULL; htb = HashListTableGetListNext(htb)) { - SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb); + for (htb = HashListTableGetListHead(ht); + htb != NULL; + htb = HashListTableGetListNext(htb)) { + sgh = (SigGroupHead *)HashListTableGetListData(htb); if (sgh->sig_array != NULL) { detect_siggroup_sigarray_free_cnt++; @@ -425,21 +769,35 @@ static void SigGroupHeadFreeSigArraysHash(DetectEngineCtx *de_ctx, HashListTable sgh->init = NULL; } } + + return; } -/* Free the sigarrays in the sgh's. Those are only - * used during the init stage. */ -void SigGroupHeadFreeSigArrays(DetectEngineCtx *de_ctx) { +/** + * \brief Free the sigarrays in the sgh's. Those are only used during the init + * stage. + * + * \param de_ctx Pointer to the detection engine context whose sigarrays have to + * be freed. + */ +void SigGroupHeadFreeSigArrays(DetectEngineCtx *de_ctx) +{ SigGroupHeadFreeSigArraysHash2(de_ctx, de_ctx->sgh_hash_table); - SigGroupHeadFreeSigArraysHash(de_ctx, de_ctx->sgh_dport_hash_table); SigGroupHeadFreeSigArraysHash(de_ctx, de_ctx->sgh_sport_hash_table); + + return; } -/* Free the mpm arrays that are only used during the - * init stage */ -void SigGroupHeadFreeMpmArrays(DetectEngineCtx *de_ctx) { +/** + * \brief Free the mpm arrays that are only used during the init stage. + * + * \param de_ctx Pointer to the detection engine context. + */ +void SigGroupHeadFreeMpmArrays(DetectEngineCtx *de_ctx) +{ HashListTableBucket *htb = NULL; + SigGroupHead *sgh = NULL; for (htb = HashListTableGetListHead(de_ctx->sgh_dport_hash_table); htb != NULL; htb = HashListTableGetListNext(htb)) { SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb); @@ -456,16 +814,24 @@ void SigGroupHeadFreeMpmArrays(DetectEngineCtx *de_ctx) { sgh->init = NULL; } } + + return; } -/** \brief Add a signature to a sgh - * \param de_ctx detection engine ctx - * \param sgh pointer to a sgh, can be NULL - * \param s signature to append - * \retval 0 success - * \retval -1 error +/** + * \brief Add a Signature to a SigGroupHead. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to a SigGroupHead. Can be NULL also. + * \param s Pointer to the Signature that has to be added to the + * SigGroupHead. + * + * \retval 0 On success. + * \retval -1 On failure. */ -int SigGroupHeadAppendSig(DetectEngineCtx *de_ctx, SigGroupHead **sgh, Signature *s) { +int SigGroupHeadAppendSig(DetectEngineCtx *de_ctx, SigGroupHead **sgh, + Signature *s) +{ if (de_ctx == NULL) return 0; @@ -498,41 +864,58 @@ int SigGroupHeadAppendSig(DetectEngineCtx *de_ctx, SigGroupHead **sgh, Signature } } return 0; + error: return -1; } -int SigGroupHeadClearSigs(SigGroupHead *sgh) { +/** + * \brief Clears the bitarray holding the sids for this SigGroupHead. + * + * \param sgh Pointer to the SigGroupHead. + * + * \retval 0 Always. + */ +int SigGroupHeadClearSigs(SigGroupHead *sgh) +{ if (sgh == NULL) return 0; - if (sgh->sig_array != NULL) { - memset(sgh->sig_array,0,sgh->sig_size); - } + if (sgh->sig_array != NULL) + memset(sgh->sig_array, 0, sgh->sig_size); + sgh->sig_cnt = 0; - sgh->mpm_content_maxlen = 0; - sgh->mpm_uricontent_maxlen = 0; return 0; } -/** \brief copy signature array from one sgh to another */ -int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst) { +/** + * \brief Copies the bitarray holding the sids from the source SigGroupHead to + * the destination SigGroupHead. + * + * \param de_ctx Pointer to the detection engine context. + * \param src Pointer to the source SigGroupHead. + * \param dst Pointer to the destination SigGroupHead. + * + * \retval 0 On success. + * \retval -1 On failure. + */ +int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst) +{ + uint32_t idx = 0; + if (src == NULL || de_ctx == NULL) return 0; if (*dst == NULL) { *dst = SigGroupHeadAlloc(DetectEngineGetMaxSigId(de_ctx) / 8 + 1); - if (*dst == NULL) { + if (*dst == NULL) goto error; - } } /* do the copy */ - uint32_t idx; - for (idx = 0; idx < src->sig_size; idx++) { + for (idx = 0; idx < src->sig_size; idx++) (*dst)->sig_array[idx] = (*dst)->sig_array[idx] | src->sig_array[idx]; - } if (src->mpm_content_maxlen != 0) { if ((*dst)->mpm_content_maxlen == 0) @@ -553,97 +936,181 @@ int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHea (*dst)->mpm_uricontent_maxlen = src->mpm_uricontent_maxlen; } return 0; + error: return -1; } -void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx) { +/** + * \brief Updates the SigGroupHead->sig_cnt with the total count of all the + * Signatures present in this SigGroupHead. + * + * \param sgh Pointer to the SigGroupHead. + * \param max_idx Maximum sid of the all the Signatures present in this + * SigGroupHead. + */ +void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx) +{ uint32_t sig; - for (sig = 0; sig < max_idx+1; sig++) { - if (sgh->sig_array[(sig/8)] & (1<<(sig%8))) { + for (sig = 0; sig < max_idx + 1; sig++) { + if (sgh->sig_array[sig / 8] & (1 << (sig % 8))) sgh->sig_cnt++; - } } + + return; +} + +/** + * \brief Prints the memory statistics for the detect-engine-siggroup.[ch] module. + */ +void DetectSigGroupPrintMemory(void) +{ + SCLogDebug(" * Sig group head memory stats (SigGroupHead %" PRIuMAX "):", + (uintmax_t)sizeof(SigGroupHead)); + SCLogDebug(" - detect_siggroup_head_memory %" PRIu32, + detect_siggroup_head_memory); + SCLogDebug(" - detect_siggroup_head_init_cnt %" PRIu32, + detect_siggroup_head_init_cnt); + SCLogDebug(" - detect_siggroup_head_free_cnt %" PRIu32, + detect_siggroup_head_free_cnt); + SCLogDebug(" - outstanding sig group heads %" PRIu32, + detect_siggroup_head_init_cnt - detect_siggroup_head_free_cnt); + SCLogDebug(" * Sig group head memory stats done"); + SCLogDebug(" * Sig group head initdata memory stats (SigGroupHeadInitData %" PRIuMAX "):", + (uintmax_t)sizeof(SigGroupHeadInitData)); + SCLogDebug(" - detect_siggroup_head_initdata_memory %" PRIu32, + detect_siggroup_head_initdata_memory); + SCLogDebug(" - detect_siggroup_head_initdata_init_cnt %" PRIu32, + detect_siggroup_head_initdata_init_cnt); + SCLogDebug(" - detect_siggroup_head_initdata_free_cnt %" PRIu32, + detect_siggroup_head_initdata_free_cnt); + SCLogDebug(" - outstanding sig group head initdatas %" PRIu32, + detect_siggroup_head_initdata_init_cnt - detect_siggroup_head_initdata_free_cnt); + SCLogDebug(" * Sig group head memory initdata stats done"); + SCLogDebug(" * Sig group sigarray memory stats:"); + SCLogDebug(" - detect_siggroup_sigarray_memory %" PRIu32, + detect_siggroup_sigarray_memory); + SCLogDebug(" - detect_siggroup_sigarray_init_cnt %" PRIu32, + detect_siggroup_sigarray_init_cnt); + SCLogDebug(" - detect_siggroup_sigarray_free_cnt %" PRIu32, + detect_siggroup_sigarray_free_cnt); + SCLogDebug(" - outstanding sig group sigarrays %" PRIu32, + (detect_siggroup_sigarray_init_cnt - + detect_siggroup_sigarray_free_cnt)); + SCLogDebug(" * Sig group sigarray memory stats done"); + SCLogDebug(" * Sig group matcharray memory stats:"); + SCLogDebug(" - detect_siggroup_matcharray_memory %" PRIu32, + detect_siggroup_matcharray_memory); + SCLogDebug(" - detect_siggroup_matcharray_init_cnt %" PRIu32, + detect_siggroup_matcharray_init_cnt); + SCLogDebug(" - detect_siggroup_matcharray_free_cnt %" PRIu32, + detect_siggroup_matcharray_free_cnt); + SCLogDebug(" - outstanding sig group matcharrays %" PRIu32, + (detect_siggroup_matcharray_init_cnt - + detect_siggroup_matcharray_free_cnt)); + SCLogDebug(" * Sig group sigarray memory stats done"); + SCLogDebug(" X Total %" PRIu32, + (detect_siggroup_head_memory + detect_siggroup_sigarray_memory + + detect_siggroup_matcharray_memory)); + + return; } -void DetectSigGroupPrintMemory(void) { - printf(" * Sig group head memory stats (SigGroupHead %" PRIuMAX "):\n", (uintmax_t)sizeof(SigGroupHead)); - printf(" - detect_siggroup_head_memory %" PRIu32 "\n", detect_siggroup_head_memory); - printf(" - detect_siggroup_head_init_cnt %" PRIu32 "\n", detect_siggroup_head_init_cnt); - printf(" - detect_siggroup_head_free_cnt %" PRIu32 "\n", detect_siggroup_head_free_cnt); - printf(" - outstanding sig group heads %" PRIu32 "\n", detect_siggroup_head_init_cnt - detect_siggroup_head_free_cnt); - printf(" * Sig group head memory stats done\n"); - printf(" * Sig group head initdata memory stats (SigGroupHeadInitData %" PRIuMAX "):\n", (uintmax_t)sizeof(SigGroupHeadInitData)); - printf(" - detect_siggroup_head_initdata_memory %" PRIu32 "\n", detect_siggroup_head_initdata_memory); - printf(" - detect_siggroup_head_initdata_init_cnt %" PRIu32 "\n", detect_siggroup_head_initdata_init_cnt); - printf(" - detect_siggroup_head_initdata_free_cnt %" PRIu32 "\n", detect_siggroup_head_initdata_free_cnt); - printf(" - outstanding sig group head initdatas %" PRIu32 "\n", detect_siggroup_head_initdata_init_cnt - detect_siggroup_head_initdata_free_cnt); - printf(" * Sig group head memory initdata stats done\n"); - printf(" * Sig group sigarray memory stats:\n"); - printf(" - detect_siggroup_sigarray_memory %" PRIu32 "\n", detect_siggroup_sigarray_memory); - printf(" - detect_siggroup_sigarray_init_cnt %" PRIu32 "\n", detect_siggroup_sigarray_init_cnt); - printf(" - detect_siggroup_sigarray_free_cnt %" PRIu32 "\n", detect_siggroup_sigarray_free_cnt); - printf(" - outstanding sig group sigarrays %" PRIu32 "\n", detect_siggroup_sigarray_init_cnt - detect_siggroup_sigarray_free_cnt); - printf(" * Sig group sigarray memory stats done\n"); - printf(" * Sig group matcharray memory stats:\n"); - printf(" - detect_siggroup_matcharray_memory %" PRIu32 "\n", detect_siggroup_matcharray_memory); - printf(" - detect_siggroup_matcharray_init_cnt %" PRIu32 "\n", detect_siggroup_matcharray_init_cnt); - printf(" - detect_siggroup_matcharray_free_cnt %" PRIu32 "\n", detect_siggroup_matcharray_free_cnt); - printf(" - outstanding sig group matcharrays %" PRIu32 "\n", detect_siggroup_matcharray_init_cnt - detect_siggroup_matcharray_free_cnt); - printf(" * Sig group sigarray memory stats done\n"); - printf(" X Total %" PRIu32 "\n", detect_siggroup_head_memory + detect_siggroup_sigarray_memory + detect_siggroup_matcharray_memory); -} - -void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - printf("SigGroupHeadPrintSigs: "); +/** + * \brief Helper function used to print the list of sids for the Signatures + * present in this SigGroupHead. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + */ +void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + SCEnter(); uint32_t i; + + SCLogDebug("The Signatures present in this SigGroupHead are: "); for (i = 0; i < sgh->sig_size; i++) { - if (sgh->sig_array[(i/8)] & (1<<(i%8))) { - printf("%" PRIu32 " ", i); - } + if (sgh->sig_array[i / 8] & (1 << (i % 8))) + SCLogDebug("%" PRIu32, i); } - printf("\n"); + SCReturn; } -void SigGroupHeadPrintContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - printf("SigGroupHeadPrintContent: "); +/** + * \brief Helper function used to print the content ids of all the contents that + * have been added to the bitarray of this SigGroupHead. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + */ +void SigGroupHeadPrintContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + SCEnter(); - uint32_t i; + uint32_t i = 0; + + SCLogDebug("Contents with the following content ids are present in this " + "SigGroupHead - "); for (i = 0; i < DetectContentMaxId(de_ctx); i++) { - if (sgh->init->content_array[(i/8)] & (1<<(i%8))) { - printf("%" PRIu32 " ", i); - } + if (sgh->init->content_array[i / 8] & (1 << (i % 8))) + SCLogDebug("%" PRIu32, i); } - printf("\n"); + SCReturn; } -void SigGroupHeadPrintContentCnt(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { - printf("SigGroupHeadPrintContent: "); +/** + * \brief Helper function used to print the total no of contents that have + * been added to the bitarray for this SigGroupHead. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + */ +void SigGroupHeadPrintContentCnt(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + SCEnter(); + + uint32_t i = 0; + uint32_t cnt = 0; - uint32_t i, cnt = 0; for (i = 0; i < DetectContentMaxId(de_ctx); i++) { - if (sgh->init->content_array[(i/8)] & (1<<(i%8))) { + if (sgh->init->content_array[i / 8] & (1 << (i % 8))) cnt++; - } } - printf("cnt %" PRIu32 "\n", cnt); + SCLogDebug("Total contents added to the SigGroupHead content bitarray: " + "%" PRIu32, cnt); + + SCReturn; } -/* load all pattern id's into a single bitarray that we can memcmp - * with other bitarrays. A fast and efficient way of comparing pattern - * sets. */ -int SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { +/** + * \brief Loads all the content ids from all the contents belonging to all the + * Signatures in this SigGroupHead, into a bitarray. A fast and an + * efficient way of comparing pattern sets. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval 0 On success, i.e. on either the detection engine context being NULL + * or on succesfully allocating memory and updating it with relevant + * data. + * \retval -1 On failure. + */ +int SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + Signature *s = NULL; + SigMatch *sm = NULL; + uint32_t sig = 0; + SigIntId num = 0; + DetectContentData *co = NULL; + if (sgh == NULL) return 0; - Signature *s; - SigMatch *sm; - if (DetectContentMaxId(de_ctx) == 0) return 0; @@ -656,9 +1123,8 @@ int SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { memset(sgh->init->content_array,0, sgh->init->content_size); - uint32_t sig; for (sig = 0; sig < sgh->sig_cnt; sig++) { - SigIntId num = sgh->match_array[sig]; + num = sgh->match_array[sig]; s = de_ctx->sig_array[num]; if (s == NULL) @@ -671,11 +1137,11 @@ int SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { if (sm == NULL) continue; - for ( ; sm != NULL; sm = sm->next) { + for ( ;sm != NULL; sm = sm->next) { if (sm->type == DETECT_CONTENT) { - DetectContentData *co = (DetectContentData *)sm->ctx; + co = (DetectContentData *)sm->ctx; - sgh->init->content_array[(co->id/8)] |= 1<<(co->id%8); + sgh->init->content_array[co->id / 8] |= 1 << (co->id % 8); } } } @@ -683,8 +1149,17 @@ int SigGroupHeadLoadContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { return 0; } -int SigGroupHeadClearContent(SigGroupHead *sh) { - if (sh == NULL || sh->init == NULL) +/** + * \brief Clears the memory allocated by SigGroupHeadLoadContent() for the + * bitarray to hold the content ids for a SigGroupHead. + * + * \param Pointer to the SigGroupHead whose content_array would to be cleared. + * + * \ret 0 Always. + */ +int SigGroupHeadClearContent(SigGroupHead *sh) +{ + if (sh == NULL) return 0; if (sh->init->content_array != NULL) { @@ -695,13 +1170,30 @@ int SigGroupHeadClearContent(SigGroupHead *sh) { return 0; } -int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { +/** + * \brief Loads all the uri content ids from all the uri contents belonging to + * all the Signatures in this SigGroupHead, into a bitarray. A fast and + * an efficient way of comparing pattern sets. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * + * \retval 0 On success, i.e. on either the detection engine context being NULL + * or on succesfully allocating memory and updating it with relevant + * data. + * \retval -1 On failure. + */ +int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) +{ + Signature *s = NULL; + SigMatch *sm = NULL; + uint32_t sig = 0; + SigIntId num = 0; + DetectUricontentData *co = NULL; + if (sgh == NULL) return 0; - Signature *s; - SigMatch *sm; - if (DetectUricontentMaxId(de_ctx) == 0) return 0; @@ -714,9 +1206,8 @@ int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { memset(sgh->init->uri_content_array, 0, sgh->init->uri_content_size); - uint32_t sig; for (sig = 0; sig < sgh->sig_cnt; sig++) { - SigIntId num = sgh->match_array[sig]; + num = sgh->match_array[sig]; s = de_ctx->sig_array[num]; if (s == NULL) @@ -729,19 +1220,30 @@ int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) { if (sm == NULL) continue; - for ( ; sm != NULL; sm = sm->next) { + for ( ;sm != NULL; sm = sm->next) { if (sm->type == DETECT_URICONTENT) { - DetectUricontentData *co = (DetectUricontentData *)sm->ctx; + co = (DetectUricontentData *)sm->ctx; - sgh->init->uri_content_array[(co->id/8)] |= 1<<(co->id%8); + sgh->init->uri_content_array[co->id / 8] |= 1 << (co->id % 8); } } } + return 0; } -int SigGroupHeadClearUricontent(SigGroupHead *sh) { - if (sh == NULL||sh->init == NULL) +/** + * \brief Clears the memory allocated by SigGroupHeadLoadUriContent() for the + * bitarray to hold the uri content ids for a SigGroupHead. + * + * \param Pointer to the SigGroupHead whose uri_content_array would to be + * cleared. + * + * \ret 0 Always. + */ +int SigGroupHeadClearUricontent(SigGroupHead *sh) +{ + if (sh == NULL) return 0; if (sh->init->uri_content_array != NULL) { @@ -753,15 +1255,21 @@ int SigGroupHeadClearUricontent(SigGroupHead *sh) { return 0; } -/** \brief Create an array with all the internal id's of the sigs that this - * sig group head will check for. - * \param de_ctx detection engine ctx - * \param sgh sig group head - * \param max_idx max idx for deternmining the array size - * \retval 0 success - * \retval -1 error +/** + * \brief Create an array with all the internal ids of the sigs that this + * sig group head will check for. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead. + * \param max_idx The maximum value of the sid in the SigGroupHead arg. + * + * \retval 0 success + * \retval -1 error */ -int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t max_idx) { +int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh, + uint32_t max_idx) +{ + Signature *s = NULL; uint32_t idx = 0; uint32_t sig = 0; @@ -779,11 +1287,11 @@ int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, uin detect_siggroup_matcharray_init_cnt++; detect_siggroup_matcharray_memory += (sgh->sig_cnt * sizeof(SigIntId)); - for (sig = 0; sig < max_idx+1; sig++) { - if (!(sgh->sig_array[(sig/8)] & (1<<(sig%8)))) + for (sig = 0; sig < max_idx + 1; sig++) { + if ( !(sgh->sig_array[(sig / 8)] & (1 << (sig % 8))) ) continue; - Signature *s = de_ctx->sig_array[sig]; + s = de_ctx->sig_array[sig]; if (s == NULL) continue; @@ -794,33 +1302,544 @@ int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, uin return 0; } -/** \brief Check if a sgh contains a sid - * \param de_ctx detection engine ctx - * \param sgh sig group head - * \param sid the signature id to check for - * \retval 0 no - * \retval 1 yes +/** + * \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an + * argument. + * + * \param de_ctx Pointer to the detection engine context. + * \param sgh Pointer to the SigGroupHead that has to be checked for the + * presence of a Signature. + * \param sid The Signature id(sid) that has to be checked in the SigGroupHead. + * + * \retval 1 On successfully finding the sid in the SigGroupHead. + * \retval 0 If the sid is not found in the SigGroupHead */ -int SigGroupHeadContainsSigId (DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid) { +int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh, + uint32_t sid) +{ uint32_t sig = 0; + Signature *s = NULL; + uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx); if (sgh == NULL) return 0; - for (sig = 0; sig < sgh->sig_cnt; sig++) { + for (sig = 0; sig < max_sid; sig++) { if (sgh->sig_array == NULL) return 0; - if (!(sgh->sig_array[(sig/8)] & (1<<(sig%8)))) + /* Check if the SigGroupHead has an entry for the sid */ + if ( !(sgh->sig_array[sig / 8] & (1 << (sig % 8))) ) continue; - Signature *s = de_ctx->sig_array[sig]; + /* If we have reached here, we have an entry for sid in the SigGrouHead. + * Retrieve the Signature from the detection engine context */ + s = de_ctx->sig_array[sig]; if (s == NULL) continue; + /* If the retrieved Signature matches the sid arg, we have a match */ if (s->id == sid) return 1; } return 0; } + +/*----------------------------------Unittests---------------------------------*/ + +#ifdef UNITTESTS + +int SigAddressPrepareStage1(DetectEngineCtx *); + +/** + * \test Check if a SigGroupHead mpm hash table is properly allocated and + * deallocated when calling SigGroupHeadMpmHashInit() and + * SigGroupHeadMpmHashFree() respectively. + */ +static int SigGroupHeadTest01(void) +{ + int result = 1; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + SigGroupHeadMpmHashInit(de_ctx); + + result &= (de_ctx->sgh_mpm_hash_table != NULL); + + SigGroupHeadMpmHashFree(de_ctx); + + result &= (de_ctx->sgh_mpm_hash_table == NULL); + + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Check if a SigGroupHead mpm uri hash table is properly allocated and + * deallocated when calling SigGroupHeadMpmUriHashInit() and + * SigGroupHeadMpmUriHashFree() respectively. + */ +static int SigGroupHeadTest02(void) +{ + int result = 1; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + SigGroupHeadMpmUriHashInit(de_ctx); + + result &= (de_ctx->sgh_mpm_uri_hash_table != NULL); + + SigGroupHeadMpmUriHashFree(de_ctx); + + result &= (de_ctx->sgh_mpm_uri_hash_table == NULL); + + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Check if a SigGroupHead hash table is properly allocated and + * deallocated when calling SigGroupHeadHashInit() and + * SigGroupHeadHashFree() respectively. + */ +static int SigGroupHeadTest03(void) +{ + int result = 1; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + SigGroupHeadHashInit(de_ctx); + + result &= (de_ctx->sgh_hash_table != NULL); + + SigGroupHeadHashFree(de_ctx); + + result &= (de_ctx->sgh_hash_table == NULL); + + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Check if a SigGroupHead dport hash table is properly allocated and + * deallocated when calling SigGroupHeadDPortHashInit() and + * SigGroupHeadDportHashFree() respectively. + */ +static int SigGroupHeadTest04(void) +{ + int result = 1; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + SigGroupHeadDPortHashInit(de_ctx); + + result &= (de_ctx->sgh_dport_hash_table != NULL); + + SigGroupHeadDPortHashFree(de_ctx); + + result &= (de_ctx->sgh_dport_hash_table == NULL); + + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Check if a SigGroupHead dport hash table is properly allocated and + * deallocated when calling SigGroupHeadSPortHashInit() and + * SigGroupHeadSportHashFree() respectively. + */ +static int SigGroupHeadTest05(void) +{ + int result = 1; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + + SigGroupHeadSPortHashInit(de_ctx); + + result &= (de_ctx->sgh_sport_hash_table != NULL); + + SigGroupHeadSPortHashFree(de_ctx); + + result &= (de_ctx->sgh_sport_hash_table == NULL); + + DetectEngineCtxFree(de_ctx); + + return result; +} + +/** + * \test Check if a SigGroupHeadAppendSig() correctly appends a sid to a + * SigGroupHead() and SigGroupHeadContainsSigId() correctly indicates + * the presence of a sid. + */ +static int SigGroupHeadTest06(void) +{ + int result = 1; + SigGroupHead *sh = NULL; + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + Signature *prev_sig = NULL; + + if (de_ctx == NULL) + return 0; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:0;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + prev_sig = de_ctx->sig_list; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:1;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:2;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:3;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:4;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + SigAddressPrepareStage1(de_ctx); + + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list); + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next); + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next); + + SigGroupHeadSetSigCnt(sh, 4); + + result &= (sh->sig_cnt == 3); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 0) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 1); + + SigGroupHeadFree(sh); + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + * \test Check if a SigGroupHeadAppendSig(), correctly appends a sid to a + * SigGroupHead() and SigGroupHeadContainsSigId(), correctly indicates + * the presence of a sid and SigGroupHeadClearSigs(), correctly clears + * the SigGroupHead->sig_array and SigGroupHead->sig_cnt. + */ +static int SigGroupHeadTest07(void) +{ + int result = 1; + SigGroupHead *sh = NULL; + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + Signature *prev_sig = NULL; + + if (de_ctx == NULL) + return 0; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:0;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + prev_sig = de_ctx->sig_list; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:1;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:2;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:3;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:4;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + SigAddressPrepareStage1(de_ctx); + + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list); + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next); + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next); + + SigGroupHeadSetSigCnt(sh, 4); + + result &= (sh->sig_cnt == 3); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 0) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 1); + + SigGroupHeadClearSigs(sh); + + result &= (sh->sig_cnt == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 0) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0); + + SigGroupHeadFree(sh); + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + * \test Check if SigGroupHeadCopySigs(), correctly copies the sig_array from + * the source to the destination SigGroupHead. + */ +static int SigGroupHeadTest08(void) +{ + int result = 1; + SigGroupHead *src_sh = NULL; + SigGroupHead *dst_sh = NULL; + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + Signature *prev_sig = NULL; + + if (de_ctx == NULL) + return 0; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:0;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + prev_sig = de_ctx->sig_list; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:1;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:2;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:3;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:4;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + SigAddressPrepareStage1(de_ctx); + + SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list); + SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next); + SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next->next->next); + + SigGroupHeadSetSigCnt(src_sh, 4); + + result &= (src_sh->sig_cnt == 3); + result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 0) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 1) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 2) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 3) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, src_sh, 4) == 1); + + SigGroupHeadCopySigs(de_ctx, src_sh, &dst_sh); + + SigGroupHeadSetSigCnt(dst_sh, 4); + + result &= (dst_sh->sig_cnt == 3); + result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 0) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 1) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 2) == 1); + result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 3) == 0); + result &= (SigGroupHeadContainsSigId(de_ctx, dst_sh, 4) == 1); + + SigGroupHeadFree(src_sh); + SigGroupHeadFree(dst_sh); + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +/** + * \test Check if SigGroupHeadBuildMatchArray(), correctly updates the + * match array with the sids. + */ +static int SigGroupHeadTest09(void) +{ + int result = 1; + SigGroupHead *sh = NULL; + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + Signature *prev_sig = NULL; + + if (de_ctx == NULL) + return 0; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:0;)"); + if (de_ctx->sig_list == NULL) { + result = 0; + goto end; + } + prev_sig = de_ctx->sig_list; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:1;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:2;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:3;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + prev_sig->next = SigInit(de_ctx, "alert tcp any any -> any any " + "(msg:\"SigGroupHead tests\"; content:test1; " + "content:test2; content:test3; sid:4;)"); + if (prev_sig->next == NULL) { + result = 0; + goto end; + } + prev_sig = prev_sig->next; + + SigAddressPrepareStage1(de_ctx); + + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list); + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next); + SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next); + + SigGroupHeadSetSigCnt(sh, 4); + SigGroupHeadBuildMatchArray(de_ctx, sh, 4); + + result &= (sh->match_array[0] == 0); + result &= (sh->match_array[1] == 2); + result &= (sh->match_array[2] == 4); + + SigGroupHeadFree(sh); + + end: + SigCleanSignatures(de_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} + +#endif + +void SigGroupHeadRegisterTests(void) +{ + +#ifdef UNITTESTS + + UtRegisterTest("SigGroupHeadTest01", SigGroupHeadTest01, 1); + UtRegisterTest("SigGroupHeadTest02", SigGroupHeadTest02, 1); + UtRegisterTest("SigGroupHeadTest03", SigGroupHeadTest03, 1); + UtRegisterTest("SigGroupHeadTest04", SigGroupHeadTest04, 1); + UtRegisterTest("SigGroupHeadTest05", SigGroupHeadTest05, 1); + UtRegisterTest("SigGroupHeadTest06", SigGroupHeadTest06, 1); + UtRegisterTest("SigGroupHeadTest07", SigGroupHeadTest07, 1); + UtRegisterTest("SigGroupHeadTest08", SigGroupHeadTest08, 1); + UtRegisterTest("SigGroupHeadTest09", SigGroupHeadTest09, 1); + +#endif + +} diff --git a/src/detect-engine-siggroup.h b/src/detect-engine-siggroup.h index f464fa326a..42b20bfc7e 100644 --- a/src/detect-engine-siggroup.h +++ b/src/detect-engine-siggroup.h @@ -1,3 +1,7 @@ +/** Copyright (c) 2009 Open Information Security Foundation. + * \author Victor Julien + */ + #ifndef __DETECT_ENGINE_SIGGROUP_H__ #define __DETECT_ENGINE_SIGGROUP_H__ @@ -45,10 +49,13 @@ int SigGroupHeadSPortHashRemove(DetectEngineCtx *, SigGroupHead *); void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid); void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx); -int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t max_idx); +int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, + uint32_t max_idx); void SigGroupHeadFreeSigArrays(DetectEngineCtx *de_ctx); -int SigGroupHeadContainsSigId (DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t sid); +int SigGroupHeadContainsSigId (DetectEngineCtx *de_ctx, SigGroupHead *sgh, + uint32_t sid); -#endif /* __DETECT_ENGINE_SIGGROUP_H__ */ +void SigGroupHeadRegisterTests(void); +#endif /* __DETECT_ENGINE_SIGGROUP_H__ */ diff --git a/src/detect.c b/src/detect.c index 776aa57229..1e244666cf 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1036,7 +1036,12 @@ int CreateGroupedAddrListCmpMpmMaxlen(DetectAddress *a, DetectAddress *b) { * srchead is a ordered "inserted" list w/o internal overlap * */ -int CreateGroupedAddrList(DetectEngineCtx *de_ctx, DetectAddress *srchead, int family, DetectAddresssHead *newhead, uint32_t unique_groups, int (*CompareFunc)(DetectAddress *, DetectAddress *), uint32_t max_idx) { +int CreateGroupedAddrList(DetectEngineCtx *de_ctx, DetectAddress *srchead, + int family, DetectAddresssHead *newhead, + uint32_t unique_groups, + int (*CompareFunc)(DetectAddress *, DetectAddress *), + uint32_t max_idx) +{ DetectAddress *tmplist = NULL, *tmplist2 = NULL, *joingr = NULL; char insert = 0; DetectAddress *gr, *next_gr; @@ -1541,7 +1546,7 @@ int BuildDestinationAddressHeads(DetectEngineCtx *de_ctx, DetectAddresssHead *he DetectAddress *grhead = NULL, *grdsthead = NULL, *grsighead = NULL; /* based on the family, select the list we are using in the head */ - grhead = GetHeadPtr(head,family); + grhead = GetHeadPtr(head, family); /* loop through the global source address list */ for (gr = grhead; gr != NULL; gr = gr->next) { @@ -1564,6 +1569,7 @@ int BuildDestinationAddressHeads(DetectEngineCtx *de_ctx, DetectAddresssHead *he continue; tmp_s = de_ctx->sig_array[sig]; + if (tmp_s == NULL) continue; @@ -1582,7 +1588,7 @@ int BuildDestinationAddressHeads(DetectEngineCtx *de_ctx, DetectAddresssHead *he DetectAddressAdd(&tmp_gr_list,grtmp); } else { /* our group will only have one sig, this one. So add that. */ - SigGroupHeadAppendSig(de_ctx,&lookup_gr->sh,tmp_s); + SigGroupHeadAppendSig(de_ctx, &lookup_gr->sh, tmp_s); lookup_gr->cnt++; } } @@ -1610,7 +1616,7 @@ int BuildDestinationAddressHeads(DetectEngineCtx *de_ctx, DetectAddresssHead *he if (sgh == NULL) { /* put the contents in our sig group head */ SigGroupHeadSetSigCnt(sgr->sh, max_idx); - SigGroupHeadBuildMatchArray(de_ctx,sgr->sh, max_idx); + SigGroupHeadBuildMatchArray(de_ctx, sgr->sh, max_idx); /* content */ SigGroupHeadLoadContent(de_ctx, sgr->sh); diff --git a/src/eidps.c b/src/eidps.c index c0c86a6acf..03a606e0a5 100644 --- a/src/eidps.c +++ b/src/eidps.c @@ -78,6 +78,7 @@ #include "util-debug.h" #include "util-error.h" +#include "detect-engine-siggroup.h" /* * we put this here, because we only use it here in main. @@ -466,6 +467,7 @@ int main(int argc, char **argv) SCLogRegisterTests(); SCRadixRegisterTests(); DefragRegisterTests(); + SigGroupHeadRegisterTests(); if (list_unittests) { UtListTests(regex_arg); }