luci-app-statistics: clean and fix plugin configurations
[project/luci.git] / applications / luci-app-statistics / htdocs / luci-static / resources / view / statistics / plugins / iptables.js
1 'use strict';
2 'require fs';
3 'require uci';
4 'require form';
5
6 return L.Class.extend({
7 title: _('Iptables Plugin Configuration'),
8 description: _('The iptables plugin will monitor selected firewall rules and collect information about processed bytes and packets per rule.'),
9
10 addFormOptions: function(s) {
11 var o, ss;
12
13 o = s.option(form.Flag, 'enable', _('Enable this plugin'));
14
15 for (var family = 4; family <= 6; family += 2) {
16 var suffix = (family == 4 ? '' : '6');
17
18 o = s.option(form.SectionValue, '__match' + suffix, form.TableSection, 'collectd_iptables_match' + suffix,
19 suffix ? _('Match IPv6 iptables rules') : _('Match IPv4 iptables rules'),
20 _('Here you can define various criteria by which the monitored iptables rules are selected.'));
21
22 o.depends('enable', '1');
23 o.load = L.bind(function(suffix, section_id) {
24 return L.resolveDefault(fs.exec_direct('/usr/sbin/ip' + suffix + 'tables-save', []), '').then(L.bind(function(res) {
25 var lines = res.split(/\n/),
26 table, chain, count, iptables = {};
27
28 for (var i = 0; i < lines.length; i++) {
29 var m;
30
31 if ((m = lines[i].match(/^\*(\S+)$/)) != null) {
32 table = m[1];
33 count = {};
34 }
35 else if ((m = lines[i].match(/^-A (.+?) ([!-].+)$/)) != null) {
36 count[m[1]] = (count[m[1]] || 0) + 1;
37
38 iptables[table] = iptables[table] || {};
39 iptables[table][m[1]] = iptables[table][m[1]] || {};
40 iptables[table][m[1]][count[m[1]]] = E('span', {
41 'style': 'overflow:hidden; text-overflow:ellipsis; max-width:200px',
42 'data-tooltip': m[2]
43 }, [
44 '#%d: '.format(count[m[1]]),
45 m[2].replace(/-m comment --comment "(.+?)" /, '')
46 ]);
47
48 /*
49 * collectd currently does not support comments with spaces:
50 * https://github.com/collectd/collectd/issues/2766
51 */
52 var c = m[2].match(/-m comment --comment "(.+)" -/);
53 if (c && c[1] != '!fw3' && !c[1].match(/[ \t\n]/))
54 iptables[table][m[1]][c[1]] = E('span', {}, [ c[1] ]);
55 }
56 }
57
58 this.subsection.iptables = iptables;
59
60 return form.SectionValue.prototype.load.apply(this, [section_id]);
61 }, this));
62 }, o, suffix);
63
64 ss = o.subsection;
65 ss.anonymous = true;
66 ss.addremove = true;
67 ss.addbtntitle = suffix ? _('Add IPv6 rule selector') : _('Add IPv4 rule selector');
68
69 o = ss.option(form.Value, 'name', _('Instance name'));
70 o.datatype = 'maxlength(63)';
71 o.validate = function(section_id, v) {
72 var table_opt = this.section.children.filter(function(o) { return o.option == 'table' })[0],
73 table_elem = table_opt.getUIElement(section_id);
74
75 table_elem.clearChoices();
76 table_elem.addChoices(Object.keys(this.section.iptables).sort());
77
78 if (v != '' && v.match(/[ \t\n]/))
79 return _('The instance name must not contain spaces');
80
81 return true;
82 };
83
84 o = ss.option(form.Value, 'table', _('Table'));
85 o.default = 'filter';
86 o.optional = true;
87 o.transformChoices = function() { return this.super('transformChoices', []) || {} };
88 o.validate = function(section_id, table) {
89 var chain_opt = this.section.children.filter(function(o) { return o.option == 'chain' })[0],
90 chain_elem = chain_opt.getUIElement(section_id);
91
92 chain_elem.clearChoices();
93 chain_elem.addChoices(Object.keys(this.section.iptables[table]).sort());
94
95 return true;
96 };
97
98 o = ss.option(form.Value, 'chain', _('Chain'));
99 o.optional = true;
100 o.transformChoices = function() { return this.super('transformChoices', []) || {} };
101 o.validate = function(section_id, chain) {
102 var table_opt = this.section.children.filter(function(o) { return o.option == 'table' })[0],
103 rule_opt = this.section.children.filter(function(o) { return o.option == 'rule' })[0],
104 rule_elem = rule_opt.getUIElement(section_id),
105 table = table_opt.formvalue(section_id);
106
107 rule_elem.clearChoices();
108
109 if (this.section.iptables[table][chain]) {
110 var keys = Object.keys(this.section.iptables[table][chain]).sort(function(a, b) {
111 var x = a.match(/^(\d+)/),
112 y = b.match(/^(\d+)/);
113
114 if (x && y)
115 return +x[1] > +y[1];
116 else if (x || y)
117 return +!!x > +!!y;
118 else
119 return a > b;
120 });
121
122 var labels = {};
123
124 for (var i = 0; i < keys.length; i++)
125 labels[keys[i]] = this.section.iptables[table][chain][keys[i]].cloneNode(true);
126
127 rule_elem.addChoices(keys, labels);
128 }
129
130 if (chain != '' && chain.match(/[ \t\n]/))
131 return _('The chain name must not contain spaces');
132
133 return true;
134 };
135
136 o = ss.option(form.Value, 'rule', _('Comment / Rule Number'));
137 o.optional = true;
138 o.transformChoices = function() { return this.super('transformChoices', []) || {} };
139 o.load = function(section_id) {
140 var table = uci.get('luci_statistics', section_id, 'table'),
141 chain = uci.get('luci_statistics', section_id, 'chain'),
142 rule = uci.get('luci_statistics', section_id, 'rule'),
143 ipt = this.section.iptables;
144
145 if (ipt[table] && ipt[table][chain] && ipt[table][chain][rule])
146 this.value(rule, ipt[table][chain][rule].cloneNode(true));
147
148 return rule;
149 };
150 o.validate = function(section_id, rule) {
151 if (rule != '' && rule.match(/[ \t\n]/))
152 return _('The comment to match must not contain spaces');
153
154 return true;
155 };
156 }
157 },
158
159 configSummary: function(section) {
160 return _('Rule monitoring enabled');
161 }
162 });