6 'require tools.firewall as fwtool';
7 'require tools.widgets as widgets';
9 function fmt(fmt /*, ...*/) {
10 var repl = [], wrap = false;
12 for (var i = 1; i < arguments.length; i++) {
13 if (L.dom.elem(arguments[i])) {
14 switch (arguments[i].nodeType) {
16 repl.push(arguments[i].outerHTML);
21 repl.push(arguments[i].data);
26 span.appendChild(arguments[i]);
27 repl.push(span.innerHTML);
36 repl.push(arguments[i]);
40 var rv = fmt.format.apply(fmt, repl);
41 return wrap ? E('span', rv) : rv;
44 function forward_proto_txt(s) {
46 fwtool.fmt_family(uci.get('firewall', s, 'family')),
47 fwtool.fmt_proto(uci.get('firewall', s, 'proto'),
48 uci.get('firewall', s, 'icmp_type')) || 'TCP+UDP');
51 function rule_src_txt(s) {
52 var z = fwtool.fmt_zone(uci.get('firewall', s, 'src')),
53 p = fwtool.fmt_port(uci.get('firewall', s, 'src_port')),
54 m = fwtool.fmt_mac(uci.get('firewall', s, 'src_mac'));
58 var a = fwtool.fmt_ip(uci.get('firewall', s, 'src_ip'), _('any host'));
60 return fmt(_('From %s in %s with source %s and %s'), a, z, p, m);
62 return fmt(_('From %s in %s with source %s'), a, z, p || m);
64 return fmt(_('From %s in %s'), a, z);
69 var a = fwtool.fmt_ip(uci.get('firewall', s, 'src_ip'), _('any router IP'));
71 return fmt(_('From %s on <var>this device</var> with source %s and %s'), a, p, m);
73 return fmt(_('From %s on <var>this device</var> with source %s'), a, p || m);
75 return fmt(_('From %s on <var>this device</var>'), a);
79 function rule_dest_txt(s) {
80 var z = fwtool.fmt_zone(uci.get('firewall', s, 'dest')),
81 p = fwtool.fmt_port(uci.get('firewall', s, 'dest_port'));
85 var a = fwtool.fmt_ip(uci.get('firewall', s, 'dest_ip'), _('any host'));
87 return fmt(_('To %s, %s in %s'), a, p, z);
89 return fmt(_('To %s in %s'), a, z);
94 var a = fwtool.fmt_ip(uci.get('firewall', s, 'dest_ip'), _('any router IP'));
96 return fmt(_('To %s at %s on <var>this device</var>'), a, p);
98 return fmt(_('To %s on <var>this device</var>'), a);
102 function rule_target_txt(s) {
103 var t = fwtool.fmt_target(uci.get('firewall', s, 'target'), uci.get('firewall', s, 'src'), uci.get('firewall', s, 'dest')),
104 l = fwtool.fmt_limit(uci.get('firewall', s, 'limit'), uci.get('firewall', s, 'limit_burst'));
107 return fmt(_('<var>%s</var> and limit to %s'), t, l);
109 return fmt('<var>%s</var>', t);
112 return L.view.extend({
113 callHostHints: rpc.declare({
119 return this.callHostHints().catch(function(e) {
120 console.debug('load fail', e);
124 render: function(hosts) {
127 m = new form.Map('firewall', _('Firewall - Traffic Rules'),
128 _('Traffic rules define policies for packets traveling between different zones, for example to reject traffic between certain hosts or to open WAN ports on the router.'));
130 s = m.section(form.GridSection, 'rule', _('Traffic Rules'));
135 s.tab('general', _('General Settings'));
136 s.tab('advanced', _('Advanced Settings'));
137 s.tab('timed', _('Time Restrictions'));
139 s.filter = function(section_id) {
140 return (uci.get('firewall', section_id, 'target') != 'SNAT');
143 s.sectiontitle = function(section_id) {
144 return uci.get('firewall', section_id, 'name') || _('Unnamed rule');
147 s.handleAdd = function(ev) {
148 var config_name = this.uciconfig || this.map.config,
149 section_id = uci.add(config_name, this.sectiontype),
152 for (var i = 0; i < this.children.length; i++)
153 if (this.children[i].option == 'src')
154 opt1 = this.children[i];
155 else if (this.children[i].option == 'dest')
156 opt2 = this.children[i];
158 opt1.default = 'wan';
159 opt2.default = 'lan';
161 this.addedSection = section_id;
162 this.renderMoreOptionsModal(section_id);
168 o = s.taboption('general', form.Value, 'name', _('Name'));
169 o.placeholder = _('Unnamed rule');
172 o = s.option(form.DummyValue, '_match', _('Match'));
174 o.textvalue = function(s) {
176 forward_proto_txt(s), E('br'),
177 rule_src_txt(s), E('br'),
182 o = s.option(form.ListValue, '_target', _('Action'));
184 o.textvalue = function(s) {
185 return rule_target_txt(s);
188 o = s.option(form.Flag, 'enabled', _('Enable'));
190 o.default = o.enabled;
193 //ft.opt_enabled(s, Button);
194 //ft.opt_name(s, Value, _('Name'));
197 o = s.taboption('advanced', form.ListValue, 'family', _('Restrict to address family'));
200 o.value('', _('IPv4 and IPv6'));
201 o.value('ipv4', _('IPv4 only'));
202 o.value('ipv6', _('IPv6 only'));
204 o = s.taboption('general', form.Value, 'proto', _('Protocol'));
206 o.default = 'tcp udp';
207 o.value('all', _('Any'));
208 o.value('tcp udp', 'TCP+UDP');
209 o.value('tcp', 'TCP');
210 o.value('udp', 'UDP');
211 o.value('icmp', 'ICMP');
212 o.cfgvalue = function(/* ... */) {
213 var v = this.super('cfgvalue', arguments);
214 return (v == 'tcpudp') ? 'tcp udp' : v;
217 o = s.taboption('advanced', form.MultiValue, 'icmp_type', _('Match ICMP type'));
222 o.placeholder = _('any');
224 o.value('echo-reply');
225 o.value('destination-unreachable');
226 o.value('network-unreachable');
227 o.value('host-unreachable');
228 o.value('protocol-unreachable');
229 o.value('port-unreachable');
230 o.value('fragmentation-needed');
231 o.value('source-route-failed');
232 o.value('network-unknown');
233 o.value('host-unknown');
234 o.value('network-prohibited');
235 o.value('host-prohibited');
236 o.value('TOS-network-unreachable');
237 o.value('TOS-host-unreachable');
238 o.value('communication-prohibited');
239 o.value('host-precedence-violation');
240 o.value('precedence-cutoff');
241 o.value('source-quench');
243 o.value('network-redirect');
244 o.value('host-redirect');
245 o.value('TOS-network-redirect');
246 o.value('TOS-host-redirect');
247 o.value('echo-request');
248 o.value('router-advertisement');
249 o.value('router-solicitation');
250 o.value('time-exceeded');
251 o.value('ttl-zero-during-transit');
252 o.value('ttl-zero-during-reassembly');
253 o.value('parameter-problem');
254 o.value('ip-header-bad');
255 o.value('required-option-missing');
256 o.value('timestamp-request');
257 o.value('timestamp-reply');
258 o.value('address-mask-request');
259 o.value('address-mask-reply');
260 o.depends('proto', 'icmp');
262 o = s.taboption('general', widgets.ZoneSelect, 'src', _('Source zone'));
266 o.allowlocal = 'src';
268 o = s.taboption('advanced', form.Value, 'src_mac', _('Source MAC address'));
270 o.datatype = 'list(macaddr)';
271 o.placeholder = _('any');
272 L.sortedKeys(hosts).forEach(function(mac) {
273 o.value(mac, '%s (%s)'.format(
275 hosts[mac].name || hosts[mac].ipv4 || hosts[mac].ipv6 || '?'
279 o = s.taboption('general', form.Value, 'src_ip', _('Source address'));
281 o.datatype = 'list(neg(ipmask))';
282 o.placeholder = _('any');
283 L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
284 o.value(hosts[mac].ipv4, '%s (%s)'.format(
286 hosts[mac].name || mac
290 o = s.taboption('general', form.Value, 'src_port', _('Source port'));
292 o.datatype = 'list(neg(portrange))';
293 o.placeholder = _('any');
294 o.depends('proto', 'tcp');
295 o.depends('proto', 'udp');
296 o.depends('proto', 'tcp udp');
297 o.depends('proto', 'tcpudp');
299 o = s.taboption('general', widgets.ZoneSelect, 'dest', _('Destination zone'));
305 o = s.taboption('general', form.Value, 'dest_ip', _('Destination address'));
307 o.datatype = 'list(neg(ipmask))';
308 o.placeholder = _('any');
309 L.sortedKeys(hosts, 'ipv4', 'addr').forEach(function(mac) {
310 o.value(hosts[mac].ipv4, '%s (%s)'.format(
312 hosts[mac].name || mac
316 o = s.taboption('general', form.Value, 'dest_port', _('Destination port'));
318 o.datatype = 'list(neg(portrange))';
319 o.placeholder = _('any');
320 o.depends('proto', 'tcp');
321 o.depends('proto', 'udp');
322 o.depends('proto', 'tcp udp');
323 o.depends('proto', 'tcpudp');
325 o = s.taboption('general', form.ListValue, 'target', _('Action'));
327 o.default = 'ACCEPT';
328 o.value('DROP', _('drop'));
329 o.value('ACCEPT', _('accept'));
330 o.value('REJECT', _('reject'));
331 o.value('NOTRACK', _("don't track"));
333 o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
334 _('Passes additional arguments to iptables. Use with care!'));
337 o = s.taboption('timed', form.MultiValue, 'weekdays', _('Week Days'));
341 o.placeholder = _('Any day');
342 o.value('Sun', _('Sunday'));
343 o.value('Mon', _('Monday'));
344 o.value('Tue', _('Tuesday'));
345 o.value('Wed', _('Wednesday'));
346 o.value('Thu', _('Thursday'));
347 o.value('Fri', _('Friday'));
348 o.value('Sat', _('Saturday'));
350 o = s.taboption('timed', form.MultiValue, 'monthdays', _('Month Days'));
354 o.placeholder = _('Any day');
355 for (var i = 1; i <= 31; i++)
358 o = s.taboption('timed', form.Value, 'start_time', _('Start Time (hh.mm.ss)'));
360 o.datatype = 'timehhmmss';
362 o = s.taboption('timed', form.Value, 'stop_time', _('Stop Time (hh.mm.ss)'));
364 o.datatype = 'timehhmmss';
366 o = s.taboption('timed', form.Value, 'start_date', _('Start Date (yyyy-mm-dd)'));
368 o.datatype = 'dateyyyymmdd';
370 o = s.taboption('timed', form.Value, 'stop_date', _('Stop Date (yyyy-mm-dd)'));
372 o.datatype = 'dateyyyymmdd';
374 o = s.taboption('timed', form.Flag, 'utc_time', _('Time in UTC'));
376 o.default = o.disabled;