'use strict'; 'require form'; 'require fs'; 'require view'; 'require uci'; 'require ui'; return view.extend({ load: function() { return Promise.all([ fs.exec_direct('/usr/libexec/luci-mwan3', ['ipset', 'dump']), uci.load('mwan3') ]); }, render: function (data) { var m, s, o; m = new form.Map('mwan3', _('MultiWAN Manager - Rules'), _('Rules specify which traffic will use a particular MWAN policy.') + '
' + _('Rules are based on IP address, port or protocol.') + '
' + _('Rules are matched from top to bottom.') + '
' + _('Rules below a matching rule are ignored.') + '
' + _('Traffic not matching any rule is routed using the main routing table.') + '
' + _('Traffic destined for known (other than default) networks is handled by the main routing table.') + '
' + _('Traffic matching a rule, but all WAN interfaces for that policy are down will be blackholed.') + '
' + _('Names may contain characters A-Z, a-z, 0-9, _ and no spaces.') + '
' + _('Rules may not share the same name as configured interfaces, members or policies.')); s = m.section(form.GridSection, 'rule'); s.addremove = true; s.anonymous = false; s.nodescriptions = true; s.sortable = true; /* This name length error check can likely be removed when mwan3 migrates to nftables */ s.renderSectionAdd = function(extra_class) { var el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments), nameEl = el.querySelector('.cbi-section-create-name'); ui.addValidator(nameEl, 'uciname', true, function(v) { let sections = [ ...uci.sections('mwan3', 'interface'), ...uci.sections('mwan3', 'member'), ...uci.sections('mwan3', 'policy'), ...uci.sections('mwan3', 'rule') ]; for (let j = 0; j < sections.length; j++) { if (sections[j]['.name'] == v) { return _('Rules may not share the same name as configured interfaces, members or policies.'); } } if (v.length > 15) return _('Name length shall not exceed 15 characters'); return true; }, 'blur', 'keyup'); return el; }; o = s.option(form.ListValue, 'family', _('Internet Protocol')); o.default = ''; o.value('', _('IPv4 and IPv6')); o.value('ipv4', _('IPv4 only')); o.value('ipv6', _('IPv6 only')); o.modalonly = true; o = s.option(form.Value, 'proto', _('Protocol'), _('View the content of /etc/protocols for protocol description')); o.default = 'all'; o.rmempty = false; o.value('all'); o.value('tcp'); o.value('udp'); o.value('icmp'); o.value('esp'); o = s.option(form.Value, 'src_ip', _('Source address'), _('Supports CIDR notation (eg \"192.168.100.0/24\") without quotes')); o.datatype = 'ipaddr'; o = s.option(form.Value, 'src_port', _('Source port'), _('May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes')); o.depends('proto', 'tcp'); o.depends('proto', 'udp'); o = s.option(form.Value, 'dest_ip', _('Destination address'), _('Supports CIDR notation (eg \"192.168.100.0/24\") without quotes')); o.datatype = 'ipaddr'; o = s.option(form.Value, 'dest_port', _('Destination port'), _('May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes')); o.depends('proto', 'tcp'); o.depends('proto', 'udp'); o = s.option(form.ListValue, 'sticky', _('Sticky'), _('Traffic from the same source IP address that previously matched this rule within the sticky timeout period will use the same WAN interface')); o.default = '0'; o.value('1', _('Yes')); o.value('0', _('No')); o.modalonly = true; o = s.option(form.Value, 'timeout', _('Sticky timeout'), _('Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set')); o.datatype = 'range(1, 1000000)'; o.modalonly = true; o.depends('sticky', '1'); o = s.option(form.Value, 'ipset', _('IPset'), _('Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/youtube.com/youtube\")')); o.value('', _('-- Please choose --')); var ipsets = data[0].split(/\n/); for (var i = 0; i < ipsets.length; i++) { if (ipsets[i].length > 0) o.value(ipsets[i]); } o.modalonly = true; o = s.option(form.Flag, 'logging', _('Logging'), _('Enables firewall rule logging (global mwan3 logging must also be enabled)')); o.modalonly = true; o = s.option(form.ListValue, 'use_policy', _('Policy assigned')); var options = uci.sections('mwan3', 'policy') for (var i = 0; i < options.length; i++) { var value = options[i]['.name']; o.value(value); } o.value('unreachable', _('unreachable (reject)')); o.value('blackhole', _('blackhole (drop)')); o.value('default', _('default (use main routing table)')); return m.render(); } })