detect/lua: add support for datasets

dataset.new
  create a dataset object in lua

<dataset>:get
  gets a reference to an existing dataset

<dataset>:add
  returns 1 if a new entry was added
  returns 0 if entry was already in the set

Example:
```
function init (args)
    local needs = {}
    needs["packet"] = tostring(true)
    return needs
end

function thread_init (args)
    conn_new, dataset.new()
    ret, err conn_new:get("conn-seen")
    if err ~= nil then
        SCLogWarning("dataset warning: " .. err)
        return 0
    end
end

function match (args)
    ipver, srcip, dstip, proto, sp, dp = SCFlowTuple()
    str = ipver .. ":<" .. srcip .. ">:<" .. dstip .. ">:" .. dp

    ret, err = conn_new:add(str, #str);
    if ret == 1 then
        SCLogInfo(str .. " => " .. ret)
    end
    return ret
end
```

Ticket: #7243.
pull/12379/head
Victor Julien 11 months ago committed by Victor Julien
parent e89ab4f88a
commit ccebae6ec0

@ -28,6 +28,7 @@
#include "threads.h"
#include "decode.h"
#include "datasets.h"
#include "detect.h"
#include "detect-parse.h"
@ -414,6 +415,121 @@ static int LuaSetFlowint(lua_State *luastate)
return 0;
}
struct LuaDataset {
Dataset *set;
};
static int LuaDatasetGC(lua_State *luastate)
{
SCLogDebug("gc:start");
struct LuaDataset *s = (struct LuaDataset *)lua_touserdata(luastate, 1);
SCLogDebug("deref %s", s->set->name);
s->set = NULL;
SCLogDebug("gc:done");
return 0;
}
static int LuaDatasetGetRef(lua_State *luastate)
{
SCLogDebug("get");
struct LuaDataset *s = (struct LuaDataset *)lua_touserdata(luastate, 1);
if (s == NULL) {
LUA_ERROR("dataset is not initialized");
}
const char *name = lua_tostring(luastate, 2);
if (name == NULL) {
LUA_ERROR("null string");
}
Dataset *dataset = DatasetFind(name, DATASET_TYPE_STRING);
if (dataset == NULL) {
LUA_ERROR("dataset not found");
}
s->set = dataset;
return 0;
}
static int LuaDatasetAdd(lua_State *luastate)
{
SCLogDebug("add:start");
struct LuaDataset *s = (struct LuaDataset *)lua_touserdata(luastate, 1);
if (s == NULL) {
LUA_ERROR("dataset is not initialized");
}
if (!lua_isstring(luastate, 2)) {
LUA_ERROR("1st arg is not a string");
}
if (!lua_isnumber(luastate, 3)) {
LUA_ERROR("2nd arg is not a number");
}
const uint8_t *str = (const uint8_t *)lua_tostring(luastate, 2);
if (str == NULL) {
LUA_ERROR("1st arg is not null string");
}
uint32_t str_len = lua_tonumber(luastate, 3);
int r = DatasetAdd(s->set, (const uint8_t *)str, str_len);
/* return value through luastate, as a luanumber */
lua_pushnumber(luastate, (lua_Number)r);
SCLogDebug("add:end");
return 1;
}
static int LuaDatasetNew(lua_State *luastate)
{
SCLogDebug("new:start");
struct LuaDataset *s = (struct LuaDataset *)lua_newuserdata(luastate, sizeof(*s));
if (s == NULL) {
LUA_ERROR("failed to get userdata");
}
luaL_getmetatable(luastate, "dataset::metatable");
lua_setmetatable(luastate, -2);
SCLogDebug("new:done");
return 1;
}
// clang-format off
const luaL_Reg datasetlib[] = {
{ "new", LuaDatasetNew },
{ "get", LuaDatasetGetRef },
{ "add", LuaDatasetAdd },
{ "__gc", LuaDatasetGC },
{ NULL, NULL }
};
// clang-format on
static void SetFuncs(lua_State *luastate, const luaL_Reg *lib)
{
for (; lib->name != NULL; lib++) {
lua_pushstring(luastate, lib->name);
lua_pushcfunction(luastate, lib->func);
lua_settable(luastate, -3);
}
}
static void CreateMeta(lua_State *luastate)
{
luaL_newmetatable(luastate, "dataset::metatable");
lua_pushliteral(luastate, "__index");
lua_pushvalue(luastate, -2);
lua_rawset(luastate, -3);
SetFuncs(luastate, datasetlib);
}
static void LuaDatasetRegister(lua_State *luastate)
{
CreateMeta(luastate);
lua_newtable(luastate);
SetFuncs(luastate, datasetlib);
lua_pushvalue(luastate, -1);
lua_setglobal(luastate, "dataset");
lua_pop(luastate, 1);
lua_pop(luastate, 1);
}
static int LuaIncrFlowint(lua_State *luastate)
{
uint32_t idx;
@ -578,6 +694,8 @@ int LuaRegisterExtensions(lua_State *lua_state)
lua_pushcfunction(lua_state, LuaGetByteVar);
lua_setglobal(lua_state, "SCByteVarGet");
LuaDatasetRegister(lua_state);
LuaRegisterFunctions(lua_state);
LuaRegisterHttpFunctions(lua_state);
LuaRegisterDnsFunctions(lua_state);

Loading…
Cancel
Save