1 // Copyright 2022 Stan Grishin <stangri@melmac.ca>
2 // This code wouldn't have been possible without help from [@vsviridov](https://github.com/vsviridov)
9 'require pbr.status as pbr';
12 get Name() { return 'pbr'; },
13 get URL() { return 'https://docs.openwrt.melmac.net/' + pkg
.Name
+ '/'; }
25 L
.resolveDefault(pbr
.getInterfaces(), {}),
26 L
.resolveDefault(pbr
.getPlatformSupport(), {}),
27 ]).then(function (data
) {
32 if (data
[0] && data
[0][pkg
.Name
] && data
[0][pkg
.Name
].interfaces
) {
33 arrInterfaces
= data
[0][pkg
.Name
].interfaces
;
36 arrInterfaces
= ["wan"];
39 if (data
[1] && data
[1][pkg
.Name
]) {
40 replyPlatform
= data
[1][pkg
.Name
];
44 ipset_installed
: null,
46 adguardhome_installed
: null,
47 dnsmasq_installed
: null,
48 unbound_installed
: null,
49 adguardhome_ipset_support
: null,
50 dnsmasq_ipset_support
: null,
51 dnsmasq_nftset_support
: null,
55 status
= new pbr
.status();
56 m
= new form
.Map(pkg
.Name
, _("Policy Based Routing - Configuration"));
58 s
= m
.section(form
.NamedSection
, 'config', pkg
.Name
);
59 s
.tab("tab_basic", _("Basic Configuration"));
60 s
.tab("tab_advanced", _("Advanced Configuration"),
61 _("%sWARNING:%s Please make sure to check the %sREADME%s before changing anything in this section! " +
62 "Change any of the settings below with extreme caution!%s").format(
63 "<br/>    <b>", "</b>",
64 "<a href=\"" + pkg
.URL
+ "#service-configuration-settings \" target=\"_blank\">", "</a>", "<br/><br/>"));
65 s
.tab("tab_webui", _("Web UI Configuration"))
67 o
= s
.taboption("tab_basic", form
.ListValue
, "verbosity", _("Output verbosity"),
68 _("Controls both system log and console output verbosity."));
69 o
.value("0", _("Suppress/No output"));
70 o
.value("1", _("Condensed output"));
71 o
.value("2", _("Verbose output"));
74 o
= s
.taboption("tab_basic", form
.ListValue
, "strict_enforcement", _("Strict enforcement"),
75 _("See the %sREADME%s for details.").format(
76 "<a href=\"" + pkg
.URL
+ "#strict-enforcement\" target=\"_blank\">", "</a>"));
77 o
.value("0", _("Do not enforce policies when their gateway is down"));
78 o
.value("1", _("Strictly enforce policies when their gateway is down"));
82 if (replyPlatform
.adguardhome_ipset_support
=== null) {
83 text
+= _("The %s support is unknown.").format("<i>adguardhome.ipset</i>") + "<br />"
85 else if (!(replyPlatform
.adguardhome_ipset_support
)) {
86 text
+= _("The %s is not supported on this system.").format("<i>adguardhome.ipset</i>") + "<br />"
88 if (replyPlatform
.dnsmasq_ipset_support
=== null) {
89 text
+= _("The %s support is unknown.").format("<i>dnsmasq.ipset</i>") + "<br />"
91 else if (!(replyPlatform
.dnsmasq_ipset_support
)) {
92 text
+= _("The %s is not supported on this system.").format("<i>dnsmasq.ipset</i>") + "<br />"
94 if (replyPlatform
.dnsmasq_nftset_support
=== null) {
95 text
+= _("The %s support is unknown.").format("<i>dnsmasq.nftset</i>") + "<br />"
97 else if (!(replyPlatform
.dnsmasq_nftset_support
)) {
98 text
+= _("The %s is not supported on this system.").format("<i>dnsmasq.nftset</i>") + "<br />"
100 text
+= _("Please check the %sREADME%s before changing this option.").format(
101 "<a href=\"" + pkg
.URL
+ "#use-resolvers-set-support\" target=\"_blank\">", "</a>");
102 o
= s
.taboption("tab_basic", form
.ListValue
, "resolver_set", _("Use resolver set support for domains"), text
);
103 o
.value("none", _("Disabled"));
104 if (replyPlatform
.adguardhome_ipset_support
) {
105 o
.value("adguardhome.ipset", _("AdGuardHome ipset"));
106 o
.default = ("adguardhome.ipset", _("AdGuardHome ipset"));
108 if (replyPlatform
.dnsmasq_ipset_support
) {
109 o
.value("dnsmasq.ipset", _("Dnsmasq ipset"));
110 o
.default = ("dnsmasq.ipset", _("Dnsmasq ipset"));
112 if (replyPlatform
.dnsmasq_nftset_support
) {
113 o
.value("dnsmasq.nftset", _("Dnsmasq nft set"));
114 o
.default = ("dnsmasq.nftset", _("Dnsmasq nft set"));
117 o
= s
.taboption("tab_basic", form
.ListValue
, "ipv6_enabled", _("IPv6 Support"));
118 o
.value("0", _("Disabled"));
119 o
.value("1", _("Enabled"));
121 o
= s
.taboption("tab_advanced", form
.DynamicList
, "supported_interface", _("Supported Interfaces"),
122 _("Allows to specify the list of interface names (in lower case) to be explicitly supported by the service. " +
123 "Can be useful if your OpenVPN tunnels have dev option other than tun* or tap*."));
126 o
= s
.taboption("tab_advanced", form
.DynamicList
, "ignored_interface", _("Ignored Interfaces"),
127 _("Allows to specify the list of interface names (in lower case) to be ignored by the service. " +
128 "Can be useful if running both VPN server and VPN client on the router."));
131 o
= s
.taboption("tab_advanced", form
.ListValue
, "rule_create_option", _("Rule Create option"),
132 _("Select Add for -A/add and Insert for -I/Insert."));
133 o
.value("add", _("Add"));
134 o
.value("insert", _("Insert"));
137 o
= s
.taboption("tab_advanced", form
.ListValue
, "icmp_interface", _("Default ICMP Interface"),
138 _("Force the ICMP protocol interface."));
139 o
.value("", _("No Change"));
140 arrInterfaces
.forEach(element
=> {
141 if (element
.toLowerCase() !== "ignore") {
147 o
= s
.taboption("tab_advanced", form
.Value
, "wan_tid", _("WAN Table ID"),
148 _("Starting (WAN) Table ID number for tables created by the service."));
150 o
.placeholder
= "201";
151 o
.datatype
= "and(uinteger, min(201))";
153 o
= s
.taboption("tab_advanced", form
.Value
, "wan_mark", _("WAN Table FW Mark"),
154 _("Starting (WAN) FW Mark for marks used by the service. High starting mark is " +
155 "used to avoid conflict with SQM/QoS. Change with caution together with") +
156 " " + _("Service FW Mask") + ".");
158 o
.placeholder
= "010000";
159 o
.datatype
= "hexstring";
161 o
= s
.taboption("tab_advanced", form
.Value
, "fw_mask", _("Service FW Mask"),
162 _("FW Mask used by the service. High mask is used to avoid conflict with SQM/QoS. " +
163 "Change with caution together with") + " " + _("WAN Table FW Mark") + ".");
165 o
.placeholder
= "ff0000";
166 o
.datatype
= "hexstring";
168 o
= s
.taboption("tab_webui", form
.ListValue
, "webui_show_ignore_target", _("Add Ignore Target"),
169 _("Adds 'ignore' to the list of interfaces for policies. See the %sREADME%s for details.").format(
170 "<a href=\"" + pkg
.URL
+ "#ignore-target\" target=\"_blank\">", "</a>"));
171 o
.value("0", _("Disabled"))
172 o
.value("1", _("Enabled"))
176 o
= s
.taboption("tab_webui", form
.DynamicList
, "webui_supported_protocol", _("Supported Protocols"),
177 _("Display these protocols in protocol column in Web UI."));
180 s
= m
.section(form
.GridSection
, 'policy', _('Policies'),
181 _("Name, interface and at least one other field are required. Multiple local and remote " +
182 "addresses/devices/domains and ports can be space separated. Placeholders below represent just " +
183 "the format/syntax and will not be used if fields are left blank."));
189 o
= s
.option(form
.Flag
, "enabled", _("Enabled"));
193 o
= s
.option(form
.Value
, "name", _("Name"));
195 o
= s
.option(form
.Value
, "src_addr", _("Local addresses / devices"));
196 o
.datatype
= "list(neg(or(cidr,host,ipmask,ipaddr,macaddr,network)))";
200 o
= s
.option(form
.Value
, "src_port", _("Local ports"));
201 o
.datatype
= "list(neg(or(portrange,port)))";
202 o
.placeholder
= "0-65535";
206 o
= s
.option(form
.Value
, "dest_addr", _("Remote addresses / domains"));
207 o
.datatype
= "list(neg(or(cidr,host,ipmask,ipaddr,macaddr,network)))";
211 o
= s
.option(form
.Value
, "dest_port", _("Remote ports"));
212 o
.datatype
= "list(neg(or(portrange,port)))";
213 o
.placeholder
= "0-65535";
217 o
= s
.option(form
.ListValue
, "proto", _("Protocol"));
218 var proto
= L
.toArray(uci
.get(pkg
.Name
, "config", "webui_supported_protocol"));
220 proto
= ["all", "tcp", "udp", "tcp udp", "icmp"]
222 proto
.forEach(element
=> {
223 if (element
=== "all") {
224 o
.value("", _("all"));
225 o
.default = ("", _("all"));
228 o
.value(element
.toLowerCase());
233 o
= s
.option(form
.ListValue
, "chain", _("Chain"));
234 o
.value("", "prerouting");
235 o
.value("forward", "forward");
236 o
.value("input", "input");
237 o
.value("output", "output");
238 o
.value("postrouting", "postrouting");
239 o
.default = ("", "prerouting");
242 o
= s
.option(form
.ListValue
, "interface", _("Interface"));
243 arrInterfaces
.forEach(element
=> {
246 o
.datatype
= "network";
249 s
= m
.section(form
.NamedSection
, 'config', pkg
.Name
, _("DSCP Tagging"),
250 _("Set DSCP tags (in range between 1 and 63) for specific interfaces. See the %sREADME%s for details.").format(
251 "<a href=\"" + pkg
.URL
+ "#dscp-tag-based-policies" + "\" target=\"_blank\">", "</a>"));
252 arrInterfaces
.forEach(element
=> {
253 if (element
.toLowerCase() !== "ignore") {
254 o
= s
.option(form
.Value
, element
+ "_dscp", element
.toUpperCase() + " " + _("DSCP Tag"));
255 o
.datatype
= "and(uinteger, min(1), max(63))";
259 s
= m
.section(form
.GridSection
, 'include', _("Custom User File Includes"),
260 _("Run the following user files after setting up but before restarting DNSMASQ. " +
261 "See the %sREADME%s for details.").format(
262 "<a href=\"" + pkg
.URL
+ "#custom-user-files\" target=\"_blank\">", "</a>"));
267 o
= s
.option(form
.Flag
, "enabled", _("Enabled"));
272 o
= s
.option(form
.Value
, "path", _("Path"));
277 return Promise
.all([status
.render(), m
.render()]);