# HG changeset patch # User Matthew Wild # Date 1778501905 -3600 # Node ID 24c34968dd45e53d28e9bcf8cb8fa21924838184 # Parent 82b6a03b9dfa677f59a129af0bb7582e571b1e3b mod_firewall: Preserve original source of actions/conditions for debug purposes diff -r 82b6a03b9dfa -r 24c34968dd45 mod_firewall/mod_firewall.lua --- a/mod_firewall/mod_firewall.lua Mon May 11 13:16:18 2026 +0100 +++ b/mod_firewall/mod_firewall.lua Mon May 11 13:18:25 2026 +0100 @@ -388,7 +388,7 @@ local function new_rule(ruleset, chain, line_no) assert(chain, "no chain specified"); - local rule = { conditions = {}, actions = {}, deps = {}, line_no = line_no }; + local rule = { conditions = {}, actions = {}, deps = {}, line_no = line_no, source = { conditions = {}, actions = {} } }; table.insert(ruleset[chain], rule); return rule; end @@ -500,6 +500,7 @@ return nil, errmsg(action_string); end table.insert(rule.actions, action_string); + table.insert(rule.source.actions, line); for _, dep in ipairs(action_deps or {}) do table.insert(rule.deps, dep); end @@ -515,7 +516,9 @@ end -- Check standard modifiers for the condition (e.g. NOT) local negated; - local condition = line:match("^[^:=%.?]*"); + local raw_condition = line:match("^[^:=%.?]*"); + local condition = raw_condition; + if condition:find("%f[%w]NOT%f[^%w]") then local s, e = condition:match("%f[%w]()NOT()%f[^%w]"); condition = (condition:sub(1,s-1)..condition:sub(e+1, -1)):match("^%s*(.-)%s*$"); @@ -532,6 +535,7 @@ end if negated then condition_code = "not("..condition_code..")"; end table.insert(rule.conditions, condition_code); + table.insert(rule.source.conditions, line); for _, dep in ipairs(condition_deps or {}) do table.insert(rule.deps, dep); end @@ -616,7 +620,8 @@ table.insert(code.global_header, 1, "local "..name:lower().."s = definitions."..name..";"); end - local code_string = "return function (definitions, fire_event, log, module, pass_return)\n\t" + -- The function signature here must match what gets passed in compile_handler() + local code_string = "return function (definitions, fire_event, log, module, pass_return, source_rules)\n\t" ..table.concat(code.global_header, "\n\t") .."\n\tlocal db = require 'util.debug';\n\n\t" .."return function (event)\n\t\t" @@ -624,7 +629,7 @@ ..table.concat(code, "") .."\n\tend;\nend"; - chain_handlers[chain_name] = code_string; + chain_handlers[chain_name] = { code = code_string, rules = rules }; end return chain_handlers; @@ -639,7 +644,7 @@ -- Compile handler code into a factory that produces a valid event handler. Factory accepts -- a value to be returned on PASS -local function compile_handler(code_string, filename) +local function compile_handler(code_string, filename, source_rules) -- Prepare event handler function local chunk, err = envload(code_string, "="..filename, _G); if not chunk then @@ -653,7 +658,7 @@ return nil, "Error initializing compiled rules: "..initialized_chunk; end return function (pass_return) - return initialized_chunk(active_definitions, fire_event, logger(filename), module, pass_return); -- Returns event handler with upvalues + return initialized_chunk(active_definitions, fire_event, logger(filename), module, pass_return, source_rules); -- Returns event handler with upvalues end end @@ -693,8 +698,9 @@ -- Loop through the chains in the script, and for each chain attach the compiled code to the -- relevant events, keeping track in events_hooked so we can cleanly unload later local events_hooked = {}; - for chain, handler_code in pairs(chain_functions) do - local new_handler, err = compile_handler(handler_code, "mod_firewall::"..chain); + for chain, chain_info in pairs(chain_functions) do + local handler_code = chain_info.code; + local new_handler, err = compile_handler(handler_code, "mod_firewall:"..base_name.."::"..chain, chain_info.rules); if not new_handler then module:log("error", "Compilation error for %s: %s", script, err); errs = true; @@ -823,10 +829,11 @@ print(); end local c = 0; - for chain, handler_code in pairs(chain_functions) do + for chain_name, chain_info in pairs(chain_functions) do + local handler_code = chain_info.code; c = c + 1; - print("---- Chain "..chain:gsub("_", " ")); - local chain_func_name = "chain_"..tostring(c).."_"..chain:gsub("%p", "_"); + print("---- Chain "..chain_name:gsub("_", " ")); + local chain_func_name = "chain_"..tostring(c).."_"..chain_name:gsub("%p", "_"); if not verbose then print(("%s = %s;"):format(chain_func_name, handler_code:sub(8))); else @@ -834,16 +841,16 @@ print(("local %s = (%s)(active_definitions, fire_event, logger(%q));"):format(chain_func_name, handler_code:sub(8), filename)); print(); - local chain_definition = chains[chain]; + local chain_definition = chains[chain_name]; if chain_definition and chain_definition.type == "event" then for _, event_name in ipairs(chain_definition) do print(("module:hook(%q, %s, %d);"):format(event_name, chain_func_name, chain_definition.priority or 0)); end end - print(("module:hook(%q, %s, %d);"):format("firewall/chains/"..chain, chain_func_name, chain_definition.priority or 0)); + print(("module:hook(%q, %s, %d);"):format("firewall/chains/"..chain_name, chain_func_name, chain_definition.priority or 0)); end - print("---- End of chain "..chain); + print("---- End of chain "..chain_name); print(); end print("end -- End of file "..filename);