]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Squashed commit of the following:
authorRuss Combs <rucombs@cisco.com>
Tue, 18 Aug 2015 14:56:52 +0000 (10:56 -0400)
committerRuss Combs <rucombs@cisco.com>
Tue, 18 Aug 2015 14:56:52 +0000 (10:56 -0400)
commit 1a1ce657531761060cc32a96106796ddcf2e9d44
Author: Joel Cornett <joel.cornett@gmail.com>
Date:   Mon Aug 17 17:53:20 2015 -0400

    added lua/dev_notes.txt
    Improved script-path & added IpApi Lua object,
    Enable multiple script-path args and let script-path specify single files
    Improved/refactored common.lua script
    Added IpApi Lua object

38 files changed:
piglet/tests/common.lua [new file with mode: 0644]
piglet/tests/instance/codec.lua
piglet/tests/instance/common.lua [deleted file]
piglet/tests/instance/inspector.lua
piglet/tests/instance/ips_action.lua
piglet/tests/instance/ips_option.lua
piglet/tests/instance/logger.lua
piglet/tests/instance/search_engine.lua
piglet/tests/instance/so_rule.lua
piglet/tests/interface/buffer.lua
piglet/tests/interface/codec_data.lua
piglet/tests/interface/common.lua [deleted file]
piglet/tests/interface/cursor.lua
piglet/tests/interface/daq_header.lua
piglet/tests/interface/decode_data.lua
piglet/tests/interface/enc_state.lua
piglet/tests/interface/event.lua
piglet/tests/interface/flow.lua
piglet/tests/interface/packet.lua
piglet/tests/interface/raw_buffer.lua
src/lua/dev_notes.txt [new file with mode: 0644]
src/main/help.cc
src/main/snort.cc
src/main/snort_config.h
src/main/snort_module.cc
src/managers/script_manager.cc
src/managers/script_manager.h
src/parser/config_file.cc
src/parser/config_file.h
src/piglet_plugins/CMakeLists.txt
src/piglet_plugins/Makefile.am
src/piglet_plugins/pp_codec_iface.cc
src/piglet_plugins/pp_decode_data_iface.cc
src/piglet_plugins/pp_inspector.cc
src/piglet_plugins/pp_ip_api_iface.cc [new file with mode: 0644]
src/piglet_plugins/pp_ip_api_iface.h [new file with mode: 0644]
src/piglet_plugins/pp_logger.cc
src/piglet_plugins/pp_test.cc

diff --git a/piglet/tests/common.lua b/piglet/tests/common.lua
new file mode 100644 (file)
index 0000000..9eba64e
--- /dev/null
@@ -0,0 +1,215 @@
+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
index d33d5a3091ae2f4062d1d53cf50c01ce55e9010e..aa0ce406e36ae856e44263eb739db480d1d0f5cd 100644 (file)
@@ -3,8 +3,8 @@ plugin =
     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
 }
 
@@ -19,12 +19,12 @@ tests =
 
     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()
diff --git a/piglet/tests/instance/common.lua b/piglet/tests/instance/common.lua
deleted file mode 100644 (file)
index 28bb724..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-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
-
index cedef29b6f1e83d2a8c38f5718294a14cca387d8..c8ee33bb27e4f271cede0d4791d76d4fb0071e41 100644 (file)
@@ -3,14 +3,14 @@ plugin =
     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
 
@@ -21,7 +21,7 @@ HEADER = [[
 DATA = "abcdefghijklmnopqrstuvwxyz"
 
 get_packet = function()
-    return get_ipv4_packet(HEADER:as_content_hex(), DATA)
+    return packet.construct_ip4(IP4:encode_hex(), DATA)
 end
 
 tests =
index 7909f65af44146c84c198a169cda4d4228a4b728..192ba125cec5293bcd2f58fe9e254a191af89e49 100644 (file)
@@ -3,8 +3,8 @@ plugin =
     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
 }
 
index a48ba5cb3e18dcd11ec93dc80551c5f9a7015588..5b944e6685a6a4e62cd2aa01da9e713156208368 100644 (file)
@@ -3,8 +3,8 @@ plugin =
     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
 }
 
index 58d2e61e239586062213bd5887c8124d7eae3ef9..177f46385f83c6199f867a033328147576a5cdc1 100644 (file)
@@ -4,15 +4,16 @@ plugin =
     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
 
