diff options
-rw-r--r-- | libs/core/luasrc/model/firewall.lua | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/libs/core/luasrc/model/firewall.lua b/libs/core/luasrc/model/firewall.lua new file mode 100644 index 0000000000..c1a8a45c79 --- /dev/null +++ b/libs/core/luasrc/model/firewall.lua @@ -0,0 +1,309 @@ +--[[ +LuCI - Firewall model + +Copyright 2009 Jo-Philipp Wich <xm@subsignal.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +local type, pairs, ipairs, table, luci, math + = type, pairs, ipairs, table, luci, math + +local lmo = require "lmo" +local utl = require "luci.util" +local uct = require "luci.model.uci.bind" + +module "luci.model.firewall" + + +local ub = uct.bind("firewall") + +function init(cursor) + if cursor then + cursor:unload("firewall") + cursor:load("firewall") + ub:init(cursor) + end +end + +function add_zone(n) + if n then + local z = ub.uci:section("firewall", "zone", nil, { + name = n, + network = " ", + input = defaults:input() or "DROP", + forward = defaults:forward() or "DROP", + output = defaults:output() or "DROP" + }) + + return z and zone(z) + end +end + +function get_zone(n) + local z + ub.uci: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 + +function get_zones() + local zones = { } + ub.uci:foreach("firewall", "zone", + function(s) + if s.name then + zones[#zones+1] = zone(s['.name']) + end + end) + return zones +end + +function get_zones_by_network(net) + local zones = { } + ub.uci:foreach("firewall", "zone", + function(s) + if s.name then + local n + for _, n in ipairs(ub:list(s.network or s.name)) do + if n == net then + zones[#zones+1] = zone(s['.name']) + return true + end + end + end + end) + return zones +end + +function del_zone(n) + local r = false + ub.uci:foreach("firewall", "zone", + function(s) + if n and s.name == n then + r = ub.uci:delete("firewall", s['.name']) + return false + end + end) + if r then + ub.uci:foreach("firewall", "rule", + function(s) + if s.src == n or s.dest == n then + ub.uci:delete("firewall", s['.name']) + end + end) + ub.uci:foreach("firewall", "redirect", + function(s) + if s.src == n then + ub.uci:delete("firewall", s['.name']) + end + end) + ub.uci:foreach("firewall", "forwarding", + function(s) + if s.src == n then + ub.uci:delete("firewall", s['.name']) + end + end) + end + return r +end + +function del_network(net) + local z + if net then + for _, z in ipairs(get_zones()) do + z:del_network(net) + end + end +end + + +defaults = ub:usection("defaults") +defaults:property_bool("syn_flood") +defaults:property_bool("drop_invalid") +defaults:property("input") +defaults:property("forward") +defaults:property("output") + + +zone = ub:section("zone") +zone:property_bool("masq") +zone:property("name") +zone:property("network") +zone:property("input") +zone:property("forward") +zone:property("output") + +function zone.add_network(self, net) + if ub.uci:get("network", net) == "interface" then + local networks = ub:list(self:network() or self:name(), net) + if #networks > 0 then + self:network(table.concat(networks, " ")) + else + self:network(" ") + end + end +end + +function zone.del_network(self, net) + local networks = ub:list(self:network() or self:name(), nil, net) + if #networks > 0 then + self:network(table.concat(networks, " ")) + else + self:network(" ") + end +end + +function zone.get_networks(self) + return ub:list(self:network() or self:name()) +end + +function zone.get_forwardings_by(self, what) + local name = self:name() + local forwards = { } + ub.uci: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, with_mtu_fix) + 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() then + local s = ub.uci:section("firewall", "forwarding", nil, { + src = self:name(), + dest = dest, + mtu_fix = with_mtu_fix and true or false + }) + return s and forwarding(s) + end +end + +function zone.add_forwarding_from(self, src, with_mtu_fix) + 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() then + local s = ub.uci:section("firewall", "forwarding", nil, { + src = src, + dest = self:name(), + mtu_fix = with_mtu_fix and true or false + }) + return s and forwarding(s) + end +end + +function zone.add_redirect(self, options) + options = options or { } + options.src = self:name() + local s = ub.uci: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 = ub.uci: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(lmo.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 = ub:section("forwarding") +forwarding:property_bool("mtu_fix") +forwarding:property("src") +forwarding:property("dest") + +function forwarding.src_zone(self) + return zone(self:src()) +end + +function forwarding.dest_zone(self) + return zone(self:dest()) +end + + +rule = ub:section("rule") +rule:property("src") +rule:property("src_ip") +rule:property("src_mac") +rule:property("src_port") +rule:property("dest") +rule:property("dest_ip") +rule:property("dest_port") +rule:property("proto") +rule:property("target") + +function rule.src_zone(self) + return zone(self:src()) +end + + +redirect = ub:section("redirect") +redirect:property("src") +redirect:property("src_ip") +redirect:property("src_mac") +redirect:property("src_port") +redirect:property("src_dport") +redirect:property("dest_ip") +redirect:property("dest_port") +redirect:property("proto") + +function redirect.src_zone(self) + return zone(self:src()) +end + |