luci-app-firewall: switch to client side CBI views
[oweals/luci.git] / applications / luci-app-firewall / htdocs / luci-static / resources / view / firewall / zones.js
1 'use strict';
2 'require rpc';
3 'require uci';
4 'require form';
5 'require network';
6 'require firewall';
7 'require tools.widgets as widgets';
8
9 return L.view.extend({
10         callOffloadSupport: rpc.declare({
11                 object: 'luci',
12                 method: 'offload_support',
13                 expect: { offload_support: false }
14         }),
15
16         load: function() {
17                 return this.callOffloadSupport();
18         },
19
20         render: function(hasOffloading) {
21                 var m, s, o, inp, out;
22
23                 m = new form.Map('firewall', _('Firewall - Zone Settings'),
24                         _('The firewall creates zones over your network interfaces to control network traffic flow.'));
25
26                 s = m.section(form.TypedSection, 'defaults', _('General Settings'));
27                 s.anonymous = true;
28                 s.addremove = false;
29
30                 o = s.option(form.Flag, 'syn_flood', _('Enable SYN-flood protection'));
31                 o = s.option(form.Flag, 'drop_invalid', _('Drop invalid packets'));
32
33                 var p = [
34                         s.option(form.ListValue, 'input', _('Input')),
35                         s.option(form.ListValue, 'output', _('Output')),
36                         s.option(form.ListValue, 'forward', _('Forward'))
37                 ];
38
39                 for (var i = 0; i < p.length; i++) {
40                         p[i].value('REJECT', _('reject'));
41                         p[i].value('DROP', _('drop'));
42                         p[i].value('ACCEPT', _('accept'));
43                 }
44
45                 /* Netfilter flow offload support */
46
47                 if (hasOffloading) {
48                         s = m.section(form.TypedSection, 'defaults', _('Routing/NAT Offloading'),
49                                 _('Experimental feature. Not fully compatible with QoS/SQM.'));
50
51                         s.anonymous = true;
52                         s.addremove = false;
53
54                         o = s.option(form.Flag, 'flow_offloading',
55                                 _('Software flow offloading'),
56                                 _('Software based offloading for routing/NAT'));
57                         o.optional = true;
58
59                         o = s.option(form.Flag, 'flow_offloading_hw',
60                                 _('Hardware flow offloading'),
61                                 _('Requires hardware NAT support. Implemented at least for mt7621'));
62                         o.optional = true;
63                         o.depends('flow_offloading', '1');
64                 }
65
66
67                 s = m.section(form.GridSection, 'zone', _('Zones'));
68                 s.addremove = true;
69                 s.anonymous = true;
70                 s.sortable  = true;
71
72                 s.tab('general', _('General Settings'));
73                 s.tab('advanced', _('Advanced Settings'));
74
75                 o = s.taboption('general', form.DummyValue, '_generalinfo');
76                 o.rawhtml = true;
77                 o.modalonly = true;
78                 o.cfgvalue = function(section_id) {
79                         var name = uci.get('firewall', section_id, 'name');
80
81                         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.')
82                                 .replace(/%s/g, name).replace(/%q/g, '"' + name + '"');
83                 };
84
85                 o = s.taboption('general', form.Value, 'name', _('Name'));
86                 o.placeholder = _('Unnamed zone');
87                 o.modalonly = true;
88                 o.datatype = 'and(uciname,maxlength(11))';
89                 o.write = function(section_id, formvalue) {
90                         var cfgvalue = this.cfgvalue(section_id);
91
92                         if (cfgvalue != formvalue)
93                                 return firewall.renameZone(cfgvalue, formvalue);
94                 };
95
96                 o = s.option(widgets.ZoneForwards, '_info', _('Zone ⇒ Forwardings'));
97                 o.editable = true;
98                 o.modalonly = false;
99                 o.cfgvalue = function(section_id) {
100                         return uci.get('firewall', section_id, 'name');
101                 };
102
103                 var p = [
104                         s.taboption('general', form.ListValue, 'input', _('Input')),
105                         s.taboption('general', form.ListValue, 'output', _('Output')),
106                         s.taboption('general', form.ListValue, 'forward', _('Forward'))
107                 ];
108
109                 for (var i = 0; i < p.length; i++) {
110                         p[i].value('REJECT', _('reject'));
111                         p[i].value('DROP', _('drop'));
112                         p[i].value('ACCEPT', _('accept'));
113                         p[i].editable = true;
114                 }
115
116                 o = s.taboption('general', form.Flag, 'masq', _('Masquerading'));
117                 o.editable = true;
118
119                 o = s.taboption('general', form.Flag, 'mtu_fix', _('MSS clamping'));
120                 o.modalonly = true;
121
122                 o = s.taboption('general', widgets.NetworkSelect, 'network', _('Covered networks'));
123                 o.modalonly = true;
124                 o.multiple = true;
125                 o.write = function(section_id, formvalue) {
126                         var name = uci.get('firewall', section_id, 'name'),
127                             cfgvalue = this.cfgvalue(section_id);
128
129                         if (typeof(cfgvalue) == 'string' && Array.isArray(formvalue) && (cfgvalue == formvalue.join(' ')))
130                                 return;
131
132                         var tasks = [ firewall.getZone(name) ];
133
134                         if (Array.isArray(formvalue))
135                                 for (var i = 0; i < formvalue.length; i++) {
136                                         var netname = formvalue[i];
137                                         tasks.push(network.getNetwork(netname).then(function(net) {
138                                                 return net || network.addNetwork(netname, { 'proto': 'none' });
139                                         }));
140                                 }
141
142                         return Promise.all(tasks).then(function(zone_networks) {
143                                 if (zone_networks[0])
144                                         for (var i = 1; i < zone_networks.length; i++)
145                                                 zone_networks[0].addNetwork(zone_networks[i].getName());
146                         });
147                 };
148
149                 o = s.taboption('advanced', form.DummyValue, '_advancedinfo');
150                 o.rawhtml = true;
151                 o.modalonly = true;
152                 o.cfgvalue = function(section_id) {
153                         var name = uci.get('firewall', section_id, 'name');
154
155                         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.')
156                                 .format(name);
157                 };
158
159                 o = s.taboption('advanced', form.ListValue, 'family', _('Restrict to address family'));
160                 o.value('', _('IPv4 and IPv6'));
161                 o.value('ipv4', _('IPv4 only'));
162                 o.value('ipv6', _('IPv6 only'));
163                 o.modalonly = true;
164
165                 o = s.taboption('advanced', form.DynamicList, 'masq_src', _('Restrict Masquerading to given source subnets'));
166                 o.depends('family', '');
167                 o.depends('family', 'ipv4');
168                 o.datatype = 'list(neg(or(uciname,hostname,ipmask4)))';
169                 o.placeholder = '0.0.0.0/0';
170                 o.modalonly = true;
171
172                 o = s.taboption('advanced', form.DynamicList, 'masq_dest', _('Restrict Masquerading to given destination subnets'));
173                 o.depends('family', '');
174                 o.depends('family', 'ipv4');
175                 o.datatype = 'list(neg(or(uciname,hostname,ipmask4)))';
176                 o.placeholder = '0.0.0.0/0';
177                 o.modalonly = true;
178
179                 o = s.taboption('advanced', form.Flag, 'conntrack', _('Force connection tracking'));
180                 o.modalonly = true;
181
182                 o = s.taboption('advanced', form.Flag, 'log', _('Enable logging on this zone'));
183                 o.modalonly = true;
184
185                 o = s.taboption('advanced', form.Value, 'log_limit', _('Limit log messages'));
186                 o.depends('log', '1');
187                 o.placeholder = '10/minute';
188                 o.modalonly = true;
189
190                 o = s.taboption('general', form.DummyValue, '_forwardinfo');
191                 o.rawhtml = true;
192                 o.modalonly = true;
193                 o.cfgvalue = function(section_id) {
194                         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.')
195                                 .format(uci.get('firewall', section_id, 'name'));
196                 };
197
198                 out = o = s.taboption('general', widgets.ZoneSelect, 'out', _('Allow forward to <em>destination zones</em>:'));
199                 o.nocreate = true;
200                 o.multiple = true;
201                 o.modalonly = true;
202                 o.filter = function(section_id, value) {
203                         return (uci.get('firewall', section_id, 'name') != value);
204                 };
205                 o.cfgvalue = function(section_id) {
206                         var out = (this.option == 'out'),
207                             zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
208                             fwds = zone.getForwardingsBy(out ? 'src' : 'dest'),
209                             value = [];
210
211                         for (var i = 0; i < fwds.length; i++)
212                                 value.push(out ? fwds[i].getDestination() : fwds[i].getSource());
213
214                         return value;
215                 };
216                 o.write = o.remove = function(section_id, formvalue) {
217                         var out = (this.option == 'out'),
218                             zone = this.lookupZone(uci.get('firewall', section_id, 'name')),
219                             fwds = zone.getForwardingsBy(out ? 'src' : 'dest');
220
221                         if (formvalue == null)
222                                 formvalue = [];
223
224                         if (Array.isArray(formvalue)) {
225                                 for (var i = 0; i < fwds.length; i++) {
226                                         var cmp = out ? fwds[i].getDestination() : fwds[i].getSource();
227                                         if (!formvalue.filter(function(d) { return d == cmp }).length)
228                                                 zone.deleteForwarding(fwds[i]);
229                                 }
230
231                                 for (var i = 0; i < formvalue.length; i++)
232                                         if (out)
233                                                 zone.addForwardingTo(formvalue[i]);
234                                         else
235                                                 zone.addForwardingFrom(formvalue[i]);
236                         }
237                 };
238
239                 inp = o = s.taboption('general', widgets.ZoneSelect, 'in', _('Allow forward from <em>source zones</em>:'));
240                 o.nocreate = true;
241                 o.multiple = true;
242                 o.modalonly = true;
243                 o.write = o.remove = out.write;
244                 o.filter = out.filter;
245                 o.cfgvalue = out.cfgvalue;
246
247                 return m.render();
248         }
249 });