[pve-devel] [PATCH manager 1/1] change icmp type selector to a combogrid

Mira Limbeck m.limbeck at proxmox.com
Wed Apr 29 15:45:27 CEST 2020


The combogrid contains all valid icmp types that iptables accepts. In
addition to the names, the Type[/Code] value is shown as well.

As the simple solution with setStore() does not work to change the store
for the combogrid and the values are only set on the first field with
the corresponding name, a workaround using names and IDs was used to switch
between the icmp and icmpv6 type selector and have only one selector
with the name 'icmp-type' at any time.

Because perl hashes have random order, we can't be sure that icmp-type
is set after proto has been set to 'icmp' so set 'icmp-type' again after
all values have been set once. This makes sure the icmp type selector
contains the right value when editing a rule.

Signed-off-by: Mira Limbeck <m.limbeck at proxmox.com>
---
 www/manager6/grid/FirewallRules.js | 173 ++++++++++++++++++++++++++++-
 1 file changed, 169 insertions(+), 4 deletions(-)

diff --git a/www/manager6/grid/FirewallRules.js b/www/manager6/grid/FirewallRules.js
index 539e301d..289aee3c 100644
--- a/www/manager6/grid/FirewallRules.js
+++ b/www/manager6/grid/FirewallRules.js
@@ -46,6 +46,107 @@ Ext.define('PVE.form.FWMacroSelector', {
     }
 });
 