@@ -22,13 +23,9 @@ HEADER = [[
 
 DATA = "abcdefghijklmnopqrstuvwxyz"
 
-get_packet = function()
-    return get_ipv4_packet(HEADER:as_content_hex(), DATA)
-end
-
 tests =
 {
-    initialize = function()
+    exists = function()
         assert(Logger)
     end,
 
@@ -37,17 +34,19 @@ tests =
     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
index ecc91d82d4cdb3d7b44aa6d612949005d714c4d4..c5968fc8c7612ab424e1f9e354156139eea6c797 100644 (file)
@@ -3,8 +3,8 @@ plugin =
     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
 }
 
index 3b2dac457ea387cc348cd4b0db837d242cacd602..de1da31cd4eee6cd30dd162008833541aab24cbf 100644 (file)
@@ -3,8 +3,8 @@ xplugin =
     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
 }
 
index b58dc47742cbc70bf97d3d562a7923dc9ccef7bf..00cfa2e99312898c433d97641838a0f2eae163ba 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
index 09cd223627a94123650df3cd4e3d7483c96b35c8..4afcf40f8b4db423a635d9942d0485e1bf45126c 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
@@ -52,8 +51,8 @@ tests =
 
     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
 }
diff --git a/piglet/tests/interface/common.lua b/piglet/tests/interface/common.lua
deleted file mode 100644 (file)
index 3b89c82..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-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
-
index ec978c4f176b91a6d414491ce5b32bfa4dfebae0..2fbd002deecee66d5ac0da861d07dd546068dfec 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
index fe64d2aed3f5aa4bedda83f3ecb6f1a09358fc0d..72b4ab9e5325c95a3a1b88cc70dc138c8bd0737b 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
@@ -42,11 +41,11 @@ tests =
     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
 }
index 7826032238dcc2d914762c06dd30c3a99e336a68..fee728fbcddb011d8b27beb36304faa6a1a7851b 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
@@ -25,16 +24,31 @@ VALUES =
     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
 }
index 54d7ef24004720f673394a375c67c16d3769898a..5f6ff2d3b1a79c6f519f05f762043a6528aebad3 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
index a04f226f026dadb506fdba6ac8ff2138904caca9..d2acdd0acfb206fcc20a6d7df93d076f2f79a14b 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
@@ -52,18 +51,18 @@ tests =
 
     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
 }
index 3ba987c952b8a557b81f7cc26877fdb6b715f974..7eacc4ba3bae82f947d34202c2b551ae2a9256b7 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
index 350a7ba6c7bdde71a991f2112f2f2c691ba4852a..ff0f62a878a18c2c83ac72b2d30063aba131725d 100644 (file)
@@ -3,9 +3,8 @@ plugin =
     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
 }
 
@@ -66,7 +65,7 @@ tests =
 
     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()
@@ -94,8 +93,8 @@ tests =
 
     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
 }
index 7cb5fe6b4f437f0a83e6ccee38d6b943a91e6284..aada788f6b9750f78381688ca561234ea754d064 100644 (file)
@@ -3,15 +3,14 @@ plugin =
     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 =
 {
@@ -24,7 +23,7 @@ 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()
@@ -74,16 +73,16 @@ tests =
         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()
@@ -102,7 +101,7 @@ tests =
         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())
@@ -117,8 +116,8 @@ tests =
         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()
diff --git a/src/lua/dev_notes.txt b/src/lua/dev_notes.txt
new file mode 100644 (file)
index 0000000..1e27681
--- /dev/null
@@ -0,0 +1,12 @@
+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
index 8613d8262bf45399603802f5faf9e5737af61963..6955dc850cf62f85770a719c0e098e170fb1efec 100644 (file)
@@ -155,7 +155,7 @@ enum HelpType
 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();
 
index 95a342bb17f40a6d8e696f71f554974a44a7d692..ee87fa6a4ca8816bea09e6dcd898e1a3320e6bf8 100644 (file)
@@ -237,7 +237,7 @@ void Snort::init(int argc, char** argv)
 #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 )
index b8d98ce544b85999fafe1ce63b4336498be3ac75..8748b23dfae5d3922a454e569a8f2d3637dd653f 100644 (file)
@@ -193,7 +193,7 @@ public:
 
     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;
 
index 030bea78365c4d3adb551016b787deba52adffa8..f321c1327157700be5330f17ee6322735ee9e31a 100644 (file)
@@ -410,7 +410,7 @@ static const Parameter s_params[] =
       "<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,
@@ -801,7 +801,7 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc)
         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") )
