LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
+Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
function index()
require("luci.i18n")
local uci = require("luci.model.uci").cursor()
+ local net = require "luci.model.network".init(uci)
local i18n = luci.i18n.translate
local has_wifi = nixio.fs.stat("/etc/config/wireless")
local has_switch = false
page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil, 16)
page.leaf = true
+
+ local wdev
+ for _, wdev in ipairs(net:get_wifidevs()) do
+ local wnet
+ for _, wnet in ipairs(wdev:get_wifinets()) do
+ entry(
+ {"admin", "network", "wireless", wnet.netid},
+ alias("admin", "network", "wireless"),
+ wdev:name() .. ": " .. wnet:shortname()
+ )
+ end
+ end
end
page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), i18n("Interfaces"), 10)
page.leaf = true
page.subindex = true
- page = entry({"admin", "network", "add"}, cbi("admin_network/iface_add"), nil)
+ page = entry({"admin", "network", "iface_add"}, cbi("admin_network/iface_add"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "iface_delete"}, call("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"}, call("iface_reconnect"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "iface_shutdown"}, call("iface_shutdown"), nil)
+ page.leaf = true
+
uci:foreach("network", "interface",
function (section)
local ifc = section[".name"]
)
if nixio.fs.access("/etc/config/dhcp") then
- page = node("admin", "network", "dhcpleases")
+ page = node("admin", "network", "dhcpleases")
page.target = cbi("admin_network/dhcpleases")
page.title = i18n("DHCP Leases")
page.order = 30
page = entry({"admin", "network", "dhcplease_status"}, call("lease_status"), nil)
page.leaf = true
- end
- page = node("admin", "network", "hosts")
- page.target = cbi("admin_network/hosts")
- page.title = i18n("Hostnames")
- page.order = 40
+ page = node("admin", "network", "hosts")
+ page.target = cbi("admin_network/hosts")
+ page.title = i18n("Hostnames")
+ page.order = 40
+ end
page = node("admin", "network", "routes")
page.target = cbi("admin_network/routes")
page.title = i18n("Static Routes")
page.order = 50
+ page = node("admin", "network", "diagnostics")
+ page.target = template("admin_network/diagnostics")
+ page.title = i18n("Diagnostics")
+ page.order = 60
+
+ page = entry({"admin", "network", "diag_ping"}, call("diag_ping"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "diag_nslookup"}, call("diag_nslookup"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "diag_traceroute"}, call("diag_traceroute"), nil)
+ page.leaf = true
end
function wifi_join()
function iface_status()
local path = luci.dispatcher.context.requestpath
- local x = luci.model.uci.cursor_state()
+ local netm = require "luci.model.network".init()
local rv = { }
local iface
for iface in path[#path]:gmatch("[%w%.%-]+") do
- local dev = x:get("network", iface, "device") or ""
- if #dev == 0 or dev:match("^%d") or dev:match("%W") then
- dev = x:get("network", iface, "ifname") or ""
- dev = dev:match("%S+")
- end
-
- local info
- local data = { }
- for _, info in ipairs(nixio.getifaddrs()) do
- local name = info.name:match("[^:]+")
- if name == dev then
- if info.family == "packet" then
- data.flags = info.flags
- data.stats = info.data
- data.macaddr = info.addr
- data.ifname = name
- elseif info.family == "inet" then
- data.ipaddrs = data.ipaddrs or { }
- data.ipaddrs[#data.ipaddrs+1] = {
- addr = info.addr,
- broadaddr = info.broadaddr,
- dstaddr = info.dstaddr,
- netmask = info.netmask,
- prefix = info.prefix
- }
- elseif info.family == "inet6" then
- data.ip6addrs = data.ip6addrs or { }
- data.ip6addrs[#data.ip6addrs+1] = {
- addr = info.addr,
- netmask = info.netmask,
- prefix = info.prefix
- }
+ local net = netm:get_network(iface)
+ if net then
+ local info
+ local dev = net:ifname()
+ local data = {
+ id = iface,
+ proto = net:proto(),
+ uptime = net:uptime(),
+ gwaddr = net:gwaddr(),
+ dnsaddrs = net:dnsaddrs()
+ }
+ for _, info in ipairs(nixio.getifaddrs()) do
+ local name = info.name:match("[^:]+")
+ if name == dev then
+ if info.family == "packet" then
+ data.flags = info.flags
+ data.stats = info.data
+ data.macaddr = info.addr
+ data.ifname = name
+ elseif info.family == "inet" then
+ data.ipaddrs = data.ipaddrs or { }
+ data.ipaddrs[#data.ipaddrs+1] = {
+ addr = info.addr,
+ broadaddr = info.broadaddr,
+ dstaddr = info.dstaddr,
+ netmask = info.netmask,
+ prefix = info.prefix
+ }
+ elseif info.family == "inet6" then
+ data.ip6addrs = data.ip6addrs or { }
+ data.ip6addrs[#data.ip6addrs+1] = {
+ addr = info.addr,
+ netmask = info.netmask,
+ prefix = info.prefix
+ }
+ end
end
end
- end
- if next(data) then
- rv[#rv+1] = data
+ if next(data) then
+ rv[#rv+1] = data
+ end
end
end
luci.http.status(404, "No such device")
end
+function iface_reconnect()
+ local path = luci.dispatcher.context.requestpath
+ local iface = path[#path]
+ local netmd = require "luci.model.network".init()
+
+ local net = netmd:get_network(iface)
+ if net then
+ local ifn
+ for _, ifn in ipairs(net:get_interfaces()) do
+ local wnet = ifn:get_wifinet()
+ if wnet then
+ local wdev = wnet:get_device()
+ if wdev then
+ luci.sys.call(
+ "env -i /sbin/wifi up %q >/dev/null 2>/dev/null"
+ % wdev:name()
+ )
+
+ luci.http.status(200, "Reconnected")
+ return
+ end
+ end
+ end
+
+ 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()
+ local path = luci.dispatcher.context.requestpath
+ local iface = path[#path]
+ 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()
+ local path = luci.dispatcher.context.requestpath
+ local iface = path[#path]
+ 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()
local path = luci.dispatcher.context.requestpath
+ local s = require "luci.tools.status"
local rv = { }
local dev
for dev in path[#path]:gmatch("[%w%.%-]+") do
- local iw = luci.sys.wifi.getiwinfo(dev)
- if iw then
- local f
- local j = { id = dev }
- for _, f in ipairs({
- "channel", "frequency", "txpower", "bitrate", "signal", "noise",
- "quality", "quality_max", "mode", "ssid", "bssid", "country",
- "encryption", "ifname", "assoclist"
- }) do
- j[f] = iw[f]
- end
-
- rv[#rv+1] = j
- end
+ rv[#rv+1] = s.wifi_network(dev)
end
if #rv > 0 then
end
function lease_status()
- local rv = { }
- local leasefile = "/var/dhcp.leases"
+ local s = require "luci.tools.status"
- local uci = require "luci.model.uci".cursor()
- local nfs = require "nixio.fs"
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(s.dhcp_leases())
+end
- uci:foreach("dhcp", "dnsmasq",
- function(s)
- if s.leasefile and nfs.access(s.leasefile) then
- leasefile = s.leasefile
- return false
- end
- end)
-
- local fd = io.open(leasefile, "r")
- if fd then
- while true do
- local ln = fd:read("*l")
- if not ln then
- break
- else
- local ts, mac, ip, name = ln:match("^(%d+) (%S+) (%S+) (%S+)")
- if ts and mac and ip and name then
- rv[#rv+1] = {
- expires = os.difftime(tonumber(ts) or 0, os.time()),
- macaddr = mac,
- ipaddr = ip,
- hostname = (name ~= "*") and name
- }
- end
+function diag_command(cmd)
+ local path = luci.dispatcher.context.requestpath
+ local addr = path[#path]
+
+ 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
- fd:close()
+
+ return
end
- luci.http.prepare_content("application/json")
- luci.http.write_json(rv)
+ luci.http.status(500, "Bad address")
+end
+
+function diag_ping()
+ diag_command("ping -c 5 -W 1 %q 2>&1")
+end
+
+function diag_traceroute()
+ diag_command("traceroute -q 1 -w 1 -n %q 2>&1")
+end
+
+function diag_nslookup()
+ diag_command("nslookup %q 2>&1")
end