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_zone_by_network(self, net)
79 ub.uci:foreach("firewall", "zone",
81 if s.name and net then
83 for _, n in ipairs(ub:list(s.network or s.name)) do
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 "1" or "0"
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 "1" or "0"
257 return s and forwarding(s)
261 function zone.del_forwardings_by(self, what)
262 local name = self:name()
263 ub.uci:foreach("firewall", "forwarding",
265 if s.src and s.dest and s[what] == name then
266 ub.uci:delete("firewall", s['.name'])
271 function zone.add_redirect(self, options)
272 options = options or { }
273 options.src = self:name()
274 local s = ub.uci:section("firewall", "redirect", nil, options)
275 return s and redirect(s)
278 function zone.add_rule(self, options)
279 options = options or { }
280 options.src = self:name()
281 local s = ub.uci:section("firewall", "rule", nil, options)
285 function zone.get_color(self)
286 if self and self:name() == "lan" then
288 elseif self and self:name() == "wan" then
291 math.randomseed(lmo.hash(self:name()))
293 local r = math.random(128)
294 local g = math.random(128)
298 if ( r + g ) < 128 then
304 local b = min + math.floor( math.random() * ( max - min ) )
306 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
313 forwarding = ub:section("forwarding")
314 forwarding:property_bool("mtu_fix")
315 forwarding:property("src")
316 forwarding:property("dest")
318 function forwarding.src_zone(self)
319 return zone(self:src())
322 function forwarding.dest_zone(self)
323 return zone(self:dest())
327 rule = ub:section("rule")
329 rule:property("src_ip")
330 rule:property("src_mac")
331 rule:property("src_port")
332 rule:property("dest")
333 rule:property("dest_ip")
334 rule:property("dest_port")
335 rule:property("proto")
336 rule:property("target")
338 function rule.src_zone(self)
339 return zone(self:src())
343 redirect = ub:section("redirect")
344 redirect:property("src")
345 redirect:property("src_ip")
346 redirect:property("src_mac")
347 redirect:property("src_port")
348 redirect:property("src_dport")
349 redirect:property("dest_ip")
350 redirect:property("dest_port")
351 redirect:property("proto")
353 function redirect.src_zone(self)
354 return zone(self:src())