lua: support key/value flowvars in lua

pull/2559/head
Victor Julien 9 years ago
parent f0af133c5f
commit 99517cbd53

@ -303,7 +303,7 @@ static int DetectFlowvarPostMatch(ThreadVars *tv,
//PrintRawDataFp(stdout, fs->buffer, fs->len);
if (fs->type == DETECT_VAR_TYPE_FLOW_POSTMATCH && p && p->flow) {
FlowVarAddStrNoLock(p->flow, fs->idx, fs->buffer, fs->len);
FlowVarAddIdValue(p->flow, fs->idx, fs->buffer, fs->len);
/* memory at fs->buffer is now the responsibility of
* the flowvar code. */
} else if (fs->type == DETECT_VAR_TYPE_PKT_POSTMATCH && fs->key && p) {

@ -72,308 +72,340 @@
#include "util-lua-dnp3.h"
static const char luaext_key_ld[] = "suricata:luadata";
static const char luaext_key_det_ctx[] = "suricata:det_ctx";
static int LuaGetFlowvar(lua_State *luastate)
/* hack to please scan-build. Even though LuaCallbackError *always*
* returns 2, scan-build doesn't accept it and and generates false
* positives */
#define LUA_ERROR(msg) \
LuaCallbackError(luastate, (msg)); \
return 2
static int GetLuaData(lua_State *luastate, DetectLuaData **ret_ld)
{
uint16_t idx;
int id;
Flow *f;
FlowVar *fv;
DetectLuaData *ld;
*ret_ld = NULL;
/* need lua data for id -> idx conversion */
DetectLuaData *ld;
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
lua_gettable(luastate, LUA_REGISTRYINDEX);
ld = lua_touserdata(luastate, -1);
SCLogDebug("ld %p", ld);
if (ld == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no ld");
return 2;
LUA_ERROR("internal error: no ld");
}
*ret_ld = ld;
return 0;
}
/* need flow and lock hint */
f = LuaStateGetFlow(luastate);
static int GetFlow(lua_State *luastate, Flow **ret_f)
{
Flow *f = LuaStateGetFlow(luastate);
if (f == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow");
return 2;
LUA_ERROR("no flow");
}
*ret_f = f;
return 0;
}
static int GetFlowVarById(lua_State *luastate, Flow *f,
FlowVar **ret_fv, _Bool fv_may_be_null, uint32_t *ret_idx)
{
DetectLuaData *ld = NULL;
if (ret_idx)
*ret_idx = 0;
*ret_fv = NULL;
/* need lua data for id -> idx conversion */
int ret = GetLuaData(luastate, &ld);
if (ret != 0)
return ret;
/* need flowvar idx */
if (!lua_isnumber(luastate, 1)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "1st arg not a number");
return 2;
LUA_ERROR("flowvar id not a number");
}
id = lua_tonumber(luastate, 1);
int id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
lua_pushnil(luastate);
lua_pushstring(luastate, "flowvar id out of range");
return 2;
LUA_ERROR("flowvar id out of range");
}
idx = ld->flowvar[id];
uint32_t idx = ld->flowvar[id];
if (idx == 0) {
lua_pushnil(luastate);
lua_pushstring(luastate, "flowvar id uninitialized");
return 2;
LUA_ERROR("flowvar id uninitialized");
}
FlowVar *fv = FlowVarGet(f, idx);
if (!fv_may_be_null && fv == NULL) {
LUA_ERROR("no flow var");
}
*ret_fv = fv;
if (ret_idx)
*ret_idx = idx;
return 0;
}
static int GetFlowVarByKey(lua_State *luastate, Flow *f, FlowVar **ret_fv)
{
*ret_fv = NULL;
if (!lua_isstring(luastate, 1)) {
LUA_ERROR("flowvar key not a string");
}
const char *keystr = lua_tostring(luastate, 1);
if (keystr == NULL) {
LUA_ERROR("key is null");
}
if (!lua_isnumber(luastate, 2)) {
LUA_ERROR("key length not specified");
}
int keylen = lua_tonumber(luastate, 2);
if (keylen < 0 || keylen > 0xff) {
LUA_ERROR("key len out of range: max 256");
}
fv = FlowVarGet(f, idx);
FlowVar *fv = FlowVarGetByKey(f, (const uint8_t *)keystr, keylen);
if (fv == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow var");
return 2;
LUA_ERROR("no flow var");
}
*ret_fv = fv;
return 0;
}
LuaPushStringBuffer(luastate, (const uint8_t *)fv->data.fv_str.value,
(size_t)fv->data.fv_str.value_len);
static int GetFlowIntById(lua_State *luastate, Flow *f,
FlowVar **ret_fv, _Bool fv_may_be_null, uint32_t *ret_idx)
{
DetectLuaData *ld = NULL;
if (ret_idx)
*ret_idx = 0;
*ret_fv = NULL;
return 1;
/* need lua data for id -> idx conversion */
int ret = GetLuaData(luastate, &ld);
if (ret != 0)
return ret;
if (!lua_isnumber(luastate, 1)) {
LUA_ERROR("flowvar id not a number");
}
int id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
LUA_ERROR("flowvar id out of range");
}
uint32_t idx = ld->flowint[id];
if (idx == 0) {
LUA_ERROR("flowvar id uninitialized");
}
FlowVar *fv = FlowVarGet(f, idx);
if (!fv_may_be_null && fv == NULL) {
LUA_ERROR("no flow var");
}
*ret_fv = fv;
if (ret_idx)
*ret_idx = idx;
return 0;
}
static int LuaGetFlowvar(lua_State *luastate)
{
Flow *f;
FlowVar *fv;
int ret;
/* need flow */
ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
if (lua_isnumber(luastate, 1)) {
ret = GetFlowVarById(luastate, f, &fv, FALSE, NULL);
if (ret != 0 || fv == NULL)
return ret;
} else if (lua_isstring(luastate, 1)) {
ret = GetFlowVarByKey(luastate, f, &fv);
if (ret != 0 || fv == NULL)
return ret;
} else {
LUA_ERROR("invalid data type as first argument");
}
int LuaSetFlowvar(lua_State *luastate)
LuaPushStringBuffer(luastate,
(const uint8_t *)fv->data.fv_str.value,
(size_t)fv->data.fv_str.value_len);
return 1;
}
static int LuaSetFlowvarById(lua_State *luastate)
{
uint16_t idx;
int id;
uint32_t idx = 0;
Flow *f;
const char *str;
int len;
uint8_t *buffer;
DetectEngineThreadCtx *det_ctx;
DetectLuaData *ld;
FlowVar *fv = NULL;
/* need lua data for id -> idx conversion */
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
lua_gettable(luastate, LUA_REGISTRYINDEX);
ld = lua_touserdata(luastate, -1);
SCLogDebug("ld %p", ld);
if (ld == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no ld");
return 2;
/* need flow */
int ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
ret = GetFlowVarById(luastate, f, &fv, TRUE, &idx);
if (ret != 0)
return ret;
if (!lua_isstring(luastate, 2)) {
LUA_ERROR("buffer not a string");
}
str = lua_tostring(luastate, 2);
if (str == NULL) {
LUA_ERROR("buffer is null");
}
/* need det_ctx */
lua_pushlightuserdata(luastate, (void *)&luaext_key_det_ctx);
lua_gettable(luastate, LUA_REGISTRYINDEX);
det_ctx = lua_touserdata(luastate, -1);
SCLogDebug("det_ctx %p", det_ctx);
if (det_ctx == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no det_ctx");
return 2;
if (!lua_isnumber(luastate, 3)) {
LUA_ERROR("buffer length not specified");
}
len = lua_tonumber(luastate, 3);
if (len < 0 || len > 0xffff) {
LUA_ERROR("len out of range: max 64k");
}
/* need flow and lock hint */
f = LuaStateGetFlow(luastate);
if (f == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow");
return 2;
buffer = SCMalloc(len+1);
if (unlikely(buffer == NULL)) {
LUA_ERROR("out of memory");
}
memcpy(buffer, str, len);
buffer[len] = '\0';
/* need flowvar idx */
if (!lua_isnumber(luastate, 1)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "1st arg not a number");
return 2;
FlowVarAddIdValue(f, idx, buffer, len);
return 0;
}
id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
lua_pushnil(luastate);
lua_pushstring(luastate, "flowvar id out of range");
return 2;
static int LuaSetFlowvarByKey(lua_State *luastate)
{
Flow *f;
const char *str;
int len;
uint8_t *buffer;
/* need flow */
int ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
const char *keystr = NULL;
int keylen = 0;
keystr = lua_tostring(luastate, 1);
if (keystr == NULL) {
LUA_ERROR("key is null");
}
if (!lua_isnumber(luastate, 2)) {
LUA_ERROR("key length not specified");
}
keylen = lua_tonumber(luastate, 2);
if (keylen < 0 || keylen > 0xff) {
LUA_ERROR("key len out of range: max 256");
}
if (!lua_isstring(luastate, 2)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "2nd arg not a string");
return 2;
if (!lua_isstring(luastate, 3)) {
LUA_ERROR("buffer not a string");
}
str = lua_tostring(luastate, 2);
str = lua_tostring(luastate, 3);
if (str == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "null string");
return 2;
LUA_ERROR("buffer is null");
}
if (!lua_isnumber(luastate, 3)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "3rd arg not a number");
return 2;
if (!lua_isnumber(luastate, 4)) {
LUA_ERROR("buffer length not specified");
}
len = lua_tonumber(luastate, 3);
len = lua_tonumber(luastate, 4);
if (len < 0 || len > 0xffff) {
lua_pushnil(luastate);
lua_pushstring(luastate, "len out of range: max 64k");
return 2;
}
idx = ld->flowvar[id];
if (idx == 0) {
lua_pushnil(luastate);
lua_pushstring(luastate, "flowvar id uninitialized");
return 2;
LUA_ERROR("len out of range: max 64k");
}
buffer = SCMalloc(len+1);
if (unlikely(buffer == NULL)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "out of memory");
return 2;
LUA_ERROR("out of memory");
}
memcpy(buffer, str, len);
buffer[len] = '\0';
FlowVarAddStr(f, idx, buffer, len);
uint8_t *keybuf = SCMalloc(keylen+1);
if (unlikely(keybuf == NULL)) {
SCFree(buffer);
LUA_ERROR("out of memory");
}
memcpy(keybuf, keystr, keylen);
keybuf[keylen] = '\0';
FlowVarAddKeyValue(f, keybuf, keylen, buffer, len);
//SCLogInfo("stored:");
//PrintRawDataFp(stdout,buffer,len);
return 0;
}
static int LuaSetFlowvar(lua_State *luastate)
{
if (lua_isnumber(luastate, 1)) {
return LuaSetFlowvarById(luastate);
} else {
return LuaSetFlowvarByKey(luastate);
}
}
static int LuaGetFlowint(lua_State *luastate)
{
uint16_t idx;
int id;
Flow *f;
FlowVar *fv;
DetectLuaData *ld;
uint32_t number;
/* need lua data for id -> idx conversion */
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
lua_gettable(luastate, LUA_REGISTRYINDEX);
ld = lua_touserdata(luastate, -1);
SCLogDebug("ld %p", ld);
if (ld == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no ld");
return 2;
}
/* need flow and lock hint */
f = LuaStateGetFlow(luastate);
if (f == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow");
return 2;
}
/* need flow */
int ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
/* need flowint idx */
if (!lua_isnumber(luastate, 1)) {
SCLogDebug("1st arg not a number");
lua_pushnil(luastate);
lua_pushstring(luastate, "1st arg not a number");
return 2;
}
id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWINTS) {
SCLogDebug("id %d", id);
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id out of range");
return 2;
}
idx = ld->flowint[id];
if (idx == 0) {
SCLogDebug("idx %u", idx);
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id uninitialized");
return 2;
}
ret = GetFlowIntById(luastate, f, &fv, FALSE, NULL);
if (ret != 0)
return ret;
/* lookup var */
fv = FlowVarGet(f, idx);
if (fv == NULL) {
SCLogDebug("fv NULL");
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow var");
return 2;
}
number = fv->data.fv_int.value;
/* return value through luastate, as a luanumber */
lua_pushnumber(luastate, (lua_Number)number);
SCLogDebug("retrieved flow:%p idx:%u value:%u", f, idx, number);
return 1;
}
int LuaSetFlowint(lua_State *luastate)
static int LuaSetFlowint(lua_State *luastate)
{
uint16_t idx;
int id;
uint32_t idx;
Flow *f;
DetectEngineThreadCtx *det_ctx;
DetectLuaData *ld;
uint32_t number;
lua_Number luanumber;
/* need lua data for id -> idx conversion */
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
lua_gettable(luastate, LUA_REGISTRYINDEX);
ld = lua_touserdata(luastate, -1);
SCLogDebug("ld %p", ld);
if (ld == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no ld");
return 2;
}
/* need det_ctx */
lua_pushlightuserdata(luastate, (void *)&luaext_key_det_ctx);
lua_gettable(luastate, LUA_REGISTRYINDEX);
det_ctx = lua_touserdata(luastate, -1);
SCLogDebug("det_ctx %p", det_ctx);
if (det_ctx == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no det_ctx");
return 2;
}
int ret = GetLuaData(luastate, &ld);
if (ret != 0)
return ret;
/* need flow and lock hint */
f = LuaStateGetFlow(luastate);
if (f == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow");
return 2;
}
/* need flow */
ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
/* need flowint idx */
if (!lua_isnumber(luastate, 1)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "1st arg not a number");
return 2;
LUA_ERROR("1st arg not a number");
}
id = lua_tonumber(luastate, 1);
int id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWVARS) {
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id out of range");
return 2;
LUA_ERROR("flowint id out of range");
}
if (!lua_isnumber(luastate, 2)) {
lua_pushnil(luastate);
lua_pushstring(luastate, "2nd arg not a number");
return 2;
LUA_ERROR("2nd arg not a number");
}
luanumber = lua_tonumber(luastate, 2);
lua_Number luanumber = lua_tonumber(luastate, 2);
if (luanumber < 0 || id > (double)UINT_MAX) {
lua_pushnil(luastate);
lua_pushstring(luastate, "value out of range, value must be unsigned 32bit int");
return 2;
LUA_ERROR("value out of range, "
"value must be unsigned 32bit int");
}
number = (uint32_t)luanumber;
uint32_t number = (uint32_t)luanumber;
idx = ld->flowint[id];
if (idx == 0) {
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id uninitialized");
return 2;
LUA_ERROR("flowint id uninitialized");
}
FlowVarAddInt(f, idx, number);
@ -384,56 +416,20 @@ int LuaSetFlowint(lua_State *luastate)
static int LuaIncrFlowint(lua_State *luastate)
{
uint16_t idx;
int id;
uint32_t idx;
Flow *f;
FlowVar *fv;
DetectLuaData *ld;
uint32_t number;
/* need lua data for id -> idx conversion */
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
lua_gettable(luastate, LUA_REGISTRYINDEX);
ld = lua_touserdata(luastate, -1);
SCLogDebug("ld %p", ld);
if (ld == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no ld");
return 2;
}
/* need flow and lock hint */
f = LuaStateGetFlow(luastate);
if (f == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow");
return 2;
}
/* need flow */
int ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
/* need flowint idx */
if (!lua_isnumber(luastate, 1)) {
SCLogDebug("1st arg not a number");
lua_pushnil(luastate);
lua_pushstring(luastate, "1st arg not a number");
return 2;
}
id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWINTS) {
SCLogDebug("id %d", id);
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id out of range");
return 2;
}
idx = ld->flowint[id];
if (idx == 0) {
SCLogDebug("idx %u", idx);
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id uninitialized");
return 2;
}
ret = GetFlowIntById(luastate, f, &fv, TRUE, &idx);
if (ret != 0)
return ret;
/* lookup var */
fv = FlowVarGet(f, idx);
if (fv == NULL) {
number = 1;
} else {
@ -446,63 +442,26 @@ static int LuaIncrFlowint(lua_State *luastate)
/* return value through luastate, as a luanumber */
lua_pushnumber(luastate, (lua_Number)number);
SCLogDebug("incremented flow:%p idx:%u value:%u", f, idx, number);
return 1;
}
static int LuaDecrFlowint(lua_State *luastate)
{
uint16_t idx;
int id;
uint32_t idx;
Flow *f;
FlowVar *fv;
DetectLuaData *ld;
uint32_t number;
/* need lua data for id -> idx conversion */
lua_pushlightuserdata(luastate, (void *)&luaext_key_ld);
lua_gettable(luastate, LUA_REGISTRYINDEX);
ld = lua_touserdata(luastate, -1);
SCLogDebug("ld %p", ld);
if (ld == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "internal error: no ld");
return 2;
}
/* need flow */
int ret = GetFlow(luastate, &f);
if (ret != 0)
return ret;
/* need flow and lock hint */
f = LuaStateGetFlow(luastate);
if (f == NULL) {
lua_pushnil(luastate);
lua_pushstring(luastate, "no flow");
return 2;
}
ret = GetFlowIntById(luastate, f, &fv, TRUE, &idx);
if (ret != 0)
return ret;
/* need flowint idx */
if (!lua_isnumber(luastate, 1)) {
SCLogDebug("1st arg not a number");
lua_pushnil(luastate);
lua_pushstring(luastate, "1st arg not a number");
return 2;
}
id = lua_tonumber(luastate, 1);
if (id < 0 || id >= DETECT_LUAJIT_MAX_FLOWINTS) {
SCLogDebug("id %d", id);
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id out of range");
return 2;
}
idx = ld->flowint[id];
if (idx == 0) {
SCLogDebug("idx %u", idx);
lua_pushnil(luastate);
lua_pushstring(luastate, "flowint id uninitialized");
return 2;
}
/* lookup var */
fv = FlowVarGet(f, idx);
if (fv == NULL) {
number = 0;
} else {
@ -515,7 +474,6 @@ static int LuaDecrFlowint(lua_State *luastate)
/* return value through luastate, as a luanumber */
lua_pushnumber(luastate, (lua_Number)number);
SCLogDebug("decremented flow:%p idx:%u value:%u", f, idx, number);
return 1;
}
@ -530,11 +488,6 @@ void LuaExtensionsMatchSetup(lua_State *lua_state, DetectLuaData *ld, DetectEngi
lua_pushlightuserdata(lua_state, (void *)ld);
lua_settable(lua_state, LUA_REGISTRYINDEX);
/* detection engine thread ctx */
lua_pushlightuserdata(lua_state, (void *)&luaext_key_det_ctx);
lua_pushlightuserdata(lua_state, (void *)det_ctx);
lua_settable(lua_state, LUA_REGISTRYINDEX);
LuaStateSetFlow(lua_state, f);
if (det_ctx->tx_id_set) {

@ -47,6 +47,27 @@ static void FlowVarUpdateInt(FlowVar *fv, uint32_t value)
fv->data.fv_int.value = value;
}
/** \brief get the flowvar with index 'idx' from the flow
* \note flow is not locked by this function, caller is
* responsible
*/
FlowVar *FlowVarGetByKey(Flow *f, const uint8_t *key, uint16_t keylen)
{
GenericVar *gv = f->flowvar;
for ( ; gv != NULL; gv = gv->next) {
if (gv->type == DETECT_FLOWVAR && gv->idx == 0) {
FlowVar *fv = (FlowVar *)gv;
if (fv->keylen == keylen && memcmp(key, fv->key, keylen) == 0) {
return fv;
}
}
}
return NULL;
}
/** \brief get the flowvar with index 'idx' from the flow
* \note flow is not locked by this function, caller is
* responsible
@ -64,11 +85,30 @@ FlowVar *FlowVarGet(Flow *f, uint32_t idx)
}
/* add a flowvar to the flow, or update it */
void FlowVarAddStrNoLock(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
void FlowVarAddKeyValue(Flow *f, uint8_t *key, uint16_t keysize, uint8_t *value, uint16_t size)
{
FlowVar *fv = SCCalloc(1, sizeof(FlowVar));
if (unlikely(fv == NULL))
return;
fv->type = DETECT_FLOWVAR;
fv->datatype = FLOWVAR_TYPE_STR;
fv->idx = 0;
fv->data.fv_str.value = value;
fv->data.fv_str.value_len = size;
fv->key = key;
fv->keylen = keysize;
fv->next = NULL;
GenericVarAppend(&f->flowvar, (GenericVar *)fv);
}
/* add a flowvar to the flow, or update it */
void FlowVarAddIdValue(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
{
FlowVar *fv = FlowVarGet(f, idx);
if (fv == NULL) {
fv = SCMalloc(sizeof(FlowVar));
fv = SCCalloc(1, sizeof(FlowVar));
if (unlikely(fv == NULL))
return;
@ -85,12 +125,6 @@ void FlowVarAddStrNoLock(Flow *f, uint32_t idx, uint8_t *value, uint16_t size)
}
}
/* add a flowvar to the flow, or update it */
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, uint32_t idx, uint32_t value)
{

@ -56,16 +56,19 @@ typedef struct FlowVar_ {
FlowVarTypeStr fv_str;
FlowVarTypeInt fv_int;
} data;
uint8_t *key;
uint16_t keylen;
} FlowVar;
/** Flowvar Interface API */
void FlowVarAddStrNoLock(Flow *, uint32_t, uint8_t *, uint16_t);
void FlowVarAddStr(Flow *, uint32_t, uint8_t *, uint16_t);
void FlowVarAddIdValue(Flow *, uint32_t id, uint8_t *value, uint16_t size);
void FlowVarAddKeyValue(Flow *f, uint8_t *key, uint16_t keysize, uint8_t *value, uint16_t size);
void FlowVarAddIntNoLock(Flow *, uint32_t, uint32_t);
void FlowVarAddInt(Flow *, uint32_t, uint32_t);
FlowVar *FlowVarGet(Flow *, uint32_t);
FlowVar *FlowVarGetByKey(Flow *f, const uint8_t *key, uint16_t keylen);
void FlowVarFree(FlowVar *);
void FlowVarPrint(GenericVar *);

@ -160,7 +160,7 @@ static void JsonAddFlowvars(const Flow *f, json_t *js_vars)
while (gv != NULL) {
if (gv->type == DETECT_FLOWVAR || gv->type == DETECT_FLOWINT) {
FlowVar *fv = (FlowVar *)gv;
if (fv->datatype == FLOWVAR_TYPE_STR) {
if (fv->datatype == FLOWVAR_TYPE_STR && fv->key == NULL) {
const char *varname = VarNameStoreLookupById(fv->idx, VAR_TYPE_FLOW_VAR);
if (varname) {
if (js_flowvars == NULL) {
@ -179,6 +179,29 @@ static void JsonAddFlowvars(const Flow *f, json_t *js_vars)
json_object_set_new(js_flowvars, varname,
json_string((char *)printable_buf));
}
} else if (fv->datatype == FLOWVAR_TYPE_STR && fv->key != NULL) {
if (js_flowvars == NULL) {
js_flowvars = json_object();
if (js_flowvars == NULL)
break;
}
uint8_t keybuf[fv->keylen + 1];
uint32_t offset = 0;
PrintStringsToBuffer(keybuf, &offset,
sizeof(keybuf),
fv->key, fv->keylen);
uint32_t len = fv->data.fv_str.value_len;
uint8_t printable_buf[len + 1];
offset = 0;
PrintStringsToBuffer(printable_buf, &offset,
sizeof(printable_buf),
fv->data.fv_str.value, fv->data.fv_str.value_len);
json_object_set_new(js_flowvars, (const char *)keybuf,
json_string((char *)printable_buf));
} else if (fv->datatype == FLOWVAR_TYPE_INT) {
const char *varname = VarNameStoreLookupById(fv->idx, VAR_TYPE_FLOW_INT);
if (varname) {

Loading…
Cancel
Save