2013-07-24 18:49:07 +02:00
|
|
|
local utils = require('util.utils')
|
|
|
|
local log = require('util.logger')
|
|
|
|
local settings = require('util.settings')
|
|
|
|
local wifi = require('network.wlanconfig')
|
|
|
|
local uci = require('uci').cursor()
|
2013-04-08 01:20:45 +02:00
|
|
|
|
|
|
|
local M = {}
|
|
|
|
local reconf = {}
|
|
|
|
local wifi
|
|
|
|
local reloadSilent
|
|
|
|
|
2013-07-24 18:49:07 +02:00
|
|
|
M.WWW_CAPTIVE_PATH = '/usr/share/lua/wifibox/www'
|
|
|
|
M.WWW_CAPTIVE_INDICATOR = '/www/.wifibox-inplace'
|
|
|
|
M.WWW_RENAME_NAME = '/www-regular'
|
2013-04-08 01:20:45 +02:00
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
|
|
|
|
2013-04-09 14:37:31 +02:00
|
|
|
local function reloadBit(dlist, itemname)
|
2013-07-24 18:49:07 +02:00
|
|
|
if dlist[itemname] == nil then dlist[itemname] = '' end
|
|
|
|
if dlist[itemname] == '' then dlist[itemname] = 'r'
|
|
|
|
elseif dlist[itemname] == 'c' then dlist[itemname] = 'b'
|
2013-04-09 14:37:31 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
local function commitBit(dlist, itemname)
|
2013-07-24 18:49:07 +02:00
|
|
|
if dlist[itemname] == nil then dlist[itemname] = '' end
|
|
|
|
if dlist[itemname] == '' then dlist[itemname] = 'c'
|
|
|
|
elseif dlist[itemname] == 'r' then dlist[itemname] = 'b'
|
2013-04-09 14:37:31 +02:00
|
|
|
end
|
|
|
|
end
|
2013-07-24 18:49:07 +02:00
|
|
|
local function bothBits(dlist, itemname) dlist[itemname] = 'b' end
|
2013-04-09 14:37:31 +02:00
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
function M.init(wifiInstance, reloadSilent)
|
|
|
|
wifi = wifiInstance
|
|
|
|
silent = reloadSilent or false
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Switch configuration between AP and station modes
|
|
|
|
-- @param components a table with components as keys with operations as values (add or remove)
|
|
|
|
-- Valid components (each with add and rm operation) are: apnet, staticaddr, dhcppool, wwwredir, dnsredir, wwwcaptive, natreflect.
|
|
|
|
-- and additionally: wifiiface/add, network/reload
|
|
|
|
function M.switchConfiguration(components)
|
|
|
|
local dirtyList = {} -- laundry list, add config/script name as key with value c (commit), r (reload) or b (both)
|
|
|
|
|
|
|
|
for k,v in pairs(components) do
|
2013-07-24 18:49:07 +02:00
|
|
|
local fname = k .. '_' .. v
|
|
|
|
if type(reconf[fname]) == 'function' then
|
|
|
|
log:debug("reconfiguring component '" .. k .. "' (" .. v .. ")")
|
2013-04-08 01:20:45 +02:00
|
|
|
reconf[fname](dirtyList)
|
|
|
|
else
|
2013-07-24 18:49:07 +02:00
|
|
|
log:warn("unknown component or action '" .. fname .. "' skipped")
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- first run all commits, then perform reloads
|
|
|
|
for k,v in pairs(dirtyList) do
|
2013-07-24 18:49:07 +02:00
|
|
|
if v == 'c' or v == 'b' then M.commitComponent(k) end
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
for k,v in pairs(dirtyList) do
|
2013-07-24 18:49:07 +02:00
|
|
|
if v == 'r' or v == 'b' then M.reloadComponent(k, silent) end
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.commitComponent(c)
|
2013-07-24 18:49:07 +02:00
|
|
|
log:info("committing component '" .. c .. "'")
|
2013-04-08 01:20:45 +02:00
|
|
|
uci:commit(c)
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.reloadComponent(c, silent)
|
2013-07-24 18:49:07 +02:00
|
|
|
log:info("reloading component '" .. c .. "'")
|
|
|
|
if silent ~= nil and silent then os.execute('/etc/init.d/' .. c .. ' reload &> /dev/null')
|
|
|
|
else os.execute('/etc/init.d/' .. c .. ' reload') end
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
function M.uciTableSet(config, section, options)
|
|
|
|
for k, v in pairs(options) do uci:set(config, section, k, v) end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--[[ Issue '/etc/init.d/network reload' command ]]
|
2013-07-24 18:49:07 +02:00
|
|
|
function reconf.network_reload(dirtyList) reloadBit(dirtyList, 'network') end
|
2013-04-09 14:37:31 +02:00
|
|
|
|
|
|
|
--[[ Issue '/etc/init.d/wireless reload' command ]]
|
2013-07-24 18:49:07 +02:00
|
|
|
function reconf.wireless_reload(dirtyList) reloadBit(dirtyList, 'wireless') end
|
2013-04-08 01:20:45 +02:00
|
|
|
|
|
|
|
--[[ Add wlan interface declaration to /etc/config/network ]]
|
|
|
|
function reconf.wifiiface_add(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:set('network', wifi.NET, 'interface')
|
|
|
|
commitBit(dirtyList, 'network')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--[[ Add/remove access point network ]]
|
|
|
|
function reconf.apnet_add_noreload(dirtyList) reconf.apnet_add(dirtyList, true) end
|
|
|
|
function reconf.apnet_add(dirtyList, noReload)
|
2013-07-27 00:25:43 +02:00
|
|
|
local ourSsid = wifi.getSubstitutedSsid(settings.get('network.ap.ssid'))
|
2013-04-08 01:20:45 +02:00
|
|
|
local sname = nil
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:foreach('wireless', 'wifi-iface', function(s)
|
|
|
|
if s.ssid == ourSsid then sname = s['.name']; return false end
|
2013-04-08 01:20:45 +02:00
|
|
|
end)
|
2013-07-24 18:49:07 +02:00
|
|
|
if sname == nil then sname = uci:add('wireless', 'wifi-iface') end
|
2013-04-08 01:20:45 +02:00
|
|
|
|
2013-07-24 18:49:07 +02:00
|
|
|
M.uciTableSet('wireless', sname, {
|
2013-04-08 01:20:45 +02:00
|
|
|
network = wifi.NET,
|
2013-07-17 22:55:27 +02:00
|
|
|
ssid = ourSsid,
|
2013-07-24 18:49:07 +02:00
|
|
|
encryption = 'none',
|
|
|
|
device = 'radio0',
|
|
|
|
mode = 'ap',
|
2013-04-08 01:20:45 +02:00
|
|
|
})
|
|
|
|
|
2013-07-24 18:49:07 +02:00
|
|
|
commitBit(dirtyList, 'wireless')
|
|
|
|
if noReload == nil or noReload == false then reloadBit(dirtyList, 'network') end
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.apnet_rm(dirtyList)
|
|
|
|
local sname = nil
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:foreach('wireless', 'wifi-iface', function(s)
|
2013-07-27 00:25:43 +02:00
|
|
|
if s.ssid == wifi.getSubstitutedSsid(settings.get('network.ap.ssid')) then sname = s['.name']; return false end
|
2013-04-08 01:20:45 +02:00
|
|
|
end)
|
2013-07-24 18:49:07 +02:00
|
|
|
if sname == nil then return log:info("AP network configuration does not exist, nothing to remove") end
|
|
|
|
uci:delete('wireless', sname)
|
|
|
|
reloadBit(dirtyList, 'network'); commitBit(dirtyList, 'wireless')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--[[ Switch between wireless static IP and DHCP ]]
|
|
|
|
function reconf.staticaddr_add(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:set('network', wifi.NET, 'interface')
|
2013-05-02 16:29:29 +02:00
|
|
|
--TODO: remove ifname on wlan interface?
|
2013-06-17 20:23:00 +02:00
|
|
|
--NOTE: 'type = "bridge"' should -not- be added as this prevents defining a separate dhcp pool (http://wiki.openwrt.org/doc/recipes/routedap)
|
2013-07-24 18:49:07 +02:00
|
|
|
M.uciTableSet('network', wifi.NET, {
|
|
|
|
proto = 'static',
|
2013-07-27 00:25:43 +02:00
|
|
|
ipaddr = settings.get('network.ap.address'),
|
|
|
|
netmask = settings.get('network.ap.netmask')
|
2013-04-09 14:37:31 +02:00
|
|
|
})
|
2013-07-24 18:49:07 +02:00
|
|
|
bothBits(dirtyList, 'network')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
--TODO: replace repeated deletes by M.uciTableDelete
|
|
|
|
function reconf.staticaddr_rm(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:set('network', wifi.NET, 'interface')
|
|
|
|
uci:set('network', wifi.NET, 'proto', 'dhcp')
|
|
|
|
uci:delete('network', wifi.NET, 'ipaddr')
|
|
|
|
uci:delete('network', wifi.NET, 'netmask')
|
|
|
|
--uci:delete('network', wifi.NET, 'type') --do not remove since it is not added anymore
|
|
|
|
bothBits(dirtyList, 'network')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--[[ Add/remove DHCP pool for wireless net ]]
|
|
|
|
function reconf.dhcppool_add(dirtyList)
|
2013-08-16 21:44:54 +02:00
|
|
|
uci:set('dhcp', wifi.NET, 'dhcp') --create section
|
2013-07-29 12:18:39 +02:00
|
|
|
M.uciTableSet('dhcp', wifi.NET, {
|
2013-04-09 14:37:31 +02:00
|
|
|
interface = wifi.NET,
|
2013-07-24 18:49:07 +02:00
|
|
|
start = '100',
|
|
|
|
limit = '150',
|
|
|
|
leasetime = '12h',
|
2013-04-09 14:37:31 +02:00
|
|
|
})
|
2013-07-24 18:49:07 +02:00
|
|
|
commitBit(dirtyList, 'dhcp'); reloadBit(dirtyList, 'dnsmasq')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.dhcppool_rm(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:delete('dhcp', wifi.NET)
|
|
|
|
commitBit(dirtyList, 'dhcp'); reloadBit(dirtyList, 'dnsmasq')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--[[ Add/remove webserver 404 redirection and denial of dirlisting ]]
|
|
|
|
function reconf.wwwredir_add(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:set('uhttpd', 'main', 'error_page', '/www/index.html')
|
|
|
|
uci:set('uhttpd', 'main', 'no_dirlist', '1')
|
|
|
|
bothBits(dirtyList, 'uhttpd')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.wwwredir_rm(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:delete('uhttpd', 'main', 'error_page')
|
|
|
|
uci:delete('uhttpd', 'main', 'no_dirlist')
|
|
|
|
bothBits(dirtyList, 'uhttpd')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--[[ Add/remove redirecton of all DNS requests to self ]]
|
|
|
|
function reconf.dnsredir_add(dirtyList)
|
2013-07-27 00:25:43 +02:00
|
|
|
local redirText = '/#/' .. settings.get('network.ap.address')
|
2013-07-24 18:49:07 +02:00
|
|
|
local sname = utils.getUciSectionName('dhcp', 'dnsmasq')
|
|
|
|
if sname == nil then return log:error("dhcp config does not contain a dnsmasq section") end
|
|
|
|
if uci:get('dhcp', sname, 'address') ~= nil then return log:debug("DNS address redirection already in place, not re-adding", false) end
|
2013-04-08 01:20:45 +02:00
|
|
|
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:set('dhcp', sname, 'address', {redirText})
|
|
|
|
commitBit(dirtyList, 'dhcp'); reloadBit(dirtyList, 'dnsmasq')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.dnsredir_rm(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
local sname = utils.getUciSectionName('dhcp', 'dnsmasq')
|
|
|
|
if sname == nil then return log:error("dhcp config does not contain a dnsmasq section") end
|
2013-04-09 14:37:31 +02:00
|
|
|
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:delete('dhcp', sname, 'address')
|
|
|
|
commitBit(dirtyList, 'dhcp'); reloadBit(dirtyList, 'dnsmasq')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--TODO: handle os.rename() return values (nil+msg on error)
|
|
|
|
function reconf.wwwcaptive_add(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
if utils.exists(M.WWW_CAPTIVE_INDICATOR) then
|
|
|
|
return log:debug("WWW captive directory already in place, not redoing", false)
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
2013-07-24 18:49:07 +02:00
|
|
|
local rv,reason = os.rename('/www', M.WWW_RENAME_NAME)
|
2013-06-17 20:23:00 +02:00
|
|
|
if rv == true then
|
2013-07-24 18:49:07 +02:00
|
|
|
utils.symlink(M.WWW_CAPTIVE_PATH, '/www')
|
2013-04-18 11:30:48 +02:00
|
|
|
return true
|
|
|
|
else
|
2013-07-24 18:49:07 +02:00
|
|
|
return log:error("Could not rename /www to " .. M.WWW_RENAME_NAME .. "(" .. reason .. ")")
|
2013-04-18 11:30:48 +02:00
|
|
|
end
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.wwwcaptive_rm(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
if not utils.exists(M.WWW_CAPTIVE_INDICATOR) then return log:debug("WWW captive directory not in place, not undoing", false) end
|
|
|
|
os.remove('/www')
|
|
|
|
if os.rename(M.WWW_RENAME_NAME, '/www') ~= true then
|
|
|
|
return log:error("Could not rename " .. M.WWW_RENAME_NAME .. " to /www")
|
2013-04-18 11:30:48 +02:00
|
|
|
end
|
|
|
|
return true
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
--[[ Setup/remove NAT reflection to redirect all IPs ]]
|
|
|
|
function reconf.natreflect_add(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:set('firewall', 'portalreflect', 'redirect');
|
|
|
|
M.uciTableSet('firewall', 'portalreflect', {
|
|
|
|
src = 'lan',
|
|
|
|
proto = 'tcp',
|
|
|
|
src_dport = '80',
|
|
|
|
dest_port = '80',
|
2013-07-27 00:25:43 +02:00
|
|
|
dest_ip = settings.get('network.ap.address'),
|
2013-07-24 18:49:07 +02:00
|
|
|
target = 'DNAT'
|
2013-04-08 01:20:45 +02:00
|
|
|
})
|
2013-07-24 18:49:07 +02:00
|
|
|
bothBits(dirtyList, 'firewall')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.natreflect_rm(dirtyList)
|
2013-07-24 18:49:07 +02:00
|
|
|
uci:delete('firewall', 'portalreflect')
|
|
|
|
bothBits(dirtyList, 'firewall')
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return M
|