1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Copyright 2011-2018 Jo-Philipp Wich <jo@mein.io>
3 -- Licensed to the public under the Apache License 2.0.
5 module("luci.controller.admin.network", package.seeall)
8 local uci = require("luci.model.uci").cursor()
12 local has_switch = false
14 uci:foreach("network", "switch",
21 page = node("admin", "network", "vlan")
22 page.target = cbi("admin_network/vlan")
23 page.title = _("Switch")
26 page = entry({"admin", "network", "switch_status"}, call("switch_status"), nil)
31 local has_wifi = false
33 uci:foreach("wireless", "wifi-device",
40 page = entry({"admin", "network", "wireless_assoclist"}, call("wifi_assoclist"), nil)
43 page = entry({"admin", "network", "wireless_join"}, post("wifi_join"), nil)
46 page = entry({"admin", "network", "wireless_add"}, post("wifi_add"), nil)
49 page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil)
52 page = entry({"admin", "network", "wireless_reconnect"}, post("wifi_reconnect"), nil)
55 page = entry({"admin", "network", "wireless_scan_trigger"}, post("wifi_scan_trigger"), nil)
58 page = entry({"admin", "network", "wireless_scan_results"}, call("wifi_scan_results"), nil)
61 page = entry({"admin", "network", "wireless"}, arcombine(cbi("admin_network/wifi_overview"), cbi("admin_network/wifi")), _("Wireless"), 15)
67 local net = require "luci.model.network".init(uci)
68 for _, wdev in ipairs(net:get_wifidevs()) do
70 for _, wnet in ipairs(wdev:get_wifinets()) do
72 {"admin", "network", "wireless", wnet:id()},
73 alias("admin", "network", "wireless"),
74 wdev:name() .. ": " .. wnet:shortname()
82 page = entry({"admin", "network", "iface_add"}, form("admin_network/iface_add"), nil)
85 page = entry({"admin", "network", "iface_status"}, call("iface_status"), nil)
88 page = entry({"admin", "network", "iface_reconnect"}, post("iface_reconnect"), nil)
91 page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), _("Interfaces"), 10)
96 uci:foreach("network", "interface",
98 local ifc = section[".name"]
99 if ifc ~= "loopback" then
100 entry({"admin", "network", "network", ifc},
107 if nixio.fs.access("/etc/config/dhcp") then
108 page = node("admin", "network", "dhcp")
109 page.target = cbi("admin_network/dhcp")
110 page.title = _("DHCP and DNS")
113 page = entry({"admin", "network", "dhcplease_status"}, call("lease_status"), nil)
116 page = node("admin", "network", "hosts")
117 page.target = cbi("admin_network/hosts")
118 page.title = _("Hostnames")
122 page = node("admin", "network", "routes")
123 page.target = cbi("admin_network/routes")
124 page.title = _("Static Routes")
127 page = node("admin", "network", "diagnostics")
128 page.target = template("admin_network/diagnostics")
129 page.title = _("Diagnostics")
132 page = entry({"admin", "network", "diag_ping"}, post("diag_ping"), nil)
135 page = entry({"admin", "network", "diag_nslookup"}, post("diag_nslookup"), nil)
138 page = entry({"admin", "network", "diag_traceroute"}, post("diag_traceroute"), nil)
141 page = entry({"admin", "network", "diag_ping6"}, post("diag_ping6"), nil)
144 page = entry({"admin", "network", "diag_traceroute6"}, post("diag_traceroute6"), nil)
150 local tpl = require "luci.template"
151 local http = require "luci.http"
152 local dev = http.formvalue("device")
153 local ssid = http.formvalue("join")
156 local cancel = (http.formvalue("cancel") or http.formvalue("cbi.cancel"))
158 local cbi = require "luci.cbi"
159 local map = luci.cbi.load("admin_network/wifi_add")[1]
161 if map:parse() ~= cbi.FORM_DONE then
171 tpl.render("admin_network/wifi_join")
175 local dev = luci.http.formvalue("device")
176 local ntm = require "luci.model.network".init()
178 dev = dev and ntm:get_wifidev(dev)
181 local net = dev:add_wifinet({
188 luci.http.redirect(net:adminlink())
192 function iface_status(ifaces)
193 local netm = require "luci.model.network".init()
197 for iface in ifaces:gmatch("[%w%.%-_]+") do
198 local net = netm:get_network(iface)
199 local device = net and net:get_interface()
203 desc = net:get_i18n(),
205 uptime = net:uptime(),
206 gwaddr = net:gwaddr(),
207 ipaddrs = net:ipaddrs(),
208 ip6addrs = net:ip6addrs(),
209 dnsaddrs = net:dnsaddrs(),
210 ip6prefix = net:ip6prefix(),
211 errors = net:errors(),
212 name = device:shortname(),
213 type = device:type(),
214 typename = device:get_type_i18n(),
215 ifname = device:name(),
216 macaddr = device:mac(),
217 is_up = net:is_up() and device:is_up(),
218 is_alias = net:is_alias(),
219 is_dynamic = net:is_dynamic(),
220 rx_bytes = device:rx_bytes(),
221 tx_bytes = device:tx_bytes(),
222 rx_packets = device:rx_packets(),
223 tx_packets = device:tx_packets(),
228 for _, device in ipairs(net:get_interfaces() or {}) do
229 data.subdevices[#data.subdevices+1] = {
230 name = device:shortname(),
231 type = device:type(),
232 typename = device:get_type_i18n(),
233 ifname = device:name(),
234 macaddr = device:mac(),
235 is_up = device:is_up(),
236 rx_bytes = device:rx_bytes(),
237 tx_bytes = device:tx_bytes(),
238 rx_packets = device:rx_packets(),
239 tx_packets = device:tx_packets(),
254 luci.http.prepare_content("application/json")
255 luci.http.write_json(rv)
259 luci.http.status(404, "No such device")
262 function iface_reconnect(iface)
263 local netmd = require "luci.model.network".init()
264 local net = netmd:get_network(iface)
266 luci.sys.call("env -i /sbin/ifup %s >/dev/null 2>/dev/null"
267 % luci.util.shellquote(iface))
268 luci.http.status(200, "Reconnected")
272 luci.http.status(404, "No such interface")
275 function wifi_status(devs)
276 local s = require "luci.tools.status"
279 if type(devs) == "string" then
281 for dev in devs:gmatch("[%w%.%-]+") do
282 rv[#rv+1] = s.wifi_network(dev)
287 luci.http.prepare_content("application/json")
288 luci.http.write_json(rv)
292 luci.http.status(404, "No such device")
295 function wifi_reconnect(radio)
296 local rc = luci.sys.call("env -i /sbin/wifi up %s" % luci.util.shellquote(radio))
299 luci.http.status(200, "Reconnected")
301 luci.http.status(500, "Error")
305 function wifi_assoclist()
306 local s = require "luci.tools.status"
308 luci.http.prepare_content("application/json")
309 luci.http.write_json(s.wifi_assoclist())
313 local function _wifi_get_scan_results(cache_key)
314 local results = luci.util.ubus("session", "get", {
315 ubus_rpc_session = luci.model.uci:get_session_id(),
319 if type(results) == "table" and
320 type(results.values) == "table" and
321 type(results.values[cache_key]) == "table"
323 return results.values[cache_key]
329 function wifi_scan_trigger(radio, update)
330 local iw = radio and luci.sys.wifi.getiwinfo(radio)
333 luci.http.status(404, "No such radio device")
337 luci.http.status(200, "Scan scheduled")
339 if nixio.fork() == 0 then
344 local data, bssids = { }, { }
345 local cache_key = "scan_%s" % radio
347 luci.util.ubus("session", "set", {
348 ubus_rpc_session = luci.model.uci:get_session_id(),
349 values = { [cache_key] = nil }
352 for _, bss in ipairs(iw.scanlist or { }) do
354 bssids[bss.bssid] = bss
358 for _, bss in ipairs(_wifi_get_scan_results(cache_key)) do
359 if not bssids[bss.bssid] then
361 data[#data + 1] = bss
366 luci.util.ubus("session", "set", {
367 ubus_rpc_session = luci.model.uci:get_session_id(),
368 values = { [cache_key] = data }
373 function wifi_scan_results(radio)
374 local results = radio and _wifi_get_scan_results("scan_%s" % radio)
376 if results and #results > 0 then
377 luci.http.prepare_content("application/json")
378 luci.http.write_json(results)
380 luci.http.status(404, "No wireless scan results")
384 function lease_status()
385 local s = require "luci.tools.status"
387 luci.http.prepare_content("application/json")
389 luci.http.write_json(s.dhcp_leases())
391 luci.http.write_json(s.dhcp6_leases())
395 function switch_status(switches)
396 local s = require "luci.tools.status"
398 luci.http.prepare_content("application/json")
399 luci.http.write_json(s.switch_status(switches))
402 function diag_command(cmd, addr)
403 if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
404 luci.http.prepare_content("text/plain")
406 local util = io.popen(cmd % luci.util.shellquote(addr))
409 local ln = util:read("*l")
410 if not ln then break end
412 luci.http.write("\n")
421 luci.http.status(500, "Bad address")
424 function diag_ping(addr)
425 diag_command("ping -c 5 -W 1 %s 2>&1", addr)
428 function diag_traceroute(addr)
429 diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr)
432 function diag_nslookup(addr)
433 diag_command("nslookup %s 2>&1", addr)
436 function diag_ping6(addr)
437 diag_command("ping6 -c 5 %s 2>&1", addr)
440 function diag_traceroute6(addr)
441 diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr)