init.lua 3.47 KB
Newer Older
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
1 2
--[[
Alpine Wall main module
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
3
Copyright (C) 2012-2016 Kaarle Ritvanen
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
4
See LICENSE file for license details
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
5 6 7
]]--


8
local M = {}
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
9

10 11 12 13 14 15
local class = require('awall.class')
local resolve = require('awall.dependency')
local IPSet = require('awall.ipset')
local IPTables = require('awall.iptables').IPTables
local optfrag = require('awall.optfrag')
M.PolicySet = require('awall.policy')
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
16

17
local util = require('awall.util')
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
18
local extend = util.extend
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
19

20

21 22 23
local posix = require('posix')
local chdir = posix.chdir

24
local endswith = require('stringy').endswith
25

Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
26

27
local events
28
local procorder
29
local achains
30

31
function M.loadmodules(path)
32
   events = {}
33
   achains = {}
34 35

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

Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
39
      extend(achains, mod.achains)
40

41
      return util.keys(export)
42 43
   end

44
   readmetadata(require('awall.model'))
45

46 47
   local cdir = posix.getcwd()
   if path then assert(chdir(path)) end
48

49
   local modules = {}
50 51 52
   for _, modfile in ipairs(
      posix.dir((path or '/usr/share')..'/awall/modules')
   ) do
53
      if stringy.endswith(modfile, '.lua') then
54
	 table.insert(modules, 'awall.modules.'..modfile:sub(1, -5))
55
      end
56
   end
57
   table.sort(modules)
58 59

   local imported = {}
60
   for i, name in ipairs(modules) do
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
61
      extend(imported, readmetadata(require(name)))
62
   end
63

64
   assert(chdir(cdir))
65

66
   events['%modules'] = {before=imported}
67
   procorder = resolve(events)
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
68 69
end

70
function M.loadclass(path)
71
   assert(path:sub(1, 1) ~= '%')
72 73 74
   return events[path] and events[path].class
end

Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
75

76
M.Config = class()
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
77

78
function M.Config:init(policyconfig)
79

80
   self.objects = policyconfig:expand()
81
   self.iptables = IPTables()
82

83 84
   local acfrags = {}

85 86 87
   local function insertrules(trules)
      for i, trule in ipairs(trules) do
	 local t = self.iptables.config[trule.family][trule.table][trule.chain]
88 89 90 91 92 93 94 95 96 97
	 local opts = optfrag.command(trule)

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

99
	 if trule.position == 'prepend' then
100
	    table.insert(t, 1, opts)
101
	 else
102
	    table.insert(t, opts)
103
	 end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
104 105 106
      end
   end

107
   for i, path in ipairs(procorder) do
108
      if path:sub(1, 1) ~= '%' then
109 110 111
	 local objs = self.objects[path]
	 if objs then
	    for k, v in pairs(objs) do
112
	       objs[k] = events[path].class.morph(
113 114 115 116 117
		  v,
		  self,
		  path..' '..k..' ('..policyconfig.source[path][k]..')'
	       )
	    end
118 119 120
	 end
      end
   end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
121

122
   for i, event in ipairs(procorder) do
123
      if event:sub(1, 1) == '%' then
124 125 126
	 local r = events[event].rules
	 if r then
	    if type(r) == 'function' then r = r(self.objects) end
127 128 129 130
	    if r then
	       assert(type(r) == 'table')
	       insertrules(r)
	    end
131 132 133
	 end
      elseif self.objects[event] then
	 for i, rule in ipairs(self.objects[event]) do
134 135
	    insertrules(rule:trules())
	 end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
136 137
      end
   end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
138

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

143
   self.ipset = IPSet(self.objects.ipset)
144
end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
145

146
function M.Config:print()
147
   self.ipset:print()
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
148
   io.write('\n')
149 150 151
   self.iptables:print()
end

152
function M.Config:dump(dir)
153
   self.ipset:dump(dir and dir..'/ipset-' or '/etc/ipset.d/')
154
   self.iptables:dump(dir or '/etc/iptables')
155
end
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
156

157
function M.Config:test()
158 159
   self.ipset:create()
   self.iptables:test()
Kaarle Ritvanen's avatar
Kaarle Ritvanen committed
160
end
161

162
function M.Config:activate()
163 164 165
   self:test()
   self.iptables:activate()
end
166 167 168


return M