diff --git a/src/output-lua-common.c b/src/output-lua-common.c index 2f264386ab..255c2f9371 100644 --- a/src/output-lua-common.c +++ b/src/output-lua-common.c @@ -118,6 +118,34 @@ void LogLuaPushTableKeyValueArray(lua_State *luastate, const char *key, const ui lua_settable(luastate, -3); } +/** \internal + * \brief fill lua stack with payload + * \param luastate the lua state + * \param p packet + * \retval cnt number of data items placed on the stack + * + * Places: payload (string) + */ +static int LuaCallbackStreamingBufferPushToStack(lua_State *luastate, const LuaStreamingBuffer *b) +{ + //PrintRawDataFp(stdout, (uint8_t *)b->data, b->data_len); + lua_pushlstring (luastate, (const char *)b->data, b->data_len); + return 1; +} + +/** \internal + * \brief Wrapper for getting payload into a lua script + * \retval cnt number of items placed on the stack + */ +static int LuaCallbackStreamingBuffer(lua_State *luastate) +{ + const LuaStreamingBuffer *b = LuaStateGetStreamingBuffer(luastate); + if (b == NULL) + return LuaCallbackError(luastate, "internal error: no buffer"); + + return LuaCallbackStreamingBufferPushToStack(luastate, b); +} + /** \internal * \brief fill lua stack with payload * \param luastate the lua state @@ -660,6 +688,9 @@ int LogLuaRegisterFunctions(lua_State *luastate) lua_pushcfunction(luastate, LuaCallbackAppLayerProtoFlow); lua_setglobal(luastate, "SCFlowAppLayerProto"); + lua_pushcfunction(luastate, LuaCallbackStreamingBuffer); + lua_setglobal(luastate, "SCStreamingBuffer"); + lua_pushcfunction(luastate, LuaCallbackLogPath); lua_setglobal(luastate, "SCLogPath"); diff --git a/src/output-lua.c b/src/output-lua.c index 40cb5190a8..d8787c272e 100644 --- a/src/output-lua.c +++ b/src/output-lua.c @@ -116,12 +116,13 @@ static int LuaStreamingLogger(ThreadVars *tv, void *thread_data, const Flow *f, SCEnter(); void *txptr = NULL; + LuaStreamingBuffer b = { data, data_len, flags }; SCLogDebug("flags %02x", flags); if (flags & OUTPUT_STREAMING_FLAG_TRANSACTION) { if (f && f->alstate) - txptr = AppLayerParserGetTx(f->proto, ALPROTO_HTTP, f->alstate, tx_id); + txptr = AppLayerParserGetTx(f->proto, f->alproto, f->alstate, tx_id); } LogLuaThreadCtx *td = (LogLuaThreadCtx *)thread_data; @@ -129,13 +130,17 @@ static int LuaStreamingLogger(ThreadVars *tv, void *thread_data, const Flow *f, SCMutexLock(&td->lua_ctx->m); LuaStateSetThreadVars(td->lua_ctx->luastate, tv); - LuaStateSetTX(td->lua_ctx->luastate, txptr); + if (flags & OUTPUT_STREAMING_FLAG_TRANSACTION) + LuaStateSetTX(td->lua_ctx->luastate, txptr); LuaStateSetFlow(td->lua_ctx->luastate, (Flow *)f, /* locked */LUA_FLOW_LOCKED_BY_PARENT); + LuaStateSetStreamingBuffer(td->lua_ctx->luastate, &b); /* prepare data to pass to script */ lua_getglobal(td->lua_ctx->luastate, "log"); lua_newtable(td->lua_ctx->luastate); - LogLuaPushTableKeyValueInt(td->lua_ctx->luastate, "tx_id", (int)(tx_id)); + + if (flags & OUTPUT_STREAMING_FLAG_TRANSACTION) + LogLuaPushTableKeyValueInt(td->lua_ctx->luastate, "tx_id", (int)(tx_id)); int retval = lua_pcall(td->lua_ctx->luastate, 1, 0, 0); if (retval != 0) { @@ -611,7 +616,10 @@ static OutputCtx *OutputLuaLogInit(ConfNode *conf) om->conf_name = script->val; om->InitSubFunc = OutputLuaLogInitSub; - if (opts.alproto == ALPROTO_HTTP) { + if (opts.alproto == ALPROTO_HTTP && opts.streaming) { + om->StreamingLogFunc = LuaStreamingLogger; + om->alproto = ALPROTO_HTTP; + } else if (opts.alproto == ALPROTO_HTTP) { om->TxLogFunc = LuaTxLogger; om->alproto = ALPROTO_HTTP; } else if (opts.packet && opts.alerts) { diff --git a/src/util-lua.c b/src/util-lua.c index 24acfa6d69..446598a570 100644 --- a/src/util-lua.c +++ b/src/util-lua.c @@ -54,6 +54,8 @@ #include #include +#include "util-lua.h" + /* key for tv (threadvars) pointer */ const char lua_ext_key_tv[] = "suricata:lua:tv:ptr"; /* key for tx pointer */ @@ -69,6 +71,8 @@ const char lua_ext_key_flow_lock_hint[] = "suricata:lua:flow:lock_hint"; const char lua_ext_key_pa[] = "suricata:lua:pkt:alert:ptr"; /* key for file pointer */ const char lua_ext_key_file[] = "suricata:lua:file:ptr"; +/* key for streaming buffer pointer */ +const char lua_ext_key_streaming_buffer[] = "suricata:lua:streaming_buffer:ptr"; /** \brief get tv pointer from the lua state */ ThreadVars *LuaStateGetThreadVars(lua_State *luastate) @@ -181,6 +185,21 @@ void LuaStateSetFile(lua_State *luastate, File *file) lua_settable(luastate, LUA_REGISTRYINDEX); } +LuaStreamingBuffer *LuaStateGetStreamingBuffer(lua_State *luastate) +{ + lua_pushlightuserdata(luastate, (void *)&lua_ext_key_streaming_buffer); + lua_gettable(luastate, LUA_REGISTRYINDEX); + void *b = lua_touserdata(luastate, -1); + return (LuaStreamingBuffer *)b; +} + +void LuaStateSetStreamingBuffer(lua_State *luastate, LuaStreamingBuffer *b) +{ + lua_pushlightuserdata(luastate, (void *)&lua_ext_key_streaming_buffer); + lua_pushlightuserdata(luastate, (void *)b); + lua_settable(luastate, LUA_REGISTRYINDEX); +} + /** \brief dump stack from lua state to screen */ void LuaPrintStack(lua_State *state) { int size = lua_gettop(state); diff --git a/src/util-lua.h b/src/util-lua.h index a43dea736d..eb7a637e35 100644 --- a/src/util-lua.h +++ b/src/util-lua.h @@ -26,6 +26,12 @@ #ifdef HAVE_LUA +typedef struct LuaStreamingBuffer_ { + const uint8_t *data; + uint32_t data_len; + uint8_t flags; +} LuaStreamingBuffer; + #define LUA_FLOW_LOCKED_BY_PARENT 0 #define LUA_FLOW_NOT_LOCKED_BY_PARENT 1 @@ -52,6 +58,8 @@ PacketAlert *LuaStateGetPacketAlert(lua_State *luastate); /** \brief get file pointer from the lua state */ File *LuaStateGetFile(lua_State *luastate); +LuaStreamingBuffer *LuaStateGetStreamingBuffer(lua_State *luastate); + /* sets */ void LuaStateSetPacket(lua_State *luastate, Packet *p); @@ -72,6 +80,8 @@ void LuaStateSetFile(lua_State *luastate, File *file); void LuaStateSetThreadVars(lua_State *luastate, ThreadVars *tv); +void LuaStateSetStreamingBuffer(lua_State *luastate, LuaStreamingBuffer *b); + void LuaPrintStack(lua_State *state); #endif /* HAVE_LUA */