'require validation';
'require tools.prng as random';
-var protocols = [
+const protocols = [
'ip', 0, 'IP',
'hopopt', 0, 'HOPOPT',
'icmp', 1, 'ICMP',
if (x == null || x === '')
return null;
- var s = String(x).toLowerCase();
+ const s = String(x).toLowerCase();
- for (var i = 0; i < protocols.length; i += 3)
+ for (let i = 0; i < protocols.length; i += 3)
if (s == protocols[i] || s == protocols[i+1])
return [ protocols[i+1], protocols[i+2], protocols[i] ];
}
return baseclass.extend({
- fmt: function(fmtstr, args, values) {
- var repl = [],
- wrap = false,
- tokens = [];
+ fmt(fmtstr, args, values) {
+ let wrap = false;
+ const tokens = [];
if (values == null) {
values = [];
wrap = true;
}
- var get = function(args, key) {
- var names = key.trim().split(/\./),
- obj = args,
- ctx = obj;
+ const get = function(args, key) {
+ const names = key.trim().split(/\./);
+ let obj = args;
+ let ctx = obj;
- for (var i = 0; i < names.length; i++) {
+ for (let n of names) {
if (!L.isObject(obj))
return null;
ctx = obj;
- obj = obj[names[i]];
+ obj = obj[n];
}
if (typeof(obj) == 'function')
return obj;
};
- var isset = function(val) {
+ const isset = function(val) {
if (L.isObject(val) && !dom.elem(val)) {
- for (var k in val)
+ for (let k in val)
if (val.hasOwnProperty(k))
return true;
}
};
- var parse = function(tokens, text) {
+ const parse = function(tokens, text) {
if (dom.elem(text)) {
tokens.push('<span data-fmt-placeholder="%d"></span>'.format(values.length));
values.push(text);
}
};
- for (var i = 0, last = 0; i <= fmtstr.length; i++) {
+ for (let i = 0, last = 0; i <= fmtstr.length; i++) {
if (fmtstr.charAt(i) == '%' && fmtstr.charAt(i + 1) == '{') {
if (i > last)
parse(tokens, fmtstr.substring(last, i));
- var j = i + 1, nest = 0;
+ let j = i + 1, nest = 0;
- var subexpr = [];
+ const subexpr = [];
- for (var off = j + 1, esc = false; j <= fmtstr.length; j++) {
- var ch = fmtstr.charAt(j);
+ for (let off = j + 1, esc = false; j <= fmtstr.length; j++) {
+ const ch = fmtstr.charAt(j);
if (esc) {
esc = false;
}
}
- var varname = subexpr[0].trim(),
- op1 = (subexpr[1] != null) ? subexpr[1] : '?',
- if_set = (subexpr[2] != null && subexpr[2] != '') ? subexpr[2] : '%{' + varname + '}',
- op2 = (subexpr[3] != null) ? subexpr[3] : ':',
- if_unset = (subexpr[4] != null) ? subexpr[4] : '';
+ const varname = subexpr[0].trim();
+ const op1 = (subexpr[1] != null) ? subexpr[1] : '?';
+ const if_set = (subexpr[2] != null && subexpr[2] != '') ? subexpr[2] : '%{' + varname + '}';
+ const op2 = (subexpr[3] != null) ? subexpr[3] : ':';
+ const if_unset = (subexpr[4] != null) ? subexpr[4] : '';
/* Invalid expression */
if (nest != 0 || subexpr.length > 5 || varname == '') {
/* enumeration */
else if (op1 == '#' && subexpr.length == 3) {
- var items = L.toArray(get(args, varname));
+ const items = L.toArray(get(args, varname));
- for (var k = 0; k < items.length; k++) {
+ for (let k = 0; k < items.length; k++) {
tokens.push.apply(tokens, this.fmt(if_set, Object.assign({}, args, {
first: k == 0,
next: k > 0,
/* ternary expression */
else if (op1 == '?' && op2 == ':' && (subexpr.length == 1 || subexpr.length == 3 || subexpr.length == 5)) {
- var val = get(args, varname);
+ const val = get(args, varname);
if (subexpr.length == 1)
parse(tokens, isset(val) ? val : '');
}
if (wrap) {
- var node = E('span', {}, tokens.join('')),
- repl = node.querySelectorAll('span[data-fmt-placeholder]');
+ const node = E('span', {}, tokens.join(''));
+ const repl = node.querySelectorAll('span[data-fmt-placeholder]');
- for (var i = 0; i < repl.length; i++)
- repl[i].parentNode.replaceChild(values[repl[i].getAttribute('data-fmt-placeholder')], repl[i]);
+ for (let r of repl)
+ r.parentNode.replaceChild(values[r.getAttribute('data-fmt-placeholder')], r);
return node;
}
}
},
- map_invert: function(v, fn) {
+ map_invert(v, fn) {
return L.toArray(v).map(function(v) {
v = String(v);
lookupProto: lookupProto,
- addDSCPOption: function(s, is_target) {
- var o = s.taboption(is_target ? 'general' : 'advanced', form.Value, is_target ? 'set_dscp' : 'dscp',
+ addDSCPOption(s, is_target) {
+ const o = s.taboption(is_target ? 'general' : 'advanced', form.Value, is_target ? 'set_dscp' : 'dscp',
is_target ? _('DSCP mark') : _('Match DSCP'),
is_target ? _('Apply the given DSCP class or value to established connections.') : _('Matches traffic carrying the specified DSCP marking.'));
if (!is_target)
value = String(value).replace(/^!\s*/, '');
- var m = value.match(/^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
+ const m = value.match(/^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
if (!m || (m[1] != null && +m[1] > 0x3f))
return _('Invalid DSCP mark');
return o;
},
- addMarkOption: function(s, is_target) {
- var o = s.taboption(is_target ? 'general' : 'advanced', form.Value,
+ addMarkOption(s, is_target) {
+ const o = s.taboption(is_target ? 'general' : 'advanced', form.Value,
(is_target > 1) ? 'set_xmark' : (is_target ? 'set_mark' : 'mark'),
(is_target > 1) ? _('XOR mark') : (is_target ? _('Set mark') : _('Match mark')),
(is_target > 1) ? _('Apply a bitwise XOR of the given value and the existing mark value on established connections. Format is value[/mask]. If a mask is specified then those bits set in the mask are zeroed out.') :
if (!is_target)
value = String(value).replace(/^!\s*/, '');
- var m = value.match(/^(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
+ const m = value.match(/^(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
if (!m || +m[1] > 0xffffffff || (m[2] != null && +m[2] > 0xffffffff))
return _('Expecting: %s').format(_('valid firewall mark'));
return o;
},
- addLimitOption: function(s) {
- var o = s.taboption('advanced', form.Value, 'limit',
+ addLimitOption(s) {
+ const o = s.taboption('advanced', form.Value, 'limit',
_('Limit matching'),
_('Limits traffic matching to the specified rate.'));
if (value == '')
return true;
- var m = String(value).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
+ const m = String(value).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
u = ['second', 'minute', 'hour', 'day'],
i = 0;
if (m)
- for (i = 0; i < u.length; i++)
+ for (let i = 0; i < u.length; i++)
if (u[i].indexOf(m[1]) == 0)
break;
return o;
},
- addLimitBurstOption: function(s) {
- var o = s.taboption('advanced', form.Value, 'limit_burst',
+ addLimitBurstOption(s) {
+ const o = s.taboption('advanced', form.Value, 'limit_burst',
_('Limit burst'),
_('Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number.'));
return o;
},
- transformHostHints: function(family, hosts) {
- var choice_values = [],
- choice_labels = {},
- ip6addrs = {},
- ipaddrs = {};
+ transformHostHints(family, hosts) {
+ const choice_values = [];
+ const choice_labels = {};
+ const ip6addrs = {};
+ const ipaddrs = {};
- for (var mac in hosts) {
+ for (let mac in hosts) {
L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4).forEach(function(ip) {
ipaddrs[ip] = mac;
});
if (!family || family == 'ipv4') {
L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ip) {
- var val = ip,
- txt = hosts[ipaddrs[ip]].name || ipaddrs[ip];
+ const val = ip;
+ const txt = hosts[ipaddrs[ip]].name || ipaddrs[ip];
choice_values.push(val);
choice_labels[val] = E([], [ val, ' (', E('strong', {}, [txt]), ')' ]);
if (!family || family == 'ipv6') {
L.sortedKeys(ip6addrs, null, 'addr').forEach(function(ip) {
- var val = ip,
- txt = hosts[ip6addrs[ip]].name || ip6addrs[ip];
+ const val = ip;
+ const txt = hosts[ip6addrs[ip]].name || ip6addrs[ip];
choice_values.push(val);
choice_labels[val] = E([], [ val, ' (', E('strong', {}, [txt]), ')' ]);
return [choice_values, choice_labels];
},
- updateHostHints: function(map, section_id, option, family, hosts) {
- var opt = map.lookupOption(option, section_id)[0].getUIElement(section_id),
- choices = this.transformHostHints(family, hosts);
+ updateHostHints(map, section_id, option, family, hosts) {
+ const opt = map.lookupOption(option, section_id)[0].getUIElement(section_id);
+ const choices = this.transformHostHints(family, hosts);
opt.clearChoices();
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);
+ renderWidget(/* ... */) {
+ const dl = form.DynamicList.prototype.renderWidget.apply(this, arguments);
+ const 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);
+ const values = L.toArray(value);
+ for (let val of values)
+ ui.DynamicList.prototype.addItem.call(this, dl, val, null, true);
};
return dl;
}
}),
- addIPOption: function(s, tab, name, label, description, family, hosts, multiple) {
- var o = s.taboption(tab, multiple ? this.CBIDynamicMultiValueList : form.Value, name, label, description);
- var fw4 = L.hasSystemFeature('firewall4');
+ addIPOption(s, tab, name, label, description, family, hosts, multiple) {
+ const o = s.taboption(tab, multiple ? this.CBIDynamicMultiValueList : form.Value, name, label, description);
+ const fw4 = L.hasSystemFeature('firewall4');
o.modalonly = true;
o.datatype = (fw4 && validation.types.iprange) ? 'list(neg(or(ipmask("true"),iprange)))' : 'list(neg(ipmask("true")))';
o.placeholder = multiple ? _('-- add IP --') : _('any');
if (family != null) {
- var choices = this.transformHostHints(family, hosts);
+ const choices = this.transformHostHints(family, hosts);
- for (var i = 0; i < choices[0].length; i++)
- o.value(choices[0][i], choices[1][choices[0][i]]);
+ for (let ch of choices[0])
+ o.value(ch, choices[1][ch]);
}
/* force combobox rendering */
return o;
},
- addLocalIPOption: function(s, tab, name, label, description, devices) {
- var o = s.taboption(tab, form.Value, name, label, description);
- var fw4 = L.hasSystemFeature('firewall4');
+ addLocalIPOption(s, tab, name, label, description, devices) {
+ const o = s.taboption(tab, form.Value, name, label, description);
+ const fw4 = L.hasSystemFeature('firewall4');
o.modalonly = true;
o.datatype = !fw4?'ip4addr("nomask")':'ipaddr("nomask")';
o.placeholder = _('any');
L.sortedKeys(devices, 'name').forEach(function(dev) {
- var ip4addrs = devices[dev].ipaddrs;
- var ip6addrs = devices[dev].ip6addrs;
+ const ip4addrs = devices[dev].ipaddrs;
+ const ip6addrs = devices[dev].ip6addrs;
if (!L.isObject(devices[dev].flags) || devices[dev].flags.loopback)
return;
- for (var i = 0; Array.isArray(ip4addrs) && i < ip4addrs.length; i++) {
+ for (let i = 0; Array.isArray(ip4addrs) && i < ip4addrs.length; i++) {
if (!L.isObject(ip4addrs[i]) || !ip4addrs[i].address)
continue;
ip4addrs[i].address, ' (', E('strong', {}, [dev]), ')'
]));
}
- for (var i = 0; fw4 && Array.isArray(ip6addrs) && i < ip6addrs.length; i++) {
+ for (let i = 0; fw4 && Array.isArray(ip6addrs) && i < ip6addrs.length; i++) {
if (!L.isObject(ip6addrs[i]) || !ip6addrs[i].address)
continue;
return o;
},
- addMACOption: function(s, tab, name, label, description, hosts) {
- var o = s.taboption(tab, this.CBIDynamicMultiValueList, name, label, description);
+ addMACOption(s, tab, name, label, description, hosts) {
+ const o = s.taboption(tab, this.CBIDynamicMultiValueList, name, label, description);
o.modalonly = true;
o.datatype = 'list(macaddr)';
CBIProtocolSelect: form.MultiValue.extend({
__name__: 'CBI.ProtocolSelect',
- addChoice: function(value, label) {
+ addChoice(value, label) {
if (!Array.isArray(this.keylist) || this.keylist.indexOf(value) == -1)
this.value(value, label);
},
- load: function(section_id) {
- var cfgvalue = L.toArray(this.super('load', [section_id]) || this.default).sort();
+ load(section_id) {
+ let cfgvalue = L.toArray(this.super('load', [section_id]) || this.default).sort();
+ let m, p;
['all', 'tcp', 'udp', 'icmp'].concat(cfgvalue).forEach(L.bind(function(value) {
switch (value) {
break;
default:
- var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
- p = lookupProto(m ? +m[1] : value);
+ m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/);
+ p = lookupProto(m ? +m[1] : value);
this.addChoice(p[2], p[1]);
break;
return cfgvalue;
},
- renderWidget: function(section_id, option_index, cfgvalue) {
- var value = (cfgvalue != null) ? cfgvalue : this.default,
- choices = this.transformChoices();
+ renderWidget(section_id, option_index, cfgvalue) {
+ const value = (cfgvalue != null) ? cfgvalue : this.default;
+ const choices = this.transformChoices();
- var widget = new ui.Dropdown(L.toArray(value), choices, {
+ const widget = new ui.Dropdown(L.toArray(value), choices, {
id: this.cbid(section_id),
sort: this.keylist,
multiple: true,
dropdown_items: -1,
create: true,
disabled: (this.readonly != null) ? this.readonly : this.map.readonly,
- validate: function(value) {
- var v = L.toArray(value);
+ validate(value) {
+ const vals = L.toArray(value);
- for (var i = 0; i < v.length; i++) {
- if (v[i] == 'all')
+ for (let v of vals) {
+ if (v == 'all')
continue;
- var m = v[i].match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/);
+ const m = v.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/);
- if (m ? (+m[1] > 255) : (lookupProto(v[i])[0] == -1))
+ if (m ? (+m[1] > 255) : (lookupProto(v)[0] == -1))
return _('Unrecognized protocol');
}
});
widget.createChoiceElement = function(sb, value) {
- var p = lookupProto(value);
+ const p = lookupProto(value);
return ui.Dropdown.prototype.createChoiceElement.call(this, sb, p[2], p[1]);
};
widget.createItems = function(sb, value) {
- var values = L.toArray(value).map(function(value) {
- var m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/),
- p = lookupProto(m ? +m[1] : value);
+ const values = L.toArray(value).map(function(value) {
+ const m = value.match(/^(0x[0-9a-f]{1,2}|[0-9]{1,3})$/);
+ const p = lookupProto(m ? +m[1] : value);
return (p[0] > -1) ? p[2] : p[1];
});
};
widget.toggleItem = function(sb, li) {
- var value = li.getAttribute('data-value'),
- toggleFn = ui.Dropdown.prototype.toggleItem;
+ const value = li.getAttribute('data-value');
+ const toggleFn = ui.Dropdown.prototype.toggleItem;
toggleFn.call(this, sb, li);
if (value == 'all') {
- var items = li.parentNode.querySelectorAll('li[data-value]');
+ const items = li.parentNode.querySelectorAll('li[data-value]');
- for (var j = 0; j < items.length; j++)
- if (items[j] !== li)
- toggleFn.call(this, sb, items[j], false);
+ for (let i of items)
+ if (i !== li)
+ toggleFn.call(this, sb, i, false);
}
else {
toggleFn.call(this, sb, li.parentNode.querySelector('li[data-value="all"]'), false);
}
}),
- checkLegacySNAT: function() {
- var redirects = uci.sections('firewall', 'redirect');
+ checkLegacySNAT() {
+ const redirects = uci.sections('firewall', 'redirect');
- for (var i = 0; i < redirects.length; i++)
- if ((redirects[i]['target'] || '').toLowerCase() == 'snat')
+ for (let red of redirects)
+ if ((red['target'] || '').toLowerCase() == 'snat')
return true;
return false;
},
- handleMigration: function(ev) {
- var redirects = uci.sections('firewall', 'redirect'),
- tasks = [];
+ handleMigration(ev) {
+ const redirects = uci.sections('firewall', 'redirect');
- var mapping = {
+ const mapping = {
dest: 'src',
reflection: null,
reflection_src: null,
src: null
};
- for (var i = 0; i < redirects.length; i++) {
- if ((redirects[i]['target'] || '').toLowerCase() != 'snat')
+ for (let red of redirects) {
+ if ((red['target'] || '').toLowerCase() != 'snat')
continue;
- var sid = uci.add('firewall', 'nat');
+ const sid = uci.add('firewall', 'nat');
- for (var opt in redirects[i]) {
+ for (let opt in red) {
if (opt.charAt(0) == '.')
continue;
if (mapping[opt] === null)
continue;
- uci.set('firewall', sid, mapping[opt] || opt, redirects[i][opt]);
+ uci.set('firewall', sid, mapping[opt] || opt, red[opt]);
}
- uci.remove('firewall', redirects[i]['.name']);
+ uci.remove('firewall', red['.name']);
}
return uci.save()
.then(L.bind(ui.changes.apply, ui.changes));
},
- renderMigration: function() {
+ renderMigration() {
ui.showModal(_('Firewall configuration migration'), [
E('p', _('The existing firewall configuration needs to be changed for LuCI to function properly.')),
E('p', _('Upon pressing "Continue", "redirect" sections with target "SNAT" will be converted to "nat" sections and the firewall will be restarted to apply the updated configuration.')),
'require ui';
return view.extend({
- load: function() {
+ load() {
return L.resolveDefault(fs.read('/etc/firewall.user'), '');
},
- handleSave: function(ev) {
- var value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
+ handleSave(ev) {
+ const value = (document.querySelector('textarea').value || '').trim().replace(/\r\n/g, '\n') + '\n';
return fs.write('/etc/firewall.user', value).then(function(rc) {
document.querySelector('textarea').value = value;
});
},
- render: function(fwuser) {
+ render(fwuser) {
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.')),
'require tools.widgets as widgets';
function rule_proto_txt(s, ctHelpers) {
- var family = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:all|\*)$/, 'any');
- var dip = uci.get('firewall', s, 'dest_ip') || '';
- var proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
+ const family = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:all|\*)$/, 'any');
+ const dip = uci.get('firewall', s, 'dest_ip') || '';
+ const proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
return (p != '*' && p != 'any' && p != 'all');
}).map(function(p) {
- var pr = fwtool.lookupProto(p);
+ const pr = fwtool.lookupProto(p);
return {
num: pr[0],
name: pr[1],
};
});
- var m = String(uci.get('firewall', s, 'helper') || '').match(/^(!\s*)?(\S+)$/);
- var h = m ? {
+ let m = String(uci.get('firewall', s, 'helper') || '').match(/^(!\s*)?(\S+)$/);
+ const h = m ? {
val: m[0].toUpperCase(),
inv: m[1],
name: (ctHelpers.filter(function(ctH) { return ctH.name.toLowerCase() == m[2].toLowerCase() })[0] || {}).description
} : null;
m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
- var f = m ? {
+ const f = m ? {
val: m[0].toUpperCase().replace(/X/g, 'x'),
inv: m[1],
num: '0x%02X'.format(+m[2]),
}
function rule_src_txt(s, hosts) {
- var z = uci.get('firewall', s, 'src');
+ const 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': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
}
function rule_limit_txt(s) {
- var m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i),
- l = m ? {
+ const m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i);
+ const l = m ? {
num: +m[1],
unit: ({ s: _('second'), m: _('minute'), h: _('hour'), d: _('day') })[m[2]],
burst: uci.get('firewall', s, 'limit_burst')
}
function rule_target_txt(s) {
- var z = uci.get('firewall', s, 'dest');
+ const 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('strong', z) : E('em', _('this device')))]),
}
function validate_opt_family(m, section_id, opt) {
- var dopt = m.section.getOption('dest_ip'),
- fmopt = m.section.getOption('family');
+ const dopt = m.section.getOption('dest_ip');
+ const fmopt = m.section.getOption('family');
if (!dopt.isValid(section_id) && opt != 'dest_ip')
return true;
if (!fmopt.isValid(section_id) && opt != 'family')
return true;
- var dip = dopt.formvalue(section_id) || '',
- fm = fmopt.formvalue(section_id) || '';
+ const dip = dopt.formvalue(section_id) || '';
+ const fm = fmopt.formvalue(section_id) || '';
if (fm == '' || (fm == 'any' && dip == '') || (fm == 'ipv6' && (dip.indexOf(':') != -1 || dip == '')) || (fm == 'ipv4' && dip.indexOf(':') == -1))
return true;
expect: { '': {} }
}),
- load: function() {
+ load() {
return Promise.all([
this.callHostHints(),
this.callConntrackHelpers(),
]);
},
- render: function(data) {
+ render(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderForwards(data);
},
- renderForwards: function(data) {
- var hosts = data[0],
- ctHelpers = data[1],
- devs = data[2],
- m, s, o;
- var fw4 = L.hasSystemFeature('firewall4');
+ renderForwards([hosts, ctHelpers, devs]) {
+ let m, s, o;
+ const fw4 = L.hasSystemFeature('firewall4');
m = new form.Map('firewall', _('Firewall - Port Forwards'),
_('Port forwarding allows remote computers on the Internet to connect to a specific computer or service within the private LAN.'));
};
s.handleAdd = function(ev) {
- var config_name = this.uciconfig || this.map.config,
- section_id = uci.add(config_name, this.sectiontype);
+ const config_name = this.uciconfig || this.map.config;
+ const section_id = uci.add(config_name, this.sectiontype);
uci.set(config_name, section_id, 'dest', 'lan');
uci.set(config_name, section_id, 'target', 'DNAT');
o.value('ipv6', _('IPv6 only'));
o.value('', _('automatic')); // infer from zone or used IP addresses
o.cfgvalue = function(section_id) {
- var val = this.map.data.get(this.map.config, section_id, 'family');
+ const val = this.map.data.get(this.map.config, section_id, 'family');
if (!val)
return '';
o = s.taboption('advanced', form.Value, 'helper', _('Match helper'), _('Match traffic using the specified connection tracking helper.'));
o.modalonly = true;
o.placeholder = _('any');
- for (var i = 0; i < ctHelpers.length; i++)
- o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
+ for (let cth of ctHelpers)
+ o.value(cth.name, '%s (%s)'.format(cth.description, cth.name.toUpperCase()));
o.validate = function(section_id, value) {
if (value == '' || value == null)
return true;
value = value.replace(/^!\s*/, '');
- for (var i = 0; i < ctHelpers.length; i++)
- if (value == ctHelpers[i].name)
+ for (let cth of ctHelpers)
+ if (value == cth.name)
return true;
return _('Unknown or not installed conntrack helper "%s"').format(value);
return view.extend({
- load: function() {
+ load() {
return Promise.all([
uci.load('firewall')
]);
},
- render: function(data) {
+ render() {
let m, s, o;
m = new form.Map('firewall', _('Firewall - IP sets'),
_('firewall4 supports referencing and creating IP sets to simplify matching of large address lists without the need to create one rule per item to match. Port ranges in ipsets are unsupported by firewall4.<br />'));
- var have_fw4 = L.hasSystemFeature('firewall4');
+ const have_fw4 = L.hasSystemFeature('firewall4');
if (have_fw4) {
s = m.section(form.NamedSection, 'fwver', 'fwver', '', _('Your device runs firewall4.'));
o.optional = false;
o.rmempty = false;
o.validate = function (section_id, value) {
- if (!/^[a-zA-Z_.][a-zA-Z0-9\/_.-]*$/.test(value))
+ if (!/^[a-zA-Z_.][a-zA-Z0-9/_.-]*$/.test(value))
return _('Invalid set name');
return true;
o.value('hash', _('hash'));
o.value('list', _('list'));
o.validate = function(section_id, value) {
- var family = this.section.formvalue(section_id, 'family');
+ const family = this.section.formvalue(section_id, 'family');
if (value.match(/bitmap/) && !family.match(/ipv4/))
return _('bitmap is ipv4 only');
return true;
'require tools.widgets as widgets';
function rule_proto_txt(s, ctHelpers) {
- var f = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:any|\*)$/, '');
+ const f = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:any|\*)$/, '');
- var proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
+ const proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
return (p != '*' && p != 'any' && p != 'all');
}).map(function(p) {
- var pr = fwtool.lookupProto(p);
+ const pr = fwtool.lookupProto(p);
return {
num: pr[0],
name: pr[1],
};
});
- var m = String(uci.get('firewall', s, 'helper') || '').match(/^(!\s*)?(\S+)$/);
- var h = m ? {
+ let m = String(uci.get('firewall', s, 'helper') || '').match(/^(!\s*)?(\S+)$/);
+ const h = m ? {
val: m[0].toUpperCase(),
inv: m[1],
name: (ctHelpers.filter(function(ctH) { return ctH.name.toLowerCase() == m[2].toLowerCase() })[0] || {}).description
} : null;
m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
- var w = m ? {
+ const w = m ? {
val: m[0].toUpperCase().replace(/X/g, 'x'),
inv: m[1],
num: '0x%02X'.format(+m[2]),
} : null;
m = String(uci.get('firewall', s, 'dscp')).match(/^(!\s*)?(?:(CS[0-7]|BE|AF[1234][123]|EF)|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
- var d = m ? {
+ const d = m ? {
val: m[0],
inv: m[1],
name: m[2],
}
function rule_src_txt(s, hosts) {
- var z = uci.get('firewall', s, 'src'),
- d = (uci.get('firewall', s, 'direction') == 'in') ? uci.get('firewall', s, 'device') : null;
+ const z = uci.get('firewall', s, 'src');
+ const 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': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
}
function rule_dest_txt(s) {
- var z = uci.get('firewall', s, 'dest'),
- d = (uci.get('firewall', s, 'direction') == 'out') ? uci.get('firewall', s, 'device') : null;
+ const z = uci.get('firewall', s, 'dest');
+ const 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': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
}
function rule_limit_txt(s) {
- var m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i),
- l = m ? {
+ const m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i);
+ const l = m ? {
num: +m[1],
unit: ({ s: _('second'), m: _('minute'), h: _('hour'), d: _('day') })[m[2]],
burst: uci.get('firewall', s, 'limit_burst')
return fwtool.fmt(_('Limit matching to <var>%{limit.num}</var> packets per <var>%{limit.unit}</var>%{limit.burst? burst <var>%{limit.burst}</var>}'), { limit: l });
}
-function rule_target_txt(s, ctHelpers) {
- var t = uci.get('firewall', s, 'target'),
- h = (uci.get('firewall', s, 'set_helper') || '').toUpperCase(),
- s = {
- target: t,
- src: uci.get('firewall', s, 'src'),
- dest: uci.get('firewall', s, 'dest'),
- set_helper: h,
- set_mark: uci.get('firewall', s, 'set_mark'),
- set_xmark: uci.get('firewall', s, 'set_xmark'),
- set_dscp: uci.get('firewall', s, 'set_dscp'),
- helper_name: (ctHelpers.filter(function(ctH) { return ctH.name.toUpperCase() == h })[0] || {}).description
- };
+function rule_target_txt(sid, ctHelpers) {
+ const t = uci.get('firewall', sid, 'target');
+ const h = (uci.get('firewall', sid, 'set_helper') || '').toUpperCase();
+ const s = {
+ target: t,
+ src: uci.get('firewall', sid, 'src'),
+ dest: uci.get('firewall', sid, 'dest'),
+ set_helper: h,
+ set_mark: uci.get('firewall', sid, 'set_mark'),
+ set_xmark: uci.get('firewall', sid, 'set_xmark'),
+ set_dscp: uci.get('firewall', sid, 'set_dscp'),
+ helper_name: (ctHelpers.filter(function(ctH) { return ctH.name.toUpperCase() == h })[0] || {}).description
+ };
switch (t) {
case 'DROP':
expect: { result: [] }
}),
- load: function() {
+ load() {
return Promise.all([
this.callHostHints(),
this.callConntrackHelpers(),
]);
},
- render: function(data) {
+ render(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderRules(data);
},
- renderRules: function(data) {
- var hosts = data[0],
- ctHelpers = data[1],
- m, s, o;
+ renderRules([hosts, ctHelpers]) {
+ let m, s, o;
m = new form.Map('firewall', _('Firewall - Traffic Rules'),
_('Traffic rules define policies for packets travelling between different zones, for example to reject traffic between certain hosts or to open WAN ports on the router.'));
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');
+ const weekdays = uci.get('firewall', section_id, 'weekdays');
+ const monthdays = uci.get('firewall', section_id, 'monthdays');
+ const start_time = uci.get('firewall', section_id, 'start_time');
+ const stop_time = uci.get('firewall', section_id, 'stop_time');
+ const start_date = uci.get('firewall', section_id, 'start_date');
+ const stop_date = uci.get('firewall', section_id, 'stop_date');
if (weekdays || monthdays || start_time || stop_time || start_date || stop_date )
return _('Time restrictions are enabled for this rule');
o.value('in', _('Inbound device'));
o.value('out', _('Outbound device'));
o.cfgvalue = function(section_id) {
- var val = uci.get('firewall', section_id, 'direction');
+ const val = uci.get('firewall', section_id, 'direction');
switch (val) {
case 'in':
case 'ingress':
o.value('MARK_XOR', _('XOR firewall mark'));
o.value('DSCP', _('DSCP classification'));
o.cfgvalue = function(section_id) {
- var t = uci.get('firewall', section_id, 'target'),
- m = uci.get('firewall', section_id, 'set_mark');
+ const t = uci.get('firewall', section_id, 'target');
+ const m = uci.get('firewall', section_id, 'set_mark');
if (t == 'MARK')
return m ? 'MARK_SET' : 'MARK_XOR';
o.modalonly = true;
o.placeholder = _('any');
o.depends('target', 'HELPER');
- for (var i = 0; i < ctHelpers.length; i++)
- o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
+ for (let cth of ctHelpers)
+ o.value(cth.name, '%s (%s)'.format(cth.description, cth.name.toUpperCase()));
o = s.taboption('advanced', form.Value, 'helper', _('Match helper'), _('Match traffic using the specified connection tracking helper.'));
o.modalonly = true;
o.placeholder = _('any');
- for (var i = 0; i < ctHelpers.length; i++)
- o.value(ctHelpers[i].name, '%s (%s)'.format(ctHelpers[i].description, ctHelpers[i].name.toUpperCase()));
+ for (let cth of ctHelpers)
+ o.value(cth.name, '%s (%s)'.format(cth.description, cth.name.toUpperCase()));
o.validate = function(section_id, value) {
if (value == '' || value == null)
return true;
value = value.replace(/^!\s*/, '');
- for (var i = 0; i < ctHelpers.length; i++)
- if (value == ctHelpers[i].name)
+ for (let cth of ctHelpers)
+ if (value == cth.name)
return true;
return _('Unknown or not installed conntrack helper "%s"').format(value);
o.write = function(section_id, value) {
return this.super('write', [ section_id, L.toArray(value).join(' ') ]);
};
- for (var i = 1; i <= 31; i++)
+ for (let i = 1; i <= 31; i++)
o.value(i);
o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh:mm:ss)'));
'require tools.widgets as widgets';
function rule_proto_txt(s) {
- var family = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:all|\*)$/, 'any');
- var sip = uci.get('firewall', s, 'src_ip') || '';
- var dip = uci.get('firewall', s, 'dest_ip') || '';
- var rwip = uci.get('firewall', s, 'snat_ip') || '';
- var proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
+ const family = (uci.get('firewall', s, 'family') || '').toLowerCase().replace(/^(?:all|\*)$/, 'any');
+ const sip = uci.get('firewall', s, 'src_ip') || '';
+ const dip = uci.get('firewall', s, 'dest_ip') || '';
+ const rwip = uci.get('firewall', s, 'snat_ip') || '';
+ const proto = L.toArray(uci.get('firewall', s, 'proto')).filter(function(p) {
return (p != '*' && p != 'any' && p != 'all');
}).map(function(p) {
- var pr = fwtool.lookupProto(p);
+ const pr = fwtool.lookupProto(p);
return {
num: pr[0],
name: pr[1]
};
});
- var m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
- var f = m ? {
+ const m = String(uci.get('firewall', s, 'mark')).match(/^(!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
+ const f = m ? {
val: m[0].toUpperCase().replace(/X/g, 'x'),
inv: m[1],
num: '0x%02X'.format(+m[2]),
}
function rule_src_txt(s, hosts) {
- var z = uci.get('firewall', s, 'src');
+ const 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': fwmodel.getZoneColorStyle(null) }, [E('em', _('any zone'))]),
}
function rule_dest_txt(s) {
- var z = uci.get('firewall', s, 'src');
+ const 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': fwmodel.getZoneColorStyle(z) }, [(z == '*') ? E('em', _('any zone')) : (z ? E('strong', z) : E('em', _('this device')))]),
}
function rule_limit_txt(s) {
- var m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i),
- l = m ? {
+ const m = String(uci.get('firewall', s, 'limit')).match(/^(\d+)\/([smhd])\w*$/i);
+ const l = m ? {
num: +m[1],
unit: ({ s: _('second'), m: _('minute'), h: _('hour'), d: _('day') })[m[2]],
burst: uci.get('firewall', s, 'limit_burst')
return fwtool.fmt(_('Limit matching to <var>%{limit.num}</var> packets per <var>%{limit.unit}</var>%{limit.burst? burst <var>%{limit.burst}</var>}'), { limit: l });
}
-function rule_target_txt(s) {
- var t = uci.get('firewall', s, 'target'),
- s = {
- target: t,
- snat_ip: uci.get('firewall', s, 'snat_ip'),
- snat_port: uci.get('firewall', s, 'snat_port')
- };
+function rule_target_txt(sid) {
+ const t = uci.get('firewall', sid, 'target');
+ const s = {
+ target: t,
+ snat_ip: uci.get('firewall', sid, 'snat_ip'),
+ snat_port: uci.get('firewall', sid, 'snat_port')
+ };
switch (t) {
case 'SNAT':
}
function validate_opt_family(m, section_id, opt) {
- var sopt = m.section.getOption('src_ip'),
- dopt = m.section.getOption('dest_ip'),
- rwopt = m.section.getOption('snat_ip'),
- fmopt = m.section.getOption('family'),
- tgopt = m.section.getOption('target');
+ const sopt = m.section.getOption('src_ip');
+ const dopt = m.section.getOption('dest_ip');
+ const rwopt = m.section.getOption('snat_ip');
+ const fmopt = m.section.getOption('family');
+ const tgopt = m.section.getOption('target');
if (!sopt.isValid(section_id) && opt != 'src_ip')
return true;
if (!tgopt.isValid(section_id) && opt != 'target')
return true;
- var sip = sopt.formvalue(section_id) || '',
- dip = dopt.formvalue(section_id) || '',
- rwip = rwopt.formvalue(section_id) || '',
- fm = fmopt.formvalue(section_id) || '',
- tg = tgopt.formvalue(section_id);
+ const sip = sopt.formvalue(section_id) || '';
+ const dip = dopt.formvalue(section_id) || '';
+ const rwip = rwopt.formvalue(section_id) || '';
+ const fm = fmopt.formvalue(section_id) || '';
+ const tg = tgopt.formvalue(section_id);
if (fm == 'ipv6' && (sip.indexOf(':') != -1 || sip == '') && (dip.indexOf(':') != -1 || dip == '') && ((rwip.indexOf(':') != -1 && tg == 'SNAT') || rwip == ''))
return true;
expect: { '': {} }
}),
- load: function() {
+ load() {
return Promise.all([
this.callHostHints(),
this.callNetworkDevices(),
]);
},
- render: function(data) {
+ render(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderNats(data);
},
- renderNats: function(data) {
- var hosts = data[0],
- devs = data[1],
- m, s, o;
- var fw4 = L.hasSystemFeature('firewall4');
+ renderNats([hosts, devs]) {
+ let m, s, o;
+ const fw4 = L.hasSystemFeature('firewall4');
m = new form.Map('firewall', _('Firewall - NAT Rules'),
_('NAT rules allow fine grained control over the source IP to use for outbound or forwarded traffic.'));
o.value('ipv6', _('IPv6 only'));
o.value('', _('automatic')); // infer from zone or used IP addresses
o.cfgvalue = function(section_id) {
- var val = this.map.data.get(this.map.config, section_id, 'family');
+ const val = this.map.data.get(this.map.config, section_id, 'family');
if (!val)
return '';
o.placeholder = null;
o.depends('target', 'SNAT');
o.validate = function(section_id, value) {
- var a = this.formvalue(section_id),
- p = this.section.formvalue(section_id, 'snat_port');
+ const a = this.formvalue(section_id);
+ const p = this.section.formvalue(section_id, 'snat_port');
if ((a == null || a == '') && (p == null || p == '') && value == '')
return _('A rewrite IP must be specified!');
o.depends({ proto: 'tcp', '!contains': true });
o.depends({ proto: 'udp', '!contains': true });
- var have_fw4 = L.hasSystemFeature('firewall4')
- if (!have_fw4) {
+ if (!fw4) {
o = s.taboption('advanced', form.Value, 'ipset', _('Use ipset'));
uci.sections('firewall', 'ipset', function(s) {
if (typeof(s.name) == 'string')
o = s.taboption('advanced', form.Flag, 'log', _('Enable logging'), _('Log matched packets to syslog.'));
o.modalonly = true;
- if (!have_fw4) {
+ if (!fw4) {
o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
_('Passes additional arguments to iptables. Use with care!'));
o.modalonly = true;
o.write = function(section_id, value) {
return this.super('write', [ section_id, L.toArray(value).join(' ') ]);
};
- for (var i = 1; i <= 31; i++)
+ for (let i = 1; i <= 31; i++)
o.value(i);
o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh:mm:ss)'));
expect: { result: [] }
}),
- load: function() {
+ load() {
return Promise.all([
this.callConntrackHelpers(),
firewall.getDefaults()
]);
},
- render: function(data) {
+ render(data) {
if (fwtool.checkLegacySNAT())
return fwtool.renderMigration();
else
return this.renderZones(data);
},
- renderZones: function(data) {
- var ctHelpers = data[0],
- fwDefaults = data[1],
- m, s, o, inp, out;
- var fw4 = L.hasSystemFeature('firewall4');
+ renderZones([ctHelpers, fwDefaults]) {
+ let m, s, o, out;
+ const fw4 = L.hasSystemFeature('firewall4');
m = new form.Map('firewall', _('Firewall - Zone Settings'),
_('The firewall creates zones over your network interfaces to control network traffic flow.'));
o = s.option(form.Flag, 'synflood_protect', _('Enable SYN-flood protection'));
o.cfgvalue = function(section_id) {
- var val = uci.get('firewall', section_id, 'synflood_protect');
+ const val = uci.get('firewall', section_id, 'synflood_protect');
return (val != null) ? val : uci.get('firewall', section_id, 'syn_flood');
};
o.write = function(section_id, value) {
o = s.option(form.Flag, 'drop_invalid', _('Drop invalid packets'));
- var p = [
+ let p = [
s.option(form.ListValue, 'input', _('Input')),
s.option(form.ListValue, 'output', _('Output')),
s.option(form.ListValue, 'forward', _('Forward'))
];
- for (var i = 0; i < p.length; i++) {
- p[i].value('REJECT', _('reject'));
- p[i].value('DROP', _('drop'));
- p[i].value('ACCEPT', _('accept'));
+ for (let popt of p) {
+ popt.value('REJECT', _('reject'));
+ popt.value('DROP', _('drop'));
+ popt.value('ACCEPT', _('accept'));
}
/* Netfilter flow offload support */
o.value('2', _("Hardware flow offloading"), _('Hardware based offloading for routing with/without NAT.') + ' ' + _(' Requires hardware NAT support.'));
o.optional = false;
o.load = function (section_id) {
- var flow_offloading = uci.get('firewall', section_id, 'flow_offloading');
- var flow_offloading_hw = uci.get('firewall', section_id, 'flow_offloading_hw');
+ const flow_offloading = uci.get('firewall', section_id, 'flow_offloading');
+ const flow_offloading_hw = uci.get('firewall', section_id, 'flow_offloading_hw');
return (flow_offloading === '1')
? (flow_offloading_hw === '1' ? '2' : '1')
: '0';
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
- var name = uci.get('firewall', section_id, 'name');
+ let name = uci.get('firewall', section_id, 'name');
if (name == null)
name = _("this new zone");
return _('This section defines common properties of %q. The <em>input</em> and <em>output</em> options set the default policies for traffic entering and leaving this zone while the <em>forward</em> option describes the policy for forwarded traffic between different networks within the zone. <em>Covered networks</em> specifies which available networks are members of this zone.')
o.placeholder = _('Unnamed zone');
o.modalonly = true;
o.rmempty = false;
- o.datatype = L.hasSystemFeature('firewall4') ? 'ucifw4zonename' : 'and(ucifw4zonename,maxlength(11))';
+ o.datatype = fw4 ? 'ucifw4zonename' : 'and(ucifw4zonename,maxlength(11))';
o.write = function(section_id, formvalue) {
- var cfgvalue = this.cfgvalue(section_id);
+ const cfgvalue = this.cfgvalue(section_id);
if (cfgvalue == null || cfgvalue == '')
return uci.set('firewall', section_id, 'name', formvalue);
return uci.get('firewall', section_id, 'name');
};
- var p = [
+ p = [
s.taboption('general', form.ListValue, 'input', _('Input')),
s.taboption('general', form.ListValue, 'output', _('Output')),
s.taboption('general', form.ListValue, 'forward', _('Intra zone forward'))
];
- for (var i = 0; i < p.length; i++) {
- p[i].value('REJECT', _('reject'));
- p[i].value('DROP', _('drop'));
- p[i].value('ACCEPT', _('accept'));
- p[i].editable = true;
+ for (let popt of p) {
+ popt.value('REJECT', _('reject'));
+ popt.value('DROP', _('drop'));
+ popt.value('ACCEPT', _('accept'));
+ popt.editable = true;
}
p[0].default = fwDefaults.getInput();
return uci.get('firewall', section_id, 'network');
};
o.write = function(section_id, formvalue) {
- var name = uci.get('firewall', section_id, 'name'),
- cfgvalue = this.cfgvalue(section_id),
- oldNetworks = L.toArray(cfgvalue),
- newNetworks = L.toArray(formvalue);
+ const name = uci.get('firewall', section_id, 'name');
+ const cfgvalue = this.cfgvalue(section_id);
+ const oldNetworks = L.toArray(cfgvalue);
+ const newNetworks = L.toArray(formvalue);
oldNetworks.sort();
newNetworks.sort();
if (oldNetworks.join(' ') == newNetworks.join(' '))
return;
- var tasks = [ firewall.getZone(name) ];
+ const tasks = [ firewall.getZone(name) ];
if (Array.isArray(formvalue))
- for (var i = 0; i < newNetworks.length; i++) {
- var netname = newNetworks[i];
+ for (let netname of newNetworks) {
tasks.push(network.getNetwork(netname).then(L.bind(function(netname, net) {
return net || network.addNetwork(netname, { 'proto': 'none' });
}, this, netname)));
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
- var name = uci.get('firewall', section_id, 'name');
+ let name = uci.get('firewall', section_id, 'name');
if (name == null)
name = _("this new zone");
return _('The options below control the forwarding policies between this zone (%s) and other zones. <em>Destination zones</em> cover forwarded traffic <strong>originating from %q</strong>. <em>Source zones</em> match forwarded traffic from other zones <strong>targeted at %q</strong>. The forwarding rule is <em>unidirectional</em>, e.g. a forward from lan to wan does <em>not</em> imply a permission to forward from wan to lan as well.')
_('Enable network address and port translation IPv6 (NAT6 or NAPT6) for outbound traffic on this zone.'));
o.modalonly = true;
o.tooltip = function(section_id) {
- var family = uci.get('firewall', section_id, 'family')
- var masq_src = uci.get('firewall', section_id, 'masq_src')
- var masq_dest = uci.get('firewall', section_id, 'masq_dest')
+ const family = uci.get('firewall', section_id, 'family')
+ const masq_src = uci.get('firewall', section_id, 'masq_src')
+ const masq_dest = uci.get('firewall', section_id, 'masq_dest')
if ((!family || family.indexOf('6') >= 0) && (masq_src || masq_dest))
return _('Limited masquerading enabled');
return null;
o = s.taboption('conntrack', form.MultiValue, 'helper', _('Conntrack helpers'), _('Explicitly choses allowed connection tracking helpers for zone traffic'));
o.depends('auto_helper', '0');
o.modalonly = true;
- for (var i = 0; i < ctHelpers.length; i++)
- 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())));
+ for (let cth of ctHelpers)
+ o.value(cth.name, E('<span><span class="hide-close">%s (%s)</span><span class="hide-open">%s</span></span>'.format(cth.description, cth.name.toUpperCase(), cth.name.toUpperCase())));
o = s.taboption('advanced', form.MultiValue, 'log', _('Enable logging'), _('Log matched packets on the selected tables to syslog.'));
o.modalonly = true;
o.placeholder = '10/minute';
o.modalonly = true;
- if (!L.hasSystemFeature('firewall4')) {
+ if (!fw4) {
o = s.taboption('extra', form.DummyValue, '_extrainfo');
o.rawhtml = true;
o.modalonly = true;
o.rawhtml = true;
o.modalonly = true;
o.cfgvalue = function(section_id) {
- var name = uci.get('firewall', section_id, 'name');
+ let name = uci.get('firewall', section_id, 'name');
if (name == null)
name = _("this new zone");
return _('The options below control the forwarding policies between this zone (%s) and other zones. <em>Destination zones</em> cover forwarded traffic <strong>originating from %q</strong>. <em>Source zones</em> match forwarded traffic from other zones <strong>targeted at %q</strong>. The forwarding rule is <em>unidirectional</em>, e.g. a forward from lan to wan does <em>not</em> imply a permission to forward from wan to lan as well.')
return (uci.get('firewall', section_id, 'name') != value);
};
o.cfgvalue = function(section_id) {
- var out = (this.option == 'out'),
- zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
- fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [],
- value = [];
+ const out = (this.option == 'out');
+ const zone = this.lookupZone(uci.get('firewall', section_id, 'name'));
+ const fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [];
+ const value = [];
- for (var i = 0; i < fwds.length; i++)
- value.push(out ? fwds[i].getDestination() : fwds[i].getSource());
+ for (let fwd of fwds)
+ value.push(out ? fwd.getDestination() : fwd.getSource());
return value;
};
o.write = o.remove = function(section_id, formvalue) {
- var out = (this.option == 'out'),
- zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
- fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [];
+ const out = (this.option == 'out');
+ const zone = this.lookupZone(uci.get('firewall', section_id, 'name'));
+ const fwds = zone ? zone.getForwardingsBy(out ? 'src' : 'dest') : [];
if (formvalue == null)
formvalue = [];
if (Array.isArray(formvalue)) {
- for (var i = 0; i < fwds.length; i++) {
- var cmp = out ? fwds[i].getDestination() : fwds[i].getSource();
+ for (let fwd of fwds) {
+ var cmp = out ? fwd.getDestination() : fwd.getSource();
if (!formvalue.filter(function(d) { return d == cmp }).length)
- zone.deleteForwarding(fwds[i]);
+ zone.deleteForwarding(fwd);
}
- for (var i = 0; i < formvalue.length; i++)
+ for (let fv of formvalue)
if (out)
- zone.addForwardingTo(formvalue[i]);
+ zone.addForwardingTo(fv);
else
- zone.addForwardingFrom(formvalue[i]);
+ zone.addForwardingFrom(fv);
}
};
- inp = o = s.taboption('general', widgets.ZoneSelect, 'in', _('Allow forward from <em>source zones</em>:'));
+ o = s.taboption('general', widgets.ZoneSelect, 'in', _('Allow forward from <em>source zones</em>:'));
o.nocreate = true;
o.multiple = true;
o.modalonly = true;