diff options
-rw-r--r-- | awall/host.lua | 14 | ||||
-rw-r--r-- | awall/init.lua | 19 | ||||
-rw-r--r-- | awall/ipset.lua | 8 | ||||
-rw-r--r-- | awall/model.lua | 37 | ||||
-rw-r--r-- | awall/modules/filter.lua | 23 | ||||
-rw-r--r-- | awall/modules/nat.lua | 18 | ||||
-rw-r--r-- | awall/modules/notrack.lua | 8 |
7 files changed, 71 insertions, 56 deletions
diff --git a/awall/host.lua b/awall/host.lua index 4b12696..be1dc61 100644 --- a/awall/host.lua +++ b/awall/host.lua @@ -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] diff --git a/awall/init.lua b/awall/init.lua index 7ee4e69..ecf983c 100644 --- a/awall/init.lua +++ b/awall/init.lua @@ -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 diff --git a/awall/ipset.lua b/awall/ipset.lua index 79b4d4c..68e7293 100644 --- a/awall/ipset.lua +++ b/awall/ipset.lua @@ -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 diff --git a/awall/model.lua b/awall/model.lua index fc5be80..b902787 100644 --- a/awall/model.lua +++ b/awall/model.lua @@ -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 diff --git a/awall/modules/filter.lua b/awall/modules/filter.lua index 37d6807..b851234 100644 --- a/awall/modules/filter.lua +++ b/awall/modules/filter.lua @@ -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(), diff --git a/awall/modules/nat.lua b/awall/modules/nat.lua index 05209c5..abe2630 100644 --- a/awall/modules/nat.lua +++ b/awall/modules/nat.lua @@ -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 diff --git a/awall/modules/notrack.lua b/awall/modules/notrack.lua index 3a2d1ee..58039f2 100644 --- a/awall/modules/notrack.lua +++ b/awall/modules/notrack.lua @@ -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 |