applications/luci-firewall: complete rework
[project/luci.git] / applications / luci-firewall / luasrc / model / cbi / luci_fw / zones.lua
index edb82a9..f0e7b86 100644 (file)
@@ -14,6 +14,9 @@ $Id$
 
 local nw = require "luci.model.network"
 local fw = require "luci.model.firewall"
+local ds = require "luci.dispatcher"
+
+local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
 
 require("luci.tools.webadmin")
 m = Map("firewall", translate("Firewall"), translate("The firewall creates zones over your network interfaces to control network traffic flow."))
@@ -25,18 +28,22 @@ s = m:section(TypedSection, "defaults")
 s.anonymous = true
 s.addremove = false
 
-s:option(Flag, "syn_flood", translate("Enable SYN-flood protection"))
+s:tab("general", translate("General Settings"))
+s:tab("custom", translate("Custom Rules"))
+
 
-local di = s:option(Flag, "drop_invalid", translate("Drop invalid packets"))
+s:taboption("general", Flag, "syn_flood", translate("Enable SYN-flood protection"))
+
+local di = s:taboption("general", Flag, "drop_invalid", translate("Drop invalid packets"))
 di.rmempty = false
 function di.cfgvalue(...)
        return AbstractValue.cfgvalue(...) or "1"
 end
 
 p = {}
-p[1] = s:option(ListValue, "input", translate("Input"))
-p[2] = s:option(ListValue, "output", translate("Output"))
-p[3] = s:option(ListValue, "forward", translate("Forward"))
+p[1] = s:taboption("general", ListValue, "input", translate("Input"))
+p[2] = s:taboption("general", ListValue, "output", translate("Output"))
+p[3] = s:taboption("general", ListValue, "forward", translate("Forward"))
 
 for i, v in ipairs(p) do
        v:value("REJECT", translate("reject"))
@@ -44,14 +51,41 @@ for i, v in ipairs(p) do
        v:value("ACCEPT", translate("accept"))
 end
 
+custom = s:taboption("custom", Value, "_custom",
+       translate("Custom Rules (/etc/firewall.user)"))
+
+custom.template = "cbi/tvalue"
+custom.rows = 20
+
+function custom.cfgvalue(self, section)
+       return nixio.fs.readfile("/etc/firewall.user")
+end
+
+function custom.write(self, section, value)
+       nixio.fs.writefile("/etc/firewall.user", value)
+end
+
 
 s = m:section(TypedSection, "zone", translate("Zones"))
 s.template = "cbi/tblsection"
 s.anonymous = true
 s.addremove = true
+s.extedit   = ds.build_url("admin", "network", "firewall", "zones", "%s")
 
-name = s:option(Value, "name", translate("Name"))
-name.size = 8
+function s.create(self)
+       local z = fw:new_zone()
+       if z then
+               luci.http.redirect(
+                       ds.build_url("admin", "network", "firewall", "zones", z.sid)
+               )
+       end
+end
+
+info = s:option(DummyValue, "_info", translate("Zone ⇒ Forwardings"))
+info.template = "cbi/firewall_zoneforwards"
+function info.cfgvalue(self, section)
+       return self.map:get(section, "name")
+end
 
 p = {}
 p[1] = s:option(ListValue, "input", translate("Input"))
@@ -67,15 +101,166 @@ end
 s:option(Flag, "masq", translate("Masquerading"))
 s:option(Flag, "mtu_fix", translate("MSS clamping"))
 
-net = s:option(MultiValue, "network", translate("Network"))
-net.template = "cbi/network_netlist"
-net.widget = "checkbox"
-net.rmempty = true
-luci.tools.webadmin.cbi_add_networks(net)
 
