applications/luci-firewall: use option "name" instead of deprecated "_name", expose "extra" option, add enable/disable toggles for portforwards, snats and rules

This commit is contained in:
Jo-Philipp Wich 2011-12-20 03:14:54 +00:00
parent 48838ea0f7
commit 0f71faaf34
5 changed files with 179 additions and 87 deletions

View file

@ -14,6 +14,9 @@ $Id$
local sys = require "luci.sys" local sys = require "luci.sys"
local dsp = require "luci.dispatcher" local dsp = require "luci.dispatcher"
local ft = require "luci.tools.firewall"
local m, s, o
arg[1] = arg[1] or "" arg[1] = arg[1] or ""
@ -29,7 +32,7 @@ if m.uci:get("firewall", arg[1]) ~= "redirect" then
luci.http.redirect(m.redirect) luci.http.redirect(m.redirect)
return return
else else
local name = m:get(arg[1], "_name") local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then if not name or #name == 0 then
name = translate("(Unnamed Entry)") name = translate("(Unnamed Entry)")
end end
@ -56,26 +59,17 @@ s = m:section(NamedSection, arg[1], "redirect", "")
s.anonymous = true s.anonymous = true
s.addremove = false s.addremove = false
s:tab("general", translate("General Settings")) ft.opt_enabled(s, Button)
s:tab("advanced", translate("Advanced Settings")) ft.opt_name(s, Value, translate("Name"))
name = s:taboption("general", Value, "_name", translate("Name"))
name.rmempty = true
name.size = 10
src = s:taboption("advanced", Value, "src", translate("Source zone")) o = s:option(Value, "proto", translate("Protocol"))
src.nocreate = true o:value("tcp udp", "TCP+UDP")
src.default = "wan" o:value("tcp", "TCP")
src.template = "cbi/firewall_zonelist" o:value("udp", "UDP")
o:value("icmp", "ICMP")
proto = s:taboption("general", Value, "proto", translate("Protocol")) function o.cfgvalue(...)
proto.optional = true
proto:value("tcp udp", "TCP+UDP")
proto:value("tcp", "TCP")
proto:value("udp", "UDP")
proto:value("icmp", "ICMP")
function proto.cfgvalue(...)
local v = Value.cfgvalue(...) local v = Value.cfgvalue(...)
if not v or v == "tcpudp" then if not v or v == "tcpudp" then
return "tcp udp" return "tcp udp"
@ -83,66 +77,88 @@ function proto.cfgvalue(...)
return v return v
end end
dport = s:taboption("general", Value, "src_dport", translate("External port"),
translate("Match incoming traffic directed at the given " ..
"destination port or port range on this host"))
dport.datatype = "portrange"
to = s:taboption("general", Value, "dest_ip", translate("Internal IP address"), o = s:option(Value, "src", translate("Source zone"))
translate("Redirect matched incoming traffic to the specified " .. o.nocreate = true
"internal host")) o.default = "wan"
to.datatype = "ip4addr" o.template = "cbi/firewall_zonelist"
for i, dataset in ipairs(sys.net.arptable()) do
to:value(dataset["IP address"])
end
toport = s:taboption("general", Value, "dest_port", translate("Internal port (optional)"),
translate("Redirect matched incoming traffic to the given port on " ..
"the internal host"))
toport.optional = true
toport.placeholder = "0-65535"
toport.datatype = "portrange"
dest = s:taboption("advanced", Value, "dest", translate("Destination zone")) o = s:option(DynamicList, "src_mac",
dest.nocreate = true
dest.default = "lan"
dest.template = "cbi/firewall_zonelist"
src_dip = s:taboption("advanced", Value, "src_dip",
translate("Intended destination address"),
translate("Only match incoming traffic directed at the given IP address."))
src_dip.optional = true
src_dip.datatype = "ip4addr"
src_dip.placeholder = translate("any")
src_mac = s:taboption("advanced", DynamicList, "src_mac",
translate("Source MAC address"), translate("Source MAC address"),
translate("Only match incoming traffic from these MACs.")) translate("Only match incoming traffic from these MACs."))
src_mac.optional = true o.rmempty = true
src_mac.datatype = "macaddr" o.datatype = "macaddr"
src_mac.placeholder = translate("any") o.placeholder = translate("any")
src_ip = s:taboption("advanced", Value, "src_ip",
o = s:option(Value, "src_ip",
translate("Source IP address"), translate("Source IP address"),
translate("Only match incoming traffic from this IP or range.")) translate("Only match incoming traffic from this IP or range."))
src_ip.optional = true o.rmempty = true
src_ip.datatype = "neg(ip4addr)" o.datatype = "neg(ip4addr)"
src_ip.placeholder = translate("any") o.placeholder = translate("any")
sport = s:taboption("advanced", Value, "src_port",
o = s:option(Value, "src_port",
translate("Source port"), translate("Source port"),
translate("Only match incoming traffic originating from the given source port or port range on the client host")) translate("Only match incoming traffic originating from the given source port or port range on the client host"))
sport.optional = true o.rmempty = true
sport.datatype = "portrange" o.datatype = "portrange"
sport.placeholder = translate("any") o.placeholder = translate("any")
reflection = s:taboption("advanced", Flag, "reflection", translate("Enable NAT Loopback"))
reflection.rmempty = true o = s:option(Value, "src_dip",
reflection.default = reflection.enabled translate("External IP address"),
reflection:depends({ target = "DNAT", src = wan_zone }) translate("Only match incoming traffic directed at the given IP address."))
reflection.cfgvalue = function(...)
o.rmempty = true
o.datatype = "ip4addr"
o.placeholder = translate("any")
o = s:option(Value, "src_dport", translate("External port"),
translate("Match incoming traffic directed at the given " ..
"destination port or port range on this host"))
o.datatype = "portrange"
o = s:option(Value, "dest", translate("Internal zone"))
o.nocreate = true
o.default = "lan"
o.template = "cbi/firewall_zonelist"
o = s:option(Value, "dest_ip", translate("Internal IP address"),
translate("Redirect matched incoming traffic to the specified \
internal host"))
o.datatype = "ip4addr"
for i, dataset in ipairs(sys.net.arptable()) do
o:value(dataset["IP address"])
end
o = s:option(Value, "dest_port",
translate("Internal port"),
translate("Redirect matched incoming traffic to the given port on \
the internal host"))
o.placeholder = translate("any")
o.datatype = "portrange"
o = s:option(Flag, "reflection", translate("Enable NAT Loopback"))
o.rmempty = true
o.default = o.enabled
o:depends("src", wan_zone)
o.cfgvalue = function(...)
return Flag.cfgvalue(...) or "1" return Flag.cfgvalue(...) or "1"
end end
s:option(Value, "extra",
translate("Extra arguments"),
translate("Passes additional arguments to iptables. Use with care!"))
return m return m

