|
|
|
/* sig group
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "decode.h"
|
|
|
|
#include "detect.h"
|
|
|
|
#include "flow-var.h"
|
|
|
|
|
|
|
|
#include "util-cidr.h"
|
|
|
|
#include "util-unittest.h"
|
|
|
|
|
|
|
|
#include "detect.h"
|
|
|
|
#include "detect-engine.h"
|
|
|
|
#include "detect-engine-address.h"
|
|
|
|
#include "detect-engine-mpm.h"
|
|
|
|
#include "detect-engine-siggroup.h"
|
|
|
|
|
|
|
|
#include "detect-content.h"
|
|
|
|
#include "detect-uricontent.h"
|
|
|
|
|
|
|
|
#include "util-hash.h"
|
|
|
|
#include "util-hashlist.h"
|
|
|
|
|
|
|
|
/* prototypes */
|
|
|
|
int SigGroupHeadClearSigs(SigGroupHead *);
|
|
|
|
|
|
|
|
static u_int32_t detect_siggroup_head_memory = 0;
|
|
|
|
static u_int32_t detect_siggroup_head_init_cnt = 0;
|
|
|
|
static u_int32_t detect_siggroup_head_free_cnt = 0;
|
|
|
|
static u_int32_t detect_siggroup_sigarray_memory = 0;
|
|
|
|
static u_int32_t detect_siggroup_sigarray_init_cnt = 0;
|
|
|
|
static u_int32_t detect_siggroup_sigarray_free_cnt = 0;
|
|
|
|
static u_int32_t detect_siggroup_matcharray_memory = 0;
|
|
|
|
static u_int32_t detect_siggroup_matcharray_init_cnt = 0;
|
|
|
|
static u_int32_t detect_siggroup_matcharray_free_cnt = 0;
|
|
|
|
|
|
|
|
/* Free a sgh */
|
|
|
|
void SigGroupHeadFree(SigGroupHead *sh) {
|
|
|
|
if (sh == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PatternMatchDestroyGroup(sh);
|
|
|
|
SigGroupHeadClearSigs(sh);
|
|
|
|
|
|
|
|
if (sh->sig_array != NULL) {
|
|
|
|
free(sh->sig_array);
|
|
|
|
sh->sig_array = NULL;
|
|
|
|
|
|
|
|
detect_siggroup_sigarray_free_cnt++;
|
|
|
|
detect_siggroup_sigarray_memory -= sh->sig_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sh->content_array != NULL) {
|
|
|
|
free(sh->content_array);
|
|
|
|
sh->content_array = NULL;
|
|
|
|
sh->content_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sh->uri_content_array != NULL) {
|
|
|
|
free(sh->uri_content_array);
|
|
|
|
sh->uri_content_array = NULL;
|
|
|
|
sh->uri_content_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sh->match_array) {
|
|
|
|
detect_siggroup_matcharray_init_cnt--;
|
|
|
|
detect_siggroup_matcharray_memory -= (sh->sig_cnt * sizeof(u_int32_t));
|
|
|
|
free(sh->match_array);
|
|
|
|
sh->match_array = NULL;
|
|
|
|
}
|
|
|
|
free(sh);
|
|
|
|
|
|
|
|
detect_siggroup_head_free_cnt++;
|
|
|
|
detect_siggroup_head_memory -= sizeof(SigGroupHead);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* initialization hashes
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* mpm sgh hash */
|
|
|
|
u_int32_t SigGroupHeadMpmHashFunc(HashListTable *ht, void *data, u_int16_t datalen) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)data;
|
|
|
|
u_int32_t hash = 0;
|
|
|
|
|
|
|
|
u_int32_t b;
|
|
|
|
for (b = 0; b < sgh->content_size; b+=1) {
|
|
|
|
hash += sgh->content_array[b];
|
|
|
|
}
|
|
|
|
return hash % ht->array_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
char SigGroupHeadMpmCompareFunc(void *data1, u_int16_t len1, void *data2, u_int16_t len2) {
|
|
|
|
SigGroupHead *sgh1 = (SigGroupHead *)data1;
|
|
|
|
SigGroupHead *sgh2 = (SigGroupHead *)data2;
|
|
|
|
|
|
|
|
if (sgh1->content_size != sgh2->content_size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (memcmp(sgh1->content_array,sgh2->content_array,sgh1->content_size) != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
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 */
|
|
|
|
|
|
|
|
u_int32_t SigGroupHeadMpmUriHashFunc(HashListTable *ht, void *data, u_int16_t datalen) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)data;
|
|
|
|
u_int32_t hash = 0;
|
|
|
|
|
|
|
|
u_int32_t b;
|
|
|
|
for (b = 0; b < sgh->uri_content_size; b+=1) {
|
|
|
|
hash += sgh->uri_content_array[b];
|
|
|
|
}
|
|
|
|
return hash % ht->array_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
char SigGroupHeadMpmUriCompareFunc(void *data1, u_int16_t len1, void *data2, u_int16_t len2) {
|
|
|
|
SigGroupHead *sgh1 = (SigGroupHead *)data1;
|
|
|
|
SigGroupHead *sgh2 = (SigGroupHead *)data2;
|
|
|
|
|
|
|
|
if (sgh1->uri_content_size != sgh2->uri_content_size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (memcmp(sgh1->uri_content_array,sgh2->uri_content_array,sgh1->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);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
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 */
|
|
|
|
|
|
|
|
u_int32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, u_int16_t datalen) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)data;
|
|
|
|
u_int32_t hash = 0;
|
|
|
|
|
|
|
|
u_int32_t b;
|
|
|
|
for (b = 0; b < sgh->sig_size; b+=1) {
|
|
|
|
hash += sgh->sig_array[b];
|
|
|
|
}
|
|
|
|
return hash % ht->array_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
char SigGroupHeadCompareFunc(void *data1, u_int16_t len1, void *data2, u_int16_t len2) {
|
|
|
|
SigGroupHead *sgh1 = (SigGroupHead *)data1;
|
|
|
|
SigGroupHead *sgh2 = (SigGroupHead *)data2;
|
|
|
|
|
|
|
|
if (sgh1->sig_size != sgh2->sig_size)
|
|
|
|
return 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);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
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 */
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
if (de_ctx->dport_hash_table == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
HashListTableFree(de_ctx->sgh_dport_hash_table);
|
|
|
|
de_ctx->sgh_dport_hash_table = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sport */
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
if (de_ctx->sport_hash_table == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
HashListTableFree(de_ctx->sgh_sport_hash_table);
|
|
|
|
de_ctx->sgh_sport_hash_table = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end hashes */
|
|
|
|
|
|
|
|
static void SigGroupHeadFreeSigArraysHash2(DetectEngineCtx *de_ctx, HashListTable *ht) {
|
|
|
|
HashListTableBucket *htb = NULL;
|
|
|
|
|
|
|
|
for (htb = HashListTableGetListHead(ht); htb != NULL; htb = HashListTableGetListNext(htb)) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
|
|
|
|
|
|
if (sgh->sig_array != NULL) {
|
|
|
|
detect_siggroup_sigarray_free_cnt++;
|
|
|
|
detect_siggroup_sigarray_memory -= sgh->sig_size;
|
|
|
|
|
|
|
|
free(sgh->sig_array);
|
|
|
|
sgh->sig_array = NULL;
|
|
|
|
sgh->sig_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgh->content_array != NULL) {
|
|
|
|
free(sgh->content_array);
|
|
|
|
sgh->content_array = NULL;
|
|
|
|
sgh->content_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgh->uri_content_array != NULL) {
|
|
|
|
free(sgh->uri_content_array);
|
|
|
|
sgh->uri_content_array = NULL;
|
|
|
|
sgh->uri_content_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SigGroupHeadFreeSigArraysHash(DetectEngineCtx *de_ctx, HashListTable *ht) {
|
|
|
|
HashListTableBucket *htb = NULL;
|
|
|
|
|
|
|
|
for (htb = HashListTableGetListHead(ht); htb != NULL; htb = HashListTableGetListNext(htb)) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
|
|
|
|
|
|
if (sgh->sig_array != NULL) {
|
|
|
|
detect_siggroup_sigarray_free_cnt++;
|
|
|
|
detect_siggroup_sigarray_memory -= sgh->sig_size;
|
|
|
|
|
|
|
|
free(sgh->sig_array);
|
|
|
|
sgh->sig_array = NULL;
|
|
|
|
sgh->sig_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the sigarrays in the sgh's. Those are only
|
|
|
|
* used during the init stage. */
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the mpm arrays that are only used during the
|
|
|
|
* init stage */
|
|
|
|
void SigGroupHeadFreeMpmArrays(DetectEngineCtx *de_ctx) {
|
|
|
|
HashListTableBucket *htb = NULL;
|
|
|
|
|
|
|
|
for (htb = HashListTableGetListHead(de_ctx->sgh_dport_hash_table); htb != NULL; htb = HashListTableGetListNext(htb)) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
|
|
|
|
|
|
if (sgh->content_array != NULL) {
|
|
|
|
free(sgh->content_array);
|
|
|
|
sgh->content_array = NULL;
|
|
|
|
sgh->content_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgh->uri_content_array != NULL) {
|
|
|
|
free(sgh->uri_content_array);
|
|
|
|
sgh->uri_content_array = NULL;
|
|
|
|
sgh->uri_content_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (htb = HashListTableGetListHead(de_ctx->sgh_sport_hash_table); htb != NULL; htb = HashListTableGetListNext(htb)) {
|
|
|
|
SigGroupHead *sgh = (SigGroupHead *)HashListTableGetListData(htb);
|
|
|
|
|
|
|
|
if (sgh->content_array != NULL) {
|
|
|
|
free(sgh->content_array);
|
|
|
|
sgh->content_array = NULL;
|
|
|
|
sgh->content_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sgh->uri_content_array != NULL) {
|
|
|
|
free(sgh->uri_content_array);
|
|
|
|
sgh->uri_content_array = NULL;
|
|
|
|
sgh->uri_content_size = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadAppendSig(DetectEngineCtx *de_ctx, SigGroupHead **sh, Signature *s) {
|
|
|
|
if (de_ctx == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* see if we have a head already */
|
|
|
|
if (*sh == NULL) {
|
|
|
|
*sh = malloc(sizeof(SigGroupHead));
|
|
|
|
if (*sh == NULL) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
memset(*sh, 0, sizeof(SigGroupHead));
|
|
|
|
|
|
|
|
detect_siggroup_head_init_cnt++;
|
|
|
|
detect_siggroup_head_memory += sizeof(SigGroupHead);
|
|
|
|
|
|
|
|
/* initialize the signature bitarray */
|
|
|
|
(*sh)->sig_size = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
|
|
|
|
(*sh)->sig_array = malloc((*sh)->sig_size);
|
|
|
|
if ((*sh)->sig_array == NULL)
|
|
|
|
goto error;
|
|
|
|
memset((*sh)->sig_array,0,(*sh)->sig_size);
|
|
|
|
|
|
|
|
detect_siggroup_sigarray_init_cnt++;
|
|
|
|
detect_siggroup_sigarray_memory += (*sh)->sig_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* enable the sig in the bitarray */
|
|
|
|
(*sh)->sig_array[(s->num/8)] |= 1<<(s->num%8);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadClearSigs(SigGroupHead *sh) {
|
|
|
|
if (sh == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (sh->sig_array != NULL) {
|
|
|
|
memset(sh->sig_array,0,sh->sig_size);
|
|
|
|
sh->sig_cnt = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst) {
|
|
|
|
if (src == NULL || de_ctx == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (*dst == NULL) {
|
|
|
|
*dst = malloc(sizeof(SigGroupHead));
|
|
|
|
if (*dst == NULL) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
memset(*dst, 0, sizeof(SigGroupHead));
|
|
|
|
|
|
|
|
detect_siggroup_head_init_cnt++;
|
|
|
|
detect_siggroup_head_memory += sizeof(SigGroupHead);
|
|
|
|
|
|
|
|
(*dst)->sig_size = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
|
|
|
|
(*dst)->sig_array = malloc((*dst)->sig_size);
|
|
|
|
if ((*dst)->sig_array == NULL)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
memset((*dst)->sig_array,0,(*dst)->sig_size);
|
|
|
|
|
|
|
|
detect_siggroup_sigarray_init_cnt++;
|
|
|
|
detect_siggroup_sigarray_memory += (*dst)->sig_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* do the copy */
|
|
|
|
u_int32_t idx;
|
|
|
|
for (idx = 0; idx < src->sig_size; idx++) {
|
|
|
|
(*dst)->sig_array[idx] = (*dst)->sig_array[idx] | src->sig_array[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SigGroupHeadSetSigCnt(SigGroupHead *sgh, u_int32_t max_idx) {
|
|
|
|
u_int32_t sig;
|
|
|
|
|
|
|
|
for (sig = 0; sig < max_idx+1; sig++) {
|
|
|
|
if (sgh->sig_array[(sig/8)] & (1<<(sig%8))) {
|
|
|
|
sgh->sig_cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DetectSigGroupPrintMemory(void) {
|
|
|
|
printf(" * Sig group head memory stats (SigGroupHead %u):\n", sizeof(SigGroupHead));
|
|
|
|
printf(" - detect_siggroup_head_memory %u\n", detect_siggroup_head_memory);
|
|
|
|
printf(" - detect_siggroup_head_init_cnt %u\n", detect_siggroup_head_init_cnt);
|
|
|
|
printf(" - detect_siggroup_head_free_cnt %u\n", detect_siggroup_head_free_cnt);
|
|
|
|
printf(" - outstanding sig group heads %u\n", detect_siggroup_head_init_cnt - detect_siggroup_head_free_cnt);
|
|
|
|
printf(" * Sig group head memory stats done\n");
|
|
|
|
printf(" * Sig group sigarray memory stats:\n");
|
|
|
|
printf(" - detect_siggroup_sigarray_memory %u\n", detect_siggroup_sigarray_memory);
|
|
|
|
printf(" - detect_siggroup_sigarray_init_cnt %u\n", detect_siggroup_sigarray_init_cnt);
|
|
|
|
printf(" - detect_siggroup_sigarray_free_cnt %u\n", detect_siggroup_sigarray_free_cnt);
|
|
|
|
printf(" - outstanding sig group sigarrays %u\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 %u\n", detect_siggroup_matcharray_memory);
|
|
|
|
printf(" - detect_siggroup_matcharray_init_cnt %u\n", detect_siggroup_matcharray_init_cnt);
|
|
|
|
printf(" - detect_siggroup_matcharray_free_cnt %u\n", detect_siggroup_matcharray_free_cnt);
|
|
|
|
printf(" - outstanding sig group matcharrays %u\n", detect_siggroup_matcharray_init_cnt - detect_siggroup_matcharray_free_cnt);
|
|
|
|
printf(" * Sig group sigarray memory stats done\n");
|
|
|
|
printf(" X Total %u\n", detect_siggroup_head_memory + detect_siggroup_sigarray_memory + detect_siggroup_matcharray_memory);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
|
|
|
|
printf("SigGroupHeadPrintSigs: ");
|
|
|
|
|
|
|
|
u_int32_t i;
|
|
|
|
for (i = 0; i < sgh->sig_size; i++) {
|
|
|
|
if (sgh->sig_array[(i/8)] & (1<<(i%8))) {
|
|
|
|
printf("%u ", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SigGroupHeadPrintContent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
|
|
|
|
printf("SigGroupHeadPrintContent: ");
|
|
|
|
|
|
|
|
u_int32_t i;
|
|
|
|
for (i = 0; i < DetectContentMaxId(de_ctx); i++) {
|
|
|
|
if (sgh->content_array[(i/8)] & (1<<(i%8))) {
|
|
|
|
printf("%u ", i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
void SigGroupHeadPrintContentCnt(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
|
|
|
|
printf("SigGroupHeadPrintContent: ");
|
|
|
|
|
|
|
|
u_int32_t i, cnt = 0;
|
|
|
|
for (i = 0; i < DetectContentMaxId(de_ctx); i++) {
|
|
|
|
if (sgh->content_array[(i/8)] & (1<<(i%8))) {
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("cnt %u\n", cnt);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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) {
|
|
|
|
if (sgh == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Signature *s;
|
|
|
|
SigMatch *sm;
|
|
|
|
|
|
|
|
if (DetectContentMaxId(de_ctx) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sgh->content_size = (DetectContentMaxId(de_ctx) / 8) + 1;
|
|
|
|
sgh->content_array = malloc(sgh->content_size * sizeof(u_int32_t));
|
|
|
|
if (sgh->content_array == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
memset(sgh->content_array,0, sgh->content_size * sizeof(u_int32_t));
|
|
|
|
|
|
|
|
u_int32_t sig;
|
|
|
|
for (sig = 0; sig < sgh->sig_cnt; sig++) {
|
|
|
|
u_int32_t num = sgh->match_array[sig];
|
|
|
|
|
|
|
|
s = de_ctx->sig_array[num];
|
|
|
|
if (s == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
sm = s->match;
|
|
|
|
if (sm == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for ( ; sm != NULL; sm = sm->next) {
|
|
|
|
if (sm->type == DETECT_CONTENT) {
|
|
|
|
DetectContentData *co = (DetectContentData *)sm->ctx;
|
|
|
|
|
|
|
|
sgh->content_array[(co->id/8)] |= 1<<(co->id%8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadClearContent(SigGroupHead *sh) {
|
|
|
|
if (sh == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (sh->content_array != NULL) {
|
|
|
|
free(sh->content_array);
|
|
|
|
sh->content_array = NULL;
|
|
|
|
sh->content_size = 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadLoadUricontent(DetectEngineCtx *de_ctx, SigGroupHead *sgh) {
|
|
|
|
if (sgh == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Signature *s;
|
|
|
|
SigMatch *sm;
|
|
|
|
|
|
|
|
if (DetectUricontentMaxId(de_ctx) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sgh->uri_content_size = (DetectUricontentMaxId(de_ctx) / 8) + 1;
|
|
|
|
sgh->uri_content_array = malloc(sgh->uri_content_size * sizeof(u_int32_t));
|
|
|
|
if (sgh->uri_content_array == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
memset(sgh->uri_content_array,0, sgh->uri_content_size * sizeof(u_int32_t));
|
|
|
|
|
|
|
|
u_int32_t sig;
|
|
|
|
for (sig = 0; sig < sgh->sig_cnt; sig++) {
|
|
|
|
u_int32_t num = sgh->match_array[sig];
|
|
|
|
|
|
|
|
s = de_ctx->sig_array[num];
|
|
|
|
if (s == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
sm = s->match;
|
|
|
|
if (sm == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
for ( ; sm != NULL; sm = sm->next) {
|
|
|
|
if (sm->type == DETECT_URICONTENT) {
|
|
|
|
DetectUricontentData *co = (DetectUricontentData *)sm->ctx;
|
|
|
|
|
|
|
|
sgh->uri_content_array[(co->id/8)] |= 1<<(co->id%8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadClearUricontent(SigGroupHead *sh) {
|
|
|
|
if (sh == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (sh->uri_content_array != NULL) {
|
|
|
|
free(sh->uri_content_array);
|
|
|
|
sh->uri_content_array = NULL;
|
|
|
|
sh->uri_content_size = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int SigGroupHeadBuildMatchArray (DetectEngineCtx *de_ctx, SigGroupHead *sgh, u_int32_t max_idx) {
|
|
|
|
u_int32_t idx = 0;
|
|
|
|
u_int32_t sig = 0;
|
|
|
|
|
|
|
|
if (sgh == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
sgh->match_array = malloc(sgh->sig_cnt * sizeof(u_int32_t));
|
|
|
|
if (sgh->match_array == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
memset(sgh->match_array,0, sgh->sig_cnt * sizeof(u_int32_t));
|
|
|
|
|
|
|
|
detect_siggroup_matcharray_init_cnt++;
|
|
|
|
detect_siggroup_matcharray_memory += (sgh->sig_cnt * sizeof(u_int32_t));
|
|
|
|
|
|
|
|
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];
|
|
|
|
if (s == NULL)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
sgh->match_array[idx] = s->num;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|