-function net.cfgvalue(self, section)
-       local value = MultiValue.cfgvalue(self, section)
-       return value or name:cfgvalue(section)
+local created = nil
+
+--
+-- Redirects
+--
+
+s = m:section(TypedSection, "redirect", translate("Redirections"))
+s.template  = "cbi/tblsection"
+s.addremove = true
+s.anonymous = true
+s.extedit   = ds.build_url("admin", "network", "firewall", "redirect", "%s")
+
+function s.create(self, section)
+       created = TypedSection.create(self, section)
+end
+
+function s.parse(self, ...)
+       TypedSection.parse(self, ...)
+       if created then
+               m.uci:save("firewall")
+               luci.http.redirect(ds.build_url(
+                       "admin", "network", "firewall", "redirect", created
+               ))
+       end
+end
+
+name = s:option(DummyValue, "_name", translate("Name"))
+function name.cfgvalue(self, s)
+       return self.map:get(s, "_name") or "-"
+end
+
+proto = s:option(DummyValue, "proto", translate("Protocol"))
+function proto.cfgvalue(self, s)
+       local p = self.map:get(s, "proto")
+       if not p or p == "tcpudp" then
+               return "TCP+UDP"
+       else
+               return p:upper()
+       end
+end
+
+src = s:option(DummyValue, "src", translate("Source"))
+function src.cfgvalue(self, s)
+       local rv = "%s:%s:%s" % {
+               self.map:get(s, "src") or "*",
+               self.map:get(s, "src_ip") or "0.0.0.0/0",
+               self.map:get(s, "src_port") or "*"
+       }
+
+       local mac = self.map:get(s, "src_mac")
+       if mac then
+               rv = rv .. ", MAC " .. mac
+       end
+
+       return rv
+end
+
+via = s:option(DummyValue, "via", translate("Via"))
+function via.cfgvalue(self, s)
+       return "%s:%s:%s" % {
+               translate("Device"),
+               self.map:get(s, "src_dip") or "0.0.0.0/0",
+               self.map:get(s, "src_dport") or "*"
+       }
+end
+
+dest = s:option(DummyValue, "dest", translate("Destination"))
+function dest.cfgvalue(self, s)
+       return "%s:%s:%s" % {
+               self.map:get(s, "dest") or "*",
+               self.map:get(s, "dest_ip") or "0.0.0.0/0",
+               self.map:get(s, "dest_port") or "*"
+       }
+end
+
+target = s:option(DummyValue, "target", translate("Action"))
+function target.cfgvalue(self, s)
+       return self.map:get(s, "target") or "DNAT"
+end
+
+
+--
+-- Rules
+--
+
+s = m:section(TypedSection, "rule", translate("Rules"))
+s.addremove = true
+s.anonymous = true
+s.template = "cbi/tblsection"
+s.extedit   = ds.build_url("admin", "network", "firewall", "rule", "%s")
+s.defaults.target = "ACCEPT"
+
+function s.create(self, section)
+       local created = TypedSection.create(self, section)
+       m.uci:save("firewall")
+       luci.http.redirect(ds.build_url(
+               "admin", "network", "firewall", "rule", created
+       ))
+       return
 end
 
+name = s:option(DummyValue, "_name", translate("Name"))
+function name.cfgvalue(self, s)
+       return self.map:get(s, "_name") or "-"
+end
+
+if has_v2 then
+       family = s:option(DummyValue, "family", translate("Family"))
+       function family.cfgvalue(self, s)
+               local f = self.map:get(s, "family")
+               if f and f:match("4") then
+                       return translate("IPv4 only")
+               elseif f and f:match("6") then
+                       return translate("IPv6 only")
+               else
+                       return translate("IPv4 and IPv6")
+               end
+       end
+end
+
+proto = s:option(DummyValue, "proto", translate("Protocol"))
+function proto.cfgvalue(self, s)
+       local p = self.map:get(s, "proto")
+       local t = self.map:get(s, "icmp_type")
+       if p == "icmp" and t then
+               return "ICMP (%s)" % t
+       elseif p == "tcpudp" or not p then
+               return "TCP+UDP"
+       else
+               return p:upper()
+       end
+end
+
+src = s:option(DummyValue, "src", translate("Source"))
+function src.cfgvalue(self, s)
+       local rv = "%s:%s:%s" % {
+               self.map:get(s, "src") or "*",
+               self.map:get(s, "src_ip") or "0.0.0.0/0",
+               self.map:get(s, "src_port") or "*"
+       }
+
+       local mac = self.map:get(s, "src_mac")
+       if mac then
+               rv = rv .. ", MAC " .. mac
+       end
+
+       return rv
+end
+
+dest = s:option(DummyValue, "dest", translate("Destination"))
+function dest.cfgvalue(self, s)
+       return "%s:%s:%s" % {
+               self.map:get(s, "dest") or translate("Device"),
+               self.map:get(s, "dest_ip") or "0.0.0.0/0",
+               self.map:get(s, "dest_port") or "*"
+       }
+end
+
+
+s:option(DummyValue, "target", translate("Action"))
+
 return m