+Ext.define('PVE.form.ICMPTypeSelector', {
+    extend: 'Proxmox.form.ComboGrid',
+    alias: 'widget.pveICMPTypeSelector',
+    allowBlank: true,
+    autoSelect: false,
+    valueField: 'name',
+    displayField: 'name',
+    listConfig: {
+	columns: [
+	    {
+		header: gettext('Type'),
+		dataIndex: 'type',
+		hideable: false,
+		sortable: false,
+		width: 50,
+	    },
+	    {
+		header: gettext('Name'),
+		dataIndex: 'name',
+		hideable: false,
+		sortable: false,
+		flex: 1,
+	    },
+	],
+    },
+    setName: function(value) {
+	this.name = value;
+    }
+});
+
+let ICMP_TYPE_NAMES_STORE = Ext.create('Ext.data.Store', {
+    field: ['type', 'name'],
+    data: [
+	{ type: 'any', name: 'any' },
+	{ type: '0', name: 'echo-reply' },
+	{ type: '3', name: 'destination-unreachable' },
+	{ type: '3/0', name: 'network-unreachable' },
+	{ type: '3/1', name: 'host-unreachable' },
+	{ type: '3/2', name: 'protocol-unreachable' },
+	{ type: '3/3', name: 'port-unreachable' },
+	{ type: '3/4', name: 'fragmentation-needed' },
+	{ type: '3/5', name: 'source-route-failed' },
+	{ type: '3/6', name: 'network-unknown' },
+	{ type: '3/7', name: 'host-unknown' },
+	{ type: '3/9', name: 'network-prohibited' },
+	{ type: '3/10', name: 'host-prohibited' },
+	{ type: '3/11', name: 'TOS-network-unreachable' },
+	{ type: '3/12', name: 'TOS-host-unreachable' },
+	{ type: '3/13', name: 'communication-prohibited' },
+	{ type: '3/14', name: 'host-precedence-violation' },
+	{ type: '3/15', name: 'precedence-cutoff' },
+	{ type: '4', name: 'source-quench' },
+	{ type: '5', name: 'redirect' },
+	{ type: '5/0', name: 'network-redirect' },
+	{ type: '5/1', name: 'host-redirect' },
+	{ type: '5/2', name: 'TOS-network-redirect' },
+	{ type: '5/3', name: 'TOS-host-redirect' },
+	{ type: '8', name: 'echo-request' },
+	{ type: '9', name: 'router-advertisement' },
+	{ type: '10', name: 'router-solicitation' },
+	{ type: '11', name: 'time-exceeded' },
+	{ type: '11/0', name: 'ttl-zero-during-transit' },
+	{ type: '11/1', name: 'ttl-zero-during-reassembly' },
+	{ type: '12', name: 'parameter-problem' },
+	{ type: '12/0', name: 'ip-header-bad' },
+	{ type: '12/1', name: 'required-option-missing' },
+	{ type: '13', name: 'timestamp-request' },
+	{ type: '14', name: 'timestamp-reply' },
+	{ type: '17', name: 'address-mask-request' },
+	{ type: '18', name: 'address-mask-reply' },
+    ],
+});
+let ICMPV6_TYPE_NAMES_STORE = Ext.create('Ext.data.Store', {
+    field: ['type', 'name'],
+    data: [
+	{ type: '1', name: 'destination-unreachable' },
+	{ type: '1/0', name: 'no-route' },
+	{ type: '1/1', name: 'communication-prohibited' },
+	{ type: '1/2', name: 'beyond-scope' },
+	{ type: '1/3', name: 'address-unreachable' },
+	{ type: '1/4', name: 'port-unreachable' },
+	{ type: '1/5', name: 'failed-policy' },
+	{ type: '1/6', name: 'reject-route', },
+	{ type: '2', name: 'packet-too-big' },
+	{ type: '3', name: 'time-exceeded' },
+	{ type: '3/0', name: 'ttl-zero-during-transit' },
+	{ type: '3/1', name: 'ttl-zero-during-reassembly' },
+	{ type: '4', name: 'parameter-problem' },
+	{ type: '4/0', name: 'bad-header' },
+	{ type: '4/1', name: 'unknown-header-type' },
+	{ type: '4/2', name: 'unknown-option' },
+	{ type: '128', name: 'echo-request' },
+	{ type: '129', name: 'echo-reply' },
+	{ type: '133', name: 'router-solicitation' },
+	{ type: '134', name: 'router-advertisement' },
+	{ type: '135', name: 'neighbour-solicitation' },
+	{ type: '136', name: 'neighbour-advertisement' },
+	{ type: '137', name: 'redirect' },
+    ],
+});
+
 Ext.define('PVE.FirewallRulePanel', {
     extend: 'Proxmox.panel.InputPanel',
 
@@ -59,7 +160,7 @@ Ext.define('PVE.FirewallRulePanel', {
 	// hack: editable ComboGrid returns nothing when empty, so we need to set ''
 	// Also, disabled text fields return nothing, so we need to set ''
 
-	Ext.Array.each(['source', 'dest', 'macro', 'proto', 'sport', 'dport', 'log'], function(key) {
+	Ext.Array.each(['source', 'dest', 'macro', 'proto', 'sport', 'dport', 'icmp-type', 'log'], function(key) {
 	    if (values[key] === undefined) {
 		values[key] = '';
 	    }
@@ -186,7 +287,43 @@ Ext.define('PVE.FirewallRulePanel', {
 		autoSelect: false,
 		editable: true,
 		value: '',
-		fieldLabel: gettext('Protocol')
+		fieldLabel: gettext('Protocol'),
+		listeners: {
+		    change: function(f, value) {
+			if (value === 'icmp' || value === 'icmpv6' || value === 'ipv6-icmp') {
+			    me.down('field[name=dport]').setHidden(true);
+			    me.down('field[name=dport]').setDisabled(true);
+			    me.down('field[name=dport]').setValue('');
+			    if (value === 'icmp') {
+				me.down('#icmpv4-type').setHidden(false);
+				me.down('#icmpv4-type').setDisabled(false);
+				me.down('#icmpv4-type').setName('icmp-type');
+				me.down('#icmpv6-type').setHidden(true);
+				me.down('#icmpv6-type').setDisabled(true);
+				me.down('#icmpv6-type').setName('icmpv6-type');
+			    } else {
+				me.down('#icmpv6-type').setHidden(false);
+				me.down('#icmpv6-type').setDisabled(false);
+				me.down('#icmpv6-type').setName('icmp-type');
+				me.down('#icmpv4-type').setHidden(true);
+				me.down('#icmpv4-type').setDisabled(true);
+				me.down('#icmpv4-type').setName('icmpv4-type');
+			    }
+
+			} else {
+			    me.down('#icmpv4-type').setHidden(true);
+			    me.down('#icmpv4-type').setDisabled(true);
+			    me.down('#icmpv4-type').setValue('');
+			    me.down('#icmpv4-type').setName('icmpv4-type');
+			    me.down('#icmpv6-type').setHidden(true);
+			    me.down('#icmpv6-type').setDisabled(true);
+			    me.down('#icmpv6-type').setValue('');
+			    me.down('#icmpv6-type').setName('icmpv6-type');
+			    me.down('field[name=dport]').setHidden(false);
+			    me.down('field[name=dport]').setDisabled(false);
+			}
+		    }
+		},
 	    },
 	    {
 		xtype: 'displayfield',
@@ -204,8 +341,32 @@ Ext.define('PVE.FirewallRulePanel', {
 		xtype: 'textfield',
 		name: 'dport',
 		value: '',
-		fieldLabel: gettext('Dest. port')
-	    }
+		fieldLabel: gettext('Dest. port'),
+	    },
+	    {
+		xtype: 'pveICMPTypeSelector',
+		name: 'icmpv4-type',
+		id: 'icmpv4-type',
+		autoSelect: false,
+		editable: true,
+		hidden: true,
+		disabled: true,
+		value: '',
+		fieldLabel: gettext('ICMP type'),
+		store: ICMP_TYPE_NAMES_STORE,
+	    },
+	    {
+		xtype: 'pveICMPTypeSelector',
+		name: 'icmpv6-type',
+		id: 'icmpv6-type',
+		autoSelect: false,
+		editable: true,
+		hidden: true,
+		disabled: true,
+		value: '',
+		fieldLabel: gettext('ICMP type'),
+		store: ICMPV6_TYPE_NAMES_STORE,
+	    },
 	];
 
 	me.advancedColumn1 = [
@@ -276,6 +437,10 @@ Ext.define('PVE.FirewallRuleEdit', {
 		success: function(response, options) {
 		    var values = response.result.data;
 		    ipanel.setValues(values);
+		    // set icmp-type again after protocol has been set
+		    if (values["icmp-type"] !== undefined) {
+			ipanel.setValues({"icmp-type": values["icmp-type"]});
+		    }
 		    if (values.errors) {
 			var field = me.query('[isFormField][name=modified_marker]')[0];
 			field.setValue(1);
-- 
2.20.1





More information about the pve-devel mailing list