summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2008-11-07 15:01:13 +0000
committerTed Trask <ttrask01@yahoo.com>2008-11-07 15:01:13 +0000
commitd37e751caf7d9bf9e33a2837d38e2263c4f370f4 (patch)
tree72481f92e5444f4e4d3964e6906500c1201b789c
parentfc670b19af9f6dd4027dcec0fc6cc0035860f9e2 (diff)
downloadacf-iptables-d37e751caf7d9bf9e33a2837d38e2263c4f370f4.tar.bz2
acf-iptables-d37e751caf7d9bf9e33a2837d38e2263c4f370f4.tar.xz
Implemented iptables edit/create/delete rule. Doesn't support all parameters yet. Modified list rules to include more info.
git-svn-id: svn://svn.alpinelinux.org/acf/iptables/trunk@1581 ab2d0c66-481e-0410-8bed-d214d4d58bed
-rw-r--r--iptables-details-html.lsp4
-rw-r--r--iptables-editrule-html.lsp17
-rw-r--r--iptables-html.lsp12
-rw-r--r--iptables-model.lua206
4 files changed, 223 insertions, 16 deletions
diff --git a/iptables-details-html.lsp b/iptables-details-html.lsp
index bbdbd9a..9edc25d 100644
--- a/iptables-details-html.lsp
+++ b/iptables-details-html.lsp
@@ -14,8 +14,8 @@ io.write("</span>")
<% for i,tab in ipairs({"filter", "nat", "mangle"}) do %>
<H3><%= tab %></H3>
<TABLE>
- <TR><%= data.value[tab].chains %> Chains</TR>
- <TR><%= data.value[tab].rules %> Rules</TR>
+ <TR><TD><%= data.value[tab].chains %> Chains</TD></TR>
+ <TR><TD><%= data.value[tab].rules %> Rules</TD></TR>
</TABLE>
<% end %>
</DL>
diff --git a/iptables-editrule-html.lsp b/iptables-editrule-html.lsp
index 7a7ad3c..8960191 100644
--- a/iptables-editrule-html.lsp
+++ b/iptables-editrule-html.lsp
@@ -21,15 +21,24 @@ displayformitem(form.value.position)
%>
</DL><H2>Basic Parameters</H2><DL>
<%
+displayformitem(form.value.jump)
displayformitem(form.value.protocol)
+displayformitem(form.value.in_interface)
+displayformitem(form.value.out_interface)
displayformitem(form.value.source)
displayformitem(form.value.destination)
-displayformitem(form.value.jump)
+%>
+</DL><DL id="details">
+<%
displayformitem(form.value.goto)
-displayformitem(form.value.in_interface)
-displayformitem(form.value.out_interface)
displayformitem(form.value.fragment)
displayformitem(form.value.set_counters)
%>
-</DL><H2>Save</H2>
+</DL><H2>Extended Parameters</H2><DL>
+<%
+displayformitem(form.value.comment)
+displayformitem(form.value.addrtype_src_type)
+displayformitem(form.value.addrtype_dst_type)
+%>
+</DL><H2><%= form.option %></H2>
<% displayformend(form) %>
diff --git a/iptables-html.lsp b/iptables-html.lsp
index d9600e1..b27216b 100644
--- a/iptables-html.lsp
+++ b/iptables-html.lsp
@@ -19,16 +19,22 @@
<% if chain.references then io.write(" ("..chain.references.." references)\n") end %>
</TD></TR>
<% for j,line in ipairs(chain) do %>
- <TR><TD STYLE='padding-left:40px'>
+ <TABLE>
+ <TR><TD WIDTH='80px' STYLE='padding-left:40px'>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/createrule?table="..tab.."&chain="..chain.name.."&position="..j.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-add.png' width='16' height='16' title="Insert Rule"></a>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/deleterule?table="..tab.."&chain="..chain.name.."&position="..j.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-remove.png' width='16' height='16' title="Delete Rule"></a>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/editrule?table="..tab.."&chain="..chain.name.."&position="..j.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/document-properties.png' width='16' height='16' title="Edit Rule"></a>
- </TD><TD><%= line %></TD>
+ </TD>
+ <TD WIDTH='50px'><%= line.packets %></TD><TD WIDTH='50px'><%= line.bytes %></TD>
+ <TD><%= line.rule %></TD>
</TR>
+ </TABLE>
<% end %>
- <TR><TD STYLE='padding-left:40px'>
+ <TABLE>
+ <TR><TD WIDTH='80px' STYLE='padding-left:40px'>
<a href="<%= page_info.script..page_info.prefix..page_info.controller.."/createrule?table="..tab.."&chain="..chain.name.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-add.png' width='16' height='16' title="Append Rule"></a>
</TD></TR>
+ </TABLE>
<% end %>
<TR><TD><a href="<%= page_info.script..page_info.prefix..page_info.controller.."/createchain?table="..tab.."&redir="..page_info.orig_action %>"><IMG SRC='/skins/static/tango/16x16/actions/list-add.png' width='16' height='16' title="Create Chain"></a></TD></TR>
</TABLE>
diff --git a/iptables-model.lua b/iptables-model.lua
index 3f55965..84e6687 100644
--- a/iptables-model.lua
+++ b/iptables-model.lua
@@ -4,6 +4,7 @@ module(..., package.seeall)
require("modelfunctions")
require("fs")
require("format")
+require("validator")
-- Set variables
local packagename = "iptables"
@@ -20,7 +21,7 @@ local details
local getdetails = function()
if not details then
details = {}
- local cmd = path .. "iptables -t filter -n -L"
+ local cmd = path .. "iptables -t filter -n -L -v"
for i,tab in ipairs(tables) do
local f = io.popen( (string.gsub(cmd, "filter", tab)) )
details[tab] = {table=tab}
@@ -32,8 +33,11 @@ local getdetails = function()
local policy = string.match(line, "policy (%w+)")
local references = string.match(line, "(%d+) references")
table.insert(details[tab], {name=name, policy=policy, references=references})
- elseif not string.match(line, "^target%s+prot") then
- table.insert(details[tab][#details[tab]], line)
+ elseif not string.match(line, "target%s+prot") then
+ local block = {}
+ block.packets, block.bytes, block.rule = string.match(line, "^%s*(%S+)%s+(%S+)%s+(.*)$")
+ table.insert(details[tab][#details[tab]], block)
+ --table.insert(details[tab][#details[tab]], line)
elseif not details[tab].header then
details[tab].header = line
end
@@ -61,6 +65,93 @@ local save = function()
details = nil
end
+local function validate_rule(rule)
+ local success = true
+
+ function basiccheck(val)
+ if string.find(val.value, "[%s\'\"]") then
+ val.errtxt = "Cannot contain spaces or quotes"
+ success = false
+ end
+ end
+
+ success = modelfunctions.validateselect(rule.value.table) and success
+ basiccheck(rule.value.chain)
+ if rule.value.position.value ~= "" and not validator.is_integer(rule.value.position.value) then
+ rule.value.position.errtxt = "Must be a number"
+ success = false
+ end
+ basiccheck(rule.value.protocol)
+ basiccheck(rule.value.source)
+ basiccheck(rule.value.destination)
+ basiccheck(rule.value.jump)
+ basiccheck(rule.value.goto)
+ basiccheck(rule.value.in_interface)
+ basiccheck(rule.value.out_interface)
+ if #rule.value.fragment.value > 1 or string.match(rule.value.fragment.value, "[^%+!]") then
+ rule.value.fragment.errtxt = "Invalid entry"
+ success = false
+ end
+ if rule.value.set_counters.value ~= "" and not string.match(rule.value.set_counters.value, "^%d+%s+%d+$") then
+ rule.value.set_counters.errtxt = "Invalid entry"
+ success = false
+ end
+ basiccheck(rule.value.addrtype_src_type)
+ basiccheck(rule.value.addrtype_dst_type)
+ if string.find(rule.value.comment.value, "[\'\"]") then
+ rule.value.comment.errtxt = "Cannot contain quotes"
+ success = false
+ end
+ if rule.value.jump.value == "" and rule.value.goto.value == "" then
+ rule.value.jump.errtxt = "Must define target or goto"
+ success = false
+ end
+
+ return success, rule
+end
+
+local function generate_rule_specification(rule)
+ local spec = {}
+
+ function addparameter(value, option)
+ if value ~= "" then
+ spec[#spec + 1] = option
+ spec[#spec + 1] = value
+ end
+ end
+ function addmodule(values, mod)
+ for i,value in ipairs(values) do
+ if value ~= "" then
+ spec[#spec + 1] = "-m "..mod
+ break
+ end
+ end
+ end
+
+ addparameter(rule.value.protocol.value, "-p")
+ addparameter(rule.value.source.value, "-s")
+ addparameter(rule.value.destination.value, "-d")
+ addparameter(rule.value.jump.value, "-j")
+ addparameter(rule.value.goto.value, "-g")
+ addparameter(rule.value.in_interface.value, "-i")
+ addparameter(rule.value.out_interface.value, "-o")
+ if rule.value.fragment.value == "!" then
+ spec[#spec + 1] = "! -f"
+ elseif rule.value.fragment.value ~= "" then
+ spec[#spec + 1] = "-f"
+ end
+ addparameter(rule.value.set_counters.value, "-c")
+ addmodule({rule.value.addrtype_src_type.value, rule.value.addrtype_dst_type.value}, "addrtype")
+ addparameter(rule.value.addrtype_src_type.value, "--src-type")
+ addparameter(rule.value.addrtype_dst_type.value, "--dst-type")
+ addmodule({rule.value.comment.value}, "comment")
+ if rule.value.comment.value ~= "" then
+ addparameter('"' .. rule.value.comment.value .. '"', "--comment")
+ end
+
+ return table.concat(spec, " ")
+end
+
-- ################################################################################
-- PUBLIC FUNCTIONS
@@ -160,7 +251,7 @@ function create_chain(chain)
success = false
end
if string.find(chain.value.chain.value, "[%s\'\"]") then
- chain.value.chain.errtxt = "Chain cannot contain spaces or quotes"
+ chain.value.chain.errtxt = "Cannot contain spaces or quotes"
success = false
end
@@ -207,18 +298,24 @@ end
function read_rule(tab, chain, pos)
local retval = {}
+ -- Identification
retval.table = cfe({ type="select", value=tab or "filter", label="Table", option=tables })
retval.chain = cfe({ value=chain or "", label="Chain" })
retval.position = cfe({ value=pos or "", label="Position" })
+ -- Basics
retval.protocol = cfe({ value="all", label="Protocol", descr="One of tcp, udp, icmp, or all, or a numeric value representing a protocol, or a protocol name from /etc/protocols. A '!' before the protocol inverts the test." })
- retval.source = cfe({ label="Source", descr="A network name or IP address (may have mask of type /xxx.xxx.xxx.xxx or /xx). A '!' before the address spcification inverts the sense of the address." })
- retval.destination = cfe({ label="Destination", descr="A network name or IP address (may have mask of type /xxx.xxx.xxx.xxx or /xx). A '!' before the address spcification inverts the sense of the address." })
+ retval.source = cfe({ label="Source", descr="A network name or IP address (may have mask of type /xxx.xxx.xxx.xxx or /xx). A '!' before the address specification inverts the sense of the address." })
+ retval.destination = cfe({ label="Destination", descr="A network name or IP address (may have mask of type /xxx.xxx.xxx.xxx or /xx). A '!' before the address specification inverts the sense of the address." })
retval.jump = cfe({ label="Target", descr="Specify the target of the rule - one of ACCEPT, DROP, QUEUE, or RETURN, or the name of a user-defined chain." })
retval.goto = cfe({ label="Goto", descr="Processing should continue in the specified chain" })
retval.in_interface = cfe({ label="In Interface", descr="Name of an interface via which a packet was received. A '!' before the interface inverts the sense. A '+' ending the interface will match any interface that begins with this name." })
retval.out_interface = cfe({ label="Out Interface", descr="Name of an interface via which a packet is going to be sent. A '!' before the interface inverts the sense. A '+' ending the interface will match any interface that begins with this name." })
retval.fragment = cfe({ label="Fragment", descr="A '+' specifies the second and further packets of fragmented packets. A '!' specifies only head fragments or unfragmented packets." })
- retval.set_counters = cfe({ label="Set Counters", descr="'Number, number' to initialize the packet and byte counters."})
+ retval.set_counters = cfe({ label="Set Counters", descr="'Number number' to initialize the packet and byte counters."})
+ -- Extensions
+ retval.addrtype_src_type = cfe({ type="select", label="Source Address Type", option={"", "UNSPEC", "UNICAST", "LOCAL", "BROADCAST", "ANYCAST", "MULTICAST", "BLACKHOLE", "UNREACHABLE", "PROHIBIT"} })
+ retval.addrtype_dst_type = cfe({ type="select", label="Destination Address Type", option={"", "UNSPEC", "UNICAST", "LOCAL", "BROADCAST", "ANYCAST", "MULTICAST", "BLACKHOLE", "UNREACHABLE", "PROHIBIT"} })
+ retval.comment = cfe({ label="Comment" })
getdetails()
if tab and not details[tab] then
@@ -236,11 +333,106 @@ function read_rule(tab, chain, pos)
retval.position.errtxt = "Cannot find rule"
else
-- We found the rule, update the settings
+ local words = {}
+ for word in string.gmatch(chn[tonumber(pos)].rule, "%S+") do words[#words + 1] = word end
+ retval.jump.value = words[1] or ""
+ retval.protocol.value = words[2] or ""
+ if words[3] == "-f" then
+ retval.fragment.value = "+"
+ elseif words[3] == "!f" then
+ retval.fragment.value = "!"
+ end
+ retval.in_interface.value = words[4] or ""
+ if retval.in_interface.value == "*" then retval.in_interface.value = "" end
+ retval.out_interface.value = words[5] or ""
+ if retval.out_interface.value == "*" then retval.out_interface.value = "" end
+ retval.source.value = words[6] or ""
+ retval.destination.value = words[7] or ""
+
+ local i=8
+ while i <= #words do
+ if words[i] == "[goto]" then
+ retval.goto.value = retval.jump.value
+ retval.jump.value = ""
+ elseif words[i] == "src-type" then
+ retval.addrtype_src_type.value = words[i+1]
+ i = i+1
+ elseif words[i] == "dst-type" then
+ retval.addrtype_dst_type.value = words[i+1]
+ i = i+1
+ end
+ i = i+1
+ end
+ retval.comment.value = string.match(chn[tonumber(pos)].rule, "/%*%s+(.*)%s%*/") or ""
end
end
return cfe({ type="group", value=retval, label="Rule" })
end
+function create_rule(rule)
+ local success, rule = validate_rule(rule)
+
+ if success then
+ local spec = generate_rule_specification(rule)
+ local cmd = path .. "iptables -t " .. rule.value.table.value
+ if rule.value.position.value ~= "" then
+ cmd = cmd .. " -I " .. rule.value.chain.value .. " " .. rule.value.position.value
+ else
+ cmd = cmd .. " -A " .. rule.value.chain.value
+ end
+ cmd = cmd .. " " .. spec .. " 2>&1"
+ local f = io.popen(cmd)
+ rule.errtxt = f:read("*a")
+ f:close()
+ if string.match(rule.errtxt, "^%s*$") then
+ rule.errtxt = nil
+ end
+ else
+ rule.errtxt = "Failed to create rule"
+ end
+
+ return rule
+end
+
+function update_rule(rule)
+ local success, rule = validate_rule(rule)
+ if rule.value.position.value == "" then
+ rule.value.position.errtxt = "Cannot be empty"
+ successs = false
+ end
+
+ if success then
+ local spec = generate_rule_specification(rule)
+ local cmd = path .. "iptables -t " .. rule.value.table.value .. " -R " .. rule.value.chain.value .. " " .. rule.value.position.value .. " " .. spec .. " 2>&1"
+ local f = io.popen(cmd)
+ rule.errtxt = f:read("*a")
+ f:close()
+ if string.match(rule.errtxt, "^%s*$") then
+ rule.errtxt = nil
+ end
+ else
+ rule.errtxt = "Failed to update rule"
+ end
+
+ return rule
+end
+
+function delete_rule(tab, chain, pos)
+ local cmdresult = cfe({ label="Delete Rule Result" })
+ if not tab or not chain or not pos then
+ cmdresult.errtxt = "Incomplete specification - must define table, chain, and position"
+ else
+ local cmd = path .. "iptables -t " .. tab .. " -D " .. chain .. " " .. pos
+ local f = io.popen(cmd)
+ cmdresult.value = f:read("*a")
+ f:close()
+ if string.match(cmdresult.value, "^%s*$") then
+ cmdresult.value = "Deleted rule"
+ end
+ end
+ return cmdresult
+end
+
function readrulesfile()
return modelfunctions.getfiledetails(rulesfile)
end