applications/luci-firewall: allow negated uci identifiers, hostnames and ip addresses...
[project/luci.git] / applications / luci-firewall / luasrc / model / cbi / luci_fw / zone.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13 ]]--
14
15 local nw = require "luci.model.network"
16 local fw = require "luci.model.firewall"
17 local utl = require "luci.util"
18 local dsp = require "luci.dispatcher"
19
20 local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
21 local out, inp
22
23 require("luci.tools.webadmin")
24 m = Map("firewall", translate("Firewall - Zone Settings"))
25 m.redirect = luci.dispatcher.build_url("admin/network/firewall")
26
27 fw.init(m.uci)
28 nw.init(m.uci)
29
30
31 local zone = fw:get_zone(arg[1])
32 if not zone then
33 luci.http.redirect(dsp.build_url("admin", "network", "firewall"))
34 return
35 end
36
37
38 s = m:section(NamedSection, zone.sid, "zone",
39 translatef("Zone %q", zone:name()),
40 translatef("This section defines common properties of %q. " ..
41 "The <em>input</em> and <em>output</em> options set the default "..
42 "policies for traffic entering and leaving this zone while the " ..
43 "<em>forward</em> option describes the policy for forwarded traffic " ..
44 "between different networks within the zone. " ..
45 "<em>Covered networks</em> specifies which available networks are " ..
46 "member of this zone.", zone:name()))
47
48 s.anonymous = true
49 s.addremove = false
50
51 m.on_commit = function(map)
52 local zone = fw:get_zone(arg[1])
53 if zone then
54 s.section = zone.sid
55 s2.section = zone.sid
56 end
57 end
58
59
60 s:tab("general", translate("General Settings"))
61 s:tab("advanced", translate("Advanced Settings"))
62
63
64 name = s:taboption("general", Value, "name", translate("Name"))
65 name.optional = false
66 name.forcewrite = true
67 name.datatype = "uciname"
68
69 function name.write(self, section, value)
70 if zone:name() ~= value then
71 fw:rename_zone(zone:name(), value)
72 out.exclude = value
73 inp.exclude = value
74 end
75
76 m.redirect = luci.dispatcher.build_url(
77 "admin", "network", "firewall", "zones", value
78 )
79 end
80
81 p = {}
82 p[1] = s:taboption("general", ListValue, "input", translate("Input"))
83 p[2] = s:taboption("general", ListValue, "output", translate("Output"))
84 p[3] = s:taboption("general", ListValue, "forward", translate("Forward"))
85
86 for i, v in ipairs(p) do
87 v:value("REJECT", translate("reject"))
88 v:value("DROP", translate("drop"))
89 v:value("ACCEPT", translate("accept"))
90 end
91
92 s:taboption("general", Flag, "masq", translate("Masquerading"))
93 s:taboption("general", Flag, "mtu_fix", translate("MSS clamping"))
94
95 net = s:taboption("general", Value, "network", translate("Covered networks"))
96 net.template = "cbi/network_netlist"
97 net.widget = "checkbox"
98 net.cast = "string"
99
100 function net.formvalue(self, section)
101 return Value.formvalue(self, section) or "-"
102 end
103
104 function net.cfgvalue(self, section)
105 return Value.cfgvalue(self, section) or name:cfgvalue(section)
106 end
107
108 function net.write(self, section, value)
109 zone:clear_networks()
110
111 local n
112 for n in utl.imatch(value) do
113 zone:add_network(n)
114 end
115 end
116
117
118 if has_v2 then
119 family = s:taboption("advanced", ListValue, "family",
120 translate("Restrict to address family"))
121
122 family.rmempty = true
123 family:value("", translate("IPv4 and IPv6"))
124 family:value("ipv4", translate("IPv4 only"))
125 family:value("ipv6", translate("IPv6 only"))
126 end
127
128 msrc = s:taboption("advanced", DynamicList, "masq_src",
129 translate("Restrict Masquerading to given source subnets"))
130
131 msrc.optional = true
132 msrc.datatype = "neg(network)"
133 msrc.placeholder = "0.0.0.0/0"
134 msrc:depends("family", "")
135 msrc:depends("family", "ipv4")
136
137 mdest = s:taboption("advanced", DynamicList, "masq_dest",
138 translate("Restrict Masquerading to given destination subnets"))
139
140 mdest.optional = true
141 mdest.datatype = "neg(network)"
142 mdest.placeholder = "0.0.0.0/0"
143 mdest:depends("family", "")
144 mdest:depends("family", "ipv4")
145
146 s:taboption("advanced", Flag, "conntrack",
147 translate("Force connection tracking"))
148
149 if has_v2 then
150 log = s:taboption("advanced", Flag, "log",
151 translate("Enable logging on this zone"))
152
153 log.rmempty = true
154 log.enabled = "1"
155
156 lim = s:taboption("advanced", Value, "log_limit",
157 translate("Limit log messages"))
158
159 lim.placeholder = "10/minute"
160 lim:depends("log", "1")
161 end
162
163
164 s2 = m:section(NamedSection, zone.sid, "fwd_out",
165 translate("Inter-Zone Forwarding"),
166 translatef("The options below control the forwarding policies between " ..
167 "this zone (%s) and other zones. <em>Destination zones</em> cover " ..
168 "forwarded traffic <strong>originating from %q</strong>. " ..
169 "<em>Source zones</em> match forwarded traffic from other zones " ..
170 "<strong>targeted at %q</strong>. The forwarding rule is " ..
171 "<em>unidirectional</em>, e.g. a forward from lan to wan does " ..
172 "<em>not</em> imply a permission to forward from wan to lan as well.",
173 zone:name(), zone:name(), zone:name()
174
175 ))
176
177 out = s2:option(Value, "out",
178 translate("Allow forward to <em>destination zones</em>:"))
179
180 out.nocreate = true
181 out.widget = "checkbox"
182 out.exclude = zone:name()
183 out.template = "cbi/firewall_zonelist"
184
185 inp = s2:option(Value, "in",
186 translate("Allow forward from <em>source zones</em>:"))
187
188 inp.nocreate = true
189 inp.widget = "checkbox"
190 inp.exclude = zone:name()
191 inp.template = "cbi/firewall_zonelist"
192
193 function out.cfgvalue(self, section)
194 local v = { }
195 local f
196 for _, f in ipairs(zone:get_forwardings_by("src")) do
197 v[#v+1] = f:dest()
198 end
199 return table.concat(v, " ")
200 end
201
202 function inp.cfgvalue(self, section)
203 local v = { }
204 local f
205 for _, f in ipairs(zone:get_forwardings_by("dest")) do
206 v[#v+1] = f:src()
207 end
208 return v
209 end
210
211 function out.formvalue(self, section)
212 return Value.formvalue(self, section) or "-"
213 end
214
215 function inp.formvalue(self, section)
216 return Value.formvalue(self, section) or "-"
217 end
218
219 function out.write(self, section, value)
220 zone:del_forwardings_by("src")
221
222 local f
223 for f in utl.imatch(value) do
224 zone:add_forwarding_to(f)
225 end
226 end
227
228 function inp.write(self, section, value)
229 zone:del_forwardings_by("dest")
230
231 local f
232 for f in utl.imatch(value) do
233 zone:add_forwarding_from(f)
234 end
235 end
236
237 return m