1 -- Copyright 2009 Jo-Philipp Wich <jow@openwrt.org>
2 -- Licensed to the public under the Apache License 2.0.
4 local type, pairs, ipairs, table, luci, math
5 = type, pairs, ipairs, table, luci, math
7 local tpl = require "luci.template.parser"
8 local utl = require "luci.util"
9 local uci = require "luci.model.uci"
11 module "luci.model.firewall"
17 return (x and #x > 0 and x:match("^[a-zA-Z0-9_]+$"))
20 function _get(c, s, o)
21 return uci_r:get(c, s, o)
24 function _set(c, s, o, v)
26 if type(v) == "boolean" then v = v and "1" or "0" end
27 return uci_r:set(c, s, o, v)
29 return uci_r:delete(c, s, o)
35 uci_r = cursor or uci_r or uci.cursor()
36 uci_s = uci_r:substate()
41 function save(self, ...)
46 function commit(self, ...)
51 function get_defaults()
55 function new_zone(self)
56 local name = "newzone"
59 while self:get_zone(name) do
61 name = "newzone%d" % count
64 return self:add_zone(name)
67 function add_zone(self, n)
68 if _valid_id(n) and not self:get_zone(n) then
70 local z = uci_r:section("firewall", "zone", nil, {
73 input = d:input() or "DROP",
74 forward = d:forward() or "DROP",
75 output = d:output() or "DROP"
82 function get_zone(self, n)
83 if uci_r:get("firewall", n) == "zone" then
87 uci_r:foreach("firewall", "zone",
89 if n and s.name == n then
98 function get_zones(self)
102 uci_r:foreach("firewall", "zone",
105 znl[s.name] = zone(s['.name'])
110 for z in utl.kspairs(znl) do
111 zones[#zones+1] = znl[z]
117 function get_zone_by_network(self, net)
120 uci_r:foreach("firewall", "zone",
122 if s.name and net then
124 for n in utl.imatch(s.network or s.name) do
136 function del_zone(self, n)
139 if uci_r:get("firewall", n) == "zone" then
140 local z = uci_r:get("firewall", n, "name")
141 r = uci_r:delete("firewall", n)
144 uci_r:foreach("firewall", "zone",
146 if n and s.name == n then
147 r = uci_r:delete("firewall", s['.name'])
154 uci_r:foreach("firewall", "rule",
156 if s.src == n or s.dest == n then
157 uci_r:delete("firewall", s['.name'])
161 uci_r:foreach("firewall", "redirect",
163 if s.src == n or s.dest == n then
164 uci_r:delete("firewall", s['.name'])
168 uci_r:foreach("firewall", "forwarding",
170 if s.src == n or s.dest == n then
171 uci_r:delete("firewall", s['.name'])
179 function rename_zone(self, old, new)
182 if _valid_id(new) and not self:get_zone(new) then
183 uci_r:foreach("firewall", "zone",
185 if old and s.name == old then
186 if not s.network then
187 uci_r:set("firewall", s['.name'], "network", old)
189 uci_r:set("firewall", s['.name'], "name", new)
196 uci_r:foreach("firewall", "rule",
199 uci_r:set("firewall", s['.name'], "src", new)
201 if s.dest == old then
202 uci_r:set("firewall", s['.name'], "dest", new)
206 uci_r:foreach("firewall", "redirect",
209 uci_r:set("firewall", s['.name'], "src", new)
211 if s.dest == old then
212 uci_r:set("firewall", s['.name'], "dest", new)
216 uci_r:foreach("firewall", "forwarding",
219 uci_r:set("firewall", s['.name'], "src", new)
221 if s.dest == old then
222 uci_r:set("firewall", s['.name'], "dest", new)
231 function del_network(self, net)
234 for _, z in ipairs(self:get_zones()) do
241 defaults = utl.class()
242 function defaults.__init__(self)
243 uci_r:foreach("firewall", "defaults",
245 self.sid = s['.name']
249 self.sid = self.sid or uci_r:section("firewall", "defaults", nil, { })
252 function defaults.get(self, opt)
253 return _get("firewall", self.sid, opt)
256 function defaults.set(self, opt, val)
257 return _set("firewall", self.sid, opt, val)
260 function defaults.syn_flood(self)
261 return (self:get("syn_flood") == "1")
264 function defaults.drop_invalid(self)
265 return (self:get("drop_invalid") == "1")
268 function defaults.input(self)
269 return self:get("input") or "DROP"
272 function defaults.forward(self)
273 return self:get("forward") or "DROP"
276 function defaults.output(self)
277 return self:get("output") or "DROP"
282 function zone.__init__(self, z)
283 if uci_r:get("firewall", z) == "zone" then
285 self.data = uci_r:get_all("firewall", z)
287 uci_r:foreach("firewall", "zone",
290 self.sid = s['.name']
298 function zone.get(self, opt)
299 return _get("firewall", self.sid, opt)
302 function zone.set(self, opt, val)
303 return _set("firewall", self.sid, opt, val)
306 function zone.masq(self)
307 return (self:get("masq") == "1")
310 function zone.name(self)
311 return self:get("name")
314 function zone.network(self)
315 return self:get("network")
318 function zone.input(self)
319 return self:get("input") or defaults():input() or "DROP"
322 function zone.forward(self)
323 return self:get("forward") or defaults():forward() or "DROP"
326 function zone.output(self)
327 return self:get("output") or defaults():output() or "DROP"
330 function zone.add_network(self, net)
331 if uci_r:get("network", net) == "interface" then
335 for n in utl.imatch(self:get("network") or self:get("name")) do
344 self:set("network", table.concat(nets, " "))
348 function zone.del_network(self, net)
352 for n in utl.imatch(self:get("network") or self:get("name")) do
359 self:set("network", table.concat(nets, " "))
361 self:set("network", " ")
365 function zone.get_networks(self)
369 for n in utl.imatch(self:get("network") or self:get("name")) do
376 function zone.clear_networks(self)
377 self:set("network", " ")
380 function zone.get_forwardings_by(self, what)
381 local name = self:name()
384 uci_r:foreach("firewall", "forwarding",
386 if s.src and s.dest and s[what] == name then
387 forwards[#forwards+1] = forwarding(s['.name'])
394 function zone.add_forwarding_to(self, dest)
397 for _, forward in ipairs(self:get_forwardings_by('src')) do
398 if forward:dest() == dest then
404 if not exist and dest ~= self:name() and _valid_id(dest) then
405 local s = uci_r:section("firewall", "forwarding", nil, {
410 return s and forwarding(s)
414 function zone.add_forwarding_from(self, src)
417 for _, forward in ipairs(self:get_forwardings_by('dest')) do
418 if forward:src() == src then
424 if not exist and src ~= self:name() and _valid_id(src) then
425 local s = uci_r:section("firewall", "forwarding", nil, {
430 return s and forwarding(s)
434 function zone.del_forwardings_by(self, what)
435 local name = self:name()
437 uci_r:delete_all("firewall", "forwarding",
439 return (s.src and s.dest and s[what] == 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(tpl.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 local z = zone(self:src())
505 function forwarding.dest_zone(self)
506 local z = zone(self:dest())
512 function rule.__init__(self, f)
516 function rule.get(self, opt)
517 return _get("firewall", self.sid, opt)
520 function rule.set(self, opt, val)
521 return _set("firewall", self.sid, opt, val)
524 function rule.src(self)
525 return uci_r:get("firewall", self.sid, "src")
528 function rule.dest(self)
529 return uci_r:get("firewall", self.sid, "dest")
532 function rule.src_zone(self)
533 return zone(self:src())
536 function rule.dest_zone(self)
537 return zone(self:dest())
541 redirect = utl.class()
542 function redirect.__init__(self, f)
546 function redirect.get(self, opt)
547 return _get("firewall", self.sid, opt)
550 function redirect.set(self, opt, val)
551 return _set("firewall", self.sid, opt, val)
554 function redirect.src(self)
555 return uci_r:get("firewall", self.sid, "src")
558 function redirect.dest(self)
559 return uci_r:get("firewall", self.sid, "dest")
562 function redirect.src_zone(self)
563 return zone(self:src())
566 function redirect.dest_zone(self)
567 return zone(self:dest())