Commit 940c970d authored by Kaarle Ritvanen's avatar Kaarle Ritvanen

prepend object identifier and file name to error messages

parent 563a3fc1
......@@ -11,17 +11,17 @@ local familypatterns = {inet='%d[%.%d/]+',
inet6='[:%x/]+',
domain='[%a-][%.%w-]*'}
local function getfamily(addr)
local function getfamily(addr, context)
for k, v in pairs(familypatterns) do
if string.match(addr, '^'..v..'$') then return k end
end
error('Malformed host specification: '..addr)
context:error('Malformed host specification: '..addr)
end
local dnscache = {}
function resolve(host)
local family = getfamily(host)
function resolve(host, context)
local family = getfamily(host, context)
if family == 'domain' then
if not dnscache[host] then
......@@ -36,12 +36,14 @@ function resolve(host)
else family = nil end
if family then
assert(getfamily(addr) == family)
assert(getfamily(addr, context) == family)
table.insert(dnscache[host], {family, addr})
end
end
end
if not dnscache[host][1] then error('Invalid host name: '..host) end
if not dnscache[host][1] then
context:error('Invalid host name: '..host)
end
end
return dnscache[host]
......
......@@ -64,6 +64,17 @@ function Config:init(policyconfig)
self.input = policyconfig:expand()
self.iptables = iptables.IPTables.new()
local function morph(path, cls)
local objs = self.input[path]
if objs then
for k, v in pairs(objs) do
objs[k] = cls.morph(v,
self,
path..' '..k..' ('..policyconfig.source[path][k]..')')
end
end
end
local function insertrules(trules)
for i, trule in ipairs(trules) do
local t = self.iptables.config[trule.family][trule.table][trule.chain]
......@@ -79,12 +90,7 @@ function Config:init(policyconfig)
if defrules[phase] then insertrules(defrules[phase]) end
end
for i, path in ipairs(procorder) do
if self.input[path] then
util.map(self.input[path],
function(obj) return classmap[path].morph(obj, self) end)
end
end
for i, path in ipairs(procorder) do morph(path, classmap[path]) end
insertdefrules('pre')
......@@ -97,6 +103,7 @@ function Config:init(policyconfig)
insertdefrules('post-'..path)
end
morph('ipset', awall.model.ConfigObject)
self.ipset = ipset.IPSet.new(self.input.ipset)
end
......
......@@ -16,11 +16,11 @@ function IPSet:init(config) self.config = config end
function IPSet:commands()
local res = {}
if self.config then
for name, params in pairs(self.config) do
if not params.type then error('Type not defined for set '..name) end
if not params.family then error('Family not defined for set '..name) end
for name, ipset in pairs(self.config) do
if not ipset.type then ipset:error('Type not defined') end
if not ipset.family then ipset:error('Family not defined') end
table.insert(res,
'create '..name..' '..params.type..' family '..params.family..'\n')
'create '..name..' '..ipset.type..' family '..ipset.family..'\n')
end
end
return res
......
......@@ -21,13 +21,20 @@ class = awall.object.class
ConfigObject = class(awall.object.Object)
function ConfigObject:init(context)
function ConfigObject:init(context, location)
if context then
self.context = context
self.root = context.input
end
self.location = location
end
function ConfigObject:create(cls, params)
return cls.morph(params, self.context, self.location)
end
function ConfigObject:error(msg) error(self.location..': '..msg) end
function ConfigObject:trules() return {} end
......@@ -45,7 +52,7 @@ function Zone:optfrags(dir)
if self.addr then
aopts = {}
for i, hostdef in util.listpairs(self.addr) do
for i, addr in ipairs(awall.host.resolve(hostdef)) do
for i, addr in ipairs(awall.host.resolve(hostdef, self)) do
table.insert(aopts,
{family=addr[1],
[aprop]=addr[2],
......@@ -69,8 +76,8 @@ fwzone = Zone.new()
Rule = class(ConfigObject)
function Rule:init(context)
ConfigObject.init(self, context)
function Rule:init(...)
ConfigObject.init(self, unpack(arg))
for i, prop in ipairs({'in', 'out'}) do
self[prop] = self[prop] and util.maplist(self[prop],
......@@ -78,7 +85,7 @@ function Rule:init(context)
if type(z) ~= 'string' then return z end
return z == '_fw' and fwzone or
self.root.zone[z] or
error('Invalid zone: '..z)
self:error('Invalid zone: '..z)
end) or self:defaultzones()
end
......@@ -87,7 +94,7 @@ function Rule:init(context)
self.service = util.maplist(self.service,
function(s)
if type(s) ~= 'string' then return s end
return self.root.service[s] or error('Invalid service: '..s)
return self.root.service[s] or self:error('Invalid service: '..s)
end)
end
end
......@@ -161,7 +168,7 @@ function Rule:servoptfrags()
for i, serv in ipairs(self.service) do
for i, sdef in util.listpairs(serv) do
if not sdef.proto then error('Protocol not defined') end
if not sdef.proto then self:error('Protocol not defined') end
if util.contains({6, 'tcp', 17, 'udp'}, sdef.proto) then
local new = not containskey(ports, sdef.proto)
......@@ -187,7 +194,7 @@ function Rule:servoptfrags()
family = 'inet6'
oname = 'icmpv6-type'
elseif sdef.type then
error('Type specification not valid with '..sdef.proto)
self:error('Type specification not valid with '..sdef.proto)
end
if sdef.type then opts = opts..' --'..oname..' '..sdef.type end
......@@ -217,7 +224,7 @@ function Rule:servoptfrags()
end
function Rule:destoptfrags()
return Zone.morph({addr=self.dest}):optfrags('out')
return self:create(Zone, {addr=self.dest}):optfrags('out')
end
function Rule:table() return 'filter' end
......@@ -227,7 +234,7 @@ function Rule:chain() return nil end
function Rule:position() return 'append' end
function Rule:target()
if not self.action then error('Action not defined') end
if not self.action then self:error('Action not defined') end
return string.upper(self.action)
end
......@@ -276,13 +283,13 @@ function Rule:trules()
if self.ipset then
local ipsetofrags = {}
for i, ipset in util.listpairs(self.ipset) do
if not ipset.name then error('Set name not defined') end
if not ipset.name then self:error('Set name not defined') end
local setdef = self.root.ipset and self.root.ipset[ipset.name]
if not setdef then error('Invalid set name') end
if not setdef then self:error('Invalid set name') end
if not ipset.args then
error('Set direction arguments not defined')
self:error('Set direction arguments not defined')
end
local setopts = '-m set --match-set '..ipset.name..' '
......@@ -290,7 +297,7 @@ function Rule:trules()
if i > 1 then setopts = setopts..',' end
if arg == 'in' then setopts = setopts..'src'
elseif arg == 'out' then setopts = setopts..'dst'
else error('Invalid set direction argument') end
else self:error('Invalid set direction argument') end
end
table.insert(ipsetofrags, {family=setdef.family, opts=setopts})
end
......@@ -306,7 +313,7 @@ function Rule:trules()
setfamilies(res)
tag(res, 'chain', self:chain())
local addrofrags = combinations(Zone.morph({addr=self.src}):optfrags('in'),
local addrofrags = combinations(self:create(Zone, {addr=self.src}):optfrags('in'),
self:destoptfrags())
if addrofrags then
......
......@@ -26,7 +26,7 @@ function Filter:destoptfrags()
if not self.dnat then return ofrags end
ofrags = awall.optfrag.combinations(ofrags, {{family='inet6'}})
local natof = model.Zone.morph({addr=self.dnat}):optfrags('out')
local natof = self:create(model.Zone, {addr=self.dnat}):optfrags('out')
assert(#natof == 1)
table.insert(ofrags, natof[1])
return ofrags
......@@ -37,28 +37,28 @@ function Filter:trules()
if self.dnat then
if not self.dest then
error('Destination address must be specified with DNAT')
self:error('Destination address must be specified with DNAT')
end
if string.find(self.dnat, '/') then
error('DNAT target cannot be a network address')
self:error('DNAT target cannot be a network address')
end
for i, attr in ipairs({'ipsec', 'ipset'}) do
if self[attr] then
error('dnat and '..attr..' options cannot be used simultaneously')
self:error('dnat and '..attr..' options cannot be used simultaneously')
end
end
local dnataddr
for i, addr in ipairs(awall.host.resolve(self.dnat)) do
for i, addr in ipairs(awall.host.resolve(self.dnat, self)) do
if addr[1] == 'inet' then
if dnataddr then
error(self.dnat..' resolves to multiple IPv4 addresses')
self:error(self.dnat..' resolves to multiple IPv4 addresses')
end
dnataddr = addr[2]
end
end
if not dnataddr then
error(self.dnat..' does not resolve to any IPv4 address')
self:error(self.dnat..' does not resolve to any IPv4 address')
end
local dnat = {['ip-range']=dnataddr}
......@@ -66,10 +66,9 @@ function Filter:trules()
dnat[attr] = self[attr]
end
if not awall.classmap.dnat then error('NAT module not installed') end
if not awall.classmap.dnat then self:error('NAT module not installed') end
awall.util.extend(res, awall.classmap.dnat.morph(dnat,
self.context):trules())
awall.util.extend(res, self:create(awall.classmap.dnat, dnat):trules())
end
awall.util.extend(res, model.Rule.trules(self))
......@@ -82,7 +81,7 @@ function Filter:limit()
for i, limit in ipairs({'conn-limit', 'flow-limit'}) do
if self[limit] then
if res then
error('Cannot specify multiple limits for a single filter rule')
self:error('Cannot specify multiple limits for a single filter rule')
end
res = limit
end
......@@ -105,7 +104,7 @@ function Filter:extraoptfrags()
local limit = self:limit()
if limit then
if self.action ~= 'accept' then
error('Cannot specify limit for '..self.action..' filter')
self:error('Cannot specify limit for '..self.action..' filter')
end
local optbase = '-m recent --name '..self:target()
table.insert(res, {chain=self:target(),
......
......@@ -15,11 +15,11 @@ local model = awall.model
local NATRule = model.class(model.Rule)
function NATRule:init(context)
model.Rule.init(self, context)
function NATRule:init(...)
model.Rule.init(self, unpack(arg))
for i, dir in ipairs({'in', 'out'}) do
if awall.util.contains(self[dir], model.fwzone) then
error('NAT rules not allowed for firewall zone')
self:error('NAT rules not allowed for firewall zone')
end
end
end
......@@ -28,7 +28,7 @@ function NATRule:defaultzones() return {nil} end
function NATRule:checkzoneoptfrag(ofrag)
if ofrag[self.params.forbidif] then
error('Cannot specify '..self.params.forbidif..'bound interface for '..self.params.target..' rule')
self:error('Cannot specify '..self.params.forbidif..'bound interface for '..self.params.target..' rule')
end
end
......@@ -46,7 +46,7 @@ function NATRule:chain() return self.params.chain end
function NATRule:target()
if self.action then return model.Rule.target(self) end
if not self['ip-range'] then error('IP range not defined for NAT rule') end
if not self['ip-range'] then self:error('IP range not defined for NAT rule') end
local target = self.params.target..' --to-'..self.params.subject..' '..self['ip-range']
if self['port-range'] then target = target..':'..self['port-range'] end
return target
......@@ -55,8 +55,8 @@ end
local DNATRule = model.class(NATRule)
function DNATRule:init(context)
NATRule.init(self, context)
function DNATRule:init(...)
NATRule.init(self, unpack(arg))
self.params = {forbidif='out', subject='destination',
chain='PREROUTING', target='DNAT'}
end
......@@ -64,8 +64,8 @@ end
local SNATRule = model.class(NATRule)
function SNATRule:init(context)
NATRule.init(self, context)
function SNATRule:init(...)
NATRule.init(self, unpack(arg))
self.params = {forbidif='in', subject='source',
chain='POSTROUTING', target='SNAT'}
end
......
......@@ -15,11 +15,11 @@ local model = awall.model
local NoTrackRule = model.class(model.Rule)
function NoTrackRule:init(context)
model.Rule.init(self, context)
function NoTrackRule:init(...)
model.Rule.init(self, unpack(arg))
for i, dir in ipairs({'in', 'out'}) do
if awall.util.contains(self[dir], model.fwzone) then
error('Connection tracking bypass rules not allowed for firewall zone')
self:error('Connection tracking bypass rules not allowed for firewall zone')
end
end
end
......@@ -28,7 +28,7 @@ function NoTrackRule:defaultzones() return {nil} end
function NoTrackRule:checkzoneoptfrag(ofrag)
if ofrag.out then
error('Cannot specify outbound interface for connection tracking bypass rule')
self:error('Cannot specify outbound interface for connection tracking bypass rule')
end
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment