From: Jo-Philipp Wich Date: Wed, 14 Aug 2019 14:42:55 +0000 (+0200) Subject: luci-base: luci.js: introduce hasSystemFeature() api X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=a4621c95201a6ac436b3cfdc9bf6ed2d2571e607;p=oweals%2Fluci.git luci-base: luci.js: introduce hasSystemFeature() api The new function allows querying the presence of certain system features such as dnsmasq or firewall availability or the compile time features of hostapd and wpa_supplicant. Signed-off-by: Jo-Philipp Wich --- diff --git a/modules/luci-base/htdocs/luci-static/resources/luci.js b/modules/luci-base/htdocs/luci-static/resources/luci.js index 66f32d722..d72764b11 100644 --- a/modules/luci-base/htdocs/luci-static/resources/luci.js +++ b/modules/luci-base/htdocs/luci-static/resources/luci.js @@ -559,6 +559,7 @@ domParser = null, originalCBIInit = null, rpcBaseURL = null, + sysFeatures = null, classes = {}; var LuCI = Class.extend({ @@ -797,6 +798,43 @@ return Promise.resolve(rpcBaseURL); }, + probeSystemFeatures: function() { + if (sysFeatures == null) { + try { + sysFeatures = JSON.parse(window.sessionStorage.getItem('sysFeatures')); + } + catch (e) {} + } + + if (!this.isObject(sysFeatures)) { + sysFeatures = classes.rpc.declare({ + object: 'luci', + method: 'getFeatures', + expect: { '': {} } + })().then(function(features) { + try { + window.sessionStorage.setItem('sysFeatures', JSON.stringify(features)); + } + catch (e) {} + + sysFeatures = features; + + return features; + }); + } + + return Promise.resolve(sysFeatures); + }, + + hasSystemFeature: function() { + var ft = sysFeatures[arguments[0]]; + + if (arguments.length == 2) + return this.isObject(ft) ? ft[arguments[1]] : null; + + return (ft != null && ft != false); + }, + setupDOM: function(res) { var domEv = res[0], uiClass = res[1], @@ -828,10 +866,12 @@ throw 'Session expired'; }); - originalCBIInit(); + return this.probeSystemFeatures().finally(this.initDOM); + }, + initDOM: function() { + originalCBIInit(); Poll.start(); - document.dispatchEvent(new CustomEvent('luci-loaded')); }, diff --git a/modules/luci-base/root/usr/libexec/rpcd/luci b/modules/luci-base/root/usr/libexec/rpcd/luci index 7644745ef..d2e90bc35 100755 --- a/modules/luci-base/root/usr/libexec/rpcd/luci +++ b/modules/luci-base/root/usr/libexec/rpcd/luci @@ -320,6 +320,92 @@ local methods = { return { helpers = rv } end + }, + + getFeatures = { + call = function() + local fs = require "nixio.fs" + local rv = {} + local ok, fd + + rv.firewall = fs.access("/sbin/fw3") + rv.opkg = fs.access("/bin/opkg") + rv.offloading = fs.access("/sys/module/xt_FLOWOFFLOAD/refcnt") + rv.br2684ctl = fs.access("/usr/sbin/br2684ctl") + rv.swconfig = fs.access("/sbin/swconfig") + rv.odhcpd = fs.access("/usr/sbin/odhcpd") + + local wifi_features = { "eap", "11n", "11ac", "11r", "11w", "acs", "sae", "owe", "suiteb192" } + + if fs.access("/usr/sbin/hostapd") then + rv.hostapd = {} + + local _, feature + for _, feature in ipairs(wifi_features) do + rv.hostapd[feature] = + (os.execute(string.format("/usr/sbin/hostapd -v%s >/dev/null 2>/dev/null", feature)) == 0) + end + end + + if fs.access("/usr/sbin/wpa_supplicant") then + rv.wpasupplicant = {} + + local _, feature + for _, feature in ipairs(wifi_features) do + rv.wpasupplicant[feature] = + (os.execute(string.format("/usr/sbin/wpa_supplicant -v%s >/dev/null 2>/dev/null", feature)) == 0) + end + end + + ok, fd = pcall(io.popen, "dnsmasq --version 2>/dev/null") + if ok then + rv.dnsmasq = {} + + while true do + local line = fd:read("*l") + if not line then + break + end + + local opts = line:match("^Compile time options: (.+)$") + if opts then + local opt + for opt in opts:gmatch("%S+") do + local no = opt:match("^no%-(%S+)$") + rv.dnsmasq[string.lower(no or opt)] = not no + end + break + end + end + + fd:close() + end + + ok, fd = pcall(io.popen, "ipset --help 2>/dev/null") + if ok then + rv.ipset = {} + + local sets = false + + while true do + local line = fd:read("*l") + if not line then + break + elseif line:match("^Supported set types:") then + sets = true + elseif sets then + local set, ver = line:match("^%s+(%S+)%s+(%d+)") + if set and not rv.ipset[set] then + rv.ipset[set] = tonumber(ver) + end + end + end + + fd:close() + end + + return rv + end } } diff --git a/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json b/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json index e58c9947b..5d08a4eab 100644 --- a/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json +++ b/modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json @@ -1,4 +1,13 @@ { + "unauthenticated": { + "description": "Allow system feature probing", + "read": { + "ubus": { + "luci": [ "getFeatures" ] + } + } + }, + "uci-access": { "description": "Grant uci write access to all configurations", "read": {