libs/core: add luci.model.firewall, oop abstraction for uci firewall

This commit is contained in:
Jo-Philipp Wich 2009-10-08 00:14:07 +00:00
parent 6ef4b7f7e8
commit 470184bd57

View file

@ -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