4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
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
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
20 local type, pairs, ipairs, table, luci, math
21 = type, pairs, ipairs, table, luci, math
23 local lmo = require "lmo"
24 local utl = require "luci.util"
25 local uct = require "luci.model.uci.bind"
27 module "luci.model.firewall"
30 local ub = uct.bind("firewall")
34 cursor:unload("firewall")
35 cursor:load("firewall")
40 function add_zone(self, n)
41 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_zone(n) then
42 local z = ub.uci:section("firewall", "zone", nil, {
45 input = defaults:input() or "DROP",
46 forward = defaults:forward() or "DROP",
47 output = defaults:output() or "DROP"
54 function get_zone(self, n)
56 ub.uci:foreach("firewall", "zone",
58 if n and s.name == n then
66 function get_zones(self)
68 ub.uci:foreach("firewall", "zone",
71 zones[#zones+1] = zone(s['.name'])
77 function get_zones_by_network(self, net)
79 ub.uci:foreach("firewall", "zone",
83 for _, n in ipairs(ub:list(s.network or s.name)) do
85 zones[#zones+1] = zone(s['.name'])
94 function del_zone(self, n)
96 ub.uci:foreach("firewall", "zone",
98 if n and s.name == n then
99 r = ub.uci:delete("firewall", s['.name'])
104 ub.uci:foreach("firewall", "rule",
106 if s.src == n or s.dest == n then
107 ub.uci:delete("firewall", s['.name'])
110 ub.uci:foreach("firewall", "redirect",
113 ub.uci:delete("firewall", s['.name'])
116 ub.uci:foreach("firewall", "forwarding",
119 ub.uci:delete("firewall", s['.name'])
126 function rename_zone(self, old, new)
128 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_zone(new) then
129 ub.uci:foreach("firewall", "zone",
131 if n and s.name == old then
132 ub.uci:set("firewall", s['.name'], "name", new)
138 ub.uci:foreach("firewall", "rule",
141 ub.uci:set("firewall", s['.name'], "src", new)
142 elseif s.dest == old then
143 ub.uci:set("firewall", s['.name'], "dest", new)
146 ub.uci:foreach("firewall", "redirect",
149 ub.uci:set("firewall", s['.name'], "src", new)
152 ub.uci:foreach("firewall", "forwarding",
155 ub.uci:set("firewall", s['.name'], "src", new)
163 function del_network(self, net)
166 for _, z in ipairs(self:get_zones()) do
173 defaults = ub:usection("defaults")
174 defaults:property_bool("syn_flood")
175 defaults:property_bool("drop_invalid")
176 defaults:property("input")
177 defaults:property("forward")
178 defaults:property("output")
181 zone = ub:section("zone")
182 zone:property_bool("masq")
183 zone:property("name")
184 zone:property("network")
185 zone:property("input")
186 zone:property("forward")
187 zone:property("output")
189 function zone.add_network(self, net)
190 if ub.uci:get("network", net) == "interface" then
191 local networks = ub:list(self:network() or self:name(), net)
192 if #networks > 0 then
193 self:network(table.concat(networks, " "))
200 function zone.del_network(self, net)
201 local networks = ub:list(self:network() or self:name(), nil, net)
202 if #networks > 0 then
203 self:network(table.concat(networks, " "))
209 function zone.get_networks(self)
210 return ub:list(self:network() or self:name())
213 function zone.get_forwardings_by(self, what)
214 local name = self:name()
216 ub.uci:foreach("firewall", "forwarding",
218 if s.src and s.dest and s[what] == name then
219 forwards[#forwards+1] = forwarding(s['.name'])
225 function zone.add_forwarding_to(self, dest, with_mtu_fix)
227 for _, forward in ipairs(self:get_forwardings_by('src')) do
228 if forward:dest() == dest then
233 if not exist and dest ~= self:name() then
234 local s = ub.uci:section("firewall", "forwarding", nil, {
237 mtu_fix = with_mtu_fix and true or false
239 return s and forwarding(s)
243 function zone.add_forwarding_from(self, src, with_mtu_fix)
245 for _, forward in ipairs(self:get_forwardings_by('dest')) do
246 if forward:src() == src then
251 if not exist and src ~= self:name() then
252 local s = ub.uci:section("firewall", "forwarding", nil, {
255 mtu_fix = with_mtu_fix and true or false
257 return s and forwarding(s)
261 function zone.add_redirect(self, options)
262 options = options or { }
263 options.src = self:name()
264 local s = ub.uci:section("firewall", "redirect", nil, options)
265 return s and redirect(s)
268 function zone.add_rule(self, options)
269 options = options or { }
270 options.src = self:name()
271 local s = ub.uci:section("firewall", "rule", nil, options)
275 function zone.get_color(self)
276 if self and self:name() == "lan" then
278 elseif self and self:name() == "wan" then
281 math.randomseed(lmo.hash(self:name()))
283 local r = math.random(128)
284 local g = math.random(128)
288 if ( r + g ) < 128 then
294 local b = min + math.floor( math.random() * ( max - min ) )
296 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
303 forwarding = ub:section("forwarding")
304 forwarding:property_bool("mtu_fix")
305 forwarding:property("src")
306 forwarding:property("dest")
308 function forwarding.src_zone(self)
309 return zone(self:src())
312 function forwarding.dest_zone(self)
313 return zone(self:dest())
317 rule = ub:section("rule")
319 rule:property("src_ip")
320 rule:property("src_mac")
321 rule:property("src_port")
322 rule:property("dest")
323 rule:property("dest_ip")
324 rule:property("dest_port")
325 rule:property("proto")
326 rule:property("target")
328 function rule.src_zone(self)
329 return zone(self:src())
333 redirect = ub:section("redirect")
334 redirect:property("src")
335 redirect:property("src_ip")
336 redirect:property("src_mac")
337 redirect:property("src_port")
338 redirect:property("src_dport")
339 redirect:property("dest_ip")
340 redirect:property("dest_port")
341 redirect:property("proto")
343 function redirect.src_zone(self)
344 return zone(self:src())