diff options
Diffstat (limited to 'modules')
4 files changed, 203 insertions, 11 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/firewall.js b/modules/luci-base/htdocs/luci-static/resources/firewall.js index d034d6e010..9ae14e16d9 100644 --- a/modules/luci-base/htdocs/luci-static/resources/firewall.js +++ b/modules/luci-base/htdocs/luci-static/resources/firewall.js @@ -375,6 +375,14 @@ Zone = AbstractFirewallItem.extend({ this.set('network', ' '); }, + getDevices: function() { + return L.toArray(this.get('device')); + }, + + getSubnets: function() { + return L.toArray(this.get('subnet')); + }, + getForwardingsBy: function(what) { var sections = uci.sections('firewall', 'forwarding'), forwards = []; diff --git a/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js b/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js index 3de1f8258e..39e5aa1655 100644 --- a/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js +++ b/modules/luci-base/htdocs/luci-static/resources/tools/widgets.js @@ -199,10 +199,16 @@ var CBIZoneForwards = form.DummyValue.extend({ __name__: 'CBI.ZoneForwards', load: function(section_id) { - return Promise.all([ firewall.getDefaults(), firewall.getZones(), network.getNetworks() ]).then(L.bind(function(dzn) { - this.defaults = dzn[0]; - this.zones = dzn[1]; - this.networks = dzn[2]; + return Promise.all([ + firewall.getDefaults(), + firewall.getZones(), + network.getNetworks(), + network.getDevices() + ]).then(L.bind(function(dznd) { + this.defaults = dznd[0]; + this.zones = dznd[1]; + this.networks = dznd[2]; + this.devices = dznd[3]; return this.super('load', section_id); }, this)); @@ -211,6 +217,8 @@ var CBIZoneForwards = form.DummyValue.extend({ renderZone: function(zone) { var name = zone.getName(), networks = zone.getNetworks(), + devices = zone.getDevices(), + subnets = zone.getSubnets(), ifaces = []; for (var j = 0; j < networks.length; j++) { @@ -223,21 +231,39 @@ var CBIZoneForwards = form.DummyValue.extend({ 'class': 'ifacebadge' + (network.getName() == this.network ? ' ifacebadge-active' : '') }, network.getName() + ': '); - var devices = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice()); + var subdevs = network.isBridge() ? network.getDevices() : L.toArray(network.getDevice()); - for (var k = 0; k < devices.length && devices[k]; k++) { + for (var k = 0; k < subdevs.length && subdevs[k]; k++) { span.appendChild(E('img', { - 'title': devices[k].getI18n(), - 'src': L.resource('icons/%s%s.png'.format(devices[k].getType(), devices[k].isUp() ? '' : '_disabled')) + 'title': subdevs[k].getI18n(), + 'src': L.resource('icons/%s%s.png'.format(subdevs[k].getType(), subdevs[k].isUp() ? '' : '_disabled')) })); } - if (!devices.length) + if (!subdevs.length) span.appendChild(E('em', _('(empty)'))); ifaces.push(span); } + for (var i = 0; i < devices.length; i++) { + var device = this.devices.filter(function(dev) { return dev.getName() == devices[i] })[0], + title = device ? device.getI18n() : _('Absent Interface'), + type = device ? device.getType() : 'ethernet', + up = device ? device.isUp() : false; + + ifaces.push(E('span', { 'class': 'ifacebadge' }, [ + E('img', { + 'title': title, + 'src': L.resource('icons/%s%s.png'.format(type, up ? '' : '_disabled')) + }), + device ? device.getName() : devices[i] + ])); + } + + if (subnets.length > 0) + ifaces.push(E('span', { 'class': 'ifacebadge' }, [ '{ %s }'.format(subnets.join('; ')) ])); + if (!ifaces.length) ifaces.push(E('span', { 'class': 'ifacebadge' }, E('em', _('(empty)')))); @@ -390,9 +416,120 @@ var CBINetworkSelect = form.ListValue.extend({ }, }); +var CBIDeviceSelect = form.ListValue.extend({ + __name__: 'CBI.DeviceSelect', + + load: function(section_id) { + return network.getDevices().then(L.bind(function(devices) { + this.devices = devices; + + return this.super('load', section_id); + }, this)); + }, + + filter: function(section_id, value) { + return true; + }, + + renderWidget: function(section_id, option_index, cfgvalue) { + var values = L.toArray((cfgvalue != null) ? cfgvalue : this.default), + choices = {}, + checked = {}, + order = []; + + for (var i = 0; i < values.length; i++) + checked[values[i]] = true; + + values = []; + + if (!this.multiple && (this.rmempty || this.optional)) + choices[''] = E('em', _('unspecified')); + + for (var i = 0; i < this.devices.length; i++) { + var device = this.devices[i], + name = device.getName(), + type = device.getType(); + + if (name == 'lo' || name == this.exclude || !this.filter(section_id, name)) + continue; + + if (this.noaliases && type == 'alias') + continue; + + if (this.nobridges && type == 'bridge') + continue; + + if (this.noinactive && device.isUp() == false) + continue; + + var item = E([ + E('img', { + 'title': device.getI18n(), + 'src': L.resource('icons/%s%s.png'.format(type, device.isUp() ? '' : '_disabled')) + }), + E('span', { 'class': 'hide-open' }, [ name ]), + E('span', { 'class': 'hide-close'}, [ device.getI18n() ]) + ]); + + var networks = device.getNetworks(); + + if (networks.length > 0) + L.dom.append(item.lastChild, [ ' (', networks.join(', '), ')' ]); + + if (checked[name]) + values.push(name); + + choices[name] = item; + order.push(name); + } + + if (!this.nocreate) { + var keys = Object.keys(checked).sort(); + + for (var i = 0; i < keys.length; i++) { + if (choices.hasOwnProperty(keys[i])) + continue; + + choices[keys[i]] = E([ + E('img', { + 'title': _('Absent Interface'), + 'src': L.resource('icons/ethernet_disabled.png') + }), + E('span', { 'class': 'hide-open' }, [ keys[i] ]), + E('span', { 'class': 'hide-close'}, [ '%s: "%h"'.format(_('Absent Interface'), keys[i]) ]) + ]); + + values.push(keys[i]); + order.push(keys[i]); + } + } + + var widget = new ui.Dropdown(this.multiple ? values : values[0], choices, { + id: this.cbid(section_id), + sort: order, + multiple: this.multiple, + optional: this.optional || this.rmempty, + select_placeholder: E('em', _('unspecified')), + display_items: this.display_size || this.size || 3, + dropdown_items: this.dropdown_size || this.size || 5, + validate: L.bind(this.validate, this, section_id), + create: !this.nocreate, + create_markup: '' + + '<li data-value="{{value}}">' + + '<img title="'+_('Custom Interface')+': "{{value}}"" src="'+L.resource('icons/ethernet_disabled.png')+'" />' + + '<span class="hide-open">{{value}}</span>' + + '<span class="hide-close">'+_('Custom Interface')+': "{{value}}"</span>' + + '</li>' + }); + + return widget.render(); + }, +}); + return L.Class.extend({ ZoneSelect: CBIZoneSelect, ZoneForwards: CBIZoneForwards, - NetworkSelect: CBINetworkSelect + NetworkSelect: CBINetworkSelect, + DeviceSelect: CBIDeviceSelect, }); diff --git a/modules/luci-base/root/usr/libexec/rpcd/luci b/modules/luci-base/root/usr/libexec/rpcd/luci index 55233d6d0a..7644745efd 100755 --- a/modules/luci-base/root/usr/libexec/rpcd/luci +++ b/modules/luci-base/root/usr/libexec/rpcd/luci @@ -285,6 +285,41 @@ local methods = { local fs = require "nixio.fs" return { offload_support = not not fs.access("/sys/module/xt_FLOWOFFLOAD/refcnt") } end + }, + + conntrack_helpers = { + call = function() + local fd = io.open("/usr/share/fw3/helpers.conf", "r") + local rv = {} + + local line, entry + while true do + line = fd:read("*l") + if not line then + break + end + + if line:match("^%s*config%s") then + if entry then + rv[#rv+1] = entry + end + entry = {} + else + local opt, val = line:match("^%s*option%s+(%S+)%s+(%S.*)$") + if opt and val then + opt = opt:gsub("^'(.+)'$", "%1"):gsub('^"(.+)"$', "%1") + val = val:gsub("^'(.+)'$", "%1"):gsub('^"(.+)"$', "%1") + entry[opt] = val + end + end + end + + if entry then + rv[#rv+1] = entry + end + + return { helpers = 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 a9baef8f9c..de145ce784 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 @@ -13,7 +13,7 @@ "read": { "ubus": { "iwinfo": [ "info" ], - "luci": [ "boardjson", "duid_hints", "host_hints", "ifaddrs", "initList", "getLocaltime", "leases", "leds", "netdevs", "offload_support", "usb" ], + "luci": [ "boardjson", "duid_hints", "host_hints", "ifaddrs", "initList", "getLocaltime", "leases", "leds", "netdevs", "usb" ], "network.device": [ "status" ], "network.interface": [ "dump" ], "network.wireless": [ "status" ], @@ -28,5 +28,17 @@ }, "uci": [ "*" ] } + }, + "luci-app-firewall": { + "description": "Grant access to firewall procedures", + "read": { + "ubus": { + "luci": [ "conntrack_helpers", "offload_support" ] + }, + "uci": [ "firewall" ] + }, + "write": { + "uci": [ "firewall" ] + } } } |