--- /dev/null
+do
+ local table = table
+ local meta = { __index = table}
+
+ -- give tables metatable access to the table library
+ function table.new(t)
+ t = t or { }
+ setmetatable(t, meta)
+ return t
+ end
+
+ function table:imap(fn)
+ local iter, a, s = ipairs(self)
+ local closure = function(...)
+ local i, v = iter(...)
+ return i, fn(v)
+ end
+
+ return closure, self, 0
+ end
+
+ function table:ifilter(fn)
+ local iter, a, s = ipairs(self)
+ local closure = function(...)
+ local i, v = iter(...)
+ while i ~= nil and not fn(v) do
+ i, v = iter(a, i)
+ end
+
+ return i, v
+ end
+
+ return closure, self, 0
+ end
+
+ function table:vomit(depth, seen, out)
+ depth = depth or 0
+
+ -- maintain a list of dumped tables to
+ -- avoid infinite loops
+ seen = seen or { }
+ out = out or { }
+
+ local indent = strint.rep(" ", level)
+
+ for n, v in pairs(self) do
+ if type(v) == "table" and not seen[v] then
+ seen[v] = true
+ table.insert(out, string.format("%s%s =", indent, tostring(n)))
+ self.vomit(v, depth + 1, seen, out)
+ else
+ table.insert(out, string.format("%s%s = %s", indent, tostring(n), tostring(v)))
+ end
+ end
+
+ return table.concat(out, "\n")
+ end
+
+ function meta:__tostring()
+ if DEBUG then
+ return self:vomit()
+ else
+ return table.__tostring(self)
+ end
+ end
+end
+
+-- string library extensions
+do
+ function string:encode_hex()
+ local out = table.new()
+
+ for tok in self:gmatch("%f[%x](%x%x)") do
+ if tok:gmatch("^%x+$") then
+ out:insert(string.char(tonumber(tok, 16)))
+ end
+ end
+
+ return out:concat("")
+ end
+
+ function string:decode_printable()
+ local out = table.new()
+
+ for tok in self:gmatch(".") do
+ if tok:match("%g") then
+ out:insert(tok)
+ else
+ out:insert(".")
+ end
+ end
+
+ return out:concat("")
+ end
+
+ function string:decode_hex()
+ local out = table.new()
+
+ for tok in self:gmatch(".") do
+ out:insert(string.format("%02x", string.byte(tok)))
+ end
+
+ return out:concat(" ")
+ end
+end
+
+-- Assertions library
+check = { }
+do
+ function raise(title, msg, lvl)
+ lvl = lvl or 3
+ local info = debug.getinfo(lvl)
+ error(
+ string.format(
+ "%s:%d: %s: %s",
+ info.short_src,
+ info.currentline,
+ title,
+ msg
+ )
+ )
+ end
+
+ function check.tables_equal(exp, act)
+ if exp == act then return end
+
+ for n, e in pairs(exp) do
+ local a = act[n]
+ if a ~= e then
+ raise(
+ "tables unequal",
+ string.format(
+ "item with key %s differs (%s ~= %s)",
+ tostring(n),
+ tostring(e),
+ tostring(a)
+ )
+ )
+ end
+ end
+ end
+
+ function check.arrays_equal(exp, act)
+ if exp == act then return end
+ if #exp ~= #act then
+ raise(
+ "arrays unequal",
+ string.format(
+ "lengths differ (#%d ~= #%d)",
+ #exp, #act
+ )
+ )
+ end
+
+ for i, e in ipairs(exp) do
+ local a = act[i]
+ if e ~= a then
+ raise(
+ "arrays unequal",
+ string.format(
+ "item at index %d differs (%s ~= %s)",
+ i, tostring(e), tostring(a)
+ )
+ )
+ end
+ end
+ end
+
+ function check.raises(fn, msg)
+ local ok, err = pcall(fn)
+ if ok then
+ raise("did not throw", msg or "")
+ end
+ end
+
+ function check.check(expr, msg)
+ if not expr then
+ raise("assertion failed", msg or "")
+ end
+ end
+end
+
+-- Test runner
+function run_tests(tests)
+ local failed = false
+
+ for name, fn in pairs(tests) do
+ ok, err = pcall(fn)
+ if not ok then
+ print("--", name, err)
+ failed = true
+ end
+ end
+
+ return not failed
+end
+
+-- Misc utils
+packet = { }
+do
+ function packet.construct_ip4(hdr, data)
+ local rb = RawBuffer.new(hdr .. data)
+ local dd = DecodeData.new()
+ local p = Packet.new(rb)
+
+ local ip_api = dd:get_ip_api()
+ ip_api:set_ip4(rb)
+
+ p:set_data(#hdr, #data)
+ p:set { proto_bits = 4 }
+ p:set_decode_data(dd)
+
+ return p
+ end
+end
type = "piglet",
name = "codec::ipv4",
test = function()
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
get_data_link_type = function()
local rv = Codec.get_data_link_type()
- assert_list_eq("data_link_types", DATA_LINK_TYPES, rv)
+ check.arrays_equal(DATA_LINK_TYPES, rv)
end,
get_protocol_ids = function()
local rv = Codec.get_protocol_ids()
- assert_list_eq("data_link_types", PROTOCOL_IDS, rv)
+ check.arrays_equal(PROTOCOL_IDS, rv)
end,
decode = function()
+++ /dev/null
-run_all = function(tests)
- local failed = false
-
- for name, fn in pairs(tests) do
- ok, msg = pcall(fn)
- if not ok then
- print("--", name, msg)
- failed = true
- end
- end
-
- if failed then
- return false
- end
-
- return true
-end
-
-assert_table_eq = function(name, expected, actual)
- for n, exp in pairs(expected) do
- local a = actual[n]
- assert(
- exp == a,
- name .. "." .. n .. ": " .. tostring(exp) .. " != " .. tostring(a)
- )
- end
-end
-
-assert_list_eq = function(name, expected, actual)
- assert(#expected == #actual, "sizes differ")
- for i, exp in ipairs(expected) do
- local a = actual[i]
- assert(
- exp == a,
- name .. "[" .. tostring(i) .. "]" .. " != " .. tostring(a)
- )
- end
-end
-
-assert_err = function(fn, msg)
- local e, m = pcall(fn)
- assert(not e, "failed to raise an error")
-
- local m_s = tostring(m)
- assert(m_s:match(msg), "error message '" .. tostring(m) .. "' ! '" .. msg .. "'")
-end
-
-get_ipv4_packet = function(hdr, data)
- local rb = RawBuffer.new(hdr .. data)
- local dd = DecodeData.new()
- local p = Packet.new(rb)
-
- dd:set_ipv4_hdr(rb)
-
- p:set_data(#hdr, #data)
- p:set({ proto_bits = 4 })
- p:set_decode_data(dd)
-
- return p, rb
-end
-
-string.as_content_hex = function(str)
- local vals = {}
- for tok in str:gmatch("(%x+)%s*") do
- table.insert(vals, string.char(tonumber(tok, 16)))
- end
-
- return table.concat(vals, "")
-end
-
-string.dump_hex = function(str)
- local vals = {}
- for tok in str:gmatch(".") do
- table.insert(vals, string.format("%x", tok:byte()))
- end
-
- return table.concat(vals, "")
-end
-
-string.dump_human = function(str)
- local vals = {}
- for tok in str:gmatch(".") do
- if tok:match("%g") then
- table.insert(vals, tok)
- else
- table.insert(vals, ".")
- end
- end
-
- return table.concat(vals, "")
-end
-
type = "piglet",
name = "inspector::telnet",
test = function()
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end,
-- FIXIT-L: Need this to keep Inspector.configure() happy
use_defaults = true
}
-HEADER = [[
+IP4 = [[
45 | 00 | 00 46 | 00 00 | 00 00 | 01 | 06
00 00 | 00 00 00 01 | 00 00 00 02
DATA = "abcdefghijklmnopqrstuvwxyz"
get_packet = function()
- return get_ipv4_packet(HEADER:as_content_hex(), DATA)
+ return packet.construct_ip4(IP4:encode_hex(), DATA)
end
tests =
type = "piglet",
name = "ips_action::react",
test = function()
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "ips_option::content",
test = function()
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
name = "logger::alert_csv",
use_defaults = true,
test = function()
+ dofile(SCRIPT_DIR .. "/../common.lua")
+
Logger.open()
- dofile(SCRIPT_DIR .. "/common.lua")
- local rv = run_all(tests)
+ local rv = run_tests(tests)
Logger.close()
return rv
end
}
-HEADER = [[
+IP4 = [[
45 | 00 | 00 46 | 00 00 | 00 00 | 01 | 06
00 00 | 00 00 00 01 | 00 00 00 02
DATA = "abcdefghijklmnopqrstuvwxyz"
-get_packet = function()
- return get_ipv4_packet(HEADER:as_content_hex(), DATA)
-end
-
tests =
{
- initialize = function()
+ exists = function()
assert(Logger)
end,
end,
alert = function()
- local p, rb = get_packet()
+ local p = packet.construct_ip4(IP4:encode_hex(), DATA)
local e = Event.new()
- e:set({ generator = 135, id = 2 })
+
+ e:set { generator = 135, id = 2 }
Logger.alert(p, "foo", e)
end,
log = function()
- local p, rb = get_packet()
+ local p = packet.construct_ip4(IP4:encode_hex(), DATA)
local e = Event.new()
- e:set({ generator = 135, id = 2 })
+
+ e:set { generator = 135, id = 2 }
Logger.log(p, "foo", e)
end
type = "piglet",
name = "search_engine::ac_full",
test = function()
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "so_rule::need_rule",
test = function()
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "piglet::buffer",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "piglet::codec_data",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
initialize_with_table = function()
local cd = CodecData.new()
- assert_table_eq("get()", DEFAULT_VALUES, cd:get())
+ check.tables_equal(DEFAULT_VALUES, cd:get())
cd:set(VALUES)
- assert_table_eq("set()", VALUES, cd:get())
+ check.tables_equal(VALUES, cd:get())
end
}
+++ /dev/null
-run_all = function(tests)
- local failed = false
-
- for name, fn in pairs(tests) do
- ok, msg = pcall(fn)
- if not ok then
- print("--", name, msg)
- failed = true
- end
- end
-
- if failed then
- return false
- end
-
- return true
-end
-
-assert_table_eq = function(name, expected, actual)
- for n, exp in pairs(expected) do
- local a = actual[n]
- assert(
- exp == a,
- name .. "." .. n .. ": " .. tostring(exp) .. " != " .. tostring(a)
- )
- end
-end
-
-assert_list_eq = function(name, expected, actual)
- assert(#expected == #actual, "sizes differ")
- for i, exp in ipairs(expected) do
- local a = actual[i]
- assert(
- exp == a,
- name .. "[" .. tostring(i) .. "]" .. " != " .. tostring(a)
- )
- end
-end
-
-assert_err = function(fn, msg)
- local e, m = pcall(fn)
- assert(not e, "failed to raise an error")
-
- local m_s = tostring(m)
- assert(m_s:match(msg), "error message '" .. tostring(m) .. "' ! '" .. msg .. "'")
-end
-
-string.as_content_hex = function(str)
- local vals = {}
- for tok in str:gmatch("(%x+)%s*") do
- table.insert(vals, string.char(tonumber(tok, 16)))
- end
-
- return table.concat(vals, "")
-end
-
-string.dump_hex = function(str)
- local vals = {}
- for tok in str:gmatch(".") do
- table.insert(vals, string.format("%x", tok:byte()))
- end
-
- return table.concat(vals, "")
-end
-
-string.dump_human = function(str)
- local vals = {}
- for tok in str:gmatch(".") do
- if tok:match("%g") then
- table.insert(vals, tok)
- else
- table.insert(vals, ".")
- end
- end
-
- return table.concat(vals, "")
-end
-
type = "piglet",
name = "piglet::cursor",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "piglet::daq_header",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
initialize_default = function()
local daq = DAQHeader.new()
assert(daq)
- assert("default", DEFAULT_VALUES, daq:get())
+ check.tables_equal(DEFAULT_VALUES, daq:get())
end,
initialize_with_table = function()
local daq = DAQHeader.new(VALUES)
- assert_table_eq("init", VALUES, daq:get())
+ check.tables_equal(VALUES, daq:get())
end
}
type = "piglet",
name = "piglet::decode_data",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = 4
}
+IP4 = [[
+45 | 00 | 00 46 | 00 00 | 00 00 | 01 | 06
+00 00 | 00 00 00 01 | 00 00 00 02
+
+00 00 | 00 00 | 00 00 00 00 | 00 00 00 00 | 06 02
+00 00 ff ff | 00 00 | 00 00 | 00 00
+]]
+
tests =
{
initialize_default = function()
local dd = DecodeData.new()
assert(dd)
- assert("default", DEFAULT_VALUES, dd:get())
+ check.tables_equal(DEFAULT_VALUES, dd:get())
end,
initialize_with_table = function()
local dd = DecodeData.new(VALUES)
- assert_table_eq("init", VALUES, dd:get())
+ check.tables_equal(VALUES, dd:get())
+ end,
+
+ ip_api = function()
+ local dd = DecodeData.new(VALUES)
+ local ip = dd:get_ip_api()
+ local raw = IP4:encode_hex()
+ ip:set_ip4(raw)
end
}
type = "piglet",
name = "piglet::enc_state",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "piglet::event",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
init_with_table = function()
local event = Event.new(VALUES)
- assert_table_eq("get()", VALUES, event:get())
+ check.tables_equal(VALUES, event:get())
end,
get_and_set = function()
local event = Event.new()
- assert_table_eq("get()", DEFAULT_VALUES, event:get())
- assert_table_eq("get().sig_info", DEFAULT_SIGINFO_VALUES, event:get().sig_info)
+ check.tables_equal(DEFAULT_VALUES, event:get())
+ check.tables_equal(DEFAULT_SIGINFO_VALUES, event:get().sig_info)
event:set(VALUES)
event:set({ sig_info = SIGINFO_VALUES })
- assert_table_eq("set()", VALUES, event:get())
- assert_table_eq("get().sig_info", SIGINFO_VALUES, event:get().sig_info)
+ check.tables_equal(VALUES, event:get())
+ check.tables_equal(SIGINFO_VALUES, event:get().sig_info)
end
}
type = "piglet",
name = "piglet::flow",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
type = "piglet",
name = "piglet::packet",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
init_with_table = function()
local p = Packet.new(VALUES)
- assert_table_eq("get()", VALUES, p:get())
+ check.tables_equal(VALUES, p:get())
end,
init_with_everything = function()
get_and_set = function()
local p = Packet.new()
- assert_table_eq("get()", DEFAULT_VALUES, p:get())
+ check.tables_equal(DEFAULT_VALUES, p:get())
p:set(VALUES)
- assert_table_eq("set()", VALUES, p:get())
+ check.tables_equal(VALUES, p:get())
end
}
type = "piglet",
name = "piglet::raw_buffer",
test = function()
- -- Put the dofile here so that it doesn't get loaded twice
- dofile(SCRIPT_DIR .. "/common.lua")
- return run_all(tests)
+ dofile(SCRIPT_DIR .. "/../common.lua")
+ return run_tests(tests)
end
}
INIT_SIZE = 16
INIT_STRING = "foobar"
-INIT_16_CONTENT = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"
+INIT_16_CONTENT = string.rep("00 ", 16)
tests =
{
initialize_with_size = function()
local rb = RawBuffer.new(INIT_SIZE)
assert(rb:size() == INIT_SIZE)
- assert(rb:read() == INIT_16_CONTENT:as_content_hex())
+ assert(rb:read() == INIT_16_CONTENT:encode_hex())
end,
initialize_with_string = function()
assert(#rv == 0, "length should equal 0, not " .. tostring(rv))
-- read oor with 1 arg (-1, 10)
- assert_err(function() rb:read(-1) end, "bad argument")
- assert_err(function() rb:read(2) end, "bad argument")
+ check.raises(function() rb:read(-1) end)
+ check.raises(function() rb:read(2) end)
-- read with 2 args
rv = rb:read(0, 0)
assert(#rv == 0, "length should equal 0, not " .. tostring(rv))
-- read oor with 2 args
- assert_err(function() rb:read(-1, 0) end, "bad argument")
- assert_err(function() rb:read(0, 2) end, "bad argument")
+ check.raises(function() rb:read(-1, 0) end)
+ check.raises(function() rb:read(0, 2) end)
end,
read_nonempty = function()
assert(rv == "fo")
-- read oob with 1 arg
- assert_err(function() rb:read(10) end, "bad argument")
+ check.raises(function() rb:read(10) end)
-- read with 2 args (full string), offset, length
rv = rb:read(0, rb:size())
assert(rv == "ooba")
-- read oob with 2 args (offset/length)
- assert_err(function() rb:read(-1, rb:size()) end, "bad argument")
- assert_err(function() rb:read(0, rb:size() + 1) end, "bad argument")
+ check.raises(function() rb:read(-1, rb:size()) end)
+ check.raises(function() rb:read(0, rb:size() + 1) end)
end,
resize = function()
--- /dev/null
+Templates and helpers for interfacing with luajit virtual machines are here:
+
+* *State* is a RAII wrapper to the lua_State* pointer
+* *ManageStack* prevents the stack from growing too large and ensures that
+ the stack has enough room.
+* *Args* provides type checking access to the lua stack from within an
+ embedded C/C\++ function
+* *lua_iface.h* contains wrappers for exposing C\++ objects to lua
+* *lua_ref.h* provides a very basic reference tracking system to prevent
+ Lua from garbage collecting objects that may be in use but are otherwise
+ untracked in the lua vm.
+* *lua_stack.h* provides templated functions to interface with the stack
static void show_help(SnortConfig* sc, const char* val, HelpType ht)
{
snort_conf = new SnortConfig;
- ScriptManager::load_scripts(sc->script_path);
+ ScriptManager::load_scripts(sc->script_paths);
PluginManager::load_plugins(sc->plugin_path);
ModuleManager::init();
#endif
ModuleManager::init();
- ScriptManager::load_scripts(snort_cmd_line_conf->script_path);
+ ScriptManager::load_scripts(snort_cmd_line_conf->script_paths);
PluginManager::load_plugins(snort_cmd_line_conf->plugin_path);
if ( snort_conf->logging_flags & LOGGING_FLAG__SHOW_PLUGINS )
std::string chroot_dir; /* -t or config chroot */
std::string plugin_path;
- std::string script_path;
+ std::vector<std::string> script_paths;
mode_t file_mask = 0;
"<pfx> prepend this to each output file" },
{ "--script-path", Parameter::PT_STRING, nullptr, nullptr,
- "<path> where to find luajit scripts" },
+ "<path> to a luajit script or directory containing luajit scripts" },
#ifdef BUILD_SHELL
{ "--shell", Parameter::PT_IMPLIED, nullptr, nullptr,
sc->run_prefix = v.get_string();
else if ( v.is("--script-path") )
- ConfigScriptPath(sc, v.get_string());
+ ConfigScriptPaths(sc, v.get_string());
#ifdef BUILD_SHELL
else if ( v.is("--shell") )
#include <string>
#include <vector>
+#include <sys/stat.h>
#include <luajit-2.0/lua.hpp>
#include "ips_manager.h"
// public methods
//-------------------------------------------------------------------------
-void ScriptManager::load_scripts(const std::string& paths)
+void ScriptManager::load_scripts(const std::vector<std::string>& paths)
{
+ struct stat s;
+
if ( paths.empty() )
return;
- const char* t = paths.c_str();
- vector<char> buf(t, t+strlen(t)+1);
- char* last, * s;
+ for ( auto path : paths )
+ {
+ size_t pos = path.find_first_not_of(":");
- s = strtok_r(&buf[0], ":", &last);
+ while ( pos != std::string::npos )
+ {
+ size_t end_pos = path.find_first_of(":", pos);
- while ( s )
- {
- Directory d(s);
- const char* f;
+ std::string d = path.substr(
+ pos, (end_pos == std::string::npos) ? end_pos : end_pos - pos);
+
+ pos = ( end_pos == std::string::npos ) ? end_pos : end_pos + 1;
+
+ if ( d.empty() )
+ continue;
+
+ if ( stat(d.c_str(), &s) )
+ continue;
- while ( (f = d.next(script_ext)) )
- load_script(f);
+ if ( s.st_mode & S_IFDIR )
+ {
+ Directory dir(d.c_str());
+ const char* f;
+ while ( (f = dir.next(script_ext)) )
+ load_script(f);
+ }
- s = strtok_r(nullptr, ":", &last);
+ else
+ load_script(d.c_str());
+ }
}
}
// in Lua. Runtime use is via the actual plugin type manager.
#include <string>
+#include <vector>
#include "main/snort_types.h"
#include "framework/base_api.h"
class ScriptManager
{
public:
- static void load_scripts(const std::string& paths);
+ static void load_scripts(const std::vector<std::string>& paths);
static void release_scripts();
static const BaseApi** get_plugins();
static std::string* get_chunk(const char* key);
sc->plugin_path = args;
}
-void ConfigScriptPath(SnortConfig* sc, const char* args)
+void ConfigScriptPaths(SnortConfig* sc, const char* args)
{
if ( sc && args )
- sc->script_path = args;
+ sc->script_paths.push_back(args);
}
void config_syslog(SnortConfig* sc, const char*)
void ConfigUtc(SnortConfig*, const char*);
void ConfigVerbose(SnortConfig*, const char*);
void ConfigPluginPath(SnortConfig*, const char*);
-void ConfigScriptPath(SnortConfig*, const char*);
+void ConfigScriptPaths(SnortConfig*, const char*);
void ConfigDstMac(SnortConfig*, const char*);
void ConfigSetGid(SnortConfig*, const char*);
pp_decode_data_iface.cc
pp_flow_iface.cc
pp_event_iface.cc
+ pp_ip_api_iface.cc
)
set (
pp_decode_data_iface.cc \
pp_flow_iface.cc \
pp_event_iface.cc \
-pp_daq_pkthdr_iface.cc
+pp_daq_pkthdr_iface.cc \
+pp_ip_api_iface.cc
plugin_list = \
pp_codec.cc \
#include "pp_daq_pkthdr_iface.h"
#include "pp_decode_data_iface.h"
#include "pp_enc_state_iface.h"
+#include "pp_ip_api_iface.h"
#include "pp_raw_buffer_iface.h"
-// FIXIT-M: This should be its own object
-static const ip::IpApi ip_api {};
+// FIXIT-M delete this, and make the IpApi arg in codec.update required
+static const ip::IpApi default_ip_api {};
struct TextLogWrapper
{
{
Lua::Args args(L);
- uint32_t flags_hi = args[1].check_size();
- uint32_t flags_lo = args[2].check_size();
- auto& rb = RawBufferIface.get(L, 3);
+ // FIXIT-M this hacky arg offset stuff is for backwards compatibilty
+ // it will be removed in later updates
+
+ int off = 0;
+ const auto* ip_api = &default_ip_api;
+
+ if ( IpApiIface.is(L, 1) )
+ {
+ ip_api = &IpApiIface.get(L, 1);
+ off++;
+ }
+
+ uint32_t flags_hi = args[off + 1].check_size();
+ uint32_t flags_lo = args[off + 2].check_size();
+ auto& rb = RawBufferIface.get(L, off + 3);
// FIXIT-L: Args vs Iface is not orthogonal
- uint16_t lyr_len = args[4].opt_size(0, rb.size());
+ uint16_t lyr_len = args[off + 4].opt_size(0, rb.size());
auto& self = CodecIface.get(L);
uint64_t flags = (static_cast<uint64_t>(flags_hi) << 8) | flags_lo;
- self.update(ip_api, flags, get_mutable_data(rb), lyr_len,
+ self.update(*ip_api, flags, get_mutable_data(rb), lyr_len,
updated_len);
lua_pushinteger(L, updated_len);
#include "lua/lua_arg.h"
#include "lua/lua_table.h"
#include "protocols/ipv4.h"
-// #include "protocols/tcp.h"
-// #include "protocols/udp.h"
-// #include "protocols/icmp4.h"
+#include "pp_ip_api_iface.h"
#include "pp_raw_buffer_iface.h"
// FIXIT-H: Add Internet Header objects
[](lua_State* L)
{ return DecodeDataIface.default_getter(L, get_fields); }
},
- // FIXIT-L: Need a more sophisticated interface to decode data ip_api
{
- "set_ipv4_hdr",
+ // Return a reference to the IpApi attached to DecodeData
+ "get_ip_api",
[](lua_State* L)
{
Lua::Args args(L);
auto& self = DecodeDataIface.get(L, 1);
- auto& rb = RawBufferIface.get(L, 2);
- size_t offset = args[3].opt_size(0, rb.size());
- // Need enough room for an IPv4 header
- if ( (rb.size() - offset) < sizeof(IP4Hdr) )
- luaL_error(
- L, "need %d bytes, got %d",
- sizeof(IP4Hdr), rb.size()
- );
+ auto** ip_api = IpApiIface.allocate(L);
+ *ip_api = &self.ip_api;
- self.ip_api.set(
- reinterpret_cast<const IP4Hdr*>(rb.data() + offset));
+ // Make sure the decode data doesn't run out from under the ref
+ Lua::add_ref(L, *ip_api, "decode_data", lua_gettop(L));
- return 0;
+ return 1;
}
},
// FIXIT-L: add access to mplsHdr field
#include "pp_decode_data_iface.h"
#include "pp_flow_iface.h"
+#include "pp_ip_api_iface.h"
#include "pp_packet_iface.h"
#include "pp_raw_buffer_iface.h"
#include "pp_stream_splitter_iface.h"
install(L, DecodeDataIface);
install(L, RawBufferIface);
install(L, FlowIface);
+ install(L, IpApiIface);
install(L, PacketIface);
install(L, StreamSplitterIface);
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// pp_ip_api_iface.cc author Joel Cornett <jocornet@cisco.com>
+
+#include "pp_ip_api_iface.h"
+
+#include <assert.h>
+#include <luajit-2.0/lua.hpp>
+
+#include "lua/lua_arg.h"
+#include "protocols/ip.h"
+#include "protocols/ipv4.h"
+#include "protocols/ipv6.h"
+
+#include "pp_raw_buffer_iface.h"
+
+template<typename Header>
+static void set_header(lua_State* L, ip::IpApi& ip_api, RawBuffer& rb)
+{
+ if ( rb.size() < sizeof(Header) )
+ luaL_error(L,
+ "buffer is to small to be cast to header, (need %d, got %d)",
+ sizeof(Header), rb.size()
+ );
+
+ else
+ {
+ const auto* hdr = reinterpret_cast<const Header*>(rb.data());
+ ip_api.set(hdr);
+ }
+}
+
+template<typename Header>
+static int set(lua_State* L)
+{
+ Lua::Args args(L);
+ auto & self = IpApiIface.get(L, 1);
+
+ RawBuffer* rb;
+ int ref_index = 2;
+
+ if ( RawBufferIface.is(L, 2) )
+ rb = &RawBufferIface.get(L, 2);
+
+ else
+ {
+ size_t len = 0;
+ const char* data = args[2].check_string(len);
+ rb = &RawBufferIface.create(L, data, len);
+ ref_index = lua_gettop(L);
+ }
+
+ set_header<Header>(L, self, *rb);
+
+ Lua::add_ref(L, &self, "iph", ref_index);
+
+ return 0;
+}
+
+static const luaL_Reg methods[] =
+{
+ {
+ "set_ip4",
+ [](lua_State* L)
+ { return set<IP4Hdr>(L); }
+ },
+ {
+ "set_ip6",
+ [](lua_State* L)
+ { return set<ip::IP6Hdr>(L); }
+ },
+ {
+ "reset",
+ [](lua_State* L)
+ { IpApiIface.get(L).reset(); return 0; }
+ },
+ { nullptr, nullptr }
+};
+
+static const luaL_Reg metamethods[] =
+{
+ {
+ "__tostring",
+ [](lua_State* L)
+ { return IpApiIface.default_tostring(L); }
+ },
+ {
+ "__gc",
+ [](lua_State* L)
+ {
+ auto& self = IpApiIface.get(L);
+ Lua::remove_refs(L, static_cast<void*>(&self));
+ return 0;
+ }
+ },
+ { nullptr, nullptr }
+};
+
+const struct Lua::TypeInterface<ip::IpApi> IpApiIface =
+{
+ "IpApi",
+ methods,
+ metamethods
+};
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2015-2015 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// pp_ip_api_iface.h author Joel Cornett <jocornet@cisco.com>
+
+#ifndef PP_IP_API_IFACE_H
+#define PP_IP_API_IFACE_H
+
+#include "lua/lua_iface.h"
+
+namespace ip
+{
+class IpApi;
+}
+
+extern const struct Lua::TypeInterface<ip::IpApi> IpApiIface;
+
+#endif
#include "pp_decode_data_iface.h"
#include "pp_event_iface.h"
+#include "pp_ip_api_iface.h"
#include "pp_packet_iface.h"
#include "pp_raw_buffer_iface.h"
install(L, RawBufferIface);
install(L, DecodeDataIface);
+ install(L, IpApiIface);
install(L, PacketIface);
install(L, EventIface);
#include "pp_enc_state_iface.h"
#include "pp_event_iface.h"
#include "pp_flow_iface.h"
+#include "pp_ip_api_iface.h"
#include "pp_packet_iface.h"
#include "pp_raw_buffer_iface.h"
install(L, EncStateIface);
install(L, EventIface);
install(L, FlowIface);
+ install(L, IpApiIface);
install(L, PacketIface);
install(L, RawBufferIface);