SigGroupHeadHashInit(de_ctx);
MpmStoreInit(de_ctx);
ThresholdHashInit(de_ctx);
- VariableNameInitHash(de_ctx);
DetectParseDupSigHashInit(de_ctx);
DetectAddressMapInit(de_ctx);
}
de_ctx->version = DetectEngineGetVersion();
+ VarNameStoreSetupStaging(de_ctx->version);
SCLogDebug("dectx with version %u", de_ctx->version);
return de_ctx;
error:
SigCleanSignatures(de_ctx);
SCFree(de_ctx->app_mpms);
de_ctx->app_mpms = NULL;
-
- VariableNameFreeHash(de_ctx);
if (de_ctx->sig_array)
SCFree(de_ctx->sig_array);
DetectPortCleanupList(de_ctx->tcp_whitelist);
DetectPortCleanupList(de_ctx->udp_whitelist);
+ /* freed our var name hash */
+ VarNameStoreFree(de_ctx->version);
+
SCFree(de_ctx);
//DetectAddressGroupPrintMemory();
//DetectSigGroupPrintMemory();
if (DetectLoadersSync() != 0) {
goto error;
}
+
+ VarNameStoreActivateStaging();
+
} else {
SCLogDebug("multi-detect not enabled (multi tenancy)");
}
if (unlikely(cd == NULL))
goto error;
- cd->idx = VariableNameGetIdx(de_ctx, fb_name, VAR_TYPE_FLOW_BIT);
+ cd->idx = VarNameStoreSetupAdd(fb_name, VAR_TYPE_FLOW_BIT);
cd->cmd = fb_cmd;
SCLogDebug("idx %" PRIu32 ", cmd %s, name %s",
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Noalert\"; flowbits:noalert,wrongusage; content:\"GET \"; sid:1;)");
FAIL_IF_NOT_NULL(s);
+ SigGroupBuild(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"toggle rule need an option\"; flowbits:toggle; content:\"GET \"; sid:5;)");
FAIL_IF_NOT_NULL(s);
+ SigGroupBuild(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Unknown cmd\"; flowbits:wrongcmd; content:\"GET \"; sid:1;)");
FAIL_IF_NOT_NULL(s);
+ SigGroupBuild(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isset option\"; flowbits:isset,fbt; content:\"GET \"; sid:1;)");
FAIL_IF_NULL(s);
- idx = VariableNameGetIdx(de_ctx, "fbt", VAR_TYPE_FLOW_BIT);
+ idx = VarNameStoreSetupAdd("fbt", VAR_TYPE_FLOW_BIT);
FAIL_IF(idx != 1);
+ SigGroupBuild(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
FAIL_IF_NULL(s);
FAIL_IF((s->flags & SIG_FLAG_NOALERT) != SIG_FLAG_NOALERT);
+ SigGroupBuild(de_ctx);
DetectEngineCtxFree(de_ctx);
PASS;
}
Flow f;
GenericVar flowvar, *gv = NULL;
int result = 0;
- int idx = 0;
+ uint32_t idx = 0;
memset(p, 0, SIZE_OF_PACKET);
memset(&th_v, 0, sizeof(th_v));
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit set\"; flowbits:set,myflow; sid:10;)");
FAIL_IF_NULL(s);
+ idx = VarNameStoreSetupAdd("myflow", VAR_TYPE_FLOW_BIT);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
- idx = VariableNameGetIdx(de_ctx, "myflow", VAR_TYPE_FLOW_BIT);
-
gv = p->flow->flowvar;
-
+ FAIL_IF_NULL(gv);
for ( ; gv != NULL; gv = gv->next) {
if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
result = 1;
}
FAIL_IF_NOT(result);
- SigGroupCleanup(de_ctx);
- SigCleanSignatures(de_ctx);
-
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
- if(gv) GenericVarFree(gv);
FLOW_DESTROY(&f);
SCFree(p);
Flow f;
GenericVar flowvar, *gv = NULL;
int result = 0;
- int idx = 0;
+ uint32_t idx = 0;
memset(p, 0, SIZE_OF_PACKET);
memset(&th_v, 0, sizeof(th_v));
s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit unset\"; flowbits:unset,myflow2; sid:11;)");
FAIL_IF_NULL(s);
+ idx = VarNameStoreSetupAdd("myflow", VAR_TYPE_FLOW_BIT);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
- idx = VariableNameGetIdx(de_ctx, "myflow", VAR_TYPE_FLOW_BIT);
-
gv = p->flow->flowvar;
+ FAIL_IF_NULL(gv);
for ( ; gv != NULL; gv = gv->next) {
if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
}
FAIL_IF(result);
- SigGroupCleanup(de_ctx);
- SigCleanSignatures(de_ctx);
-
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
- if(gv) GenericVarFree(gv);
FLOW_DESTROY(&f);
SCFree(p);
Flow f;
GenericVar flowvar, *gv = NULL;
int result = 0;
- int idx = 0;
+ uint32_t idx = 0;
memset(p, 0, SIZE_OF_PACKET);
memset(&th_v, 0, sizeof(th_v));
s = s->next = SigInit(de_ctx,"alert ip any any -> any any (msg:\"Flowbit unset\"; flowbits:toggle,myflow2; sid:11;)");
FAIL_IF_NULL(s);
+ idx = VarNameStoreSetupAdd("myflow", VAR_TYPE_FLOW_BIT);
SigGroupBuild(de_ctx);
DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
- idx = VariableNameGetIdx(de_ctx, "myflow", VAR_TYPE_FLOW_BIT);
-
gv = p->flow->flowvar;
+ FAIL_IF_NULL(gv);
for ( ; gv != NULL; gv = gv->next) {
if (gv->type == DETECT_FLOWBITS && gv->idx == idx) {
}
FAIL_IF(result);
- SigGroupCleanup(de_ctx);
- SigCleanSignatures(de_ctx);
-
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
- if(gv) GenericVarFree(gv);
FLOW_DESTROY(&f);
SCFree(p);
#define DETECT_FLOWBITS_CMD_MAX 6
typedef struct DetectFlowbitsData_ {
- uint16_t idx;
+ uint32_t idx;
uint8_t cmd;
} DetectFlowbitsData;
* return zero(not match).
*/
if (sfd->targettype == FLOWINT_TARGET_VAR) {
- uint16_t tvar_idx = VariableNameGetIdx(det_ctx->de_ctx, sfd->target.tvar.name, VAR_TYPE_FLOW_INT);
+ uint32_t tvar_idx = VarNameStoreLookupByName(sfd->target.tvar.name, VAR_TYPE_FLOW_INT);
fvt = FlowVarGet(p->flow, tvar_idx);
/* We don't have that variable initialized yet */
SCLogError(SC_ERR_MEM_ALLOC, "malloc from strdup failed");
goto error;
}
- if (de_ctx != NULL)
- sfd->idx = VariableNameGetIdx(de_ctx, varname, VAR_TYPE_FLOW_INT);
+ sfd->idx = VarNameStoreSetupAdd(varname, VAR_TYPE_FLOW_INT);
+ SCLogDebug("sfd->name %s id %u", sfd->name, sfd->idx);
sfd->modifier = modifier;
pcre_free_substring(varname);
* against the target */
char *name;
/* Internal id of the var */
- uint16_t idx;
+ uint32_t idx;
/* The modifier/operation/condition we are
* going to execute */
fd->name = SCStrdup(varname);
if (unlikely(fd->name == NULL))
goto error;
- fd->idx = VariableNameGetIdx(de_ctx, varname, VAR_TYPE_FLOW_VAR);
+ fd->idx = VarNameStoreSetupAdd(varname, VAR_TYPE_FLOW_VAR);
/* Okay so far so good, lets get this into a SigMatch
* and put it in the Signature. */
/** \brief Store flowvar in det_ctx so we can exec it post-match */
-int DetectFlowvarStoreMatch(DetectEngineThreadCtx *det_ctx, uint16_t idx,
+int DetectFlowvarStoreMatch(DetectEngineThreadCtx *det_ctx, uint32_t idx,
uint8_t *buffer, uint16_t len, int type)
{
DetectFlowvarList *fs = det_ctx->flowvarlist;
/** \brief Setup a post-match for flowvar storage
* We're piggyback riding the DetectFlowvarData struct
*/
-int DetectFlowvarPostMatchSetup(Signature *s, uint16_t idx)
+int DetectFlowvarPostMatchSetup(Signature *s, uint32_t idx)
{
SigMatch *sm = NULL;
DetectFlowvarData *fv = NULL;
typedef struct DetectFlowvarData_ {
char *name;
- uint16_t idx;
+ uint32_t idx;
uint8_t *content;
uint8_t content_len;
uint8_t flags;
/* prototypes */
void DetectFlowvarRegister (void);
-int DetectFlowvarPostMatchSetup(Signature *s, uint16_t idx);
-int DetectFlowvarStoreMatch(DetectEngineThreadCtx *, uint16_t, uint8_t *, uint16_t, int);
+int DetectFlowvarPostMatchSetup(Signature *s, uint32_t idx);
+int DetectFlowvarStoreMatch(DetectEngineThreadCtx *, uint32_t, uint8_t *, uint16_t, int);
/* For use only by DetectFlowvarProcessList() */
void DetectFlowvarProcessListInternal(DetectFlowvarList *fs, Flow *f);
if (unlikely(cd == NULL))
goto error;
- cd->idx = VariableNameGetIdx(de_ctx, fb_name, VAR_TYPE_HOST_BIT);
+ cd->idx = VarNameStoreSetupAdd(fb_name, VAR_TYPE_HOST_BIT);
cd->cmd = fb_cmd;
cd->tracker = hb_dir;
cd->type = VAR_TYPE_HOST_BIT;
s = de_ctx->sig_list = SigInit(de_ctx,"alert ip any any -> any any (msg:\"isset option\"; hostbits:isset,fbt; content:\"GET \"; sid:1;)");
FAIL_IF_NULL(s);
- idx = VariableNameGetIdx(de_ctx, "fbt", VAR_TYPE_HOST_BIT);
+ idx = VarNameStoreSetupAdd("fbt", VAR_TYPE_HOST_BIT);
FAIL_IF(idx != 1);
SigGroupBuild(de_ctx);
SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
- SigGroupCleanup(de_ctx);
- SigCleanSignatures(de_ctx);
-
DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
DetectEngineCtxFree(de_ctx);
HostBitsTestShutdown();
goto error;
}
- uint16_t idx = VariableNameGetIdx(de_ctx, (char *)value, VAR_TYPE_FLOW_VAR);
+ uint32_t idx = VarNameStoreSetupAdd((char *)value, VAR_TYPE_FLOW_VAR);
ld->flowvar[ld->flowvars++] = idx;
SCLogDebug("script uses flowvar %u with script id %u", idx, ld->flowvars - 1);
}
goto error;
}
- uint16_t idx = VariableNameGetIdx(de_ctx, (char *)value, VAR_TYPE_FLOW_INT);
+ uint32_t idx = VarNameStoreSetupAdd((char *)value, VAR_TYPE_FLOW_INT);
ld->flowint[ld->flowints++] = idx;
SCLogDebug("script uses flowint %u with script id %u", idx, ld->flowints - 1);
}
uint32_t flags;
AppProto alproto;
char *buffername; /* buffer name in case of a single buffer */
- uint16_t flowint[DETECT_LUAJIT_MAX_FLOWINTS];
+ uint32_t flowint[DETECT_LUAJIT_MAX_FLOWINTS];
uint16_t flowints;
- uint16_t flowvar[DETECT_LUAJIT_MAX_FLOWVARS];
uint16_t flowvars;
+ uint32_t flowvar[DETECT_LUAJIT_MAX_FLOWVARS];
uint32_t sid;
uint32_t rev;
uint32_t gid;
}
if (pd->capname != NULL) {
if (pd->flags & DETECT_PCRE_CAPTURE_PKT)
- pd->capidx = VariableNameGetIdx(de_ctx, (char *)pd->capname, VAR_TYPE_PKT_VAR);
+ pd->capidx = VarNameStoreSetupAdd((char *)pd->capname, VAR_TYPE_PKT_VAR);
else if (pd->flags & DETECT_PCRE_CAPTURE_FLOW)
- pd->capidx = VariableNameGetIdx(de_ctx, (char *)pd->capname, VAR_TYPE_FLOW_VAR);
+ pd->capidx = VarNameStoreSetupAdd((char *)pd->capname, VAR_TYPE_FLOW_VAR);
}
SCLogDebug("pd->capname %s", pd->capname);
pcre_extra *sd;
int opts;
uint16_t flags;
- uint16_t capidx;
+ uint32_t capidx;
char *capname;
} DetectPcreData;
if (unlikely(cd == NULL))
return -1;
- cd->idx = VariableNameGetIdx(de_ctx, fb_name, var_type);
+ cd->idx = VarNameStoreSetupAdd(fb_name, var_type);
cd->cmd = fb_cmd;
cd->tracker = hb_dir;
cd->type = var_type;
#define DETECT_XBITS_EXPIRE_DEFAULT 30
typedef struct DetectXbitsData_ {
- uint16_t idx;
+ uint32_t idx;
uint8_t cmd;
uint8_t tracker;
uint32_t expire;
}
FlowBit *fb = (FlowBit *) gv;
- const char *name = VariableIdxGetName(de_ctx, fb->idx, VAR_TYPE_FLOW_BIT);
+ const char *name = VarNameStoreLookupById(fb->idx, VAR_TYPE_FLOW_BIT);
if (name != NULL) {
p->debuglog_flowbits_names[i] = SCStrdup(name);
if (p->debuglog_flowbits_names[i] == NULL) {
#endif
SCFree(de_ctx->app_mpms);
de_ctx->app_mpms = NULL;
+
+ if (!DetectEngineMultiTenantEnabled()) {
+ VarNameStoreActivateStaging();
+ }
return 0;
}
#include "stream.h"
+#include "util-var-name.h"
+
#define DETECT_MAX_RULE_SIZE 8192
/* forward declarations for the structures from detect-engine-sigorder.h */
/** list for flowvar store candidates, to be stored from
* post-match function */
typedef struct DetectFlowvarList_ {
- uint16_t idx; /**< flowvar name idx */
+ uint32_t idx; /**< flowvar name idx */
uint16_t len; /**< data len */
int type; /**< type of store candidate POSTMATCH or ALWAYS */
uint8_t *buffer; /**< alloc'd buffer, may be freed by
HashListTable *mpm_hash_table;
- HashListTable *variable_names;
- HashListTable *variable_idxs;
- uint16_t variable_names_idx;
-
/* hash table used to cull out duplicate sigs */
HashListTable *dup_sig_hash_table;
#include "util-unittest.h"
/* get the flowbit with idx from the flow */
-static FlowBit *FlowBitGet(Flow *f, uint16_t idx)
+static FlowBit *FlowBitGet(Flow *f, uint32_t idx)
{
GenericVar *gv = f->flowvar;
for ( ; gv != NULL; gv = gv->next) {
}
/* add a flowbit to the flow */
-static void FlowBitAdd(Flow *f, uint16_t idx)
+static void FlowBitAdd(Flow *f, uint32_t idx)
{
FlowBit *fb = FlowBitGet(f, idx);
if (fb == NULL) {
}
}
-static void FlowBitRemove(Flow *f, uint16_t idx)
+static void FlowBitRemove(Flow *f, uint32_t idx)
{
FlowBit *fb = FlowBitGet(f, idx);
if (fb == NULL)
FlowBitFree(fb);
}
-void FlowBitSet(Flow *f, uint16_t idx)
+void FlowBitSet(Flow *f, uint32_t idx)
{
FlowBitAdd(f, idx);
}
-void FlowBitUnset(Flow *f, uint16_t idx)
+void FlowBitUnset(Flow *f, uint32_t idx)
{
FlowBitRemove(f, idx);
}
-void FlowBitToggle(Flow *f, uint16_t idx)
+void FlowBitToggle(Flow *f, uint32_t idx)
{
FlowBit *fb = FlowBitGet(f, idx);
if (fb != NULL) {
}
}
-int FlowBitIsset(Flow *f, uint16_t idx)
+int FlowBitIsset(Flow *f, uint32_t idx)
{
int r = 0;
return r;
}
-int FlowBitIsnotset(Flow *f, uint16_t idx)
+int FlowBitIsnotset(Flow *f, uint32_t idx)
{
int r = 0;
typedef struct FlowBit_ {
uint8_t type; /* type, DETECT_FLOWBITS in this case */
- uint16_t idx; /* name idx */
+ uint32_t idx; /* name idx */
GenericVar *next; /* right now just implement this as a list,
* in the long run we have think of something
* faster. */
void FlowBitFree(FlowBit *);
void FlowBitRegisterTests(void);
-void FlowBitSet(Flow *, uint16_t);
-void FlowBitUnset(Flow *, uint16_t);
-void FlowBitToggle(Flow *, uint16_t);
-int FlowBitIsset(Flow *, uint16_t);
-int FlowBitIsnotset(Flow *, uint16_t);
+void FlowBitSet(Flow *, uint32_t);
+void FlowBitUnset(Flow *, uint32_t);
+void FlowBitToggle(Flow *, uint32_t);
+int FlowBitIsset(Flow *, uint32_t);
+int FlowBitIsnotset(Flow *, uint32_t);
#endif /* __FLOW_BIT_H__ */
* \note flow is not locked by this function, caller is
* responsible
*/
-FlowVar *FlowVarGet(Flow *f, uint16_t idx)
+FlowVar *FlowVarGet(Flow *f, uint32_t idx)
{
GenericVar *gv = f->flowvar;
}
/* add a flowvar to the flow, or update it */
-void FlowVarAddStrNoLock(Flow *f, uint16_t idx, uint8_t *value, uint16_t size)
+void FlowVarAddStrNoLock(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
{
FlowVar *fv = FlowVarGet(f, idx);
if (fv == NULL) {
}
/* add a flowvar to the flow, or update it */
-void FlowVarAddStr(Flow *f, uint16_t idx, uint8_t *value, uint16_t size)
+void FlowVarAddStr(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
{
FlowVarAddStrNoLock(f, idx, value, size);
}
/* add a flowvar to the flow, or update it */
-void FlowVarAddIntNoLock(Flow *f, uint16_t idx, uint32_t value)
+void FlowVarAddIntNoLock(Flow *f, uint32_t idx, uint32_t value)
{
FlowVar *fv = FlowVarGet(f, idx);
if (fv == NULL) {
}
/* add a flowvar to the flow, or update it */
-void FlowVarAddInt(Flow *f, uint16_t idx, uint32_t value)
+void FlowVarAddInt(Flow *f, uint32_t idx, uint32_t value)
{
FlowVarAddIntNoLock(f, idx, value);
}
FlowVar *fv = (FlowVar *)gv;
if (fv->datatype == FLOWVAR_TYPE_STR) {
- SCLogDebug("Name idx \"%" PRIu16 "\", Value \"", fv->idx);
+ SCLogDebug("Name idx \"%" PRIu32 "\", Value \"", fv->idx);
for (u = 0; u < fv->data.fv_str.value_len; u++) {
if (isprint(fv->data.fv_str.value[u]))
SCLogDebug("%c", fv->data.fv_str.value[u]);
}
SCLogDebug("\", Len \"%" PRIu16 "\"\n", fv->data.fv_str.value_len);
} else if (fv->datatype == FLOWVAR_TYPE_INT) {
- SCLogDebug("Name idx \"%" PRIu16 "\", Value \"%" PRIu32 "\"", fv->idx,
+ SCLogDebug("Name idx \"%" PRIu32 "\", Value \"%" PRIu32 "\"", fv->idx,
fv->data.fv_int.value);
} else {
SCLogDebug("Unknown data type at flowvars\n");
/** Generic Flowvar Structure */
typedef struct FlowVar_ {
uint8_t type; /* type, DETECT_FLOWVAR in this case */
- uint16_t idx; /* name idx */
+ uint32_t idx; /* name idx */
GenericVar *next; /* right now just implement this as a list,
* in the long run we have think of something
* faster. */
/** Flowvar Interface API */
-void FlowVarAddStrNoLock(Flow *, uint16_t, uint8_t *, uint16_t);
-void FlowVarAddStr(Flow *, uint16_t, uint8_t *, uint16_t);
-void FlowVarAddIntNoLock(Flow *, uint16_t, uint32_t);
-void FlowVarAddInt(Flow *, uint16_t, uint32_t);
-FlowVar *FlowVarGet(Flow *, uint16_t);
+void FlowVarAddStrNoLock(Flow *, uint32_t, uint8_t *, uint16_t);
+void FlowVarAddStr(Flow *, uint32_t, uint8_t *, uint16_t);
+void FlowVarAddIntNoLock(Flow *, uint32_t, uint32_t);
+void FlowVarAddInt(Flow *, uint32_t, uint32_t);
+FlowVar *FlowVarGet(Flow *, uint32_t);
void FlowVarFree(FlowVar *);
void FlowVarPrint(GenericVar *);
}
/* get the bit with idx from the host */
-static XBit *HostBitGet(Host *h, uint16_t idx)
+static XBit *HostBitGet(Host *h, uint32_t idx)
{
GenericVar *gv = HostGetStorageById(h, host_bit_id);
for ( ; gv != NULL; gv = gv->next) {
}
/* add a flowbit to the flow */
-static void HostBitAdd(Host *h, uint16_t idx, uint32_t expire)
+static void HostBitAdd(Host *h, uint32_t idx, uint32_t expire)
{
XBit *fb = HostBitGet(h, idx);
if (fb == NULL) {
}
}
-static void HostBitRemove(Host *h, uint16_t idx)
+static void HostBitRemove(Host *h, uint32_t idx)
{
XBit *fb = HostBitGet(h, idx);
if (fb == NULL)
}
}
-void HostBitSet(Host *h, uint16_t idx, uint32_t expire)
+void HostBitSet(Host *h, uint32_t idx, uint32_t expire)
{
XBit *fb = HostBitGet(h, idx);
if (fb == NULL) {
}
}
-void HostBitUnset(Host *h, uint16_t idx)
+void HostBitUnset(Host *h, uint32_t idx)
{
XBit *fb = HostBitGet(h, idx);
if (fb != NULL) {
}
}
-void HostBitToggle(Host *h, uint16_t idx, uint32_t expire)
+void HostBitToggle(Host *h, uint32_t idx, uint32_t expire)
{
XBit *fb = HostBitGet(h, idx);
if (fb != NULL) {
}
}
-int HostBitIsset(Host *h, uint16_t idx, uint32_t ts)
+int HostBitIsset(Host *h, uint32_t idx, uint32_t ts)
{
XBit *fb = HostBitGet(h, idx);
if (fb != NULL) {
return 0;
}
-int HostBitIsnotset(Host *h, uint16_t idx, uint32_t ts)
+int HostBitIsnotset(Host *h, uint32_t idx, uint32_t ts)
{
XBit *fb = HostBitGet(h, idx);
if (fb == NULL) {
int HostHasHostBits(Host *host);
int HostBitsTimedoutCheck(Host *h, struct timeval *ts);
-void HostBitSet(Host *, uint16_t, uint32_t);
-void HostBitUnset(Host *, uint16_t);
-void HostBitToggle(Host *, uint16_t, uint32_t);
-int HostBitIsset(Host *, uint16_t, uint32_t);
-int HostBitIsnotset(Host *, uint16_t, uint32_t);
+void HostBitSet(Host *, uint32_t, uint32_t);
+void HostBitUnset(Host *, uint32_t);
+void HostBitToggle(Host *, uint32_t, uint32_t);
+int HostBitIsset(Host *, uint32_t, uint32_t);
+int HostBitIsnotset(Host *, uint32_t, uint32_t);
#endif /* __HOST_BIT_H__ */
}
/* get the bit with idx from the ippair */
-static XBit *IPPairBitGet(IPPair *h, uint16_t idx)
+static XBit *IPPairBitGet(IPPair *h, uint32_t idx)
{
GenericVar *gv = IPPairGetStorageById(h, ippair_bit_id);
for ( ; gv != NULL; gv = gv->next) {
}
/* add a flowbit to the flow */
-static void IPPairBitAdd(IPPair *h, uint16_t idx, uint32_t expire)
+static void IPPairBitAdd(IPPair *h, uint32_t idx, uint32_t expire)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb == NULL) {
}
}
-static void IPPairBitRemove(IPPair *h, uint16_t idx)
+static void IPPairBitRemove(IPPair *h, uint32_t idx)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb == NULL)
}
}
-void IPPairBitSet(IPPair *h, uint16_t idx, uint32_t expire)
+void IPPairBitSet(IPPair *h, uint32_t idx, uint32_t expire)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb == NULL) {
}
}
-void IPPairBitUnset(IPPair *h, uint16_t idx)
+void IPPairBitUnset(IPPair *h, uint32_t idx)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb != NULL) {
}
}
-void IPPairBitToggle(IPPair *h, uint16_t idx, uint32_t expire)
+void IPPairBitToggle(IPPair *h, uint32_t idx, uint32_t expire)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb != NULL) {
}
}
-int IPPairBitIsset(IPPair *h, uint16_t idx, uint32_t ts)
+int IPPairBitIsset(IPPair *h, uint32_t idx, uint32_t ts)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb != NULL) {
return 0;
}
-int IPPairBitIsnotset(IPPair *h, uint16_t idx, uint32_t ts)
+int IPPairBitIsnotset(IPPair *h, uint32_t idx, uint32_t ts)
{
XBit *fb = IPPairBitGet(h, idx);
if (fb == NULL) {
int IPPairHasBits(IPPair *host);
int IPPairBitsTimedoutCheck(IPPair *h, struct timeval *ts);
-void IPPairBitSet(IPPair *, uint16_t, uint32_t);
-void IPPairBitUnset(IPPair *, uint16_t);
-void IPPairBitToggle(IPPair *, uint16_t, uint32_t);
-int IPPairBitIsset(IPPair *, uint16_t, uint32_t);
-int IPPairBitIsnotset(IPPair *, uint16_t, uint32_t);
+void IPPairBitSet(IPPair *, uint32_t, uint32_t);
+void IPPairBitUnset(IPPair *, uint32_t);
+void IPPairBitToggle(IPPair *, uint32_t, uint32_t);
+int IPPairBitIsset(IPPair *, uint32_t, uint32_t);
+int IPPairBitIsnotset(IPPair *, uint32_t, uint32_t);
#endif /* __IPPAIR_BIT_H__ */
#include "suricata-common.h"
#include "detect.h"
#include "util-hashlist.h"
+#include "util-var-name.h"
+
+/* the way this can be used w/o locking lookups:
+ * - Lookups use only g_varnamestore_current which is read only
+ * - Detection setups a new ctx in staging, which will include the 'current'
+ * entries keeping ID's stable
+ * - Detection hot swaps staging into current after a new detect engine was
+ * created. Current remains available through 'old'.
+ * - When detect reload is complete (threads are all moved over), 'old' can
+ * be freed.
+ */
+
+typedef struct VarNameStore_ {
+ HashListTable *names;
+ HashListTable *ids;
+ uint32_t max_id;
+ uint32_t de_ctx_version; /**< de_ctx version 'owning' this */
+} VarNameStore;
+
+static int initialized = 0;
+/* currently VarNameStore that is READ ONLY. This way lookups can
+ * be done w/o locking or synchronization */
+SC_ATOMIC_DECLARE(VarNameStore *, g_varnamestore_current);
+
+/* old VarNameStore on the way out */
+static VarNameStore *g_varnamestore_old = NULL;
+
+/* new VarNameStore that is being prepared. Multiple DetectLoader threads
+ * may be updating it so a lock is used for synchronization. */
+static VarNameStore *g_varnamestore_staging = NULL;
+static SCMutex g_varnamestore_staging_m = SCMUTEX_INITIALIZER;
/** \brief Name2idx mapping structure for flowbits, flowvars and pktvars. */
typedef struct VariableName_ {
char *name;
uint8_t type; /* flowbit, pktvar, etc */
- uint16_t idx;
+ uint32_t idx;
} VariableName;
static uint32_t VariableNameHash(HashListTable *ht, void *buf, uint16_t buflen)
}
/** \brief Initialize the Name idx hash.
- * \param de_ctx Ptr to the detection engine ctx.
- * \retval -1 in case of error
- * \retval 0 in case of success
*/
-int VariableNameInitHash(DetectEngineCtx *de_ctx)
+static VarNameStore *VarNameStoreInit(void)
{
- de_ctx->variable_names = HashListTableInit(4096, VariableNameHash, VariableNameCompare, VariableNameFree);
- if (de_ctx->variable_names == NULL)
- return -1;
+ VarNameStore *v = SCCalloc(1, sizeof(*v));
+ if (v == NULL)
+ return NULL;
+
+ v->names = HashListTableInit(4096, VariableNameHash, VariableNameCompare, VariableNameFree);
+ if (v->names == NULL) {
+ SCFree(v);
+ return NULL;
+ }
- de_ctx->variable_idxs = HashListTableInit(4096, VariableIdxHash, VariableIdxCompare, NULL);
- if (de_ctx->variable_idxs == NULL)
- return -1;
+ v->ids = HashListTableInit(4096, VariableIdxHash, VariableIdxCompare, NULL);
+ if (v->ids == NULL) {
+ HashListTableFree(v->names);
+ SCFree(v);
+ return NULL;
+ }
- de_ctx->variable_names_idx = 0;
- return 0;
+ v->max_id = 0;
+ return v;
}
-void VariableNameFreeHash(DetectEngineCtx *de_ctx)
+static void VarNameStoreDoFree(VarNameStore *v)
{
- if (de_ctx->variable_names != NULL) {
- HashListTableFree(de_ctx->variable_names);
- HashListTableFree(de_ctx->variable_idxs);
- de_ctx->variable_names = NULL;
- de_ctx->variable_idxs = NULL;
+ if (v) {
+ HashListTableFree(v->names);
+ HashListTableFree(v->ids);
+ SCFree(v);
}
-
- return;
}
+
/** \brief Get a name idx for a name. If the name is already used reuse the idx.
* \param name nul terminated string with the name
* \param type variable type
* \retval 0 in case of error
* \retval idx the idx or 0
*/
-uint16_t VariableNameGetIdx(DetectEngineCtx *de_ctx, const char *name, enum VarTypes type)
+static uint32_t VariableNameGetIdx(VarNameStore *v, const char *name, enum VarTypes type)
{
- uint16_t idx = 0;
+ uint32_t idx = 0;
VariableName *fn = SCMalloc(sizeof(VariableName));
if (unlikely(fn == NULL))
if (fn->name == NULL)
goto error;
- VariableName *lookup_fn = (VariableName *)HashListTableLookup(de_ctx->variable_names, (void *)fn, 0);
+ VariableName *lookup_fn = (VariableName *)HashListTableLookup(v->names, (void *)fn, 0);
if (lookup_fn == NULL) {
- de_ctx->variable_names_idx++;
+ v->max_id++;
- idx = fn->idx = de_ctx->variable_names_idx;
- HashListTableAdd(de_ctx->variable_names, (void *)fn, 0);
- HashListTableAdd(de_ctx->variable_idxs, (void *)fn, 0);
+ idx = fn->idx = v->max_id;
+ HashListTableAdd(v->names, (void *)fn, 0);
+ HashListTableAdd(v->ids, (void *)fn, 0);
+ SCLogDebug("new registration %s id %u type %u", fn->name, fn->idx, fn->type);
} else {
idx = lookup_fn->idx;
VariableNameFree(fn);
return 0;
}
+#if 0
/** \brief Get a name from the idx.
* \param idx index of the variable whose name is to be fetched
* \param type variable type
* \retval NULL in case of error
* \retval name of the variable if successful.
+ * \todo no alloc on lookup
*/
-const char *VariableIdxGetName(DetectEngineCtx *de_ctx, uint16_t idx, enum VarTypes type)
+static const char *VariableIdxGetName(VarNameStore *v, uint32_t idx, enum VarTypes type)
{
VariableName *fn = SCMalloc(sizeof(VariableName));
if (unlikely(fn == NULL))
fn->type = type;
fn->idx = idx;
- VariableName *lookup_fn = (VariableName *)HashListTableLookup(de_ctx->variable_idxs, (void *)fn, 0);
+ VariableName *lookup_fn = (VariableName *)HashListTableLookup(v->ids, (void *)fn, 0);
if (lookup_fn != NULL) {
name = SCStrdup(lookup_fn->name);
if (unlikely(name == NULL))
VariableNameFree(fn);
return NULL;
}
+#endif
+/** \brief setup staging store. Include current store if there is one.
+ */
+int VarNameStoreSetupStaging(uint32_t de_ctx_version)
+{
+ SCMutexLock(&g_varnamestore_staging_m);
+
+ if (!initialized) {
+ SC_ATOMIC_INIT(g_varnamestore_current);
+ initialized = 1;
+ }
+
+ if (g_varnamestore_staging != NULL &&
+ g_varnamestore_staging->de_ctx_version == de_ctx_version) {
+ SCMutexUnlock(&g_varnamestore_staging_m);
+ return 0;
+ }
+
+ VarNameStore *nv = VarNameStoreInit();
+ if (nv == NULL) {
+ SCMutexUnlock(&g_varnamestore_staging_m);
+ return -1;
+ }
+ g_varnamestore_staging = nv;
+ nv->de_ctx_version = de_ctx_version;
+
+ VarNameStore *current = SC_ATOMIC_GET(g_varnamestore_current);
+ if (current) {
+ /* add all entries from the current hash into this new one. */
+ HashListTableBucket *b = HashListTableGetListHead(current->names);
+ while (b) {
+ VariableName *var = HashListTableGetListData(b);
+
+ VariableName *newvar = SCCalloc(1, sizeof(*newvar));
+ BUG_ON(newvar == NULL);
+ memcpy(newvar, var, sizeof(*newvar));
+ newvar->name = SCStrdup(var->name);
+ BUG_ON(newvar->name == NULL);
+
+ HashListTableAdd(nv->names, (void *)newvar, 0);
+ HashListTableAdd(nv->ids, (void *)newvar, 0);
+ nv->max_id = MAX(nv->max_id, newvar->idx);
+ SCLogDebug("xfer %s id %u type %u", newvar->name, newvar->idx, newvar->type);
+
+ b = HashListTableGetListNext(b);
+ }
+ }
+
+ SCLogDebug("set up staging with detect engine ver %u", nv->de_ctx_version);
+ SCMutexUnlock(&g_varnamestore_staging_m);
+ return 0;
+}
+
+const char *VarNameStoreLookupById(const uint32_t id, const enum VarTypes type)
+{
+ VarNameStore *current = SC_ATOMIC_GET(g_varnamestore_current);
+ BUG_ON(current == NULL);
+ VariableName lookup = { NULL, type, id };
+ VariableName *found = (VariableName *)HashListTableLookup(current->ids, (void *)&lookup, 0);
+ if (found == NULL) {
+ return NULL;
+ }
+ return found->name;
+}
+
+uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type)
+{
+ VarNameStore *current = SC_ATOMIC_GET(g_varnamestore_current);
+ BUG_ON(current == NULL);
+ VariableName lookup = { (char *)name, type, 0 };
+ VariableName *found = (VariableName *)HashListTableLookup(current->names, (void *)&lookup, 0);
+ if (found == NULL) {
+ return 0;
+ }
+ SCLogDebug("found %u for %s type %u", found->idx, name, type);
+ return found->idx;
+}
+
+/** \brief add to staging or return existing id if already in there */
+uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type)
+{
+ uint32_t id;
+ SCMutexLock(&g_varnamestore_staging_m);
+ id = VariableNameGetIdx(g_varnamestore_staging, name, type);
+ SCMutexUnlock(&g_varnamestore_staging_m);
+ return id;
+}
+
+void VarNameStoreActivateStaging(void)
+{
+ SCMutexLock(&g_varnamestore_staging_m);
+ if (g_varnamestore_old) {
+ VarNameStoreDoFree(g_varnamestore_old);
+ g_varnamestore_old = NULL;
+ }
+ g_varnamestore_old = SC_ATOMIC_GET(g_varnamestore_current);
+ SC_ATOMIC_SET(g_varnamestore_current, g_varnamestore_staging);
+ g_varnamestore_staging = NULL;
+ SCMutexUnlock(&g_varnamestore_staging_m);
+}
+
+void VarNameStoreFreeOld(void)
+{
+ SCMutexLock(&g_varnamestore_staging_m);
+ SCLogDebug("freeing g_varnamestore_old %p", g_varnamestore_old);
+ if (g_varnamestore_old) {
+ VarNameStoreDoFree(g_varnamestore_old);
+ g_varnamestore_old = NULL;
+ }
+ SCMutexUnlock(&g_varnamestore_staging_m);
+}
+
+void VarNameStoreFree(uint32_t de_ctx_version)
+{
+ SCLogDebug("freeing detect engine version %u", de_ctx_version);
+ SCMutexLock(&g_varnamestore_staging_m);
+ if (g_varnamestore_old && g_varnamestore_old->de_ctx_version == de_ctx_version) {
+ VarNameStoreDoFree(g_varnamestore_old);
+ g_varnamestore_old = NULL;
+ SCLogDebug("freeing detect engine version %u: old done", de_ctx_version);
+ }
+
+ /* if at this point we have a staging area which matches our version
+ * we didn't complete the setup and are cleaning up the mess. */
+ if (g_varnamestore_staging && g_varnamestore_staging->de_ctx_version == de_ctx_version) {
+ VarNameStoreDoFree(g_varnamestore_staging);
+ g_varnamestore_staging = NULL;
+ SCLogDebug("freeing detect engine version %u: staging done", de_ctx_version);
+ }
+
+ VarNameStore *current = SC_ATOMIC_GET(g_varnamestore_current);
+ if (current && current->de_ctx_version == de_ctx_version) {
+ VarNameStoreDoFree(current);
+ SC_ATOMIC_SET(g_varnamestore_current, NULL);
+ SCLogDebug("freeing detect engine version %u: current done", de_ctx_version);
+ }
+ SCMutexUnlock(&g_varnamestore_staging_m);
+}
-/* Copyright (C) 2007-2010 Open Information Security Foundation
+/* Copyright (C) 2007-2016 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
#ifndef __UTIL_VAR_NAME_H__
#define __UTIL_VAR_NAME_H__
-int VariableNameInitHash(DetectEngineCtx *);
-void VariableNameFreeHash(DetectEngineCtx *);
-
-uint16_t VariableNameGetIdx(DetectEngineCtx *,
- const char *name, enum VarTypes type);
-const char *VariableIdxGetName(DetectEngineCtx *,
- uint16_t id, enum VarTypes type);
+int VarNameStoreSetupStaging(uint32_t de_ctx_version);
+const char *VarNameStoreLookupById(const uint32_t id, const enum VarTypes type);
+uint32_t VarNameStoreLookupByName(const char *name, const enum VarTypes type);
+uint32_t VarNameStoreSetupAdd(const char *name, const enum VarTypes type);
+void VarNameStoreActivateStaging(void);
+void VarNameStoreFreeOld(void);
+void VarNameStoreFree(uint32_t de_ctx_version);
#endif
typedef struct GenericVar_ {
uint8_t type;
- uint16_t idx;
+ uint32_t idx;
struct GenericVar_ *next;
} GenericVar;
typedef struct XBit_ {
uint8_t type; /* type, DETECT_XBITS in this case */
- uint16_t idx; /* name idx */
+ uint32_t idx; /* name idx */
GenericVar *next;
uint32_t expire;
} XBit;