summaryrefslogtreecommitdiffhomepage
path: root/applications/luci-app-firewall/htdocs/luci-static
diff options
context:
space:
mode:
Diffstat (limited to 'applications/luci-app-firewall/htdocs/luci-static')
-rw-r--r--applications/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js63
-rw-r--r--applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js2
-rw-r--r--applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js24
-rw-r--r--applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js43
-rw-r--r--applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js27
-rw-r--r--applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js87
6 files changed, 158 insertions, 88 deletions
diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js b/applications/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js
index 32998c2ff8..03e505e89d 100644
--- a/applications/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js
+++ b/applications/luci-app-firewall/htdocs/luci-static/resources/tools/firewall.js
@@ -392,12 +392,25 @@ return baseclass.extend({
},
transformHostHints: function(family, hosts) {
- var choice_values = [], choice_labels = {};
+ var choice_values = [],
+ choice_labels = {},
+ ip6addrs = {},
+ ipaddrs = {};
+
+ for (var mac in hosts) {
+ L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4).forEach(function(ip) {
+ ipaddrs[ip] = mac;
+ });
+
+ L.toArray(hosts[mac].ip6addrs || hosts[mac].ipv6).forEach(function(ip) {
+ ip6addrs[ip] = mac;
+ });
+ }
if (!family || family == 'ipv4') {
- L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
- var val = hosts[mac].ipv4,
- txt = hosts[mac].name || mac;
+ L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ip) {
+ var val = ip,
+ txt = hosts[ipaddrs[ip]].name || ipaddrs[ip];
choice_values.push(val);
choice_labels[val] = E([], [ val, ' (', E('strong', {}, [txt]), ')' ]);
@@ -405,9 +418,9 @@ return baseclass.extend({
}
if (!family || family == 'ipv6') {
- L.sortedKeys(hosts, 'ipv6', 'addr').forEach(function(mac) {
- var val = hosts[mac].ipv6,
- txt = hosts[mac].name || mac;
+ L.sortedKeys(ip6addrs, null, 'addr').forEach(function(ip) {
+ var val = ip,
+ txt = hosts[ip6addrs[ip]].name || ip6addrs[ip];
choice_values.push(val);
choice_labels[val] = E([], [ val, ' (', E('strong', {}, [txt]), ')' ]);
@@ -425,11 +438,26 @@ return baseclass.extend({
opt.addChoices(choices[0], choices[1]);
},
+ CBIDynamicMultiValueList: form.DynamicList.extend({
+ renderWidget: function(/* ... */) {
+ var dl = form.DynamicList.prototype.renderWidget.apply(this, arguments),
+ inst = dom.findClassInstance(dl);
+
+ inst.addItem = function(dl, value, text, flash) {
+ var values = L.toArray(value);
+ for (var i = 0; i < values.length; i++)
+ ui.DynamicList.prototype.addItem.call(this, dl, values[i], null, true);
+ };
+
+ return dl;
+ }
+ }),
+
addIPOption: function(s, tab, name, label, description, family, hosts, multiple) {
- var o = s.taboption(tab, multiple ? form.DynamicList : form.Value, name, label, description);
+ var o = s.taboption(tab, multiple ? this.CBIDynamicMultiValueList : form.Value, name, label, description);
o.modalonly = true;
- o.datatype = 'list(neg(ipmask))';
+ o.datatype = 'list(neg(ipmask("true")))';
o.placeholder = multiple ? _('-- add IP --') : _('any');
if (family != null) {
@@ -474,7 +502,7 @@ return baseclass.extend({
},
addMACOption: function(s, tab, name, label, description, hosts) {
- var o = s.taboption(tab, form.DynamicList, name, label, description);
+ var o = s.taboption(tab, this.CBIDynamicMultiValueList, name, label, description);
o.modalonly = true;
o.datatype = 'list(macaddr)';
@@ -482,7 +510,10 @@ return baseclass.extend({
L.sortedKeys(hosts).forEach(function(mac) {
o.value(mac, E([], [ mac, ' (', E('strong', {}, [
- hosts[mac].name || hosts[mac].ipv4 || hosts[mac].ipv6 || '?'
+ hosts[mac].name ||
+ L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0] ||
+ L.toArray(hosts[mac].ip6addrs || hosts[mac].ipv6)[0] ||
+ '?'
]), ')' ]));
});
@@ -522,6 +553,9 @@ return baseclass.extend({
}
}, this));
+ if (cfgvalue == '*' || cfgvalue == 'any' || cfgvalue == 'all')
+ cfgvalue = 'all';
+
return cfgvalue;
},
@@ -556,8 +590,7 @@ return baseclass.extend({
});
widget.createChoiceElement = function(sb, value) {
- var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
- p = lookupProto(lookupProto(m ? +m[1] : value)[0]);
+ var p = lookupProto(value);
return ui.Dropdown.prototype.createChoiceElement.call(this, sb, p[2], p[1]);
};
@@ -567,9 +600,11 @@ return baseclass.extend({
var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
p = lookupProto(m ? +m[1] : value);
- return (p[0] > -1) ? p[2] : value;
+ return (p[0] > -1) ? p[2] : p[1];
});
+ values.sort();
+
return ui.Dropdown.prototype.createItems.call(this, sb, values.join(' '));
};
diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js
index ca870552a6..1997a720c6 100644
--- a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js
+++ b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/custom.js
@@ -24,7 +24,7 @@ return view.extend({
return E([
E('h2', _('Firewall - Custom Rules')),
E('p', {}, _('Custom rules allow you to execute arbitrary iptables commands which are not otherwise covered by the firewall framework. The commands are executed after each firewall restart, right after the default ruleset has been loaded.')),
- E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 10 }, [ fwuser != null ? fwuser : '' ]))
+ E('p', {}, E('textarea', { 'style': 'width:100%', 'rows': 25 }, [ fwuser != null ? fwuser : '' ]))
]);
},
diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js
index 82703c320e..cbd4362049 100644
--- a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js
+++ b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js
@@ -46,7 +46,7 @@ function rule_src_txt(s, hosts) {
var z = uci.get('firewall', s, 'src');
return fwtool.fmt(_('From %{src}%{src_ip?, IP %{src_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{src_port?, port %{src_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}%{src_mac?, MAC %{src_mac#%{next?, }<var%{item.inv? data-tooltip="Match MACs except %{item.val}%{item.hint.name? a.k.a. %{item.hint.name}}.":%{item.hint.name? data-tooltip="%{item.hint.name}"}}>%{item.ival}</var>}}'), {
- src: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
+ src: E('span', { 'class': 'zonebadge', 'style': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
src_ip: fwtool.map_invert(uci.get('firewall', s, 'src_ip'), 'toLowerCase'),
src_mac: fwtool.map_invert(uci.get('firewall', s, 'src_mac'), 'toUpperCase').map(function(v) { return Object.assign(v, { hint: hosts[v.val] }) }),
src_port: fwtool.map_invert(uci.get('firewall', s, 'src_port'))
@@ -55,7 +55,7 @@ function rule_src_txt(s, hosts) {
function rule_dest_txt(s) {
return fwtool.fmt(_('To %{dest}%{dest_ip?, IP %{dest_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{dest_port?, port %{dest_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
- dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName(null) }, [E('em', _('this device'))]),
+ dest: E('span', { 'class': 'zonebadge', 'style': fwmodel.getZoneColorStyle(null) }, [E('em', _('this device'))]),
dest_ip: fwtool.map_invert(uci.get('firewall', s, 'src_dip'), 'toLowerCase'),
dest_port: fwtool.map_invert(uci.get('firewall', s, 'src_dport'))
});
@@ -79,7 +79,7 @@ function rule_target_txt(s) {
var z = uci.get('firewall', s, 'dest');
return fwtool.fmt(_('<var data-tooltip="DNAT">Forward</var> to %{dest}%{dest_ip? IP <var>%{dest_ip}</var>}%{dest_port? port <var>%{dest_port}</var>}'), {
- dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
+ dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
dest_ip: (uci.get('firewall', s, 'dest_ip') || '').toLowerCase(),
dest_port: uci.get('firewall', s, 'dest_port')
});
@@ -149,9 +149,10 @@ return view.extend({
var config_name = this.uciconfig || this.map.config,
section_id = uci.add(config_name, this.sectiontype);
+ uci.set(config_name, section_id, 'dest', 'lan');
uci.set(config_name, section_id, 'target', 'DNAT');
- this.addedSection = section_id;
+ m.addedSection = section_id;
this.renderMoreOptionsModal(section_id);
};
@@ -201,7 +202,7 @@ return view.extend({
o = fwtool.addIPOption(s, 'advanced', 'src_ip', _('Source IP address'),
_('Only match incoming traffic from this IP or range.'), 'ipv4', hosts);
o.rmempty = true;
- o.datatype = 'neg(ipmask4)';
+ o.datatype = 'neg(ipmask4("true"))';
o = s.taboption('advanced', form.Value, 'src_port', _('Source port'),
_('Only match incoming traffic originating from the given source port or port range on the client host'));
@@ -214,7 +215,7 @@ return view.extend({
o = fwtool.addLocalIPOption(s, 'advanced', 'src_dip', _('External IP address'),
_('Only match incoming traffic directed at the given IP address.'), devs);
- o.datatype = 'neg(ipmask4)';
+ o.datatype = 'neg(ipmask4("true"))';
o.rmempty = true;
o = s.taboption('general', form.Value, 'src_dport', _('External port'),
@@ -229,7 +230,6 @@ return view.extend({
o.modalonly = true;
o.rmempty = true;
o.nocreate = true;
- o.default = 'lan';
o = fwtool.addIPOption(s, 'general', 'dest_ip', _('Internal IP address'),
_('Redirect matched incoming traffic to the specified internal host'), 'ipv4', hosts);
@@ -281,10 +281,12 @@ return view.extend({
fwtool.addLimitOption(s);
fwtool.addLimitBurstOption(s);
- o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
- _('Passes additional arguments to iptables. Use with care!'));
- o.modalonly = true;
- o.rmempty = true;
+ if (!L.hasSystemFeature('firewall4')) {
+ o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
+ _('Passes additional arguments to iptables. Use with care!'));
+ o.modalonly = true;
+ o.rmempty = true;
+ }
return m.render();
}
diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js
index 8cb1a1242b..2afb438969 100644
--- a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js
+++ b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js
@@ -62,7 +62,7 @@ function rule_src_txt(s, hosts) {
d = (uci.get('firewall', s, 'direction') == 'in') ? uci.get('firewall', s, 'device') : null;
return fwtool.fmt(_('From %{src}%{src_device?, interface <var>%{src_device}</var>}%{src_ip?, IP %{src_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{src_port?, port %{src_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}%{src_mac?, MAC %{src_mac#%{next?, }<var%{item.inv? data-tooltip="Match MACs except %{item.val}%{item.hint.name? a.k.a. %{item.hint.name}}.":%{item.hint.name? data-tooltip="%{item.hint.name}"}}>%{item.ival}</var>}}'), {
- src: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
+ src: E('span', { 'class': 'zonebadge', 'style': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
src_ip: fwtool.map_invert(uci.get('firewall', s, 'src_ip'), 'toLowerCase'),
src_mac: fwtool.map_invert(uci.get('firewall', s, 'src_mac'), 'toUpperCase').map(function(v) { return Object.assign(v, { hint: hosts[v.val] }) }),
src_port: fwtool.map_invert(uci.get('firewall', s, 'src_port')),
@@ -75,7 +75,7 @@ function rule_dest_txt(s) {
d = (uci.get('firewall', s, 'direction') == 'out') ? uci.get('firewall', s, 'device') : null;
return fwtool.fmt(_('To %{dest}%{dest_device?, interface <var>%{dest_device}</var>}%{dest_ip?, IP %{dest_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{dest_port?, port %{dest_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
- dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
+ dest: E('span', { 'class': 'zonebadge', 'style': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
dest_ip: fwtool.map_invert(uci.get('firewall', s, 'dest_ip'), 'toLowerCase'),
dest_port: fwtool.map_invert(uci.get('firewall', s, 'dest_port')),
dest_device: d
@@ -193,13 +193,8 @@ return view.extend({
s.handleAdd = function(ev) {
var config_name = this.uciconfig || this.map.config,
section_id = uci.add(config_name, this.sectiontype),
- opt1, opt2;
-
- for (var i = 0; i < this.children.length; i++)
- if (this.children[i].option == 'src')
- opt1 = this.children[i];
- else if (this.children[i].option == 'dest')
- opt2 = this.children[i];
+ opt1 = this.getOption('src'),
+ opt2 = this.getOption('dest');
opt1.default = 'wan';
opt2.default = 'lan';
@@ -236,7 +231,19 @@ return view.extend({
o.modalonly = false;
o.default = o.enabled;
o.editable = true;
+ o.tooltip = function(section_id) {
+ var weekdays = uci.get('firewall', section_id, 'weekdays');
+ var monthdays = uci.get('firewall', section_id, 'monthdays');
+ var start_time = uci.get('firewall', section_id, 'start_time');
+ var stop_time = uci.get('firewall', section_id, 'stop_time');
+ var start_date = uci.get('firewall', section_id, 'start_date');
+ var stop_date = uci.get('firewall', section_id, 'stop_date');
+ if (weekdays || monthdays || start_time || stop_time || start_date || stop_date )
+ return _('Time restritions are enabled for this rule');
+
+ return null;
+ };
o = s.taboption('advanced', form.ListValue, 'direction', _('Match device'));
o.modalonly = true;
@@ -291,6 +298,8 @@ return view.extend({
o.value('', 'any');
o.value('address-mask-reply');
o.value('address-mask-request');
+ o.value('address-unreachable'); /* ipv6 */
+ o.value('bad-header'); /* ipv6 */
o.value('communication-prohibited');
o.value('destination-unreachable');
o.value('echo-reply');
@@ -308,6 +317,8 @@ return view.extend({
o.value('network-redirect');
o.value('network-unknown');
o.value('network-unreachable');
+ o.value('no-route'); /* ipv6 */
+ o.value('packet-too-big');
o.value('parameter-problem');
o.value('port-unreachable');
o.value('precedence-cutoff');
@@ -327,6 +338,8 @@ return view.extend({
o.value('TOS-network-unreachable');
o.value('ttl-zero-during-reassembly');
o.value('ttl-zero-during-transit');
+ o.value('unknown-header-type'); /* ipv6 */
+ o.value('unknown-option'); /* ipv6 */
o.depends({ proto: 'icmp', '!contains': true });
o.depends({ proto: 'icmpv6', '!contains': true });
@@ -419,9 +432,11 @@ return view.extend({
fwtool.addLimitOption(s);
fwtool.addLimitBurstOption(s);
- o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
- _('Passes additional arguments to iptables. Use with care!'));
- o.modalonly = true;
+ if (!L.hasSystemFeature('firewall4')) {
+ o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
+ _('Passes additional arguments to iptables. Use with care!'));
+ o.modalonly = true;
+ }
o = s.taboption('timed', form.MultiValue, 'weekdays', _('Week Days'));
o.modalonly = true;
@@ -450,11 +465,11 @@ return view.extend({
for (var i = 1; i <= 31; i++)
o.value(i);
- o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh.mm.ss)'));
+ o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh:mm:ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
- o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh.mm.ss)'));
+ o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh:mm:ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js
index 859dba3e88..e8c90a7574 100644
--- a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js
+++ b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js
@@ -37,7 +37,7 @@ function rule_src_txt(s, hosts) {
var z = uci.get('firewall', s, 'src');
return fwtool.fmt(_('From %{src}%{src_device?, interface <var>%{src_device}</var>}%{src_ip?, IP %{src_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{src_port?, port %{src_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
- src: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName(null) }, [E('em', _('any zone'))]),
+ src: E('span', { 'class': 'zonebadge', 'style': fwmodel.getZoneColorStyle(null) }, [E('em', _('any zone'))]),
src_ip: fwtool.map_invert(uci.get('firewall', s, 'src_ip'), 'toLowerCase'),
src_port: fwtool.map_invert(uci.get('firewall', s, 'src_port'))
});
@@ -47,7 +47,7 @@ function rule_dest_txt(s) {
var z = uci.get('firewall', s, 'src');
return fwtool.fmt(_('To %{dest}%{dest_device?, via interface <var>%{dest_device}</var>}%{dest_ip?, IP %{dest_ip#%{next?, }<var%{item.inv? data-tooltip="Match IP addresses except %{item.val}."}>%{item.ival}</var>}}%{dest_port?, port %{dest_port#%{next?, }<var%{item.inv? data-tooltip="Match ports except %{item.val}."}>%{item.ival}</var>}}'), {
- dest: E('span', { 'class': 'zonebadge', 'style': 'background-color:' + fwmodel.getColorForName((z && z != '*') ? z : null) }, [(z == '*') ? E('em', _('any zone')) : (z || E('em', _('this device')))]),
+ dest: E('span', { 'class': 'zonebadge', 'style': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
dest_ip: fwtool.map_invert(uci.get('firewall', s, 'dest_ip'), 'toLowerCase'),
dest_port: fwtool.map_invert(uci.get('firewall', s, 'dest_port')),
dest_device: uci.get('firewall', s, 'device')
@@ -180,7 +180,7 @@ return view.extend({
o = fwtool.addIPOption(s, 'general', 'src_ip', _('Source address'),
_('Match forwarded traffic from this IP or range.'), 'ipv4', hosts);
o.rmempty = true;
- o.datatype = 'neg(ipmask4)';
+ o.datatype = 'neg(ipmask4("true"))';
o = s.taboption('general', form.Value, 'src_port', _('Source port'),
_('Match forwarded traffic originating from the given source port or port range.'));
@@ -194,7 +194,7 @@ return view.extend({
o = fwtool.addIPOption(s, 'general', 'dest_ip', _('Destination address'),
_('Match forwarded traffic directed at the given IP address.'), 'ipv4', hosts);
o.rmempty = true;
- o.datatype = 'neg(ipmask4)';
+ o.datatype = 'neg(ipmask4("true"))';
o = s.taboption('general', form.Value, 'dest_port', _('Destination port'),
_('Match forwarded traffic directed at the given destination port or port range.'));
@@ -217,9 +217,8 @@ return view.extend({
o.placeholder = null;
o.depends('target', 'SNAT');
o.validate = function(section_id, value) {
- var port = this.map.lookupOption('snat_port', section_id),
- a = this.formvalue(section_id),
- p = port ? port[0].formvalue(section_id) : null;
+ var a = this.formvalue(section_id),
+ p = this.section.formvalue(section_id, 'snat_port');
if ((a == null || a == '') && (p == null || p == '') && value == '')
return _('A rewrite IP must be specified!');
@@ -246,10 +245,12 @@ return view.extend({
fwtool.addLimitOption(s);
fwtool.addLimitBurstOption(s);
- o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
- _('Passes additional arguments to iptables. Use with care!'));
- o.modalonly = true;
- o.rmempty = true;
+ if (!L.hasSystemFeature('firewall4')) {
+ o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
+ _('Passes additional arguments to iptables. Use with care!'));
+ o.modalonly = true;
+ o.rmempty = true;
+ }
o = s.taboption('timed', form.MultiValue, 'weekdays', _('Week Days'));
o.modalonly = true;
@@ -278,11 +279,11 @@ return view.extend({
for (var i = 1; i <= 31; i++)
o.value(i);
- o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh.mm.ss)'));
+ o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh:mm:ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
- o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh.mm.ss)'));
+ o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh:mm:ss)'));
o.modalonly = true;
o.datatype = 'timehhmmss';
diff --git a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js
index b24521e1ee..58cd2a7c1e 100644
--- a/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js
+++ b/applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/zones.js
@@ -158,6 +158,14 @@ return view.extend({
o = s.taboption('general', form.Flag, 'masq', _('Masquerading'));
o.editable = true;
+ o.tooltip = function(section_id) {
+ var masq_src = uci.get('firewall', section_id, 'masq_src')
+ var masq_dest = uci.get('firewall', section_id, 'masq_dest')
+ if (masq_src || masq_dest)
+ return _('Limited masquerading enabled');
+
+ return null;
+ };
o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamping'));
o.modalonly = true;
@@ -170,25 +178,32 @@ return view.extend({
};
o.write = function(section_id, formvalue) {
var name = uci.get('firewall', section_id, 'name'),
- cfgvalue = this.cfgvalue(section_id);
+ cfgvalue = this.cfgvalue(section_id),
+ oldNetworks = L.toArray(cfgvalue),
+ newNetworks = L.toArray(formvalue);
+
+ oldNetworks.sort();
+ newNetworks.sort();
- if (typeof(cfgvalue) == 'string' && Array.isArray(formvalue) && (cfgvalue == formvalue.join(' ')))
+ if (oldNetworks.join(' ') == newNetworks.join(' '))
return;
var tasks = [ firewall.getZone(name) ];
if (Array.isArray(formvalue))
- for (var i = 0; i < formvalue.length; i++) {
- var netname = formvalue[i];
- tasks.push(network.getNetwork(netname).then(function(net) {
+ for (var i = 0; i < newNetworks.length; i++) {
+ var netname = newNetworks[i];
+ tasks.push(network.getNetwork(netname).then(L.bind(function(netname, net) {
return net || network.addNetwork(netname, { 'proto': 'none' });
- }));
+ }, this, netname)));
}
return Promise.all(tasks).then(function(zone_networks) {
- if (zone_networks[0])
+ if (zone_networks[0]) {
+ zone_networks[0].clearNetworks();
for (var i = 1; i < zone_networks.length; i++)
zone_networks[0].addNetwork(zone_networks[i].getName());
+ }
});
};
@@ -209,7 +224,7 @@ return view.extend({
o.multiple = true;
o = s.taboption('advanced', form.DynamicList, 'subnet', _('Covered subnets'), _('Use this option to classify zone traffic by source or destination subnet instead of networks or devices.'));
- o.datatype = 'neg(cidr)';
+ o.datatype = 'neg(cidr("true"))';
o.modalonly = true;
o.multiple = true;
@@ -244,7 +259,7 @@ return view.extend({
o.depends('auto_helper', '0');
o.modalonly = true;
for (var i = 0; i < ctHelpers.length; i++)
- o.value(ctHelpers[i].name, '<span class="hide-close">%s (%s)</span><span class="hide-open">%s</span>'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase(), ctHelpers[i].name.toUpperCase()));
+ o.value(ctHelpers[i].name, E('<span><span class="hide-close">%s (%s)</span><span class="hide-open">%s</span></span>'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase(), ctHelpers[i].name.toUpperCase())));
o = s.taboption('advanced', form.Flag, 'log', _('Enable logging on this zone'));
o.modalonly = true;
@@ -254,32 +269,34 @@ return view.extend({
o.placeholder = '10/minute';
o.modalonly = true;
- o = s.taboption('extra', form.DummyValue, '_extrainfo');
- o.rawhtml = true;
- o.modalonly = true;
- o.cfgvalue = function(section_id) {
- return _('Passing raw iptables arguments to source and destination traffic classification rules allows to match packets based on other criteria than interfaces or subnets. These options should be used with extreme care as invalid values could render the firewall ruleset broken, completely exposing all services.');
- };
-
- o = s.taboption('extra', form.Value, 'extra_src', _('Extra source arguments'), _('Additional raw <em>iptables</em> arguments to classify zone source traffic, e.g. <code>-p tcp --sport 443</code> to only match inbound HTTPS traffic.'));
- o.modalonly = true;
- o.cfgvalue = function(section_id) {
- return uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
- };
- o.write = function(section_id, value) {
- uci.unset('firewall', section_id, 'extra');
- uci.set('firewall', section_id, 'extra_src', value);
- };
-
- o = s.taboption('extra', form.Value, 'extra_dest', _('Extra destination arguments'), _('Additional raw <em>iptables</em> arguments to classify zone destination traffic, e.g. <code>-p tcp --dport 443</code> to only match outbound HTTPS traffic.'));
- o.modalonly = true;
- o.cfgvalue = function(section_id) {
- return uci.get('firewall', section_id, 'extra_dest') || uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
- };
- o.write = function(section_id, value) {
- uci.unset('firewall', section_id, 'extra');
- uci.set('firewall', section_id, 'extra_dest', value);
- };
+ if (!L.hasSystemFeature('firewall4')) {
+ o = s.taboption('extra', form.DummyValue, '_extrainfo');
+ o.rawhtml = true;
+ o.modalonly = true;
+ o.cfgvalue = function(section_id) {
+ return _('Passing raw iptables arguments to source and destination traffic classification rules allows to match packets based on other criteria than interfaces or subnets. These options should be used with extreme care as invalid values could render the firewall ruleset broken, completely exposing all services.');
+ };
+
+ o = s.taboption('extra', form.Value, 'extra_src', _('Extra source arguments'), _('Additional raw <em>iptables</em> arguments to classify zone source traffic, e.g. <code>-p tcp --sport 443</code> to only match inbound HTTPS traffic.'));
+ o.modalonly = true;
+ o.cfgvalue = function(section_id) {
+ return uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
+ };
+ o.write = function(section_id, value) {
+ uci.unset('firewall', section_id, 'extra');
+ uci.set('firewall', section_id, 'extra_src', value);
+ };
+
+ o = s.taboption('extra', form.Value, 'extra_dest', _('Extra destination arguments'), _('Additional raw <em>iptables</em> arguments to classify zone destination traffic, e.g. <code>-p tcp --dport 443</code> to only match outbound HTTPS traffic.'));
+ o.modalonly = true;
+ o.cfgvalue = function(section_id) {
+ return uci.get('firewall', section_id, 'extra_dest') || uci.get('firewall', section_id, 'extra_src') || uci.get('firewall', section_id, 'extra');
+ };
+ o.write = function(section_id, value) {
+ uci.unset('firewall', section_id, 'extra');
+ uci.set('firewall', section_id, 'extra_dest', value);
+ };
+ }
o = s.taboption('general', form.DummyValue, '_forwardinfo');
o.rawhtml = true;