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:delete(c, s, o)
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 old and s.name == old then
185 if not s.network then
186 uci_r:set("firewall", s['.name'], "network", old)
188 uci_r:set("firewall", s['.name'], "name", new)
195 uci_r:foreach("firewall", "rule",
198 uci_r:set("firewall", s['.name'], "src", new)
200 if s.dest == old then
201 uci_r:set("firewall", s['.name'], "dest", new)
205 uci_r:foreach("firewall", "redirect",
208 uci_r:set("firewall", s['.name'], "src", new)
210 if s.dest == old then
211 uci_r:set("firewall", s['.name'], "dest", new)
215 uci_r:foreach("firewall", "forwarding",
218 uci_r:set("firewall", s['.name'], "src", new)
220 if s.dest == old then
221 uci_r:set("firewall", s['.name'], "dest", new)
230 function del_network(self, net)
233 for _, z in ipairs(self:get_zones()) do
240 defaults = utl.class()
241 function defaults.__init__(self)
242 uci_r:foreach("firewall", "defaults",
244 self.sid = s['.name']
248 self.sid = self.sid or uci_r:section("firewall", "defaults", nil, { })
251 function defaults.get(self, opt)
252 return _get("firewall", self.sid, opt)
255 function defaults.set(self, opt, val)
256 return _set("firewall", self.sid, opt, val)
259 function defaults.syn_flood(self)
260 return (self:get("syn_flood") == "1")
263 function defaults.drop_invalid(self)
264 return (self:get("drop_invalid") == "1")
267 function defaults.input(self)
268 return self:get("input") or "DROP"
271 function defaults.forward(self)
272 return self:get("forward") or "DROP"
275 function defaults.output(self)
276 return self:get("output") or "DROP"
281 function zone.__init__(self, z)
282 if uci_r:get("firewall", z) == "zone" then
284 self.data = uci_r:get_all("firewall", z)
286 uci_r:foreach("firewall", "zone",
289 self.sid = s['.name']
297 function zone.get(self, opt)
298 return _get("firewall", self.sid, opt)
301 function zone.set(self, opt, val)
302 return _set("firewall", self.sid, opt, val)
305 function zone.masq(self)
306 return (self:get("masq") == "1")
309 function zone.name(self)
310 return self:get("name")
313 function zone.network(self)
314 return self:get("network")
317 function zone.input(self)
318 return self:get("input") or "DROP"
321 function zone.forward(self)
322 return self:get("forward") or "DROP"
325 function zone.output(self)
326 return self:get("output") or "DROP"
329 function zone.add_network(self, net)
330 if uci_r:get("network", net) == "interface" then
334 for n in utl.imatch(self:get("network") or self:get("name")) do
343 self:set("network", table.concat(nets, " "))
345 self:set("network", " ")
350 function zone.del_network(self, net)
354 for n in utl.imatch(self:get("network") or self:get("name")) do
361 self:set("network", table.concat(nets, " "))
363 self:set("network", " ")
367 function zone.get_networks(self)
371 for n in utl.imatch(self:get("network") or self:get("name")) do
378 function zone.get_forwardings_by(self, what)
379 local name = self:name()
382 uci_r:foreach("firewall", "forwarding",
384 if s.src and s.dest and s[what] == name then
385 forwards[#forwards+1] = forwarding(s['.name'])
392 function zone.add_forwarding_to(self, dest)
395 for _, forward in ipairs(self:get_forwardings_by('src')) do
396 if forward:dest() == dest then
402 if not exist and dest ~= self:name() then
403 local s = uci_r:section("firewall", "forwarding", nil, {
408 return s and forwarding(s)
412 function zone.add_forwarding_from(self, src)
415 for _, forward in ipairs(self:get_forwardings_by('dest')) do
416 if forward:src() == src then
422 if not exist and src ~= self:name() then
423 local s = uci_r:section("firewall", "forwarding", nil, {
428 return s and forwarding(s)
432 function zone.del_forwardings_by(self, what)
433 local name = self:name()
435 uci_r:foreach("firewall", "forwarding",
437 if s.src and s.dest and s[what] == name then
438 uci_r:delete("firewall", s['.name'])
443 function zone.add_redirect(self, options)
444 options = options or { }
445 options.src = self:name()
447 local s = uci_r:section("firewall", "redirect", nil, options)
448 return s and redirect(s)
451 function zone.add_rule(self, options)
452 options = options or { }
453 options.src = self:name()
455 local s = uci_r:section("firewall", "rule", nil, options)
459 function zone.get_color(self)
460 if self and self:name() == "lan" then
462 elseif self and self:name() == "wan" then
465 math.randomseed(lmo.hash(self:name()))
467 local r = math.random(128)
468 local g = math.random(128)
472 if ( r + g ) < 128 then
478 local b = min + math.floor( math.random() * ( max - min ) )
480 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
487 forwarding = utl.class()
488 function forwarding.__init__(self, f)
492 function forwarding.src(self)
493 return uci_r:get("firewall", self.sid, "src")
496 function forwarding.dest(self)
497 return uci_r:get("firewall", self.sid, "dest")
500 function forwarding.src_zone(self)
501 return zone(self:src())
504 function forwarding.dest_zone(self)
505 return zone(self:dest())
510 function rule.__init__(self, f)
514 function rule.get(self, opt)
515 return _get("firewall", self.sid, opt)
518 function rule.set(self, opt, val)
519 return _set("firewall", self.sid, opt, val)
522 function rule.src(self)
523 return uci_r:get("firewall", self.sid, "src")
526 function rule.dest(self)
527 return uci_r:get("firewall", self.sid, "dest")
530 function rule.src_zone(self)
531 return zone(self:src())
534 function rule.dest_zone(self)
535 return zone(self:dest())
539 redirect = utl.class()
540 function redirect.__init__(self, f)
544 function redirect.get(self, opt)
545 return _get("firewall", self.sid, opt)
548 function redirect.set(self, opt, val)
549 return _set("firewall", self.sid, opt, val)
552 function redirect.src(self)
553 return uci_r:get("firewall", self.sid, "src")
556 function redirect.dest(self)
557 return uci_r:get("firewall", self.sid, "dest")
560 function redirect.src_zone(self)
561 return zone(self:src())
564 function redirect.dest_zone(self)
565 return zone(self:dest())