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 uci = require "luci.model.uci"
27 module "luci.model.firewall"
33 return (x and #x > 0 and x:match("^[a-zA-Z0-9_]+$"))
36 function _get(c, s, o)
37 return uci_r:get(c, s, o)
40 function _set(c, s, o, v)
42 if type(v) == "boolean" then v = v and "1" or "0" end
43 return uci_r:set(c, s, o, v)
45 return uci_r:del(c, s, o, v)
51 uci_r = cursor or uci_r or uci.cursor()
52 uci_s = uci_r:substate()
57 function save(self, ...)
62 function commit(self, ...)
67 function add_zone(self, n)
68 if _valid_id(n) and not self:get_zone(n) then
69 local z = uci_r:section("firewall", "zone", nil, {
72 input = defaults:input() or "DROP",
73 forward = defaults:forward() or "DROP",
74 output = defaults:output() or "DROP"
81 function get_zone(self, n)
82 if uci_r:get("firewall", n) == "zone" then
86 uci_r:foreach("firewall", "zone",
88 if n and s.name == n then
97 function get_zones(self)
101 uci_r:foreach("firewall", "zone",
104 znl[s.name] = zone(s['.name'])
109 for z in utl.kspairs(znl) do
110 zones[#zones+1] = znl[z]
116 function get_zone_by_network(self, net)
119 uci_r:foreach("firewall", "zone",
121 if s.name and net then
123 for n in utl.imatch(s.network or s.name) do
135 function del_zone(self, n)
138 if uci_r:get("firewall", n) == "zone" then
139 local z = uci_r:get("firewall", n, "name")
140 r = uci_r:delete("firwall", n)
143 uci_r:foreach("firewall", "zone",
145 if n and s.name == n then
146 r = uci_r:delete("firewall", s['.name'])
153 uci_r:foreach("firewall", "rule",
155 if s.src == n or s.dest == n then
156 uci_r:delete("firewall", s['.name'])
160 uci_r:foreach("firewall", "redirect",
163 uci_r:delete("firewall", s['.name'])
167 uci_r:foreach("firewall", "forwarding",
170 uci_r:delete("firewall", s['.name'])
178 function rename_zone(self, old, new)
181 if _valid_id(new) and not self:get_zone(new) then
182 uci_r:foreach("firewall", "zone",
184 if n and s.name == old then
185 uci_r:set("firewall", s['.name'], "name", new)
192 uci_r:foreach("firewall", "rule",
195 uci_r:set("firewall", s['.name'], "src", new)
197 if s.dest == old then
198 uci_r:set("firewall", s['.name'], "dest", new)
202 uci_r:foreach("firewall", "redirect",
205 uci_r:set("firewall", s['.name'], "src", new)
207 if s.dest == old then
208 uci_r:set("firewall", s['.name'], "dest", new)
212 ub.uci:foreach("firewall", "forwarding",
215 ub.uci:set("firewall", s['.name'], "src", new)
217 if s.dest == old then
218 uci_r:set("firewall", s['.name'], "dest", new)
227 function del_network(self, net)
230 for _, z in ipairs(self:get_zones()) do
237 defaults = utl.class()
238 function defaults.__init__(self)
239 uci_r:foreach("firewall", "defaults",
241 self.sid = s['.name']
245 self.sid = self.sid or uci_r:section("firewall", "defaults", nil, { })
248 function defaults.get(self, opt)
249 return _get("firewall", self.sid, opt)
252 function defaults.set(self, opt, val)
253 return _set("firewall", self.sid, opt, val)
256 function defaults.syn_flood(self)
257 return (self:get("syn_flood") == "1")
260 function defaults.drop_invalid(self)
261 return (self:get("drop_invalid") == "1")
264 function defaults.input(self)
265 return self:get("input") or "DROP"
268 function defaults.forward(self)
269 return self:get("forward") or "DROP"
272 function defaults.output(self)
273 return self:get("output") or "DROP"
278 function zone.__init__(self, z)
279 if uci_r:get("firewall", z) == "zone" then
281 self.data = uci_r:get_all("firewall", z)
283 uci_r:foreach("firewall", "zone",
286 self.sid = s['.name']
294 function zone.get(self, opt)
295 return _get("firewall", self.sid, opt)
298 function zone.set(self, opt, val)
299 return _set("firewall", self.sid, opt, val)
302 function zone.masq(self)
303 return (self:get("masq") == "1")
306 function zone.name(self)
307 return self:get("name")
310 function zone.network(self)
311 return self:get("network")
314 function zone.input(self)
315 return self:get("input") or "DROP"
318 function zone.forward(self)
319 return self:get("forward") or "DROP"
322 function zone.output(self)
323 return self:get("output") or "DROP"
326 function zone.add_network(self, net)
327 if uci_r:get("network", net) == "interface" then
331 for n in utl.imatch(self:get("network") or self:get("name")) do
340 self:set("network", table.concat(nets, " "))
342 self:set("network", " ")
347 function zone.del_network(self, net)
351 for n in utl.imatch(self:get("network") or self:get("name")) do
358 self:set("network", table.concat(nets, " "))
360 self:set("network", " ")
364 function zone.get_networks(self)
368 for n in utl.imatch(self:get("network") or self:get("name")) do
375 function zone.get_forwardings_by(self, what)
376 local name = self:name()
379 uci_r:foreach("firewall", "forwarding",
381 if s.src and s.dest and s[what] == name then
382 forwards[#forwards+1] = forwarding(s['.name'])
389 function zone.add_forwarding_to(self, dest)
392 for _, forward in ipairs(self:get_forwardings_by('src')) do
393 if forward:dest() == dest then
399 if not exist and dest ~= self:name() then
400 local s = uci_r:section("firewall", "forwarding", nil, {
405 return s and forwarding(s)
409 function zone.add_forwarding_from(self, src)
412 for _, forward in ipairs(self:get_forwardings_by('dest')) do
413 if forward:src() == src then
419 if not exist and src ~= self:name() then
420 local s = uci_r:section("firewall", "forwarding", nil, {
425 return s and forwarding(s)
429 function zone.del_forwardings_by(self, what)
430 local name = self:name()
432 uci_r:foreach("firewall", "forwarding",
434 if s.src and s.dest and s[what] == name then
435 uci_r:delete("firewall", s['.name'])
440 function zone.add_redirect(self, options)
441 options = options or { }
442 options.src = self:name()
444 local s = uci_r:section("firewall", "redirect", nil, options)
445 return s and redirect(s)
448 function zone.add_rule(self, options)
449 options = options or { }
450 options.src = self:name()
452 local s = uci_r:section("firewall", "rule", nil, options)
456 function zone.get_color(self)
457 if self and self:name() == "lan" then
459 elseif self and self:name() == "wan" then
462 math.randomseed(lmo.hash(self:name()))
464 local r = math.random(128)
465 local g = math.random(128)
469 if ( r + g ) < 128 then
475 local b = min + math.floor( math.random() * ( max - min ) )
477 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
484 forwarding = utl.class()
485 function forwarding.__init__(self, f)
489 function forwarding.src(self)
490 return uci_r:get("firewall", self.sid, "src")
493 function forwarding.dest(self)
494 return uci_r:get("firewall", self.sid, "dest")
497 function forwarding.src_zone(self)
498 return zone(self:src())
501 function forwarding.dest_zone(self)
502 return zone(self:dest())
507 function rule.__init__(self, f)
511 function rule.get(self, opt)
512 return _get("firewall", self.sid, opt)
515 function rule.set(self, opt, val)
516 return _set("firewall", self.sid, opt, val)
519 function rule.src(self)
520 return uci_r:get("firewall", self.sid, "src")
523 function rule.dest(self)
524 return uci_r:get("firewall", self.sid, "dest")
527 function rule.src_zone(self)
528 return zone(self:src())
531 function rule.dest_zone(self)
532 return zone(self:dest())
536 redirect = utl.class()
537 function redirect.__init__(self, f)
541 function redirect.get(self, opt)
542 return _get("firewall", self.sid, opt)
545 function redirect.set(self, opt, val)
546 return _set("firewall", self.sid, opt, val)
549 function redirect.src(self)
550 return uci_r:get("firewall", self.sid, "src")
553 function redirect.dest(self)
554 return uci_r:get("firewall", self.sid, "dest")
557 function redirect.src_zone(self)
558 return zone(self:src())
561 function redirect.dest_zone(self)
562 return zone(self:dest())