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"
35 elseif type(x) == "table" then
36 x = table.concat(x, " ")
39 return x:gmatch("%S+")
43 return (x and #x > 0 and x:match("^[a-zA-Z0-9_]+$"))
46 function _get(c, s, o)
47 return uci_r:get(c, s, o)
50 function _set(c, s, o, v)
52 if type(v) == "boolean" then v = v and "1" or "0" end
53 return uci_r:set(c, s, o, v)
55 return uci_r:del(c, s, o, v)
61 uci_r = cursor or uci_r or uci.cursor()
62 uci_s = uci_r:substate()
67 function save(self, ...)
72 function commit(self, ...)
77 function add_zone(self, n)
78 if _valid_id(n) and not self:get_zone(n) then
79 local z = uci_r:section("firewall", "zone", nil, {
82 input = defaults:input() or "DROP",
83 forward = defaults:forward() or "DROP",
84 output = defaults:output() or "DROP"
91 function get_zone(self, n)
92 if uci_r:get("firewall", n) == "zone" then
96 uci_r:foreach("firewall", "zone",
98 if n and s.name == n then
107 function get_zones(self)
111 uci_r:foreach("firewall", "zone",
114 znl[s.name] = zone(s['.name'])
119 for z in utl.kspairs(znl) do
120 zones[#zones+1] = znl[z]
126 function get_zone_by_network(self, net)
129 uci_r:foreach("firewall", "zone",
131 if s.name and net then
133 for n in _strlist(s.network or s.name) do
145 function del_zone(self, n)
148 if uci_r:get("firewall", n) == "zone" then
149 local z = uci_r:get("firewall", n, "name")
150 r = uci_r:delete("firwall", n)
153 uci_r:foreach("firewall", "zone",
155 if n and s.name == n then
156 r = uci_r:delete("firewall", s['.name'])
163 uci_r:foreach("firewall", "rule",
165 if s.src == n or s.dest == n then
166 uci_r:delete("firewall", s['.name'])
170 uci_r:foreach("firewall", "redirect",
173 uci_r:delete("firewall", s['.name'])
177 uci_r:foreach("firewall", "forwarding",
180 uci_r:delete("firewall", s['.name'])
188 function rename_zone(self, old, new)
191 if _valid_id(new) and not self:get_zone(new) then
192 uci_r:foreach("firewall", "zone",
194 if n and s.name == old then
195 uci_r:set("firewall", s['.name'], "name", new)
202 uci_r:foreach("firewall", "rule",
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 uci_r:foreach("firewall", "redirect",
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 ub.uci:foreach("firewall", "forwarding",
225 ub.uci:set("firewall", s['.name'], "src", new)
227 if s.dest == old then
228 uci_r:set("firewall", s['.name'], "dest", new)
237 function del_network(self, net)
240 for _, z in ipairs(self:get_zones()) do
247 defaults = utl.class()
248 function defaults.__init__(self)
249 uci_r:foreach("firewall", "defaults",
251 self.sid = s['.name']
255 self.sid = self.sid or uci_r:section("firewall", "defaults", nil, { })
258 function defaults.get(self, opt)
259 return _get("firewall", self.sid, opt)
262 function defaults.set(self, opt, val)
263 return _set("firewall", self.sid, opt, val)
266 function defaults.syn_flood(self)
267 return (self:get("syn_flood") == "1")
270 function defaults.drop_invalid(self)
271 return (self:get("drop_invalid") == "1")
274 function defaults.input(self)
275 return self:get("input") or "DROP"
278 function defaults.forward(self)
279 return self:get("forward") or "DROP"
282 function defaults.output(self)
283 return self:get("output") or "DROP"
288 function zone.__init__(self, z)
289 if uci_r:get("firewall", z) == "zone" then
291 self.data = uci_r:get_all("firewall", z)
293 uci_r:foreach("firewall", "zone",
296 self.sid = s['.name']
304 function zone.get(self, opt)
305 return _get("firewall", self.sid, opt)
308 function zone.set(self, opt, val)
309 return _set("firewall", self.sid, opt, val)
312 function zone.masq(self)
313 return (self:get("masq") == "1")
316 function zone.name(self)
317 return self:get("name")
320 function zone.network(self)
321 return self:get("network")
324 function zone.input(self)
325 return self:get("input") or "DROP"
328 function zone.forward(self)
329 return self:get("forward") or "DROP"
332 function zone.output(self)
333 return self:get("output") or "DROP"
336 function zone.add_network(self, net)
337 if uci_r:get("network", net) == "interface" then
341 for n in _strlist(self:get("network") or self:get("name")) do
350 self:set("network", table.concat(nets, " "))
352 self:set("network", " ")
357 function zone.del_network(self, net)
361 for n in _strlist(self:get("network") or self:get("name")) do
368 self:set("network", table.concat(nets, " "))
370 self:set("network", " ")
374 function zone.get_networks(self)
378 for n in _strlist(self:get("network") or self:get("name")) do
385 function zone.get_forwardings_by(self, what)
386 local name = self:name()
389 uci_r:foreach("firewall", "forwarding",
391 if s.src and s.dest and s[what] == name then
392 forwards[#forwards+1] = forwarding(s['.name'])
399 function zone.add_forwarding_to(self, dest)
402 for _, forward in ipairs(self:get_forwardings_by('src')) do
403 if forward:dest() == dest then
409 if not exist and dest ~= self:name() then
410 local s = uci_r:section("firewall", "forwarding", nil, {
415 return s and forwarding(s)
419 function zone.add_forwarding_from(self, src)
422 for _, forward in ipairs(self:get_forwardings_by('dest')) do
423 if forward:src() == src then
429 if not exist and src ~= self:name() then
430 local s = uci_r:section("firewall", "forwarding", nil, {
435 return s and forwarding(s)
439 function zone.del_forwardings_by(self, what)
440 local name = self:name()
442 uci_r:foreach("firewall", "forwarding",
444 if s.src and s.dest and s[what] == name then
445 uci_r:delete("firewall", s['.name'])
450 function zone.add_redirect(self, options)
451 options = options or { }
452 options.src = self:name()
454 local s = uci_r:section("firewall", "redirect", nil, options)
455 return s and redirect(s)
458 function zone.add_rule(self, options)
459 options = options or { }
460 options.src = self:name()
462 local s = uci_r:section("firewall", "rule", nil, options)
466 function zone.get_color(self)
467 if self and self:name() == "lan" then
469 elseif self and self:name() == "wan" then
472 math.randomseed(lmo.hash(self:name()))
474 local r = math.random(128)
475 local g = math.random(128)
479 if ( r + g ) < 128 then
485 local b = min + math.floor( math.random() * ( max - min ) )
487 return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
494 forwarding = utl.class()
495 function forwarding.__init__(self, f)
499 function forwarding.src(self)
500 return uci_r:get("firewall", self.sid, "src")
503 function forwarding.dest(self)
504 return uci_r:get("firewall", self.sid, "dest")
507 function forwarding.src_zone(self)
508 return zone(self:src())
511 function forwarding.dest_zone(self)
512 return zone(self:dest())
517 function rule.__init__(self, f)
521 function rule.get(self, opt)
522 return _get("firewall", self.sid, opt)
525 function rule.set(self, opt, val)
526 return _set("firewall", self.sid, opt, val)
529 function rule.src(self)
530 return uci_r:get("firewall", self.sid, "src")
533 function rule.dest(self)
534 return uci_r:get("firewall", self.sid, "dest")
537 function rule.src_zone(self)
538 return zone(self:src())
541 function rule.dest_zone(self)
542 return zone(self:dest())
546 redirect = utl.class()
547 function redirect.__init__(self, f)
551 function redirect.get(self, opt)
552 return _get("firewall", self.sid, opt)
555 function redirect.set(self, opt, val)
556 return _set("firewall", self.sid, opt, val)
559 function redirect.src(self)
560 return uci_r:get("firewall", self.sid, "src")
563 function redirect.dest(self)
564 return uci_r:get("firewall", self.sid, "dest")
567 function redirect.src_zone(self)
568 return zone(self:src())
571 function redirect.dest_zone(self)
572 return zone(self:dest())