#!/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.policy' for i, action in ipairs({'disable', 'enable'}) do for i, policy in ipairs(params[string.sub(action, 1, 1)]) do policyset = policyset or awall.policy.PolicySet.new(params.i, params.I) policyset[action](policyset, policy, confdir, import) end end if policyset then os.exit() end if mode == 'l' then for name, status in awall.policy.PolicySet.new(params.i, params.I):list() do print(name, status) end os.exit() end require 'awall' require 'awall.iptables' awall.loadmodules(basedir) config = awall.Config.new(params.i, params.I) 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: ') 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