aboutsummaryrefslogtreecommitdiffstats
path: root/awall-cli
blob: fd155de8b58df2d0499cd3f2d40c7886e501257b (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
#!/usr/bin/lua

--[[
Alpine Wall
Copyright (C) 2012 Kaarle Ritvanen
Licensed under the terms of GPL2
]]--

require 'alt_getopt'
require 'lfs'
require 'signal'
require 'stringy'

short_opts = 'ad:e:Flo:V'
long_opts = {activate='a',
	     disable='d',
	     enable='e',
	     list='l',
	     ['output-dir']='o',
	     verify='V'}

params = {d = {}, e = {}}

if stringy.endswith(arg[0], '/awall-cli') then
   basedir = string.sub(arg[0], 1, -11)
   params.i = {basedir..'/json'}
   params.I = {}

   short_opts = short_opts..'i:I:'
   long_opts['input-dir'] = 'i'
   long_opts['import-path'] = 'I'
end

require 'awall.util'

for switch, value in pairs(alt_getopt.get_opts(arg, short_opts, long_opts)) do
   if awall.util.contains({'a', 'l'}, switch) then mode = switch
   elseif awall.util.contains({'d', 'e', 'i', 'I'}, switch) then
      table.insert(params[switch], value)
   elseif switch == 'F' then fallback = true
   elseif switch == 'o' then
      iptdir = value
      ipsfile = value..'/ipset'
   elseif switch == 'V' then verify = true
   else assert(false) end
end


require 'awall'

policyset = awall.PolicySet.new(params.i, params.I)

for i, action in ipairs({'disable', 'enable'}) do
   for i, policy in ipairs(params[string.sub(action, 1, 1)]) do
      policyset[action](policyset, policy, confdir, import)
      exit = true
   end
end
if exit then os.exit() end

if mode == 'l' then
   for name, status in policyset:list() do print(name, status) end
   os.exit()
end


require 'awall.iptables'
awall.loadmodules(basedir)

config = awall.Config.new(policyset)


if mode == 'a' then

   awall.iptables.backup()

   signal.signal('SIGCHLD',
		 function() if pid and lpc.wait(pid, 1) then os.exit(2) end end)
   for i, sig in ipairs({'INT', 'TERM'}) do
      signal.signal('SIG'..sig, function()
				   interrupted = true
				   io.stdin:close()
				end)
   end

   require 'lpc'
   pid, stdio, stdout = lpc.run(arg[0], '-F')
   stdio:close()
   stdout:close()
   
   config:activate()

   io.stderr:write('New firewall configuration activated\n')
   io.stderr:write('Press RETURN to commit changes permanently: ')
   interrupted = not io.read()

   signal.signal('SIGCHLD', 'default')
   signal.kill(pid, 'SIGTERM')
   lpc.wait(pid)

   if interrupted then
      io.stderr:write('\nActivation canceled, reverting to the old configuration\n')
      awall.iptables.revert()

   else config:dump() end


elseif fallback then

   for i, sig in ipairs({'HUP', 'PIPE'}) do
      signal.signal('SIG'..sig, function() end)
   end

   require 'lsleep'
   lsleep.sleep(10)

   io.stderr:write('\nTimeout, reverting to the old configuration\n')
   awall.iptables.revert()

else
   if verify then config:test() end
   config:dump(iptdir, ipsfile)
end