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, " "))
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.clear_networks(self)
376 self:set("network", " ")
379 function zone.get_forwardings_by(self, what)
380 local name = self:name()
383 uci_r:foreach("firewall", "forwarding",
385 if s.src and s.dest and s[what] == name then
386 forwards[#forwards+1] = forwarding(s['.name'])
393 function zone.add_forwarding_to(self, dest)
396 for _, forward in ipairs(self:get_forwardings_by('src')) do
397 if forward:dest() == dest then
403 if not exist and dest ~= self:name() and _valid_id(dest) then
404 local s = uci_r:section("firewall", "forwarding", nil, {
409 return s and forwarding(s)
413 function zone.add_forwarding_from(self, src)
416 for _, forward in ipairs(self:get_forwardings_by('dest')) do
417 if forward:src() == src then
423 if not exist and src ~= self:name() and _valid_id(src) then
424 local s = uci_r:section("firewall", "forwarding", nil, {
429 return s and forwarding(s)
433 function zone.del_forwardings_by(self, what)
434 local name = self:name()
436 uci_r:delete_all("firewall", "forwarding",
438 return (s.src and s.dest and s[what] == name)
442 function zone.add_redirect(self, options)
443 options = options or { }
444 options.src = self:name()
446 local s = uci_r:section("firewall", "redirect", nil, options)
447 return s and redirect(s)
450 function zone.add_rule(self, options)
451 options = options or { }
452 options.src = self:name()
454 local s = uci_r:section("firewall", "rule", nil, options)
458 function zone.get_color(self)
459 if self and self:name() == "lan" then
461 elseif self and self:name() == "wan" then
464 math.randomseed(lmo.hash(self:name()))
466 local r = math.random(128)
467 local g = math.random(128)
471 if ( r + g ) < 128 then
477 local b = min + math.floor( math.random() * ( max - min ) )
479 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
486 forwarding = utl.class()
487 function forwarding.__init__(self, f)
491 function forwarding.src(self)
492 return uci_r:get("firewall", self.sid, "src")
495 function forwarding.dest(self)
496 return uci_r:get("firewall", self.sid, "dest")
499 function forwarding.src_zone(self)
500 return zone(self:src())
503 function forwarding.dest_zone(self)
504 return zone(self:dest())
509 function rule.__init__(self, f)
513 function rule.get(self, opt)
514 return _get("firewall", self.sid, opt)
517 function rule.set(self, opt, val)
518 return _set("firewall", self.sid, opt, val)
521 function rule.src(self)
522 return uci_r:get("firewall", self.sid, "src")
525 function rule.dest(self)
526 return uci_r:get("firewall", self.sid, "dest")
529 function rule.src_zone(self)
530 return zone(self:src())
533 function rule.dest_zone(self)
534 return zone(self:dest())
538 redirect = utl.class()
539 function redirect.__init__(self, f)
543 function redirect.get(self, opt)
544 return _get("firewall", self.sid, opt)
547 function redirect.set(self, opt, val)
548 return _set("firewall", self.sid, opt, val)
551 function redirect.src(self)
552 return uci_r:get("firewall", self.sid, "src")
555 function redirect.dest(self)
556 return uci_r:get("firewall", self.sid, "dest")
559 function redirect.src_zone(self)
560 return zone(self:src())
563 function redirect.dest_zone(self)
564 return zone(self:dest())