2013-07-11 10:30:59 +02:00
|
|
|
local config = require("config")
|
2013-07-08 13:43:59 +02:00
|
|
|
local u = require("util.utils")
|
2013-07-17 08:25:24 +02:00
|
|
|
local l = require("util.logger")
|
2013-04-08 01:20:45 +02:00
|
|
|
local uci = require("uci").cursor()
|
|
|
|
|
|
|
|
local M = {}
|
|
|
|
local reconf = {}
|
|
|
|
local wifi
|
|
|
|
local reloadSilent
|
|
|
|
|
2013-07-08 19:02:20 +02:00
|
|
|
M.WWW_CAPTIVE_PATH = "/usr/share/lua/wifibox/www"
|
2013-07-04 17:26:13 +02:00
|
|
|
M.WWW_CAPTIVE_INDICATOR = "/www/.wifibox-inplace"
|
2013-04-08 01:20:45 +02:00
|
|
|
M.WWW_RENAME_NAME = "/www-regular"
|
|
|
|
|
2013-04-18 11:30:48 +02:00
|
|
|
|
|
|
|
|
2013-04-09 14:37:31 +02:00
|
|
|
local function reloadBit(dlist, itemname)
|
|
|
|
if dlist[itemname] == nil then dlist[itemname] = "" end
|
|
|
|
if dlist[itemname] == "" then dlist[itemname] = "r"
|
|
|
|
elseif dlist[itemname] == "c" then dlist[itemname] = "b"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local function commitBit(dlist, itemname)
|
|
|
|
if dlist[itemname] == nil then dlist[itemname] = "" end
|
|
|
|
if dlist[itemname] == "" then dlist[itemname] = "c"
|
|
|
|
elseif dlist[itemname] == "r" then dlist[itemname] = "b"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local function bothBits(dlist, itemname) dlist[itemname] = "b" end
|
|
|
|
|
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
|
|
|
|
local fname = k .. "_" .. v
|
|
|
|
if type(reconf[fname]) == "function" then
|
2013-06-30 19:06:55 +02:00
|
|
|
l:debug("reconfiguring component '" .. k .. "' (" .. v .. ")")
|
2013-04-08 01:20:45 +02:00
|
|
|
reconf[fname](dirtyList)
|
|
|
|
else
|
2013-06-30 19:06:55 +02:00
|
|
|
l: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
|
|
|
|
if v == "c" or v == "b" then M.commitComponent(k) end
|
|
|
|
end
|
|
|
|
for k,v in pairs(dirtyList) do
|
|
|
|
if v == "r" or v == "b" then M.reloadComponent(k, silent) end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.commitComponent(c)
|
2013-06-30 19:06:55 +02:00
|
|
|
l:info("committing component '" .. c .. "'")
|
2013-04-08 01:20:45 +02:00
|
|
|
uci:commit(c)
|
|
|
|
end
|
|
|
|
|
|
|
|
function M.reloadComponent(c, silent)
|
2013-06-30 19:06:55 +02:00
|
|
|
l:info("reloading component '" .. c .. "'")
|
2013-04-08 01:20:45 +02:00
|
|
|
if silent ~= nil and silent then os.execute("/etc/init.d/" .. c .. " reload &> /dev/null")
|
|
|
|
else os.execute("/etc/init.d/" .. c .. " reload") end
|
|
|
|
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-04-09 14:37:31 +02:00
|
|
|
function reconf.network_reload(dirtyList) reloadBit(dirtyList, "network") end
|
|
|
|
|
|
|
|
--[[ Issue '/etc/init.d/wireless reload' command ]]
|
|
|
|
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)
|
|
|
|
uci:set("network", wifi.NET, "interface")
|
2013-04-09 14:37:31 +02:00
|
|
|
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)
|
|
|
|
local sname = nil
|
|
|
|
uci:foreach("wireless", "wifi-iface", function(s)
|
2013-07-11 10:30:59 +02:00
|
|
|
if s.ssid == config.DEFAULT_AP_SSID then sname = s[".name"]; return false end
|
2013-04-08 01:20:45 +02:00
|
|
|
end)
|
|
|
|
if sname == nil then sname = uci:add("wireless", "wifi-iface") end
|
|
|
|
|
|
|
|
M.uciTableSet("wireless", sname, {
|
|
|
|
network = wifi.NET,
|
2013-07-11 10:30:59 +02:00
|
|
|
ssid = config.DEFAULT_AP_SSID,
|
2013-04-08 01:20:45 +02:00
|
|
|
encryption = "none",
|
|
|
|
device = "radio0",
|
|
|
|
mode = "ap",
|
|
|
|
})
|
|
|
|
|
2013-04-09 14:37:31 +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
|
|
|
|
uci:foreach("wireless", "wifi-iface", function(s)
|
2013-07-11 10:30:59 +02:00
|
|
|
if s.ssid == config.DEFAULT_AP_SSID then sname = s[".name"]; return false end
|
2013-04-08 01:20:45 +02:00
|
|
|
end)
|
2013-06-30 19:06:55 +02:00
|
|
|
if sname == nil then return l:info("AP network configuration does not exist, nothing to remove") end
|
2013-04-08 01:20:45 +02:00
|
|
|
uci:delete("wireless", sname)
|
2013-04-09 14:37:31 +02:00
|
|
|
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-04-09 14:37:31 +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-04-09 14:37:31 +02:00
|
|
|
M.uciTableSet("network", wifi.NET, {
|
|
|
|
proto = "static",
|
2013-07-11 10:30:59 +02:00
|
|
|
ipaddr = config.DEFAULT_AP_ADDRESS,
|
|
|
|
netmask = config.DEFAULT_AP_NETMASK
|
2013-04-09 14:37:31 +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-04-09 14:37:31 +02:00
|
|
|
uci:set("network", wifi.NET, "interface")
|
2013-04-08 01:20:45 +02:00
|
|
|
uci:set("network", wifi.NET, "proto", "dhcp")
|
|
|
|
uci:delete("network", wifi.NET, "ipaddr")
|
|
|
|
uci:delete("network", wifi.NET, "netmask")
|
2013-06-17 20:23:00 +02:00
|
|
|
--uci:delete("network", wifi.NET, "type") --do not remove since it is not added anymore
|
2013-04-09 14:37:31 +02:00
|
|
|
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-04-09 14:37:31 +02:00
|
|
|
uci:set("dhcp", wifi.NET, "dhcp") --create section
|
|
|
|
M.uciTableSet("dhcp", wifi.NET, {
|
|
|
|
interface = wifi.NET,
|
|
|
|
start = "100",
|
|
|
|
limit = "150",
|
|
|
|
leasetime = "12h",
|
|
|
|
})
|
|
|
|
commitBit(dirtyList, "dhcp"); reloadBit(dirtyList, "dnsmasq")
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.dhcppool_rm(dirtyList)
|
|
|
|
uci:delete("dhcp", wifi.NET)
|
2013-04-09 14:37:31 +02:00
|
|
|
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)
|
|
|
|
uci:set("uhttpd", "main", "error_page", "/admin/autowifi.html")
|
|
|
|
uci:set("uhttpd", "main", "no_dirlist", "1")
|
2013-04-09 14:37:31 +02:00
|
|
|
bothBits(dirtyList, "uhttpd")
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.wwwredir_rm(dirtyList)
|
|
|
|
uci:delete("uhttpd", "main", "error_page")
|
|
|
|
uci:delete("uhttpd", "main", "no_dirlist")
|
2013-04-09 14:37:31 +02:00
|
|
|
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-11 10:30:59 +02:00
|
|
|
local redirText = "/#/" .. config.DEFAULT_AP_ADDRESS
|
2013-04-08 01:20:45 +02:00
|
|
|
local sname = u.getUciSectionName("dhcp", "dnsmasq")
|
2013-06-30 19:06:55 +02:00
|
|
|
if sname == nil then return l:error("dhcp config does not contain a dnsmasq section") end
|
|
|
|
if uci:get("dhcp", sname, "address") ~= nil then return l:debug("DNS address redirection already in place, not re-adding", false) end
|
2013-04-08 01:20:45 +02:00
|
|
|
|
|
|
|
uci:set("dhcp", sname, "address", {redirText})
|
2013-04-09 14:37:31 +02:00
|
|
|
commitBit(dirtyList, "dhcp"); reloadBit(dirtyList, "dnsmasq")
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.dnsredir_rm(dirtyList)
|
|
|
|
local sname = u.getUciSectionName("dhcp", "dnsmasq")
|
2013-06-30 19:06:55 +02:00
|
|
|
if sname == nil then return l:error("dhcp config does not contain a dnsmasq section") end
|
2013-04-09 14:37:31 +02:00
|
|
|
|
2013-04-08 01:20:45 +02:00
|
|
|
uci:delete("dhcp", sname, "address")
|
2013-04-09 14:37:31 +02:00
|
|
|
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)
|
|
|
|
if u.exists(M.WWW_CAPTIVE_INDICATOR) then
|
2013-06-30 19:06:55 +02:00
|
|
|
return l:debug("WWW captive directory already in place, not redoing", false)
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
2013-06-17 20:23:00 +02:00
|
|
|
local rv,reason = os.rename("/www", M.WWW_RENAME_NAME)
|
|
|
|
if rv == true then
|
2013-04-18 11:30:48 +02:00
|
|
|
u.symlink(M.WWW_CAPTIVE_PATH, "/www")
|
|
|
|
return true
|
|
|
|
else
|
2013-06-30 19:06:55 +02:00
|
|
|
return l: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-06-30 19:06:55 +02:00
|
|
|
if not u.exists(M.WWW_CAPTIVE_INDICATOR) then return l:debug("WWW captive directory not in place, not undoing", false) end
|
2013-04-08 01:20:45 +02:00
|
|
|
os.remove("/www")
|
2013-04-18 11:30:48 +02:00
|
|
|
if os.rename(M.WWW_RENAME_NAME, "/www") ~= true then
|
2013-06-30 19:06:55 +02:00
|
|
|
return l: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)
|
|
|
|
uci:set("firewall", "portalreflect", "redirect");
|
|
|
|
M.uciTableSet("firewall", "portalreflect", {
|
|
|
|
src = "lan",
|
|
|
|
proto = "tcp",
|
|
|
|
src_dport = "80",
|
|
|
|
dest_port = "80",
|
2013-07-11 10:30:59 +02:00
|
|
|
dest_ip = config.DEFAULT_AP_ADDRESS,
|
2013-04-08 01:20:45 +02:00
|
|
|
target = "DNAT"
|
|
|
|
})
|
2013-04-09 14:37:31 +02:00
|
|
|
bothBits(dirtyList, "firewall")
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
function reconf.natreflect_rm(dirtyList)
|
|
|
|
uci:delete("firewall", "portalreflect")
|
2013-04-09 14:37:31 +02:00
|
|
|
bothBits(dirtyList, "firewall")
|
2013-04-08 01:20:45 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return M
|