diff --git a/src/datasets.c b/src/datasets.c index 46f39d1926..9104ef2e99 100644 --- a/src/datasets.c +++ b/src/datasets.c @@ -47,6 +47,7 @@ static inline void DatasetUnlockData(THashData *d) (void) THashDecrUsecnt(d); THashDataUnlock(d); } +static bool DatasetIsStatic(const char *save, const char *load); enum DatasetTypes DatasetGetTypeFromString(const char *s) { @@ -72,7 +73,7 @@ static Dataset *DatasetSearchByName(const char *name) { Dataset *set = sets; while (set) { - if (strcasecmp(name, set->name) == 0) { + if (strcasecmp(name, set->name) == 0 && set->hidden == false) { return set; } set = set->next; @@ -532,6 +533,66 @@ out_err: return NULL; } +static bool DatasetIsStatic(const char *save, const char *load) +{ + /* A set is static if it does not have any dynamic properties like + * save and/or state defined but has load defined. + * */ + if ((load != NULL || strlen(load) > 0) && + (save == NULL || strlen(save) == 0)) { + return true; + } + return false; +} + +void DatasetReload(void) +{ + /* In order to reload the datasets, just mark the current sets as hidden + * and clean them up later. + * New datasets shall be created with the rule reload and do not require + * any intervention. + * */ + SCMutexLock(&sets_lock); + Dataset *set = sets; + while (set) { + if (!DatasetIsStatic(set->save, set->load) || set->from_yaml == true) { + SCLogDebug("Not a static set, skipping %s", set->name); + set = set->next; + continue; + } + set->hidden = true; + SCLogDebug("Set %s at %p hidden successfully", set->name, set); + set = set->next; + } + SCMutexUnlock(&sets_lock); +} + +void DatasetPostReloadCleanup(void) +{ + SCLogDebug("Post Reload Cleanup starting.. Hidden sets will be removed"); + SCMutexLock(&sets_lock); + Dataset *cur = sets; + Dataset *prev = NULL; + while (cur) { + Dataset *next = cur->next; + if (cur->hidden == false) { + prev = cur; + cur = next; + continue; + } + // Delete the set in case it was hidden + if (prev != NULL) { + prev->next = next; + } else { + sets = next; + } + THashShutdown(cur->hash); + SCFree(cur); + cur = next; + } + SCMutexUnlock(&sets_lock); +} + int DatasetsInit(void) { SCLogDebug("datasets start"); @@ -585,6 +646,7 @@ int DatasetsInit(void) if (dset == NULL) FatalError(SC_ERR_FATAL, "failed to setup dataset for %s", set_name); SCLogDebug("dataset %s: id %d type %s", set_name, n, set_type->val); + dset->from_yaml = true; n++; } else if (strcmp(set_type->val, "sha256") == 0) { @@ -592,6 +654,7 @@ int DatasetsInit(void) if (dset == NULL) FatalError(SC_ERR_FATAL, "failed to setup dataset for %s", set_name); SCLogDebug("dataset %s: id %d type %s", set_name, n, set_type->val); + dset->from_yaml = true; n++; } else if (strcmp(set_type->val, "string") == 0) { @@ -599,6 +662,7 @@ int DatasetsInit(void) if (dset == NULL) FatalError(SC_ERR_FATAL, "failed to setup dataset for %s", set_name); SCLogDebug("dataset %s: id %d type %s", set_name, n, set_type->val); + dset->from_yaml = true; n++; } diff --git a/src/datasets.h b/src/datasets.h index 16ae562684..71003b28c2 100644 --- a/src/datasets.h +++ b/src/datasets.h @@ -24,6 +24,8 @@ int DatasetsInit(void); void DatasetsDestroy(void); void DatasetsSave(void); +void DatasetReload(void); +void DatasetPostReloadCleanup(void); enum DatasetTypes { #define DATASET_TYPE_NOTSET 0 @@ -37,7 +39,8 @@ typedef struct Dataset { char name[DATASET_NAME_MAX_LEN + 1]; enum DatasetTypes type; uint32_t id; - + bool from_yaml; /* Mark whether the set was retrieved from YAML */ + bool hidden; /* Mark the old sets hidden in case of reload */ THashTableContext *hash; char load[PATH_MAX]; diff --git a/src/detect-engine.c b/src/detect-engine.c index cc767c8f08..ead7de6011 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -31,6 +31,7 @@ #include "flow-worker.h" #include "conf.h" #include "conf-yaml-loader.h" +#include "datasets.h" #include "app-layer-parser.h" #include "app-layer-htp.h" @@ -4093,6 +4094,7 @@ int DetectEngineReload(const SCInstance *suri) if (old_de_ctx == NULL) return -1; SCLogDebug("get ref to old_de_ctx %p", old_de_ctx); + DatasetReload(); /* only reload a regular 'normal' and 'delayed detect stub' detect engines */ if (!(old_de_ctx->type == DETECT_ENGINE_TYPE_NORMAL || @@ -4134,6 +4136,8 @@ int DetectEngineReload(const SCInstance *suri) /* walk free list, freeing the old_de_ctx */ DetectEnginePruneFreeList(); + DatasetPostReloadCleanup(); + DetectEngineBumpVersion(); SCLogDebug("old_de_ctx should have been freed");