mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-03-09 15:40:03 +00:00
Add macvlan support
This commit is contained in:
parent
40fdd921b9
commit
9f8643647e
255 changed files with 134998 additions and 0 deletions
|
@ -0,0 +1,9 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.filebrowser", package.seeall)
|
||||
|
||||
function index()
|
||||
entry( {"admin", "filebrowser"}, template("cbi/filebrowser") ).leaf = true
|
||||
end
|
42
luci-mod-admin-full/luasrc/controller/admin/index.lua
Normal file
42
luci-mod-admin-full/luasrc/controller/admin/index.lua
Normal file
|
@ -0,0 +1,42 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.index", package.seeall)
|
||||
|
||||
function index()
|
||||
local root = node()
|
||||
if not root.target then
|
||||
root.target = alias("admin")
|
||||
root.index = true
|
||||
end
|
||||
|
||||
local page = node("admin")
|
||||
page.target = firstchild()
|
||||
page.title = _("Administration")
|
||||
page.order = 10
|
||||
page.sysauth = "root"
|
||||
page.sysauth_authenticator = "htmlauth"
|
||||
page.ucidata = true
|
||||
page.index = true
|
||||
|
||||
-- Empty services menu to be populated by addons
|
||||
entry({"admin", "services"}, firstchild(), _("Services"), 40).index = true
|
||||
|
||||
entry({"admin", "logout"}, call("action_logout"), _("Logout"), 90)
|
||||
end
|
||||
|
||||
function action_logout()
|
||||
local dsp = require "luci.dispatcher"
|
||||
local utl = require "luci.util"
|
||||
local sid = dsp.context.authsession
|
||||
|
||||
if sid then
|
||||
utl.ubus("session", "destroy", { ubus_rpc_session = sid })
|
||||
|
||||
luci.http.header("Set-Cookie", "sysauth=%s; expires=%s; path=%s/" %{
|
||||
sid, 'Thu, 01 Jan 1970 01:00:00 GMT', dsp.build_url()
|
||||
})
|
||||
end
|
||||
|
||||
luci.http.redirect(dsp.build_url())
|
||||
end
|
429
luci-mod-admin-full/luasrc/controller/admin/network.lua
Normal file
429
luci-mod-admin-full/luasrc/controller/admin/network.lua
Normal file
|
@ -0,0 +1,429 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.network", package.seeall)
|
||||
|
||||
function index()
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local page
|
||||
|
||||
page = node("admin", "network")
|
||||
page.target = firstchild()
|
||||
page.title = _("Network")
|
||||
page.order = 50
|
||||
page.index = true
|
||||
|
||||
-- if page.inreq then
|
||||
local has_switch = false
|
||||
|
||||
uci:foreach("network", "switch",
|
||||
function(s)
|
||||
has_switch = true
|
||||
return false
|
||||
end)
|
||||
|
||||
if has_switch then
|
||||
page = node("admin", "network", "vlan")
|
||||
page.target = cbi("admin_network/vlan")
|
||||
page.title = _("Switch")
|
||||
page.order = 20
|
||||
|
||||
page = entry({"admin", "network", "switch_status"}, call("switch_status"), nil)
|
||||
page.leaf = true
|
||||
end
|
||||
|
||||
|
||||
local has_wifi = false
|
||||
|
||||
uci:foreach("wireless", "wifi-device",
|
||||
function(s)
|
||||
has_wifi = true
|
||||
return false
|
||||
end)
|
||||
|
||||
if has_wifi then
|
||||
page = entry({"admin", "network", "wireless_join"}, post("wifi_join"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "wireless_add"}, post("wifi_add"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "wireless_delete"}, post("wifi_delete"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "wireless_reconnect"}, post("wifi_reconnect"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "wireless_shutdown"}, post("wifi_shutdown"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "wireless"}, arcombine(template("admin_network/wifi_overview"), cbi("admin_network/wifi")), _("Wireless"), 15)
|
||||
page.leaf = true
|
||||
page.subindex = true
|
||||
|
||||
if page.inreq then
|
||||
local wdev
|
||||
local net = require "luci.model.network".init(uci)
|
||||
for _, wdev in ipairs(net:get_wifidevs()) do
|
||||
local wnet
|
||||
for _, wnet in ipairs(wdev:get_wifinets()) do
|
||||
entry(
|
||||
{"admin", "network", "wireless", wnet:id()},
|
||||
alias("admin", "network", "wireless"),
|
||||
wdev:name() .. ": " .. wnet:shortname()
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
page = entry({"admin", "network", "iface_add"}, cbi("admin_network/iface_add"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "iface_delete"}, post("iface_delete"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "iface_status"}, call("iface_status"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "iface_reconnect"}, post("iface_reconnect"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "iface_shutdown"}, post("iface_shutdown"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), _("Interfaces"), 10)
|
||||
page.leaf = true
|
||||
page.subindex = true
|
||||
|
||||
if page.inreq then
|
||||
uci:foreach("network", "interface",
|
||||
function (section)
|
||||
local ifc = section[".name"]
|
||||
if ifc ~= "loopback" then
|
||||
entry({"admin", "network", "network", ifc},
|
||||
true, ifc:upper())
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
if nixio.fs.access("/etc/config/dhcp") then
|
||||
page = node("admin", "network", "dhcp")
|
||||
page.target = cbi("admin_network/dhcp")
|
||||
page.title = _("DHCP and DNS")
|
||||
page.order = 30
|
||||
|
||||
page = entry({"admin", "network", "dhcplease_status"}, call("lease_status"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = node("admin", "network", "hosts")
|
||||
page.target = cbi("admin_network/hosts")
|
||||
page.title = _("Hostnames")
|
||||
page.order = 40
|
||||
end
|
||||
|
||||
page = node("admin", "network", "routes")
|
||||
page.target = cbi("admin_network/routes")
|
||||
page.title = _("Static Routes")
|
||||
page.order = 50
|
||||
|
||||
page = node("admin", "network", "diagnostics")
|
||||
page.target = template("admin_network/diagnostics")
|
||||
page.title = _("Diagnostics")
|
||||
page.order = 60
|
||||
|
||||
page = entry({"admin", "network", "diag_ping"}, post("diag_ping"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "diag_nslookup"}, post("diag_nslookup"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "diag_traceroute"}, post("diag_traceroute"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "diag_ping6"}, post("diag_ping6"), nil)
|
||||
page.leaf = true
|
||||
|
||||
page = entry({"admin", "network", "diag_traceroute6"}, post("diag_traceroute6"), nil)
|
||||
page.leaf = true
|
||||
-- end
|
||||
end
|
||||
|
||||
function wifi_join()
|
||||
local tpl = require "luci.template"
|
||||
local http = require "luci.http"
|
||||
local dev = http.formvalue("device")
|
||||
local ssid = http.formvalue("join")
|
||||
|
||||
if dev and ssid then
|
||||
local cancel = (http.formvalue("cancel") or http.formvalue("cbi.cancel"))
|
||||
if not cancel then
|
||||
local cbi = require "luci.cbi"
|
||||
local map = luci.cbi.load("admin_network/wifi_add")[1]
|
||||
|
||||
if map:parse() ~= cbi.FORM_DONE then
|
||||
tpl.render("header")
|
||||
map:render()
|
||||
tpl.render("footer")
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
tpl.render("admin_network/wifi_join")
|
||||
end
|
||||
|
||||
function wifi_add()
|
||||
local dev = luci.http.formvalue("device")
|
||||
local ntm = require "luci.model.network".init()
|
||||
|
||||
dev = dev and ntm:get_wifidev(dev)
|
||||
|
||||
if dev then
|
||||
local net = dev:add_wifinet({
|
||||
mode = "ap",
|
||||
ssid = "OpenWrt",
|
||||
encryption = "none"
|
||||
})
|
||||
|
||||
ntm:save("wireless")
|
||||
luci.http.redirect(net:adminlink())
|
||||
end
|
||||
end
|
||||
|
||||
function wifi_delete(network)
|
||||
local ntm = require "luci.model.network".init()
|
||||
local wnet = ntm:get_wifinet(network)
|
||||
if wnet then
|
||||
local dev = wnet:get_device()
|
||||
local nets = wnet:get_networks()
|
||||
if dev then
|
||||
ntm:del_wifinet(network)
|
||||
ntm:commit("wireless")
|
||||
local _, net
|
||||
for _, net in ipairs(nets) do
|
||||
if net:is_empty() then
|
||||
ntm:del_network(net:name())
|
||||
ntm:commit("network")
|
||||
end
|
||||
end
|
||||
luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>/dev/null")
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
|
||||
end
|
||||
|
||||
function iface_status(ifaces)
|
||||
local netm = require "luci.model.network".init()
|
||||
local rv = { }
|
||||
|
||||
local iface
|
||||
for iface in ifaces:gmatch("[%w%.%-_]+") do
|
||||
local net = netm:get_network(iface)
|
||||
local device = net and net:get_interface()
|
||||
if device then
|
||||
local data = {
|
||||
id = iface,
|
||||
proto = net:proto(),
|
||||
uptime = net:uptime(),
|
||||
gwaddr = net:gwaddr(),
|
||||
ipaddrs = net:ipaddrs(),
|
||||
ip6addrs = net:ip6addrs(),
|
||||
dnsaddrs = net:dnsaddrs(),
|
||||
ip6prefix = net:ip6prefix(),
|
||||
name = device:shortname(),
|
||||
type = device:type(),
|
||||
ifname = device:name(),
|
||||
macaddr = device:mac(),
|
||||
is_up = device:is_up(),
|
||||
rx_bytes = device:rx_bytes(),
|
||||
tx_bytes = device:tx_bytes(),
|
||||
rx_packets = device:rx_packets(),
|
||||
tx_packets = device:tx_packets(),
|
||||
|
||||
subdevices = { }
|
||||
}
|
||||
|
||||
for _, device in ipairs(net:get_interfaces() or {}) do
|
||||
data.subdevices[#data.subdevices+1] = {
|
||||
name = device:shortname(),
|
||||
type = device:type(),
|
||||
ifname = device:name(),
|
||||
macaddr = device:mac(),
|
||||
macaddr = device:mac(),
|
||||
is_up = device:is_up(),
|
||||
rx_bytes = device:rx_bytes(),
|
||||
tx_bytes = device:tx_bytes(),
|
||||
rx_packets = device:rx_packets(),
|
||||
tx_packets = device:tx_packets(),
|
||||
}
|
||||
end
|
||||
|
||||
rv[#rv+1] = data
|
||||
else
|
||||
rv[#rv+1] = {
|
||||
id = iface,
|
||||
name = iface,
|
||||
type = "ethernet"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
if #rv > 0 then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such device")
|
||||
end
|
||||
|
||||
function iface_reconnect(iface)
|
||||
local netmd = require "luci.model.network".init()
|
||||
local net = netmd:get_network(iface)
|
||||
if net then
|
||||
luci.sys.call("env -i /sbin/ifup %q >/dev/null 2>/dev/null" % iface)
|
||||
luci.http.status(200, "Reconnected")
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such interface")
|
||||
end
|
||||
|
||||
function iface_shutdown(iface)
|
||||
local netmd = require "luci.model.network".init()
|
||||
local net = netmd:get_network(iface)
|
||||
if net then
|
||||
luci.sys.call("env -i /sbin/ifdown %q >/dev/null 2>/dev/null" % iface)
|
||||
luci.http.status(200, "Shutdown")
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such interface")
|
||||
end
|
||||
|
||||
function iface_delete(iface)
|
||||
local netmd = require "luci.model.network".init()
|
||||
local net = netmd:del_network(iface)
|
||||
if net then
|
||||
luci.sys.call("env -i /sbin/ifdown %q >/dev/null 2>/dev/null" % iface)
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
|
||||
netmd:commit("network")
|
||||
netmd:commit("wireless")
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such interface")
|
||||
end
|
||||
|
||||
function wifi_status(devs)
|
||||
local s = require "luci.tools.status"
|
||||
local rv = { }
|
||||
|
||||
local dev
|
||||
for dev in devs:gmatch("[%w%.%-]+") do
|
||||
rv[#rv+1] = s.wifi_network(dev)
|
||||
end
|
||||
|
||||
if #rv > 0 then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such device")
|
||||
end
|
||||
|
||||
local function wifi_reconnect_shutdown(shutdown, wnet)
|
||||
local netmd = require "luci.model.network".init()
|
||||
local net = netmd:get_wifinet(wnet)
|
||||
local dev = net:get_device()
|
||||
if dev and net then
|
||||
dev:set("disabled", nil)
|
||||
net:set("disabled", shutdown and 1 or nil)
|
||||
netmd:commit("wireless")
|
||||
|
||||
luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>/dev/null")
|
||||
luci.http.status(200, shutdown and "Shutdown" or "Reconnected")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(404, "No such radio")
|
||||
end
|
||||
|
||||
function wifi_reconnect(wnet)
|
||||
wifi_reconnect_shutdown(false, wnet)
|
||||
end
|
||||
|
||||
function wifi_shutdown(wnet)
|
||||
wifi_reconnect_shutdown(true, wnet)
|
||||
end
|
||||
|
||||
function lease_status()
|
||||
local s = require "luci.tools.status"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write('[')
|
||||
luci.http.write_json(s.dhcp_leases())
|
||||
luci.http.write(',')
|
||||
luci.http.write_json(s.dhcp6_leases())
|
||||
luci.http.write(']')
|
||||
end
|
||||
|
||||
function switch_status(switches)
|
||||
local s = require "luci.tools.status"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(s.switch_status(switches))
|
||||
end
|
||||
|
||||
function diag_command(cmd, addr)
|
||||
if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
|
||||
luci.http.prepare_content("text/plain")
|
||||
|
||||
local util = io.popen(cmd % addr)
|
||||
if util then
|
||||
while true do
|
||||
local ln = util:read("*l")
|
||||
if not ln then break end
|
||||
luci.http.write(ln)
|
||||
luci.http.write("\n")
|
||||
end
|
||||
|
||||
util:close()
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
luci.http.status(500, "Bad address")
|
||||
end
|
||||
|
||||
function diag_ping(addr)
|
||||
diag_command("ping -c 5 -W 1 %q 2>&1", addr)
|
||||
end
|
||||
|
||||
function diag_traceroute(addr)
|
||||
diag_command("traceroute -q 1 -w 1 -n %q 2>&1", addr)
|
||||
end
|
||||
|
||||
function diag_nslookup(addr)
|
||||
diag_command("nslookup %q 2>&1", addr)
|
||||
end
|
||||
|
||||
function diag_ping6(addr)
|
||||
diag_command("ping6 -c 5 %q 2>&1", addr)
|
||||
end
|
||||
|
||||
function diag_traceroute6(addr)
|
||||
diag_command("traceroute6 -q 1 -w 2 -n %q 2>&1", addr)
|
||||
end
|
152
luci-mod-admin-full/luasrc/controller/admin/status.lua
Normal file
152
luci-mod-admin-full/luasrc/controller/admin/status.lua
Normal file
|
@ -0,0 +1,152 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.status", package.seeall)
|
||||
|
||||
function index()
|
||||
entry({"admin", "status"}, alias("admin", "status", "overview"), _("Status"), 20).index = true
|
||||
entry({"admin", "status", "overview"}, template("admin_status/index"), _("Overview"), 1)
|
||||
|
||||
entry({"admin", "status", "iptables"}, template("admin_status/iptables"), _("Firewall"), 2).leaf = true
|
||||
entry({"admin", "status", "iptables_action"}, post("action_iptables")).leaf = true
|
||||
|
||||
entry({"admin", "status", "routes"}, template("admin_status/routes"), _("Routes"), 3)
|
||||
entry({"admin", "status", "syslog"}, call("action_syslog"), _("System Log"), 4)
|
||||
entry({"admin", "status", "dmesg"}, call("action_dmesg"), _("Kernel Log"), 5)
|
||||
entry({"admin", "status", "processes"}, cbi("admin_status/processes"), _("Processes"), 6)
|
||||
|
||||
entry({"admin", "status", "realtime"}, alias("admin", "status", "realtime", "load"), _("Realtime Graphs"), 7)
|
||||
|
||||
entry({"admin", "status", "realtime", "load"}, template("admin_status/load"), _("Load"), 1).leaf = true
|
||||
entry({"admin", "status", "realtime", "load_status"}, call("action_load")).leaf = true
|
||||
|
||||
entry({"admin", "status", "realtime", "bandwidth"}, template("admin_status/bandwidth"), _("Traffic"), 2).leaf = true
|
||||
entry({"admin", "status", "realtime", "bandwidth_status"}, call("action_bandwidth")).leaf = true
|
||||
|
||||
if nixio.fs.access("/etc/config/wireless") then
|
||||
entry({"admin", "status", "realtime", "wireless"}, template("admin_status/wireless"), _("Wireless"), 3).leaf = true
|
||||
entry({"admin", "status", "realtime", "wireless_status"}, call("action_wireless")).leaf = true
|
||||
end
|
||||
|
||||
entry({"admin", "status", "realtime", "connections"}, template("admin_status/connections"), _("Connections"), 4).leaf = true
|
||||
entry({"admin", "status", "realtime", "connections_status"}, call("action_connections")).leaf = true
|
||||
|
||||
entry({"admin", "status", "nameinfo"}, call("action_nameinfo")).leaf = true
|
||||
end
|
||||
|
||||
function action_syslog()
|
||||
local syslog = luci.sys.syslog()
|
||||
luci.template.render("admin_status/syslog", {syslog=syslog})
|
||||
end
|
||||
|
||||
function action_dmesg()
|
||||
local dmesg = luci.sys.dmesg()
|
||||
luci.template.render("admin_status/dmesg", {dmesg=dmesg})
|
||||
end
|
||||
|
||||
function action_iptables()
|
||||
if luci.http.formvalue("zero") then
|
||||
if luci.http.formvalue("family") == "6" then
|
||||
luci.util.exec("/usr/sbin/ip6tables -Z")
|
||||
else
|
||||
luci.util.exec("/usr/sbin/iptables -Z")
|
||||
end
|
||||
elseif luci.http.formvalue("restart") then
|
||||
luci.util.exec("/etc/init.d/firewall restart")
|
||||
end
|
||||
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/status/iptables"))
|
||||
end
|
||||
|
||||
function action_bandwidth(iface)
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface)
|
||||
if bwc then
|
||||
luci.http.write("[")
|
||||
|
||||
while true do
|
||||
local ln = bwc:read("*l")
|
||||
if not ln then break end
|
||||
luci.http.write(ln)
|
||||
end
|
||||
|
||||
luci.http.write("]")
|
||||
bwc:close()
|
||||
end
|
||||
end
|
||||
|
||||
function action_wireless(iface)
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -r %q 2>/dev/null" % iface)
|
||||
if bwc then
|
||||
luci.http.write("[")
|
||||
|
||||
while true do
|
||||
local ln = bwc:read("*l")
|
||||
if not ln then break end
|
||||
luci.http.write(ln)
|
||||
end
|
||||
|
||||
luci.http.write("]")
|
||||
bwc:close()
|
||||
end
|
||||
end
|
||||
|
||||
function action_load()
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
local bwc = io.popen("luci-bwc -l 2>/dev/null")
|
||||
if bwc then
|
||||
luci.http.write("[")
|
||||
|
||||
while true do
|
||||
local ln = bwc:read("*l")
|
||||
if not ln then break end
|
||||
luci.http.write(ln)
|
||||
end
|
||||
|
||||
luci.http.write("]")
|
||||
bwc:close()
|
||||
end
|
||||
end
|
||||
|
||||
function action_connections()
|
||||
local sys = require "luci.sys"
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
|
||||
luci.http.write("{ connections: ")
|
||||
luci.http.write_json(sys.net.conntrack())
|
||||
|
||||
local bwc = io.popen("luci-bwc -c 2>/dev/null")
|
||||
if bwc then
|
||||
luci.http.write(", statistics: [")
|
||||
|
||||
while true do
|
||||
local ln = bwc:read("*l")
|
||||
if not ln then break end
|
||||
luci.http.write(ln)
|
||||
end
|
||||
|
||||
luci.http.write("]")
|
||||
bwc:close()
|
||||
end
|
||||
|
||||
luci.http.write(" }")
|
||||
end
|
||||
|
||||
function action_nameinfo(...)
|
||||
local i
|
||||
local rv = { }
|
||||
for i = 1, select('#', ...) do
|
||||
local addr = select(i, ...)
|
||||
local fqdn = nixio.getnameinfo(addr)
|
||||
rv[addr] = fqdn or (addr:match(":") and "[%s]" % addr or addr)
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
end
|
439
luci-mod-admin-full/luasrc/controller/admin/system.lua
Normal file
439
luci-mod-admin-full/luasrc/controller/admin/system.lua
Normal file
|
@ -0,0 +1,439 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.system", package.seeall)
|
||||
|
||||
function index()
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
entry({"admin", "system"}, alias("admin", "system", "system"), _("System"), 30).index = true
|
||||
entry({"admin", "system", "system"}, cbi("admin_system/system"), _("System"), 1)
|
||||
entry({"admin", "system", "clock_status"}, post_on({ set = true }, "action_clock_status"))
|
||||
|
||||
entry({"admin", "system", "admin"}, cbi("admin_system/admin"), _("Administration"), 2)
|
||||
|
||||
if fs.access("/bin/opkg") then
|
||||
entry({"admin", "system", "packages"}, post_on({ exec = "1" }, "action_packages"), _("Software"), 10)
|
||||
entry({"admin", "system", "packages", "ipkg"}, form("admin_system/ipkg"))
|
||||
end
|
||||
|
||||
entry({"admin", "system", "startup"}, form("admin_system/startup"), _("Startup"), 45)
|
||||
entry({"admin", "system", "crontab"}, form("admin_system/crontab"), _("Scheduled Tasks"), 46)
|
||||
|
||||
if fs.access("/sbin/block") and fs.access("/etc/config/fstab") then
|
||||
entry({"admin", "system", "fstab"}, cbi("admin_system/fstab"), _("Mount Points"), 50)
|
||||
entry({"admin", "system", "fstab", "mount"}, cbi("admin_system/fstab/mount"), nil).leaf = true
|
||||
entry({"admin", "system", "fstab", "swap"}, cbi("admin_system/fstab/swap"), nil).leaf = true
|
||||
end
|
||||
|
||||
if fs.access("/sys/class/leds") then
|
||||
entry({"admin", "system", "leds"}, cbi("admin_system/leds"), _("<abbr title=\"Light Emitting Diode\">LED</abbr> Configuration"), 60)
|
||||
end
|
||||
|
||||
entry({"admin", "system", "flashops"}, call("action_flashops"), _("Backup / Flash Firmware"), 70)
|
||||
entry({"admin", "system", "flashops", "reset"}, post("action_reset"))
|
||||
entry({"admin", "system", "flashops", "backup"}, post("action_backup"))
|
||||
entry({"admin", "system", "flashops", "backupfiles"}, form("admin_system/backupfiles"))
|
||||
|
||||
-- call() instead of post() due to upload handling!
|
||||
entry({"admin", "system", "flashops", "restore"}, call("action_restore"))
|
||||
entry({"admin", "system", "flashops", "sysupgrade"}, call("action_sysupgrade"))
|
||||
|
||||
entry({"admin", "system", "reboot"}, template("admin_system/reboot"), _("Reboot"), 90)
|
||||
entry({"admin", "system", "reboot", "call"}, post("action_reboot"))
|
||||
end
|
||||
|
||||
function action_clock_status()
|
||||
local set = tonumber(luci.http.formvalue("set"))
|
||||
if set ~= nil and set > 0 then
|
||||
local date = os.date("*t", set)
|
||||
if date then
|
||||
luci.sys.call("date -s '%04d-%02d-%02d %02d:%02d:%02d'" %{
|
||||
date.year, date.month, date.day, date.hour, date.min, date.sec
|
||||
})
|
||||
luci.sys.call("/etc/init.d/sysfixtime restart")
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({ timestring = os.date("%c") })
|
||||
end
|
||||
|
||||
function action_packages()
|
||||
local fs = require "nixio.fs"
|
||||
local ipkg = require "luci.model.ipkg"
|
||||
local submit = (luci.http.formvalue("exec") == "1")
|
||||
local update, upgrade
|
||||
local changes = false
|
||||
local install = { }
|
||||
local remove = { }
|
||||
local stdout = { "" }
|
||||
local stderr = { "" }
|
||||
local out, err
|
||||
|
||||
-- Display
|
||||
local display = luci.http.formvalue("display") or "installed"
|
||||
|
||||
-- Letter
|
||||
local letter = string.byte(luci.http.formvalue("letter") or "A", 1)
|
||||
letter = (letter == 35 or (letter >= 65 and letter <= 90)) and letter or 65
|
||||
|
||||
-- Search query
|
||||
local query = luci.http.formvalue("query")
|
||||
query = (query ~= '') and query or nil
|
||||
|
||||
|
||||
-- Modifying actions
|
||||
if submit then
|
||||
-- Packets to be installed
|
||||
local ninst = luci.http.formvalue("install")
|
||||
local uinst = nil
|
||||
|
||||
-- Install from URL
|
||||
local url = luci.http.formvalue("url")
|
||||
if url and url ~= '' then
|
||||
uinst = url
|
||||
end
|
||||
|
||||
-- Do install
|
||||
if ninst then
|
||||
install[ninst], out, err = ipkg.install(ninst)
|
||||
stdout[#stdout+1] = out
|
||||
stderr[#stderr+1] = err
|
||||
changes = true
|
||||
end
|
||||
|
||||
if uinst then
|
||||
local pkg
|
||||
for pkg in luci.util.imatch(uinst) do
|
||||
install[uinst], out, err = ipkg.install(pkg)
|
||||
stdout[#stdout+1] = out
|
||||
stderr[#stderr+1] = err
|
||||
changes = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove packets
|
||||
local rem = luci.http.formvalue("remove")
|
||||
if rem then
|
||||
remove[rem], out, err = ipkg.remove(rem)
|
||||
stdout[#stdout+1] = out
|
||||
stderr[#stderr+1] = err
|
||||
changes = true
|
||||
end
|
||||
|
||||
|
||||
-- Update all packets
|
||||
update = luci.http.formvalue("update")
|
||||
if update then
|
||||
update, out, err = ipkg.update()
|
||||
stdout[#stdout+1] = out
|
||||
stderr[#stderr+1] = err
|
||||
end
|
||||
|
||||
|
||||
-- Upgrade all packets
|
||||
upgrade = luci.http.formvalue("upgrade")
|
||||
if upgrade then
|
||||
upgrade, out, err = ipkg.upgrade()
|
||||
stdout[#stdout+1] = out
|
||||
stderr[#stderr+1] = err
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- List state
|
||||
local no_lists = true
|
||||
local old_lists = false
|
||||
if fs.access("/var/opkg-lists/") then
|
||||
local list
|
||||
for list in fs.dir("/var/opkg-lists/") do
|
||||
no_lists = false
|
||||
if (fs.stat("/var/opkg-lists/"..list, "mtime") or 0) < (os.time() - (24 * 60 * 60)) then
|
||||
old_lists = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
luci.template.render("admin_system/packages", {
|
||||
display = display,
|
||||
letter = letter,
|
||||
query = query,
|
||||
install = install,
|
||||
remove = remove,
|
||||
update = update,
|
||||
upgrade = upgrade,
|
||||
no_lists = no_lists,
|
||||
old_lists = old_lists,
|
||||
stdout = table.concat(stdout, ""),
|
||||
stderr = table.concat(stderr, "")
|
||||
})
|
||||
|
||||
-- Remove index cache
|
||||
if changes then
|
||||
fs.unlink("/tmp/luci-indexcache")
|
||||
end
|
||||
end
|
||||
|
||||
local function image_supported(image)
|
||||
return (os.execute("sysupgrade -T %q >/dev/null" % image) == 0)
|
||||
end
|
||||
|
||||
local function image_checksum(image)
|
||||
return (luci.sys.exec("md5sum %q" % image):match("^([^%s]+)"))
|
||||
end
|
||||
|
||||
local function image_sha256_checksum(image)
|
||||
return (luci.sys.exec("sha256sum %q" % image):match("^([^%s]+)"))
|
||||
end
|
||||
|
||||
local function supports_sysupgrade()
|
||||
return nixio.fs.access("/lib/upgrade/platform.sh")
|
||||
end
|
||||
|
||||
local function supports_reset()
|
||||
return (os.execute([[grep -sqE '"rootfs_data"|"ubi"' /proc/mtd]]) == 0)
|
||||
end
|
||||
|
||||
local function storage_size()
|
||||
local size = 0
|
||||
if nixio.fs.access("/proc/mtd") then
|
||||
for l in io.lines("/proc/mtd") do
|
||||
local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
|
||||
if n == "linux" or n == "firmware" then
|
||||
size = tonumber(s, 16)
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif nixio.fs.access("/proc/partitions") then
|
||||
for l in io.lines("/proc/partitions") do
|
||||
local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
|
||||
if b and n and not n:match('[0-9]') then
|
||||
size = tonumber(b) * 1024
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return size
|
||||
end
|
||||
|
||||
|
||||
function action_flashops()
|
||||
--
|
||||
-- Overview
|
||||
--
|
||||
luci.template.render("admin_system/flashops", {
|
||||
reset_avail = supports_reset(),
|
||||
upgrade_avail = supports_sysupgrade()
|
||||
})
|
||||
end
|
||||
|
||||
function action_sysupgrade()
|
||||
local fs = require "nixio.fs"
|
||||
local http = require "luci.http"
|
||||
local image_tmp = "/tmp/firmware.img"
|
||||
|
||||
local fp
|
||||
http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not fp and meta and meta.name == "image" then
|
||||
fp = io.open(image_tmp, "w")
|
||||
end
|
||||
if fp and chunk then
|
||||
fp:write(chunk)
|
||||
end
|
||||
if fp and eof then
|
||||
fp:close()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if not luci.dispatcher.test_post_security() then
|
||||
fs.unlink(image_tmp)
|
||||
return
|
||||
end
|
||||
|
||||
--
|
||||
-- Cancel firmware flash
|
||||
--
|
||||
if http.formvalue("cancel") then
|
||||
fs.unlink(image_tmp)
|
||||
http.redirect(luci.dispatcher.build_url('admin/system/flashops'))
|
||||
return
|
||||
end
|
||||
|
||||
--
|
||||
-- Initiate firmware flash
|
||||
--
|
||||
local step = tonumber(http.formvalue("step") or 1)
|
||||
if step == 1 then
|
||||
if image_supported(image_tmp) then
|
||||
luci.template.render("admin_system/upgrade", {
|
||||
checksum = image_checksum(image_tmp),
|
||||
sha256ch = image_sha256_checksum(image_tmp),
|
||||
storage = storage_size(),
|
||||
size = (fs.stat(image_tmp, "size") or 0),
|
||||
keep = (not not http.formvalue("keep"))
|
||||
})
|
||||
else
|
||||
fs.unlink(image_tmp)
|
||||
luci.template.render("admin_system/flashops", {
|
||||
reset_avail = supports_reset(),
|
||||
upgrade_avail = supports_sysupgrade(),
|
||||
image_invalid = true
|
||||
})
|
||||
end
|
||||
--
|
||||
-- Start sysupgrade flash
|
||||
--
|
||||
elseif step == 2 then
|
||||
local keep = (http.formvalue("keep") == "1") and "" or "-n"
|
||||
luci.template.render("admin_system/applyreboot", {
|
||||
title = luci.i18n.translate("Flashing..."),
|
||||
msg = luci.i18n.translate("The system is flashing now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings."),
|
||||
addr = (#keep > 0) and "192.168.1.1" or nil
|
||||
})
|
||||
fork_exec("sleep 1; killall dropbear uhttpd; sleep 1; /sbin/sysupgrade %s %q" %{ keep, image_tmp })
|
||||
end
|
||||
end
|
||||
|
||||
function action_backup()
|
||||
local reader = ltn12_popen("sysupgrade --create-backup - 2>/dev/null")
|
||||
|
||||
luci.http.header(
|
||||
'Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' %{
|
||||
luci.sys.hostname(),
|
||||
os.date("%Y-%m-%d")
|
||||
})
|
||||
|
||||
luci.http.prepare_content("application/x-targz")
|
||||
luci.ltn12.pump.all(reader, luci.http.write)
|
||||
end
|
||||
|
||||
function action_restore()
|
||||
local fs = require "nixio.fs"
|
||||
local http = require "luci.http"
|
||||
local archive_tmp = "/tmp/restore.tar.gz"
|
||||
|
||||
local fp
|
||||
http.setfilehandler(
|
||||
function(meta, chunk, eof)
|
||||
if not fp and meta and meta.name == "archive" then
|
||||
fp = io.open(archive_tmp, "w")
|
||||
end
|
||||
if fp and chunk then
|
||||
fp:write(chunk)
|
||||
end
|
||||
if fp and eof then
|
||||
fp:close()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
if not luci.dispatcher.test_post_security() then
|
||||
fs.unlink(archive_tmp)
|
||||
return
|
||||
end
|
||||
|
||||
local upload = http.formvalue("archive")
|
||||
if upload and #upload > 0 then
|
||||
luci.template.render("admin_system/applyreboot")
|
||||
os.execute("tar -C / -xzf %q >/dev/null 2>&1" % archive_tmp)
|
||||
luci.sys.reboot()
|
||||
return
|
||||
end
|
||||
|
||||
http.redirect(luci.dispatcher.build_url('admin/system/flashops'))
|
||||
end
|
||||
|
||||
function action_reset()
|
||||
if supports_reset() then
|
||||
luci.template.render("admin_system/applyreboot", {
|
||||
title = luci.i18n.translate("Erasing..."),
|
||||
msg = luci.i18n.translate("The system is erasing the configuration partition now and will reboot itself when finished."),
|
||||
addr = "192.168.1.1"
|
||||
})
|
||||
|
||||
fork_exec("sleep 1; killall dropbear uhttpd; sleep 1; jffs2reset -y && reboot")
|
||||
return
|
||||
end
|
||||
|
||||
http.redirect(luci.dispatcher.build_url('admin/system/flashops'))
|
||||
end
|
||||
|
||||
function action_passwd()
|
||||
local p1 = luci.http.formvalue("pwd1")
|
||||
local p2 = luci.http.formvalue("pwd2")
|
||||
local stat = nil
|
||||
|
||||
if p1 or p2 then
|
||||
if p1 == p2 then
|
||||
stat = luci.sys.user.setpasswd("root", p1)
|
||||
else
|
||||
stat = 10
|
||||
end
|
||||
end
|
||||
|
||||
luci.template.render("admin_system/passwd", {stat=stat})
|
||||
end
|
||||
|
||||
function action_reboot()
|
||||
luci.sys.reboot()
|
||||
end
|
||||
|
||||
function fork_exec(command)
|
||||
local pid = nixio.fork()
|
||||
if pid > 0 then
|
||||
return
|
||||
elseif pid == 0 then
|
||||
-- change to root dir
|
||||
nixio.chdir("/")
|
||||
|
||||
-- patch stdin, out, err to /dev/null
|
||||
local null = nixio.open("/dev/null", "w+")
|
||||
if null then
|
||||
nixio.dup(null, nixio.stderr)
|
||||
nixio.dup(null, nixio.stdout)
|
||||
nixio.dup(null, nixio.stdin)
|
||||
if null:fileno() > 2 then
|
||||
null:close()
|
||||
end
|
||||
end
|
||||
|
||||
-- replace with target command
|
||||
nixio.exec("/bin/sh", "-c", command)
|
||||
end
|
||||
end
|
||||
|
||||
function ltn12_popen(command)
|
||||
|
||||
local fdi, fdo = nixio.pipe()
|
||||
local pid = nixio.fork()
|
||||
|
||||
if pid > 0 then
|
||||
fdo:close()
|
||||
local close
|
||||
return function()
|
||||
local buffer = fdi:read(2048)
|
||||
local wpid, stat = nixio.waitpid(pid, "nohang")
|
||||
if not close and wpid and stat == "exited" then
|
||||
close = true
|
||||
end
|
||||
|
||||
if buffer and #buffer > 0 then
|
||||
return buffer
|
||||
elseif close then
|
||||
fdi:close()
|
||||
return nil
|
||||
end
|
||||
end
|
||||
elseif pid == 0 then
|
||||
nixio.dup(fdo, nixio.stdout)
|
||||
fdi:close()
|
||||
fdo:close()
|
||||
nixio.exec("/bin/sh", "-c", command)
|
||||
end
|
||||
end
|
64
luci-mod-admin-full/luasrc/controller/admin/uci.lua
Normal file
64
luci-mod-admin-full/luasrc/controller/admin/uci.lua
Normal file
|
@ -0,0 +1,64 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2010-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
module("luci.controller.admin.uci", package.seeall)
|
||||
|
||||
function index()
|
||||
local redir = luci.http.formvalue("redir", true) or
|
||||
luci.dispatcher.build_url(unpack(luci.dispatcher.context.request))
|
||||
|
||||
entry({"admin", "uci"}, nil, _("Configuration"))
|
||||
entry({"admin", "uci", "changes"}, call("action_changes"), _("Changes"), 40).query = {redir=redir}
|
||||
entry({"admin", "uci", "revert"}, post("action_revert"), _("Revert"), 30).query = {redir=redir}
|
||||
entry({"admin", "uci", "apply"}, post("action_apply"), _("Apply"), 20).query = {redir=redir}
|
||||
entry({"admin", "uci", "saveapply"}, post("action_apply"), _("Save & Apply"), 10).query = {redir=redir}
|
||||
end
|
||||
|
||||
function action_changes()
|
||||
local uci = luci.model.uci.cursor()
|
||||
local changes = uci:changes()
|
||||
|
||||
luci.template.render("admin_uci/changes", {
|
||||
changes = next(changes) and changes
|
||||
})
|
||||
end
|
||||
|
||||
function action_apply()
|
||||
local path = luci.dispatcher.context.path
|
||||
local uci = luci.model.uci.cursor()
|
||||
local changes = uci:changes()
|
||||
local reload = {}
|
||||
|
||||
-- Collect files to be applied and commit changes
|
||||
for r, tbl in pairs(changes) do
|
||||
table.insert(reload, r)
|
||||
if path[#path] ~= "apply" then
|
||||
uci:load(r)
|
||||
uci:commit(r)
|
||||
uci:unload(r)
|
||||
end
|
||||
end
|
||||
|
||||
luci.template.render("admin_uci/apply", {
|
||||
changes = next(changes) and changes,
|
||||
configs = reload
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
function action_revert()
|
||||
local uci = luci.model.uci.cursor()
|
||||
local changes = uci:changes()
|
||||
|
||||
-- Collect files to be reverted
|
||||
for r, tbl in pairs(changes) do
|
||||
uci:load(r)
|
||||
uci:revert(r)
|
||||
uci:unload(r)
|
||||
end
|
||||
|
||||
luci.template.render("admin_uci/revert", {
|
||||
changes = next(changes) and changes
|
||||
})
|
||||
end
|
317
luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua
Normal file
317
luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua
Normal file
|
@ -0,0 +1,317 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local ipc = require "luci.ip"
|
||||
local o
|
||||
require "luci.util"
|
||||
|
||||
m = Map("dhcp", translate("DHCP and DNS"),
|
||||
translate("Dnsmasq is a combined <abbr title=\"Dynamic Host Configuration Protocol" ..
|
||||
"\">DHCP</abbr>-Server and <abbr title=\"Domain Name System\">DNS</abbr>-" ..
|
||||
"Forwarder for <abbr title=\"Network Address Translation\">NAT</abbr> " ..
|
||||
"firewalls"))
|
||||
|
||||
s = m:section(TypedSection, "dnsmasq", translate("Server Settings"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("files", translate("Resolv and Hosts Files"))
|
||||
s:tab("tftp", translate("TFTP Settings"))
|
||||
s:tab("advanced", translate("Advanced Settings"))
|
||||
|
||||
s:taboption("general", Flag, "domainneeded",
|
||||
translate("Domain required"),
|
||||
translate("Don't forward <abbr title=\"Domain Name System\">DNS</abbr>-Requests without " ..
|
||||
"<abbr title=\"Domain Name System\">DNS</abbr>-Name"))
|
||||
|
||||
s:taboption("general", Flag, "authoritative",
|
||||
translate("Authoritative"),
|
||||
translate("This is the only <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</" ..
|
||||
"abbr> in the local network"))
|
||||
|
||||
|
||||
s:taboption("files", Flag, "readethers",
|
||||
translate("Use <code>/etc/ethers</code>"),
|
||||
translate("Read <code>/etc/ethers</code> to configure the <abbr title=\"Dynamic Host " ..
|
||||
"Configuration Protocol\">DHCP</abbr>-Server"))
|
||||
|
||||
s:taboption("files", Value, "leasefile",
|
||||
translate("Leasefile"),
|
||||
translate("file where given <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</" ..
|
||||
"abbr>-leases will be stored"))
|
||||
|
||||
s:taboption("files", Flag, "noresolv",
|
||||
translate("Ignore resolve file")).optional = true
|
||||
|
||||
rf = s:taboption("files", Value, "resolvfile",
|
||||
translate("Resolve file"),
|
||||
translate("local <abbr title=\"Domain Name System\">DNS</abbr> file"))
|
||||
|
||||
rf:depends("noresolv", "")
|
||||
rf.optional = true
|
||||
|
||||
|
||||
s:taboption("files", Flag, "nohosts",
|
||||
translate("Ignore <code>/etc/hosts</code>")).optional = true
|
||||
|
||||
s:taboption("files", DynamicList, "addnhosts",
|
||||
translate("Additional Hosts files")).optional = true
|
||||
|
||||
qu = s:taboption("advanced", Flag, "quietdhcp",
|
||||
translate("Suppress logging"),
|
||||
translate("Suppress logging of the routine operation of these protocols"))
|
||||
qu.optional = true
|
||||
|
||||
se = s:taboption("advanced", Flag, "sequential_ip",
|
||||
translate("Allocate IP sequentially"),
|
||||
translate("Allocate IP addresses sequentially, starting from the lowest available address"))
|
||||
se.optional = true
|
||||
|
||||
s:taboption("advanced", Flag, "boguspriv",
|
||||
translate("Filter private"),
|
||||
translate("Do not forward reverse lookups for local networks"))
|
||||
|
||||
s:taboption("advanced", Flag, "filterwin2k",
|
||||
translate("Filter useless"),
|
||||
translate("Do not forward requests that cannot be answered by public name servers"))
|
||||
|
||||
|
||||
s:taboption("advanced", Flag, "localise_queries",
|
||||
translate("Localise queries"),
|
||||
translate("Localise hostname depending on the requesting subnet if multiple IPs are available"))
|
||||
|
||||
local have_dnssec_support = luci.util.checklib("/usr/sbin/dnsmasq", "libhogweed.so")
|
||||
|
||||
if have_dnssec_support then
|
||||
o = s:taboption("advanced", Flag, "dnssec",
|
||||
translate("DNSSEC"))
|
||||
o.optional = true
|
||||
|
||||
o = s:taboption("advanced", Flag, "dnsseccheckunsigned",
|
||||
translate("DNSSEC check unsigned"),
|
||||
translate("Requires upstream supports DNSSEC; verify unsigned domain responses really come from unsigned domains"))
|
||||
o.optional = true
|
||||
end
|
||||
|
||||
s:taboption("general", Value, "local",
|
||||
translate("Local server"),
|
||||
translate("Local domain specification. Names matching this domain are never forwarded and are resolved from DHCP or hosts files only"))
|
||||
|
||||
s:taboption("general", Value, "domain",
|
||||
translate("Local domain"),
|
||||
translate("Local domain suffix appended to DHCP names and hosts file entries"))
|
||||
|
||||
s:taboption("advanced", Flag, "expandhosts",
|
||||
translate("Expand hosts"),
|
||||
translate("Add local domain suffix to names served from hosts files"))
|
||||
|
||||
s:taboption("advanced", Flag, "nonegcache",
|
||||
translate("No negative cache"),
|
||||
translate("Do not cache negative replies, e.g. for not existing domains"))
|
||||
|
||||
s:taboption("advanced", Value, "serversfile",
|
||||
translate("Additional servers file"),
|
||||
translate("This file may contain lines like 'server=/domain/1.2.3.4' or 'server=1.2.3.4' for"..
|
||||
"domain-specific or full upstream <abbr title=\"Domain Name System\">DNS</abbr> servers."))
|
||||
|
||||
s:taboption("advanced", Flag, "strictorder",
|
||||
translate("Strict order"),
|
||||
translate("<abbr title=\"Domain Name System\">DNS</abbr> servers will be queried in the " ..
|
||||
"order of the resolvfile")).optional = true
|
||||
|
||||
|
||||
bn = s:taboption("advanced", DynamicList, "bogusnxdomain", translate("Bogus NX Domain Override"),
|
||||
translate("List of hosts that supply bogus NX domain results"))
|
||||
|
||||
bn.optional = true
|
||||
bn.placeholder = "67.215.65.132"
|
||||
|
||||
|
||||
s:taboption("general", Flag, "logqueries",
|
||||
translate("Log queries"),
|
||||
translate("Write received DNS requests to syslog")).optional = true
|
||||
|
||||
df = s:taboption("general", DynamicList, "server", translate("DNS forwardings"),
|
||||
translate("List of <abbr title=\"Domain Name System\">DNS</abbr> " ..
|
||||
"servers to forward requests to"))
|
||||
|
||||
df.optional = true
|
||||
df.placeholder = "/example.org/10.1.2.3"
|
||||
|
||||
|
||||
rp = s:taboption("general", Flag, "rebind_protection",
|
||||
translate("Rebind protection"),
|
||||
translate("Discard upstream RFC1918 responses"))
|
||||
|
||||
rp.rmempty = false
|
||||
|
||||
|
||||
rl = s:taboption("general", Flag, "rebind_localhost",
|
||||
translate("Allow localhost"),
|
||||
translate("Allow upstream responses in the 127.0.0.0/8 range, e.g. for RBL services"))
|
||||
|
||||
rl:depends("rebind_protection", "1")
|
||||
|
||||
|
||||
rd = s:taboption("general", DynamicList, "rebind_domain",
|
||||
translate("Domain whitelist"),
|
||||
translate("List of domains to allow RFC1918 responses for"))
|
||||
rd.optional = true
|
||||
|
||||
rd:depends("rebind_protection", "1")
|
||||
rd.datatype = "host(1)"
|
||||
rd.placeholder = "ihost.netflix.com"
|
||||
|
||||
|
||||
pt = s:taboption("advanced", Value, "port",
|
||||
translate("<abbr title=\"Domain Name System\">DNS</abbr> server port"),
|
||||
translate("Listening port for inbound DNS queries"))
|
||||
|
||||
pt.optional = true
|
||||
pt.datatype = "port"
|
||||
pt.placeholder = 53
|
||||
|
||||
|
||||
qp = s:taboption("advanced", Value, "queryport",
|
||||
translate("<abbr title=\"Domain Name System\">DNS</abbr> query port"),
|
||||
translate("Fixed source port for outbound DNS queries"))
|
||||
|
||||
qp.optional = true
|
||||
qp.datatype = "port"
|
||||
qp.placeholder = translate("any")
|
||||
|
||||
|
||||
lm = s:taboption("advanced", Value, "dhcpleasemax",
|
||||
translate("<abbr title=\"maximal\">Max.</abbr> <abbr title=\"Dynamic Host Configuration " ..
|
||||
"Protocol\">DHCP</abbr> leases"),
|
||||
translate("Maximum allowed number of active DHCP leases"))
|
||||
|
||||
lm.optional = true
|
||||
lm.datatype = "uinteger"
|
||||
lm.placeholder = translate("unlimited")
|
||||
|
||||
|
||||
em = s:taboption("advanced", Value, "ednspacket_max",
|
||||
translate("<abbr title=\"maximal\">Max.</abbr> <abbr title=\"Extension Mechanisms for " ..
|
||||
"Domain Name System\">EDNS0</abbr> packet size"),
|
||||
translate("Maximum allowed size of EDNS.0 UDP packets"))
|
||||
|
||||
em.optional = true
|
||||
em.datatype = "uinteger"
|
||||
em.placeholder = 1280
|
||||
|
||||
|
||||
cq = s:taboption("advanced", Value, "dnsforwardmax",
|
||||
translate("<abbr title=\"maximal\">Max.</abbr> concurrent queries"),
|
||||
translate("Maximum allowed number of concurrent DNS queries"))
|
||||
|
||||
cq.optional = true
|
||||
cq.datatype = "uinteger"
|
||||
cq.placeholder = 150
|
||||
|
||||
|
||||
s:taboption("tftp", Flag, "enable_tftp",
|
||||
translate("Enable TFTP server")).optional = true
|
||||
|
||||
tr = s:taboption("tftp", Value, "tftp_root",
|
||||
translate("TFTP server root"),
|
||||
translate("Root directory for files served via TFTP"))
|
||||
|
||||
tr.optional = true
|
||||
tr:depends("enable_tftp", "1")
|
||||
tr.placeholder = "/"
|
||||
|
||||
|
||||
db = s:taboption("tftp", Value, "dhcp_boot",
|
||||
translate("Network boot image"),
|
||||
translate("Filename of the boot image advertised to clients"))
|
||||
|
||||
db.optional = true
|
||||
db:depends("enable_tftp", "1")
|
||||
db.placeholder = "pxelinux.0"
|
||||
|
||||
o = s:taboption("general", Flag, "localservice",
|
||||
translate("Local Service Only"),
|
||||
translate("Limit DNS service to subnets interfaces on which we are serving DNS."))
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("general", Flag, "nonwildcard",
|
||||
translate("Non-wildcard"),
|
||||
translate("Bind only to specific interfaces rather than wildcard address."))
|
||||
o.optional = false
|
||||
o.rmempty = false
|
||||
|
||||
o = s:taboption("general", DynamicList, "interface",
|
||||
translate("Listen Interfaces"),
|
||||
translate("Limit listening to these interfaces, and loopback."))
|
||||
o.optional = true
|
||||
o:depends("nonwildcard", true)
|
||||
|
||||
o = s:taboption("general", DynamicList, "notinterface",
|
||||
translate("Exclude interfaces"),
|
||||
translate("Prevent listening on these interfaces."))
|
||||
o.optional = true
|
||||
o:depends("nonwildcard", true)
|
||||
|
||||
m:section(SimpleSection).template = "admin_network/lease_status"
|
||||
|
||||
s = m:section(TypedSection, "host", translate("Static Leases"),
|
||||
translate("Static leases are used to assign fixed IP addresses and symbolic hostnames to " ..
|
||||
"DHCP clients. They are also required for non-dynamic interface configurations where " ..
|
||||
"only hosts with a corresponding lease are served.") .. "<br />" ..
|
||||
translate("Use the <em>Add</em> Button to add a new lease entry. The <em>MAC-Address</em> " ..
|
||||
"indentifies the host, the <em>IPv4-Address</em> specifies to the fixed address to " ..
|
||||
"use and the <em>Hostname</em> is assigned as symbolic name to the requesting host. " ..
|
||||
"The optional <em>Lease time</em> can be used to set non-standard host-specific " ..
|
||||
"lease time, e.g. 12h, 3d or infinite."))
|
||||
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
name = s:option(Value, "name", translate("Hostname"))
|
||||
name.datatype = "hostname"
|
||||
name.rmempty = true
|
||||
|
||||
function name.write(self, section, value)
|
||||
Value.write(self, section, value)
|
||||
m:set(section, "dns", "1")
|
||||
end
|
||||
|
||||
function name.remove(self, section)
|
||||
Value.remove(self, section)
|
||||
m:del(section, "dns")
|
||||
end
|
||||
|
||||
mac = s:option(Value, "mac", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
|
||||
mac.datatype = "list(macaddr)"
|
||||
mac.rmempty = true
|
||||
|
||||
ip = s:option(Value, "ip", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
|
||||
ip.datatype = "or(ip4addr,'ignore')"
|
||||
|
||||
time = s:option(Value, "leasetime", translate("Lease time"))
|
||||
time.rmempty = true
|
||||
|
||||
hostid = s:option(Value, "hostid", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Suffix (hex)"))
|
||||
|
||||
ipc.neighbors({ family = 4 }, function(n)
|
||||
if n.mac and n.dest then
|
||||
ip:value(n.dest:string())
|
||||
mac:value(n.mac, "%s (%s)" %{ n.mac, n.dest:string() })
|
||||
end
|
||||
end)
|
||||
|
||||
function ip.validate(self, value, section)
|
||||
local m = mac:formvalue(section) or ""
|
||||
local n = name:formvalue(section) or ""
|
||||
if value and #n == 0 and #m == 0 then
|
||||
return nil, translate("One of hostname or mac address must be specified!")
|
||||
end
|
||||
return Value.validate(self, value, section)
|
||||
end
|
||||
|
||||
|
||||
return m
|
28
luci-mod-admin-full/luasrc/model/cbi/admin_network/hosts.lua
Normal file
28
luci-mod-admin-full/luasrc/model/cbi/admin_network/hosts.lua
Normal file
|
@ -0,0 +1,28 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2010-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local ipc = require "luci.ip"
|
||||
|
||||
m = Map("dhcp", translate("Hostnames"))
|
||||
|
||||
s = m:section(TypedSection, "domain", translate("Host entries"))
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
hn = s:option(Value, "name", translate("Hostname"))
|
||||
hn.datatype = "hostname"
|
||||
hn.rmempty = true
|
||||
|
||||
ip = s:option(Value, "ip", translate("IP address"))
|
||||
ip.datatype = "ipaddr"
|
||||
ip.rmempty = true
|
||||
|
||||
ipc.neighbors({ }, function(n)
|
||||
if n.mac and n.dest and not n.dest:is6linklocal() then
|
||||
ip:value(n.dest:string(), "%s (%s)" %{ n.dest:string(), n.mac })
|
||||
end
|
||||
end)
|
||||
|
||||
return m
|
113
luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua
Normal file
113
luci-mod-admin-full/luasrc/model/cbi/admin_network/iface_add.lua
Normal file
|
@ -0,0 +1,113 @@
|
|||
-- Copyright 2009-2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local nw = require "luci.model.network".init()
|
||||
local fw = require "luci.model.firewall".init()
|
||||
local utl = require "luci.util"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
|
||||
m = SimpleForm("network", translate("Create Interface"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/network/network")
|
||||
m.reset = false
|
||||
|
||||
newnet = m:field(Value, "_netname", translate("Name of the new interface"),
|
||||
translate("The allowed characters are: <code>A-Z</code>, <code>a-z</code>, " ..
|
||||
"<code>0-9</code> and <code>_</code>"
|
||||
))
|
||||
|
||||
newnet:depends("_attach", "")
|
||||
newnet.default = arg[1] and "net_" .. arg[1]:gsub("[^%w_]+", "_")
|
||||
newnet.datatype = "and(uciname,maxlength(15))"
|
||||
|
||||
advice = m:field(DummyValue, "d1", translate("Note: interface name length"),
|
||||
translate("Maximum length of the name is 15 characters including " ..
|
||||
"the automatic protocol/bridge prefix (br-, 6in4-, pppoe- etc.)"
|
||||
))
|
||||
|
||||
newproto = m:field(ListValue, "_netproto", translate("Protocol of the new interface"))
|
||||
|
||||
--netbridge = m:field(Flag, "_bridge", translate("Create a bridge over multiple interfaces"))
|
||||
|
||||
newtype = m:field(ListValue, "_type", translate("Type of the new interface"))
|
||||
newtype:value("", translate("Default"))
|
||||
newtype:value("macvlan", translate("Create a macvlan sub interface"))
|
||||
newtype:value("bridge", translate("Create a bridge over multiple interfaces"))
|
||||
|
||||
|
||||
sifname = m:field(Value, "_ifname", translate("Cover the following interface"))
|
||||
|
||||
sifname.widget = "radio"
|
||||
sifname.template = "cbi/network_ifacelist"
|
||||
sifname.nobridges = true
|
||||
|
||||
|
||||
mifname = m:field(Value, "_ifnames", translate("Cover the following interfaces"))
|
||||
|
||||
mifname.widget = "checkbox"
|
||||
mifname.template = "cbi/network_ifacelist"
|
||||
mifname.nobridges = true
|
||||
|
||||
vifname = m:field(Value, "_vifname", translate("Cover the following interface"))
|
||||
vifname.default = "eth0"
|
||||
|
||||
local _, p
|
||||
for _, p in ipairs(nw:get_protocols()) do
|
||||
if p:is_installed() then
|
||||
newproto:value(p:proto(), p:get_i18n())
|
||||
--if not p:is_virtual() then netbridge:depends("_netproto", p:proto()) end
|
||||
if not p:is_virtual() then newtype:depends("_netproto", p:proto()) end
|
||||
if not p:is_floating() then
|
||||
--sifname:depends({ _bridge = "", _netproto = p:proto()})
|
||||
--mifname:depends({ _bridge = "1", _netproto = p:proto()})
|
||||
sifname:depends({ _type = "", _netproto = p:proto() })
|
||||
mifname:depends({ _type = "bridge", _netproto = p:proto() })
|
||||
vifname:depends({ _type = "macvlan", _netproto = p:proto() })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function newproto.validate(self, value, section)
|
||||
local name = newnet:formvalue(section)
|
||||
if not name or #name == 0 then
|
||||
newnet:add_error(section, translate("No network name specified"))
|
||||
elseif m:get(name) then
|
||||
newnet:add_error(section, translate("The given network name is not unique"))
|
||||
end
|
||||
|
||||
local proto = nw:get_protocol(value)
|
||||
if proto and not proto:is_floating() then
|
||||
--local br = (netbridge:formvalue(section) == "1")
|
||||
--local ifn = br and mifname:formvalue(section) or sifname:formvalue(section)
|
||||
local ifn = ( (newtype:formvalue(section) == "macvlan" and name) or (newtype:formvalue(section) == "bridge" and mifname:formvalue(section)) or sifname:formvalue(section) )
|
||||
for ifn in utl.imatch(ifn) do
|
||||
return value
|
||||
end
|
||||
return nil, translate("The selected protocol needs a device assigned")
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
function newproto.write(self, section, value)
|
||||
local name = newnet:formvalue(section)
|
||||
if name and #name > 0 then
|
||||
--local br = (netbridge:formvalue(section) == "1") and "bridge" or nil
|
||||
--local net = nw:add_network(name, { proto = value, type = br })
|
||||
local isBridge = (newtype:formvalue(section) == "bridge") or nil
|
||||
local isMacvlan = (newtype:formvalue(section) == "macvlan") or nil
|
||||
local net = nw:add_network(name, { proto = value, type = newtype:formvalue(section), interface = isMacvlan and vifname:formvalue(section) or nil })
|
||||
if net then
|
||||
local ifn
|
||||
--br and mifname:formvalue(section) or sifname:formvalue(section)
|
||||
for ifn in utl.imatch(
|
||||
(isMacvlan and name) or (isBridge and mifname:formvalue(section)) or (sifname:formvalue(section))
|
||||
) do
|
||||
net:add_interface(ifn)
|
||||
end
|
||||
nw:save("network")
|
||||
nw:save("wireless")
|
||||
end
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/network", name))
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
547
luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua
Normal file
547
luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua
Normal file
|
@ -0,0 +1,547 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local ut = require "luci.util"
|
||||
local pt = require "luci.tools.proto"
|
||||
local nw = require "luci.model.network"
|
||||
local fw = require "luci.model.firewall"
|
||||
|
||||
arg[1] = arg[1] or ""
|
||||
|
||||
local has_dnsmasq = fs.access("/etc/config/dhcp")
|
||||
local has_firewall = fs.access("/etc/config/firewall")
|
||||
|
||||
m = Map("network", translate("Interfaces") .. " - " .. arg[1]:upper(), translate("On this page you can configure the network interfaces. You can bridge several interfaces by ticking the \"bridge interfaces\" field and enter the names of several network interfaces separated by spaces. You can also use <abbr title=\"Virtual Local Area Network\">VLAN</abbr> notation <samp>INTERFACE.VLANNR</samp> (<abbr title=\"for example\">e.g.</abbr>: <samp>eth0.1</samp>)."))
|
||||
m.redirect = luci.dispatcher.build_url("admin", "network", "network")
|
||||
m:chain("wireless")
|
||||
|
||||
if has_firewall then
|
||||
m:chain("firewall")
|
||||
end
|
||||
|
||||
nw.init(m.uci)
|
||||
fw.init(m.uci)
|
||||
|
||||
|
||||
local net = nw:get_network(arg[1])
|
||||
|
||||
local function backup_ifnames(is_bridge)
|
||||
if not net:is_floating() and not m:get(net:name(), "_orig_ifname") then
|
||||
local ifcs = net:get_interfaces() or { net:get_interface() }
|
||||
if ifcs then
|
||||
local _, ifn
|
||||
local ifns = { }
|
||||
for _, ifn in ipairs(ifcs) do
|
||||
ifns[#ifns+1] = ifn:name()
|
||||
end
|
||||
if #ifns > 0 then
|
||||
m:set(net:name(), "_orig_ifname", table.concat(ifns, " "))
|
||||
m:set(net:name(), "_orig_bridge", tostring(net:is_bridge()))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- redirect to overview page if network does not exist anymore (e.g. after a revert)
|
||||
if not net then
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
|
||||
return
|
||||
end
|
||||
|
||||
-- protocol switch was requested, rebuild interface config and reload page
|
||||
if m:formvalue("cbid.network.%s._switch" % net:name()) then
|
||||
-- get new protocol
|
||||
local ptype = m:formvalue("cbid.network.%s.proto" % net:name()) or "-"
|
||||
local proto = nw:get_protocol(ptype, net:name())
|
||||
if proto then
|
||||
-- backup default
|
||||
backup_ifnames()
|
||||
|
||||
-- if current proto is not floating and target proto is not floating,
|
||||
-- then attempt to retain the ifnames
|
||||
--error(net:proto() .. " > " .. proto:proto())
|
||||
if not net:is_floating() and not proto:is_floating() then
|
||||
-- if old proto is a bridge and new proto not, then clip the
|
||||
-- interface list to the first ifname only
|
||||
if net:is_bridge() and proto:is_virtual() then
|
||||
local _, ifn
|
||||
local first = true
|
||||
for _, ifn in ipairs(net:get_interfaces() or { net:get_interface() }) do
|
||||
if first then
|
||||
first = false
|
||||
else
|
||||
net:del_interface(ifn)
|
||||
end
|
||||
end
|
||||
m:del(net:name(), "type")
|
||||
end
|
||||
|
||||
-- if the current proto is floating, the target proto not floating,
|
||||
-- then attempt to restore ifnames from backup
|
||||
elseif net:is_floating() and not proto:is_floating() then
|
||||
-- if we have backup data, then re-add all orphaned interfaces
|
||||
-- from it and restore the bridge choice
|
||||
local br = (m:get(net:name(), "_orig_bridge") == "true")
|
||||
local ifn
|
||||
local ifns = { }
|
||||
for ifn in ut.imatch(m:get(net:name(), "_orig_ifname")) do
|
||||
ifn = nw:get_interface(ifn)
|
||||
if ifn and not ifn:get_network() then
|
||||
proto:add_interface(ifn)
|
||||
if not br then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if br then
|
||||
m:set(net:name(), "type", "bridge")
|
||||
end
|
||||
|
||||
-- in all other cases clear the ifnames
|
||||
else
|
||||
local _, ifc
|
||||
for _, ifc in ipairs(net:get_interfaces() or { net:get_interface() }) do
|
||||
net:del_interface(ifc)
|
||||
end
|
||||
m:del(net:name(), "type")
|
||||
end
|
||||
|
||||
-- clear options
|
||||
local k, v
|
||||
for k, v in pairs(m:get(net:name())) do
|
||||
if k:sub(1,1) ~= "." and
|
||||
k ~= "type" and
|
||||
k ~= "ifname" and
|
||||
k ~= "_orig_ifname" and
|
||||
k ~= "_orig_bridge"
|
||||
then
|
||||
m:del(net:name(), k)
|
||||
end
|
||||
end
|
||||
|
||||
-- set proto
|
||||
m:set(net:name(), "proto", proto:proto())
|
||||
m.uci:save("network")
|
||||
m.uci:save("wireless")
|
||||
|
||||
-- reload page
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/network", arg[1]))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- dhcp setup was requested, create section and reload page
|
||||
if m:formvalue("cbid.dhcp._enable._enable") then
|
||||
m.uci:section("dhcp", "dhcp", arg[1], {
|
||||
interface = arg[1],
|
||||
start = "100",
|
||||
limit = "150",
|
||||
leasetime = "12h"
|
||||
})
|
||||
|
||||
m.uci:save("dhcp")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/network", arg[1]))
|
||||
return
|
||||
end
|
||||
|
||||
local ifc = net:get_interface()
|
||||
|
||||
s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Setup"))
|
||||
s:tab("advanced", translate("Advanced Settings"))
|
||||
s:tab("physical", translate("Physical Settings"))
|
||||
|
||||
if has_firewall then
|
||||
s:tab("firewall", translate("Firewall Settings"))
|
||||
end
|
||||
|
||||
|
||||
st = s:taboption("general", DummyValue, "__status", translate("Status"))
|
||||
|
||||
local function set_status()
|
||||
-- if current network is empty, print a warning
|
||||
if not net:is_floating() and net:is_empty() then
|
||||
st.template = "cbi/dvalue"
|
||||
st.network = nil
|
||||
st.value = translate("There is no device assigned yet, please attach a network device in the \"Physical Settings\" tab")
|
||||
else
|
||||
st.template = "admin_network/iface_status"
|
||||
st.network = arg[1]
|
||||
st.value = nil
|
||||
end
|
||||
end
|
||||
|
||||
m.on_init = set_status
|
||||
m.on_after_save = set_status
|
||||
|
||||
l = s:taboption("general", Value, "label", translate("Label"))
|
||||
l.rmempty = true
|
||||
l:depends("multipath", "on")
|
||||
l:depends("multipath", "master")
|
||||
l:depends("multipath", "backup")
|
||||
l:depends("multipath", "handover")
|
||||
|
||||
p = s:taboption("general", ListValue, "proto", translate("Protocol"))
|
||||
p.default = net:proto()
|
||||
|
||||
|
||||
if not net:is_installed() then
|
||||
p_install = s:taboption("general", Button, "_install")
|
||||
p_install.title = translate("Protocol support is not installed")
|
||||
p_install.inputtitle = translate("Install package %q" % net:opkg_package())
|
||||
p_install.inputstyle = "apply"
|
||||
p_install:depends("proto", net:proto())
|
||||
|
||||
function p_install.write()
|
||||
return luci.http.redirect(
|
||||
luci.dispatcher.build_url("admin/system/packages") ..
|
||||
"?submit=1&install=%s" % net:opkg_package()
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
p_switch = s:taboption("general", Button, "_switch")
|
||||
p_switch.title = translate("Really switch protocol?")
|
||||
p_switch.inputtitle = translate("Switch protocol")
|
||||
p_switch.inputstyle = "apply"
|
||||
|
||||
local _, pr
|
||||
for _, pr in ipairs(nw:get_protocols()) do
|
||||
p:value(pr:proto(), pr:get_i18n())
|
||||
if pr:proto() ~= net:proto() then
|
||||
p_switch:depends("proto", pr:proto())
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
auto = s:taboption("advanced", Flag, "auto", translate("Bring up on boot"))
|
||||
auto.default = (net:proto() == "none") and auto.disabled or auto.enabled
|
||||
|
||||
-- Add MPTCP
|
||||
if fs.access("/proc/sys/net/mptcp") then
|
||||
mptcp = s:taboption("advanced", ListValue, "multipath", translate("Multipath TCP"))
|
||||
mptcp:value("on", translate("enabled"))
|
||||
mptcp:value("off", translate("disabled"))
|
||||
mptcp:value("master", translate("master"))
|
||||
mptcp:value("backup", translate("backup"))
|
||||
mptcp:value("handover", translate("handover"))
|
||||
mptcp.default = "off"
|
||||
end
|
||||
|
||||
delegate = s:taboption("advanced", Flag, "delegate", translate("Use builtin IPv6-management"))
|
||||
delegate.default = delegate.enabled
|
||||
|
||||
|
||||
if not net:is_virtual() then
|
||||
--br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
|
||||
--br.enabled = "bridge"
|
||||
--br.rmempty = true
|
||||
--br:depends("proto", "static")
|
||||
--br:depends("proto", "dhcp")
|
||||
--br:depends("proto", "none")
|
||||
iftype = s:taboption("physical", ListValue, "type", translate("Type of the interface"))
|
||||
iftype:value("", translate("Default"))
|
||||
iftype:value("macvlan", translate("Create a macvlan sub interface"))
|
||||
iftype:value("bridge", translate("Create a bridge over multiple interfaces"))
|
||||
iftype:depends("proto", "static")
|
||||
iftype:depends("proto", "dhcp")
|
||||
iftype:depends("proto", "none")
|
||||
|
||||
stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
|
||||
translate("Enables the Spanning Tree Protocol on this bridge"))
|
||||
stp:depends("type", "bridge")
|
||||
stp.rmempty = true
|
||||
-- macsource = s:taboption("physical", DynamicList, "vlanmacs", translate("Add MACs address to enable source mode"))
|
||||
-- macsource:depends("type", "macvlan")
|
||||
-- macsource.rmempty = true
|
||||
end
|
||||
|
||||
macvlanmaster = s:taboption("physical", Value, "interface", translate("Master interface"))
|
||||
macvlanmaster.default = "eth0"
|
||||
macvlanmaster:depends("type", "macvlan")
|
||||
|
||||
if not net:is_floating() then
|
||||
ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
|
||||
ifname_single.template = "cbi/network_ifacelist"
|
||||
ifname_single.widget = "radio"
|
||||
ifname_single.nobridges = true
|
||||
ifname_single.rmempty = false
|
||||
ifname_single.network = arg[1]
|
||||
ifname_single:depends("type", "")
|
||||
|
||||
function ifname_single.cfgvalue(self, s)
|
||||
-- let the template figure out the related ifaces through the network model
|
||||
return nil
|
||||
end
|
||||
|
||||
function ifname_single.write(self, s, val)
|
||||
local i
|
||||
local new_ifs = { }
|
||||
local old_ifs = { }
|
||||
|
||||
for _, i in ipairs(net:get_interfaces() or { net:get_interface() }) do
|
||||
old_ifs[#old_ifs+1] = i:name()
|
||||
end
|
||||
|
||||
for i in ut.imatch(val) do
|
||||
new_ifs[#new_ifs+1] = i
|
||||
|
||||
-- if this is not a bridge, only assign first interface
|
||||
if self.option == "ifname_single" then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(old_ifs)
|
||||
table.sort(new_ifs)
|
||||
|
||||
for i = 1, math.max(#old_ifs, #new_ifs) do
|
||||
if old_ifs[i] ~= new_ifs[i] then
|
||||
backup_ifnames()
|
||||
for i = 1, #old_ifs do
|
||||
net:del_interface(old_ifs[i])
|
||||
end
|
||||
for i = 1, #new_ifs do
|
||||
net:add_interface(new_ifs[i])
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if not net:is_virtual() then
|
||||
ifname_multi = s:taboption("physical", Value, "ifname_multi", translate("Interface"))
|
||||
ifname_multi.template = "cbi/network_ifacelist"
|
||||
ifname_multi.nobridges = true
|
||||
ifname_multi.rmempty = false
|
||||
ifname_multi.network = arg[1]
|
||||
ifname_multi.widget = "checkbox"
|
||||
ifname_multi:depends("type", "bridge")
|
||||
ifname_multi.cfgvalue = ifname_single.cfgvalue
|
||||
ifname_multi.write = ifname_single.write
|
||||
end
|
||||
|
||||
|
||||
if has_firewall then
|
||||
fwzone = s:taboption("firewall", Value, "_fwzone",
|
||||
translate("Create / Assign firewall-zone"),
|
||||
translate("Choose the firewall zone you want to assign to this interface. Select <em>unspecified</em> to remove the interface from the associated zone or fill out the <em>create</em> field to define a new zone and attach the interface to it."))
|
||||
|
||||
fwzone.template = "cbi/firewall_zonelist"
|
||||
fwzone.network = arg[1]
|
||||
fwzone.rmempty = false
|
||||
|
||||
function fwzone.cfgvalue(self, section)
|
||||
self.iface = section
|
||||
local z = fw:get_zone_by_network(section)
|
||||
return z and z:name()
|
||||
end
|
||||
|
||||
function fwzone.write(self, section, value)
|
||||
local zone = fw:get_zone(value)
|
||||
|
||||
if not zone and value == '-' then
|
||||
value = m:formvalue(self:cbid(section) .. ".newzone")
|
||||
if value and #value > 0 then
|
||||
zone = fw:add_zone(value)
|
||||
else
|
||||
fw:del_network(section)
|
||||
end
|
||||
end
|
||||
|
||||
if zone then
|
||||
fw:del_network(section)
|
||||
zone:add_network(section)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function p.write() end
|
||||
function p.remove() end
|
||||
function p.validate(self, value, section)
|
||||
if value == net:proto() then
|
||||
if not net:is_floating() and net:is_empty() then
|
||||
local ifn = ((br and (br:formvalue(section) == "bridge"))
|
||||
and ifname_multi:formvalue(section)
|
||||
or ifname_single:formvalue(section))
|
||||
for ifn in ut.imatch(ifn) do
|
||||
return value
|
||||
end
|
||||
return nil, translate("The selected protocol needs a device assigned")
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
|
||||
local form, ferr = loadfile(
|
||||
ut.libpath() .. "/model/cbi/admin_network/proto_%s.lua" % net:proto()
|
||||
)
|
||||
|
||||
if not form then
|
||||
s:taboption("general", DummyValue, "_error",
|
||||
translate("Missing protocol extension for proto %q" % net:proto())
|
||||
).value = ferr
|
||||
else
|
||||
setfenv(form, getfenv(1))(m, s, net)
|
||||
end
|
||||
|
||||
|
||||
local _, field
|
||||
for _, field in ipairs(s.children) do
|
||||
if field ~= st and field ~= p and field ~= p_install and field ~= p_switch then
|
||||
if next(field.deps) then
|
||||
local _, dep
|
||||
for _, dep in ipairs(field.deps) do
|
||||
dep.proto = net:proto()
|
||||
end
|
||||
else
|
||||
field:depends("proto", net:proto())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Display DNS settings if dnsmasq is available
|
||||
--
|
||||
|
||||
if has_dnsmasq and net:proto() == "static" then
|
||||
m2 = Map("dhcp", "", "")
|
||||
|
||||
local has_section = false
|
||||
|
||||
m2.uci:foreach("dhcp", "dhcp", function(s)
|
||||
if s.interface == arg[1] then
|
||||
has_section = true
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
if not has_section and has_dnsmasq then
|
||||
|
||||
s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
|
||||
s.anonymous = true
|
||||
s.cfgsections = function() return { "_enable" } end
|
||||
|
||||
x = s:option(Button, "_enable")
|
||||
x.title = translate("No DHCP Server configured for this interface")
|
||||
x.inputtitle = translate("Setup DHCP Server")
|
||||
x.inputstyle = "apply"
|
||||
|
||||
elseif has_section then
|
||||
|
||||
s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
|
||||
s.addremove = false
|
||||
s.anonymous = true
|
||||
s:tab("general", translate("General Setup"))
|
||||
s:tab("advanced", translate("Advanced Settings"))
|
||||
s:tab("ipv6", translate("IPv6 Settings"))
|
||||
|
||||
function s.filter(self, section)
|
||||
return m2.uci:get("dhcp", section, "interface") == arg[1]
|
||||
end
|
||||
|
||||
local ignore = s:taboption("general", Flag, "ignore",
|
||||
translate("Ignore interface"),
|
||||
translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
|
||||
"this interface."))
|
||||
|
||||
local start = s:taboption("general", Value, "start", translate("Start"),
|
||||
translate("Lowest leased address as offset from the network address."))
|
||||
start.optional = true
|
||||
start.datatype = "or(uinteger,ip4addr)"
|
||||
start.default = "100"
|
||||
|
||||
local limit = s:taboption("general", Value, "limit", translate("Limit"),
|
||||
translate("Maximum number of leased addresses."))
|
||||
limit.optional = true
|
||||
limit.datatype = "uinteger"
|
||||
limit.default = "150"
|
||||
|
||||
local ltime = s:taboption("general", Value, "leasetime", translate("Lease time"),
|
||||
translate("Expiry time of leased addresses, minimum is 2 minutes (<code>2m</code>)."))
|
||||
ltime.rmempty = true
|
||||
ltime.default = "12h"
|
||||
|
||||
local dd = s:taboption("advanced", Flag, "dynamicdhcp",
|
||||
translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
|
||||
translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
|
||||
"clients having static leases will be served."))
|
||||
dd.default = dd.enabled
|
||||
|
||||
s:taboption("advanced", Flag, "force", translate("Force"),
|
||||
translate("Force DHCP on this network even if another server is detected."))
|
||||
|
||||
-- XXX: is this actually useful?
|
||||
--s:taboption("advanced", Value, "name", translate("Name"),
|
||||
-- translate("Define a name for this network."))
|
||||
|
||||
mask = s:taboption("advanced", Value, "netmask",
|
||||
translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
|
||||
translate("Override the netmask sent to clients. Normally it is calculated " ..
|
||||
"from the subnet that is served."))
|
||||
|
||||
mask.optional = true
|
||||
mask.datatype = "ip4addr"
|
||||
|
||||
s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
|
||||
translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
|
||||
"192.168.2.2</code>\" which advertises different DNS servers to clients."))
|
||||
|
||||
for i, n in ipairs(s.children) do
|
||||
if n ~= ignore then
|
||||
n:depends("ignore", "")
|
||||
end
|
||||
end
|
||||
|
||||
o = s:taboption("ipv6", ListValue, "ra", translate("Router Advertisement-Service"))
|
||||
o:value("", translate("disabled"))
|
||||
o:value("server", translate("server mode"))
|
||||
o:value("relay", translate("relay mode"))
|
||||
o:value("hybrid", translate("hybrid mode"))
|
||||
|
||||
o = s:taboption("ipv6", ListValue, "dhcpv6", translate("DHCPv6-Service"))
|
||||
o:value("", translate("disabled"))
|
||||
o:value("server", translate("server mode"))
|
||||
o:value("relay", translate("relay mode"))
|
||||
o:value("hybrid", translate("hybrid mode"))
|
||||
|
||||
o = s:taboption("ipv6", ListValue, "ndp", translate("NDP-Proxy"))
|
||||
o:value("", translate("disabled"))
|
||||
o:value("relay", translate("relay mode"))
|
||||
o:value("hybrid", translate("hybrid mode"))
|
||||
|
||||
o = s:taboption("ipv6", ListValue, "ra_management", translate("DHCPv6-Mode"),
|
||||
translate("Default is stateless + stateful"))
|
||||
o:value("0", translate("stateless"))
|
||||
o:value("1", translate("stateless + stateful"))
|
||||
o:value("2", translate("stateful-only"))
|
||||
o:depends("dhcpv6", "server")
|
||||
o:depends("dhcpv6", "hybrid")
|
||||
o.default = "1"
|
||||
|
||||
o = s:taboption("ipv6", Flag, "ra_default", translate("Always announce default router"),
|
||||
translate("Announce as default router even if no public prefix is available."))
|
||||
o:depends("ra", "server")
|
||||
o:depends("ra", "hybrid")
|
||||
|
||||
s:taboption("ipv6", DynamicList, "dns", translate("Announced DNS servers"))
|
||||
s:taboption("ipv6", DynamicList, "domain", translate("Announced DNS domains"))
|
||||
|
||||
else
|
||||
m2 = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return m, m2
|
134
luci-mod-admin-full/luasrc/model/cbi/admin_network/network.lua
Normal file
134
luci-mod-admin-full/luasrc/model/cbi/admin_network/network.lua
Normal file
|
@ -0,0 +1,134 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
|
||||
m = Map("network", translate("Interfaces"))
|
||||
m.pageaction = false
|
||||
m:section(SimpleSection).template = "admin_network/iface_overview"
|
||||
|
||||
if fs.access("/etc/init.d/dsl_control") then
|
||||
dsl = m:section(TypedSection, "dsl", translate("DSL"))
|
||||
|
||||
dsl.anonymous = true
|
||||
|
||||
annex = dsl:option(ListValue, "annex", translate("Annex"))
|
||||
annex:value("a", translate("Annex A + L + M (all)"))
|
||||
annex:value("b", translate("Annex B (all)"))
|
||||
annex:value("j", translate("Annex J (all)"))
|
||||
annex:value("m", translate("Annex M (all)"))
|
||||
annex:value("bdmt", translate("Annex B G.992.1"))
|
||||
annex:value("b2", translate("Annex B G.992.3"))
|
||||
annex:value("b2p", translate("Annex B G.992.5"))
|
||||
annex:value("at1", translate("ANSI T1.413"))
|
||||
annex:value("admt", translate("Annex A G.992.1"))
|
||||
annex:value("alite", translate("Annex A G.992.2"))
|
||||
annex:value("a2", translate("Annex A G.992.3"))
|
||||
annex:value("a2p", translate("Annex A G.992.5"))
|
||||
annex:value("l", translate("Annex L G.992.3 POTS 1"))
|
||||
annex:value("m2", translate("Annex M G.992.3"))
|
||||
annex:value("m2p", translate("Annex M G.992.5"))
|
||||
|
||||
tone = dsl:option(ListValue, "tone", translate("Tone"))
|
||||
tone:value("", translate("auto"))
|
||||
tone:value("a", translate("A43C + J43 + A43"))
|
||||
tone:value("av", translate("A43C + J43 + A43 + V43"))
|
||||
tone:value("b", translate("B43 + B43C"))
|
||||
tone:value("bv", translate("B43 + B43C + V43"))
|
||||
|
||||
xfer_mode = dsl:option(ListValue, "xfer_mode", translate("Encapsulation mode"))
|
||||
xfer_mode:value("atm", translate("ATM (Asynchronous Transfer Mode)"))
|
||||
xfer_mode:value("ptm", translate("PTM/EFM (Packet Transfer Mode)"))
|
||||
|
||||
line_mode = dsl:option(ListValue, "line_mode", translate("DSL line mode"))
|
||||
line_mode:value("", translate("auto"))
|
||||
line_mode:value("adsl", translate("ADSL"))
|
||||
line_mode:value("vdsl", translate("VDSL"))
|
||||
|
||||
firmware = dsl:option(Value, "firmware", translate("Firmware File"))
|
||||
|
||||
m.pageaction = true
|
||||
end
|
||||
|
||||
-- Show ATM bridge section if we have the capabilities
|
||||
if fs.access("/usr/sbin/br2684ctl") then
|
||||
atm = m:section(TypedSection, "atm-bridge", translate("ATM Bridges"),
|
||||
translate("ATM bridges expose encapsulated ethernet in AAL5 " ..
|
||||
"connections as virtual Linux network interfaces which can " ..
|
||||
"be used in conjunction with DHCP or PPP to dial into the " ..
|
||||
"provider network."))
|
||||
|
||||
atm.addremove = true
|
||||
atm.anonymous = true
|
||||
|
||||
atm.create = function(self, section)
|
||||
local sid = TypedSection.create(self, section)
|
||||
local max_unit = -1
|
||||
|
||||
m.uci:foreach("network", "atm-bridge",
|
||||
function(s)
|
||||
local u = tonumber(s.unit)
|
||||
if u ~= nil and u > max_unit then
|
||||
max_unit = u
|
||||
end
|
||||
end)
|
||||
|
||||
m.uci:set("network", sid, "unit", max_unit + 1)
|
||||
m.uci:set("network", sid, "atmdev", 0)
|
||||
m.uci:set("network", sid, "encaps", "llc")
|
||||
m.uci:set("network", sid, "payload", "bridged")
|
||||
m.uci:set("network", sid, "vci", 35)
|
||||
m.uci:set("network", sid, "vpi", 8)
|
||||
|
||||
return sid
|
||||
end
|
||||
|
||||
atm:tab("general", translate("General Setup"))
|
||||
atm:tab("advanced", translate("Advanced Settings"))
|
||||
|
||||
vci = atm:taboption("general", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
|
||||
vpi = atm:taboption("general", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
|
||||
encaps = atm:taboption("general", ListValue, "encaps", translate("Encapsulation mode"))
|
||||
encaps:value("llc", translate("LLC"))
|
||||
encaps:value("vc", translate("VC-Mux"))
|
||||
|
||||
atmdev = atm:taboption("advanced", Value, "atmdev", translate("ATM device number"))
|
||||
unit = atm:taboption("advanced", Value, "unit", translate("Bridge unit number"))
|
||||
payload = atm:taboption("advanced", ListValue, "payload", translate("Forwarding mode"))
|
||||
payload:value("bridged", translate("bridged"))
|
||||
payload:value("routed", translate("routed"))
|
||||
m.pageaction = true
|
||||
end
|
||||
|
||||
local network = require "luci.model.network"
|
||||
local s = m:section(NamedSection, "globals", "globals", translate("Global network options"))
|
||||
if network:has_ipv6() then
|
||||
local o = s:option(Value, "ula_prefix", translate("IPv6 ULA-Prefix"))
|
||||
o.datatype = "ip6addr"
|
||||
o.rmempty = true
|
||||
end
|
||||
if fs.access("/proc/sys/net/mptcp") then
|
||||
local mtcp = s:option(ListValue, "multipath", translate("Multipath TCP"))
|
||||
mtcp:value("enable", translate("enable"))
|
||||
mtcp:value("disable", translate("disable"))
|
||||
local mtcppm = s:option(ListValue, "mptcp_path_manager", translate("Multipath TCP path-manager"))
|
||||
mtcppm:value("default", translate("default"))
|
||||
mtcppm:value("fullmesh", translate("fullmesh"))
|
||||
mtcppm:value("ndiffports", translate("ndiffports"))
|
||||
mtcppm:value("blinder", translate("blinder"))
|
||||
local mtcpsch = s:option(ListValue, "mptcp_scheduler", translate("Multipath TCP scheduler"))
|
||||
mtcpsch:value("default", translate("default"))
|
||||
mtcpsch:value("roundrobin", translate("round-robin"))
|
||||
mtcpsch:value("redundant", translate("redundant"))
|
||||
local congestion = s:option(ListValue, "congestion", translate("Congestion Control"))
|
||||
local availablecong = sys.exec("sysctl net.ipv4.tcp_available_congestion_control | awk -F'= ' '{print $NF}'")
|
||||
for cong in string.gmatch(availablecong, "[^%s]+") do
|
||||
congestion:value(cong, translate(cong))
|
||||
end
|
||||
end
|
||||
m.pageaction = true
|
||||
|
||||
|
||||
return m
|
|
@ -0,0 +1,67 @@
|
|||
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local map, section, net = ...
|
||||
|
||||
local device, apn, service, pincode, username, password
|
||||
local ipv6, maxwait, defaultroute, metric, peerdns, dns,
|
||||
keepalive_failure, keepalive_interval, demand
|
||||
|
||||
|
||||
mca = s:taboption("ahcp", Value, "multicast_address", translate("Multicast address"))
|
||||
mca.optional = true
|
||||
mca.placeholder = "ff02::cca6:c0f9:e182:5359"
|
||||
mca.datatype = "ip6addr"
|
||||
mca:depends("proto", "ahcp")
|
||||
|
||||
port = s:taboption("ahcp", Value, "port", translate("Port"))
|
||||
port.optional = true
|
||||
port.placeholder = 5359
|
||||
port.datatype = "port"
|
||||
port:depends("proto", "ahcp")
|
||||
|
||||
fam = s:taboption("ahcp", ListValue, "_family", translate("Protocol family"))
|
||||
fam:value("", translate("IPv4 and IPv6"))
|
||||
fam:value("ipv4", translate("IPv4 only"))
|
||||
fam:value("ipv6", translate("IPv6 only"))
|
||||
fam:depends("proto", "ahcp")
|
||||
|
||||
function fam.cfgvalue(self, section)
|
||||
local v4 = m.uci:get_bool("network", section, "ipv4_only")
|
||||
local v6 = m.uci:get_bool("network", section, "ipv6_only")
|
||||
if v4 then
|
||||
return "ipv4"
|
||||
elseif v6 then
|
||||
return "ipv6"
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
function fam.write(self, section, value)
|
||||
if value == "ipv4" then
|
||||
m.uci:set("network", section, "ipv4_only", "true")
|
||||
m.uci:delete("network", section, "ipv6_only")
|
||||
elseif value == "ipv6" then
|
||||
m.uci:set("network", section, "ipv6_only", "true")
|
||||
m.uci:delete("network", section, "ipv4_only")
|
||||
end
|
||||
end
|
||||
|
||||
function fam.remove(self, section)
|
||||
m.uci:delete("network", section, "ipv4_only")
|
||||
m.uci:delete("network", section, "ipv6_only")
|
||||
end
|
||||
|
||||
nodns = s:taboption("ahcp", Flag, "no_dns", translate("Disable DNS setup"))
|
||||
nodns.optional = true
|
||||
nodns.enabled = "true"
|
||||
nodns.disabled = "false"
|
||||
nodns.default = nodns.disabled
|
||||
nodns:depends("proto", "ahcp")
|
||||
|
||||
ltime = s:taboption("ahcp", Value, "lease_time", translate("Lease validity time"))
|
||||
ltime.optional = true
|
||||
ltime.placeholder = 3666
|
||||
ltime.datatype = "uinteger"
|
||||
ltime:depends("proto", "ahcp")
|
||||
|
102
luci-mod-admin-full/luasrc/model/cbi/admin_network/routes.lua
Normal file
102
luci-mod-admin-full/luasrc/model/cbi/admin_network/routes.lua
Normal file
|
@ -0,0 +1,102 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
m = Map("network",
|
||||
translate("Routes"),
|
||||
translate("Routes specify over which interface and gateway a certain host or network " ..
|
||||
"can be reached."))
|
||||
|
||||
s = m:section(TypedSection, "route", translate("Static IPv4 Routes"))
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
iface = s:option(ListValue, "interface", translate("Interface"))
|
||||
wa.cbi_add_networks(iface)
|
||||
|
||||
t = s:option(Value, "target", translate("Target"), translate("Host-<abbr title=\"Internet Protocol Address\">IP</abbr> or Network"))
|
||||
t.datatype = "ip4addr"
|
||||
t.rmempty = false
|
||||
|
||||
n = s:option(Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"), translate("if target is a network"))
|
||||
n.placeholder = "255.255.255.255"
|
||||
n.datatype = "ip4addr"
|
||||
n.rmempty = true
|
||||
|
||||
g = s:option(Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
|
||||
g.datatype = "ip4addr"
|
||||
g.rmempty = true
|
||||
|
||||
metric = s:option(Value, "metric", translate("Metric"))
|
||||
metric.placeholder = 0
|
||||
metric.datatype = "range(0,255)"
|
||||
metric.size = 5
|
||||
metric.rmempty = true
|
||||
|
||||
mtu = s:option(Value, "mtu", translate("MTU"))
|
||||
mtu.placeholder = 1500
|
||||
mtu.datatype = "range(64,9000)"
|
||||
mtu.size = 5
|
||||
mtu.rmempty = true
|
||||
|
||||
routetype = s:option(Value, "type", translate("Route type"))
|
||||
routetype:value("", "unicast")
|
||||
routetype:value("local", "local")
|
||||
routetype:value("broadcast", "broadcast")
|
||||
routetype:value("multicast", "multicast")
|
||||
routetype:value("unreachable", "unreachable")
|
||||
routetype:value("prohibit", "prohibit")
|
||||
routetype:value("blackhole", "blackhole")
|
||||
routetype:value("anycast", "anycast")
|
||||
routetype.default = ""
|
||||
routetype.rmempty = true
|
||||
|
||||
if fs.access("/proc/net/ipv6_route") then
|
||||
s = m:section(TypedSection, "route6", translate("Static IPv6 Routes"))
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
s.template = "cbi/tblsection"
|
||||
|
||||
iface = s:option(ListValue, "interface", translate("Interface"))
|
||||
wa.cbi_add_networks(iface)
|
||||
|
||||
t = s:option(Value, "target", translate("Target"), translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address or Network (CIDR)"))
|
||||
t.datatype = "ip6addr"
|
||||
t.rmempty = false
|
||||
|
||||
g = s:option(Value, "gateway", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
|
||||
g.datatype = "ip6addr"
|
||||
g.rmempty = true
|
||||
|
||||
metric = s:option(Value, "metric", translate("Metric"))
|
||||
metric.placeholder = 0
|
||||
metric.datatype = "range(0,65535)" -- XXX: not sure
|
||||
metric.size = 5
|
||||
metric.rmempty = true
|
||||
|
||||
mtu = s:option(Value, "mtu", translate("MTU"))
|
||||
mtu.placeholder = 1500
|
||||
mtu.datatype = "range(64,9000)"
|
||||
mtu.size = 5
|
||||
mtu.rmempty = true
|
||||
|
||||
routetype = s:option(Value, "type", translate("Route type"))
|
||||
routetype:value("", "unicast")
|
||||
routetype:value("local", "local")
|
||||
routetype:value("broadcast", "broadcast")
|
||||
routetype:value("multicast", "multicast")
|
||||
routetype:value("unreachable", "unreachable")
|
||||
routetype:value("prohibit", "prohibit")
|
||||
routetype:value("blackhole", "blackhole")
|
||||
routetype:value("anycast", "anycast")
|
||||
routetype.default = ""
|
||||
routetype.rmempty = true
|
||||
end
|
||||
|
||||
|
||||
return m
|
363
luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua
Normal file
363
luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua
Normal file
|
@ -0,0 +1,363 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2010-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
m = Map("network", translate("Switch"), translate("The network ports on this device can be combined to several <abbr title=\"Virtual Local Area Network\">VLAN</abbr>s in which computers can communicate directly with each other. <abbr title=\"Virtual Local Area Network\">VLAN</abbr>s are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network."))
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local nw = require "luci.model.network"
|
||||
local switches = { }
|
||||
|
||||
nw.init(m.uci)
|
||||
|
||||
local topologies = nw:get_switch_topologies() or {}
|
||||
|
||||
local update_interfaces = function(old_ifname, new_ifname)
|
||||
local info = { }
|
||||
|
||||
m.uci:foreach("network", "interface", function(section)
|
||||
local old_ifnames = m.uci:get("network", section[".name"], "ifname")
|
||||
local new_ifnames = { }
|
||||
local cur_ifname
|
||||
local changed = false
|
||||
for cur_ifname in luci.util.imatch(old_ifnames) do
|
||||
if cur_ifname == old_ifname then
|
||||
new_ifnames[#new_ifnames+1] = new_ifname
|
||||
changed = true
|
||||
else
|
||||
new_ifnames[#new_ifnames+1] = cur_ifname
|
||||
end
|
||||
end
|
||||
if changed then
|
||||
m.uci:set("network", section[".name"], "ifname", table.concat(new_ifnames, " "))
|
||||
|
||||
info[#info+1] = translatef("Interface %q device auto-migrated from %q to %q.",
|
||||
section[".name"], old_ifname, new_ifname)
|
||||
end
|
||||
end)
|
||||
|
||||
if #info > 0 then
|
||||
m.message = (m.message and m.message .. "\n" or "") .. table.concat(info, "\n")
|
||||
end
|
||||
end
|
||||
|
||||
m.uci:foreach("network", "switch",
|
||||
function(x)
|
||||
local sid = x['.name']
|
||||
local switch_name = x.name or sid
|
||||
local has_vlan = nil
|
||||
local has_learn = nil
|
||||
local has_vlan4k = nil
|
||||
local has_jumbo3 = nil
|
||||
local has_mirror = nil
|
||||
local min_vid = 0
|
||||
local max_vid = 16
|
||||
local num_vlans = 16
|
||||
|
||||
local switch_title
|
||||
local enable_vlan4k = false
|
||||
|
||||
local topo = topologies[switch_name]
|
||||
|
||||
if not topo then
|
||||
m.message = translatef("Switch %q has an unknown topology - the VLAN settings might not be accurate.", switch_name)
|
||||
topo = {
|
||||
ports = {
|
||||
{ num = 0, label = "Port 1" },
|
||||
{ num = 1, label = "Port 2" },
|
||||
{ num = 2, label = "Port 3" },
|
||||
{ num = 3, label = "Port 4" },
|
||||
{ num = 4, label = "Port 5" },
|
||||
{ num = 5, label = "CPU (eth0)", tagged = false }
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
-- Parse some common switch properties from swconfig help output.
|
||||
local swc = io.popen("swconfig dev %q help 2>/dev/null" % switch_name)
|
||||
if swc then
|
||||
|
||||
local is_port_attr = false
|
||||
local is_vlan_attr = false
|
||||
|
||||
while true do
|
||||
local line = swc:read("*l")
|
||||
if not line then break end
|
||||
|
||||
if line:match("^%s+%-%-vlan") then
|
||||
is_vlan_attr = true
|
||||
|
||||
elseif line:match("^%s+%-%-port") then
|
||||
is_vlan_attr = false
|
||||
is_port_attr = true
|
||||
|
||||
elseif line:match("cpu @") then
|
||||
switch_title = line:match("^switch%d: %w+%((.-)%)")
|
||||
num_vlans = tonumber(line:match("vlans: (%d+)")) or 16
|
||||
min_vid = 1
|
||||
|
||||
elseif line:match(": pvid") or line:match(": tag") or line:match(": vid") then
|
||||
if is_vlan_attr then has_vlan4k = line:match(": (%w+)") end
|
||||
|
||||
elseif line:match(": enable_vlan4k") then
|
||||
enable_vlan4k = true
|
||||
|
||||
elseif line:match(": enable_vlan") then
|
||||
has_vlan = "enable_vlan"
|
||||
|
||||
elseif line:match(": enable_learning") then
|
||||
has_learn = "enable_learning"
|
||||
|
||||
elseif line:match(": enable_mirror_rx") then
|
||||
has_mirror = "enable_mirror_rx"
|
||||
|
||||
elseif line:match(": max_length") then
|
||||
has_jumbo3 = "max_length"
|
||||
end
|
||||
end
|
||||
|
||||
swc:close()
|
||||
end
|
||||
|
||||
|
||||
-- Switch properties
|
||||
s = m:section(NamedSection, x['.name'], "switch",
|
||||
switch_title and translatef("Switch %q (%s)", switch_name, switch_title)
|
||||
or translatef("Switch %q", switch_name))
|
||||
|
||||
s.addremove = false
|
||||
|
||||
if has_vlan then
|
||||
s:option(Flag, has_vlan, translate("Enable VLAN functionality"))
|
||||
end
|
||||
|
||||
if has_learn then
|
||||
x = s:option(Flag, has_learn, translate("Enable learning and aging"))
|
||||
x.default = x.enabled
|
||||
end
|
||||
|
||||
if has_jumbo3 then
|
||||
x = s:option(Flag, has_jumbo3, translate("Enable Jumbo Frame passthrough"))
|
||||
x.enabled = "3"
|
||||
x.rmempty = true
|
||||
end
|
||||
|
||||
-- Does this switch support port mirroring?
|
||||
if has_mirror then
|
||||
s:option(Flag, "enable_mirror_rx", translate("Enable mirroring of incoming packets"))
|
||||
s:option(Flag, "enable_mirror_tx", translate("Enable mirroring of outgoing packets"))
|
||||
|
||||
local sp = s:option(ListValue, "mirror_source_port", translate("Mirror source port"))
|
||||
local mp = s:option(ListValue, "mirror_monitor_port", translate("Mirror monitor port"))
|
||||
|
||||
sp:depends("enable_mirror_tx", "1")
|
||||
sp:depends("enable_mirror_rx", "1")
|
||||
|
||||
mp:depends("enable_mirror_tx", "1")
|
||||
mp:depends("enable_mirror_rx", "1")
|
||||
|
||||
local _, pt
|
||||
for _, pt in ipairs(topo.ports) do
|
||||
sp:value(pt.num, pt.label)
|
||||
mp:value(pt.num, pt.label)
|
||||
end
|
||||
end
|
||||
|
||||
-- VLAN table
|
||||
s = m:section(TypedSection, "switch_vlan",
|
||||
switch_title and translatef("VLANs on %q (%s)", switch_name, switch_title)
|
||||
or translatef("VLANs on %q", switch_name))
|
||||
|
||||
s.template = "cbi/tblsection"
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
-- Filter by switch
|
||||
s.filter = function(self, section)
|
||||
local device = m:get(section, "device")
|
||||
return (device and device == switch_name)
|
||||
end
|
||||
|
||||
-- Override cfgsections callback to enforce row ordering by vlan id.
|
||||
s.cfgsections = function(self)
|
||||
local osections = TypedSection.cfgsections(self)
|
||||
local sections = { }
|
||||
local section
|
||||
|
||||
for _, section in luci.util.spairs(
|
||||
osections,
|
||||
function(a, b)
|
||||
return (tonumber(m:get(osections[a], has_vlan4k or "vlan")) or 9999)
|
||||
< (tonumber(m:get(osections[b], has_vlan4k or "vlan")) or 9999)
|
||||
end
|
||||
) do
|
||||
sections[#sections+1] = section
|
||||
end
|
||||
|
||||
return sections
|
||||
end
|
||||
|
||||
-- When creating a new vlan, preset it with the highest found vid + 1.
|
||||
s.create = function(self, section, origin)
|
||||
-- Filter by switch
|
||||
if m:get(origin, "device") ~= switch_name then
|
||||
return
|
||||
end
|
||||
|
||||
local sid = TypedSection.create(self, section)
|
||||
|
||||
local max_nr = 0
|
||||
local max_id = 0
|
||||
|
||||
m.uci:foreach("network", "switch_vlan",
|
||||
function(s)
|
||||
if s.device == switch_name then
|
||||
local nr = tonumber(s.vlan)
|
||||
local id = has_vlan4k and tonumber(s[has_vlan4k])
|
||||
if nr ~= nil and nr > max_nr then max_nr = nr end
|
||||
if id ~= nil and id > max_id then max_id = id end
|
||||
end
|
||||
end)
|
||||
|
||||
m:set(sid, "device", switch_name)
|
||||
m:set(sid, "vlan", max_nr + 1)
|
||||
|
||||
if has_vlan4k then
|
||||
m:set(sid, has_vlan4k, max_id + 1)
|
||||
end
|
||||
|
||||
return sid
|
||||
end
|
||||
|
||||
|
||||
local port_opts = { }
|
||||
local untagged = { }
|
||||
|
||||
-- Parse current tagging state from the "ports" option.
|
||||
local portvalue = function(self, section)
|
||||
local pt
|
||||
for pt in (m:get(section, "ports") or ""):gmatch("%w+") do
|
||||
local pc, tu = pt:match("^(%d+)([tu]*)")
|
||||
if pc == self.option then return (#tu > 0) and tu or "u" end
|
||||
end
|
||||
return ""
|
||||
end
|
||||
|
||||
-- Validate port tagging. Ensure that a port is only untagged once,
|
||||
-- bail out if not.
|
||||
local portvalidate = function(self, value, section)
|
||||
-- ensure that the ports appears untagged only once
|
||||
if value == "u" then
|
||||
if not untagged[self.option] then
|
||||
untagged[self.option] = true
|
||||
else
|
||||
return nil,
|
||||
translatef("%s is untagged in multiple VLANs!", self.title)
|
||||
end
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
|
||||
local vid = s:option(Value, has_vlan4k or "vlan", "VLAN ID", "<div id='portstatus-%s'></div>" % switch_name)
|
||||
local mx_vid = has_vlan4k and 4094 or (num_vlans - 1)
|
||||
|
||||
vid.rmempty = false
|
||||
vid.forcewrite = true
|
||||
vid.vlan_used = { }
|
||||
vid.datatype = "and(uinteger,range("..min_vid..","..mx_vid.."))"
|
||||
|
||||
-- Validate user provided VLAN ID, make sure its within the bounds
|
||||
-- allowed by the switch.
|
||||
vid.validate = function(self, value, section)
|
||||
local v = tonumber(value)
|
||||
local m = has_vlan4k and 4094 or (num_vlans - 1)
|
||||
if v ~= nil and v >= min_vid and v <= m then
|
||||
if not self.vlan_used[v] then
|
||||
self.vlan_used[v] = true
|
||||
return value
|
||||
else
|
||||
return nil,
|
||||
translatef("Invalid VLAN ID given! Only unique IDs are allowed")
|
||||
end
|
||||
else
|
||||
return nil,
|
||||
translatef("Invalid VLAN ID given! Only IDs between %d and %d are allowed.", min_vid, m)
|
||||
end
|
||||
end
|
||||
|
||||
-- When writing the "vid" or "vlan" option, serialize the port states
|
||||
-- as well and write them as "ports" option to uci.
|
||||
vid.write = function(self, section, new_vid)
|
||||
local o
|
||||
local p = { }
|
||||
for _, o in ipairs(port_opts) do
|
||||
local new_tag = o:formvalue(section)
|
||||
if new_tag == "t" then
|
||||
p[#p+1] = o.option .. new_tag
|
||||
elseif new_tag == "u" then
|
||||
p[#p+1] = o.option
|
||||
end
|
||||
|
||||
if o.info and o.info.device then
|
||||
local old_tag = o:cfgvalue(section)
|
||||
local old_vid = self:cfgvalue(section)
|
||||
if old_tag ~= new_tag or old_vid ~= new_vid then
|
||||
local old_ifname = (old_tag == "u") and o.info.device
|
||||
or "%s.%s" %{ o.info.device, old_vid }
|
||||
|
||||
local new_ifname = (new_tag == "u") and o.info.device
|
||||
or "%s.%s" %{ o.info.device, new_vid }
|
||||
|
||||
if old_ifname ~= new_ifname then
|
||||
update_interfaces(old_ifname, new_ifname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if enable_vlan4k then
|
||||
m:set(sid, "enable_vlan4k", "1")
|
||||
end
|
||||
|
||||
m:set(section, "ports", table.concat(p, " "))
|
||||
return Value.write(self, section, new_vid)
|
||||
end
|
||||
|
||||
-- Fallback to "vlan" option if "vid" option is supported but unset.
|
||||
vid.cfgvalue = function(self, section)
|
||||
return m:get(section, has_vlan4k or "vlan")
|
||||
or m:get(section, "vlan")
|
||||
end
|
||||
|
||||
local _, pt
|
||||
for _, pt in ipairs(topo.ports) do
|
||||
local po = s:option(ListValue, tostring(pt.num), pt.label, '<div id="portstatus-%s-%d"></div>' %{ switch_name, pt.num })
|
||||
|
||||
po:value("", translate("off"))
|
||||
|
||||
if not pt.tagged then
|
||||
po:value("u", translate("untagged"))
|
||||
end
|
||||
|
||||
po:value("t", translate("tagged"))
|
||||
|
||||
po.cfgvalue = portvalue
|
||||
po.validate = portvalidate
|
||||
po.write = function() end
|
||||
po.info = pt
|
||||
|
||||
port_opts[#port_opts+1] = po
|
||||
end
|
||||
|
||||
table.sort(port_opts, function(a, b) return a.option < b.option end)
|
||||
switches[#switches+1] = switch_name
|
||||
end
|
||||
)
|
||||
|
||||
-- Switch status template
|
||||
s = m:section(SimpleSection)
|
||||
s.template = "admin_network/switch_status"
|
||||
s.switches = switches
|
||||
|
||||
return m
|
1192
luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua
Normal file
1192
luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua
Normal file
File diff suppressed because it is too large
Load diff
173
luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi_add.lua
Normal file
173
luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi_add.lua
Normal file
|
@ -0,0 +1,173 @@
|
|||
-- Copyright 2009 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local nw = require "luci.model.network"
|
||||
local fw = require "luci.model.firewall"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local http = require "luci.http"
|
||||
|
||||
local iw = luci.sys.wifi.getiwinfo(http.formvalue("device"))
|
||||
|
||||
local has_firewall = fs.access("/etc/config/firewall")
|
||||
|
||||
if not iw then
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
|
||||
return
|
||||
end
|
||||
|
||||
m = SimpleForm("network", translatef("Joining Network: %q", http.formvalue("join")))
|
||||
m.cancel = translate("Back to scan results")
|
||||
m.reset = false
|
||||
|
||||
function m.on_cancel()
|
||||
local dev = http.formvalue("device")
|
||||
http.redirect(luci.dispatcher.build_url(
|
||||
dev and "admin/network/wireless_join?device=" .. dev
|
||||
or "admin/network/wireless"
|
||||
))
|
||||
end
|
||||
|
||||
nw.init(uci)
|
||||
fw.init(uci)
|
||||
|
||||
m.hidden = {
|
||||
device = http.formvalue("device"),
|
||||
join = http.formvalue("join"),
|
||||
channel = http.formvalue("channel"),
|
||||
mode = http.formvalue("mode"),
|
||||
bssid = http.formvalue("bssid"),
|
||||
wep = http.formvalue("wep"),
|
||||
wpa_suites = http.formvalue("wpa_suites"),
|
||||
wpa_version = http.formvalue("wpa_version")
|
||||
}
|
||||
|
||||
if iw and iw.mbssid_support then
|
||||
replace = m:field(Flag, "replace", translate("Replace wireless configuration"),
|
||||
translate("Check this option to delete the existing networks from this radio."))
|
||||
|
||||
function replace.cfgvalue() return "0" end
|
||||
else
|
||||
replace = m:field(DummyValue, "replace", translate("Replace wireless configuration"))
|
||||
replace.default = translate("The hardware is not multi-SSID capable and the existing " ..
|
||||
"configuration will be replaced if you proceed.")
|
||||
|
||||
function replace.formvalue() return "1" end
|
||||
end
|
||||
|
||||
if http.formvalue("wep") == "1" then
|
||||
key = m:field(Value, "key", translate("WEP passphrase"),
|
||||
translate("Specify the secret encryption key here."))
|
||||
|
||||
key.password = true
|
||||
key.datatype = "wepkey"
|
||||
|
||||
elseif (tonumber(m.hidden.wpa_version) or 0) > 0 and
|
||||
(m.hidden.wpa_suites == "PSK" or m.hidden.wpa_suites == "PSK2")
|
||||
then
|
||||
key = m:field(Value, "key", translate("WPA passphrase"),
|
||||
translate("Specify the secret encryption key here."))
|
||||
|
||||
key.password = true
|
||||
key.datatype = "wpakey"
|
||||
--m.hidden.wpa_suite = (tonumber(http.formvalue("wpa_version")) or 0) >= 2 and "psk2" or "psk"
|
||||
end
|
||||
|
||||
newnet = m:field(Value, "_netname_new", translate("Name of the new network"),
|
||||
translate("The allowed characters are: <code>A-Z</code>, <code>a-z</code>, " ..
|
||||
"<code>0-9</code> and <code>_</code>"
|
||||
))
|
||||
|
||||
newnet.default = m.hidden.mode == "Ad-Hoc" and "mesh" or "wwan"
|
||||
newnet.datatype = "uciname"
|
||||
|
||||
if has_firewall then
|
||||
fwzone = m:field(Value, "_fwzone",
|
||||
translate("Create / Assign firewall-zone"),
|
||||
translate("Choose the firewall zone you want to assign to this interface. Select <em>unspecified</em> to remove the interface from the associated zone or fill out the <em>create</em> field to define a new zone and attach the interface to it."))
|
||||
|
||||
fwzone.template = "cbi/firewall_zonelist"
|
||||
fwzone.default = m.hidden.mode == "Ad-Hoc" and "mesh" or "wan"
|
||||
end
|
||||
|
||||
function newnet.parse(self, section)
|
||||
local net, zone
|
||||
|
||||
if has_firewall then
|
||||
local zval = fwzone:formvalue(section)
|
||||
zone = fw:get_zone(zval)
|
||||
|
||||
if not zone and zval == '-' then
|
||||
zval = m:formvalue(fwzone:cbid(section) .. ".newzone")
|
||||
if zval and #zval > 0 then
|
||||
zone = fw:add_zone(zval)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local wdev = nw:get_wifidev(m.hidden.device)
|
||||
|
||||
wdev:set("disabled", false)
|
||||
wdev:set("channel", m.hidden.channel)
|
||||
|
||||
if replace:formvalue(section) then
|
||||
local n
|
||||
for _, n in ipairs(wdev:get_wifinets()) do
|
||||
wdev:del_wifinet(n)
|
||||
end
|
||||
end
|
||||
|
||||
local wconf = {
|
||||
device = m.hidden.device,
|
||||
ssid = m.hidden.join,
|
||||
mode = (m.hidden.mode == "Ad-Hoc" and "adhoc" or "sta")
|
||||
}
|
||||
|
||||
if m.hidden.wep == "1" then
|
||||
wconf.encryption = "wep-open"
|
||||
wconf.key = "1"
|
||||
wconf.key1 = key and key:formvalue(section) or ""
|
||||
elseif (tonumber(m.hidden.wpa_version) or 0) > 0 then
|
||||
wconf.encryption = (tonumber(m.hidden.wpa_version) or 0) >= 2 and "psk2" or "psk"
|
||||
wconf.key = key and key:formvalue(section) or ""
|
||||
else
|
||||
wconf.encryption = "none"
|
||||
end
|
||||
|
||||
if wconf.mode == "adhoc" or wconf.mode == "sta" then
|
||||
wconf.bssid = m.hidden.bssid
|
||||
end
|
||||
|
||||
local value = self:formvalue(section)
|
||||
net = nw:add_network(value, { proto = "dhcp" })
|
||||
|
||||
if not net then
|
||||
self.error = { [section] = "missing" }
|
||||
else
|
||||
wconf.network = net:name()
|
||||
|
||||
local wnet = wdev:add_wifinet(wconf)
|
||||
if wnet then
|
||||
if zone then
|
||||
fw:del_network(net:name())
|
||||
zone:add_network(net:name())
|
||||
end
|
||||
|
||||
uci:save("wireless")
|
||||
uci:save("network")
|
||||
uci:save("firewall")
|
||||
|
||||
luci.http.redirect(wnet:adminlink())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if has_firewall then
|
||||
function fwzone.cfgvalue(self, section)
|
||||
self.iface = section
|
||||
local z = fw:get_zone_by_network(section)
|
||||
return z and z:name()
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
|
@ -0,0 +1,34 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
f = SimpleForm("processes", translate("Processes"), translate("This list gives an overview over currently running system processes and their status."))
|
||||
f.reset = false
|
||||
f.submit = false
|
||||
|
||||
t = f:section(Table, luci.sys.process.list())
|
||||
t:option(DummyValue, "PID", translate("PID"))
|
||||
t:option(DummyValue, "USER", translate("Owner"))
|
||||
t:option(DummyValue, "COMMAND", translate("Command"))
|
||||
t:option(DummyValue, "%CPU", translate("CPU usage (%)"))
|
||||
t:option(DummyValue, "%MEM", translate("Memory usage (%)"))
|
||||
|
||||
hup = t:option(Button, "_hup", translate("Hang Up"))
|
||||
hup.inputstyle = "reload"
|
||||
function hup.write(self, section)
|
||||
null, self.tag_error[section] = luci.sys.process.signal(section, 1)
|
||||
end
|
||||
|
||||
term = t:option(Button, "_term", translate("Terminate"))
|
||||
term.inputstyle = "remove"
|
||||
function term.write(self, section)
|
||||
null, self.tag_error[section] = luci.sys.process.signal(section, 15)
|
||||
end
|
||||
|
||||
kill = t:option(Button, "_kill", translate("Kill"))
|
||||
kill.inputstyle = "reset"
|
||||
function kill.write(self, section)
|
||||
null, self.tag_error[section] = luci.sys.process.signal(section, 9)
|
||||
end
|
||||
|
||||
return f
|
121
luci-mod-admin-full/luasrc/model/cbi/admin_system/admin.lua
Normal file
121
luci-mod-admin-full/luasrc/model/cbi/admin_system/admin.lua
Normal file
|
@ -0,0 +1,121 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
m = Map("system", translate("Router Password"),
|
||||
translate("Changes the administrator password for accessing the device"))
|
||||
|
||||
s = m:section(TypedSection, "_dummy", "")
|
||||
s.addremove = false
|
||||
s.anonymous = true
|
||||
|
||||
pw1 = s:option(Value, "pw1", translate("Password"))
|
||||
pw1.password = true
|
||||
|
||||
pw2 = s:option(Value, "pw2", translate("Confirmation"))
|
||||
pw2.password = true
|
||||
|
||||
function s.cfgsections()
|
||||
return { "_pass" }
|
||||
end
|
||||
|
||||
function m.parse(map)
|
||||
local v1 = pw1:formvalue("_pass")
|
||||
local v2 = pw2:formvalue("_pass")
|
||||
|
||||
if v1 and v2 and #v1 > 0 and #v2 > 0 then
|
||||
if v1 == v2 then
|
||||
if luci.sys.user.setpasswd(luci.dispatcher.context.authuser, v1) == 0 then
|
||||
m.message = translate("Password successfully changed!")
|
||||
else
|
||||
m.message = translate("Unknown Error, password not changed!")
|
||||
end
|
||||
else
|
||||
m.message = translate("Given password confirmation did not match, password not changed!")
|
||||
end
|
||||
end
|
||||
|
||||
Map.parse(map)
|
||||
end
|
||||
|
||||
|
||||
if fs.access("/etc/config/dropbear") then
|
||||
|
||||
m2 = Map("dropbear", translate("SSH Access"),
|
||||
translate("Dropbear offers <abbr title=\"Secure Shell\">SSH</abbr> network shell access and an integrated <abbr title=\"Secure Copy\">SCP</abbr> server"))
|
||||
|
||||
s = m2:section(TypedSection, "dropbear", translate("Dropbear Instance"))
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
|
||||
ni = s:option(Value, "Interface", translate("Interface"),
|
||||
translate("Listen only on the given interface or, if unspecified, on all"))
|
||||
|
||||
ni.template = "cbi/network_netlist"
|
||||
ni.nocreate = true
|
||||
ni.unspecified = true
|
||||
|
||||
|
||||
pt = s:option(Value, "Port", translate("Port"),
|
||||
translate("Specifies the listening port of this <em>Dropbear</em> instance"))
|
||||
|
||||
pt.datatype = "port"
|
||||
pt.default = 22
|
||||
|
||||
|
||||
pa = s:option(Flag, "PasswordAuth", translate("Password authentication"),
|
||||
translate("Allow <abbr title=\"Secure Shell\">SSH</abbr> password authentication"))
|
||||
|
||||
pa.enabled = "on"
|
||||
pa.disabled = "off"
|
||||
pa.default = pa.enabled
|
||||
pa.rmempty = false
|
||||
|
||||
|
||||
ra = s:option(Flag, "RootPasswordAuth", translate("Allow root logins with password"),
|
||||
translate("Allow the <em>root</em> user to login with password"))
|
||||
|
||||
ra.enabled = "on"
|
||||
ra.disabled = "off"
|
||||
ra.default = ra.enabled
|
||||
|
||||
|
||||
gp = s:option(Flag, "GatewayPorts", translate("Gateway ports"),
|
||||
translate("Allow remote hosts to connect to local SSH forwarded ports"))
|
||||
|
||||
gp.enabled = "on"
|
||||
gp.disabled = "off"
|
||||
gp.default = gp.disabled
|
||||
|
||||
|
||||
s2 = m2:section(TypedSection, "_dummy", translate("SSH-Keys"),
|
||||
translate("Here you can paste public SSH-Keys (one per line) for SSH public-key authentication."))
|
||||
s2.addremove = false
|
||||
s2.anonymous = true
|
||||
s2.template = "cbi/tblsection"
|
||||
|
||||
function s2.cfgsections()
|
||||
return { "_keys" }
|
||||
end
|
||||
|
||||
keys = s2:option(TextValue, "_data", "")
|
||||
keys.wrap = "off"
|
||||
keys.rows = 3
|
||||
keys.rmempty = false
|
||||
|
||||
function keys.cfgvalue()
|
||||
return fs.readfile("/etc/dropbear/authorized_keys") or ""
|
||||
end
|
||||
|
||||
function keys.write(self, section, value)
|
||||
if value then
|
||||
fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n"))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return m, m2
|
|
@ -0,0 +1,80 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
if luci.http.formvalue("cbid.luci.1._list") then
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/flashops/backupfiles") .. "?display=list")
|
||||
elseif luci.http.formvalue("cbid.luci.1._edit") then
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system/flashops/backupfiles") .. "?display=edit")
|
||||
return
|
||||
end
|
||||
|
||||
m = SimpleForm("luci", translate("Backup file list"))
|
||||
m:append(Template("admin_system/backupfiles"))
|
||||
|
||||
if luci.http.formvalue("display") ~= "list" then
|
||||
f = m:section(SimpleSection, nil, translate("This is a list of shell glob patterns for matching files and directories to include during sysupgrade. Modified files in /etc/config/ and certain other configurations are automatically preserved."))
|
||||
|
||||
l = f:option(Button, "_list", translate("Show current backup file list"))
|
||||
l.inputtitle = translate("Open list...")
|
||||
l.inputstyle = "apply"
|
||||
|
||||
c = f:option(TextValue, "_custom")
|
||||
c.rmempty = false
|
||||
c.cols = 70
|
||||
c.rows = 30
|
||||
|
||||
c.cfgvalue = function(self, section)
|
||||
return nixio.fs.readfile("/etc/sysupgrade.conf")
|
||||
end
|
||||
|
||||
c.write = function(self, section, value)
|
||||
value = value:gsub("\r\n?", "\n")
|
||||
return nixio.fs.writefile("/etc/sysupgrade.conf", value)
|
||||
end
|
||||
else
|
||||
m.submit = false
|
||||
m.reset = false
|
||||
|
||||
f = m:section(SimpleSection, nil, translate("Below is the determined list of files to backup. It consists of changed configuration files marked by opkg, essential base files and the user defined backup patterns."))
|
||||
|
||||
l = f:option(Button, "_edit", translate("Back to configuration"))
|
||||
l.inputtitle = translate("Close list...")
|
||||
l.inputstyle = "link"
|
||||
|
||||
|
||||
d = f:option(DummyValue, "_detected")
|
||||
d.rawhtml = true
|
||||
d.cfgvalue = function(s)
|
||||
local list = io.popen(
|
||||
"( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' /etc/sysupgrade.conf " ..
|
||||
"/lib/upgrade/keep.d/* 2>/dev/null) -type f 2>/dev/null; " ..
|
||||
"opkg list-changed-conffiles ) | sort -u"
|
||||
)
|
||||
|
||||
if list then
|
||||
local files = { "<ul>" }
|
||||
|
||||
while true do
|
||||
local ln = list:read("*l")
|
||||
if not ln then
|
||||
break
|
||||
else
|
||||
files[#files+1] = "<li>"
|
||||
files[#files+1] = luci.util.pcdata(ln)
|
||||
files[#files+1] = "</li>"
|
||||
end
|
||||
end
|
||||
|
||||
list:close()
|
||||
files[#files+1] = "</ul>"
|
||||
|
||||
return table.concat(files, "")
|
||||
end
|
||||
|
||||
return "<em>" .. translate("No files found") .. "</em>"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return m
|
|
@ -0,0 +1,27 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
m = Map("system", translate("Buttons"),
|
||||
translate("This page allows the configuration of custom button actions"))
|
||||
|
||||
s = m:section(TypedSection, "button", "")
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
s:option(Value, "button", translate("Name"))
|
||||
|
||||
act = s:option(ListValue, "action",
|
||||
translate("Action"),
|
||||
translate("Specifies the button state to handle"))
|
||||
|
||||
act:value("released")
|
||||
|
||||
s:option(Value, "handler",
|
||||
translate("Handler"),
|
||||
translate("Path to executable which handles the button event"))
|
||||
|
||||
min = s:option(Value, "min", translate("Minimum hold time"))
|
||||
min.rmempty = true
|
||||
|
||||
max = s:option(Value, "max", translate("Maximum hold time"))
|
||||
max.rmempty = true
|
|
@ -0,0 +1,32 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008-2013 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local cronfile = "/etc/crontabs/root"
|
||||
|
||||
f = SimpleForm("crontab", translate("Scheduled Tasks"),
|
||||
translate("This is the system crontab in which scheduled tasks can be defined.") ..
|
||||
translate("<br/>Note: you need to manually restart the cron service if the " ..
|
||||
"crontab file was empty before editing."))
|
||||
|
||||
t = f:field(TextValue, "crons")
|
||||
t.rmempty = true
|
||||
t.rows = 10
|
||||
function t.cfgvalue()
|
||||
return fs.readfile(cronfile) or ""
|
||||
end
|
||||
|
||||
function f.handle(self, state, data)
|
||||
if state == FORM_VALID then
|
||||
if data.crons then
|
||||
fs.writefile(cronfile, data.crons:gsub("\r\n", "\n"))
|
||||
luci.sys.call("/usr/bin/crontab %q" % cronfile)
|
||||
else
|
||||
fs.writefile(cronfile, "")
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return f
|
270
luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab.lua
Normal file
270
luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab.lua
Normal file
|
@ -0,0 +1,270 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
require("luci.tools.webadmin")
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "nixio.util"
|
||||
local tp = require "luci.template.parser"
|
||||
|
||||
local block = io.popen("block info", "r")
|
||||
local ln, dev, devices = nil, nil, {}
|
||||
|
||||
repeat
|
||||
ln = block:read("*l")
|
||||
dev = ln and ln:match("^/dev/(.-):")
|
||||
|
||||
if dev then
|
||||
local e, s, key, val = { }
|
||||
|
||||
for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
|
||||
e[key:lower()] = val
|
||||
devices[val] = e
|
||||
end
|
||||
|
||||
s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev)))
|
||||
|
||||
e.dev = "/dev/%s" % dev
|
||||
e.size = s and math.floor(s / 2048)
|
||||
|
||||
devices[e.dev] = e
|
||||
end
|
||||
until not ln
|
||||
|
||||
block:close()
|
||||
|
||||
m = Map("fstab", translate("Mount Points"))
|
||||
s = m:section(TypedSection, "global", translate("Global Settings"))
|
||||
s.addremove = false
|
||||
s.anonymous = true
|
||||
|
||||
detect = s:option(Button, "block_detect", translate("Generate Config"), translate("Find all currently attached filesystems and swap and replace configuration with defaults based on what was detected"))
|
||||
detect.inputstyle = "reload"
|
||||
|
||||
detect.write = function(self, section)
|
||||
luci.sys.call("block detect >/etc/config/fstab")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system", "fstab"))
|
||||
end
|
||||
|
||||
o = s:option(Flag, "anon_swap", translate("Anonymous Swap"), translate("Mount swap not specifically configured"))
|
||||
o.default = o.disabled
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "anon_mount", translate("Anonymous Mount"), translate("Mount filesystems not specifically configured"))
|
||||
o.default = o.disabled
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "auto_swap", translate("Automount Swap"), translate("Automatically mount swap on hotplug"))
|
||||
o.default = o.enabled
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "auto_mount", translate("Automount Filesystem"), translate("Automatically mount filesystems on hotplug"))
|
||||
o.default = o.enabled
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "check_fs", translate("Check fileystems before mount"), translate("Automatically check filesystem for errors before mounting"))
|
||||
o.default = o.disabled
|
||||
o.rmempty = false
|
||||
|
||||
local mounts = luci.sys.mounts()
|
||||
local non_system_mounts = {}
|
||||
for rawmount, val in pairs(mounts) do
|
||||
if (string.find(val.mountpoint, "/tmp/.jail") == nil) then
|
||||
repeat
|
||||
val.umount = false
|
||||
if (val.mountpoint == "/") then
|
||||
break
|
||||
elseif (val.mountpoint == "/overlay") then
|
||||
break
|
||||
elseif (val.mountpoint == "/rom") then
|
||||
break
|
||||
elseif (val.mountpoint == "/tmp") then
|
||||
break
|
||||
elseif (val.mountpoint == "/tmp/shm") then
|
||||
break
|
||||
elseif (val.mountpoint == "/tmp/upgrade") then
|
||||
break
|
||||
elseif (val.mountpoint == "/dev") then
|
||||
break
|
||||
end
|
||||
val.umount = true
|
||||
until true
|
||||
non_system_mounts[rawmount] = val
|
||||
end
|
||||
end
|
||||
|
||||
v = m:section(Table, non_system_mounts, translate("Mounted file systems"))
|
||||
|
||||
fs = v:option(DummyValue, "fs", translate("Filesystem"))
|
||||
|
||||
mp = v:option(DummyValue, "mountpoint", translate("Mount Point"))
|
||||
|
||||
avail = v:option(DummyValue, "avail", translate("Available"))
|
||||
function avail.cfgvalue(self, section)
|
||||
return luci.tools.webadmin.byte_format(
|
||||
( tonumber(mounts[section].available) or 0 ) * 1024
|
||||
) .. " / " .. luci.tools.webadmin.byte_format(
|
||||
( tonumber(mounts[section].blocks) or 0 ) * 1024
|
||||
)
|
||||
end
|
||||
|
||||
used = v:option(DummyValue, "used", translate("Used"))
|
||||
function used.cfgvalue(self, section)
|
||||
return ( mounts[section].percent or "0%" ) .. " (" ..
|
||||
luci.tools.webadmin.byte_format(
|
||||
( tonumber(mounts[section].used) or 0 ) * 1024
|
||||
) .. ")"
|
||||
end
|
||||
|
||||
unmount = v:option(Button, "unmount", translate("Unmount"))
|
||||
unmount.render = function(self, section, scope)
|
||||
if non_system_mounts[section].umount then
|
||||
self.title = translate("Unmount")
|
||||
self.inputstyle = "remove"
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
end
|
||||
|
||||
unmount.write = function(self, section)
|
||||
if non_system_mounts[section].umount then
|
||||
luci.sys.call("/bin/umount '%s'" % luci.util.shellstartsqescape(non_system_mounts[section].mountpoint))
|
||||
return luci.http.redirect(luci.dispatcher.build_url("admin/system", "fstab"))
|
||||
end
|
||||
end
|
||||
|
||||
mount = m:section(TypedSection, "mount", translate("Mount Points"), translate("Mount Points define at which point a memory device will be attached to the filesystem"))
|
||||
mount.anonymous = true
|
||||
mount.addremove = true
|
||||
mount.template = "cbi/tblsection"
|
||||
mount.extedit = luci.dispatcher.build_url("admin/system/fstab/mount/%s")
|
||||
|
||||
mount.create = function(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
luci.http.redirect(mount.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
mount:option(Flag, "enabled", translate("Enabled")).rmempty = false
|
||||
|
||||
dev = mount:option(DummyValue, "device", translate("Device"))
|
||||
dev.rawhtml = true
|
||||
dev.cfgvalue = function(self, section)
|
||||
local v, e
|
||||
|
||||
v = m.uci:get("fstab", section, "uuid")
|
||||
e = v and devices[v:lower()]
|
||||
if v and e and e.size then
|
||||
return "UUID: %s (%s, %d MB)" %{ tp.pcdata(v), e.dev, e.size }
|
||||
elseif v and e then
|
||||
return "UUID: %s (%s)" %{ tp.pcdata(v), e.dev }
|
||||
elseif v then
|
||||
return "UUID: %s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
|
||||
end
|
||||
|
||||
v = m.uci:get("fstab", section, "label")
|
||||
e = v and devices[v]
|
||||
if v and e and e.size then
|
||||
return "Label: %s (%s, %d MB)" %{ tp.pcdata(v), e.dev, e.size }
|
||||
elseif v and e then
|
||||
return "Label: %s (%s)" %{ tp.pcdata(v), e.dev }
|
||||
elseif v then
|
||||
return "Label: %s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
|
||||
end
|
||||
|
||||
v = Value.cfgvalue(self, section) or "?"
|
||||
e = v and devices[v]
|
||||
if v and e and e.size then
|
||||
return "%s (%d MB)" %{ tp.pcdata(v), e.size }
|
||||
elseif v and e then
|
||||
return tp.pcdata(v)
|
||||
elseif v then
|
||||
return "%s (<em>%s</em>)" %{ tp.pcdata(v), translate("not present") }
|
||||
end
|
||||
end
|
||||
|
||||
mp = mount:option(DummyValue, "target", translate("Mount Point"))
|
||||
mp.cfgvalue = function(self, section)
|
||||
if m.uci:get("fstab", section, "is_rootfs") == "1" then
|
||||
return "/overlay"
|
||||
else
|
||||
return Value.cfgvalue(self, section) or "?"
|
||||
end
|
||||
end
|
||||
|
||||
fs = mount:option(DummyValue, "fstype", translate("Filesystem"))
|
||||
fs.cfgvalue = function(self, section)
|
||||
local v, e
|
||||
|
||||
v = m.uci:get("fstab", section, "uuid")
|
||||
v = v and v:lower() or m.uci:get("fstab", section, "label")
|
||||
v = v or m.uci:get("fstab", section, "device")
|
||||
|
||||
e = v and devices[v]
|
||||
|
||||
return e and e.type or m.uci:get("fstab", section, "fstype") or "?"
|
||||
end
|
||||
|
||||
op = mount:option(DummyValue, "options", translate("Options"))
|
||||
op.cfgvalue = function(self, section)
|
||||
return Value.cfgvalue(self, section) or "defaults"
|
||||
end
|
||||
|
||||
rf = mount:option(DummyValue, "is_rootfs", translate("Root"))
|
||||
rf.cfgvalue = function(self, section)
|
||||
local target = m.uci:get("fstab", section, "target")
|
||||
if target == "/" then
|
||||
return translate("yes")
|
||||
elseif target == "/overlay" then
|
||||
return translate("overlay")
|
||||
else
|
||||
return translate("no")
|
||||
end
|
||||
end
|
||||
|
||||
ck = mount:option(DummyValue, "enabled_fsck", translate("Check"))
|
||||
ck.cfgvalue = function(self, section)
|
||||
return Value.cfgvalue(self, section) == "1"
|
||||
and translate("yes") or translate("no")
|
||||
end
|
||||
|
||||
|
||||
swap = m:section(TypedSection, "swap", "SWAP", translate("If your physical memory is insufficient unused data can be temporarily swapped to a swap-device resulting in a higher amount of usable <abbr title=\"Random Access Memory\">RAM</abbr>. Be aware that swapping data is a very slow process as the swap-device cannot be accessed with the high datarates of the <abbr title=\"Random Access Memory\">RAM</abbr>."))
|
||||
swap.anonymous = true
|
||||
swap.addremove = true
|
||||
swap.template = "cbi/tblsection"
|
||||
swap.extedit = luci.dispatcher.build_url("admin/system/fstab/swap/%s")
|
||||
|
||||
swap.create = function(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
luci.http.redirect(swap.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
swap:option(Flag, "enabled", translate("Enabled")).rmempty = false
|
||||
|
||||
dev = swap:option(DummyValue, "device", translate("Device"))
|
||||
dev.cfgvalue = function(self, section)
|
||||
local v
|
||||
|
||||
v = m.uci:get("fstab", section, "uuid")
|
||||
if v then return "UUID: %s" % v end
|
||||
|
||||
v = m.uci:get("fstab", section, "label")
|
||||
if v then return "Label: %s" % v end
|
||||
|
||||
v = Value.cfgvalue(self, section) or "?"
|
||||
e = v and devices[v]
|
||||
if v and e and e.size then
|
||||
return "%s (%s MB)" % {v, e.size}
|
||||
else
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
|
@ -0,0 +1,151 @@
|
|||
-- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "nixio.util"
|
||||
|
||||
local has_fscheck = fs.access("/usr/sbin/e2fsck")
|
||||
|
||||
local block = io.popen("block info", "r")
|
||||
local ln, dev, devices = nil, nil, {}
|
||||
|
||||
repeat
|
||||
ln = block:read("*l")
|
||||
dev = ln and ln:match("^/dev/(.-):")
|
||||
|
||||
if dev then
|
||||
local e, s, key, val = { }
|
||||
|
||||
for key, val in ln:gmatch([[(%w+)="(.-)"]]) do
|
||||
e[key:lower()] = val
|
||||
end
|
||||
|
||||
s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev)))
|
||||
|
||||
e.dev = "/dev/%s" % dev
|
||||
e.size = s and math.floor(s / 2048)
|
||||
|
||||
devices[#devices+1] = e
|
||||
end
|
||||
until not ln
|
||||
|
||||
block:close()
|
||||
|
||||
|
||||
m = Map("fstab", translate("Mount Points - Mount Entry"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/system/fstab")
|
||||
|
||||
if not arg[1] or m.uci:get("fstab", arg[1]) ~= "mount" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
mount = m:section(NamedSection, arg[1], "mount", translate("Mount Entry"))
|
||||
mount.anonymous = true
|
||||
mount.addremove = false
|
||||
|
||||
mount:tab("general", translate("General Settings"))
|
||||
mount:tab("advanced", translate("Advanced Settings"))
|
||||
|
||||
|
||||
mount:taboption("general", Flag, "enabled", translate("Enable this mount")).rmempty = false
|
||||
|
||||
|
||||
o = mount:taboption("general", Value, "uuid", translate("UUID"),
|
||||
translate("If specified, mount the device by its UUID instead of a fixed device node"))
|
||||
|
||||
o:value("", translate("-- match by uuid --"))
|
||||
|
||||
for i, d in ipairs(devices) do
|
||||
if d.uuid and d.size then
|
||||
o:value(d.uuid, "%s (%s, %d MB)" %{ d.uuid, d.dev, d.size })
|
||||
elseif d.uuid then
|
||||
o:value(d.uuid, "%s (%s)" %{ d.uuid, d.dev })
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
o = mount:taboption("general", Value, "label", translate("Label"),
|
||||
translate("If specified, mount the device by the partition label instead of a fixed device node"))
|
||||
|
||||
o:value("", translate("-- match by label --"))
|
||||
|
||||
o:depends("uuid", "")
|
||||
|
||||
for i, d in ipairs(devices) do
|
||||
if d.label and d.size then
|
||||
o:value(d.label, "%s (%s, %d MB)" %{ d.label, d.dev, d.size })
|
||||
elseif d.label then
|
||||
o:value(d.label, "%s (%s)" %{ d.label, d.dev })
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
o = mount:taboption("general", Value, "device", translate("Device"),
|
||||
translate("The device file of the memory or partition (<abbr title=\"for example\">e.g.</abbr> <code>/dev/sda1</code>)"))
|
||||
|
||||
o:value("", translate("-- match by device --"))
|
||||
|
||||
o:depends({ uuid = "", label = "" })
|
||||
|
||||
for i, d in ipairs(devices) do
|
||||
if d.size then
|
||||
o:value(d.dev, "%s (%d MB)" %{ d.dev, d.size })
|
||||
else
|
||||
o:value(d.dev)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
o = mount:taboption("general", Value, "target", translate("Mount point"),
|
||||
translate("Specifies the directory the device is attached to"))
|
||||
|
||||
o:value("/", translate("Use as root filesystem (/)"))
|
||||
o:value("/overlay", translate("Use as external overlay (/overlay)"))
|
||||
|
||||
|
||||
o = mount:taboption("general", DummyValue, "__notice", translate("Root preparation"))
|
||||
o:depends("target", "/")
|
||||
o.rawhtml = true
|
||||
o.default = [[
|
||||
<p>%s</p><pre>mkdir -p /tmp/introot
|
||||
mkdir -p /tmp/extroot
|
||||
mount --bind / /tmp/introot
|
||||
mount /dev/sda1 /tmp/extroot
|
||||
tar -C /tmp/introot -cvf - . | tar -C /tmp/extroot -xf -
|
||||
umount /tmp/introot
|
||||
umount /tmp/extroot</pre>
|
||||
]] %{
|
||||
translate("Make sure to clone the root filesystem using something like the commands below:"),
|
||||
|
||||
}
|
||||
|
||||
|
||||
o = mount:taboption("advanced", Value, "fstype", translate("Filesystem"),
|
||||
translate("The filesystem that was used to format the memory (<abbr title=\"for example\">e.g.</abbr> <samp><abbr title=\"Third Extended Filesystem\">ext3</abbr></samp>)"))
|
||||
|
||||
o:value("", "auto")
|
||||
|
||||
local fs
|
||||
for fs in io.lines("/proc/filesystems") do
|
||||
fs = fs:match("%S+")
|
||||
if fs ~= "nodev" then
|
||||
o:value(fs)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
o = mount:taboption("advanced", Value, "options", translate("Mount options"),
|
||||
translate("See \"mount\" manpage for details"))
|
||||
|
||||
o.placeholder = "defaults"
|
||||
|
||||
|
||||
if has_fscheck then
|
||||
o = mount:taboption("advanced", Flag, "enabled_fsck", translate("Run filesystem check"),
|
||||
translate("Run a filesystem check before mounting the device"))
|
||||
end
|
||||
|
||||
return m
|
|
@ -0,0 +1,54 @@
|
|||
-- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "nixio.util"
|
||||
|
||||
local devices = {}
|
||||
util.consume((fs.glob("/dev/sd*")), devices)
|
||||
util.consume((fs.glob("/dev/hd*")), devices)
|
||||
util.consume((fs.glob("/dev/scd*")), devices)
|
||||
util.consume((fs.glob("/dev/mmc*")), devices)
|
||||
|
||||
local size = {}
|
||||
for i, dev in ipairs(devices) do
|
||||
local s = tonumber((fs.readfile("/sys/class/block/%s/size" % dev:sub(6))))
|
||||
size[dev] = s and math.floor(s / 2048)
|
||||
end
|
||||
|
||||
|
||||
m = Map("fstab", translate("Mount Points - Swap Entry"))
|
||||
m.redirect = luci.dispatcher.build_url("admin/system/fstab")
|
||||
|
||||
if not arg[1] or m.uci:get("fstab", arg[1]) ~= "swap" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
mount = m:section(NamedSection, arg[1], "swap", translate("Swap Entry"))
|
||||
mount.anonymous = true
|
||||
mount.addremove = false
|
||||
|
||||
mount:tab("general", translate("General Settings"))
|
||||
mount:tab("advanced", translate("Advanced Settings"))
|
||||
|
||||
|
||||
mount:taboption("general", Flag, "enabled", translate("Enable this swap")).rmempty = false
|
||||
|
||||
|
||||
o = mount:taboption("general", Value, "device", translate("Device"),
|
||||
translate("The device file of the memory or partition (<abbr title=\"for example\">e.g.</abbr> <code>/dev/sda1</code>)"))
|
||||
|
||||
for i, d in ipairs(devices) do
|
||||
o:value(d, size[d] and "%s (%s MB)" % {d, size[d]})
|
||||
end
|
||||
|
||||
o = mount:taboption("advanced", Value, "uuid", translate("UUID"),
|
||||
translate("If specified, mount the device by its UUID instead of a fixed device node"))
|
||||
|
||||
o = mount:taboption("advanced", Value, "label", translate("Label"),
|
||||
translate("If specified, mount the device by the partition label instead of a fixed device node"))
|
||||
|
||||
|
||||
return m
|
64
luci-mod-admin-full/luasrc/model/cbi/admin_system/ipkg.lua
Normal file
64
luci-mod-admin-full/luasrc/model/cbi/admin_system/ipkg.lua
Normal file
|
@ -0,0 +1,64 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local ipkgfile = "/etc/opkg.conf"
|
||||
local distfeeds = "/etc/opkg/distfeeds.conf"
|
||||
local customfeeds = "/etc/opkg/customfeeds.conf"
|
||||
|
||||
f = SimpleForm("ipkgconf", translate("OPKG-Configuration"), translate("General options for opkg"))
|
||||
|
||||
f:append(Template("admin_system/ipkg"))
|
||||
|
||||
t = f:field(TextValue, "lines")
|
||||
t.wrap = "off"
|
||||
t.rows = 10
|
||||
function t.cfgvalue()
|
||||
return nixio.fs.readfile(ipkgfile) or ""
|
||||
end
|
||||
|
||||
function t.write(self, section, data)
|
||||
return nixio.fs.writefile(ipkgfile, data:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
function f.handle(self, state, data)
|
||||
return true
|
||||
end
|
||||
|
||||
g = SimpleForm("distfeedconf", translate("Distribution feeds"),
|
||||
translate("Build/distribution specific feed definitions. This file will NOT be preserved in any sysupgrade."))
|
||||
|
||||
d = g:field(TextValue, "lines2")
|
||||
d.wrap = "off"
|
||||
d.rows = 10
|
||||
function d.cfgvalue()
|
||||
return nixio.fs.readfile(distfeeds) or ""
|
||||
end
|
||||
|
||||
function d.write(self, section, data)
|
||||
return nixio.fs.writefile(distfeeds, data:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
function g.handle(self, state, data)
|
||||
return true
|
||||
end
|
||||
|
||||
h = SimpleForm("customfeedconf", translate("Custom feeds"),
|
||||
translate("Custom feed definitions, e.g. private feeds. This file can be preserved in a sysupgrade."))
|
||||
|
||||
c = h:field(TextValue, "lines3")
|
||||
c.wrap = "off"
|
||||
c.rows = 10
|
||||
function c.cfgvalue()
|
||||
return nixio.fs.readfile(customfeeds) or ""
|
||||
end
|
||||
|
||||
function c.write(self, section, data)
|
||||
return nixio.fs.writefile(customfeeds, data:gsub("\r\n", "\n"))
|
||||
end
|
||||
|
||||
function h.handle(self, state, data)
|
||||
return true
|
||||
end
|
||||
|
||||
return f, g, h
|
155
luci-mod-admin-full/luasrc/model/cbi/admin_system/leds.lua
Normal file
155
luci-mod-admin-full/luasrc/model/cbi/admin_system/leds.lua
Normal file
|
@ -0,0 +1,155 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
m = Map("system", translate("<abbr title=\"Light Emitting Diode\">LED</abbr> Configuration"), translate("Customizes the behaviour of the device <abbr title=\"Light Emitting Diode\">LED</abbr>s if possible."))
|
||||
|
||||
local sysfs_path = "/sys/class/leds/"
|
||||
local leds = {}
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local nu = require "nixio.util"
|
||||
local util = require "luci.util"
|
||||
|
||||
if fs.access(sysfs_path) then
|
||||
leds = nu.consume((fs.dir(sysfs_path)))
|
||||
end
|
||||
|
||||
if #leds == 0 then
|
||||
return m
|
||||
end
|
||||
|
||||
|
||||
s = m:section(TypedSection, "led", "")
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
|
||||
function s.parse(self, ...)
|
||||
TypedSection.parse(self, ...)
|
||||
os.execute("/etc/init.d/led enable")
|
||||
end
|
||||
|
||||
|
||||
s:option(Value, "name", translate("Name"))
|
||||
|
||||
|
||||
sysfs = s:option(ListValue, "sysfs", translate("<abbr title=\"Light Emitting Diode\">LED</abbr> Name"))
|
||||
for k, v in ipairs(leds) do
|
||||
sysfs:value(v)
|
||||
end
|
||||
|
||||
s:option(Flag, "default", translate("Default state")).rmempty = false
|
||||
|
||||
|
||||
trigger = s:option(ListValue, "trigger", translate("Trigger"))
|
||||
|
||||
local triggers = fs.readfile(sysfs_path .. leds[1] .. "/trigger")
|
||||
for t in triggers:gmatch("[%w-]+") do
|
||||
trigger:value(t, translate(t:gsub("-", "")))
|
||||
end
|
||||
|
||||
|
||||
delayon = s:option(Value, "delayon", translate ("On-State Delay"))
|
||||
delayon:depends("trigger", "timer")
|
||||
|
||||
delayoff = s:option(Value, "delayoff", translate ("Off-State Delay"))
|
||||
delayoff:depends("trigger", "timer")
|
||||
|
||||
|
||||
dev = s:option(ListValue, "_net_dev", translate("Device"))
|
||||
dev.rmempty = true
|
||||
dev:value("")
|
||||
dev:depends("trigger", "netdev")
|
||||
|
||||
function dev.cfgvalue(self, section)
|
||||
return m.uci:get("system", section, "dev")
|
||||
end
|
||||
|
||||
function dev.write(self, section, value)
|
||||
m.uci:set("system", section, "dev", value)
|
||||
end
|
||||
|
||||
function dev.remove(self, section)
|
||||
local t = trigger:formvalue(section)
|
||||
if t ~= "netdev" and t ~= "usbdev" then
|
||||
m.uci:delete("system", section, "dev")
|
||||
end
|
||||
end
|
||||
|
||||
for k, v in pairs(luci.sys.net.devices()) do
|
||||
if v ~= "lo" then
|
||||
dev:value(v)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
mode = s:option(MultiValue, "mode", translate("Trigger Mode"))
|
||||
mode.rmempty = true
|
||||
mode:depends("trigger", "netdev")
|
||||
mode:value("link", translate("Link On"))
|
||||
mode:value("tx", translate("Transmit"))
|
||||
mode:value("rx", translate("Receive"))
|
||||
|
||||
|
||||
usbdev = s:option(ListValue, "_usb_dev", translate("USB Device"))
|
||||
usbdev:depends("trigger", "usbdev")
|
||||
usbdev.rmempty = true
|
||||
usbdev:value("")
|
||||
|
||||
function usbdev.cfgvalue(self, section)
|
||||
return m.uci:get("system", section, "dev")
|
||||
end
|
||||
|
||||
function usbdev.write(self, section, value)
|
||||
m.uci:set("system", section, "dev", value)
|
||||
end
|
||||
|
||||
function usbdev.remove(self, section)
|
||||
local t = trigger:formvalue(section)
|
||||
if t ~= "netdev" and t ~= "usbdev" then
|
||||
m.uci:delete("system", section, "dev")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
usbport = s:option(MultiValue, "port", translate("USB Ports"))
|
||||
usbport:depends("trigger", "usbport")
|
||||
usbport.rmempty = true
|
||||
usbport.widget = "checkbox"
|
||||
usbport.cast = "table"
|
||||
usbport.size = 1
|
||||
|
||||
function usbport.valuelist(self, section)
|
||||
local port, ports = nil, {}
|
||||
for port in util.imatch(m.uci:get("system", section, "port")) do
|
||||
local b, n = port:match("^usb(%d+)-port(%d+)$")
|
||||
if not (b and n) then
|
||||
b, n = port:match("^(%d+)-(%d+)$")
|
||||
end
|
||||
if b and n then
|
||||
ports[#ports+1] = "usb%u-port%u" %{ tonumber(b), tonumber(n) }
|
||||
end
|
||||
end
|
||||
return ports
|
||||
end
|
||||
|
||||
function usbport.validate(self, value)
|
||||
return type(value) == "string" and { value } or value
|
||||
end
|
||||
|
||||
|
||||
for p in nixio.fs.glob("/sys/bus/usb/devices/[0-9]*/manufacturer") do
|
||||
local id = p:match("%d+-%d+")
|
||||
local mf = nixio.fs.readfile("/sys/bus/usb/devices/" .. id .. "/manufacturer") or "?"
|
||||
local pr = nixio.fs.readfile("/sys/bus/usb/devices/" .. id .. "/product") or "?"
|
||||
usbdev:value(id, "%s (%s - %s)" %{ id, mf, pr })
|
||||
end
|
||||
|
||||
for p in nixio.fs.glob("/sys/bus/usb/devices/*/usb[0-9]*-port[0-9]*") do
|
||||
local bus, port = p:match("usb(%d+)-port(%d+)")
|
||||
if bus and port then
|
||||
usbport:value("usb%u-port%u" %{ tonumber(bus), tonumber(port) },
|
||||
"Hub %u, Port %u" %{ tonumber(bus), tonumber(port) })
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
|
@ -0,0 +1,97 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Copyright 2010 Manuel Munz <freifunk at somakoma dot de>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local fs = require "nixio.fs"
|
||||
local sys = require "luci.sys"
|
||||
|
||||
local inits = { }
|
||||
|
||||
for _, name in ipairs(sys.init.names()) do
|
||||
local index = sys.init.index(name)
|
||||
local enabled = sys.init.enabled(name)
|
||||
|
||||
if index < 255 then
|
||||
inits["%02i.%s" % { index, name }] = {
|
||||
name = name,
|
||||
index = tostring(index),
|
||||
enabled = enabled
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
m = SimpleForm("initmgr", translate("Initscripts"), translate("You can enable or disable installed init scripts here. Changes will applied after a device reboot.<br /><strong>Warning: If you disable essential init scripts like \"network\", your device might become inaccessible!</strong>"))
|
||||
m.reset = false
|
||||
m.submit = false
|
||||
|
||||
|
||||
s = m:section(Table, inits)
|
||||
|
||||
i = s:option(DummyValue, "index", translate("Start priority"))
|
||||
n = s:option(DummyValue, "name", translate("Initscript"))
|
||||
|
||||
|
||||
e = s:option(Button, "endisable", translate("Enable/Disable"))
|
||||
|
||||
e.render = function(self, section, scope)
|
||||
if inits[section].enabled then
|
||||
self.title = translate("Enabled")
|
||||
self.inputstyle = "save"
|
||||
else
|
||||
self.title = translate("Disabled")
|
||||
self.inputstyle = "reset"
|
||||
end
|
||||
|
||||
Button.render(self, section, scope)
|
||||
end
|
||||
|
||||
e.write = function(self, section)
|
||||
if inits[section].enabled then
|
||||
inits[section].enabled = false
|
||||
return sys.init.disable(inits[section].name)
|
||||
else
|
||||
inits[section].enabled = true
|
||||
return sys.init.enable(inits[section].name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
start = s:option(Button, "start", translate("Start"))
|
||||
start.inputstyle = "apply"
|
||||
start.write = function(self, section)
|
||||
sys.call("/etc/init.d/%s %s >/dev/null" %{ inits[section].name, self.option })
|
||||
end
|
||||
|
||||
restart = s:option(Button, "restart", translate("Restart"))
|
||||
restart.inputstyle = "reload"
|
||||
restart.write = start.write
|
||||
|
||||
stop = s:option(Button, "stop", translate("Stop"))
|
||||
stop.inputstyle = "remove"
|
||||
stop.write = start.write
|
||||
|
||||
|
||||
|
||||
f = SimpleForm("rc", translate("Local Startup"),
|
||||
translate("This is the content of /etc/rc.local. Insert your own commands here (in front of 'exit 0') to execute them at the end of the boot process."))
|
||||
|
||||
t = f:field(TextValue, "rcs")
|
||||
t.rmempty = true
|
||||
t.rows = 20
|
||||
|
||||
function t.cfgvalue()
|
||||
return fs.readfile("/etc/rc.local") or ""
|
||||
end
|
||||
|
||||
function f.handle(self, state, data)
|
||||
if state == FORM_VALID then
|
||||
if data.rcs then
|
||||
fs.writefile("/etc/rc.local", data.rcs:gsub("\r\n", "\n"))
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return m, f
|
224
luci-mod-admin-full/luasrc/model/cbi/admin_system/system.lua
Normal file
224
luci-mod-admin-full/luasrc/model/cbi/admin_system/system.lua
Normal file
|
@ -0,0 +1,224 @@
|
|||
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
-- Licensed to the public under the Apache License 2.0.
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local zones = require "luci.sys.zoneinfo"
|
||||
local fs = require "nixio.fs"
|
||||
local conf = require "luci.config"
|
||||
|
||||
local m, s, o
|
||||
local has_ntpd = fs.access("/usr/sbin/ntpd")
|
||||
|
||||
m = Map("system", translate("System"), translate("Here you can configure the basic aspects of your device like its hostname or the timezone."))
|
||||
m:chain("luci")
|
||||
|
||||
|
||||
s = m:section(TypedSection, "system", translate("System Properties"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
s:tab("general", translate("General Settings"))
|
||||
s:tab("logging", translate("Logging"))
|
||||
s:tab("language", translate("Language and Style"))
|
||||
|
||||
|
||||
--
|
||||
-- System Properties
|
||||
--
|
||||
|
||||
o = s:taboption("general", DummyValue, "_systime", translate("Local Time"))
|
||||
o.template = "admin_system/clock_status"
|
||||
|
||||
|
||||
o = s:taboption("general", Value, "hostname", translate("Hostname"))
|
||||
o.datatype = "hostname"
|
||||
|
||||
function o.write(self, section, value)
|
||||
Value.write(self, section, value)
|
||||
sys.hostname(value)
|
||||
end
|
||||
|
||||
|
||||
o = s:taboption("general", ListValue, "zonename", translate("Timezone"))
|
||||
o:value("UTC")
|
||||
|
||||
for i, zone in ipairs(zones.TZ) do
|
||||
o:value(zone[1])
|
||||
end
|
||||
|
||||
function o.write(self, section, value)
|
||||
local function lookup_zone(title)
|
||||
for _, zone in ipairs(zones.TZ) do
|
||||
if zone[1] == title then return zone[2] end
|
||||
end
|
||||
end
|
||||
|
||||
AbstractValue.write(self, section, value)
|
||||
local timezone = lookup_zone(value) or "GMT0"
|
||||
self.map.uci:set("system", section, "timezone", timezone)
|
||||
fs.writefile("/etc/TZ", timezone .. "\n")
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Logging
|
||||
--
|
||||
|
||||
o = s:taboption("logging", Value, "log_size", translate("System log buffer size"), "kiB")
|
||||
o.optional = true
|
||||
o.placeholder = 16
|
||||
o.datatype = "uinteger"
|
||||
|
||||
o = s:taboption("logging", Value, "log_ip", translate("External system log server"))
|
||||
o.optional = true
|
||||
o.placeholder = "0.0.0.0"
|
||||
o.datatype = "ip4addr"
|
||||
|
||||
o = s:taboption("logging", Value, "log_port", translate("External system log server port"))
|
||||
o.optional = true
|
||||
o.placeholder = 514
|
||||
o.datatype = "port"
|
||||
|
||||
o = s:taboption("logging", ListValue, "log_proto", translate("External system log server protocol"))
|
||||
o:value("udp", "UDP")
|
||||
o:value("tcp", "TCP")
|
||||
|
||||
o = s:taboption("logging", Value, "log_file", translate("Write system log to file"))
|
||||
o.optional = true
|
||||
o.placeholder = "/tmp/system.log"
|
||||
|
||||
o = s:taboption("logging", ListValue, "conloglevel", translate("Log output level"))
|
||||
o:value(8, translate("Debug"))
|
||||
o:value(7, translate("Info"))
|
||||
o:value(6, translate("Notice"))
|
||||
o:value(5, translate("Warning"))
|
||||
o:value(4, translate("Error"))
|
||||
o:value(3, translate("Critical"))
|
||||
o:value(2, translate("Alert"))
|
||||
o:value(1, translate("Emergency"))
|
||||
|
||||
o = s:taboption("logging", ListValue, "cronloglevel", translate("Cron Log Level"))
|
||||
o.default = 8
|
||||
o:value(5, translate("Debug"))
|
||||
o:value(8, translate("Normal"))
|
||||
o:value(9, translate("Warning"))
|
||||
|
||||
|
||||
--
|
||||
-- Langauge & Style
|
||||
--
|
||||
|
||||
o = s:taboption("language", ListValue, "_lang", translate("Language"))
|
||||
o:value("auto")
|
||||
|
||||
local i18ndir = luci.i18n.i18ndir .. "base."
|
||||
for k, v in luci.util.kspairs(conf.languages) do
|
||||
local file = i18ndir .. k:gsub("_", "-")
|
||||
if k:sub(1, 1) ~= "." and fs.access(file .. ".lmo") then
|
||||
o:value(k, v)
|
||||
end
|
||||
end
|
||||
|
||||
function o.cfgvalue(...)
|
||||
return m.uci:get("luci", "main", "lang")
|
||||
end
|
||||
|
||||
function o.write(self, section, value)
|
||||
m.uci:set("luci", "main", "lang", value)
|
||||
end
|
||||
|
||||
|
||||
o = s:taboption("language", ListValue, "_mediaurlbase", translate("Design"))
|
||||
for k, v in pairs(conf.themes) do
|
||||
if k:sub(1, 1) ~= "." then
|
||||
o:value(v, k)
|
||||
end
|
||||
end
|
||||
|
||||
function o.cfgvalue(...)
|
||||
return m.uci:get("luci", "main", "mediaurlbase")
|
||||
end
|
||||
|
||||
function o.write(self, section, value)
|
||||
m.uci:set("luci", "main", "mediaurlbase", value)
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- NTP
|
||||
--
|
||||
|
||||
if has_ntpd then
|
||||
|
||||
-- timeserver setup was requested, create section and reload page
|
||||
if m:formvalue("cbid.system._timeserver._enable") then
|
||||
m.uci:section("system", "timeserver", "ntp",
|
||||
{
|
||||
server = { "0.openwrt.pool.ntp.org", "1.openwrt.pool.ntp.org", "2.openwrt.pool.ntp.org", "3.openwrt.pool.ntp.org" }
|
||||
}
|
||||
)
|
||||
|
||||
m.uci:save("system")
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/system", arg[1]))
|
||||
return
|
||||
end
|
||||
|
||||
local has_section = false
|
||||
m.uci:foreach("system", "timeserver",
|
||||
function(s)
|
||||
has_section = true
|
||||
return false
|
||||
end)
|
||||
|
||||
if not has_section then
|
||||
|
||||
s = m:section(TypedSection, "timeserver", translate("Time Synchronization"))
|
||||
s.anonymous = true
|
||||
s.cfgsections = function() return { "_timeserver" } end
|
||||
|
||||
x = s:option(Button, "_enable")
|
||||
x.title = translate("Time Synchronization is not configured yet.")
|
||||
x.inputtitle = translate("Set up Time Synchronization")
|
||||
x.inputstyle = "apply"
|
||||
|
||||
else
|
||||
|
||||
s = m:section(TypedSection, "timeserver", translate("Time Synchronization"))
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Flag, "enable", translate("Enable NTP client"))
|
||||
o.rmempty = false
|
||||
|
||||
function o.cfgvalue(self)
|
||||
return sys.init.enabled("sysntpd")
|
||||
and self.enabled or self.disabled
|
||||
end
|
||||
|
||||
function o.write(self, section, value)
|
||||
if value == self.enabled then
|
||||
sys.init.enable("sysntpd")
|
||||
sys.call("env -i /etc/init.d/sysntpd start >/dev/null")
|
||||
else
|
||||
sys.call("env -i /etc/init.d/sysntpd stop >/dev/null")
|
||||
sys.init.disable("sysntpd")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
o = s:option(Flag, "enable_server", translate("Provide NTP server"))
|
||||
o:depends("enable", "1")
|
||||
|
||||
|
||||
o = s:option(DynamicList, "server", translate("NTP server candidates"))
|
||||
o.datatype = "host(0)"
|
||||
o:depends("enable", "1")
|
||||
|
||||
-- retain server list even if disabled
|
||||
function o.remove() end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
return m
|
115
luci-mod-admin-full/luasrc/view/admin_network/diagnostics.htm
Normal file
115
luci-mod-admin-full/luasrc/view/admin_network/diagnostics.htm
Normal file
|
@ -0,0 +1,115 @@
|
|||
<%#
|
||||
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local has_ping6 = fs.access("/bin/ping6") or fs.access("/usr/bin/ping6")
|
||||
local has_traceroute6 = fs.access("/usr/bin/traceroute6")
|
||||
|
||||
local dns_host = luci.config.diag and luci.config.diag.dns or "dev.openwrt.org"
|
||||
local ping_host = luci.config.diag and luci.config.diag.ping or "dev.openwrt.org"
|
||||
local route_host = luci.config.diag and luci.config.diag.route or "dev.openwrt.org"
|
||||
%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var stxhr = new XHR();
|
||||
|
||||
function update_status(field, proto)
|
||||
{
|
||||
var tool = field.name;
|
||||
var addr = field.value;
|
||||
var protocol = proto ? "6" : "";
|
||||
|
||||
var legend = document.getElementById('diag-rc-legend');
|
||||
var output = document.getElementById('diag-rc-output');
|
||||
|
||||
if (legend && output)
|
||||
{
|
||||
output.innerHTML =
|
||||
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
|
||||
'<%:Waiting for command to complete...%>'
|
||||
;
|
||||
|
||||
legend.parentNode.style.display = 'block';
|
||||
legend.style.display = 'inline';
|
||||
|
||||
stxhr.post('<%=url('admin/network')%>/diag_' + tool + protocol + '/' + addr, { token: '<%=token%>' },
|
||||
function(x)
|
||||
{
|
||||
if (x.responseText)
|
||||
{
|
||||
legend.style.display = 'none';
|
||||
output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
|
||||
}
|
||||
else
|
||||
{
|
||||
legend.style.display = 'none';
|
||||
output.innerHTML = '<span class="error"><%:Bad address specified!%></span>';
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
<form method="post" action="<%=url('admin/network/diagnostics')%>">
|
||||
<div class="cbi-map">
|
||||
<h2 name="content"><%:Diagnostics%></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Network Utilities%></legend>
|
||||
|
||||
<br />
|
||||
|
||||
<div style="width:30%; float:left">
|
||||
<input style="margin: 5px 0" type="text" value="<%=ping_host%>" name="ping" /><br />
|
||||
<% if has_ping6 then %>
|
||||
<select name="ping_proto" style="width:auto">
|
||||
<option value="" selected="selected"><%:IPv4%></option>
|
||||
<option value="6"><%:IPv6%></option>
|
||||
</select>
|
||||
<input type="button" value="<%:Ping%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.ping, this.form.ping_proto.selectedIndex)" />
|
||||
<% else %>
|
||||
<input type="button" value="<%:Ping%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.ping)" />
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div style="width:33%; float:left">
|
||||
<input style="margin: 5px 0" type="text" value="<%=route_host%>" name="traceroute" /><br />
|
||||
<% if has_traceroute6 then %>
|
||||
<select name="traceroute_proto" style="width:auto">
|
||||
<option value="" selected="selected"><%:IPv4%></option>
|
||||
<option value="6"><%:IPv6%></option>
|
||||
</select>
|
||||
<input type="button" value="<%:Traceroute%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.traceroute, this.form.traceroute_proto.selectedIndex)" />
|
||||
<% else %>
|
||||
<input type="button" value="<%:Traceroute%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.traceroute)" />
|
||||
<% end %>
|
||||
<% if not has_traceroute6 then %>
|
||||
<p> </p>
|
||||
<p><%:Install iputils-traceroute6 for IPv6 traceroute%></p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div style="width:33%; float:left;">
|
||||
<input style="margin: 5px 0" type="text" value="<%=dns_host%>" name="nslookup" /><br />
|
||||
<input type="button" value="<%:Nslookup%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.nslookup)" />
|
||||
</div>
|
||||
|
||||
<br style="clear:both" /><br />
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend id="diag-rc-legend"><%:Collecting data...%></legend>
|
||||
<span id="diag-rc-output"></span>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<%+footer%>
|
254
luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm
Normal file
254
luci-mod-admin-full/luasrc/view/admin_network/iface_overview.htm
Normal file
|
@ -0,0 +1,254 @@
|
|||
<%#
|
||||
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local ntm = require "luci.model.network".init()
|
||||
local fwm = require "luci.model.firewall".init()
|
||||
|
||||
local net
|
||||
local ifaces = { }
|
||||
local netlist = { }
|
||||
for _, net in ipairs(ntm:get_networks()) do
|
||||
if net:name() ~= "loopback" then
|
||||
local z = fwm:get_zone_by_network(net:name())
|
||||
ifaces[#ifaces+1] = net:name()
|
||||
netlist[#netlist+1] = {
|
||||
net:name(), z and z:name() or "-", z
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(netlist,
|
||||
function(a, b)
|
||||
if a[2] ~= b[2] then
|
||||
return a[2] < b[2]
|
||||
else
|
||||
return a[1] < b[1]
|
||||
end
|
||||
end)
|
||||
-%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function iface_shutdown(id, reconnect) {
|
||||
if (!reconnect && !confirm(String.format('<%_Really shutdown interface "%s" ?\nYou might lose access to this device if you are connected via this interface.%>', id)))
|
||||
return;
|
||||
|
||||
var d = document.getElementById(id + '-ifc-description');
|
||||
if (d)
|
||||
d.innerHTML = reconnect
|
||||
? '<em><%:Interface is reconnecting...%></em>'
|
||||
: '<em><%:Interface is shutting down...%></em>';
|
||||
|
||||
var s = document.getElementById('ifc-rc-status');
|
||||
if (s)
|
||||
{
|
||||
s.parentNode.style.display = 'block';
|
||||
s.innerHTML = '<%:Waiting for changes to be applied...%>';
|
||||
}
|
||||
|
||||
(new XHR()).post('<%=url('admin/network')%>/iface_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, { token: '<%=token%>' },
|
||||
function(x)
|
||||
{
|
||||
if (s)
|
||||
{
|
||||
s.innerHTML = reconnect
|
||||
? '<%:Interface reconnected%>'
|
||||
: '<%:Interface shut down%>';
|
||||
|
||||
window.setTimeout(function() {
|
||||
s.parentNode.style.display = 'none';
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function iface_delete(id) {
|
||||
if (!confirm('<%:Really delete this interface? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this interface.%>'))
|
||||
return;
|
||||
|
||||
(new XHR()).post('<%=url('admin/network/iface_delete')%>/' + id, { token: '<%=token%>' },
|
||||
function(x) {
|
||||
location.href = '<%=url('admin/network/network')%>';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var iwxhr = new XHR();
|
||||
var wifidevs = <%=luci.http.write_json(netdevs)%>;
|
||||
var arptable = <%=luci.http.write_json(arpcache)%>;
|
||||
|
||||
XHR.poll(5, '<%=url('admin/network/iface_status', table.concat(ifaces, ","))%>', null,
|
||||
function(x, ifcs)
|
||||
{
|
||||
if (ifcs)
|
||||
{
|
||||
for (var idx = 0; idx < ifcs.length; idx++)
|
||||
{
|
||||
var ifc = ifcs[idx];
|
||||
var html = '';
|
||||
|
||||
var s = document.getElementById(ifc.id + '-ifc-devices');
|
||||
if (s)
|
||||
{
|
||||
var stat = String.format(
|
||||
'<img src="<%=resource%>/icons/%s%s.png" style="width:16px; height:16px; vertical-align:middle" />',
|
||||
ifc.type,
|
||||
ifc.is_up ? '' : '_disabled'
|
||||
);
|
||||
|
||||
if (ifc.subdevices && ifc.subdevices.length)
|
||||
{
|
||||
stat += ' <strong>(';
|
||||
|
||||
for (var j = 0; j < ifc.subdevices.length; j++)
|
||||
{
|
||||
var sif = ifc.subdevices[j];
|
||||
|
||||
stat += String.format(
|
||||
'<img src="<%=resource%>/icons/%s%s.png" style="width:16px; height:16px; vertical-align:middle" title="%h" />',
|
||||
sif.type,
|
||||
sif.is_up ? '' : '_disabled',
|
||||
sif.name
|
||||
);
|
||||
}
|
||||
|
||||
stat += ')</strong>';
|
||||
}
|
||||
|
||||
stat += String.format(
|
||||
'<br /><small>%h</small>',
|
||||
ifc.name
|
||||
);
|
||||
|
||||
s.innerHTML = stat;
|
||||
}
|
||||
|
||||
var d = document.getElementById(ifc.id + '-ifc-description');
|
||||
if (d && ifc.proto && ifc.ifname)
|
||||
{
|
||||
if (ifc.is_up)
|
||||
{
|
||||
html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
|
||||
}
|
||||
|
||||
if (ifc.macaddr)
|
||||
{
|
||||
html += String.format('<strong><%:MAC-Address%>:</strong> %s<br />', ifc.macaddr);
|
||||
}
|
||||
|
||||
html += String.format(
|
||||
'<strong><%:RX%></strong>: %.2mB (%d <%:Pkts.%>)<br />' +
|
||||
'<strong><%:TX%></strong>: %.2mB (%d <%:Pkts.%>)<br />',
|
||||
ifc.rx_bytes, ifc.rx_packets,
|
||||
ifc.tx_bytes, ifc.tx_packets
|
||||
);
|
||||
|
||||
if (ifc.ipaddrs && ifc.ipaddrs.length)
|
||||
{
|
||||
for (var i = 0; i < ifc.ipaddrs.length; i++)
|
||||
html += String.format(
|
||||
'<strong><%:IPv4%>:</strong> %s<br />',
|
||||
ifc.ipaddrs[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.ip6addrs && ifc.ip6addrs.length)
|
||||
{
|
||||
for (var i = 0; i < ifc.ip6addrs.length; i++)
|
||||
html += String.format(
|
||||
'<strong><%:IPv6%>:</strong> %s<br />',
|
||||
ifc.ip6addrs[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.ip6prefix)
|
||||
{
|
||||
html += String.format('<strong><%:IPv6-PD%>:</strong> %s<br />', ifc.ip6prefix);
|
||||
}
|
||||
|
||||
d.innerHTML = html;
|
||||
}
|
||||
else if (d && !ifc.proto)
|
||||
{
|
||||
var e = document.getElementById(ifc.id + '-ifc-edit');
|
||||
if (e)
|
||||
e.disabled = true;
|
||||
|
||||
d.innerHTML = String.format(
|
||||
'<em><%:Unsupported protocol type.%></em><br />' +
|
||||
'<a href="%h"><%:Install protocol extensions...%></a>',
|
||||
'<%=url("admin/system/packages")%>?query=luci-proto&display=available'
|
||||
);
|
||||
}
|
||||
else if (d && !ifc.ifname)
|
||||
{
|
||||
d.innerHTML = String.format(
|
||||
'<em><%:Network without interfaces.%></em><br />' +
|
||||
'<a href="<%=url("admin/network/network/%s")%>?tab.network.%s=physical"><%:Assign interfaces...%></a>',
|
||||
ifc.name, ifc.name
|
||||
);
|
||||
}
|
||||
else if (d)
|
||||
{
|
||||
d.innerHTML = '<em><%:Interface not present or not connected yet.%></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend><%:Reconnecting interface%></legend>
|
||||
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
|
||||
<span id="ifc-rc-status"><%:Waiting for changes to be applied...%></span>
|
||||
</fieldset>
|
||||
|
||||
<div class="cbi-map">
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Interface Overview%></legend>
|
||||
|
||||
<table class="cbi-section-table" style="margin:10px; empty-cells:hide">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell" style="text-align:left"><%:Status%></th>
|
||||
<th class="cbi-section-table-cell"><%:Actions%></th>
|
||||
</tr>
|
||||
<%
|
||||
for i, net in ipairs(netlist) do
|
||||
local z = net[3]
|
||||
local c = z and z:get_color() or "#EEEEEE"
|
||||
local t = z and translate("Part of zone %q" % z:name()) or translate("No zone assigned")
|
||||
%>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=i % 2 + 1%>">
|
||||
<td class="cbi-value-field" style="padding:3px">
|
||||
<div class="ifacebox">
|
||||
<div class="ifacebox-head" style="background-color:<%=c%>" title="<%=pcdata(t)%>">
|
||||
<strong><%=net[1]:upper()%></strong>
|
||||
</div>
|
||||
<div class="ifacebox-body" id="<%=net[1]%>-ifc-devices">
|
||||
<img src="<%=resource%>/icons/ethernet_disabled.png" style="width:16px; height:16px" /><br />
|
||||
<small>?</small>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=net[1]%>-ifc-description">
|
||||
<em><%:Collecting data...%></em>
|
||||
</td>
|
||||
<td style="width:420px">
|
||||
<input type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', true)" title="<%:Reconnect this interface%>" value="<%:Connect%>" />
|
||||
<input type="button" class="cbi-button cbi-button-reset" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', false)" title="<%:Shutdown this interface%>" value="<%:Stop%>" />
|
||||
<input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=url("admin/network/network", net[1])%>'" title="<%:Edit this interface%>" value="<%:Edit%>" id="<%=net[1]%>-ifc-edit" />
|
||||
<input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="iface_delete('<%=net[1]%>')" value="<%:Delete%>" />
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
<input type="button" class="cbi-button cbi-button-add" value="<%:Add new interface...%>" onclick="location.href='<%=url("admin/network/iface_add")%>'" />
|
||||
</fieldset>
|
||||
</div>
|
|
@ -0,0 +1,87 @@
|
|||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(5, '<%=url('admin/network/iface_status', self.network)%>', null,
|
||||
function(x, ifc)
|
||||
{
|
||||
if (ifc && (ifc = ifc[0]))
|
||||
{
|
||||
var html = '';
|
||||
|
||||
var s = document.getElementById('<%=self.option%>-ifc-signal');
|
||||
if (s)
|
||||
s.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/%s%s.png" style="width:16px; height:16px" />' +
|
||||
'<br /><small>%s</small>',
|
||||
ifc.type, ifc.is_up ? '' : '_disabled',
|
||||
ifc.name
|
||||
);
|
||||
|
||||
var d = document.getElementById('<%=self.option%>-ifc-description');
|
||||
if (d && ifc.ifname)
|
||||
{
|
||||
if (ifc.is_up)
|
||||
{
|
||||
html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
|
||||
}
|
||||
|
||||
if (ifc.macaddr)
|
||||
{
|
||||
html += String.format('<strong><%:MAC-Address%>:</strong> %s<br />', ifc.macaddr);
|
||||
}
|
||||
|
||||
html += String.format(
|
||||
'<strong><%:RX%></strong>: %.2mB (%d <%:Pkts.%>)<br />' +
|
||||
'<strong><%:TX%></strong>: %.2mB (%d <%:Pkts.%>)<br />',
|
||||
ifc.rx_bytes, ifc.rx_packets,
|
||||
ifc.tx_bytes, ifc.tx_packets
|
||||
);
|
||||
|
||||
if (ifc.ipaddrs && ifc.ipaddrs.length)
|
||||
{
|
||||
for (var i = 0; i < ifc.ipaddrs.length; i++)
|
||||
html += String.format(
|
||||
'<strong><%:IPv4%>:</strong> %s<br />',
|
||||
ifc.ipaddrs[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.ip6addrs && ifc.ip6addrs.length)
|
||||
{
|
||||
for (var i = 0; i < ifc.ip6addrs.length; i++)
|
||||
html += String.format(
|
||||
'<strong><%:IPv6%>:</strong> %s<br />',
|
||||
ifc.ip6addrs[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.ip6prefix)
|
||||
{
|
||||
html += String.format('<strong><%:IPv6-PD%>:</strong> %s<br />', ifc.ip6prefix);
|
||||
}
|
||||
|
||||
d.innerHTML = html;
|
||||
}
|
||||
else if (d)
|
||||
{
|
||||
d.innerHTML = '<em><%:Interface not present or not connected yet.%></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<table>
|
||||
<tr class="cbi-section-table">
|
||||
<td></td>
|
||||
<td class="cbi-value-field" style="min-width:16px; padding:3px; text-align:center" id="<%=self.option%>-ifc-signal">
|
||||
<img src="<%=resource%>/icons/ethernet_disabled.png" style="width:16px; height:16px" /><br />
|
||||
<small>?</small>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=self.option%>-ifc-description">
|
||||
<em><%:Collecting data...%></em>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<%+cbi/valuefooter%>
|
138
luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm
Normal file
138
luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm
Normal file
|
@ -0,0 +1,138 @@
|
|||
<script type="text/javascript">//<![CDATA[
|
||||
function duid2mac(duid) {
|
||||
// DUID-LLT / Ethernet
|
||||
if (duid.length === 28 && duid.substr(0, 8) === '00010001')
|
||||
return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
// DUID-LL / Ethernet
|
||||
if (duid.length === 24 && duid.substr(0, 8) === '00030001')
|
||||
return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
|
||||
|
||||
XHR.poll(5, '<%=url('admin/network/dhcplease_status')%>', null,
|
||||
function(x, st)
|
||||
{
|
||||
var tb = document.getElementById('lease_status_table');
|
||||
if (st && st[0] && tb)
|
||||
{
|
||||
/* clear all rows */
|
||||
while( tb.rows.length > 1 )
|
||||
tb.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < st[0].length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (st[0][i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (st[0][i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', st[0][i].expires);
|
||||
|
||||
var tr = tb.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
tr.insertCell(-1).innerHTML = st[0][i].hostname ? st[0][i].hostname : '?';
|
||||
tr.insertCell(-1).innerHTML = st[0][i].ipaddr;
|
||||
tr.insertCell(-1).innerHTML = st[0][i].macaddr;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( tb.rows.length == 1 )
|
||||
{
|
||||
var tr = tb.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
|
||||
var tb6 = document.getElementById('lease6_status_table');
|
||||
if (st && st[1] && tb6)
|
||||
{
|
||||
tb6.parentNode.style.display = 'block';
|
||||
|
||||
/* clear all rows */
|
||||
while( tb6.rows.length > 1 )
|
||||
tb6.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < st[1].length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (st[1][i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (st[1][i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', st[1][i].expires);
|
||||
|
||||
var tr = tb6.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
var host = hosts[duid2mac(st[1][i].duid)];
|
||||
if (host)
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
|
||||
((host.name && (host.ipv4 || host.ipv6))
|
||||
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
|
||||
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
|
||||
);
|
||||
else
|
||||
tr.insertCell(-1).innerHTML = st[1][i].hostname ? st[1][i].hostname : '?';
|
||||
|
||||
tr.insertCell(-1).innerHTML = st[1][i].ip6addr;
|
||||
tr.insertCell(-1).innerHTML = st[1][i].duid;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( tb6.rows.length == 1 )
|
||||
{
|
||||
var tr = tb6.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Active DHCP Leases%></legend>
|
||||
<table class="cbi-section-table" id="lease_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Hostname%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv4-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend><%:Active DHCPv6 Leases%></legend>
|
||||
<table class="cbi-section-table" id="lease6_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Host%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:DUID%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
|
@ -0,0 +1,44 @@
|
|||
<script type="text/javascript">//<![CDATA[
|
||||
var switches = [ '<%=table.concat(self.switches, "', '")%>' ];
|
||||
XHR.poll(5, '<%=url('admin/network/switch_status')%>/' + switches.join(','), null,
|
||||
function(x, st)
|
||||
{
|
||||
for (var i = 0; i < switches.length; i++)
|
||||
{
|
||||
var ports = st[switches[i]];
|
||||
var th0 = document.getElementById('portstatus-' + switches[i]);
|
||||
|
||||
if (th0 && ports && ports.length)
|
||||
{
|
||||
if (!th0.innerHTML)
|
||||
th0.innerHTML = '<%:Port status:%>';
|
||||
|
||||
for (var j = 0; j < ports.length; j++)
|
||||
{
|
||||
var th = document.getElementById('portstatus-' + switches[i] + '-' + j);
|
||||
|
||||
if (!th)
|
||||
continue;
|
||||
|
||||
if (ports[j].link)
|
||||
{
|
||||
th.innerHTML = String.format(
|
||||
'<small><img src="<%=resource%>/icons/port_up.png" />' +
|
||||
'<br />%d<%:baseT%><br />%s</small>',
|
||||
ports[j].speed, ports[j].duplex
|
||||
? '<%:full-duplex%>' : '<%:half-duplex%>'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
th.innerHTML = String.format(
|
||||
'<small><img src="<%=resource%>/icons/port_down.png" />' +
|
||||
'<br /><%:no link%></small>'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
149
luci-mod-admin-full/luasrc/view/admin_network/wifi_join.htm
Normal file
149
luci-mod-admin-full/luasrc/view/admin_network/wifi_join.htm
Normal file
|
@ -0,0 +1,149 @@
|
|||
<%#
|
||||
Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
|
||||
local sys = require "luci.sys"
|
||||
local utl = require "luci.util"
|
||||
|
||||
function guess_wifi_signal(info)
|
||||
local scale = (100 / (info.quality_max or 100) * (info.quality or 0))
|
||||
local icon
|
||||
|
||||
if not info.bssid or info.bssid == "00:00:00:00:00:00" then
|
||||
icon = resource .. "/icons/signal-none.png"
|
||||
elseif scale < 15 then
|
||||
icon = resource .. "/icons/signal-0.png"
|
||||
elseif scale < 35 then
|
||||
icon = resource .. "/icons/signal-0-25.png"
|
||||
elseif scale < 55 then
|
||||
icon = resource .. "/icons/signal-25-50.png"
|
||||
elseif scale < 75 then
|
||||
icon = resource .. "/icons/signal-50-75.png"
|
||||
else
|
||||
icon = resource .. "/icons/signal-75-100.png"
|
||||
end
|
||||
|
||||
return icon
|
||||
end
|
||||
|
||||
function percent_wifi_signal(info)
|
||||
local qc = info.quality or 0
|
||||
local qm = info.quality_max or 0
|
||||
|
||||
if info.bssid and qc > 0 and qm > 0 then
|
||||
return math.floor((100 / qm) * qc)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function format_wifi_encryption(info)
|
||||
if info.wep == true then
|
||||
return "WEP"
|
||||
elseif info.wpa > 0 then
|
||||
return translatef("<abbr title='Pairwise: %s / Group: %s'>%s - %s</abbr>",
|
||||
table.concat(info.pair_ciphers, ", "),
|
||||
table.concat(info.group_ciphers, ", "),
|
||||
(info.wpa == 3) and translate("mixed WPA/WPA2")
|
||||
or (info.wpa == 2 and "WPA2" or "WPA"),
|
||||
table.concat(info.auth_suites, ", ")
|
||||
)
|
||||
elseif info.enabled then
|
||||
return "<em>%s</em>" % translate("unknown")
|
||||
else
|
||||
return "<em>%s</em>" % translate("open")
|
||||
end
|
||||
end
|
||||
|
||||
local dev = luci.http.formvalue("device")
|
||||
local iw = luci.sys.wifi.getiwinfo(dev)
|
||||
|
||||
if not iw then
|
||||
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
function scanlist(times)
|
||||
local i, k, v
|
||||
local l = { }
|
||||
local s = { }
|
||||
|
||||
for i = 1, times do
|
||||
for k, v in ipairs(iw.scanlist or { }) do
|
||||
if not s[v.bssid] then
|
||||
l[#l+1] = v
|
||||
s[v.bssid] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return l
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Join Network: Wireless Scan%></h2>
|
||||
|
||||
<div class="cbi-map">
|
||||
<fieldset class="cbi-section">
|
||||
<table class="cbi-section-table" style="empty-cells:hide">
|
||||
<!-- scan list -->
|
||||
<% for i, net in ipairs(scanlist(3)) do net.encryption = net.encryption or { } %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
|
||||
<td class="cbi-value-field" style="width:16px; padding:3px">
|
||||
<abbr title="<%:Signal%>: <%=net.signal%> <%:dB%> / <%:Quality%>: <%=net.quality%>/<%=net.quality_max%>">
|
||||
<img src="<%=guess_wifi_signal(net)%>" /><br />
|
||||
<small><%=percent_wifi_signal(net)%>%</small>
|
||||
</abbr>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px">
|
||||
<big><strong><%=net.ssid and utl.pcdata(net.ssid) or "<em>%s</em>" % translate("hidden")%></strong></big><br />
|
||||
<strong>Channel:</strong> <%=net.channel%> |
|
||||
<strong>Mode:</strong> <%=net.mode%> |
|
||||
<strong>BSSID:</strong> <%=net.bssid%> |
|
||||
<strong>Encryption:</strong> <%=format_wifi_encryption(net.encryption)%>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="width:40px">
|
||||
<form action="<%=url('admin/network/wireless_join')%>" method="post">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
|
||||
<input type="hidden" name="join" value="<%=utl.pcdata(net.ssid)%>" />
|
||||
<input type="hidden" name="mode" value="<%=net.mode%>" />
|
||||
<input type="hidden" name="bssid" value="<%=net.bssid%>" />
|
||||
<input type="hidden" name="channel" value="<%=net.channel%>" />
|
||||
<input type="hidden" name="wep" value="<%=net.encryption.wep and 1 or 0%>" />
|
||||
<% if net.encryption.wpa then %>
|
||||
<input type="hidden" name="wpa_version" value="<%=net.encryption.wpa%>" />
|
||||
<% for _, v in ipairs(net.encryption.auth_suites) do %><input type="hidden" name="wpa_suites" value="<%=v%>" />
|
||||
<% end; for _, v in ipairs(net.encryption.group_ciphers) do %><input type="hidden" name="wpa_group" value="<%=v%>" />
|
||||
<% end; for _, v in ipairs(net.encryption.pair_ciphers) do %><input type="hidden" name="wpa_pairwise" value="<%=v%>" />
|
||||
<% end; end %>
|
||||
|
||||
<input type="hidden" name="clbridge" value="<%=iw.type == "wl" and 1 or 0%>" />
|
||||
|
||||
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Join Network%>" />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<!-- /scan list -->
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="cbi-page-actions right">
|
||||
<form class="inline" action="<%=url("admin/network/wireless")%>" method="get">
|
||||
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Back to overview%>" />
|
||||
</form>
|
||||
<form class="inline" action="<%=url('admin/network/wireless_join')%>" method="post">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
|
||||
<input class="cbi-button cbi-input-find" type="submit" value="<%:Repeat scan%>" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
470
luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm
Normal file
470
luci-mod-admin-full/luasrc/view/admin_network/wifi_overview.htm
Normal file
|
@ -0,0 +1,470 @@
|
|||
<%#
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
|
||||
local ip = require "luci.ip"
|
||||
local fs = require "nixio.fs"
|
||||
local utl = require "luci.util"
|
||||
local uci = require "luci.model.uci".cursor()
|
||||
local ntm = require "luci.model.network"
|
||||
|
||||
local has_iwinfo = pcall(require, "iwinfo")
|
||||
|
||||
ntm.init(uci)
|
||||
|
||||
function guess_wifi_hw(dev)
|
||||
local bands = ""
|
||||
local ifname = dev:name()
|
||||
local name, idx = ifname:match("^([a-z]+)(%d+)")
|
||||
idx = tonumber(idx)
|
||||
|
||||
if has_iwinfo then
|
||||
local bl = dev.iwinfo.hwmodelist
|
||||
if bl and next(bl) then
|
||||
if bl.a then bands = bands .. "a" end
|
||||
if bl.b then bands = bands .. "b" end
|
||||
if bl.g then bands = bands .. "g" end
|
||||
if bl.n then bands = bands .. "n" end
|
||||
if bl.ac then bands = bands .. "ac" end
|
||||
end
|
||||
|
||||
local hw = dev.iwinfo.hardware_name
|
||||
if hw then
|
||||
return "%s 802.11%s" %{ hw, bands }
|
||||
end
|
||||
end
|
||||
|
||||
-- wl.o
|
||||
if name == "wl" then
|
||||
local name = translatef("Broadcom 802.11%s Wireless Controller", bands)
|
||||
local nm = 0
|
||||
|
||||
local fd = nixio.open("/proc/bus/pci/devices", "r")
|
||||
if fd then
|
||||
local ln
|
||||
for ln in fd:linesource() do
|
||||
if ln:match("wl$") then
|
||||
if nm == idx then
|
||||
local version = ln:match("^%S+%s+%S%S%S%S([0-9a-f]+)")
|
||||
name = translatef(
|
||||
"Broadcom BCM%04x 802.11 Wireless Controller",
|
||||
tonumber(version, 16)
|
||||
)
|
||||
|
||||
break
|
||||
else
|
||||
nm = nm + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
fd:close()
|
||||
end
|
||||
|
||||
return name
|
||||
|
||||
-- madwifi
|
||||
elseif name == "ath" or name == "wifi" then
|
||||
return translatef("Atheros 802.11%s Wireless Controller", bands)
|
||||
|
||||
-- ralink
|
||||
elseif name == "ra" then
|
||||
return translatef("RaLink 802.11%s Wireless Controller", bands)
|
||||
|
||||
-- hermes
|
||||
elseif name == "eth" then
|
||||
return translate("Hermes 802.11b Wireless Controller")
|
||||
|
||||
-- hostap
|
||||
elseif name == "wlan" and fs.stat("/proc/net/hostap/" .. ifname, "type") == "dir" then
|
||||
return translate("Prism2/2.5/3 802.11b Wireless Controller")
|
||||
|
||||
-- dunno yet
|
||||
else
|
||||
return translatef("Generic 802.11%s Wireless Controller", bands)
|
||||
end
|
||||
end
|
||||
|
||||
local devices = ntm:get_wifidevs()
|
||||
local netlist = { }
|
||||
local netdevs = { }
|
||||
|
||||
local dev
|
||||
for _, dev in ipairs(devices) do
|
||||
local net
|
||||
for _, net in ipairs(dev:get_wifinets()) do
|
||||
netlist[#netlist+1] = net:id()
|
||||
netdevs[net:id()] = dev:name()
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<% if not has_iwinfo then %>
|
||||
<div class="errorbox">
|
||||
<strong><%:Package libiwinfo required!%></strong><br />
|
||||
<%_The <em>libiwinfo-lua</em> package is not installed. You must install this component for working wireless configuration!%>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var wifidevs = <%=luci.http.write_json(netdevs)%>;
|
||||
|
||||
var is_reconnecting = false;
|
||||
|
||||
function nowrap(s) {
|
||||
return s.replace(/ /g, ' ');
|
||||
}
|
||||
|
||||
function wifirate(bss, rx) {
|
||||
var p = rx ? 'rx_' : 'tx_',
|
||||
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
|
||||
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
|
||||
ht = bss[p+'ht'], vht = bss[p+'vht'],
|
||||
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
|
||||
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'];
|
||||
|
||||
if (ht || vht) {
|
||||
if (vht) s += ', VHT-MCS %d'.format(mcs);
|
||||
if (nss) s += ', VHT-NSS %d'.format(nss);
|
||||
if (ht) s += ', MCS %s'.format(mcs);
|
||||
if (sgi) s += ', <%:Short GI%>';
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function wifi_shutdown(id, toggle) {
|
||||
var reconnect = (toggle.getAttribute('active') == 'false');
|
||||
|
||||
if (!reconnect && !confirm(String.format('<%:Really shut down network?\nYou might lose access to this device if you are connected via this interface.%>')))
|
||||
return;
|
||||
|
||||
is_reconnecting = true;
|
||||
|
||||
var s = document.getElementById('iw-rc-status');
|
||||
if (s)
|
||||
{
|
||||
s.parentNode.style.display = 'block';
|
||||
s.innerHTML = '<%:Waiting for changes to be applied...%>';
|
||||
}
|
||||
|
||||
for (var net in wifidevs)
|
||||
{
|
||||
var st = document.getElementById(net + '-iw-status');
|
||||
if (st)
|
||||
st.innerHTML = '<em><%:Wireless is restarting...%></em>';
|
||||
}
|
||||
|
||||
(new XHR()).post('<%=url('admin/network')%>/wireless_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, { token: '<%=token%>' },
|
||||
function(x)
|
||||
{
|
||||
if (s)
|
||||
{
|
||||
s.innerHTML = reconnect
|
||||
? '<%:Wireless restarted%>'
|
||||
: '<%:Wireless shut down%>';
|
||||
|
||||
window.setTimeout(function() {
|
||||
s.parentNode.style.display = 'none';
|
||||
is_reconnecting = false;
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function wifi_delete(id) {
|
||||
if (!confirm('<%:Really delete this wireless network? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this network.%>'))
|
||||
return;
|
||||
|
||||
(new XHR()).post('<%=url('admin/network/wireless_delete')%>/' + id, { token: '<%=token%>' },
|
||||
function(x) {
|
||||
location.href = '<%=url('admin/network/wireless')%>';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
|
||||
|
||||
XHR.poll(5, '<%=url('admin/network/wireless_status', table.concat(netlist, ","))%>', null,
|
||||
function(x, st)
|
||||
{
|
||||
if (st)
|
||||
{
|
||||
var assoctable = document.getElementById('iw-assoclist');
|
||||
if (assoctable)
|
||||
while (assoctable.rows.length > 1)
|
||||
assoctable.rows[1].parentNode.removeChild(assoctable.rows[1]);
|
||||
|
||||
var devup = { };
|
||||
var rowstyle = 1;
|
||||
|
||||
for( var i = 0; i < st.length; i++ )
|
||||
{
|
||||
var iw = st[i];
|
||||
var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && iw.mode != 'Unknown' && !iw.disabled);
|
||||
var p = iw.quality;
|
||||
var q = is_assoc ? p : -1;
|
||||
|
||||
var icon;
|
||||
if (q < 0)
|
||||
icon = "<%=resource%>/icons/signal-none.png";
|
||||
else if (q == 0)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (q < 25)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (q < 50)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (q < 75)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
if (!devup[wifidevs[iw.id]])
|
||||
devup[wifidevs[iw.id]] = is_assoc;
|
||||
|
||||
var sig = document.getElementById(iw.id + '-iw-signal');
|
||||
if (sig)
|
||||
sig.innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>"><img src="%s" /> %d%%</span>',
|
||||
iw.signal, iw.noise, icon, p
|
||||
);
|
||||
|
||||
var toggle = document.getElementById(iw.id + '-iw-toggle');
|
||||
if (toggle)
|
||||
{
|
||||
if (!iw.disabled)
|
||||
{
|
||||
toggle.className = 'cbi-button cbi-button-reset';
|
||||
toggle.value = '<%:Disable%>';
|
||||
toggle.title = '<%:Shutdown this network%>';
|
||||
}
|
||||
else
|
||||
{
|
||||
toggle.className = 'cbi-button cbi-button-reload';
|
||||
toggle.value = '<%:Enable%>';
|
||||
toggle.title = '<%:Activate this network%>';
|
||||
}
|
||||
|
||||
toggle.setAttribute('active', !iw.disabled);
|
||||
}
|
||||
|
||||
var info = document.getElementById(iw.id + '-iw-status');
|
||||
if (info)
|
||||
{
|
||||
if (is_assoc)
|
||||
info.innerHTML = String.format(
|
||||
'<strong><%:SSID%>:</strong> %h | ' +
|
||||
'<strong><%:Mode%>:</strong> %s<br />' +
|
||||
'<strong><%:BSSID%>:</strong> %s | ' +
|
||||
'<strong><%:Encryption%>:</strong> %s',
|
||||
iw.ssid, iw.mode, iw.bssid,
|
||||
iw.encryption ? iw.encryption : '<%:None%>'
|
||||
);
|
||||
else
|
||||
info.innerHTML = String.format(
|
||||
'<strong><%:SSID%>:</strong> %h | ' +
|
||||
'<strong><%:Mode%>:</strong> %s<br />' +
|
||||
'<em>%s</em>',
|
||||
iw.ssid || '?', iw.mode,
|
||||
is_reconnecting
|
||||
? '<em><%:Wireless is restarting...%></em>'
|
||||
: '<em><%:Wireless is disabled or not associated%></em>'
|
||||
);
|
||||
}
|
||||
|
||||
var dev = document.getElementById(wifidevs[iw.id] + '-iw-devinfo');
|
||||
if (dev)
|
||||
{
|
||||
if (is_assoc)
|
||||
dev.innerHTML = String.format(
|
||||
'<strong><%:Channel%>:</strong> %s (%s <%:GHz%>) | ' +
|
||||
'<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%>',
|
||||
iw.channel ? iw.channel : '?',
|
||||
iw.frequency ? iw.frequency : '?',
|
||||
iw.bitrate ? iw.bitrate : '?'
|
||||
);
|
||||
else
|
||||
dev.innerHTML = '';
|
||||
}
|
||||
|
||||
if (assoctable)
|
||||
{
|
||||
var assoclist = [ ];
|
||||
for( var bssid in iw.assoclist )
|
||||
{
|
||||
assoclist.push(iw.assoclist[bssid]);
|
||||
assoclist[assoclist.length-1].bssid = bssid;
|
||||
}
|
||||
|
||||
assoclist.sort(function(a, b) { a.bssid < b.bssid });
|
||||
|
||||
for( var j = 0; j < assoclist.length; j++ )
|
||||
{
|
||||
var tr = assoctable.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + rowstyle;
|
||||
|
||||
var icon;
|
||||
var q = (-1 * (assoclist[j].noise - assoclist[j].signal)) / 5;
|
||||
if (q < 1)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (q < 2)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (q < 3)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (q < 4)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
|
||||
iw.device.name, iw.ifname
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = nowrap(String.format('%h', iw.ssid ? iw.ssid : '?'));
|
||||
tr.insertCell(-1).innerHTML = assoclist[j].bssid;
|
||||
|
||||
var host = hosts[assoclist[j].bssid];
|
||||
if (host)
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
|
||||
((host.name && (host.ipv4 || host.ipv6))
|
||||
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
|
||||
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
|
||||
);
|
||||
else
|
||||
tr.insertCell(-1).innerHTML = '?';
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
|
||||
assoclist[j].signal, assoclist[j].noise, assoclist[j].signal - assoclist[j].noise,
|
||||
icon,
|
||||
assoclist[j].signal, assoclist[j].noise
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = nowrap(wifirate(assoclist[j], true)) + '<br />' + nowrap(wifirate(assoclist[j], false));
|
||||
|
||||
rowstyle = (rowstyle == 1) ? 2 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (assoctable && assoctable.rows.length == 1)
|
||||
{
|
||||
var tr = assoctable.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 8;
|
||||
td.innerHTML = '<br /><em><%:No information available%></em>';
|
||||
}
|
||||
|
||||
for (var dev in devup)
|
||||
{
|
||||
var img = document.getElementById(dev + '-iw-upstate');
|
||||
if (img)
|
||||
img.src = '<%=resource%>/icons/wifi_big' + (devup[dev] ? '' : '_disabled') + '.png';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Wireless Overview%></h2>
|
||||
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend><%:Reconnecting interface%></legend>
|
||||
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
|
||||
<span id="iw-rc-status"><%:Waiting for changes to be applied...%></span>
|
||||
</fieldset>
|
||||
|
||||
<div class="cbi-map">
|
||||
|
||||
<% for _, dev in ipairs(devices) do local nets = dev:get_wifinets() %>
|
||||
<!-- device <%=dev:name()%> -->
|
||||
<fieldset class="cbi-section">
|
||||
<table class="cbi-section-table" style="margin:10px; empty-cells:hide">
|
||||
<!-- physical device -->
|
||||
<tr>
|
||||
<td style="width:34px"><img src="<%=resource%>/icons/wifi_big_disabled.png" style="float:left; margin-right:10px" id="<%=dev:name()%>-iw-upstate" /></td>
|
||||
<td colspan="2" style="text-align:left">
|
||||
<big><strong><%=guess_wifi_hw(dev)%> (<%=dev:name()%>)</strong></big><br />
|
||||
<span id="<%=dev:name()%>-iw-devinfo"></span>
|
||||
</td>
|
||||
<td style="width:310px;text-align:right">
|
||||
<form action="<%=url('admin/network/wireless_join')%>" method="post" class="inline">
|
||||
<input type="hidden" name="device" value="<%=dev:name()%>" />
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="submit" class="cbi-button cbi-button-find" style="width:100px" title="<%:Find and join network%>" value="<%:Scan%>" />
|
||||
</form>
|
||||
<form action="<%=url('admin/network/wireless_add')%>" method="post" class="inline">
|
||||
<input type="hidden" name="device" value="<%=dev:name()%>" />
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="submit" class="cbi-button cbi-button-add" style="width:100px" title="<%:Provide new network%>" value="<%:Add%>" />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- /physical device -->
|
||||
|
||||
<!-- network list -->
|
||||
<% if #nets > 0 then %>
|
||||
<% for i, net in ipairs(nets) do %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
|
||||
<td></td>
|
||||
<td class="cbi-value-field" style="vertical-align:middle; padding:3px" id="<%=net:id()%>-iw-signal">
|
||||
<span class="ifacebadge" title="<%:Not associated%>"><img src="<%=resource%>/icons/signal-none.png" /> 0%</span>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=net:id()%>-iw-status">
|
||||
<em><%:Collecting data...%></em>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="width:310px;text-align:right">
|
||||
<input id="<%=net:id()%>-iw-toggle" type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="wifi_shutdown('<%=net:id()%>', this)" title="<%:Delete this network%>" value="<%:Enable%>" />
|
||||
<input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
|
||||
<input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="wifi_delete('<%=net:id()%>')" title="<%:Delete this network%>" value="<%:Remove%>" />
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-2">
|
||||
<td></td>
|
||||
<td colspan="3" class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px">
|
||||
<em><%:No network configured on this device%></em>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<!-- /network list -->
|
||||
</table>
|
||||
</fieldset>
|
||||
<!-- /device <%=dev:name()%> -->
|
||||
<% end %>
|
||||
|
||||
|
||||
<h2><%:Associated Stations%></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<table class="cbi-section-table valign-middle" style="margin:10px" id="iw-assoclist">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"></th>
|
||||
<th class="cbi-section-table-cell"><%:SSID%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Host%></th>
|
||||
<th class="cbi-section-table-cell"><%:Signal%> / <%:Noise%></th>
|
||||
<th class="cbi-section-table-cell"><%:RX Rate%> / <%:TX Rate%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-2">
|
||||
<td class="cbi-value-field" colspan="6">
|
||||
<em><%:Collecting data...%></em>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
|
@ -0,0 +1,78 @@
|
|||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(5, '<%=url('admin/network/wireless_status', self.ifname)%>', null,
|
||||
function(x, iw)
|
||||
{
|
||||
if (iw && (iw = iw[0]))
|
||||
{
|
||||
var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && !iw.disabled);
|
||||
var p = iw.quality;
|
||||
var q = is_assoc ? p : -1;
|
||||
|
||||
var icon;
|
||||
if (q < 0)
|
||||
icon = "<%=resource%>/icons/signal-none.png";
|
||||
else if (q == 0)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (q < 25)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (q < 50)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (q < 75)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
var s = document.getElementById('<%=self.option%>-iw-signal');
|
||||
if (s)
|
||||
s.innerHTML = String.format(
|
||||
'<img src="%s" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>" /><br />' +
|
||||
'<small>%d%%</small>', icon, iw.signal, iw.noise, p
|
||||
);
|
||||
|
||||
var d = document.getElementById('<%=self.option%>-iw-description');
|
||||
if (d && is_assoc)
|
||||
d.innerHTML = String.format(
|
||||
'<strong><%:Mode%>:</strong> %s | ' +
|
||||
'<strong><%:SSID%>:</strong> %h<br />' +
|
||||
'<strong><%:BSSID%>:</strong> %s | ' +
|
||||
'<strong><%:Encryption%>:</strong> %s<br />' +
|
||||
'<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>) | ' +
|
||||
'<strong><%:Tx-Power%>:</strong> %d <%:dBm%><br />' +
|
||||
'<strong><%:Signal%>:</strong> %d <%:dBm%> | ' +
|
||||
'<strong><%:Noise%>:</strong> %d <%:dBm%><br />' +
|
||||
'<strong><%:Bitrate%>:</strong> %.1f <%:Mbit/s%> | ' +
|
||||
'<strong><%:Country%>:</strong> %s',
|
||||
iw.mode, iw.ssid, iw.bssid,
|
||||
iw.encryption ? iw.encryption : '<%:None%>',
|
||||
iw.channel, iw.frequency ? iw.frequency : 0,
|
||||
iw.txpower, iw.signal, iw.noise,
|
||||
iw.bitrate ? iw.bitrate : 0, iw.country
|
||||
);
|
||||
else if (d)
|
||||
d.innerHTML = String.format(
|
||||
'<strong><%:SSID%>:</strong> %h | ' +
|
||||
'<strong><%:Mode%>:</strong> %s<br />' +
|
||||
'<em><%:Wireless is disabled or not associated%></em>',
|
||||
iw.ssid || '?', iw.mode
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<table>
|
||||
<tr class="cbi-section-table">
|
||||
<td></td>
|
||||
<td class="cbi-value-field" style="width:16px; padding:3px" id="<%=self.option%>-iw-signal">
|
||||
<img src="<%=resource%>/icons/signal-none.png" title="<%:Not associated%>" /><br />
|
||||
<small>0%</small>
|
||||
</td>
|
||||
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=self.option%>-iw-description">
|
||||
<em><%:Collecting data...%></em>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<%+cbi/valuefooter%>
|
301
luci-mod-admin-full/luasrc/view/admin_status/bandwidth.htm
Normal file
301
luci-mod-admin-full/luasrc/view/admin_status/bandwidth.htm
Normal file
|
@ -0,0 +1,301 @@
|
|||
<%#
|
||||
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local ntm = require "luci.model.network".init()
|
||||
|
||||
local dev
|
||||
local devices = { }
|
||||
for _, dev in luci.util.vspairs(luci.sys.net.devices()) do
|
||||
if dev ~= "lo" and not ntm:ignore_interface(dev) then
|
||||
devices[#devices+1] = dev
|
||||
end
|
||||
end
|
||||
|
||||
local curdev = luci.http.formvalue("dev") or devices[1]
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var RXB = 1;
|
||||
var RXP = 2;
|
||||
var TXB = 3;
|
||||
var TXP = 4;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 0;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_rx = [ ];
|
||||
var data_tx = [ ];
|
||||
|
||||
var line_rx;
|
||||
var line_tx;
|
||||
|
||||
var label_25;
|
||||
var label_50;
|
||||
var label_75;
|
||||
|
||||
var label_rx_cur;
|
||||
var label_rx_avg;
|
||||
var label_rx_peak;
|
||||
|
||||
var label_tx_cur;
|
||||
var label_tx_avg;
|
||||
var label_tx_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
|
||||
function bandwidth_label(bytes, br)
|
||||
{
|
||||
var uby = '<%:kB/s%>';
|
||||
var kby = (bytes / 1024);
|
||||
|
||||
if (kby >= 1024)
|
||||
{
|
||||
uby = '<%:MB/s%>';
|
||||
kby = kby / 1024;
|
||||
}
|
||||
|
||||
var ubi = '<%:kbit/s%>';
|
||||
var kbi = (bytes * 8 / 1024);
|
||||
|
||||
if (kbi >= 1024)
|
||||
{
|
||||
ubi = '<%:Mbit/s%>';
|
||||
kbi = kbi / 1024;
|
||||
}
|
||||
|
||||
return String.format("%f %s%s(%f %s)",
|
||||
kbi.toFixed(2), ubi,
|
||||
br ? '<br />' : ' ',
|
||||
kby.toFixed(2), uby
|
||||
);
|
||||
}
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
var svg = document.getElementById('bwsvg');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['bwsvg'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G)
|
||||
{
|
||||
window.setTimeout(arguments.callee, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_wanted; i++)
|
||||
{
|
||||
data_rx[i] = 0;
|
||||
data_tx[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_rx = G.getElementById('rx');
|
||||
line_tx = G.getElementById('tx');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_rx_cur = document.getElementById('rx_bw_cur');
|
||||
label_rx_avg = document.getElementById('rx_bw_avg');
|
||||
label_rx_peak = document.getElementById('rx_bw_peak');
|
||||
|
||||
label_tx_cur = document.getElementById('tx_bw_cur');
|
||||
label_tx_avg = document.getElementById('tx_bw_avg');
|
||||
label_tx_peak = document.getElementById('tx_bw_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (step * 60); i < width; i += step * 60)
|
||||
{
|
||||
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#999999; font-size:9pt');
|
||||
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25.parentNode.appendChild(line);
|
||||
label_25.parentNode.appendChild(text);
|
||||
}
|
||||
|
||||
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/bandwidth_status", curdev)%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_rx_avg = 0;
|
||||
var data_tx_avg = 0;
|
||||
|
||||
var data_rx_peak = 0;
|
||||
var data_tx_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
/* normalize difference against time interval */
|
||||
if (i > 0)
|
||||
{
|
||||
var time_delta = data[i][TIME] - data[i-1][TIME];
|
||||
if (time_delta)
|
||||
{
|
||||
data_rx.push((data[i][RXB] - data[i-1][RXB]) / time_delta);
|
||||
data_tx.push((data[i][TXB] - data[i-1][TXB]) / time_delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_rx = data_rx.slice(data_rx.length - data_wanted, data_rx.length);
|
||||
data_tx = data_tx.slice(data_tx.length - data_wanted, data_tx.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_rx.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_rx[i]);
|
||||
data_max = Math.max(data_max, data_tx[i]);
|
||||
|
||||
data_rx_peak = Math.max(data_rx_peak, data_rx[i]);
|
||||
data_tx_peak = Math.max(data_tx_peak, data_tx[i]);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
data_rx_avg = (data_rx_avg + data_rx[i]) / 2;
|
||||
data_tx_avg = (data_tx_avg + data_tx[i]) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_rx_avg = data_rx[i];
|
||||
data_tx_avg = data_tx[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / (data_max * 1.1);
|
||||
|
||||
|
||||
/* plot data */
|
||||
var pt_rx = '0,' + height;
|
||||
var pt_tx = '0,' + height;
|
||||
|
||||
var y_rx = 0;
|
||||
var y_tx = 0;
|
||||
|
||||
for (var i = 0; i < data_rx.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_rx = height - Math.floor(data_rx[i] * data_scale);
|
||||
y_tx = height - Math.floor(data_tx[i] * data_scale);
|
||||
|
||||
pt_rx += ' ' + x + ',' + y_rx;
|
||||
pt_tx += ' ' + x + ',' + y_tx;
|
||||
}
|
||||
|
||||
pt_rx += ' ' + width + ',' + y_rx + ' ' + width + ',' + height;
|
||||
pt_tx += ' ' + width + ',' + y_tx + ' ' + width + ',' + height;
|
||||
|
||||
|
||||
line_rx.setAttribute('points', pt_rx);
|
||||
line_tx.setAttribute('points', pt_tx);
|
||||
|
||||
label_25.firstChild.data = bandwidth_label(1.1 * 0.25 * data_max);
|
||||
label_50.firstChild.data = bandwidth_label(1.1 * 0.50 * data_max);
|
||||
label_75.firstChild.data = bandwidth_label(1.1 * 0.75 * data_max);
|
||||
|
||||
label_rx_cur.innerHTML = bandwidth_label(data_rx[data_rx.length-1], true);
|
||||
label_tx_cur.innerHTML = bandwidth_label(data_tx[data_tx.length-1], true);
|
||||
|
||||
label_rx_avg.innerHTML = bandwidth_label(data_rx_avg, true);
|
||||
label_tx_avg.innerHTML = bandwidth_label(data_tx_avg, true);
|
||||
|
||||
label_rx_peak.innerHTML = bandwidth_label(data_rx_peak, true);
|
||||
label_tx_peak.innerHTML = bandwidth_label(data_tx_peak, true);
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Traffic%></h2>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<% for _, dev in ipairs(devices) do %>
|
||||
<li class="cbi-tab<%= dev == curdev and "" or "-disabled" %>"><a href="?dev=<%=pcdata(dev)%>"><%=pcdata(dev)%></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/bandwidth.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<table style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:Inbound:%></strong></td>
|
||||
<td id="rx_bw_cur">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="rx_bw_avg">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="rx_bw_peak">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:Outbound:%></strong></td>
|
||||
<td id="tx_bw_cur">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="tx_bw_avg">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="tx_bw_peak">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<%+footer%>
|
376
luci-mod-admin-full/luasrc/view/admin_status/connections.htm
Normal file
376
luci-mod-admin-full/luasrc/view/admin_status/connections.htm
Normal file
|
@ -0,0 +1,376 @@
|
|||
<%#
|
||||
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var UDP = 1;
|
||||
var TCP = 2;
|
||||
var OTHER = 3;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 0;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_udp = [ ];
|
||||
var data_tcp = [ ];
|
||||
var data_otr = [ ];
|
||||
|
||||
var line_udp;
|
||||
var line_tcp;
|
||||
|
||||
var label_25;
|
||||
var label_50;
|
||||
var label_75;
|
||||
|
||||
var label_udp_cur;
|
||||
var label_udp_avg;
|
||||
var label_udp_peak;
|
||||
|
||||
var label_tcp_cur;
|
||||
var label_tcp_avg;
|
||||
var label_tcp_peak;
|
||||
|
||||
var label_otr_cur;
|
||||
var label_otr_avg;
|
||||
var label_otr_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
var conn_table;
|
||||
|
||||
var dns_cache = { };
|
||||
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
var svg = document.getElementById('bwsvg');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['bwsvg'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G)
|
||||
{
|
||||
window.setTimeout(arguments.callee, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_wanted; i++)
|
||||
{
|
||||
data_udp[i] = 0;
|
||||
data_tcp[i] = 0;
|
||||
data_otr[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_udp = G.getElementById('udp');
|
||||
line_tcp = G.getElementById('tcp');
|
||||
line_otr = G.getElementById('other');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_udp_cur = document.getElementById('lb_udp_cur');
|
||||
label_udp_avg = document.getElementById('lb_udp_avg');
|
||||
label_udp_peak = document.getElementById('lb_udp_peak');
|
||||
|
||||
label_tcp_cur = document.getElementById('lb_tcp_cur');
|
||||
label_tcp_avg = document.getElementById('lb_tcp_avg');
|
||||
label_tcp_peak = document.getElementById('lb_tcp_peak');
|
||||
|
||||
label_otr_cur = document.getElementById('lb_otr_cur');
|
||||
label_otr_avg = document.getElementById('lb_otr_avg');
|
||||
label_otr_peak = document.getElementById('lb_otr_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
conn_table = document.getElementById('connections');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (step * 60); i < width; i += step * 60)
|
||||
{
|
||||
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#999999; font-size:9pt');
|
||||
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25.parentNode.appendChild(line);
|
||||
label_25.parentNode.appendChild(text);
|
||||
}
|
||||
|
||||
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/connections_status")%>', null,
|
||||
function(x, json)
|
||||
{
|
||||
var conn = json.connections;
|
||||
|
||||
while (conn_table.rows.length > 1)
|
||||
conn_table.rows[0].parentNode.deleteRow(-1);
|
||||
|
||||
|
||||
var lookup_queue = [ ];
|
||||
|
||||
conn.sort(function(a, b) {
|
||||
return b.bytes - a.bytes;
|
||||
});
|
||||
|
||||
for (var i = 0; i < conn.length; i++)
|
||||
{
|
||||
var c = conn[i];
|
||||
|
||||
if ((c.src == '127.0.0.1' && c.dst == '127.0.0.1')
|
||||
|| (c.src == '::1' && c.dst == '::1'))
|
||||
continue;
|
||||
|
||||
var tr = conn_table.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
if (!dns_cache[c.src])
|
||||
lookup_queue.push(c.src);
|
||||
|
||||
if (!dns_cache[c.dst])
|
||||
lookup_queue.push(c.dst);
|
||||
|
||||
var src = dns_cache[c.src] || (c.layer3 == 'ipv6' ? '[' + c.src + ']' : c.src);
|
||||
var dst = dns_cache[c.dst] || (c.layer3 == 'ipv6' ? '[' + c.dst + ']' : c.dst);
|
||||
|
||||
tr.insertCell(-1).innerHTML = c.layer3.toUpperCase();
|
||||
tr.insertCell(-1).innerHTML = c.layer4.toUpperCase();
|
||||
tr.insertCell(-1).innerHTML = String.format('%s:%d', src, c.sport);
|
||||
tr.insertCell(-1).innerHTML = String.format('%s:%d', dst, c.dport);
|
||||
|
||||
var traf = tr.insertCell(-1);
|
||||
traf.style.whiteSpace = 'nowrap';
|
||||
traf.innerHTML = String.format('%1024.2mB (%d <%:Pkts.%>)', c.bytes, c.packets);
|
||||
}
|
||||
|
||||
if (lookup_queue.length > 0)
|
||||
XHR.get('<%=build_url("admin/status/nameinfo")%>/' + lookup_queue.slice(0, 100).join('/'), null,
|
||||
function(x, json)
|
||||
{
|
||||
for (var addr in json)
|
||||
dns_cache[addr] = json[addr];
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
var data = json.statistics;
|
||||
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_udp_avg = 0;
|
||||
var data_tcp_avg = 0;
|
||||
var data_otr_avg = 0;
|
||||
|
||||
var data_udp_peak = 0;
|
||||
var data_tcp_peak = 0;
|
||||
var data_otr_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_udp.push(data[i][UDP]);
|
||||
data_tcp.push(data[i][TCP]);
|
||||
data_otr.push(data[i][OTHER]);
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_udp = data_udp.slice(data_udp.length - data_wanted, data_udp.length);
|
||||
data_tcp = data_tcp.slice(data_tcp.length - data_wanted, data_tcp.length);
|
||||
data_otr = data_otr.slice(data_otr.length - data_wanted, data_otr.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_udp.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_udp[i]);
|
||||
data_max = Math.max(data_max, data_tcp[i]);
|
||||
data_max = Math.max(data_max, data_otr[i]);
|
||||
|
||||
data_udp_peak = Math.max(data_udp_peak, data_udp[i]);
|
||||
data_tcp_peak = Math.max(data_tcp_peak, data_tcp[i]);
|
||||
data_otr_peak = Math.max(data_otr_peak, data_otr[i]);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
data_udp_avg = (data_udp_avg + data_udp[i]) / 2;
|
||||
data_tcp_avg = (data_tcp_avg + data_tcp[i]) / 2;
|
||||
data_otr_avg = (data_otr_avg + data_otr[i]) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_udp_avg = data_udp[i];
|
||||
data_tcp_avg = data_tcp[i];
|
||||
data_otr_avg = data_otr[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / (data_max * 1.1);
|
||||
|
||||
|
||||
/* plot data */
|
||||
var pt_udp = '0,' + height;
|
||||
var pt_tcp = '0,' + height;
|
||||
var pt_otr = '0,' + height;
|
||||
|
||||
var y_udp = 0;
|
||||
var y_tcp = 0;
|
||||
var y_otr = 0;
|
||||
|
||||
for (var i = 0; i < data_udp.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_udp = height - Math.floor(data_udp[i] * data_scale);
|
||||
y_tcp = height - Math.floor(data_tcp[i] * data_scale);
|
||||
y_otr = height - Math.floor(data_otr[i] * data_scale);
|
||||
|
||||
pt_udp += ' ' + x + ',' + y_udp;
|
||||
pt_tcp += ' ' + x + ',' + y_tcp;
|
||||
pt_otr += ' ' + x + ',' + y_otr;
|
||||
}
|
||||
|
||||
pt_udp += ' ' + width + ',' + y_udp + ' ' + width + ',' + height;
|
||||
pt_tcp += ' ' + width + ',' + y_tcp + ' ' + width + ',' + height;
|
||||
pt_otr += ' ' + width + ',' + y_otr + ' ' + width + ',' + height;
|
||||
|
||||
|
||||
var order = [
|
||||
[ line_udp, data_udp[data_udp.length-1] ],
|
||||
[ line_tcp, data_tcp[data_tcp.length-1] ],
|
||||
[ line_otr, data_otr[data_otr.length-1] ]
|
||||
];
|
||||
|
||||
order.sort(function(a, b) { return b[1] - a[1] });
|
||||
|
||||
for (var i = 0; i < order.length; i++)
|
||||
order[i][0].parentNode.appendChild(order[i][0]);
|
||||
|
||||
|
||||
line_udp.setAttribute('points', pt_udp);
|
||||
line_tcp.setAttribute('points', pt_tcp);
|
||||
line_otr.setAttribute('points', pt_otr);
|
||||
|
||||
label_25.firstChild.data = Math.floor(1.1 * 0.25 * data_max);
|
||||
label_50.firstChild.data = Math.floor(1.1 * 0.50 * data_max);
|
||||
label_75.firstChild.data = Math.floor(1.1 * 0.75 * data_max);
|
||||
|
||||
label_udp_cur.innerHTML = Math.floor(data_udp[data_udp.length-1]);
|
||||
label_tcp_cur.innerHTML = Math.floor(data_tcp[data_tcp.length-1]);
|
||||
label_otr_cur.innerHTML = Math.floor(data_otr[data_otr.length-1]);
|
||||
|
||||
label_udp_avg.innerHTML = Math.floor(data_udp_avg);
|
||||
label_tcp_avg.innerHTML = Math.floor(data_tcp_avg);
|
||||
label_otr_avg.innerHTML = Math.floor(data_otr_avg);
|
||||
|
||||
label_udp_peak.innerHTML = Math.floor(data_udp_peak);
|
||||
label_tcp_peak.innerHTML = Math.floor(data_tcp_peak);
|
||||
label_otr_peak.innerHTML = Math.floor(data_otr_peak);
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Connections%></h2>
|
||||
|
||||
<div class="cbi-map-descr"><%:This page gives an overview over currently active network connections.%></div>
|
||||
|
||||
<fieldset class="cbi-section" id="cbi-table-table">
|
||||
<legend><%:Active Connections%></legend>
|
||||
|
||||
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/connections.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<table style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:UDP:%></strong></td>
|
||||
<td id="lb_udp_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_udp_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_udp_peak">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:TCP:%></strong></td>
|
||||
<td id="lb_tcp_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_tcp_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_tcp_peak">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid red"><%:Other:%></strong></td>
|
||||
<td id="lb_otr_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_otr_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_otr_peak">0</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br />
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table" id="connections">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:Protocol%></th>
|
||||
<th class="cbi-section-table-cell"><%:Source%></th>
|
||||
<th class="cbi-section-table-cell"><%:Destination%></th>
|
||||
<th class="cbi-section-table-cell"><%:Transfer%></th>
|
||||
</tr>
|
||||
|
||||
<tr><td colspan="5"><em><%:Collecting data...%></em></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<%+footer%>
|
12
luci-mod-admin-full/luasrc/view/admin_status/dmesg.htm
Normal file
12
luci-mod-admin-full/luasrc/view/admin_status/dmesg.htm
Normal file
|
@ -0,0 +1,12 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
<h2 name="content"><%:Kernel Log%></h2>
|
||||
<div id="content_syslog">
|
||||
<textarea readonly="readonly" wrap="off" rows="<%=dmesg:cmatch("\n")+2%>" id="syslog"><%=dmesg:pcdata()%></textarea>
|
||||
</div>
|
||||
<%+footer%>
|
827
luci-mod-admin-full/luasrc/view/admin_status/index.htm
Normal file
827
luci-mod-admin-full/luasrc/view/admin_status/index.htm
Normal file
|
@ -0,0 +1,827 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%
|
||||
local fs = require "nixio.fs"
|
||||
local util = require "luci.util"
|
||||
local stat = require "luci.tools.status"
|
||||
local ver = require "luci.version"
|
||||
|
||||
local has_ipv6 = fs.access("/proc/net/ipv6_route")
|
||||
local has_dhcp = fs.access("/etc/config/dhcp")
|
||||
local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
|
||||
|
||||
local sysinfo = luci.util.ubus("system", "info") or { }
|
||||
local boardinfo = luci.util.ubus("system", "board") or { }
|
||||
local unameinfo = nixio.uname() or { }
|
||||
|
||||
local meminfo = sysinfo.memory or {
|
||||
total = 0,
|
||||
free = 0,
|
||||
buffered = 0,
|
||||
shared = 0
|
||||
}
|
||||
|
||||
local swapinfo = sysinfo.swap or {
|
||||
total = 0,
|
||||
free = 0
|
||||
}
|
||||
|
||||
local has_dsl = fs.access("/etc/init.d/dsl_control")
|
||||
|
||||
if luci.http.formvalue("status") == "1" then
|
||||
local ntm = require "luci.model.network".init()
|
||||
local wan = ntm:get_wannet()
|
||||
local wan6 = ntm:get_wan6net()
|
||||
|
||||
local conn_count = tonumber(
|
||||
fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count")) or 0
|
||||
|
||||
local conn_max = tonumber((
|
||||
luci.sys.exec("sysctl net.nf_conntrack_max") or
|
||||
luci.sys.exec("sysctl net.ipv4.netfilter.ip_conntrack_max") or
|
||||
""):match("%d+")) or 4096
|
||||
|
||||
local rv = {
|
||||
uptime = sysinfo.uptime or 0,
|
||||
localtime = os.date(),
|
||||
loadavg = sysinfo.load or { 0, 0, 0 },
|
||||
memory = meminfo,
|
||||
swap = swapinfo,
|
||||
connmax = conn_max,
|
||||
conncount = conn_count,
|
||||
leases = stat.dhcp_leases(),
|
||||
leases6 = stat.dhcp6_leases(),
|
||||
wifinets = stat.wifi_networks()
|
||||
}
|
||||
|
||||
if wan then
|
||||
rv.wan = {
|
||||
ipaddr = wan:ipaddr(),
|
||||
gwaddr = wan:gwaddr(),
|
||||
netmask = wan:netmask(),
|
||||
dns = wan:dnsaddrs(),
|
||||
expires = wan:expires(),
|
||||
uptime = wan:uptime(),
|
||||
proto = wan:proto(),
|
||||
ifname = wan:ifname(),
|
||||
link = wan:adminlink()
|
||||
}
|
||||
end
|
||||
|
||||
if wan6 then
|
||||
rv.wan6 = {
|
||||
ip6addr = wan6:ip6addr(),
|
||||
gw6addr = wan6:gw6addr(),
|
||||
dns = wan6:dns6addrs(),
|
||||
ip6prefix = wan6:ip6prefix(),
|
||||
uptime = wan6:uptime(),
|
||||
proto = wan6:proto(),
|
||||
ifname = wan6:ifname(),
|
||||
link = wan6:adminlink()
|
||||
}
|
||||
end
|
||||
|
||||
if has_dsl then
|
||||
local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
|
||||
local dsl_func = loadstring(dsl_stat)
|
||||
if dsl_func then
|
||||
rv.dsl = dsl_func()
|
||||
end
|
||||
end
|
||||
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(rv)
|
||||
|
||||
return
|
||||
elseif luci.http.formvalue("hosts") == "1" then
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json(luci.sys.net.host_hints())
|
||||
|
||||
return
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
function progressbar(v, m)
|
||||
{
|
||||
var vn = parseInt(v) || 0;
|
||||
var mn = parseInt(m) || 100;
|
||||
var pc = Math.floor((100 / mn) * vn);
|
||||
|
||||
return String.format(
|
||||
'<div style="width:200px; position:relative; border:1px solid #999999">' +
|
||||
'<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
|
||||
'<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
|
||||
'<small>%s / %s (%d%%)</small>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>', pc, v, m, pc
|
||||
);
|
||||
}
|
||||
|
||||
function wifirate(bss, rx) {
|
||||
var p = rx ? 'rx_' : 'tx_',
|
||||
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
|
||||
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
|
||||
ht = bss[p+'ht'], vht = bss[p+'vht'],
|
||||
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
|
||||
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'];
|
||||
|
||||
if (ht || vht) {
|
||||
if (vht) s += ', VHT-MCS %d'.format(mcs);
|
||||
if (nss) s += ', VHT-NSS %d'.format(nss);
|
||||
if (ht) s += ', MCS %s'.format(mcs);
|
||||
if (sgi) s += ', <%:Short GI%>';
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function duid2mac(duid) {
|
||||
// DUID-LLT / Ethernet
|
||||
if (duid.length === 28 && duid.substr(0, 8) === '00010001')
|
||||
return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
// DUID-LL / Ethernet
|
||||
if (duid.length === 24 && duid.substr(0, 8) === '00030001')
|
||||
return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
var npoll = 1;
|
||||
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
|
||||
|
||||
function updateHosts() {
|
||||
XHR.get('<%=REQUEST_URI%>', { hosts: 1 }, function(x, data) {
|
||||
hosts = data;
|
||||
});
|
||||
}
|
||||
|
||||
XHR.poll(5, '<%=REQUEST_URI%>', { status: 1 },
|
||||
function(x, info)
|
||||
{
|
||||
if (!(npoll++ % 5))
|
||||
updateHosts();
|
||||
|
||||
var si = document.getElementById('wan4_i');
|
||||
var ss = document.getElementById('wan4_s');
|
||||
var ifc = info.wan;
|
||||
|
||||
if (ifc && ifc.ifname && ifc.proto != 'none')
|
||||
{
|
||||
var s = String.format(
|
||||
'<strong><%:Type%>: </strong>%s<br />' +
|
||||
'<strong><%:Address%>: </strong>%s<br />' +
|
||||
'<strong><%:Netmask%>: </strong>%s<br />' +
|
||||
'<strong><%:Gateway%>: </strong>%s<br />',
|
||||
ifc.proto,
|
||||
(ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
|
||||
(ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
|
||||
(ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0'
|
||||
);
|
||||
|
||||
for (var i = 0; i < ifc.dns.length; i++)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:DNS%> %d: </strong>%s<br />',
|
||||
i + 1, ifc.dns[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.expires > -1)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Expires%>: </strong>%t<br />',
|
||||
ifc.expires
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc.uptime > 0)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Connected%>: </strong>%t<br />',
|
||||
ifc.uptime
|
||||
);
|
||||
}
|
||||
|
||||
ss.innerHTML = String.format('<small>%s</small>', s);
|
||||
si.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small><a href="%s">%s</a></small>',
|
||||
ifc.link, ifc.ifname
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
si.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
|
||||
ss.innerHTML = '<em><%:Not connected%></em>';
|
||||
}
|
||||
|
||||
<% if has_ipv6 then %>
|
||||
var si6 = document.getElementById('wan6_i');
|
||||
var ss6 = document.getElementById('wan6_s');
|
||||
var ifc6 = info.wan6;
|
||||
|
||||
if (ifc6 && ifc6.ifname && ifc6.proto != 'none')
|
||||
{
|
||||
var s = String.format(
|
||||
'<strong><%:Type%>: </strong>%s%s<br />',
|
||||
ifc6.proto, (ifc6.ip6prefix) ? '-pd' : ''
|
||||
);
|
||||
|
||||
if (!ifc6.ip6prefix)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Address%>: </strong>%s<br />',
|
||||
(ifc6.ip6addr) ? ifc6.ip6addr : '::'
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Prefix Delegated%>: </strong>%s<br />',
|
||||
ifc6.ip6prefix
|
||||
);
|
||||
if (ifc6.ip6addr)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Address%>: </strong>%s<br />',
|
||||
ifc6.ip6addr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
s += String.format(
|
||||
'<strong><%:Gateway%>: </strong>%s<br />',
|
||||
(ifc6.gw6addr) ? ifc6.gw6addr : '::'
|
||||
);
|
||||
|
||||
for (var i = 0; i < ifc6.dns.length; i++)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:DNS%> %d: </strong>%s<br />',
|
||||
i + 1, ifc6.dns[i]
|
||||
);
|
||||
}
|
||||
|
||||
if (ifc6.uptime > 0)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:Connected%>: </strong>%t<br />',
|
||||
ifc6.uptime
|
||||
);
|
||||
}
|
||||
|
||||
ss6.innerHTML = String.format('<small>%s</small>', s);
|
||||
si6.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small><a href="%s">%s</a></small>',
|
||||
ifc6.link, ifc6.ifname
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
|
||||
ss6.innerHTML = '<em><%:Not connected%></em>';
|
||||
}
|
||||
<% end %>
|
||||
|
||||
<% if has_dsl then %>
|
||||
var dsl_i = document.getElementById('dsl_i');
|
||||
var dsl_s = document.getElementById('dsl_s');
|
||||
|
||||
var s = String.format(
|
||||
'<strong><%:Status%>: </strong>%s<br />' +
|
||||
'<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
|
||||
'<strong><%:Line Mode%>: </strong>%s<br />' +
|
||||
'<strong><%:Annex%>: </strong>%s<br />' +
|
||||
'<strong><%:Profile%>: </strong>%s<br />' +
|
||||
'<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
|
||||
'<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
|
||||
'<strong><%:Latency%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
|
||||
'<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
|
||||
'<strong><%:Line Uptime%>: </strong>%s<br />' +
|
||||
'<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
|
||||
'<strong><%:Power Management Mode%>: </strong>%s<br />',
|
||||
info.dsl.line_state, info.dsl.line_state_detail,
|
||||
info.dsl.line_state_num,
|
||||
info.dsl.line_mode_s,
|
||||
info.dsl.annex_s,
|
||||
info.dsl.profile_s,
|
||||
info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
|
||||
info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
|
||||
info.dsl.latency_num_down, info.dsl.latency_num_up,
|
||||
info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
|
||||
info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
|
||||
info.dsl.noise_margin_down, info.dsl.noise_margin_up,
|
||||
info.dsl.actatp_down, info.dsl.actatp_up,
|
||||
info.dsl.errors_fec_near, info.dsl.errors_fec_far,
|
||||
info.dsl.errors_es_near, info.dsl.errors_es_far,
|
||||
info.dsl.errors_ses_near, info.dsl.errors_ses_far,
|
||||
info.dsl.errors_loss_near, info.dsl.errors_loss_far,
|
||||
info.dsl.errors_uas_near, info.dsl.errors_uas_far,
|
||||
info.dsl.errors_hec_near, info.dsl.errors_hec_far,
|
||||
info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
|
||||
info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
|
||||
info.dsl.line_uptime_s,
|
||||
info.dsl.atuc_vendor_id,
|
||||
info.dsl.power_mode_s
|
||||
);
|
||||
|
||||
dsl_s.innerHTML = String.format('<small>%s</small>', s);
|
||||
dsl_i.innerHTML = String.format(
|
||||
'<img src="<%=resource%>/icons/ethernet.png" />' +
|
||||
'<br /><small>DSL</small>'
|
||||
);
|
||||
<% end %>
|
||||
|
||||
<% if has_dhcp then %>
|
||||
var ls = document.getElementById('lease_status_table');
|
||||
if (ls)
|
||||
{
|
||||
/* clear all rows */
|
||||
while( ls.rows.length > 1 )
|
||||
ls.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < info.leases.length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (info.leases[i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (info.leases[i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', info.leases[i].expires);
|
||||
|
||||
var tr = ls.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
|
||||
tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( ls.rows.length == 1 )
|
||||
{
|
||||
var tr = ls.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
|
||||
var ls6 = document.getElementById('lease6_status_table');
|
||||
if (ls6 && info.leases6)
|
||||
{
|
||||
ls6.parentNode.style.display = 'block';
|
||||
|
||||
/* clear all rows */
|
||||
while( ls6.rows.length > 1 )
|
||||
ls6.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
for( var i = 0; i < info.leases6.length; i++ )
|
||||
{
|
||||
var timestr;
|
||||
|
||||
if (info.leases6[i].expires === false)
|
||||
timestr = '<em><%:unlimited%></em>';
|
||||
else if (info.leases6[i].expires <= 0)
|
||||
timestr = '<em><%:expired%></em>';
|
||||
else
|
||||
timestr = String.format('%t', info.leases6[i].expires);
|
||||
|
||||
var tr = ls6.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
|
||||
|
||||
var host = hosts[duid2mac(info.leases6[i].duid)];
|
||||
if (host)
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
|
||||
((host.name && (host.ipv4 || host.ipv6))
|
||||
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
|
||||
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
|
||||
);
|
||||
else
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].hostname ? info.leases6[i].hostname : '?';
|
||||
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
|
||||
tr.insertCell(-1).innerHTML = info.leases6[i].duid;
|
||||
tr.insertCell(-1).innerHTML = timestr;
|
||||
}
|
||||
|
||||
if( ls6.rows.length == 1 )
|
||||
{
|
||||
var tr = ls6.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 4;
|
||||
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
|
||||
<% if has_wifi then %>
|
||||
var assoclist = [ ];
|
||||
|
||||
var ws = document.getElementById('wifi_status_table');
|
||||
if (ws)
|
||||
{
|
||||
var wsbody = ws.rows[0].parentNode;
|
||||
while (ws.rows.length > 0)
|
||||
wsbody.deleteRow(0);
|
||||
|
||||
for (var didx = 0; didx < info.wifinets.length; didx++)
|
||||
{
|
||||
var dev = info.wifinets[didx];
|
||||
|
||||
var tr = wsbody.insertRow(-1);
|
||||
var td;
|
||||
|
||||
td = tr.insertCell(-1);
|
||||
td.width = "33%";
|
||||
td.innerHTML = dev.name;
|
||||
td.style.verticalAlign = "top";
|
||||
|
||||
td = tr.insertCell(-1);
|
||||
|
||||
var s = '';
|
||||
|
||||
for (var nidx = 0; nidx < dev.networks.length; nidx++)
|
||||
{
|
||||
var net = dev.networks[nidx];
|
||||
var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
|
||||
|
||||
var icon;
|
||||
if (!is_assoc)
|
||||
icon = "<%=resource%>/icons/signal-none.png";
|
||||
else if (net.quality == 0)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (net.quality < 25)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (net.quality < 50)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (net.quality < 75)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
s += String.format(
|
||||
'<table><tr><td style="text-align:center; width:32px; padding:3px">' +
|
||||
'<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
|
||||
'<br /><small>%d%%</small>' +
|
||||
'</td><td style="text-align:left; padding:3px"><small>' +
|
||||
'<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
|
||||
'<strong><%:Mode%>:</strong> %s<br />' +
|
||||
'<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
|
||||
'<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
|
||||
icon, net.signal, net.noise,
|
||||
net.quality,
|
||||
net.link, net.ssid || '?',
|
||||
net.mode,
|
||||
net.channel, net.frequency,
|
||||
net.bitrate || '?'
|
||||
);
|
||||
|
||||
if (is_assoc)
|
||||
{
|
||||
s += String.format(
|
||||
'<strong><%:BSSID%>:</strong> %s<br />' +
|
||||
'<strong><%:Encryption%>:</strong> %s',
|
||||
net.bssid || '?',
|
||||
net.encryption
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += '<em><%:Wireless is disabled or not associated%></em>';
|
||||
}
|
||||
|
||||
s += '</small></td></tr></table>';
|
||||
|
||||
for (var bssid in net.assoclist)
|
||||
{
|
||||
var bss = net.assoclist[bssid];
|
||||
|
||||
bss.bssid = bssid;
|
||||
bss.link = net.link;
|
||||
bss.name = net.name;
|
||||
bss.ifname = net.ifname;
|
||||
bss.radio = dev.name;
|
||||
|
||||
assoclist.push(bss);
|
||||
}
|
||||
}
|
||||
|
||||
if (!s)
|
||||
s = '<em><%:No information available%></em>';
|
||||
|
||||
td.innerHTML = s;
|
||||
}
|
||||
}
|
||||
|
||||
var ac = document.getElementById('wifi_assoc_table');
|
||||
if (ac)
|
||||
{
|
||||
/* clear all rows */
|
||||
while( ac.rows.length > 1 )
|
||||
ac.rows[0].parentNode.deleteRow(1);
|
||||
|
||||
assoclist.sort(function(a, b) {
|
||||
return (a.name == b.name)
|
||||
? (a.bssid < b.bssid)
|
||||
: (a.name > b.name )
|
||||
;
|
||||
});
|
||||
|
||||
for( var i = 0; i < assoclist.length; i++ )
|
||||
{
|
||||
var tr = ac.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
|
||||
|
||||
var icon;
|
||||
var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
|
||||
if (q < 1)
|
||||
icon = "<%=resource%>/icons/signal-0.png";
|
||||
else if (q < 2)
|
||||
icon = "<%=resource%>/icons/signal-0-25.png";
|
||||
else if (q < 3)
|
||||
icon = "<%=resource%>/icons/signal-25-50.png";
|
||||
else if (q < 4)
|
||||
icon = "<%=resource%>/icons/signal-50-75.png";
|
||||
else
|
||||
icon = "<%=resource%>/icons/signal-75-100.png";
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
|
||||
assoclist[i].radio, assoclist[i].ifname
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<a href="%s">%s</a>',
|
||||
assoclist[i].link,
|
||||
'%h'.format(assoclist[i].name).nobr()
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = assoclist[i].bssid;
|
||||
|
||||
var host = hosts[assoclist[i].bssid];
|
||||
if (host)
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
|
||||
((host.name && (host.ipv4 || host.ipv6))
|
||||
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
|
||||
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
|
||||
);
|
||||
else
|
||||
tr.insertCell(-1).innerHTML = '?';
|
||||
|
||||
tr.insertCell(-1).innerHTML = String.format(
|
||||
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
|
||||
assoclist[i].signal, assoclist[i].noise, assoclist[i].signal - assoclist[i].noise,
|
||||
icon,
|
||||
assoclist[i].signal, assoclist[i].noise
|
||||
);
|
||||
|
||||
tr.insertCell(-1).innerHTML = wifirate(assoclist[i], true).nobr() + '<br />' + wifirate(assoclist[i], false).nobr();
|
||||
}
|
||||
|
||||
if (ac.rows.length == 1)
|
||||
{
|
||||
var tr = ac.rows[0].parentNode.insertRow(-1);
|
||||
tr.className = 'cbi-section-table-row';
|
||||
|
||||
var td = tr.insertCell(-1);
|
||||
td.colSpan = 7;
|
||||
td.innerHTML = '<br /><em><%:No information available%></em>';
|
||||
}
|
||||
}
|
||||
<% end %>
|
||||
|
||||
var e;
|
||||
|
||||
if (e = document.getElementById('localtime'))
|
||||
e.innerHTML = info.localtime;
|
||||
|
||||
if (e = document.getElementById('uptime'))
|
||||
e.innerHTML = String.format('%t', info.uptime);
|
||||
|
||||
if (e = document.getElementById('loadavg'))
|
||||
e.innerHTML = String.format(
|
||||
'%.02f, %.02f, %.02f',
|
||||
info.loadavg[0] / 65535.0,
|
||||
info.loadavg[1] / 65535.0,
|
||||
info.loadavg[2] / 65535.0
|
||||
);
|
||||
|
||||
if (e = document.getElementById('memtotal'))
|
||||
e.innerHTML = progressbar(
|
||||
((info.memory.free + info.memory.buffered) / 1024) + " <%:kB%>",
|
||||
(info.memory.total / 1024) + " <%:kB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('memfree'))
|
||||
e.innerHTML = progressbar(
|
||||
(info.memory.free / 1024) + " <%:kB%>",
|
||||
(info.memory.total / 1024) + " <%:kB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('membuff'))
|
||||
e.innerHTML = progressbar(
|
||||
(info.memory.buffered / 1024) + " <%:kB%>",
|
||||
(info.memory.total / 1024) + " <%:kB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('swaptotal'))
|
||||
e.innerHTML = progressbar(
|
||||
(info.swap.free / 1024) + " <%:kB%>",
|
||||
(info.swap.total / 1024) + " <%:kB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('swapfree'))
|
||||
e.innerHTML = progressbar(
|
||||
(info.swap.free / 1024) + " <%:kB%>",
|
||||
(info.swap.total / 1024) + " <%:kB%>"
|
||||
);
|
||||
|
||||
if (e = document.getElementById('conns'))
|
||||
e.innerHTML = progressbar(info.conncount, info.connmax);
|
||||
|
||||
}
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Status%></h2>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:System%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Hostname%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
|
||||
<tr><td width="33%"><%:Model%></td><td><%=pcdata(boardinfo.model or boardinfo.system or "?")%></td></tr>
|
||||
<tr><td width="33%"><%:Firmware Version%></td><td>
|
||||
<%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
|
||||
<%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
|
||||
</td></tr>
|
||||
<tr><td width="33%"><%:Kernel Version%></td><td><%=unameinfo.release or "?"%></td></tr>
|
||||
<tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
|
||||
<tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
|
||||
<tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Memory%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
|
||||
<tr><td width="33%"><%:Free%></td><td id="memfree">-</td></tr>
|
||||
<tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if swapinfo.total > 0 then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Swap%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%"><%:Total Available%></td><td id="swaptotal">-</td></tr>
|
||||
<tr><td width="33%"><%:Free%></td><td id="swapfree">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Network%></legend>
|
||||
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<% if has_ipv6 then %>
|
||||
<tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
<% end %>
|
||||
<tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<% if has_dhcp then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:DHCP Leases%></legend>
|
||||
|
||||
<table class="cbi-section-table" id="lease_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Hostname%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv4-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section" style="display:none">
|
||||
<legend><%:DHCPv6 Leases%></legend>
|
||||
|
||||
<table class="cbi-section-table" id="lease6_status_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Host%></th>
|
||||
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:DUID%></th>
|
||||
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% if has_dsl then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:DSL%></legend>
|
||||
<table width="100%" cellspacing="10">
|
||||
<tr><td width="33%" style="vertical-align:top"><%:DSL Status%></td><td>
|
||||
<table><tr>
|
||||
<td id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
|
||||
<td id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<% if has_wifi then %>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Wireless%></legend>
|
||||
|
||||
<table id="wifi_status_table" width="100%" cellspacing="10">
|
||||
<tr><td><em><%:Collecting data...%></em></td></tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Associated Stations%></legend>
|
||||
|
||||
<table class="cbi-section-table valign-middle" id="wifi_assoc_table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"> </th>
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Host%></th>
|
||||
<th class="cbi-section-table-cell"><%:Signal%> / <%:Noise%></th>
|
||||
<th class="cbi-section-table-cell"><%:RX Rate%> / <%:TX Rate%></th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td colspan="6"><em><br /><%:Collecting data...%></em></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<%-
|
||||
local incdir = util.libpath() .. "/view/admin_status/index/"
|
||||
if fs.access(incdir) then
|
||||
local inc
|
||||
for inc in fs.dir(incdir) do
|
||||
if inc:match("%.htm$") then
|
||||
include("admin_status/index/" .. inc:gsub("%.htm$", ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+footer%>
|
156
luci-mod-admin-full/luasrc/view/admin_status/iptables.htm
Normal file
156
luci-mod-admin-full/luasrc/view/admin_status/iptables.htm
Normal file
|
@ -0,0 +1,156 @@
|
|||
<%#
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
|
||||
require "luci.sys.iptparser"
|
||||
local wba = require "luci.tools.webadmin"
|
||||
local fs = require "nixio.fs"
|
||||
local io = require "io"
|
||||
|
||||
local has_ip6tables = fs.access("/usr/sbin/ip6tables")
|
||||
local mode = 4
|
||||
|
||||
if has_ip6tables then
|
||||
mode = luci.dispatcher.context.requestpath
|
||||
mode = tonumber(mode[#mode] ~= "iptables" and mode[#mode]) or 4
|
||||
end
|
||||
|
||||
local ipt = luci.sys.iptparser.IptParser(mode)
|
||||
|
||||
local rowcnt = 1
|
||||
function rowstyle()
|
||||
rowcnt = rowcnt + 1
|
||||
return (rowcnt % 2) + 1
|
||||
end
|
||||
|
||||
function link_target(t,c)
|
||||
if ipt:is_custom_target(c) then
|
||||
return '<a href="#rule_%s_%s">%s</a>' %{ t:lower(), c, c }
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
function link_iface(i)
|
||||
local net = wba.iface_get_network(i)
|
||||
if net and i ~= "lo" then
|
||||
return '<a href="%s">%s</a>' %{
|
||||
url("admin/network/network", net), i
|
||||
}
|
||||
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
local tables = { "Filter", "NAT", "Mangle", "Raw" }
|
||||
if mode == 6 then
|
||||
tables = { "Filter", "Mangle", "Raw" }
|
||||
local ok, lines = pcall(io.lines, "/proc/net/ip6_tables_names")
|
||||
if ok and lines then
|
||||
local line
|
||||
for line in lines do
|
||||
if line == "nat" then
|
||||
tables = { "Filter", "NAT", "Mangle", "Raw" }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<style type="text/css">
|
||||
span:target {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2 name="content"><%:Firewall Status%></h2>
|
||||
<br />
|
||||
|
||||
<% if has_ip6tables then %>
|
||||
<ul class="cbi-tabmenu">
|
||||
<li class="cbi-tab<%= mode ~= 4 and "-disabled" %>"><a href="<%=url("admin/status/iptables/4")%>"><%:IPv4 Firewall%></a></li>
|
||||
<li class="cbi-tab<%= mode ~= 6 and "-disabled" %>"><a href="<%=url("admin/status/iptables/6")%>"><%:IPv6 Firewall%></a></li>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
<div class="cbi-map" style="position: relative">
|
||||
|
||||
<form method="post" action="<%=url("admin/status/iptables_action")%>" style="position: absolute; right: 0">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="family" value="<%=mode%>" />
|
||||
<input type="submit" class="cbi-button" name="zero" value="<%:Reset Counters%>" />
|
||||
<input type="submit" class="cbi-button" name="restart" value="<%:Restart Firewall%>" />
|
||||
</form>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
|
||||
<% for _, tbl in ipairs(tables) do chaincnt = 0 %>
|
||||
<h3><%:Table%>: <%=tbl%></h3>
|
||||
<table class="cbi-section-table" style="font-size:90%">
|
||||
<% for _, chain in ipairs(ipt:chains(tbl)) do
|
||||
rowcnt = 0
|
||||
chaincnt = chaincnt + 1
|
||||
chaininfo = ipt:chain(tbl, chain)
|
||||
%>
|
||||
<tr class="cbi-section-table-titles cbi-rowstyle-<%=rowstyle()%>">
|
||||
<th class="cbi-section-table-cell" style="text-align:left" colspan="11">
|
||||
<br /><span id="rule_<%=tbl:lower()%>_<%=chain%>">
|
||||
<%:Chain%> <em><%=chain%></em>
|
||||
(<%- if chaininfo.policy then -%>
|
||||
<%:Policy%>: <em><%=chaininfo.policy%></em>, <%:Packets%>: <%=chaininfo.packets%>, <%:Traffic%>: <%=wba.byte_format(chaininfo.bytes)-%>
|
||||
<%- else -%>
|
||||
<%:References%>: <%=chaininfo.references-%>
|
||||
<%- end -%>)</span>
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="cbi-section-table-descr">
|
||||
<th class="cbi-section-table-cell"><%:Pkts.%></th>
|
||||
<th class="cbi-section-table-cell"><%:Traffic%></th>
|
||||
<th class="cbi-section-table-cell"><%:Target%></th>
|
||||
<th class="cbi-section-table-cell"><%:Prot.%></th>
|
||||
<th class="cbi-section-table-cell"><%:In%></th>
|
||||
<th class="cbi-section-table-cell"><%:Out%></th>
|
||||
<th class="cbi-section-table-cell"><%:Source%></th>
|
||||
<th class="cbi-section-table-cell"><%:Destination%></th>
|
||||
<th class="cbi-section-table-cell" style="width:30%"><%:Options%></th>
|
||||
</tr>
|
||||
|
||||
<% for _, rule in ipairs(ipt:find({table=tbl, chain=chain})) do %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=rowstyle()%>">
|
||||
<td><%=rule.packets%></td>
|
||||
<td style="white-space: nowrap"><%=wba.byte_format(rule.bytes)%></td>
|
||||
<td><%=rule.target and link_target(tbl, rule.target) or "-"%></td>
|
||||
<td><%=rule.protocol%></td>
|
||||
<td><%=link_iface(rule.inputif)%></td>
|
||||
<td><%=link_iface(rule.outputif)%></td>
|
||||
<td><%=rule.source%></td>
|
||||
<td><%=rule.destination%></td>
|
||||
<td style="width:30%"><small><%=#rule.options > 0 and luci.util.pcdata(table.concat(rule.options, " ")) or "-"%></small></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
||||
<% if rowcnt == 1 then %>
|
||||
<tr class="cbi-section-table-titles cbi-rowstyle-<%=rowstyle()%>">
|
||||
<td colspan="9"><em><%:No rules in this chain%></em></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% if chaincnt == 0 then %>
|
||||
<tr class="cbi-section-table-titles cbi-rowstyle-<%=rowstyle()%>">
|
||||
<td colspan="9"><em><%:No chains in this table%></em></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<br /><br />
|
||||
<% end %>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
284
luci-mod-admin-full/luasrc/view/admin_status/load.htm
Normal file
284
luci-mod-admin-full/luasrc/view/admin_status/load.htm
Normal file
|
@ -0,0 +1,284 @@
|
|||
<%#
|
||||
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G;
|
||||
var TIME = 0;
|
||||
var L01 = 1;
|
||||
var L05 = 2;
|
||||
var L15 = 3;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 0;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_01 = [ ];
|
||||
var data_05 = [ ];
|
||||
var data_15 = [ ];
|
||||
|
||||
var line_01;
|
||||
var line_05;
|
||||
var line_15;
|
||||
|
||||
var label_25;
|
||||
var label_050;
|
||||
var label_75;
|
||||
|
||||
var label_01_cur;
|
||||
var label_01_avg;
|
||||
var label_01_peak;
|
||||
|
||||
var label_05_cur;
|
||||
var label_05_avg;
|
||||
var label_05_peak;
|
||||
|
||||
var label_15_cur;
|
||||
var label_15_avg;
|
||||
var label_15_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
var svg = document.getElementById('bwsvg');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['bwsvg'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G)
|
||||
{
|
||||
window.setTimeout(arguments.callee, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_wanted; i++)
|
||||
{
|
||||
data_01[i] = 0;
|
||||
data_05[i] = 0;
|
||||
data_15[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_01 = G.getElementById('load01');
|
||||
line_05 = G.getElementById('load05');
|
||||
line_15 = G.getElementById('load15');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
|
||||
label_01_cur = document.getElementById('lb_load01_cur');
|
||||
label_01_avg = document.getElementById('lb_load01_avg');
|
||||
label_01_peak = document.getElementById('lb_load01_peak');
|
||||
|
||||
label_05_cur = document.getElementById('lb_load05_cur');
|
||||
label_05_avg = document.getElementById('lb_load05_avg');
|
||||
label_05_peak = document.getElementById('lb_load05_peak');
|
||||
|
||||
label_15_cur = document.getElementById('lb_load15_cur');
|
||||
label_15_avg = document.getElementById('lb_load15_avg');
|
||||
label_15_peak = document.getElementById('lb_load15_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (step * 60); i < width; i += step * 60)
|
||||
{
|
||||
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#999999; font-size:9pt');
|
||||
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25.parentNode.appendChild(line);
|
||||
label_25.parentNode.appendChild(text);
|
||||
}
|
||||
|
||||
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/load_status")%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
|
||||
var data_01_avg = 0;
|
||||
var data_05_avg = 0;
|
||||
var data_15_avg = 0;
|
||||
|
||||
var data_01_peak = 0;
|
||||
var data_05_peak = 0;
|
||||
var data_15_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_01.push(data[i][L01]);
|
||||
data_05.push(data[i][L05]);
|
||||
data_15.push(data[i][L15]);
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_01 = data_01.slice(data_01.length - data_wanted, data_01.length);
|
||||
data_05 = data_05.slice(data_05.length - data_wanted, data_05.length);
|
||||
data_15 = data_15.slice(data_15.length - data_wanted, data_15.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_01.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_01[i]);
|
||||
data_max = Math.max(data_max, data_05[i]);
|
||||
data_max = Math.max(data_max, data_15[i]);
|
||||
|
||||
data_01_peak = Math.max(data_01_peak, data_01[i]);
|
||||
data_05_peak = Math.max(data_05_peak, data_05[i]);
|
||||
data_15_peak = Math.max(data_15_peak, data_15[i]);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
data_01_avg = (data_01_avg + data_01[i]) / 2;
|
||||
data_05_avg = (data_05_avg + data_05[i]) / 2;
|
||||
data_15_avg = (data_15_avg + data_15[i]) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_01_avg = data_01[i];
|
||||
data_05_avg = data_05[i];
|
||||
data_15_avg = data_15[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = height / (data_max * 1.1);
|
||||
|
||||
|
||||
/* plot data */
|
||||
var pt_01 = '0,' + height;
|
||||
var pt_05 = '0,' + height;
|
||||
var pt_15 = '0,' + height;
|
||||
|
||||
var y_01 = 0;
|
||||
var y_05 = 0;
|
||||
var y_15 = 0;
|
||||
|
||||
for (var i = 0; i < data_01.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_01 = height - Math.floor(data_01[i] * data_scale);
|
||||
y_05 = height - Math.floor(data_05[i] * data_scale);
|
||||
y_15 = height - Math.floor(data_15[i] * data_scale);
|
||||
|
||||
pt_01 += ' ' + x + ',' + y_01;
|
||||
pt_05 += ' ' + x + ',' + y_05;
|
||||
pt_15 += ' ' + x + ',' + y_15;
|
||||
}
|
||||
|
||||
pt_01 += ' ' + width + ',' + y_01 + ' ' + width + ',' + height;
|
||||
pt_05 += ' ' + width + ',' + y_05 + ' ' + width + ',' + height;
|
||||
pt_15 += ' ' + width + ',' + y_15 + ' ' + width + ',' + height;
|
||||
|
||||
|
||||
line_01.setAttribute('points', pt_01);
|
||||
line_05.setAttribute('points', pt_05);
|
||||
line_15.setAttribute('points', pt_15);
|
||||
|
||||
label_25.firstChild.data = (1.1 * 0.25 * data_max / 100).toFixed(2);
|
||||
label_50.firstChild.data = (1.1 * 0.50 * data_max / 100).toFixed(2);
|
||||
label_75.firstChild.data = (1.1 * 0.75 * data_max / 100).toFixed(2);
|
||||
|
||||
label_01_cur.innerHTML = (data_01[data_01.length-1] / 100).toFixed(2);
|
||||
label_05_cur.innerHTML = (data_05[data_05.length-1] / 100).toFixed(2);
|
||||
label_15_cur.innerHTML = (data_15[data_15.length-1] / 100).toFixed(2);
|
||||
|
||||
label_01_avg.innerHTML = (data_01_avg / 100).toFixed(2);
|
||||
label_05_avg.innerHTML = (data_05_avg / 100).toFixed(2);
|
||||
label_15_avg.innerHTML = (data_15_avg / 100).toFixed(2);
|
||||
|
||||
label_01_peak.innerHTML = (data_01_peak / 100).toFixed(2);
|
||||
label_05_peak.innerHTML = (data_05_peak / 100).toFixed(2);
|
||||
label_15_peak.innerHTML = (data_15_peak / 100).toFixed(2);
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Load%></h2>
|
||||
|
||||
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/load.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<table style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ff0000; white-space:nowrap"><%:1 Minute Load:%></strong></td>
|
||||
<td id="lb_load01_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_load01_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_load01_peak">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ff6600; white-space:nowrap"><%:5 Minute Load:%></strong></td>
|
||||
<td id="lb_load05_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_load05_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_load05_peak">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ffaa00; white-space:nowrap"><%:15 Minute Load:%></strong></td>
|
||||
<td id="lb_load15_cur">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="lb_load15_avg">0</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="lb_load15_peak">0</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<%+footer%>
|
162
luci-mod-admin-full/luasrc/view/admin_status/routes.htm
Normal file
162
luci-mod-admin-full/luasrc/view/admin_status/routes.htm
Normal file
|
@ -0,0 +1,162 @@
|
|||
<%#
|
||||
Copyright 2008-2009 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
require "luci.tools.webadmin"
|
||||
require "nixio.fs"
|
||||
|
||||
local ip = require "luci.ip"
|
||||
local style = true
|
||||
local _, v
|
||||
|
||||
local rtn = {
|
||||
[255] = "local",
|
||||
[254] = "main",
|
||||
[253] = "default",
|
||||
[0] = "unspec"
|
||||
}
|
||||
|
||||
if nixio.fs.access("/etc/iproute2/rt_tables") then
|
||||
local ln
|
||||
for ln in io.lines("/etc/iproute2/rt_tables") do
|
||||
local i, n = ln:match("^(%d+)%s+(%S+)")
|
||||
if i and n then
|
||||
rtn[tonumber(i)] = n
|
||||
end
|
||||
end
|
||||
end
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<div class="cbi-map" id="cbi-network">
|
||||
<h2 name="content"><%:Routes%></h2>
|
||||
<div class="cbi-map-descr"><%:The following rules are currently active on this system.%></div>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend>ARP</legend>
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Media Access Control">MAC</abbr>-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
</tr>
|
||||
|
||||
<%
|
||||
for _, v in ipairs(ip.neighbors({ family = 4 })) do
|
||||
if v.mac then
|
||||
%>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=v.dest%></td>
|
||||
<td class="cbi-value-field"><%=v.mac%></td>
|
||||
<td class="cbi-value-field"><%=v.dev%></td>
|
||||
</tr>
|
||||
<%
|
||||
style = not style
|
||||
end
|
||||
end
|
||||
%>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%_Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Routes%></legend>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:Target%></th>
|
||||
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Gateway%></th>
|
||||
<th class="cbi-section-table-cell"><%:Metric%></th>
|
||||
<th class="cbi-section-table-cell"><%:Table%></th>
|
||||
</tr>
|
||||
<% for _, v in ipairs(ip.routes({ family = 4, type = 1 })) do %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=luci.tools.webadmin.iface_get_network(v.dev) or v.dev%></td>
|
||||
<td class="cbi-value-field"><%=v.dest%></td>
|
||||
<td class="cbi-value-field"><%=v.gw%></td>
|
||||
<td class="cbi-value-field"><%=v.metric or 0%></td>
|
||||
<td class="cbi-value-field"><%=rtn[v.table] or v.table%></td>
|
||||
</tr>
|
||||
<% style = not style end %>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<%
|
||||
if nixio.fs.access("/proc/net/ipv6_route") then
|
||||
style = true
|
||||
%>
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%_Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Routes%></legend>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:Network%></th>
|
||||
<th class="cbi-section-table-cell"><%:Target%></th>
|
||||
<th class="cbi-section-table-cell"><%:Source%></th>
|
||||
<th class="cbi-section-table-cell"><%:Metric%></th>
|
||||
<th class="cbi-section-table-cell"><%:Table%></th>
|
||||
</tr>
|
||||
<%
|
||||
for _, v in ipairs(ip.routes({ family = 6, type = 1 })) do
|
||||
if v.dest and not v.dest:is6linklocal() then
|
||||
%>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></td>
|
||||
<td class="cbi-value-field"><%=v.dest%></td>
|
||||
<td class="cbi-value-field"><%=v.from%></td>
|
||||
<td class="cbi-value-field"><%=v.metric or 0%></td>
|
||||
<td class="cbi-value-field"><%=rtn[v.table] or v.table%></td>
|
||||
</tr>
|
||||
<%
|
||||
style = not style
|
||||
end
|
||||
end
|
||||
%>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:IPv6 Neighbours%></legend>
|
||||
|
||||
<div class="cbi-section-node">
|
||||
<table class="cbi-section-table">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:Interface%></th>
|
||||
</tr>
|
||||
<%
|
||||
for _, v in ipairs(ip.neighbors({ family = 6 })) do
|
||||
if v.dest and not v.dest:is6linklocal() and v.mac then
|
||||
%>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
|
||||
<td class="cbi-value-field"><%=v.dest%></td>
|
||||
<td class="cbi-value-field"><%=v.mac%></td>
|
||||
<td class="cbi-value-field"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></td>
|
||||
</tr>
|
||||
<%
|
||||
style = not style
|
||||
end
|
||||
end
|
||||
%>
|
||||
</table>
|
||||
</div>
|
||||
</fieldset>
|
||||
<br />
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
12
luci-mod-admin-full/luasrc/view/admin_status/syslog.htm
Normal file
12
luci-mod-admin-full/luasrc/view/admin_status/syslog.htm
Normal file
|
@ -0,0 +1,12 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
<h2 name="content"><%:System Log%></h2>
|
||||
<div id="content_syslog">
|
||||
<textarea readonly="readonly" wrap="off" rows="<%=syslog:cmatch("\n")+2%>" id="syslog"><%=syslog:pcdata()%></textarea>
|
||||
</div>
|
||||
<%+footer%>
|
370
luci-mod-admin-full/luasrc/view/admin_status/wireless.htm
Normal file
370
luci-mod-admin-full/luasrc/view/admin_status/wireless.htm
Normal file
|
@ -0,0 +1,370 @@
|
|||
<%#
|
||||
Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local ntm = require "luci.model.network".init()
|
||||
|
||||
local dev
|
||||
local devices = { }
|
||||
for _, dev in luci.util.vspairs(luci.sys.net.devices()) do
|
||||
if dev:match("^wlan%d") or dev:match("^ath%d") or dev:match("^wl%d") then
|
||||
devices[#devices+1] = dev
|
||||
end
|
||||
end
|
||||
|
||||
local curdev = luci.http.formvalue("dev") or devices[1]
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var bwxhr = new XHR();
|
||||
|
||||
var G, G2;
|
||||
var TIME = 0;
|
||||
var RATE = 1;
|
||||
var RSSI = 2;
|
||||
var NOISE = 3;
|
||||
|
||||
var width = 760;
|
||||
var height = 300;
|
||||
var step = 5;
|
||||
|
||||
var data_wanted = Math.floor(width / step);
|
||||
var data_fill = 0;
|
||||
var data_stamp = 0;
|
||||
|
||||
var data_rssi = [ ];
|
||||
var data_noise = [ ];
|
||||
var data_rate = [ ];
|
||||
|
||||
var line_rssi;
|
||||
var line_noise;
|
||||
var line_rate;
|
||||
|
||||
var label_25, label_25_2;
|
||||
var label_50, label_50_2;
|
||||
var label_75, label_75_2;
|
||||
|
||||
var label_rssi_cur;
|
||||
var label_rssi_avg;
|
||||
var label_rssi_peak;
|
||||
|
||||
var label_noise_cur;
|
||||
var label_noise_avg;
|
||||
var label_noise_peak;
|
||||
|
||||
var label_rate_cur;
|
||||
var label_rate_avg;
|
||||
var label_rate_peak;
|
||||
|
||||
var label_scale;
|
||||
|
||||
|
||||
/* wait for SVG */
|
||||
window.setTimeout(
|
||||
function() {
|
||||
var svg = document.getElementById('iwsvg');
|
||||
var svg2 = document.getElementById('iwsvg2');
|
||||
|
||||
try {
|
||||
G = svg.getSVGDocument
|
||||
? svg.getSVGDocument() : svg.contentDocument;
|
||||
G2 = svg2.getSVGDocument
|
||||
? svg2.getSVGDocument() : svg2.contentDocument;
|
||||
}
|
||||
catch(e) {
|
||||
G = document.embeds['iwsvg'].getSVGDocument();
|
||||
G2 = document.embeds['iwsvg2'].getSVGDocument();
|
||||
}
|
||||
|
||||
if (!G || !G2)
|
||||
{
|
||||
window.setTimeout(arguments.callee, 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* find sizes */
|
||||
width = svg.offsetWidth - 2;
|
||||
height = svg.offsetHeight - 2;
|
||||
data_wanted = Math.ceil(width / step);
|
||||
|
||||
/* prefill datasets */
|
||||
for (var i = 0; i < data_wanted; i++)
|
||||
{
|
||||
data_rssi[i] = 0;
|
||||
data_noise[i] = 0;
|
||||
data_rate[i] = 0;
|
||||
}
|
||||
|
||||
/* find svg elements */
|
||||
line_rssi = G.getElementById('rssi');
|
||||
line_noise = G.getElementById('noise');
|
||||
line_rate = G2.getElementById('rate');
|
||||
|
||||
label_25 = G.getElementById('label_25');
|
||||
label_50 = G.getElementById('label_50');
|
||||
label_75 = G.getElementById('label_75');
|
||||
label_25_2 = G2.getElementById('label_25');
|
||||
label_50_2 = G2.getElementById('label_50');
|
||||
label_75_2 = G2.getElementById('label_75');
|
||||
|
||||
label_rssi_cur = document.getElementById('rssi_bw_cur');
|
||||
label_rssi_avg = document.getElementById('rssi_bw_avg');
|
||||
label_rssi_peak = document.getElementById('rssi_bw_peak');
|
||||
|
||||
label_noise_cur = document.getElementById('noise_bw_cur');
|
||||
label_noise_avg = document.getElementById('noise_bw_avg');
|
||||
label_noise_peak = document.getElementById('noise_bw_peak');
|
||||
|
||||
label_rate_cur = document.getElementById('rate_bw_cur');
|
||||
label_rate_avg = document.getElementById('rate_bw_avg');
|
||||
label_rate_peak = document.getElementById('rate_bw_peak');
|
||||
|
||||
label_scale = document.getElementById('scale');
|
||||
label_scale_2 = document.getElementById('scale2');
|
||||
|
||||
|
||||
/* plot horizontal time interval lines */
|
||||
for (var i = width % (step * 60); i < width; i += step * 60)
|
||||
{
|
||||
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', i);
|
||||
line.setAttribute('y1', 0);
|
||||
line.setAttribute('x2', i);
|
||||
line.setAttribute('y2', '100%');
|
||||
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text.setAttribute('x', i + 5);
|
||||
text.setAttribute('y', 15);
|
||||
text.setAttribute('style', 'fill:#999999; font-size:9pt');
|
||||
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25.parentNode.appendChild(line);
|
||||
label_25.parentNode.appendChild(text);
|
||||
|
||||
|
||||
var line2 = G2.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line2.setAttribute('x1', i);
|
||||
line2.setAttribute('y1', 0);
|
||||
line2.setAttribute('x2', i);
|
||||
line2.setAttribute('y2', '100%');
|
||||
line2.setAttribute('style', 'stroke:black;stroke-width:0.1');
|
||||
|
||||
var text2 = G2.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||
text2.setAttribute('x', i + 5);
|
||||
text2.setAttribute('y', 15);
|
||||
text2.setAttribute('style', 'fill:#999999; font-size:9pt');
|
||||
text2.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
|
||||
|
||||
label_25_2.parentNode.appendChild(line2);
|
||||
label_25_2.parentNode.appendChild(text2);
|
||||
}
|
||||
|
||||
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
label_scale_2.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
|
||||
|
||||
/* render datasets, start update interval */
|
||||
XHR.poll(3, '<%=build_url("admin/status/realtime/wireless_status", curdev)%>', null,
|
||||
function(x, data)
|
||||
{
|
||||
var noise_floor = 255;
|
||||
var rate_floor = 60000;
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
noise_floor = Math.min(noise_floor, data[i][NOISE]);
|
||||
rate_floor = Math.min(rate_floor, data[i][RATE]);
|
||||
}
|
||||
|
||||
noise_floor -= 5;
|
||||
|
||||
var data_max = 0;
|
||||
var data_scale = 0;
|
||||
var data_max_2 = 0;
|
||||
var data_scale_2 = 0;
|
||||
|
||||
var data_rssi_avg = 0;
|
||||
var data_noise_avg = 0;
|
||||
var data_rate_avg = 0;
|
||||
|
||||
var data_rssi_peak = 0;
|
||||
var data_noise_peak = 0;
|
||||
var data_rate_peak = 0;
|
||||
|
||||
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
|
||||
{
|
||||
/* skip overlapping entries */
|
||||
if (data[i][TIME] <= data_stamp)
|
||||
continue;
|
||||
|
||||
data_rssi.push(data[i][RSSI] - noise_floor);
|
||||
data_noise.push(data[i][NOISE] - noise_floor);
|
||||
data_rate.push(Math.floor(data[i][RATE] / 1000));
|
||||
}
|
||||
|
||||
/* cut off outdated entries */
|
||||
data_rssi = data_rssi.slice(data_rssi.length - data_wanted, data_rssi.length);
|
||||
data_noise = data_noise.slice(data_noise.length - data_wanted, data_noise.length);
|
||||
data_rate = data_rate.slice(data_rate.length - data_wanted, data_rate.length);
|
||||
|
||||
/* find peak */
|
||||
for (var i = 0; i < data_rssi.length; i++)
|
||||
{
|
||||
data_max = Math.max(data_max, data_rssi[i]);
|
||||
data_max_2 = Math.max(data_max_2, data_rate[i]);
|
||||
|
||||
data_rssi_peak = Math.max(data_rssi_peak, data_rssi[i]);
|
||||
data_noise_peak = Math.max(data_noise_peak, data_noise[i]);
|
||||
data_rate_peak = Math.max(data_rate_peak, data_rate[i]);
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
data_rssi_avg = (data_rssi_avg + data_rssi[i]) / 2;
|
||||
data_noise_avg = (data_noise_avg + data_noise[i]) / 2;
|
||||
data_rate_avg = (data_rate_avg + data_rate[i]) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
data_rssi_avg = data_rssi[i];
|
||||
data_noise_avg = data_noise[i];
|
||||
data_rate_avg = data_rate[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* remember current timestamp, calculate horizontal scale */
|
||||
data_stamp = data[data.length-1][TIME];
|
||||
data_scale = (height / (data_max * 1.1)).toFixed(1);
|
||||
data_scale_2 = (height / (data_max_2 * 1.1)).toFixed(1);
|
||||
|
||||
/* plot data */
|
||||
var pt_rssi = '0,' + height;
|
||||
var pt_noise = '0,' + height;
|
||||
var pt_rate = '0,' + height;
|
||||
|
||||
var y_rssi = 0;
|
||||
var y_noise = 0;
|
||||
var y_rate = 0;
|
||||
|
||||
for (var i = 0; i < data_rssi.length; i++)
|
||||
{
|
||||
var x = i * step;
|
||||
|
||||
y_rssi = height - Math.floor(data_rssi[i] * data_scale);
|
||||
y_noise = height - Math.floor(data_noise[i] * data_scale);
|
||||
y_rate = height - Math.floor(data_rate[i] * data_scale_2);
|
||||
|
||||
y_rssi -= Math.floor(y_rssi % (1/data_scale));
|
||||
y_noise -= Math.floor(y_noise % (1/data_scale));
|
||||
|
||||
pt_rssi += ' ' + x + ',' + y_rssi;
|
||||
pt_noise += ' ' + x + ',' + y_noise;
|
||||
pt_rate += ' ' + x + ',' + y_rate;
|
||||
}
|
||||
|
||||
pt_rssi += ' ' + width + ',' + y_rssi + ' ' + width + ',' + height;
|
||||
pt_noise += ' ' + width + ',' + y_noise + ' ' + width + ',' + height;
|
||||
pt_rate += ' ' + width + ',' + y_rate + ' ' + width + ',' + height;
|
||||
|
||||
line_rssi.setAttribute('points', pt_rssi);
|
||||
line_noise.setAttribute('points', pt_noise);
|
||||
line_rate.setAttribute('points', pt_rate);
|
||||
|
||||
function wireless_label(dbm, noise)
|
||||
{
|
||||
if (noise)
|
||||
return String.format("%d <%:dBm%> (SNR %d <%:dBm%>)", noise_floor + dbm - 255, dbm - noise);
|
||||
else
|
||||
return String.format("%d <%:dBm%>", noise_floor + dbm - 255);
|
||||
}
|
||||
|
||||
function rate_label(mbit)
|
||||
{
|
||||
return String.format("%d <%:Mbit/s%>", mbit);
|
||||
}
|
||||
|
||||
label_25.firstChild.data = wireless_label(1.1 * 0.25 * data_max);
|
||||
label_50.firstChild.data = wireless_label(1.1 * 0.50 * data_max);
|
||||
label_75.firstChild.data = wireless_label(1.1 * 0.75 * data_max);
|
||||
|
||||
label_25_2.firstChild.data = rate_label(1.1 * 0.25 * data_max_2);
|
||||
label_50_2.firstChild.data = rate_label(1.1 * 0.50 * data_max_2);
|
||||
label_75_2.firstChild.data = rate_label(1.1 * 0.75 * data_max_2);
|
||||
|
||||
label_rssi_cur.innerHTML = wireless_label(data_rssi[data_rssi.length-1], data_noise[data_noise.length-1]).nobr();
|
||||
label_noise_cur.innerHTML = wireless_label(data_noise[data_noise.length-1]).nobr();
|
||||
|
||||
label_rssi_avg.innerHTML = wireless_label(data_rssi_avg, data_noise_avg).nobr();
|
||||
label_noise_avg.innerHTML = wireless_label(data_noise_avg).nobr();
|
||||
|
||||
label_rssi_peak.innerHTML = wireless_label(data_rssi_peak, data_noise_peak).nobr();
|
||||
label_noise_peak.innerHTML = wireless_label(data_noise_peak).nobr();
|
||||
|
||||
label_rate_cur.innerHTML = rate_label(data_rate[data_rate.length-1]);
|
||||
label_rate_avg.innerHTML = rate_label(data_rate_avg);
|
||||
label_rate_peak.innerHTML = rate_label(data_rate_peak);
|
||||
}
|
||||
);
|
||||
}
|
||||
}, 1000
|
||||
);
|
||||
//]]></script>
|
||||
|
||||
<h2 name="content"><%:Realtime Wireless%></h2>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<% for _, dev in ipairs(devices) do %>
|
||||
<li class="cbi-tab<%= dev == curdev and "" or "-disabled" %>"><a href="?dev=<%=pcdata(dev)%>"><%=pcdata(dev)%></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<embed id="iwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/wireless.svg" />
|
||||
<div style="text-align:right"><small id="scale">-</small></div>
|
||||
<br />
|
||||
|
||||
<table style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:Signal:%></strong></td>
|
||||
<td id="rssi_bw_cur">0 <%:dBm%></td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="rssi_bw_avg">0 <%:dBm%></td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="rssi_bw_peak">0 <%:dBm%></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid red"><%:Noise:%></strong></td>
|
||||
<td id="noise_bw_cur">0 <%:dBm%></td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="noise_bw_avg">0 <%:dBm%></td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="noise_bw_peak">0 <%:dBm%></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br />
|
||||
|
||||
<embed id="iwsvg2" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/wifirate.svg" />
|
||||
<div style="text-align:right"><small id="scale2">-</small></div>
|
||||
<br />
|
||||
|
||||
<table style="width:100%; table-layout:fixed" cellspacing="5">
|
||||
<tr>
|
||||
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:Phy Rate:%></strong></td>
|
||||
<td id="rate_bw_cur">0 MBit/s</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
|
||||
<td id="rate_bw_avg">0 MBit/s</td>
|
||||
|
||||
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
|
||||
<td id="rate_bw_peak">0 MBit/s</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<%+footer%>
|
41
luci-mod-admin-full/luasrc/view/admin_system/applyreboot.htm
Normal file
41
luci-mod-admin-full/luasrc/view/admin_system/applyreboot.htm
Normal file
|
@ -0,0 +1,41 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title><%=luci.sys.hostname()%> - <% if title then %><%=title%><% else %><%:Rebooting...%><% end %></title>
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
|
||||
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var interval = window.setInterval(function() {
|
||||
var img = new Image();
|
||||
|
||||
img.onload = function() {
|
||||
window.clearInterval(interval);
|
||||
location.href = ('https:' == document.location.protocol ? 'https://' : 'http://') + '<%=addr or luci.http.getenv("SERVER_NAME")%>/';
|
||||
};
|
||||
|
||||
img.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + '<%=addr or luci.http.getenv("SERVER_NAME")%><%=resource%>/icons/loading.gif?' + Math.random();
|
||||
}, 5000);
|
||||
//]]></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="maincontainer">
|
||||
<div id="maincontent">
|
||||
<h2 name="content"><%:System%> - <% if title then %><%=title%><% else %><%:Rebooting...%><% end %></h2>
|
||||
<fieldset class="cbi-section">
|
||||
<p>
|
||||
<% if msg then %><%=msg%><% else %><%:Changes applied.%><% end %>
|
||||
</p>
|
||||
<p>
|
||||
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
|
||||
<%:Waiting for changes to be applied...%>
|
||||
</p>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
10
luci-mod-admin-full/luasrc/view/admin_system/backupfiles.htm
Normal file
10
luci-mod-admin-full/luasrc/view/admin_system/backupfiles.htm
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<li class="cbi-tab-disabled"><a href="<%=url("admin/system/flashops")%>"><%:Actions%></a></li>
|
||||
<li class="cbi-tab"><a href="#"><%:Configuration%></a></li>
|
||||
</ul>
|
|
@ -0,0 +1,36 @@
|
|||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
XHR.poll(5, '<%=url('admin/system/clock_status')%>', null,
|
||||
function(x, rv)
|
||||
{
|
||||
var s = document.getElementById('<%=self.option%>-clock-status');
|
||||
if (s)
|
||||
{
|
||||
s.innerHTML = rv.timestring || '?';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
function sync_clock(btn)
|
||||
{
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Synchronizing...%>';
|
||||
|
||||
(new XHR()).post('<%=url('admin/system/clock_status')%>',
|
||||
{ token: '<%=token%>', set: Math.floor((new Date()).getTime() / 1000) },
|
||||
function()
|
||||
{
|
||||
btn.disabled = false;
|
||||
btn.value = '<%:Sync with browser%>';
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
<span id="<%=self.option%>-clock-status"><em><%:Collecting data...%></em></span>
|
||||
<input type="button" class="cbi-button cbi-button-apply" value="<%:Sync with browser%>" onclick="return sync_clock(this)" />
|
||||
|
||||
<%+cbi/valuefooter%>
|
93
luci-mod-admin-full/luasrc/view/admin_system/flashops.htm
Normal file
93
luci-mod-admin-full/luasrc/view/admin_system/flashops.htm
Normal file
|
@ -0,0 +1,93 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Flash operations%></h2>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<li class="cbi-tab"><a href="#"><%:Actions%></a></li>
|
||||
<li class="cbi-tab-disabled"><a href="<%=REQUEST_URI%>/backupfiles"><%:Configuration%></a></li>
|
||||
</ul>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Backup / Restore%></legend>
|
||||
<div class="cbi-section-descr"><%:Click "Generate archive" to download a tar archive of the current configuration files. To reset the firmware to its initial state, click "Perform reset" (only possible with squashfs images).%></div>
|
||||
<div class="cbi-section-node">
|
||||
<form class="inline" method="post" action="<%=url('admin/system/flashops/backup')%>">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<div class="cbi-value<% if not reset_avail then %> cbi-value-last<% end %>">
|
||||
<label class="cbi-value-title" for="image"><%:Download backup%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input class="cbi-button cbi-button-apply" type="submit" name="backup" value="<%:Generate archive%>" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<% if reset_avail then %>
|
||||
<form class="inline" method="post" action="<%=url('admin/system/flashops/reset')%>">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<div class="cbi-value cbi-value-last">
|
||||
<label class="cbi-value-title"><%:Reset to defaults%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input onclick="return confirm('<%:Really reset all changes?%>')" class="cbi-button cbi-button-reset" type="submit" name="reset" value="<%:Perform reset%>" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<% end %>
|
||||
</div>
|
||||
<br />
|
||||
<div class="cbi-section-descr"><%:To restore configuration files, you can upload a previously generated backup archive here.%></div>
|
||||
<div class="cbi-section-node">
|
||||
<form class="inline" method="post" action="<%=url('admin/system/flashops/restore')%>" enctype="multipart/form-data">
|
||||
<div class="cbi-value cbi-value-last">
|
||||
<label class="cbi-value-title" for="archive"><%:Restore backup%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="file" name="archive" id="archive" />
|
||||
<input type="submit" class="cbi-button cbi-input-apply" name="restore" value="<%:Upload archive...%>" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<br />
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<legend><%:Flash new firmware image%></legend>
|
||||
<% if upgrade_avail then %>
|
||||
<form method="post" action="<%=url('admin/system/flashops/sysupgrade')%>" enctype="multipart/form-data">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<div class="cbi-section-descr"><%:Upload a sysupgrade-compatible image here to replace the running firmware. Check "Keep settings" to retain the current configuration (requires a compatible firmware image).%></div>
|
||||
<div class="cbi-section-node">
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title" for="keep"><%:Keep settings%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="checkbox" name="keep" id="keep" checked="checked" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cbi-value cbi-value-last<% if image_invalid then %> cbi-value-error<% end %>">
|
||||
<label class="cbi-value-title" for="image"><%:Image%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="file" name="image" id="image" />
|
||||
<input type="submit" class="cbi-button cbi-input-apply" value="<%:Flash image...%>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% if image_invalid then %>
|
||||
<div class="cbi-section-error"><%:The uploaded image file does not contain a supported format. Make sure that you choose the generic image format for your platform. %></div>
|
||||
<% end %>
|
||||
</form>
|
||||
<% else %>
|
||||
<div class="cbi-section-descr"><%:Sorry, there is no sysupgrade support present; a new firmware image must be flashed manually. Please refer to the wiki for device specific install instructions.%></div>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<%+footer%>
|
10
luci-mod-admin-full/luasrc/view/admin_system/ipkg.htm
Normal file
10
luci-mod-admin-full/luasrc/view/admin_system/ipkg.htm
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<li class="cbi-tab-disabled"><a href="<%=url("admin/system/packages")%>"><%:Actions%></a></li>
|
||||
<li class="cbi-tab"><a href="#"><%:Configuration%></a></li>
|
||||
</ul>
|
212
luci-mod-admin-full/luasrc/view/admin_system/packages.htm
Normal file
212
luci-mod-admin-full/luasrc/view/admin_system/packages.htm
Normal file
|
@ -0,0 +1,212 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%-
|
||||
local opkg = require "luci.model.ipkg"
|
||||
local fs = require "nixio.fs"
|
||||
local wa = require "luci.tools.webadmin"
|
||||
local rowcnt = 1
|
||||
|
||||
function rowstyle()
|
||||
rowcnt = rowcnt + 1
|
||||
return (rowcnt % 2) + 1
|
||||
end
|
||||
|
||||
local fstat = fs.statvfs(opkg.overlay_root())
|
||||
local space_total = fstat and fstat.blocks or 0
|
||||
local space_free = fstat and fstat.bfree or 0
|
||||
local space_used = space_total - space_free
|
||||
|
||||
local used_perc = math.floor(0.5 + ((space_total > 0) and ((100 / space_total) * space_used) or 100))
|
||||
local free_byte = space_free * fstat.frsize
|
||||
|
||||
local filter = { }
|
||||
|
||||
|
||||
local opkg_list = luci.model.ipkg.list_all
|
||||
local querypat
|
||||
if query and #query > 0 then
|
||||
querypat = '*%s*' % query
|
||||
opkg_list = luci.model.ipkg.find
|
||||
end
|
||||
|
||||
local letterpat
|
||||
if letter == 35 then
|
||||
letterpat = "[^a-z]*"
|
||||
else
|
||||
letterpat = string.char(letter, 42) -- 'A' '*'
|
||||
end
|
||||
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Software%></h2>
|
||||
|
||||
<div class="cbi-map">
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<li class="cbi-tab"><a href="#"><%:Actions%></a></li>
|
||||
<li class="cbi-tab-disabled"><a href="<%=REQUEST_URI%>/ipkg"><%:Configuration%></a></li>
|
||||
</ul>
|
||||
|
||||
<form method="post" action="<%=REQUEST_URI%>">
|
||||
<input type="hidden" name="exec" value="1" />
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<fieldset class="cbi-section-node">
|
||||
<% if (install and next(install)) or (remove and next(remove)) or update or upgrade then %>
|
||||
<div class="cbi-value">
|
||||
<% if #stdout > 0 then %><pre><%=pcdata(stdout)%></pre><% end %>
|
||||
<% if #stderr > 0 then %><pre class="error"><%=pcdata(stderr)%></pre><% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if querypat then %>
|
||||
<div class="cbi-value">
|
||||
<%:Displaying only packages containing%> <strong>"<%=pcdata(query)%>"</strong>
|
||||
<input type="button" onclick="location.href='?display=<%=pcdata(display)%>'" href="#" class="cbi-button cbi-button-reset" style="margin-left:1em" value="<%:Reset%>" />
|
||||
<br style="clear:both" />
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if no_lists or old_lists then %>
|
||||
<div class="cbi-value">
|
||||
<% if old_lists then %>
|
||||
<%:Package lists are older than 24 hours%>
|
||||
<% else %>
|
||||
<%:No package lists available%>
|
||||
<% end %>
|
||||
<input type="submit" name="update" href="#" class="cbi-button cbi-button-apply" style="margin-left:3em" value="<%:Update lists%>" />
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="cbi-value cbi-value-last">
|
||||
<%:Free space%>: <strong><%=(100-used_perc)%>%</strong> (<strong><%=wa.byte_format(free_byte)%></strong>)
|
||||
<div style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080">
|
||||
<div style="background-color:#F08080; border-right:1px solid #000000; height:100%; width:<%=used_perc%>%"> </div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<br />
|
||||
|
||||
<fieldset class="cbi-section-node">
|
||||
<input type="hidden" name="display" value="<%=pcdata(display)%>" />
|
||||
|
||||
<div class="cbi-value">
|
||||
<label class="cbi-value-title"><%:Download and install package%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="text" name="url" size="30" value="" />
|
||||
<input class="cbi-button cbi-input-save" type="submit" name="go" value="<%:OK%>" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cbi-value cbi-value-last">
|
||||
<label class="cbi-value-title"><%:Filter%>:</label>
|
||||
<div class="cbi-value-field">
|
||||
<input type="text" name="query" size="20" value="<%=pcdata(query)%>" />
|
||||
<input type="submit" class="cbi-button cbi-input-find" name="search" value="<%:Find package%>" />
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
|
||||
<h3><%:Status%></h3>
|
||||
|
||||
|
||||
<ul class="cbi-tabmenu">
|
||||
<li class="cbi-tab<% if display ~= "installed" then %>-disabled<% end %>"><a href="?display=installed&query=<%=pcdata(query)%>"><%:Installed packages%><% if query then %> (<%=pcdata(query)%>)<% end %></a></li>
|
||||
<li class="cbi-tab<% if display ~= "available" then %>-disabled<% end %>"><a href="?display=available&query=<%=pcdata(query)%>"><%:Available packages%><% if query then %> (<%=pcdata(query)%>)<% end %></a></li>
|
||||
</ul>
|
||||
|
||||
<% if display ~= "available" then %>
|
||||
<fieldset class="cbi-section">
|
||||
<table class="cbi-section-table" style="width:100%">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell" style="text-align:left"> </th>
|
||||
<th class="cbi-section-table-cell" style="text-align:left"><%:Package name%></th>
|
||||
<th class="cbi-section-table-cell" style="text-align:left"><%:Version%></th>
|
||||
</tr>
|
||||
<% local empty = true; luci.model.ipkg.list_installed(querypat, function(n, v, s, d) empty = false; filter[n] = true %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=rowstyle()%>">
|
||||
<td style="text-align:left; width:10%">
|
||||
<form method="post" class="inline" action="<%=REQUEST_URI%>">
|
||||
<input type="hidden" name="exec" value="1" />
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="remove" value="<%=pcdata(n)%>" />
|
||||
<a onclick="window.confirm('<%:Remove%> "<%=luci.util.pcdata(n)%>" ?') && this.parentNode.submit(); return false" href="#"><%:Remove%></a>
|
||||
</form>
|
||||
</td>
|
||||
<td style="text-align:left"><%=luci.util.pcdata(n)%></td>
|
||||
<td style="text-align:left"><%=luci.util.pcdata(v)%></td>
|
||||
</tr>
|
||||
<% end) %>
|
||||
<% if empty then %>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td style="text-align:left"> </td>
|
||||
<td style="text-align:left"><em><%:none%></em></td>
|
||||
<td style="text-align:left"><em><%:none%></em></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
</fieldset>
|
||||
<% else %>
|
||||
<fieldset class="cbi-section">
|
||||
<% if not querypat then %>
|
||||
<ul class="cbi-tabmenu">
|
||||
<% local i; for i = 65, 90 do %>
|
||||
<li class="cbi-tab<% if letter ~= i then %>-disabled<% end %>"><a href="?display=available&letter=<%=string.char(i)%>"><%=string.char(i)%></a></li>
|
||||
<% end %>
|
||||
<li class="cbi-tab<% if letter ~= 35 then %>-disabled<% end %>"><a href="?display=available&letter=%23">#</a></li>
|
||||
</ul>
|
||||
<div class="cbi-section-node">
|
||||
<% end %>
|
||||
<table class="cbi-section-table" style="width:100%">
|
||||
<tr class="cbi-section-table-titles">
|
||||
<th class="cbi-section-table-cell" style="text-align:left"> </th>
|
||||
<th class="cbi-section-table-cell" style="text-align:left"><%:Package name%></th>
|
||||
<th class="cbi-section-table-cell" style="text-align:left"><%:Version%></th>
|
||||
<th class="cbi-section-table-cell" style="text-align:right"><%:Size (.ipk)%></th>
|
||||
<th class="cbi-section-table-cell" style="text-align:left"><%:Description%></th>
|
||||
</tr>
|
||||
<% local empty = true; opkg_list(querypat or letterpat, function(n, v, s, d) if filter[n] then return end; empty = false %>
|
||||
<tr class="cbi-section-table-row cbi-rowstyle-<%=rowstyle()%>">
|
||||
<td style="text-align:left; width:10%">
|
||||
<form method="post" class="inline" action="<%=REQUEST_URI%>">
|
||||
<input type="hidden" name="exec" value="1" />
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="install" value="<%=pcdata(n)%>" />
|
||||
<a onclick="window.confirm('<%:Install%> "<%=luci.util.pcdata(n)%>" ?') && this.parentNode.submit(); return false" href="#"><%:Install%></a>
|
||||
</form>
|
||||
</td>
|
||||
<td style="text-align:left"><%=luci.util.pcdata(n)%></td>
|
||||
<td style="text-align:left"><%=luci.util.pcdata(v)%></td>
|
||||
<td style="text-align:right"><%=luci.util.pcdata(s)%></td>
|
||||
<td style="text-align:left"><%=luci.util.pcdata(d)%></td>
|
||||
</tr>
|
||||
<% end) %>
|
||||
<% if empty then %>
|
||||
<tr class="cbi-section-table-row">
|
||||
<td style="text-align:left"> </td>
|
||||
<td style="text-align:left"><em><%:none%></em></td>
|
||||
<td style="text-align:left"><em><%:none%></em></td>
|
||||
<td style="text-align:right"><em><%:none%></em></td>
|
||||
<td style="text-align:left"><em><%:none%></em></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<% if not querypat then %>
|
||||
</div>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
59
luci-mod-admin-full/luasrc/view/admin_system/reboot.htm
Normal file
59
luci-mod-admin-full/luasrc/view/admin_system/reboot.htm
Normal file
|
@ -0,0 +1,59 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Reboot%></h2>
|
||||
<br />
|
||||
|
||||
<p><%:Reboots the operating system of your device%></p>
|
||||
|
||||
<%- local c = require("luci.model.uci").cursor():changes(); if c and next(c) then -%>
|
||||
<p class="alert-message warning"><%:Warning: There are unsaved changes that will get lost on reboot!%></p>
|
||||
<%- end -%>
|
||||
|
||||
<hr />
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var tries = 0;
|
||||
|
||||
function ok() {
|
||||
window.location = '<%=controller%>/admin';
|
||||
}
|
||||
|
||||
function check() {
|
||||
if (tries++ < 12)
|
||||
window.setTimeout(ping, 5000);
|
||||
else
|
||||
alert('<%:Device unreachable%>');
|
||||
}
|
||||
|
||||
function ping() {
|
||||
var img = document.createElement('img');
|
||||
|
||||
img.onload = ok;
|
||||
img.onerror = check;
|
||||
img.src = '<%=resource%>/icons/loading.gif?' + Math.random();
|
||||
|
||||
document.getElementById('reboot-message').innerHTML = '<%:Waiting for device...%>';
|
||||
}
|
||||
|
||||
function reboot(button) {
|
||||
button.style.display = 'none';
|
||||
document.getElementById('reboot-message').parentNode.style.display = '';
|
||||
|
||||
(new XHR()).post('<%=controller%>/admin/system/reboot/call', { token: '<%=token%>' }, check);
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
<input class="cbi-button cbi-button-apply" type="button" value="<%:Perform reboot%>" onclick="reboot(this)" />
|
||||
|
||||
<p class="alert-message" style="display:none">
|
||||
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
|
||||
<span id="reboot-message"><%:Device is rebooting...%></span>
|
||||
</p>
|
||||
|
||||
<%+footer%>
|
59
luci-mod-admin-full/luasrc/view/admin_system/upgrade.htm
Normal file
59
luci-mod-admin-full/luasrc/view/admin_system/upgrade.htm
Normal file
|
@ -0,0 +1,59 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2009 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Flash Firmware%> - <%:Verify%></h2>
|
||||
<p>
|
||||
<%_ The flash image was uploaded.
|
||||
Below is the checksum and file size listed,
|
||||
compare them with the original file to ensure data integrity.<br />
|
||||
Click "Proceed" below to start the flash procedure. %>
|
||||
|
||||
<% if storage > 0 and size > storage then %>
|
||||
<br /><br />
|
||||
<div class="error"><%:It appears that you are trying to
|
||||
flash an image that does not fit into the flash memory, please verify
|
||||
the image file! %></div>
|
||||
<% end %>
|
||||
|
||||
</p>
|
||||
|
||||
<fieldset class="cbi-section">
|
||||
<ul>
|
||||
<li><%:Checksum%><br />
|
||||
<%:MD5%>: <code><%=checksum%></code><br />
|
||||
<%:SHA256%>: <code><%=sha256ch%></code></li>
|
||||
<li><%:Size%>: <%
|
||||
local w = require "luci.tools.webadmin"
|
||||
write(w.byte_format(size))
|
||||
|
||||
if storage > 0 then
|
||||
write(luci.i18n.translatef(
|
||||
" (%s available)",
|
||||
w.byte_format(storage)
|
||||
))
|
||||
end
|
||||
%></li>
|
||||
<li><% if keep then %>
|
||||
<%:Configuration files will be kept.%>
|
||||
<% else %>
|
||||
<%:Note: Configuration files will be erased.%>
|
||||
<% end %></li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
||||
<div class="cbi-page-actions right">
|
||||
<form class="inline" action="<%=REQUEST_URI%>" method="post">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="step" value="2" />
|
||||
<input type="hidden" name="keep" value="<%=keep and "1" or ""%>" />
|
||||
<input class="cbi-button cbi-button-reset" name="cancel" type="submit" value="<%:Cancel%>" />
|
||||
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
23
luci-mod-admin-full/luasrc/view/admin_uci/apply.htm
Normal file
23
luci-mod-admin-full/luasrc/view/admin_uci/apply.htm
Normal file
|
@ -0,0 +1,23 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Configuration%> / <%:Apply%></h2>
|
||||
|
||||
<% if changes then %>
|
||||
<%+cbi/apply_xhr%>
|
||||
<%+admin_uci/changelog%>
|
||||
|
||||
<%- cbi_apply_xhr('uci-apply', configs) -%>
|
||||
|
||||
<p><strong><%:The following changes have been committed%>:</strong></p>
|
||||
<%- uci_changelog(changes) -%>
|
||||
<% else %>
|
||||
<p><strong><%:There are no pending changes to apply!%></strong></p>
|
||||
<% end %>
|
||||
|
||||
<%+footer%>
|
79
luci-mod-admin-full/luasrc/view/admin_uci/changelog.htm
Normal file
79
luci-mod-admin-full/luasrc/view/admin_uci/changelog.htm
Normal file
|
@ -0,0 +1,79 @@
|
|||
<%#
|
||||
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<% export("uci_changelog", function(changes) -%>
|
||||
<fieldset class="cbi-section">
|
||||
<strong><%:Legend:%></strong>
|
||||
<div class="uci-change-legend">
|
||||
<div class="uci-change-legend-label"><ins> </ins> <%:Section added%></div>
|
||||
<div class="uci-change-legend-label"><del> </del> <%:Section removed%></div>
|
||||
<div class="uci-change-legend-label"><var><ins> </ins></var> <%:Option changed%></div>
|
||||
<div class="uci-change-legend-label"><var><del> </del></var> <%:Option removed%></div>
|
||||
<br style="clear:both" />
|
||||
</div>
|
||||
<br />
|
||||
|
||||
<div class="uci-change-list"><%
|
||||
local util = luci.util
|
||||
local ret = { }
|
||||
|
||||
for r, tbl in pairs(changes) do
|
||||
for s, os in pairs(tbl) do
|
||||
-- section add
|
||||
if os['.type'] and os['.type'] ~= "" then
|
||||
ret[#ret+1] = "<ins>%s.%s=<strong>%s</strong>" %{ r, s, os['.type'] }
|
||||
for o, v in util.kspairs(os) do
|
||||
if o:sub(1,1) ~= "." then
|
||||
if type(v) == "table" then
|
||||
local i
|
||||
for i = 1, #v do
|
||||
ret[#ret+1] = "<br />%s.%s.%s+=<strong>%s</strong>"
|
||||
%{ r, s, o, util.pcdata(v[i]) }
|
||||
end
|
||||
else
|
||||
ret[#ret+1] = "<br />%s.%s.%s=<strong>%s</strong>"
|
||||
%{ r, s, o, util.pcdata(v) }
|
||||
end
|
||||
end
|
||||
end
|
||||
ret[#ret+1] = "</ins><br />"
|
||||
|
||||
-- section delete
|
||||
elseif os['.type'] and os['.type'] == "" then
|
||||
ret[#ret+1] = "<del>%s.<strong>%s</strong></del><br />" %{ r, s }
|
||||
|
||||
-- modifications
|
||||
else
|
||||
ret[#ret+1] = "<var>%s.%s<br />" %{ r, s }
|
||||
for o, v in util.kspairs(os) do
|
||||
if o:sub(1,1) ~= "." then
|
||||
if v and #v > 0 then
|
||||
ret[#ret+1] = "<ins>"
|
||||
if type(v) == "table" then
|
||||
local i
|
||||
for i = 1, #v do
|
||||
ret[#ret+1] = "%s.%s.%s+=<strong>%s</strong><br />"
|
||||
%{ r, s, o, util.pcdata(v[i]) }
|
||||
end
|
||||
|
||||
else
|
||||
ret[#ret+1] = "%s.%s.%s=<strong>%s</strong><br />"
|
||||
%{ r, s, o, util.pcdata(v) }
|
||||
end
|
||||
ret[#ret+1] = "</ins>"
|
||||
else
|
||||
ret[#ret+1] = "<del>%s.%s.<strong>%s</strong><br /></del>" %{ r, s, o }
|
||||
end
|
||||
end
|
||||
end
|
||||
ret[#ret+1] = "</var><br />"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
write(table.concat(ret))
|
||||
%></div>
|
||||
</fieldset>
|
||||
<%- end) %>
|
46
luci-mod-admin-full/luasrc/view/admin_uci/changes.htm
Normal file
46
luci-mod-admin-full/luasrc/view/admin_uci/changes.htm
Normal file
|
@ -0,0 +1,46 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Configuration%> / <%:Changes%></h2>
|
||||
|
||||
<% if changes then %>
|
||||
<%+admin_uci/changelog%>
|
||||
<%- uci_changelog(changes) -%>
|
||||
<% else %>
|
||||
<p><strong><%:There are no pending changes!%></strong></p>
|
||||
<% end %>
|
||||
|
||||
<div class="cbi-page-actions">
|
||||
<% local r = luci.http.formvalue("redir"); if r and #r > 0 then %>
|
||||
<div style="float:left">
|
||||
<form class="inline" method="get" action="<%=luci.util.pcdata(r)%>">
|
||||
<input class="cbi-button cbi-button-link" style="float:left; margin:0" type="submit" value="<%:Back%>" />
|
||||
</form>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div style="text-align:right">
|
||||
<form class="inline" method="post" action="<%=controller%>/admin/uci/apply">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
|
||||
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Apply%>" />
|
||||
</form>
|
||||
<form class="inline" method="post" action="<%=controller%>/admin/uci/saveapply">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
|
||||
<input class="cbi-button cbi-button-save" type="submit" value="<%:Save & Apply%>" />
|
||||
</form>
|
||||
<form class="inline" method="post" action="<%=controller%>/admin/uci/revert">
|
||||
<input type="hidden" name="token" value="<%=token%>" />
|
||||
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
|
||||
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Revert%>" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
27
luci-mod-admin-full/luasrc/view/admin_uci/revert.htm
Normal file
27
luci-mod-admin-full/luasrc/view/admin_uci/revert.htm
Normal file
|
@ -0,0 +1,27 @@
|
|||
<%#
|
||||
Copyright 2008 Steven Barth <steven@midlink.org>
|
||||
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
|
||||
Licensed to the public under the Apache License 2.0.
|
||||
-%>
|
||||
|
||||
<%+header%>
|
||||
|
||||
<h2 name="content"><%:Configuration%> / <%:Revert%></h2>
|
||||
|
||||
<% if changes then %>
|
||||
<%+cbi/apply_xhr%>
|
||||
<%+admin_uci/changelog%>
|
||||
|
||||
<p><strong><%:The following changes have been reverted%>:</strong></p>
|
||||
<%- uci_changelog(changes) -%>
|
||||
<% else %>
|
||||
<p><strong><%:There are no pending changes to revert!%></strong></p>
|
||||
<% end %>
|
||||
|
||||
<div class="cbi-page-actions">
|
||||
<form class="inline" method="get" action="<%=luci.util.pcdata(luci.http.formvalue("redir"))%>">
|
||||
<input class="cbi-button cbi-button-link" style="margin:0" type="submit" value="<%:Back%>" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<%+footer%>
|
168
luci-mod-admin-full/luasrc/view/cbi/wireless_modefreq.htm
Normal file
168
luci-mod-admin-full/luasrc/view/cbi/wireless_modefreq.htm
Normal file
|
@ -0,0 +1,168 @@
|
|||
<%+cbi/valueheader%>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
var freqlist = <%= luci.http.write_json(self.freqlist) %>;
|
||||
var hwmodes = <%= luci.http.write_json(self.hwmodes) %>;
|
||||
var htmodes = <%= luci.http.write_json(self.htmodes) %>;
|
||||
|
||||
var channels = {
|
||||
'11g': [
|
||||
'auto', 'auto', true
|
||||
],
|
||||
'11a': [
|
||||
'auto', 'auto', true
|
||||
]
|
||||
};
|
||||
|
||||
for (var i = 0; i < freqlist.length; i++)
|
||||
channels[(freqlist[i].mhz > 2484) ? '11a' : '11g'].push(
|
||||
freqlist[i].channel,
|
||||
'%d (%d MHz)'.format(freqlist[i].channel, freqlist[i].mhz),
|
||||
!freqlist[i].restricted
|
||||
);
|
||||
|
||||
var modes = [
|
||||
'', 'Legacy', true,
|
||||
'n', 'N', hwmodes.n,
|
||||
'ac', 'AC', hwmodes.ac
|
||||
];
|
||||
|
||||
var htmodes = {
|
||||
'': [
|
||||
'', '-', true
|
||||
],
|
||||
'n': [
|
||||
'HT20', '20 MHz', htmodes.HT20,
|
||||
'HT40', '40 MHz', htmodes.HT40
|
||||
],
|
||||
'ac': [
|
||||
'VHT20', '20 MHz', htmodes.VHT20,
|
||||
'VHT40', '40 MHz', htmodes.VHT40,
|
||||
'VHT80', '80 MHz', htmodes.VHT80,
|
||||
'VHT160', '160 MHz', htmodes.VHT160
|
||||
]
|
||||
};
|
||||
|
||||
var bands = {
|
||||
'': [
|
||||
'11g', '2.4 GHz', (channels['11g'].length > 3),
|
||||
'11a', '5 GHz', (channels['11a'].length > 3)
|
||||
],
|
||||
'n': [
|
||||
'11g', '2.4 GHz', (channels['11g'].length > 3),
|
||||
'11a', '5 GHz', (channels['11a'].length > 3)
|
||||
],
|
||||
'ac': [
|
||||
'11a', '5 GHz', true
|
||||
]
|
||||
};
|
||||
|
||||
function cbi_set_values(sel, vals)
|
||||
{
|
||||
if (sel.vals)
|
||||
sel.vals.selected = sel.selectedIndex;
|
||||
|
||||
while (sel.options[0])
|
||||
sel.remove(0);
|
||||
|
||||
for (var i = 0; vals && i < vals.length; i += 3)
|
||||
{
|
||||
if (!vals[i+2])
|
||||
continue;
|
||||
|
||||
var opt = document.createElement('option');
|
||||
opt.value = vals[i+0];
|
||||
opt.text = vals[i+1];
|
||||
|
||||
sel.add(opt);
|
||||
}
|
||||
|
||||
if (!isNaN(vals.selected))
|
||||
sel.selectedIndex = vals.selected;
|
||||
|
||||
sel.parentNode.style.display = (sel.options.length <= 1) ? 'none' : '';
|
||||
sel.vals = vals;
|
||||
}
|
||||
|
||||
function cbi_toggle_wifi_mode(id)
|
||||
{
|
||||
cbi_toggle_wifi_htmode(id);
|
||||
cbi_toggle_wifi_band(id);
|
||||
}
|
||||
|
||||
function cbi_toggle_wifi_htmode(id)
|
||||
{
|
||||
var mode = document.getElementById(id + '.mode');
|
||||
var bwdt = document.getElementById(id + '.htmode');
|
||||
|
||||
cbi_set_values(bwdt, htmodes[mode.value]);
|
||||
}
|
||||
|
||||
function cbi_toggle_wifi_band(id)
|
||||
{
|
||||
var mode = document.getElementById(id + '.mode');
|
||||
var band = document.getElementById(id + '.band');
|
||||
|
||||
cbi_set_values(band, bands[mode.value]);
|
||||
cbi_toggle_wifi_channel(id);
|
||||
}
|
||||
|
||||
function cbi_toggle_wifi_channel(id)
|
||||
{
|
||||
var band = document.getElementById(id + '.band');
|
||||
var chan = document.getElementById(id + '.channel');
|
||||
|
||||
cbi_set_values(chan, channels[band.value]);
|
||||
}
|
||||
|
||||
function cbi_init_wifi(id)
|
||||
{
|
||||
var mode = document.getElementById(id + '.mode');
|
||||
var band = document.getElementById(id + '.band');
|
||||
var chan = document.getElementById(id + '.channel');
|
||||
var bwdt = document.getElementById(id + '.htmode');
|
||||
|
||||
cbi_set_values(mode, modes);
|
||||
|
||||
if (/VHT20|VHT40|VHT80|VHT160/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
|
||||
mode.value = 'ac';
|
||||
else if (/HT20|HT40/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
|
||||
mode.value = 'n';
|
||||
else
|
||||
mode.value = '';
|
||||
|
||||
cbi_toggle_wifi_mode(id);
|
||||
|
||||
if (/a/.test(<%= luci.http.write_json(self.map:get(section, "hwmode")) %>))
|
||||
band.value = '11a';
|
||||
else
|
||||
band.value = '11g';
|
||||
|
||||
cbi_toggle_wifi_band(id);
|
||||
|
||||
bwdt.value = <%= luci.http.write_json(self.map:get(section, "htmode")) %>;
|
||||
chan.value = <%= luci.http.write_json(self.map:get(section, "channel")) %>;
|
||||
}
|
||||
//]]></script>
|
||||
|
||||
<label style="float:left; margin-right:3px">
|
||||
<%:Mode%><br />
|
||||
<select style="width:auto" id="<%= cbid %>.mode" name="<%= cbid %>.mode" onchange="cbi_toggle_wifi_mode('<%= cbid %>')"></select>
|
||||
</label>
|
||||
<label style="float:left; margin-right:3px">
|
||||
<%:Band%><br />
|
||||
<select style="width:auto" id="<%= cbid %>.band" name="<%= cbid %>.band" onchange="cbi_toggle_wifi_band('<%= cbid %>')"></select>
|
||||
</label>
|
||||
<label style="float:left; margin-right:3px">
|
||||
<%:Channel%><br />
|
||||
<select style="width:auto" id="<%= cbid %>.channel" name="<%= cbid %>.channel"></select>
|
||||
</label>
|
||||
<label style="float:left; margin-right:3px">
|
||||
<%:Width%><br />
|
||||
<select style="width:auto" id="<%= cbid %>.htmode" name="<%= cbid %>.htmode"></select>
|
||||
</label>
|
||||
<br style="clear:left" />
|
||||
|
||||
<script type="text/javascript">cbi_init_wifi('<%= cbid %>');</script>
|
||||
|
||||
<%+cbi/valuefooter%>
|
Loading…
Add table
Add a link
Reference in a new issue