summaryrefslogtreecommitdiffstats
path: root/awall/init.lua
blob: 04c2fc4a279f6fe0d2d91ccc6adf1f2df3b6c191 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
--[[
Alpine Wall main module
Copyright (C) 2012-2013 Kaarle Ritvanen
See LICENSE file for license details
]]--

module(..., package.seeall)

require 'lfs'
require 'stringy'

require 'awall.dependency'
require 'awall.ipset'
require 'awall.iptables'
require 'awall.model'
require 'awall.object'
require 'awall.optfrag'
require 'awall.policy'
require 'awall.util'

local optfrag = awall.optfrag


local events
local procorder
local achains

function loadmodules(path)
   events = {}
   achains = {}

   local function readmetadata(mod)
      local export = mod.export or {}
      for name, target in pairs(export) do events[name] = target end

      for name, opts in pairs(mod.achains or {}) do
	 assert(not achains[name])
	 achains[name] = opts
      end

      return awall.util.keys(export)
   end

   readmetadata(model)

   local cdir = lfs.currentdir()
   if path then lfs.chdir(path) end

   local modules = {}
   for modfile in lfs.dir((path or '/usr/share/lua/5.1')..'/awall/modules') do
      if stringy.endswith(modfile, '.lua') then
	 table.insert(modules, 'awall.modules.'..string.sub(modfile, 1, -5))
      end
   end
   table.sort(modules)

   local imported = {}
   for i, name in ipairs(modules) do
      require(name)
      awall.util.extend(imported, readmetadata(package.loaded[name]))
   end

   lfs.chdir(cdir)

   events['%modules'] = {before=imported}
   procorder = awall.dependency.order(events)
end

function loadclass(path)
   assert(string.sub(path, 1, 1) ~= '%')
   return events[path] and events[path].class
end


PolicySet = policy.PolicySet


Config = object.class()

function Config:init(policyconfig)

   self.objects = policyconfig:expand()
   self.iptables = iptables.IPTables.new()

   local acfrags = {}

   local function insertrules(trules)
      for i, trule in ipairs(trules) do
	 local t = self.iptables.config[trule.family][trule.table][trule.chain]
	 local opts = (trule.opts and trule.opts..' ' or '')..'-j '..trule.target

	 local acfrag = {family=trule.family,
			 table=trule.table,
			 chain=trule.target}
	 acfrags[optfrag.location(acfrag)] = acfrag

	 if trule.position == 'prepend' then
	    table.insert(t, 1, opts)
	 else
	    table.insert(t, opts)
	 end
      end
   end

   for i, path in ipairs(procorder) do
      if string.sub(path, 1, 1) ~= '%' then
	 local objs = self.objects[path]
	 if objs then
	    for k, v in pairs(objs) do
	       objs[k] = events[path].class.morph(
		  v,
		  self,
		  path..' '..k..' ('..policyconfig.source[path][k]..')'
	       )
	    end
	 end
      end
   end

   for i, event in ipairs(procorder) do
      if string.sub(event, 1, 1) == '%' then
	 local r = events[event].rules
	 if r then
	    if type(r) == 'function' then r = r(self.objects) end
	    assert(type(r) == 'table')
	    insertrules(r)
	 end
      elseif self.objects[event] then
	 for i, rule in ipairs(self.objects[event]) do
	    insertrules(rule:trules())
	 end
      end
   end

   local ofrags = {}
   for k, v in pairs(acfrags) do table.insert(ofrags, v) end
   insertrules(optfrag.combinations(achains, ofrags))

   self.ipset = ipset.IPSet.new(self.objects.ipset)
end

function Config:print()
   self.ipset:print()
   print()
   self.iptables:print()
end

function Config:dump(dir)
   self.ipset:dump(dir or '/etc/ipset.d')
   self.iptables:dump(dir or '/etc/iptables')
end

function Config:test()
   self.ipset:create()
   self.iptables:test()
end

function Config:activate()
   self:test()
   self.iptables:activate()
end