luci-app-firewall: support 'DSCP' action and matches for rules
[project/luci.git] / applications / luci-app-firewall / htdocs / luci-static / resources / view / firewall / rules.js
index 1d9af33fca57a8518be9ddc087013ea0867f65cb..9d8d8d15598312ae370e61864f8cdb7d51e4c6f6 100644 (file)
@@ -393,6 +393,85 @@ return L.view.extend({
                o.value('REJECT', _('reject'));
                o.value('NOTRACK', _("don't track"));
                o.value('HELPER', _('assign conntrack helper'));
+               o.value('MARK_SET', _('apply firewall mark'));
+               o.value('MARK_XOR', _('XOR firewall mark'));
+               o.value('DSCP', _('DSCP classification'));
+               o.cfgvalue = function(section_id) {
+                       var t = uci.get('firewall', section_id, 'target'),
+                           m = uci.get('firewall', section_id, 'set_mark');
+
+                       if (t == 'MARK')
+                               return m ? 'MARK_SET' : 'MARK_XOR';
+
+                       return t;
+               };
+               o.write = function(section_id, value) {
+                       return this.super('write', [section_id, (value == 'MARK_SET' || value == 'MARK_XOR') ? 'MARK' : value]);
+               };
+
+               o = s.taboption('general', form.Value, 'set_mark', _('Set mark'), _('Set the given mark value on established connections. Format is value[/mask]. If a mask is specified then only those bits set in the mask are modified.'));
+               o.modalonly = true;
+               o.rmempty = false;
+               o.depends('target', 'MARK_SET');
+               o.validate = function(section_id, value) {
+                       var m = String(value).match(/^(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
+
+                       if (!m || +m[1] > 0xffffffff || (m[2] != null && +m[2] > 0xffffffff))
+                               return _('Expecting: %s').format(_('valid firewall mark'));
+
+                       return true;
+               };
+
+               o = s.taboption('general', form.Value, 'set_xmark', _('XOR mark'), _('Apply a bitwise XOR of the given value and the existing mark value on established connections. Format is value[/mask]. If a mask is specified then those bits set in the mask are zeroed out.'));
+               o.modalonly = true;
+               o.rmempty = false;
+               o.depends('target', 'MARK_XOR');
+               o.validate = function(section_id, value) {
+                       var m = String(value).match(/^(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
+
+                       if (!m || +m[1] > 0xffffffff || (m[2] != null && +m[2] > 0xffffffff))
+                               return _('Expecting: %s').format(_('valid firewall mark'));
+
+                       return true;
+               };
+
+               o = s.taboption('general', form.Value, 'set_dhcp', _('DSCP mark'), _('Apply the given DSCP class or value to established connections.'));
+               o.modalonly = true;
+               o.rmempty = false;
+               o.depends('target', 'DSCP');
+               o.value('CS0');
+               o.value('CS1');
+               o.value('CS2');
+               o.value('CS3');
+               o.value('CS4');
+               o.value('CS5');
+               o.value('CS6');
+               o.value('CS7');
+               o.value('BE');
+               o.value('AF11');
+               o.value('AF12');
+               o.value('AF13');
+               o.value('AF21');
+               o.value('AF22');
+               o.value('AF23');
+               o.value('AF31');
+               o.value('AF32');
+               o.value('AF33');
+               o.value('AF41');
+               o.value('AF42');
+               o.value('AF43');
+               o.value('EF');
+               o.validate = function(section_id, value) {
+                       if (value == '')
+                               return _('DSCP mark required');
+
+                       var m = String(value).match(/^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
+
+                       if (!m || (m[1] != null && +m[1] > 0x3f))
+                               return _('Invalid DSCP mark');
+
+                       return true;
+               };
 
                o = s.taboption('general', form.ListValue, 'set_helper', _('Tracking helper'), _('Assign the specified connection tracking helper to matched traffic.'));
                o.modalonly = true;
@@ -419,6 +498,63 @@ return L.view.extend({
                        return _('Unknown or not installed conntrack helper "%s"').format(value);
                };
 
+               o = s.taboption('advanced', form.Value, 'mark', _('Match mark'),
+                       _('Matches a specific firewall mark or a range of different marks.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.validate = function(section_id, value) {
+                       if (value == '')
+                               return true;
+
+                       var m = String(value).match(/^(?:!\s*)?(0x[0-9a-f]{1,8}|[0-9]{1,10})(?:\/(0x[0-9a-f]{1,8}|[0-9]{1,10}))?$/i);
+
+                       if (!m || +m[1] > 0xffffffff || (m[2] != null && +m[2] > 0xffffffff))
+                               return _('Expecting: %s').format(_('valid firewall mark'));
+
+                       return true;
+               };
+
+               o = s.taboption('advanced', form.Value, 'dscp', _('Match DSCP'),
+                       _('Matches traffic carrying the specified DSCP marking.'));
+               o.modalonly = true;
+               o.rmempty = true;
+               o.placeholder = _('any');
+               o.value('CS0');
+               o.value('CS1');
+               o.value('CS2');
+               o.value('CS3');
+               o.value('CS4');
+               o.value('CS5');
+               o.value('CS6');
+               o.value('CS7');
+               o.value('BE');
+               o.value('AF11');
+               o.value('AF12');
+               o.value('AF13');
+               o.value('AF21');
+               o.value('AF22');
+               o.value('AF23');
+               o.value('AF31');
+               o.value('AF32');
+               o.value('AF33');
+               o.value('AF41');
+               o.value('AF42');
+               o.value('AF43');
+               o.value('EF');
+               o.validate = function(section_id, value) {
+                       if (value == '')
+                               return true;
+
+                       value = String(value).replace(/^!\s*/, '');
+
+                       var m = value.match(/^(?:CS[0-7]|BE|AF[1234][123]|EF|(0x[0-9a-f]{1,2}|[0-9]{1,2}))$/);
+
+                       if (!m || +m[1] > 0xffffffff || (m[2] != null && +m[2] > 0xffffffff))
+                               return _('Invalid DSCP mark');
+
+                       return true;
+               };
+
                o = s.taboption('advanced', form.Value, 'extra', _('Extra arguments'),
                        _('Passes additional arguments to iptables. Use with care!'));
                o.modalonly = true;