index b7a2216558dd95886073f0e28f0841517753c540..0920b510de99729166a32f2a982bc39f88d84467 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <string>
 #include <vector>
+#include <sys/stat.h>
 #include <luajit-2.0/lua.hpp>
 
 #include "ips_manager.h"
@@ -241,26 +242,43 @@ static void load_script(const char* f)
 // 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());
+        }
     }
 }
 
index ec0c499ddeba2d66756a47708dec568a4b32f654..11127774e25bd0a0c83d546504e653eb73e6f3d4 100644 (file)
@@ -24,6 +24,7 @@
 // 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"
@@ -33,7 +34,7 @@
 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);
index 632d14ef6a01eae527a82a3093765412b6032412..9ad3a60c513e823c3b9a8be49b5e09a0c7c0ce57 100644 (file)
@@ -571,10 +571,10 @@ void ConfigPluginPath(SnortConfig* sc, const char* args)
         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*)
index 6fa512e1d434243439510fb970db703f77eef1c1..9d73806656808a4ea7d3fa0afdb7f055edfb9902 100644 (file)
@@ -54,7 +54,7 @@ void ConfigProcessAllEvents(SnortConfig*, 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*);
index 51cf2375f97e641d683526a15b66b3701a20fc59..c39b27cd62caa874d35a513971146eb671fe51b5 100644 (file)
@@ -74,6 +74,7 @@ set (
     pp_decode_data_iface.cc
     pp_flow_iface.cc
     pp_event_iface.cc
+    pp_ip_api_iface.cc
 )
 
 set (
index e2653f2b1d6ea62ca16ab86db81462adb3e936cc..d68f525d7393b1ce304a45b58ebbb060df7ab800 100644 (file)
@@ -24,7 +24,8 @@ pp_packet_iface.cc \
 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 \
index af91e8629314f17e65045afbf1639b088cc073ab..718394bab76f43511982f11625d02526b972278a 100644 (file)
 #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
 {
@@ -164,12 +165,24 @@ static const luaL_Reg methods[] =
         {
             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);
 
@@ -177,7 +190,7 @@ static const luaL_Reg methods[] =
 
             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);
index 9392191a74bf6234c5a4af3cb3c3d4b1dc3da7f4..edde23848dfa8ec533138f80ddca6aff90c0a93a 100644 (file)
 #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
@@ -91,28 +89,22 @@ static const luaL_Reg methods[] =
         [](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
index 95fd08712ab3c75ace043fe2e7b1f92ec45fd7fd..df9a4e71f819aac506c54833be161b677e681446 100644 (file)
@@ -30,6 +30,7 @@
 
 #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"
@@ -72,6 +73,7 @@ bool InspectorPiglet::setup()
     install(L, DecodeDataIface);
     install(L, RawBufferIface);
     install(L, FlowIface);
+    install(L, IpApiIface);
     install(L, PacketIface);
     install(L, StreamSplitterIface);
 
diff --git a/src/piglet_plugins/pp_ip_api_iface.cc b/src/piglet_plugins/pp_ip_api_iface.cc
new file mode 100644 (file)
index 0000000..4b4079a
--- /dev/null
@@ -0,0 +1,119 @@
+//--------------------------------------------------------------------------
+// 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
+};
diff --git a/src/piglet_plugins/pp_ip_api_iface.h b/src/piglet_plugins/pp_ip_api_iface.h
new file mode 100644 (file)
index 0000000..5d5a449
--- /dev/null
@@ -0,0 +1,32 @@
+//--------------------------------------------------------------------------
+// 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
index 365128e4c918641ccc503e9f156c08250a03bb7f..c86369b1e5dd32d1d53557212a74aee6e7d3b32c 100644 (file)
@@ -29,6 +29,7 @@
 
 #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"
 
@@ -67,6 +68,7 @@ bool LoggerPiglet::setup()
 
     install(L, RawBufferIface);
     install(L, DecodeDataIface);
+    install(L, IpApiIface);
     install(L, PacketIface);
     install(L, EventIface);
 
index 165a2eba0a32317478e564cc24b380ca0d379efd..6fe50cd7699f9197acb5f5ff52974715da76b54f 100644 (file)
@@ -36,6 +36,7 @@
 #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"
 
@@ -59,6 +60,7 @@ bool TestPiglet::setup()
     install(L, EncStateIface);
     install(L, EventIface);
     install(L, FlowIface);
+    install(L, IpApiIface);
     install(L, PacketIface);
     install(L, RawBufferIface);