View file

@ -49,7 +49,7 @@ function s.create(self, section)
self.map:set(created, "src_dport", e) self.map:set(created, "src_dport", e)
self.map:set(created, "dest_ip", a) self.map:set(created, "dest_ip", a)
self.map:set(created, "dest_port", i) self.map:set(created, "dest_port", i)
self.map:set(created, "_name", n) self.map:set(created, "name", n)
end end
if p ~= "other" then if p ~= "other" then
@ -71,10 +71,9 @@ function s.filter(self, sid)
return (self.map:get(sid, "target") ~= "SNAT") return (self.map:get(sid, "target") ~= "SNAT")
end end
name = s:option(DummyValue, "_name", translate("Name"))
function name.cfgvalue(self, s) ft.opt_name(s, DummyValue, translate("Name"))
return self.map:get(s, "_name") or "-"
end
proto = s:option(DummyValue, "proto", translate("Protocol")) proto = s:option(DummyValue, "proto", translate("Protocol"))
proto.rawhtml = true proto.rawhtml = true
@ -131,4 +130,6 @@ function dest.cfgvalue(self, s)
end end
end end
ft.opt_enabled(s, Flag, translate("Enable")).width = "1%"
return m return m

View file

@ -17,6 +17,7 @@ local sys = require "luci.sys"
local dsp = require "luci.dispatcher" local dsp = require "luci.dispatcher"
local nxo = require "nixio" local nxo = require "nixio"
local ft = require "luci.tools.firewall"
local nw = require "luci.model.network" local nw = require "luci.model.network"
local m, s, o, k, v local m, s, o, k, v
@ -46,7 +47,7 @@ if not rule_type then
-- --
elseif rule_type == "redirect" then elseif rule_type == "redirect" then
local name = m:get(arg[1], "_name") local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then if not name or #name == 0 then
name = translate("(Unnamed SNAT)") name = translate("(Unnamed SNAT)")
else else
@ -76,9 +77,8 @@ elseif rule_type == "redirect" then
s.addremove = false s.addremove = false
o = s:option(Value, "_name", translate("Name")) ft.opt_enabled(s, Button)
o.rmempty = true ft.opt_name(s, Value, translate("Name"))
o.size = 10
o = s:option(Value, "proto", o = s:option(Value, "proto",
@ -115,7 +115,7 @@ elseif rule_type == "redirect" then
o = s:option(Value, "src_ip", translate("Source IP address")) o = s:option(Value, "src_ip", translate("Source IP address"))
o.rmempty = true o.rmempty = true
o.datatype = "neg(ip4addr)" o.datatype = "neg(ipaddr)"
o.placeholder = translate("any") o.placeholder = translate("any")
@ -176,15 +176,29 @@ elseif rule_type == "redirect" then
o.placeholder = translate('Do not rewrite') o.placeholder = translate('Do not rewrite')
s:option(Value, "extra",
translate("Extra arguments"),
translate("Passes additional arguments to iptables. Use with care!"))
-- --
-- Rule -- Rule
-- --
else else
local name = m:get(arg[1], "name") or m:get(arg[1], "_name")
if not name or #name == 0 then
name = translate("(Unnamed Rule)")
end
m.title = "%s - %s" %{ translate("Firewall - Traffic Rules"), name }
s = m:section(NamedSection, arg[1], "rule", "") s = m:section(NamedSection, arg[1], "rule", "")
s.anonymous = true s.anonymous = true
s.addremove = false s.addremove = false
s:option(Value, "_name", translate("Name").." "..translate("(optional)")) ft.opt_enabled(s, Button)
ft.opt_name(s, Value, translate("Name"))
o = s:option(ListValue, "family", translate("Restrict to address family")) o = s:option(ListValue, "family", translate("Restrict to address family"))
@ -295,6 +309,11 @@ else
o:value("ACCEPT", translate("accept")) o:value("ACCEPT", translate("accept"))
o:value("REJECT", translate("reject")) o:value("REJECT", translate("reject"))
o:value("NOTRACK", translate("don't track")) o:value("NOTRACK", translate("don't track"))
s:option(Value, "extra",
translate("Extra arguments"),
translate("Passes additional arguments to iptables. Use with care!"))
end end
return m return m

View file

@ -59,7 +59,7 @@ function s.parse(self, ...)
self.map:set(created, "src", "wan") self.map:set(created, "src", "wan")
self.map:set(created, "proto", (i_p ~= "other") and i_p or "all") self.map:set(created, "proto", (i_p ~= "other") and i_p or "all")
self.map:set(created, "dest_port", i_e) self.map:set(created, "dest_port", i_e)
self.map:set(created, "_name", i_n) self.map:set(created, "name", i_n)
if i_p ~= "other" and i_e and #i_e > 0 then if i_p ~= "other" and i_e and #i_e > 0 then
created = nil created = nil
@ -71,7 +71,7 @@ function s.parse(self, ...)
self.map:set(created, "target", "ACCEPT") self.map:set(created, "target", "ACCEPT")
self.map:set(created, "src", f_s) self.map:set(created, "src", f_s)
self.map:set(created, "dest", f_d) self.map:set(created, "dest", f_d)
self.map:set(created, "_name", f_n) self.map:set(created, "name", f_n)
end end
if created then if created then
@ -82,10 +82,7 @@ function s.parse(self, ...)
end end
end end
name = s:option(DummyValue, "_name", translate("Name")) ft.opt_name(s, DummyValue, translate("Name"))
function name.cfgvalue(self, s)
return self.map:get(s, "_name") or "-"
end
family = s:option(DummyValue, "family", translate("Family")) family = s:option(DummyValue, "family", translate("Family"))
function family.cfgvalue(self, s) function family.cfgvalue(self, s)
@ -170,6 +167,8 @@ function target.cfgvalue(self, s)
end end
end end
ft.opt_enabled(s, Flag, translate("Enable")).width = "1%"
-- --
-- SNAT -- SNAT
@ -210,7 +209,7 @@ function s.parse(self, ...)
self.map:set(created, "proto", "all") self.map:set(created, "proto", "all")
self.map:set(created, "src_dip", a) self.map:set(created, "src_dip", a)
self.map:set(created, "src_dport", p) self.map:set(created, "src_dport", p)
self.map:set(created, "_name", n) self.map:set(created, "name", n)
end end
if created then if created then
@ -225,10 +224,7 @@ function s.filter(self, sid)
return (self.map:get(sid, "target") == "SNAT") return (self.map:get(sid, "target") == "SNAT")
end end
name = s:option(DummyValue, "_name", translate("Name")) ft.opt_name(s, DummyValue, translate("Name"))
function name.cfgvalue(self, s)
return self.map:get(s, "_name") or "-"
end
proto = s:option(DummyValue, "proto", translate("Protocol")) proto = s:option(DummyValue, "proto", translate("Protocol"))
proto.rawhtml = true proto.rawhtml = true
@ -285,5 +281,7 @@ function snat.cfgvalue(self, s)
end end
end end
ft.opt_enabled(s, Flag, translate("Enable")).width = "1%"
return m return m

View file

@ -227,3 +227,61 @@ function fmt_target(x, dest)
end end
end end
end end
function opt_enabled(s, t, ...)
if t == luci.cbi.Button then
local o = s:option(t, "__enabled")
function o.render(self, section)
if self.map:get(section, "enabled") ~= "0" then
self.title = translate("Rule is enabled")
self.inputtitle = translate("Disable")
self.inputstyle = "reset"
else
self.title = translate("Rule is disabled")
self.inputtitle = translate("Enable")
self.inputstyle = "apply"
end
t.render(self, section)
end
function o.write(self, section, value)
if self.map:get(section, "enabled") ~= "0" then
self.map:set(section, "enabled", "0")
else
self.map:del(section, "enabled")
end
end
return o
else
local o = s:option(t, "enabled", ...)
o.enabled = ""
o.disabled = "0"
o.default = o.enabled
return o
end
end
function opt_name(s, t, ...)
local o = s:option(t, "name", ...)
function o.cfgvalue(self, section)
return self.map:get(section, "name") or
self.map:get(section, "_name") or "-"
end
function o.write(self, section, value)
if value ~= "-" then
self.map:set(section, "name", value)
self.map:del(section, "_name")
else
self:remove(section)
end
end
function o.remove(self, section)
self.map:del(section, "name")
self.map:del(section, "_name")
end
return o
end