123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- -- Copyright 2009 Jo-Philipp Wich <jow@openwrt.org>
- -- Licensed to the public under the Apache License 2.0.
- local type, pairs, ipairs, table, luci, math
- = type, pairs, ipairs, table, luci, math
- local tpl = require "luci.template.parser"
- local utl = require "luci.util"
- local uci = require "luci.model.uci"
- module "luci.model.firewall"
- local uci_r, uci_s
- function _valid_id(x)
- return (x and #x > 0 and x:match("^[a-zA-Z0-9_]+$"))
- end
- function _get(c, s, o)
- return uci_r:get(c, s, o)
- end
- function _set(c, s, o, v)
- if v ~= nil then
- if type(v) == "boolean" then v = v and "1" or "0" end
- return uci_r:set(c, s, o, v)
- else
- return uci_r:delete(c, s, o)
- end
- end
- function init(cursor)
- uci_r = cursor or uci_r or uci.cursor()
- uci_s = uci_r:substate()
- return _M
- end
- function save(self, ...)
- uci_r:save(...)
- uci_r:load(...)
- end
- function commit(self, ...)
- uci_r:commit(...)
- uci_r:load(...)
- end
- function get_defaults()
- return defaults()
- end
- function new_zone(self)
- local name = "newzone"
- local count = 1
- while self:get_zone(name) do
- count = count + 1
- name = "newzone%d" % count
- end
- return self:add_zone(name)
- end
- function add_zone(self, n)
- if _valid_id(n) and not self:get_zone(n) then
- local d = defaults()
- local z = uci_r:section("firewall", "zone", nil, {
- name = n,
- network = " ",
- input = d:input() or "DROP",
- forward = d:forward() or "DROP",
- output = d:output() or "DROP"
- })
- return z and zone(z)
- end
- end
- function get_zone(self, n)
- if uci_r:get("firewall", n) == "zone" then
- return zone(n)
- else
- local z
- uci_r:foreach("firewall", "zone",
- function(s)
- if n and s.name == n then
- z = s['.name']
- return false
- end
- end)
- return z and zone(z)
- end
- end
- function get_zones(self)
- local zones = { }
- local znl = { }
- uci_r:foreach("firewall", "zone",
- function(s)
- if s.name then
- znl[s.name] = zone(s['.name'])
- end
- end)
- local z
- for z in utl.kspairs(znl) do
- zones[#zones+1] = znl[z]
- end
- return zones
- end
- function get_zone_by_network(self, net)
- local z
- uci_r:foreach("firewall", "zone",
- function(s)
- if s.name and net then
- local n
- for n in utl.imatch(s.network or s.name) do
- if n == net then
- z = s['.name']
- return false
- end
- end
- end
- end)
- return z and zone(z)
- end
- function del_zone(self, n)
- local r = false
- if uci_r:get("firewall", n) == "zone" then
- local z = uci_r:get("firewall", n, "name")
- r = uci_r:delete("firewall", n)
- n = z
- else
- uci_r:foreach("firewall", "zone",
- function(s)
- if n and s.name == n then
- r = uci_r:delete("firewall", s['.name'])
- return false
- end
- end)
- end
- if r then
- uci_r:foreach("firewall", "rule",
- function(s)
- if s.src == n or s.dest == n then
- uci_r:delete("firewall", s['.name'])
- end
- end)
- uci_r:foreach("firewall", "redirect",
- function(s)
- if s.src == n or s.dest == n then
- uci_r:delete("firewall", s['.name'])
- end
- end)
- uci_r:foreach("firewall", "forwarding",
- function(s)
- if s.src == n or s.dest == n then
- uci_r:delete("firewall", s['.name'])
- end
- end)
- end
- return r
- end
- function rename_zone(self, old, new)
- local r = false
- if _valid_id(new) and not self:get_zone(new) then
- uci_r:foreach("firewall", "zone",
- function(s)
- if old and s.name == old then
- if not s.network then
- uci_r:set("firewall", s['.name'], "network", old)
- end
- uci_r:set("firewall", s['.name'], "name", new)
- r = true
- return false
- end
- end)
- if r then
- uci_r:foreach("firewall", "rule",
- function(s)
- if s.src == old then
- uci_r:set("firewall", s['.name'], "src", new)
- end
- if s.dest == old then
- uci_r:set("firewall", s['.name'], "dest", new)
- end
- end)
- uci_r:foreach("firewall", "redirect",
- function(s)
- if s.src == old then
- uci_r:set("firewall", s['.name'], "src", new)
- end
- if s.dest == old then
- uci_r:set("firewall", s['.name'], "dest", new)
- end
- end)
- uci_r:foreach("firewall", "forwarding",
- function(s)
- if s.src == old then
- uci_r:set("firewall", s['.name'], "src", new)
- end
- if s.dest == old then
- uci_r:set("firewall", s['.name'], "dest", new)
- end
- end)
- end
- end
- return r
- end
- function del_network(self, net)
- local z
- if net then
- for _, z in ipairs(self:get_zones()) do
- z:del_network(net)
- end
- end
- end
- defaults = utl.class()
- function defaults.__init__(self)
- uci_r:foreach("firewall", "defaults",
- function(s)
- self.sid = s['.name']
- return false
- end)
- self.sid = self.sid or uci_r:section("firewall", "defaults", nil, { })
- end
- function defaults.get(self, opt)
- return _get("firewall", self.sid, opt)
- end
- function defaults.set(self, opt, val)
- return _set("firewall", self.sid, opt, val)
- end
- function defaults.syn_flood(self)
- return (self:get("syn_flood") == "1")
- end
- function defaults.drop_invalid(self)
- return (self:get("drop_invalid") == "1")
- end
- function defaults.input(self)
- return self:get("input") or "DROP"
- end
- function defaults.forward(self)
- return self:get("forward") or "DROP"
- end
- function defaults.output(self)
- return self:get("output") or "DROP"
- end
- zone = utl.class()
- function zone.__init__(self, z)
- if uci_r:get("firewall", z) == "zone" then
- self.sid = z
- self.data = uci_r:get_all("firewall", z)
- else
- uci_r:foreach("firewall", "zone",
- function(s)
- if s.name == z then
- self.sid = s['.name']
- self.data = s
- return false
- end
- end)
- end
- end
- function zone.get(self, opt)
- return _get("firewall", self.sid, opt)
- end
- function zone.set(self, opt, val)
- return _set("firewall", self.sid, opt, val)
- end
- function zone.masq(self)
- return (self:get("masq") == "1")
- end
- function zone.name(self)
- return self:get("name")
- end
- function zone.network(self)
- return self:get("network")
- end
- function zone.input(self)
- return self:get("input") or defaults():input() or "DROP"
- end
- function zone.forward(self)
- return self:get("forward") or defaults():forward() or "DROP"
- end
- function zone.output(self)
- return self:get("output") or defaults():output() or "DROP"
- end
- function zone.add_network(self, net)
- if uci_r:get("network", net) == "interface" then
- local nets = { }
- local n
- for n in utl.imatch(self:get("network") or self:get("name")) do
- if n ~= net then
- nets[#nets+1] = n
- end
- end
- nets[#nets+1] = net
- _M:del_network(net)
- self:set("network", table.concat(nets, " "))
- end
- end
- function zone.del_network(self, net)
- local nets = { }
- local n
- for n in utl.imatch(self:get("network") or self:get("name")) do
- if n ~= net then
- nets[#nets+1] = n
- end
- end
- if #nets > 0 then
- self:set("network", table.concat(nets, " "))
- else
- self:set("network", " ")
- end
- end
- function zone.get_networks(self)
- local nets = { }
- local n
- for n in utl.imatch(self:get("network") or self:get("name")) do
- nets[#nets+1] = n
- end
- return nets
- end
- function zone.clear_networks(self)
- self:set("network", " ")
- end
- function zone.get_forwardings_by(self, what)
- local name = self:name()
- local forwards = { }
- uci_r:foreach("firewall", "forwarding",
- function(s)
- if s.src and s.dest and s[what] == name then
- forwards[#forwards+1] = forwarding(s['.name'])
- end
- end)
- return forwards
- end
- function zone.add_forwarding_to(self, dest)
- local exist, forward
- for _, forward in ipairs(self:get_forwardings_by('src')) do
- if forward:dest() == dest then
- exist = true
- break
- end
- end
- if not exist and dest ~= self:name() and _valid_id(dest) then
- local s = uci_r:section("firewall", "forwarding", nil, {
- src = self:name(),
- dest = dest
- })
- return s and forwarding(s)
- end
- end
- function zone.add_forwarding_from(self, src)
- local exist, forward
- for _, forward in ipairs(self:get_forwardings_by('dest')) do
- if forward:src() == src then
- exist = true
- break
- end
- end
- if not exist and src ~= self:name() and _valid_id(src) then
- local s = uci_r:section("firewall", "forwarding", nil, {
- src = src,
- dest = self:name()
- })
- return s and forwarding(s)
- end
- end
- function zone.del_forwardings_by(self, what)
- local name = self:name()
- uci_r:delete_all("firewall", "forwarding",
- function(s)
- return (s.src and s.dest and s[what] == name)
- end)
- end
- function zone.add_redirect(self, options)
- options = options or { }
- options.src = self:name()
- local s = uci_r:section("firewall", "redirect", nil, options)
- return s and redirect(s)
- end
- function zone.add_rule(self, options)
- options = options or { }
- options.src = self:name()
- local s = uci_r:section("firewall", "rule", nil, options)
- return s and rule(s)
- end
- function zone.get_color(self)
- if self and self:name() == "lan" then
- return "#90f090"
- elseif self and self:name() == "wan" then
- return "#f09090"
- elseif self then
- math.randomseed(tpl.hash(self:name()))
- local r = math.random(128)
- local g = math.random(128)
- local min = 0
- local max = 128
- if ( r + g ) < 128 then
- min = 128 - r - g
- else
- max = 255 - r - g
- end
- local b = min + math.floor( math.random() * ( max - min ) )
- return "#%02x%02x%02x" % { 0xFF - r, 0xFF - g, 0xFF - b }
- else
- return "#eeeeee"
- end
- end
- forwarding = utl.class()
- function forwarding.__init__(self, f)
- self.sid = f
- end
- function forwarding.src(self)
- return uci_r:get("firewall", self.sid, "src")
- end
- function forwarding.dest(self)
- return uci_r:get("firewall", self.sid, "dest")
- end
- function forwarding.src_zone(self)
- local z = zone(self:src())
- return z.sid and z
- end
- function forwarding.dest_zone(self)
- local z = zone(self:dest())
- return z.sid and z
- end
- rule = utl.class()
- function rule.__init__(self, f)
- self.sid = f
- end
- function rule.get(self, opt)
- return _get("firewall", self.sid, opt)
- end
- function rule.set(self, opt, val)
- return _set("firewall", self.sid, opt, val)
- end
- function rule.src(self)
- return uci_r:get("firewall", self.sid, "src")
- end
- function rule.dest(self)
- return uci_r:get("firewall", self.sid, "dest")
- end
- function rule.src_zone(self)
- return zone(self:src())
- end
- function rule.dest_zone(self)
- return zone(self:dest())
- end
- redirect = utl.class()
- function redirect.__init__(self, f)
- self.sid = f
- end
- function redirect.get(self, opt)
- return _get("firewall", self.sid, opt)
- end
- function redirect.set(self, opt, val)
- return _set("firewall", self.sid, opt, val)
- end
- function redirect.src(self)
- return uci_r:get("firewall", self.sid, "src")
- end
- function redirect.dest(self)
- return uci_r:get("firewall", self.sid, "dest")
- end
- function redirect.src_zone(self)
- return zone(self:src())
- end
- function redirect.dest_zone(self)
- return zone(self:dest())
- end
|