luci-app-firewall: support 'limit' and 'limit_burst' options
authorJo-Philipp Wich <jo@mein.io>
Thu, 16 Jan 2020 20:36:39 +0000 (21:36 +0100)
committerJo-Philipp Wich <jo@mein.io>
Tue, 28 Jan 2020 17:32:42 +0000 (18:32 +0100)
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
(backported from commit 28f4a9fcedda504adac3426195749c45b8893836)

applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/forwards.js
applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/rules.js
applications/luci-app-firewall/htdocs/luci-static/resources/view/firewall/snats.js

index 030b78b2d992d75dc04ccfc8abb43dd5a0b91f7f..f8b9e19e121418c48a1d2449003bb97f7c91622e 100644 (file)
@@ -315,6 +315,42 @@ return L.view.extend({
                        return true;
                };
 
+               o = s.taboption('advanced', form.Value, 'limit', _('Limit matching'),
+                       _('Limits traffic matching to the specified rate.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = _('unlimited');
+               o.value('10/second');
+               o.value('60/minute');
+               o.value('3/hour');
+               o.value('500/day');
+               o.validate = function(section_id, value) {
+                       if (value == '')
+                               return true;
+
+                       var m = String(value).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
+                           u = ['second', 'minute', 'hour', 'day'],
+                           i = 0;
+
+                       if (m)
+                               for (i = 0; i < u.length; i++)
+                                       if (u[i].indexOf(m[1]) == 0)
+                                               break;
+
+                       if (!m || i >= u.length)
+                               return _('Invalid limit value');
+
+                       return true;
+               };
+
+               o = s.taboption('advanced', form.Value, 'limit_burst', _('Limit burst'),
+                       _('Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = '5';
+               o.datatype = 'uinteger';
+               o.depends({ limit: null, '!reverse': true });
+
                o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
                        _('Passes additional arguments to iptables. Use with care!'));
                o.modalonly = true;
index 9d8d8d15598312ae370e61864f8cdb7d51e4c6f6..a5b27ccf306667a73bfbe9cb0b8d17a80f1641ec 100644 (file)
@@ -555,6 +555,42 @@ return L.view.extend({
                        return true;
                };
 
+               o = s.taboption('advanced', form.Value, 'limit', _('Limit matching'),
+                       _('Limits traffic matching to the specified rate.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = _('unlimited');
+               o.value('10/second');
+               o.value('60/minute');
+               o.value('3/hour');
+               o.value('500/day');
+               o.validate = function(section_id, value) {
+                       if (value == '')
+                               return true;
+
+                       var m = String(value).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
+                           u = ['second', 'minute', 'hour', 'day'],
+                           i = 0;
+
+                       if (m)
+                               for (i = 0; i < u.length; i++)
+                                       if (u[i].indexOf(m[1]) == 0)
+                                               break;
+
+                       if (!m || i >= u.length)
+                               return _('Invalid limit value');
+
+                       return true;
+               };
+
+               o = s.taboption('advanced', form.Value, 'limit_burst', _('Limit burst'),
+                       _('Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = '5';
+               o.datatype = 'uinteger';
+               o.depends({ limit: null, '!reverse': true });
+
                o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
                        _('Passes additional arguments to iptables. Use with care!'));
                o.modalonly = true;
index 48fd98ff28d0048471dfb8a63b43f129d555f16a..b46791587a15f1070a0c1322744a48cb6d2d7073 100644 (file)
@@ -81,10 +81,11 @@ function snat_proto_txt(s) {
        var m = uci.get('firewall', s, 'mark'),
            p = uci.get('firewall', s, 'proto');
 
-       return fmt(_('Match %{protocol?%{family} %{protocol} traffic:any %{family} traffic} %{mark?with firewall mark %{mark}}'), {
+       return fmt(_('Match %{protocol?%{family} %{protocol} traffic:any %{family} traffic} %{mark?with firewall mark %{mark}} %{limit?limited to %{limit}}'), {
                protocol: (p && p != 'all' && p != 'any' && p != '*') ? fwtool.fmt_proto(uci.get('firewall', s, 'proto')) : null,
                family:   fwtool.fmt_family('ipv4'),
-               mark:     m ? E('var', {}, fwtool.fmt_neg(m)) : null
+               mark:     m ? E('var', {}, fwtool.fmt_neg(m)) : null,
+               limit:  fwtool.fmt_limit(uci.get('firewall', s, 'limit'), uci.get('firewall', s, 'limit_burst'))
        });
 }
 
@@ -328,6 +329,42 @@ return L.view.extend({
                        return true;
                };
 
+               o = s.taboption('advanced', form.Value, 'limit', _('Limit matching'),
+                       _('Limits traffic matching to the specified rate.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = _('unlimited');
+               o.value('10/second');
+               o.value('60/minute');
+               o.value('3/hour');
+               o.value('500/day');
+               o.validate = function(section_id, value) {
+                       if (value == '')
+                               return true;
+
+                       var m = String(value).toLowerCase().match(/^(?:0x[0-9a-f]{1,8}|[0-9]{1,10})\/([a-z]+)$/),
+                           u = ['second', 'minute', 'hour', 'day'],
+                           i = 0;
+
+                       if (m)
+                               for (i = 0; i < u.length; i++)
+                                       if (u[i].indexOf(m[1]) == 0)
+                                               break;
+
+                       if (!m || i >= u.length)
+                               return _('Invalid limit value');
+
+                       return true;
+               };
+
+               o = s.taboption('advanced', form.Value, 'limit_burst', _('Limit burst'),
+                       _('Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not reached, up to this number.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = '5';
+               o.datatype = 'uinteger';
+               o.depends({ limit: null, '!reverse': true });
+
                o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
                        _('Passes additional arguments to iptables. Use with care!'));
                o.modalonly = true;