Skip to content

Commit

Permalink
detect/lua: add support for datasets
Browse files Browse the repository at this point in the history
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: OISF#7243.
  • Loading branch information
victorjulien authored and jasonish committed Jan 10, 2025
1 parent febca27 commit e032c90
Showing 1 changed file with 118 additions and 0 deletions.
118 changes: 118 additions & 0 deletions src/detect-lua-extensions.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "threads.h"
#include "decode.h"
#include "datasets.h"

#include "detect.h"
#include "detect-parse.h"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit e032c90

Please sign in to comment.