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 tpl = require "luci.template.parser"
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 get_defaults()
71 function new_zone(self)
72 local name = "newzone"
75 while self:get_zone(name) do
77 name = "newzone%d" % count
80 return self:add_zone(name)
83 function add_zone(self, n)
84 if _valid_id(n) and not self:get_zone(n) then
86 local z = uci_r:section("firewall", "zone", nil, {
89 input = d:input() or "DROP",
90 forward = d:forward() or "DROP",
91 output = d:output() or "DROP"
98 function get_zone(self, n)
99 if uci_r:get("firewall", n) == "zone" then
103 uci_r:foreach("firewall", "zone",
105 if n and s.name == n then
114 function get_zones(self)
118 uci_r:foreach("firewall", "zone",
121 znl[s.name] = zone(s['.name'])
126 for z in utl.kspairs(znl) do
127 zones[#zones+1] = znl[z]
133 function get_zone_by_network(self, net)
136 uci_r:foreach("firewall", "zone",
138 if s.name and net then
140 for n in utl.imatch(s.network or s.name) do
152 function del_zone(self, n)
155 if uci_r:get("firewall", n) == "zone" then
156 local z = uci_r:get("firewall", n, "name")
157 r = uci_r:delete("firewall", n)
160 uci_r:foreach("firewall", "zone",
162 if n and s.name == n then
163 r = uci_r:delete("firewall", s['.name'])
170 uci_r:foreach("firewall", "rule",
172 if s.src == n or s.dest == n then
173 uci_r:delete("firewall", s['.name'])
177 uci_r:foreach("firewall", "redirect",
179 if s.src == n or s.dest == n then
180 uci_r:delete("firewall", s['.name'])
184 uci_r:foreach("firewall", "forwarding",
186 if s.src == n or s.dest == n then
187 uci_r:delete("firewall", s['.name'])
195 function rename_zone(self, old, new)
198 if _valid_id(new) and not self:get_zone(new) then
199 uci_r:foreach("firewall", "zone",
201 if old and s.name == old then
202 if not s.network then
203 uci_r:set("firewall", s['.name'], "network", old)
205 uci_r:set("firewall", s['.name'], "name", new)
212 uci_r:foreach("firewall", "rule",
215 uci_r:set("firewall", s['.name'], "src", new)
217 if s.dest == old then
218 uci_r:set("firewall", s['.name'], "dest", new)
222 uci_r:foreach("firewall", "redirect",
225 uci_r:set("firewall", s['.name'], "src", new)
227 if s.dest == old then
228 uci_r:set("firewall", s['.name'], "dest", new)
232 uci_r:foreach("firewall", "forwarding",
235 uci_r:set("firewall", s['.name'], "src", new)
237 if s.dest == old then
238 uci_r:set("firewall", s['.name'], "dest", new)
247 function del_network(self, net)
250 for _, z in ipairs(self:get_zones()) do
257 defaults = utl.class()
258 function defaults.__init__(self)
259 uci_r:foreach("firewall", "defaults",
261 self.sid = s['.name']
265 self.sid = self.sid or uci_r:section("firewall", "defaults", nil, { })
268 function defaults.get(self, opt)
269 return _get("firewall", self.sid, opt)
272 function defaults.set(self, opt, val)
273 return _set("firewall", self.sid, opt, val)
276 function defaults.syn_flood(self)
277 return (self:get("syn_flood") == "1")
280 function defaults.drop_invalid(self)
281 return (self:get("drop_invalid") == "1")
284 function defaults.input(self)
285 return self:get("input") or "DROP"
288 function defaults.forward(self)
289 return self:get("forward") or "DROP"
292 function defaults.output(self)
293 return self:get("output") or "DROP"
298 function zone.__init__(self, z)
299 if uci_r:get("firewall", z) == "zone" then
301 self.data = uci_r:get_all("firewall", z)
303 uci_r:foreach("firewall", "zone",
306 self.sid = s['.name']
314 function zone.get(self, opt)
315 return _get("firewall", self.sid, opt)
318 function zone.set(self, opt, val)
319 return _set("firewall", self.sid, opt, val)
322 function zone.masq(self)
323 return (self:get("masq") == "1")
326 function zone.name(self)
327 return self:get("name")
330 function zone.network(self)
331 return self:get("network")
334 function zone.input(self)
335 return self:get("input") or defaults():input() or "DROP"
338 function zone.forward(self)
339 return self:get("forward") or defaults():forward() or "DROP"
342 function zone.output(self)
343 return self:get("output") or defaults():output() or "DROP"
346 function zone.add_network(self, net)
347 if uci_r:get("network", net) == "interface" then
351 for n in utl.imatch(self:get("network") or self:get("name")) do
360 self:set("network", table.concat(nets, " "))
364 function zone.del_network(self, net)
368 for n in utl.imatch(self:get("network") or self:get("name")) do
375 self:set("network", table.concat(nets, " "))
377 self:set("network", " ")
381 function zone.get_networks(self)
385 for n in utl.imatch(self:get("network") or self:get("name")) do
392 function zone.clear_networks(self)
393 self:set("network", " ")
396 function zone.get_forwardings_by(self, what)
397 local name = self:name()
400 uci_r:foreach("firewall", "forwarding",
402 if s.src and s.dest and s[what] == name then
403 forwards[#forwards+1] = forwarding(s['.name'])
410 function zone.add_forwarding_to(self, dest)
413 for _, forward in ipairs(self:get_forwardings_by('src')) do
414 if forward:dest() == dest then
420 if not exist and dest ~= self:name() and _valid_id(dest) then
421 local s = uci_r:section("firewall", "forwarding", nil, {
426 return s and forwarding(s)
430 function zone.add_forwarding_from(self, src)
433 for _, forward in ipairs(self:get_forwardings_by('dest')) do
434 if forward:src() == src then
440 if not exist and src ~= self:name() and _valid_id(src) then
441 local s = uci_r:section("firewall", "forwarding", nil, {
446 return s and forwarding(s)
450 function zone.del_forwardings_by(self, what)
451 local name = self:name()
453 uci_r:delete_all("firewall", "forwarding",
455 return (s.src and s.dest and s[what] == name)
459 function zone.add_redirect(self, options)
460 options = options or { }
461 options.src = self:name()
463 local s = uci_r:section("firewall", "redirect", nil, options)
464 return s and redirect(s)
467 function zone.add_rule(self, options)
468 options = options or { }
469 options.src = self:name()
471 local s = uci_r:section("firewall", "rule", nil, options)
475 function zone.get_color(self)
476 if self and self:name() == "lan" then
478 elseif self and self:name() == "wan" then
481 math.randomseed(tpl.hash(self:name()))
483 local r = math.random(128)
484 local g = math.random(128)
488 if ( r + g ) < 128 then
494 local b = min + math.floor( math.random() * ( max - min ) )
496 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
503 forwarding = utl.class()
504 function forwarding.__init__(self, f)
508 function forwarding.src(self)
509 return uci_r:get("firewall", self.sid, "src")
512 function forwarding.dest(self)
513 return uci_r:get("firewall", self.sid, "dest")
516 function forwarding.src_zone(self)
517 return zone(self:src())
520 function forwarding.dest_zone(self)
521 return zone(self:dest())
526 function rule.__init__(self, f)
530 function rule.get(self, opt)
531 return _get("firewall", self.sid, opt)
534 function rule.set(self, opt, val)
535 return _set("firewall", self.sid, opt, val)
538 function rule.src(self)
539 return uci_r:get("firewall", self.sid, "src")
542 function rule.dest(self)
543 return uci_r:get("firewall", self.sid, "dest")
546 function rule.src_zone(self)
547 return zone(self:src())
550 function rule.dest_zone(self)
551 return zone(self:dest())
555 redirect = utl.class()
556 function redirect.__init__(self, f)
560 function redirect.get(self, opt)
561 return _get("firewall", self.sid, opt)
564 function redirect.set(self, opt, val)
565 return _set("firewall", self.sid, opt, val)
568 function redirect.src(self)
569 return uci_r:get("firewall", self.sid, "src")
572 function redirect.dest(self)
573 return uci_r:get("firewall", self.sid, "dest")
576 function redirect.src_zone(self)
577 return zone(self:src())
580 function redirect.dest_zone(self)
581 return zone(self:dest())