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_join"}, post("wifi_join"), nil)
43 page = entry({"admin", "network", "wireless_add"}, post("wifi_add"), nil)
46 page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil)
49 page = entry({"admin", "network", "wireless_reconnect"}, post("wifi_reconnect"), nil)
52 page = entry({"admin", "network", "wireless_scan_trigger"}, post("wifi_scan_trigger"), nil)
55 page = entry({"admin", "network", "wireless_scan_results"}, call("wifi_scan_results"), nil)
58 page = entry({"admin", "network", "wireless"}, arcombine(cbi("admin_network/wifi_overview"), cbi("admin_network/wifi")), _("Wireless"), 15)
64 local net = require "luci.model.network".init(uci)
65 for _, wdev in ipairs(net:get_wifidevs()) do
67 for _, wnet in ipairs(wdev:get_wifinets()) do
69 {"admin", "network", "wireless", wnet:id()},
70 alias("admin", "network", "wireless"),
71 wdev:name() .. ": " .. wnet:shortname()
79 page = entry({"admin", "network", "iface_status"}, call("iface_status"), nil)
82 page = entry({"admin", "network", "iface_reconnect"}, post("iface_reconnect"), nil)
85 page = entry({"admin", "network", "iface_down"}, post("iface_down"), nil)
88 page = entry({"admin", "network", "network"}, view("network/interfaces"), _("Interfaces"), 10)
93 if nixio.fs.access("/etc/config/dhcp") then
94 page = node("admin", "network", "dhcp")
95 page.target = view("network/dhcp")
96 page.title = _("DHCP and DNS")
99 page = node("admin", "network", "hosts")
100 page.target = view("network/hosts")
101 page.title = _("Hostnames")
105 page = node("admin", "network", "routes")
106 page.target = view("network/routes")
107 page.title = _("Static Routes")
110 page = node("admin", "network", "diagnostics")
111 page.target = template("admin_network/diagnostics")
112 page.title = _("Diagnostics")
115 page = entry({"admin", "network", "diag_ping"}, post("diag_ping"), nil)
118 page = entry({"admin", "network", "diag_nslookup"}, post("diag_nslookup"), nil)
121 page = entry({"admin", "network", "diag_traceroute"}, post("diag_traceroute"), nil)
124 page = entry({"admin", "network", "diag_ping6"}, post("diag_ping6"), nil)
127 page = entry({"admin", "network", "diag_traceroute6"}, post("diag_traceroute6"), nil)
133 local tpl = require "luci.template"
134 local http = require "luci.http"
135 local dev = http.formvalue("device")
136 local ssid = http.formvalue("join")
139 local cancel = (http.formvalue("cancel") or http.formvalue("cbi.cancel"))
141 local cbi = require "luci.cbi"
142 local map = luci.cbi.load("admin_network/wifi_add")[1]
144 if map:parse() ~= cbi.FORM_DONE then
154 tpl.render("admin_network/wifi_join")
158 local dev = luci.http.formvalue("device")
159 local ntm = require "luci.model.network".init()
161 dev = dev and ntm:get_wifidev(dev)
164 local net = dev:add_wifinet({
172 luci.http.redirect(net:adminlink())
176 function iface_status(ifaces)
177 local netm = require "luci.model.network".init()
181 for iface in ifaces:gmatch("[%w%.%-_]+") do
182 local net = netm:get_network(iface)
183 local device = net and net:get_interface()
187 desc = net:get_i18n(),
189 uptime = net:uptime(),
190 gwaddr = net:gwaddr(),
191 ipaddrs = net:ipaddrs(),
192 ip6addrs = net:ip6addrs(),
193 dnsaddrs = net:dnsaddrs(),
194 ip6prefix = net:ip6prefix(),
195 errors = net:errors(),
196 name = device:shortname(),
197 type = device:type(),
198 typename = device:get_type_i18n(),
199 ifname = device:name(),
200 macaddr = device:mac(),
201 is_up = net:is_up() and device:is_up(),
202 is_alias = net:is_alias(),
203 is_dynamic = net:is_dynamic(),
204 is_auto = net:is_auto(),
205 rx_bytes = device:rx_bytes(),
206 tx_bytes = device:tx_bytes(),
207 rx_packets = device:rx_packets(),
208 tx_packets = device:tx_packets(),
213 for _, device in ipairs(net:get_interfaces() or {}) do
214 data.subdevices[#data.subdevices+1] = {
215 name = device:shortname(),
216 type = device:type(),
217 typename = device:get_type_i18n(),
218 ifname = device:name(),
219 macaddr = device:mac(),
220 is_up = device:is_up(),
221 rx_bytes = device:rx_bytes(),
222 tx_bytes = device:tx_bytes(),
223 rx_packets = device:rx_packets(),
224 tx_packets = device:tx_packets(),
239 luci.http.prepare_content("application/json")
240 luci.http.write_json(rv)
244 luci.http.status(404, "No such device")
247 function iface_reconnect(iface)
248 local netmd = require "luci.model.network".init()
249 local net = netmd:get_network(iface)
251 luci.sys.call("env -i /sbin/ifup %s >/dev/null 2>/dev/null"
252 % luci.util.shellquote(iface))
253 luci.http.status(200, "Reconnected")
257 luci.http.status(404, "No such interface")
260 local function addr2dev(addr, src)
261 local ip = require "luci.ip"
262 local route = ip.route(addr, src)
263 if not src and route and route.src then
264 route = ip.route(addr, route.src:string())
266 return route and route.dev
269 function iface_down(iface, force)
270 local netmd = require "luci.model.network".init()
271 local peer = luci.http.getenv("REMOTE_ADDR")
272 local serv = luci.http.getenv("SERVER_ADDR")
274 if force ~= "force" and serv and peer then
275 local dev = addr2dev(peer, serv)
277 local nets = netmd:get_networks()
281 for _, net in ipairs(nets) do
282 if net:contains_interface(dev) then
288 if outnet:name() == iface then
289 luci.http.status(409, "Is inbound interface")
293 local peeraddr = outnet:get("peeraddr")
294 for _, ai in ipairs(peeraddr and nixio.getaddrinfo(peeraddr) or {}) do
295 local peerdev = addr2dev(ai.address)
296 for _, net in ipairs(peerdev and nets or {}) do
297 if net:contains_interface(peerdev) and net:name() == iface then
298 luci.http.status(409, "Is inbound interface")
306 if netmd:get_network(iface) then
307 luci.sys.call("env -i /sbin/ifdown %s >/dev/null 2>/dev/null"
308 % luci.util.shellquote(iface))
309 luci.http.status(200, "Shut down")
313 luci.http.status(404, "No such interface")
316 function wifi_status(devs)
317 local s = require "luci.tools.status"
320 if type(devs) == "string" then
322 for dev in devs:gmatch("[%w%.%-]+") do
323 rv[#rv+1] = s.wifi_network(dev)
328 luci.http.prepare_content("application/json")
329 luci.http.write_json(rv)
333 luci.http.status(404, "No such device")
336 function wifi_reconnect(radio)
337 local rc = luci.sys.call("env -i /sbin/wifi up %s" % luci.util.shellquote(radio))
340 luci.http.status(200, "Reconnected")
342 luci.http.status(500, "Error")
346 local function _wifi_get_scan_results(cache_key)
347 local results = luci.util.ubus("session", "get", {
348 ubus_rpc_session = luci.model.uci:get_session_id(),
352 if type(results) == "table" and
353 type(results.values) == "table" and
354 type(results.values[cache_key]) == "table"
356 return results.values[cache_key]
362 function wifi_scan_trigger(radio, update)
363 local iw = radio and luci.sys.wifi.getiwinfo(radio)
366 luci.http.status(404, "No such radio device")
370 luci.http.status(204, "Scan scheduled")
372 if nixio.fork() == 0 then
377 local data, bssids = { }, { }
378 local cache_key = "scan_%s" % radio
380 luci.util.ubus("session", "set", {
381 ubus_rpc_session = luci.model.uci:get_session_id(),
382 values = { [cache_key] = nil }
385 for _, bss in ipairs(iw.scanlist or { }) do
387 bssids[bss.bssid] = bss
391 local cached = _wifi_get_scan_results(cache_key)
393 for _, bss in ipairs(cached) do
394 if not bssids[bss.bssid] then
396 data[#data + 1] = bss
402 luci.util.ubus("session", "set", {
403 ubus_rpc_session = luci.model.uci:get_session_id(),
404 values = { [cache_key] = data }
409 function wifi_scan_results(radio)
410 local results = radio and _wifi_get_scan_results("scan_%s" % radio)
413 luci.http.prepare_content("application/json")
414 luci.http.write_json(results)
416 luci.http.status(404, "No wireless scan results")
420 function switch_status(switches)
421 local s = require "luci.tools.status"
423 luci.http.prepare_content("application/json")
424 luci.http.write_json(s.switch_status(switches))
427 function diag_command(cmd, addr)
428 if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
429 luci.http.prepare_content("text/plain")
431 local util = io.popen(cmd % luci.util.shellquote(addr))
434 local ln = util:read("*l")
435 if not ln then break end
437 luci.http.write("\n")
446 luci.http.status(500, "Bad address")
449 function diag_ping(addr)
450 diag_command("ping -c 5 -W 1 %s 2>&1", addr)
453 function diag_traceroute(addr)
454 diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr)
457 function diag_nslookup(addr)
458 diag_command("nslookup %s 2>&1", addr)
461 function diag_ping6(addr)
462 diag_command("ping6 -c 5 %s 2>&1", addr)
465 function diag_traceroute6(addr)
466 diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr)