summaryrefslogtreecommitdiffstats
path: root/iptables-model.lua
diff options
context:
space:
mode:
authorTed Trask <ttrask01@yahoo.com>2008-11-03 21:30:32 +0000
committerTed Trask <ttrask01@yahoo.com>2008-11-03 21:30:32 +0000
commitfc670b19af9f6dd4027dcec0fc6cc0035860f9e2 (patch)
treeb86af704ba7bbef308e28014f3c0162bf2fea627 /iptables-model.lua
downloadacf-iptables-fc670b19af9f6dd4027dcec0fc6cc0035860f9e2.tar.bz2
acf-iptables-fc670b19af9f6dd4027dcec0fc6cc0035860f9e2.tar.xz
Created iptables ACF to directly view / edit rules. Status, view, and expert work. Form to edit / create rules not functional yet.
git-svn-id: svn://svn.alpinelinux.org/acf/iptables/trunk@1575 ab2d0c66-481e-0410-8bed-d214d4d58bed
Diffstat (limited to 'iptables-model.lua')
-rw-r--r--iptables-model.lua268
1 files changed, 268 insertions, 0 deletions
diff --git a/iptables-model.lua b/iptables-model.lua
new file mode 100644
index 0000000..3f55965
--- /dev/null
+++ b/iptables-model.lua
@@ -0,0 +1,268 @@
+module(..., package.seeall)
+
+-- Load libraries
+require("modelfunctions")
+require("fs")
+require("format")
+
+-- Set variables
+local packagename = "iptables"
+local servicename = "iptables"
+local rulesfile = "/var/lib/iptables/rules-save"
+
+local path = "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin "
+local tables = {"filter", "nat", "mangle"}
+local details
+
+-- ################################################################################
+-- LOCAL FUNCTIONS
+
+local getdetails = function()
+ if not details then
+ details = {}
+ local cmd = path .. "iptables -t filter -n -L"
+ for i,tab in ipairs(tables) do
+ local f = io.popen( (string.gsub(cmd, "filter", tab)) )
+ details[tab] = {table=tab}
+ local file = f:read("*a")
+ f:close()
+ for line in string.gmatch(file, "([^\n]+)") do
+ if string.match(line, "^Chain") then
+ local name = string.match(line, "^%w+%s+(%S+)")
+ 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 details[tab].header then
+ details[tab].header = line
+ end
+ end
+ end
+ end
+end
+
+local find_chain = function(tab, chain)
+ getdetails()
+ if details[tab] then
+ for i,chn in ipairs(details[tab]) do
+ if chain == chn.name then
+ return chn
+ end
+ end
+ end
+ return nil
+end
+
+local save = function()
+ local cmd = path .. "/etc/init.d/"..servicename.." save 2>&1"
+ local f = io.popen( cmd )
+ f:close()
+ details = nil
+end
+
+-- ################################################################################
+-- PUBLIC FUNCTIONS
+
+function getstatus()
+ local status = {}
+
+ local value, errtxt = processinfo.package_version(packagename)
+ status.version = cfe({
+ label="Program version",
+ value=value,
+ errtxt=errtxt,
+ })
+
+ return cfe({ type="group", value=status, label="IPtables Status" })
+end
+
+function getstatusdetails()
+ getdetails()
+ local retval = {}
+ for i,tab in ipairs(tables) do
+ local chains = 0
+ local rules = 0
+ for i,chain in ipairs(details[tab]) do
+ chains = chains + 1
+ rules = rules + #chain
+ end
+ retval[tab] = {chains=chains, rules=rules}
+ end
+
+ return cfe({ type="structure", value=retval, label="IPtables Status Details" })
+end
+
+function getrules(tab)
+ getdetails()
+ tab = tab or "filter"
+
+ return cfe({ type="structure", value=details[tab] or {}, label=string.gsub(tab, "^.", string.upper).." Rules" })
+end
+
+function read_chain(tab, chain)
+ local retval = {}
+ retval.table = cfe({ type="select", value=tab or "filter", label="Table", option=tables })
+ retval.chain = cfe({ value=chain or "", label="Chain" })
+ getdetails()
+ if tab and not details[tab] then
+ retval.table.errtxt = "Invalid table"
+ end
+ if chain then
+ local chn = find_chain(retval.table.value, chain)
+ if not chn then
+ retval.chain.errtxt = "Cannot find chain"
+ elseif chn.policy then
+ -- only built-in chains can have policies, and the target can only be DROP or ACCEPT
+ retval.policy = cfe({ type="select", value=chn.policy, label="Policy", option={"DROP", "ACCEPT"} })
+ end
+ end
+ return cfe({ type="group", value=retval, label="Chain" })
+end
+
+function update_chain(chain)
+ local success = true
+ getdetails()
+ if not details[chain.value.table.value] then
+ chain.value.table.errtxt = "Invalid table"
+ success = false
+ elseif not find_chain(chain.value.table.value, chain.value.chain.value) then
+ chain.value.chain.errtxt = "Invalid chain"
+ success = false
+ end
+
+ if success then
+ if chain.value.policy then
+ local cmd = path .. "iptables -t "..chain.value.table.value.." -P "..chain.value.chain.value.." "..chain.value.policy.value.." 2>&1"
+ local f = io.popen(cmd)
+ local errtxt = f:read("*a")
+ f:close()
+ if errtxt ~= "" then
+ chain.errtxt = errtxt
+ end
+ save()
+ end
+ else
+ chain.errtxt = "Failed to update chain"
+ end
+
+ return chain
+end
+
+function create_chain(chain)
+ local success = true
+ getdetails()
+ if not details[chain.value.table.value] then
+ chain.value.table.errtxt = "Invalid table"
+ success = false
+ elseif find_chain(chain.value.table.value, chain.value.chain.value) then
+ chain.value.chain.errtxt = "Chain already exists"
+ success = false
+ end
+ if string.find(chain.value.chain.value, "[%s\'\"]") then
+ chain.value.chain.errtxt = "Chain cannot contain spaces or quotes"
+ success = false
+ end
+
+ if success then
+ local cmd = path .. "iptables -t "..chain.value.table.value.." -N "..chain.value.chain.value.." 2>&1"
+ local f = io.popen(cmd)
+ local errtxt = f:read("*a")
+ if errtxt ~= "" then
+ chain.errtxt = errtxt
+ end
+ f:close()
+ save()
+ else
+ chain.errtxt = "Failed to create chain"
+ end
+
+ return chain
+end
+
+function delete_chain(tab, chain)
+ local retval = cfe({ label="Delete Chain result" })
+ tab = tab or "filter"
+ local chn = find_chain(tab, chain)
+ if not chn then
+ retval.errtxt = "Could not find chain"
+ elseif chn.policy then
+ retval.errtxt = "Cannot delete built-in chain"
+ elseif chn.references and tonumber(chn.references) > 0 then
+ retval.errtxt = "Cannot delete chain with references"
+ else
+ local cmd = path .. "iptables -t "..tab.." -X "..chain.." 2>&1"
+ local f = io.popen(cmd)
+ local errtxt = f:read("*a")
+ if errtxt ~= "" then
+ retval.errtxt = errtxt
+ else
+ retval.value = "Deleted Chain"
+ end
+ save()
+ end
+
+ return retval
+end
+
+function read_rule(tab, chain, pos)
+ local retval = {}
+ 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" })
+ 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.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."})
+
+ getdetails()
+ if tab and not details[tab] then
+ retval.table.errtxt = "Invalid table"
+ end
+ local chn
+ if chain then
+ chn = find_chain(retval.table.value, chain)
+ if not chn then
+ retval.chain.errtxt = "Cannot find chain"
+ end
+ end
+ if pos and chn then
+ if not chn[tonumber(pos)] then
+ retval.position.errtxt = "Cannot find rule"
+ else
+ -- We found the rule, update the settings
+ end
+ end
+ return cfe({ type="group", value=retval, label="Rule" })
+end
+
+function readrulesfile()
+ return modelfunctions.getfiledetails(rulesfile)
+end
+
+function updaterulesfile(filedetails)
+ return modelfunctions.setfiledetails(filedetails, {rulesfile})
+end
+
+-- local implementation to add save, reload, and panic actions
+function startstop_service(action)
+ local cmdresult = cfe({ label="Start/Stop result" })
+
+ if (string.lower(action) == "start") or (string.lower(action) == "stop") or (string.lower(action) == "restart") or (string.lower(action) == "save") or (string.lower(action) == "reload") or (string.lower(action) == "panic") then
+ local file = io.popen( "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin /etc/init.d/" ..
+ servicename .. " " .. string.lower(action) .. " 2>&1" )
+ if file ~= nil then
+ cmdresult.value = file:read( "*a" )
+ file:close()
+ end
+ posix.sleep(2) -- Wait for the process to start|stop
+ else
+ cmdresult.errtxt = "Unknown command!"
+ end
+ return cmdresult
+end