diff options
Diffstat (limited to 'modules/luci-mod-status')
6 files changed, 477 insertions, 62 deletions
diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/channel_analysis.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/channel_analysis.js index 692c67e3cd..2ce22d5838 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/channel_analysis.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/channel_analysis.js @@ -97,21 +97,20 @@ return view.extend({ }) }, - create_channel_graph: function(chan_analysis, freq_tbl, freq) { - var is5GHz = freq == '5GHz', - columns = is5GHz ? freq_tbl.length * 4 : freq_tbl.length + 3, + create_channel_graph: function(chan_analysis, freq_tbl, band) { + var columns = (band != 2) ? freq_tbl.length * 4 : freq_tbl.length + 3, chan_graph = chan_analysis.graph, G = chan_graph.firstElementChild, step = (chan_graph.offsetWidth - 2) / columns, curr_offset = step; - function createGraphHLine(graph, pos) { + function createGraphHLine(graph, pos, width, dash) { var elem = document.createElementNS('http://www.w3.org/2000/svg', 'line'); elem.setAttribute('x1', pos); elem.setAttribute('y1', 0); elem.setAttribute('x2', pos); elem.setAttribute('y2', '100%'); - elem.setAttribute('style', 'stroke:black;stroke-width:0.1'); + elem.setAttribute('style', 'stroke:black;stroke-width:'+width+';stroke-dasharray:'+dash); graph.appendChild(elem); } @@ -126,40 +125,51 @@ return view.extend({ chan_analysis.col_width = step; - createGraphHLine(G,curr_offset); + createGraphHLine(G,curr_offset, 0.1, 1); for (var i=0; i< freq_tbl.length;i++) { var channel = freq_tbl[i] chan_analysis.offset_tbl[channel] = curr_offset+step; - createGraphHLine(G,curr_offset+step); - createGraphText(G,curr_offset+step, channel); + if (band != 2) { + createGraphHLine(G,curr_offset+step, 0.1, 3); + if (channel < 100) + createGraphText(G,curr_offset-(step/2), channel); + else + createGraphText(G,curr_offset-step, channel); + } else { + createGraphHLine(G,curr_offset+step, 0.1, 0); + createGraphText(G,curr_offset+step, channel); + } curr_offset += step; - if (is5GHz && freq_tbl[i+1]) { + if ((band != 2) && freq_tbl[i+1]) { var next_channel = freq_tbl[i+1]; - /* Check if we are transitioning to another 5Ghz band range */ + /* Check if we are transitioning to another 5/6Ghz band range */ if ((next_channel - channel) == 4) { for (var j=1; j < 4; j++) { chan_analysis.offset_tbl[channel+j] = curr_offset+step; - createGraphHLine(G,curr_offset+step); + if (j == 2) + createGraphHLine(G,curr_offset+step, 0.1, 0); + else + createGraphHLine(G,curr_offset+step, 0.1, 1); curr_offset += step; } } else { chan_analysis.offset_tbl[channel+1] = curr_offset+step; - createGraphHLine(G,curr_offset+step); + createGraphHLine(G,curr_offset+step, 0.1, 1); curr_offset += step; chan_analysis.offset_tbl[next_channel-2] = curr_offset+step; - createGraphHLine(G,curr_offset+step); + createGraphHLine(G,curr_offset+step, 0.5, 0); curr_offset += step; chan_analysis.offset_tbl[next_channel-1] = curr_offset+step; - createGraphHLine(G,curr_offset+step); + createGraphHLine(G,curr_offset+step, 0.1, 1); curr_offset += step; } } } - createGraphHLine(G,curr_offset+step); + createGraphHLine(G,curr_offset+step, 0.1, 1); chan_analysis.tab.addEventListener('cbi-tab-active', L.bind(function(ev) { this.active_tab = ev.detail.tab; @@ -182,7 +192,8 @@ return view.extend({ local_wifi = data[1], table = radio.table, chan_analysis = radio.graph, - scanCache = radio.scanCache; + scanCache = radio.scanCache, + band = radio.band; var rows = []; @@ -191,42 +202,45 @@ return view.extend({ scanCache[results[i].bssid] = {}; scanCache[results[i].bssid].data = results[i]; + scanCache[results[i].bssid].data.stale = false; } - if (scanCache[local_wifi.bssid] == null) - scanCache[local_wifi.bssid] = {}; - - scanCache[local_wifi.bssid].data = local_wifi; + if (band + 'g' == radio.dev.get('band')) { + if (scanCache[local_wifi.bssid] == null) + scanCache[local_wifi.bssid] = {}; - if (chan_analysis.offset_tbl[local_wifi.channel] != null && local_wifi.center_chan1) { - var center_channels = [local_wifi.center_chan1], - chan_width_text = local_wifi.htmode.replace(/(V)*H[TE]/,''), /* Handle HT VHT HE */ - chan_width = parseInt(chan_width_text)/10; + scanCache[local_wifi.bssid].data = local_wifi; - if (local_wifi.center_chan2) { - center_channels.push(local_wifi.center_chan2); - chan_width = 8; - } + if (chan_analysis.offset_tbl[local_wifi.channel] != null && local_wifi.center_chan1) { + var center_channels = [local_wifi.center_chan1], + chan_width_text = local_wifi.htmode.replace(/(V)*H[TE]/,''), /* Handle HT VHT HE */ + chan_width = parseInt(chan_width_text)/10; - local_wifi.signal = -10; - local_wifi.ssid = 'Local Interface'; + if (local_wifi.center_chan2) { + center_channels.push(local_wifi.center_chan2); + chan_width = 8; + } - this.add_wifi_to_graph(chan_analysis, local_wifi, scanCache, center_channels, chan_width); - rows.push([ - this.render_signal_badge(q, local_wifi.signal), - [ - E('span', { 'style': 'color:'+scanCache[local_wifi.bssid].color }, '⬤ '), - local_wifi.ssid - ], - '%d'.format(local_wifi.channel), - '%h MHz'.format(chan_width_text), - '%h'.format(local_wifi.mode), - '%h'.format(local_wifi.bssid) - ]); + local_wifi.signal = -10; + local_wifi.ssid = 'Local Interface'; + + this.add_wifi_to_graph(chan_analysis, local_wifi, scanCache, center_channels, chan_width); + rows.push([ + this.render_signal_badge(q, local_wifi.signal), + [ + E('span', { 'style': 'color:'+scanCache[local_wifi.bssid].color }, '⬤ '), + local_wifi.ssid + ], + '%d'.format(local_wifi.channel), + '%h MHz'.format(chan_width_text), + '%h'.format(local_wifi.mode), + '%h'.format(local_wifi.bssid) + ]); + } } for (var k in scanCache) - if (scanCache[k].stale) + if (scanCache[k].data.stale) results.push(scanCache[k].data); results.sort(function(a, b) { @@ -254,6 +268,8 @@ return view.extend({ chan_width = 2; /* Skip WiFi not supported by the current band */ + if (band != res.band) + continue; if (chan_analysis.offset_tbl[res.channel] == null) continue; @@ -302,7 +318,7 @@ return view.extend({ E('span', { 'style': s }, '%h'.format(res.bssid)) ]); - res.stale = true; + scanCache[results[i].bssid].data.stale = true; } cbi_update_table(table, rows); @@ -364,22 +380,20 @@ return view.extend({ var tabs = E('div', {}, E('div')); for (var ifname in wifiDevs) { - var freq_tbl = { - ['2.4GHz'] : [], - ['5GHz'] : [], + var bands = { + [2] : { title: '2.4GHz', channels: [] }, + [5] : { title: '5GHz', channels: [] }, + [6] : { title: '6GHz', channels: [] }, }; /* Split FrequencyList in Bands */ wifiDevs[ifname].freq.forEach(function(freq) { - if (freq.mhz >= 5000) { - freq_tbl['5GHz'].push(freq.channel); - } else { - freq_tbl['2.4GHz'].push(freq.channel); - } + if (bands[freq.band]) + bands[freq.band].channels.push(freq.channel); }); - for (var freq in freq_tbl) { - if (freq_tbl[freq].length == 0) + for (var band in bands) { + if (bands[band].channels.length == 0) continue; var csvg = svg.cloneNode(true), @@ -393,7 +407,7 @@ return view.extend({ E('th', { 'class': 'th col-3 middle left hide-xs' }, _('BSSID')) ]) ]), - tab = E('div', { 'data-tab': ifname+freq, 'data-tab-title': ifname+' ('+freq+')' }, + tab = E('div', { 'data-tab': ifname+band, 'data-tab-title': ifname+' ('+bands[band].title+')' }, [E('br'),csvg,E('br'),table,E('br')]), graph_data = { graph: csvg, @@ -402,8 +416,9 @@ return view.extend({ tab: tab, }; - this.radios[ifname+freq] = { + this.radios[ifname+band] = { dev: wifiDevs[ifname].dev, + band: band, graph: graph_data, table: table, scanCache: {}, @@ -414,7 +429,7 @@ return view.extend({ tabs.firstElementChild.appendChild(tab) - requestAnimationFrame(L.bind(this.create_channel_graph, this, graph_data, freq_tbl[freq], freq)); + requestAnimationFrame(L.bind(this.create_channel_graph, this, graph_data, bands[band].channels, band)); } } diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/29_ports.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/29_ports.js new file mode 100644 index 0000000000..b511897921 --- /dev/null +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/29_ports.js @@ -0,0 +1,386 @@ +'use strict'; +'require baseclass'; +'require fs'; +'require ui'; +'require uci'; +'require rpc'; +'require network'; +'require firewall'; + +var callGetBuiltinEthernetPorts = rpc.declare({ + object: 'luci', + method: 'getBuiltinEthernetPorts', + expect: { result: [] } +}); + +function isString(v) +{ + return typeof(v) === 'string' && v !== ''; +} + +function resolveVLANChain(ifname, bridges, mapping) +{ + while (!mapping[ifname]) { + var m = ifname.match(/^(.+)\.([^.]+)$/); + + if (!m) + break; + + if (bridges[m[1]]) { + if (bridges[m[1]].vlan_filtering) + mapping[ifname] = bridges[m[1]].vlans[m[2]]; + else + mapping[ifname] = bridges[m[1]].ports; + } + else if (/^[0-9]{1,4}$/.test(m[2]) && m[2] <= 4095) { + mapping[ifname] = [ m[1] ]; + } + else { + break; + } + + ifname = m[1]; + } +} + +function buildVLANMappings(mapping) +{ + var bridge_vlans = uci.sections('network', 'bridge-vlan'), + vlan_devices = uci.sections('network', 'device'), + interfaces = uci.sections('network', 'interface'), + bridges = {}; + + /* find bridge VLANs */ + for (var i = 0, s; (s = bridge_vlans[i]) != null; i++) { + if (!isString(s.device) || !/^[0-9]{1,4}$/.test(s.vlan) || +s.vlan > 4095) + continue; + + var aliases = L.toArray(s.alias), + ports = L.toArray(s.ports), + br = bridges[s.device] = (bridges[s.device] || { ports: [], vlans: {}, vlan_filtering: true }); + + br.vlans[s.vlan] = []; + + for (var j = 0; j < ports.length; j++) { + var port = ports[j].replace(/:[ut*]+$/, ''); + + if (br.ports.indexOf(port) === -1) + br.ports.push(port); + + br.vlans[s.vlan].push(port); + } + + for (var j = 0; j < aliases.length; j++) + if (aliases[j] != s.vlan) + br.vlans[aliases[j]] = br.vlans[s.vlan]; + } + + /* find bridges, VLAN devices */ + for (var i = 0, s; (s = vlan_devices[i]) != null; i++) { + if (s.type == 'bridge') { + if (!isString(s.name)) + continue; + + var ports = L.toArray(s.ports), + br = bridges[s.name] || (bridges[s.name] = { ports: [], vlans: {}, vlan_filtering: false }); + + if (s.vlan_filtering == '0') + br.vlan_filtering = false; + else if (s.vlan_filtering == '1') + br.vlan_filtering = true; + + for (var j = 0; j < ports.length; j++) + if (br.ports.indexOf(ports[j]) === -1) + br.ports.push(ports[j]); + + mapping[s.name] = br.ports; + } + else if (s.type == '8021q' || s.type == '8021ad') { + if (!isString(s.name) || !isString(s.vid) || !isString(s.ifname)) + continue; + + /* parent device is a bridge */ + if (bridges[s.ifname]) { + /* parent bridge is VLAN enabled, device refers to VLAN ports */ + if (bridges[s.ifname].vlan_filtering) + mapping[s.name] = bridges[s.ifname].vlans[s.vid]; + + /* parent bridge is not VLAN enabled, device refers to all bridge ports */ + else + mapping[s.name] = bridges[s.ifname].ports; + } + + /* parent is a simple netdev */ + else { + mapping[s.name] = [ s.ifname ]; + } + + resolveVLANChain(s.ifname, bridges, mapping); + } + } + + /* resolve VLAN tagged interfaces in bridge ports */ + for (var brname in bridges) { + for (var i = 0; i < bridges[brname].ports.length; i++) + resolveVLANChain(bridges[brname].ports[i], bridges, mapping); + + for (var vid in bridges[brname].vlans) + for (var i = 0; i < bridges[brname].vlans[vid].length; i++) + resolveVLANChain(bridges[brname].vlans[vid][i], bridges, mapping); + } + + /* find implicit VLAN devices */ + for (var i = 0, s; (s = interfaces[i]) != null; i++) { + if (!isString(s.device)) + continue; + + resolveVLANChain(s.device, bridges, mapping); + } +} + +function resolveVLANPorts(ifname, mapping, seen) +{ + var ports = []; + + if (!seen) + seen = {}; + + if (mapping[ifname]) { + for (var i = 0; i < mapping[ifname].length; i++) { + if (!seen[mapping[ifname][i]]) { + seen[mapping[ifname][i]] = true; + ports.push.apply(ports, resolveVLANPorts(mapping[ifname][i], mapping, seen)); + } + } + } + else { + ports.push(ifname); + } + + return ports.sort(L.naturalCompare); +} + +function buildInterfaceMapping(zones, networks) { + var vlanmap = {}, + portmap = {}, + netmap = {}; + + buildVLANMappings(vlanmap); + + for (var i = 0; i < networks.length; i++) { + var l3dev = networks[i].getDevice(); + + if (!l3dev) + continue; + + var ports = resolveVLANPorts(l3dev.getName(), vlanmap); + + for (var j = 0; j < ports.length; j++) { + portmap[ports[j]] = portmap[ports[j]] || { networks: [], zones: [] }; + portmap[ports[j]].networks.push(networks[i]); + } + + netmap[networks[i].getName()] = networks[i]; + } + + for (var i = 0; i < zones.length; i++) { + var networknames = zones[i].getNetworks(); + + for (var j = 0; j < networknames.length; j++) { + if (!netmap[networknames[j]]) + continue; + + var l3dev = netmap[networknames[j]].getDevice(); + + if (!l3dev) + continue; + + var ports = resolveVLANPorts(l3dev.getName(), vlanmap); + + for (var k = 0; k < ports.length; k++) { + portmap[ports[k]] = portmap[ports[k]] || { networks: [], zones: [] }; + + if (portmap[ports[k]].zones.indexOf(zones[i]) === -1) + portmap[ports[k]].zones.push(zones[i]); + } + } + } + + return portmap; +} + +function formatSpeed(carrier, speed, duplex) { + if (speed && duplex) { + var d = (duplex == 'half') ? '\u202f(H)' : '', + e = E('span', { 'title': _('Speed: %d Mibit/s, Duplex: %s').format(speed, duplex) }); + + switch (speed) { + case 10: e.innerText = '10\u202fM' + d; break; + case 100: e.innerText = '100\u202fM' + d; break; + case 1000: e.innerText = '1\u202fGbE' + d; break; + case 2500: e.innerText = '2.5\u202fGbE'; break; + case 5000: e.innerText = '5\u202fGbE'; break; + case 10000: e.innerText = '10\u202fGbE'; break; + case 25000: e.innerText = '25\u202fGbE'; break; + case 40000: e.innerText = '40\u202fGbE'; break; + default: e.innerText = '%d\u202fMbE%s'.format(speed, d); + } + + return e; + } + + return carrier ? _('Connected') : _('no link'); +} + +function formatStats(portdev) { + var stats = portdev._devstate('stats') || {}; + + return ui.itemlist(E('span'), [ + _('Received bytes'), '%1024mB'.format(stats.rx_bytes), + _('Received packets'), '%1000mPkts.'.format(stats.rx_packets), + _('Received multicast'), '%1000mPkts.'.format(stats.multicast), + _('Receive errors'), '%1000mPkts.'.format(stats.rx_errors), + _('Receive dropped'), '%1000mPkts.'.format(stats.rx_dropped), + + _('Transmitted bytes'), '%1024mB'.format(stats.tx_bytes), + _('Transmitted packets'), '%1000mPkts.'.format(stats.tx_packets), + _('Transmit errors'), '%1000mPkts.'.format(stats.tx_errors), + _('Transmit dropped'), '%1000mPkts.'.format(stats.tx_dropped), + + _('Collisions seen'), stats.collisions + ]); +} + +function renderNetworkBadge(network, zonename) { + var l3dev = network.getDevice(); + var span = E('span', { 'class': 'ifacebadge', 'style': 'margin:.125em 0' }, [ + E('span', { + 'class': 'zonebadge', + 'title': zonename ? _('Part of zone %q').format(zonename) : _('No zone assigned'), + 'style': firewall.getZoneColorStyle(zonename) + }, '\u202f'), + '\u202f', network.getName(), ': ' + ]); + + if (l3dev) + span.appendChild(E('img', { + 'title': l3dev.getI18n(), + 'src': L.resource('icons/%s%s.png'.format(l3dev.getType(), l3dev.isUp() ? '' : '_disabled')) + })); + else + span.appendChild(E('em', _('(no interfaces attached)'))); + + return span; +} + +function renderNetworksTooltip(pmap) { + var res = [ null ], + zmap = {}; + + for (var i = 0; pmap && i < pmap.zones.length; i++) { + var networknames = pmap.zones[i].getNetworks(); + + for (var k = 0; k < networknames.length; k++) + zmap[networknames[k]] = pmap.zones[i].getName(); + } + + for (var i = 0; pmap && i < pmap.networks.length; i++) + res.push(E('br'), renderNetworkBadge(pmap.networks[i], zmap[pmap.networks[i].getName()])); + + if (res.length > 1) + res[0] = N_((res.length - 1) / 2, 'Part of network:', 'Part of networks:'); + else + res[0] = _('Port is not part of any network'); + + return E([], res); +} + +return baseclass.extend({ + title: _('Port status'), + + load: function() { + return Promise.all([ + L.resolveDefault(callGetBuiltinEthernetPorts(), []), + L.resolveDefault(fs.read('/etc/board.json'), '{}'), + firewall.getZones(), + network.getNetworks(), + uci.load('network') + ]); + }, + + render: function(data) { + if (L.hasSystemFeature('swconfig')) + return null; + + var board = JSON.parse(data[1]), + known_ports = [], + port_map = buildInterfaceMapping(data[2], data[3]); + + if (Array.isArray(data[0]) && data[0].length > 0) { + known_ports = data[0].map(port => ({ + ...port, + netdev: network.instantiateDevice(port.device) + })); + } + else { + if (L.isObject(board) && L.isObject(board.network)) { + for (var k = 'lan'; k != null; k = (k == 'lan') ? 'wan' : null) { + if (!L.isObject(board.network[k])) + continue; + + if (Array.isArray(board.network[k].ports)) + for (let i = 0; i < board.network[k].ports.length; i++) + known_ports.push({ + role: k, + device: board.network[k].ports[i], + netdev: network.instantiateDevice(board.network[k].ports[i]) + }); + else if (typeof(board.network[k].device) == 'string') + known_ports.push({ + role: k, + device: board.network[k].device, + netdev: network.instantiateDevice(board.network[k].device) + }); + } + } + } + + known_ports.sort(function(a, b) { + return L.naturalCompare(a.device, b.device); + }); + + return E('div', { 'style': 'display:grid;grid-template-columns:repeat(auto-fit, minmax(70px, 1fr));margin-bottom:1em' }, known_ports.map(function(port) { + var speed = port.netdev.getSpeed(), + duplex = port.netdev.getDuplex(), + carrier = port.netdev.getCarrier(), + pmap = port_map[port.netdev.getName()], + pzones = (pmap && pmap.zones.length) ? pmap.zones.sort(function(a, b) { return L.naturalCompare(a.getName(), b.getName()) }) : [ null ]; + + return E('div', { 'class': 'ifacebox', 'style': 'margin:.25em;min-width:70px;max-width:100px' }, [ + E('div', { 'class': 'ifacebox-head', 'style': 'font-weight:bold' }, [ port.netdev.getName() ]), + E('div', { 'class': 'ifacebox-body' }, [ + E('img', { 'src': L.resource('icons/port_%s.png').format(carrier ? 'up' : 'down') }), + E('br'), + formatSpeed(carrier, speed, duplex) + ]), + E('div', { 'class': 'ifacebox-head cbi-tooltip-container', 'style': 'display:flex' }, [ + E([], pzones.map(function(zone) { + return E('div', { + 'class': 'zonebadge', + 'style': 'cursor:help;flex:1;height:3px;opacity:' + (carrier ? 1 : 0.25) + ';' + firewall.getZoneColorStyle(zone) + }); + })), + E('span', { 'class': 'cbi-tooltip left' }, [ renderNetworksTooltip(pmap) ]) + ]), + E('div', { 'class': 'ifacebox-body' }, [ + E('div', { 'class': 'cbi-tooltip-container', 'style': 'text-align:left;font-size:80%' }, [ + '\u25b2\u202f%1024.1mB'.format(port.netdev.getTXBytes()), + E('br'), + '\u25bc\u202f%1024.1mB'.format(port.netdev.getRXBytes()), + E('span', { 'class': 'cbi-tooltip' }, formatStats(port.netdev)) + ]), + ]) + ]); + })); + } +}); diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js index 956c1b20f9..4c52916423 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js @@ -82,7 +82,7 @@ return baseclass.extend({ } }; - var table = E('table', { 'class': 'table lases' }, [ + var table = E('table', { 'id': 'status_leases', 'class': 'table lases' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th' }, _('Hostname')), E('th', { 'class': 'th' }, _('IPv4 address')), @@ -129,7 +129,7 @@ return baseclass.extend({ return rows; }, this)), E('em', _('There are no active leases'))); - var table6 = E('table', { 'class': 'table leases6' }, [ + var table6 = E('table', { 'id': 'status_leases6', 'class': 'table leases6' }, [ E('tr', { 'class': 'tr table-titles' }, [ E('th', { 'class': 'th' }, _('Host')), E('th', { 'class': 'th' }, _('IPv6 address')), diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js index 951c31218d..917dada57a 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/iptables.js @@ -173,7 +173,7 @@ return view.extend({ srcnet, dstnet, options, - [ comment ] + [ comment, '%h'.format(comment) ] ]); if (target) { @@ -252,7 +252,11 @@ return view.extend({ elem = document.getElementById('rule_%s_%s'.format(table.toLowerCase(), chain)); if (elem) { - (document.documentElement || document.body.parentNode || document.body).scrollTop = elem.offsetTop - 40; + if (elem.scrollIntoView) { + elem.scrollIntoView(); + } else { + (document.documentElement || document.body.parentNode || document.body).scrollTop = elem.offsetTop - 40; + } elem.classList.remove('flash'); void elem.offsetWidth; elem.classList.add('flash'); diff --git a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/nftables.js b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/nftables.js index d891526d04..be62d91350 100644 --- a/modules/luci-mod-status/htdocs/luci-static/resources/view/status/nftables.js +++ b/modules/luci-mod-status/htdocs/luci-static/resources/view/status/nftables.js @@ -9,7 +9,7 @@ var expr_translations = { 'meta.iifname': _('Ingress device name', 'nft meta iifname'), 'meta.oifname': _('Egress device name', 'nft meta oifname'), 'meta.iif': _('Ingress device id', 'nft meta iif'), - 'meta.iif': _('Egress device id', 'nft meta oif'), + 'meta.oif': _('Egress device id', 'nft meta oif'), 'meta.l4proto': _('IP protocol', 'nft meta l4proto'), 'meta.l4proto.tcp': 'TCP', diff --git a/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json b/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json index 7c2cd0998f..20cd23bb6c 100644 --- a/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json +++ b/modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status-index.json @@ -3,6 +3,7 @@ "description": "Grant access to main status display", "read": { "file": { + "/etc/board.json": [ "read" ], "/proc/sys/net/netfilter/nf_conntrack_count": [ "read" ], "/proc/sys/net/netfilter/nf_conntrack_max": [ "read" ], "/www/luci-static/resources/view/status/include": [ "list" ] @@ -36,6 +37,15 @@ } }, + "luci-mod-status-index-ports": { + "description": "Grant access to port status display", + "read": { + "ubus": { + "luci": [ "getBuiltinEthernetPorts" ] + } + } + }, + "luci-mod-status-index-wifi": { "description": "Grant access to wireless status display", "read": { |