From 027d882f4dfd946332de945b0ac9400b65ec216a Mon Sep 17 00:00:00 2001 From: Ycarus Date: Fri, 25 May 2018 14:36:55 +0200 Subject: [PATCH] Update luci-mod-admin-full to latest version --- .../luasrc/controller/admin/network.lua | 31 +- .../luasrc/controller/admin/network.lua.orig | 433 ++++++++++++++ .../luasrc/controller/admin/status.lua | 10 +- .../luasrc/controller/admin/system.lua | 5 +- .../luasrc/controller/admin/uci.lua | 101 +++- .../luasrc/model/cbi/admin_network/dhcp.lua | 19 +- .../model/cbi/admin_network/dhcp.lua.orig | 343 +++++++++++ .../luasrc/model/cbi/admin_network/ifaces.lua | 5 + .../model/cbi/admin_network/ifaces.lua.orig | 562 ++++++++++++++++++ .../luasrc/model/cbi/admin_network/vlan.lua | 3 +- .../luasrc/model/cbi/admin_network/wifi.lua | 128 ++-- .../luasrc/view/admin_system/flashops.htm | 3 + .../luasrc/view/admin_system/packages.htm | 2 +- .../luasrc/view/admin_uci/apply.htm | 23 - .../luasrc/view/admin_uci/changes.htm | 29 +- .../luasrc/view/admin_uci/revert.htm | 33 +- .../luasrc/view/cbi/wireless_modefreq.htm | 6 +- luci-mod-admin-full/root/etc/init.d/macvlan | 0 .../etc/uci-defaults/50_luci-mod-admin-full | 22 + .../root/etc/uci-defaults/51_macvlan | 0 20 files changed, 1589 insertions(+), 169 deletions(-) create mode 100644 luci-mod-admin-full/luasrc/controller/admin/network.lua.orig create mode 100644 luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua.orig create mode 100644 luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua.orig delete mode 100644 luci-mod-admin-full/luasrc/view/admin_uci/apply.htm mode change 100755 => 100644 luci-mod-admin-full/root/etc/init.d/macvlan create mode 100755 luci-mod-admin-full/root/etc/uci-defaults/50_luci-mod-admin-full mode change 100755 => 100644 luci-mod-admin-full/root/etc/uci-defaults/51_macvlan diff --git a/luci-mod-admin-full/luasrc/controller/admin/network.lua b/luci-mod-admin-full/luasrc/controller/admin/network.lua index e881694be..e9bdd4383 100644 --- a/luci-mod-admin-full/luasrc/controller/admin/network.lua +++ b/luci-mod-admin-full/luasrc/controller/admin/network.lua @@ -82,7 +82,7 @@ function index() end - page = entry({"admin", "network", "iface_add"}, cbi("admin_network/iface_add"), nil) + page = entry({"admin", "network", "iface_add"}, form("admin_network/iface_add"), nil) page.leaf = true page = entry({"admin", "network", "iface_delete"}, post("iface_delete"), nil) @@ -301,7 +301,8 @@ 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.sys.call("env -i /sbin/ifup %s >/dev/null 2>/dev/null" + % luci.util.shellquote(iface)) luci.http.status(200, "Reconnected") return end @@ -313,7 +314,8 @@ 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.sys.call("env -i /sbin/ifdown %s >/dev/null 2>/dev/null" + % luci.util.shellquote(iface)) luci.http.status(200, "Shutdown") return end @@ -325,7 +327,8 @@ 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.sys.call("env -i /sbin/ifdown %s >/dev/null 2>/dev/null" + % luci.util.shellquote(iface)) luci.http.redirect(luci.dispatcher.build_url("admin/network/network")) netmd:commit("network") netmd:commit("wireless") @@ -339,9 +342,11 @@ 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) + if type(devs) == "string" then + local dev + for dev in devs:gmatch("[%w%.%-]+") do + rv[#rv+1] = s.wifi_network(dev) + end end if #rv > 0 then @@ -401,7 +406,7 @@ 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) + local util = io.popen(cmd % luci.util.shellquote(addr)) if util then while true do local ln = util:read("*l") @@ -420,23 +425,23 @@ function diag_command(cmd, addr) end function diag_ping(addr) - diag_command("ping -c 5 -W 1 %q 2>&1", addr) + diag_command("ping -c 5 -W 1 %s 2>&1", addr) end function diag_traceroute(addr) - diag_command("traceroute -q 1 -w 1 -n %q 2>&1", addr) + diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr) end function diag_nslookup(addr) - diag_command("nslookup %q 2>&1", addr) + diag_command("nslookup %s 2>&1", addr) end function diag_ping6(addr) - diag_command("ping6 -c 5 %q 2>&1", addr) + diag_command("ping6 -c 5 %s 2>&1", addr) end function diag_traceroute6(addr) - diag_command("traceroute6 -q 1 -w 2 -n %q 2>&1", addr) + diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr) end function diag_iperf3(addr) diff --git a/luci-mod-admin-full/luasrc/controller/admin/network.lua.orig b/luci-mod-admin-full/luasrc/controller/admin/network.lua.orig new file mode 100644 index 000000000..a26d3d14e --- /dev/null +++ b/luci-mod-admin-full/luasrc/controller/admin/network.lua.orig @@ -0,0 +1,433 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2011-2015 Jo-Philipp Wich +-- 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"}, form("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(), + 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 %s >/dev/null 2>/dev/null" + % luci.util.shellquote(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 %s >/dev/null 2>/dev/null" + % luci.util.shellquote(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 %s >/dev/null 2>/dev/null" + % luci.util.shellquote(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 = { } + + if type(devs) == "string" then + local dev + for dev in devs:gmatch("[%w%.%-]+") do + rv[#rv+1] = s.wifi_network(dev) + 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 + +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 % luci.util.shellquote(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 %s 2>&1", addr) +end + +function diag_traceroute(addr) + diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr) +end + +function diag_nslookup(addr) + diag_command("nslookup %s 2>&1", addr) +end + +function diag_ping6(addr) + diag_command("ping6 -c 5 %s 2>&1", addr) +end + +function diag_traceroute6(addr) + diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr) +end diff --git a/luci-mod-admin-full/luasrc/controller/admin/status.lua b/luci-mod-admin-full/luasrc/controller/admin/status.lua index 22e1b7e17..4471fd597 100644 --- a/luci-mod-admin-full/luasrc/controller/admin/status.lua +++ b/luci-mod-admin-full/luasrc/controller/admin/status.lua @@ -14,7 +14,7 @@ function index() 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", "processes"}, form("admin_status/processes"), _("Processes"), 6) entry({"admin", "status", "realtime"}, alias("admin", "status", "realtime", "load"), _("Realtime Graphs"), 7) @@ -62,7 +62,9 @@ end function action_bandwidth(iface) luci.http.prepare_content("application/json") - local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface) + local bwc = io.popen("luci-bwc -i %s 2>/dev/null" + % luci.util.shellquote(iface)) + if bwc then luci.http.write("[") @@ -80,7 +82,9 @@ end function action_wireless(iface) luci.http.prepare_content("application/json") - local bwc = io.popen("luci-bwc -r %q 2>/dev/null" % iface) + local bwc = io.popen("luci-bwc -r %s 2>/dev/null" + % luci.util.shellquote(iface)) + if bwc then luci.http.write("[") diff --git a/luci-mod-admin-full/luasrc/controller/admin/system.lua b/luci-mod-admin-full/luasrc/controller/admin/system.lua index 5478afa3e..6fcd66f44 100644 --- a/luci-mod-admin-full/luasrc/controller/admin/system.lua +++ b/luci-mod-admin-full/luasrc/controller/admin/system.lua @@ -27,7 +27,8 @@ function index() entry({"admin", "system", "fstab", "swap"}, cbi("admin_system/fstab/swap"), nil).leaf = true end - if fs.access("/sys/class/leds") then + local nodes, number = fs.glob("/sys/class/leds/*") + if number > 0 then entry({"admin", "system", "leds"}, cbi("admin_system/leds"), _("LED Configuration"), 60) end @@ -195,7 +196,7 @@ local function supports_sysupgrade() end local function supports_reset() - return (os.execute([[grep -sqE '"rootfs_data"|"ubi"' /proc/mtd]]) == 0) + return (os.execute([[grep -sq "^overlayfs:/overlay / overlay " /proc/mounts]]) == 0) end local function storage_size() diff --git a/luci-mod-admin-full/luasrc/controller/admin/uci.lua b/luci-mod-admin-full/luasrc/controller/admin/uci.lua index 9c33d9c18..9533ff5e6 100644 --- a/luci-mod-admin-full/luasrc/controller/admin/uci.lua +++ b/luci-mod-admin-full/luasrc/controller/admin/uci.lua @@ -5,60 +5,97 @@ 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)) + local redir = luci.http.formvalue("redir", true) + or table.concat(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} + + local node + local authen = function(checkpass, allowed_users) + return "root", luci.http.formvalue("sid") + end + + node = entry({"admin", "uci", "apply_rollback"}, post("action_apply_rollback"), nil) + node.cors = true + node.sysauth_authenticator = authen + + node = entry({"admin", "uci", "apply_unchecked"}, post("action_apply_unchecked"), nil) + node.cors = true + node.sysauth_authenticator = authen + + node = entry({"admin", "uci", "confirm"}, post("action_confirm"), nil) + node.cors = true + node.sysauth_authenticator = authen end + function action_changes() - local uci = luci.model.uci.cursor() + local uci = require "luci.model.uci" local changes = uci:changes() luci.template.render("admin_uci/changes", { - changes = next(changes) and changes + changes = next(changes) and changes, + timeout = timeout }) 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 uci = require "luci.model.uci" local changes = uci:changes() -- Collect files to be reverted + local r, tbl 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 + + +local function ubus_state_to_http(errstr) + local map = { + ["Invalid command"] = 400, + ["Invalid argument"] = 400, + ["Method not found"] = 404, + ["Entry not found"] = 404, + ["No data"] = 204, + ["Permission denied"] = 403, + ["Timeout"] = 504, + ["Not supported"] = 500, + ["Unknown error"] = 500, + ["Connection failed"] = 503 + } + + local code = map[errstr] or 200 + local msg = errstr or "OK" + + luci.http.status(code, msg) + + if code ~= 204 then + luci.http.prepare_content("text/plain") + luci.http.write(msg) + end +end + +function action_apply_rollback() + local uci = require "luci.model.uci" + local _, errstr = uci:apply(true) + ubus_state_to_http(errstr) +end + +function action_apply_unchecked() + local uci = require "luci.model.uci" + local _, errstr = uci:apply(false) + ubus_state_to_http(errstr) +end + +function action_confirm() + local uci = require "luci.model.uci" + local _, errstr = uci:confirm() + ubus_state_to_http(errstr) +end diff --git a/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua b/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua index 1ec1d47e0..58bc966b2 100644 --- a/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua +++ b/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua @@ -115,7 +115,7 @@ s:taboption("advanced", Flag, "nonegcache", 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 DNS servers.")) + "domain-specific or full upstream DNS servers.")) s:taboption("advanced", Flag, "strictorder", translate("Strict order"), @@ -212,6 +212,12 @@ cq.optional = true cq.datatype = "uinteger" cq.placeholder = 150 +cs = s:taboption("advanced", Value, "cachesize", + translate("Size of DNS query cache"), + translate("Number of cached DNS entries (max is 10000, 0 is no caching)")) +cs.optional = true +cs.datatype = "range(0,10000)" +cs.placeholder = 150 s:taboption("tftp", Flag, "enable_tftp", translate("Enable TFTP server")).optional = true @@ -264,7 +270,7 @@ s = m:section(TypedSection, "host", translate("Static Leases"), "DHCP clients. They are also required for non-dynamic interface configurations where " .. "only hosts with a corresponding lease are served.") .. "
" .. translate("Use the Add Button to add a new lease entry. The MAC-Address " .. - "indentifies the host, the IPv4-Address specifies the fixed address to " .. + "identifies the host, the IPv4-Address specifies the fixed address to " .. "use, and the Hostname is assigned as a symbolic name to the requesting host. " .. "The optional Lease time can be used to set non-standard host-specific " .. "lease time, e.g. 12h, 3d or infinite.")) @@ -274,7 +280,7 @@ s.anonymous = true s.template = "cbi/tblsection" name = s:option(Value, "name", translate("Hostname")) -name.datatype = "hostname" +name.datatype = "hostname('strict')" name.rmempty = true function name.write(self, section, value) @@ -291,6 +297,11 @@ mac = s:option(Value, "mac", translate("MAC mac.datatype = "list(macaddr)" mac.rmempty = true +function mac.cfgvalue(self, section) + local val = Value.cfgvalue(self, section) + return ipc.checkmac(val) or val +end + ip = s:option(Value, "ip", translate("IPv4-Address")) ip.datatype = "or(ip4addr,'ignore')" @@ -298,7 +309,7 @@ gw = s:option(Value, "gw", translate("Gateway")) gw.datatype = "or(ip4addr,'ignore')" time = s:option(Value, "leasetime", translate("Lease time")) -time.rmempty = true +time.rmempty = true duid = s:option(Value, "duid", translate("DUID")) duid.datatype = "and(rangelength(20,36),hexstring)" diff --git a/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua.orig b/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua.orig new file mode 100644 index 000000000..855ed31f1 --- /dev/null +++ b/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua.orig @@ -0,0 +1,343 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local ipc = require "luci.ip" +local sys = require "luci.sys" +local o +require "luci.util" + +m = Map("dhcp", translate("DHCP and DNS"), + translate("Dnsmasq is a combined DHCP-Server and DNS-" .. + "Forwarder for NAT " .. + "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 DNS-Requests without " .. + "DNS-Name")) + +s:taboption("general", Flag, "authoritative", + translate("Authoritative"), + translate("This is the only DHCP in the local network")) + + +s:taboption("files", Flag, "readethers", + translate("Use /etc/ethers"), + translate("Read /etc/ethers to configure the DHCP-Server")) + +s:taboption("files", Value, "leasefile", + translate("Leasefile"), + translate("file where given DHCP-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 DNS file")) + +rf:depends("noresolv", "") +rf.optional = true + + +s:taboption("files", Flag, "nohosts", + translate("Ignore /etc/hosts")).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 + +bp = s:taboption("advanced", Flag, "boguspriv", + translate("Filter private"), + translate("Do not forward reverse lookups for local networks")) +bp.default = bp.enabled + +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 DNS servers.")) + +s:taboption("advanced", Flag, "strictorder", + translate("Strict order"), + translate("DNS 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 DNS " .. + "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("DNS 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("DNS 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("Max. DHCP 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("Max. EDNS0 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("Max. concurrent queries"), + translate("Maximum allowed number of concurrent DNS queries")) + +cq.optional = true +cq.datatype = "uinteger" +cq.placeholder = 150 + +cs = s:taboption("advanced", Value, "cachesize", + translate("Size of DNS query cache"), + translate("Number of cached DNS entries (max is 10000, 0 is no caching)")) +cs.optional = true +cs.datatype = "range(0,10000)" +cs.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.") .. "
" .. + translate("Use the Add Button to add a new lease entry. The MAC-Address " .. + "identifies the host, the IPv4-Address specifies the fixed address to " .. + "use, and the Hostname is assigned as a symbolic name to the requesting host. " .. + "The optional Lease time 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('strict')" +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("MAC-Address")) +mac.datatype = "list(macaddr)" +mac.rmempty = true + +function mac.cfgvalue(self, section) + local val = Value.cfgvalue(self, section) + return ipc.checkmac(val) or val +end + +ip = s:option(Value, "ip", translate("IPv4-Address")) +ip.datatype = "or(ip4addr,'ignore')" + +time = s:option(Value, "leasetime", translate("Lease time")) +time.rmempty = true + +duid = s:option(Value, "duid", translate("DUID")) +duid.datatype = "and(rangelength(20,36),hexstring)" +fp = io.open("/var/hosts/odhcpd") +if fp then + for line in fp:lines() do + local net_val, duid_val = string.match(line, "# (%S+)%s+(%S+)") + if duid_val then + duid:value(duid_val, duid_val) + end + end + fp:close() +end + +hostid = s:option(Value, "hostid", translate("IPv6-Suffix (hex)")) + +sys.net.host_hints(function(m, v4, v6, name) + if m and v4 then + ip:value(v4) + mac:value(m, "%s (%s)" %{ m, name or v4 }) + 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 diff --git a/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua b/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua index 1a685fbe0..153d4dac4 100644 --- a/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua +++ b/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua @@ -296,6 +296,11 @@ if not net:is_virtual() then translate("Enables the Spanning Tree Protocol on this bridge")) stp:depends("type", "bridge") stp.rmempty = true + + igmp = s:taboption("physical", Flag, "igmp_snooping", translate("Enable IGMP snooping"), + translate("Enables IGMP snooping on this bridge")) + igmp:depends("type", "bridge") + igmp.rmempty = true -- macsource = s:taboption("physical", DynamicList, "vlanmacs", translate("Add MACs address to enable source mode")) -- macsource:depends("type", "macvlan") -- macsource.rmempty = true diff --git a/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua.orig b/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua.orig new file mode 100644 index 000000000..38e5de7b3 --- /dev/null +++ b/luci-mod-admin-full/luasrc/model/cbi/admin_network/ifaces.lua.orig @@ -0,0 +1,562 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008-2011 Jo-Philipp Wich +-- 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 VLAN notation INTERFACE.VLANNR (e.g.: eth0.1).")) +m.redirect = luci.dispatcher.build_url("admin", "network", "network") +m:chain("wireless") +m:chain("luci") + +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 set_ifstate(name, option, value) + local found = false + + m.uci:foreach("luci", "ifstate", function (s) + if s.interface == name then + m.uci:set("luci", s[".name"], option, value) + found = true + return false + end + end) + + if not found then + local sid = m.uci:add("luci", "ifstate") + m.uci:set("luci", sid, "interface", name) + m.uci:set("luci", sid, option, value) + end + + m.uci:save("luci") +end + +local function get_ifstate(name, option) + local val + + m.uci:foreach("luci", "ifstate", function (s) + if s.interface == name then + val = m.uci:get("luci", s[".name"], option) + return false + end + end) + + return val +end + +local function backup_ifnames(is_bridge) + if not net:is_floating() and not get_ifstate(net:name(), "ifname") then + local ifcs = net:get_interfaces() or { net:get_interface() } + if ifcs then + local _, ifn + local ifns = { } + for _, ifn in ipairs(ifcs) do + local wif = ifn:get_wifinet() + ifns[#ifns+1] = wif and wif:id() or ifn:name() + end + if #ifns > 0 then + set_ifstate(net:name(), "ifname", table.concat(ifns, " ")) + set_ifstate(net:name(), "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 = (get_ifstate(net:name(), "bridge") == "true") + local ifn + local ifns = { } + for ifn in ut.imatch(get_ifstate(net:name(), "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" + 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 + + +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 + +delegate = s:taboption("advanced", Flag, "delegate", translate("Use builtin IPv6-management")) +delegate.default = delegate.enabled + +force_link = s:taboption("advanced", Flag, "force_link", + translate("Force link"), + translate("Set interface properties regardless of the link carrier (If set, carrier sense events do not invoke hotplug handlers).")) + +force_link.default = (net:proto() == "static") and force_link.enabled or force_link.disabled + + +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") + + stp = s:taboption("physical", Flag, "stp", translate("Enable STP"), + translate("Enables the Spanning Tree Protocol on this bridge")) + stp:depends("type", "bridge") + stp.rmempty = true + + igmp = s:taboption("physical", Flag, "igmp_snooping", translate("Enable IGMP snooping"), + translate("Enables IGMP snooping on this bridge")) + igmp:depends("type", "bridge") + igmp.rmempty = true +end + + +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 unspecified to remove the interface from the associated zone or fill out the create 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 DHCP 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 (2m).")) + ltime.rmempty = true + ltime.default = "12h" + + local dd = s:taboption("advanced", Flag, "dynamicdhcp", + translate("Dynamic DHCP"), + 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("IPv4-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 \"6,192.168.2.1," .. + "192.168.2.2\" 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 diff --git a/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua b/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua index 89a73a5ca..b52dff13a 100644 --- a/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua +++ b/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua @@ -5,6 +5,7 @@ m = Map("network", translate("Switch"), translate("The network ports on this device can be combined to several VLANs in which computers can communicate directly with each other. VLANs 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 ut = require "luci.util" local nw = require "luci.model.network" local switches = { } @@ -74,7 +75,7 @@ m.uci:foreach("network", "switch", end -- Parse some common switch properties from swconfig help output. - local swc = io.popen("swconfig dev %q help 2>/dev/null" % switch_name) + local swc = io.popen("swconfig dev %s help 2>/dev/null" % ut.shellquote(switch_name)) if swc then local is_port_attr = false diff --git a/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua b/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua index c0bb38030..cacaa2595 100644 --- a/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua +++ b/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua @@ -7,6 +7,17 @@ local ut = require "luci.util" local nt = require "luci.sys".net local fs = require "nixio.fs" +local acct_port, acct_secret, acct_server, anonymous_identity, ant1, ant2, + auth, auth_port, auth_secret, auth_server, bssid, cacert, cacert2, + cc, ch, cipher, clientcert, clientcert2, ea, eaptype, en, encr, + ft_protocol, ft_psk_generate_local, hidden, htmode, identity, + ieee80211r, ieee80211w, ifname, isolate, key_retries, + legacyrates, max_timeout, meshfwd, meshid, ml, mobility_domain, mode, + mp, nasid, network, password, pmk_r1_push, privkey, privkey2, privkeypwd, + privkeypwd2, r0_key_lifetime, r0kh, r1_key_holder, r1kh, + reassociation_deadline, retry_timeout, ssid, st, tp, wepkey, wepslot, + wmm, wpakey, wps + arg[1] = arg[1] or "" m = Map("wireless", "", @@ -19,16 +30,6 @@ m:chain("network") m:chain("firewall") m.redirect = luci.dispatcher.build_url("admin/network/wireless") -local ifsection - -function m.on_commit(map) - local wnet = nw:get_wifinet(arg[1]) - if ifsection and wnet then - ifsection.section = wnet.sid - m.title = luci.util.pcdata(wnet:get_i18n()) - end -end - nw.init(m.uci) local wnet = nw:get_wifinet(arg[1]) @@ -40,38 +41,6 @@ if not wnet or not wdev then return end --- wireless toggle was requested, commit and reload page -function m.parse(map) - local new_cc = m:formvalue("cbid.wireless.%s.country" % wdev:name()) - local old_cc = m:get(wdev:name(), "country") - - if m:formvalue("cbid.wireless.%s.__toggle" % wdev:name()) then - if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then - wnet:set("disabled", nil) - else - wnet:set("disabled", "1") - end - wdev:set("disabled", nil) - - nw:commit("wireless") - luci.sys.call("(env -i /bin/ubus call network reload) >/dev/null 2>/dev/null") - - luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", arg[1])) - return - end - - Map.parse(map) - - if m:get(wdev:name(), "type") == "mac80211" and new_cc and new_cc ~= old_cc then - luci.sys.call("iw reg set %q" % new_cc) - luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", arg[1])) - return - end -end - -m.title = luci.util.pcdata(wnet:get_i18n()) - - local function txpower_list(iw) local list = iw.txpwrlist or { } local off = tonumber(iw.txpower_offset) or 0 @@ -112,6 +81,57 @@ local hw_modes = iw.hwmodelist or { } local tx_power_list = txpower_list(iw) local tx_power_cur = txpower_current(wdev:get("txpower"), tx_power_list) +-- wireless toggle was requested, commit and reload page +function m.parse(map) + local new_cc = m:formvalue("cbid.wireless.%s.country" % wdev:name()) + local old_cc = m:get(wdev:name(), "country") + + if m:formvalue("cbid.wireless.%s.__toggle" % wdev:name()) then + if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then + wnet:set("disabled", nil) + else + wnet:set("disabled", "1") + end + wdev:set("disabled", nil) + m.apply_needed = true + m.redirect = nil + end + + Map.parse(map) + + if m:get(wdev:name(), "type") == "mac80211" and new_cc and new_cc ~= old_cc then + luci.sys.call("iw reg set %s" % ut.shellquote(new_cc)) + + local old_ch = tonumber(m:formvalue("cbid.wireless.%s._mode_freq.channel" % wdev:name()) or "") + if old_ch then + local _, c, new_ch + for _, c in ipairs(iw.freqlist) do + if c.channel > old_ch or (old_ch <= 14 and c.channel > 14) then + break + end + new_ch = c.channel + end + if new_ch ~= old_ch then + wdev:set("channel", new_ch) + m.message = translatef("Channel %d is not available in the %s regulatory domain and has been auto-adjusted to %d.", + old_ch, new_cc, new_ch) + end + end + end + + if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then + en.title = translate("Wireless network is disabled") + en.inputtitle = translate("Enable") + en.inputstyle = "apply" + else + en.title = translate("Wireless network is enabled") + en.inputtitle = translate("Disable") + en.inputstyle = "reset" + end +end + +m.title = luci.util.pcdata(wnet:get_i18n()) + s = m:section(NamedSection, wdev:name(), "wifi-device", translate("Device Configuration")) s.addremove = false @@ -119,29 +139,12 @@ s:tab("general", translate("General Setup")) s:tab("macfilter", translate("MAC-Filter")) s:tab("advanced", translate("Advanced Settings")) ---[[ -back = s:option(DummyValue, "_overview", translate("Overview")) -back.value = "" -back.titleref = luci.dispatcher.build_url("admin", "network", "wireless") -]] - st = s:taboption("general", DummyValue, "__status", translate("Status")) st.template = "admin_network/wifi_status" st.ifname = arg[1] en = s:taboption("general", Button, "__toggle") -if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then - en.title = translate("Wireless network is disabled") - en.inputtitle = translate("Enable") - en.inputstyle = "apply" -else - en.title = translate("Wireless network is enabled") - en.inputtitle = translate("Disable") - en.inputstyle = "reset" -end - - local hwtype = wdev:get("type") -- NanoFoo @@ -170,9 +173,7 @@ if found_sta then found_sta.channel or "(auto)", table.concat(found_sta.names, ", ")) else ch = s:taboption("general", Value, "_mode_freq", '
'..translate("Operating frequency")) - ch.hwmodes = hw_modes - ch.htmodes = iw.htmodelist - ch.freqlist = iw.freqlist + ch.iwinfo = iw ch.template = "cbi/wireless_modefreq" function ch.cfgvalue(self, section) @@ -341,7 +342,6 @@ end ----------------------- Interface ----------------------- s = m:section(NamedSection, wnet.sid, "wifi-iface", translate("Interface Configuration")) -ifsection = s s.addremove = false s.anonymous = true s.defaults.device = wdev:name() @@ -1049,7 +1049,7 @@ if hwtype == "mac80211" then retry_timeout.rmempty = true end - local key_retries = s:taboption("encryption", Flag, "wpa_disable_eapol_key_retries", + key_retries = s:taboption("encryption", Flag, "wpa_disable_eapol_key_retries", translate("Enable key reinstallation (KRACK) countermeasures"), translate("Complicates key reinstallation attacks on the client side by disabling retransmission of EAPOL-Key frames that are used to install keys. This workaround might cause interoperability issues and reduced robustness of key negotiation especially in environments with heavy traffic load.")) diff --git a/luci-mod-admin-full/luasrc/view/admin_system/flashops.htm b/luci-mod-admin-full/luasrc/view/admin_system/flashops.htm index 3e3f65d91..b32ef7826 100644 --- a/luci-mod-admin-full/luasrc/view/admin_system/flashops.htm +++ b/luci-mod-admin-full/luasrc/view/admin_system/flashops.htm @@ -54,6 +54,9 @@ + <% if reset_avail then %> +
<%:Custom files (certificates, scripts) may remain on the system. To prevent this, perform a factory-reset first.%>
+ <% end %>
diff --git a/luci-mod-admin-full/luasrc/view/admin_system/packages.htm b/luci-mod-admin-full/luasrc/view/admin_system/packages.htm index d5d78289b..88e0fffd9 100644 --- a/luci-mod-admin-full/luasrc/view/admin_system/packages.htm +++ b/luci-mod-admin-full/luasrc/view/admin_system/packages.htm @@ -69,7 +69,7 @@ end <% if querypat then %>
<%:Displaying only packages containing%> "<%=pcdata(query)%>" - +
<% end %> diff --git a/luci-mod-admin-full/luasrc/view/admin_uci/apply.htm b/luci-mod-admin-full/luasrc/view/admin_uci/apply.htm deleted file mode 100644 index 370027e51..000000000 --- a/luci-mod-admin-full/luasrc/view/admin_uci/apply.htm +++ /dev/null @@ -1,23 +0,0 @@ -<%# - Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --%> - -<%+header%> - -

<%:Configuration%> / <%:Apply%>

- -<% if changes then %> - <%+cbi/apply_xhr%> - <%+admin_uci/changelog%> - - <%- cbi_apply_xhr('uci-apply', configs) -%> - -

<%:The following changes have been committed%>:

- <%- uci_changelog(changes) -%> -<% else %> -

<%:There are no pending changes to apply!%>

-<% end %> - -<%+footer%> diff --git a/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm b/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm index c3373604f..9e9ce2be2 100644 --- a/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm +++ b/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm @@ -1,40 +1,41 @@ <%# Copyright 2008 Steven Barth - Copyright 2008-2015 Jo-Philipp Wich + Copyright 2008-2018 Jo-Philipp Wich Licensed to the public under the Apache License 2.0. -%> <%+header%> +<%- + local node, redir_url = luci.dispatcher.lookup(luci.http.formvalue("redir")) + + include("cbi/apply_widget") + include("admin_uci/changelog") + + cbi_apply_widget(redir_url or url("admin/uci/changes")) +-%> +

<%:Configuration%> / <%:Changes%>

<% if changes then %> - <%+admin_uci/changelog%> <%- uci_changelog(changes) -%> <% else %>

<%:There are no pending changes!%>

<% end %> + +
- <% local r = luci.http.formvalue("redir"); if r and #r > 0 then %> + <% if redir_url then %>
-
+
<% end %>
-
- - " /> - -
-
- - " /> - -
+
" /> diff --git a/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm b/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm index 5da7281a8..dff53420a 100644 --- a/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm +++ b/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm @@ -1,27 +1,42 @@ <%# Copyright 2008 Steven Barth - Copyright 2008 Jo-Philipp Wich + Copyright 2008-2018 Jo-Philipp Wich Licensed to the public under the Apache License 2.0. -%> <%+header%> +<%- + local node, redir_url = luci.dispatcher.lookup(luci.http.formvalue("redir")) + + include("cbi/apply_widget") + include("admin_uci/changelog") + + cbi_apply_widget(redir_url or url("admin/uci/revert")) +-%> +

<%:Configuration%> / <%:Revert%>

<% if changes then %> - <%+cbi/apply_xhr%> - <%+admin_uci/changelog%> -

<%:The following changes have been reverted%>:

<%- uci_changelog(changes) -%> <% else %>

<%:There are no pending changes to revert!%>

<% end %> -
- "> - - -
+ + + +<% if redir_url then %> +
+
+ +
+
+<% end %> <%+footer%> diff --git a/luci-mod-admin-full/luasrc/view/cbi/wireless_modefreq.htm b/luci-mod-admin-full/luasrc/view/cbi/wireless_modefreq.htm index 2fb64b3c4..ebb02e489 100644 --- a/luci-mod-admin-full/luasrc/view/cbi/wireless_modefreq.htm +++ b/luci-mod-admin-full/luasrc/view/cbi/wireless_modefreq.htm @@ -1,9 +1,9 @@ <%+cbi/valueheader%>