You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by we...@apache.org on 2023/12/01 10:59:29 UTC
(cloudstack) branch 4.19-list-network-protocols created (now d17a600c4da)
This is an automated email from the ASF dual-hosted git repository.
weizhou pushed a change to branch 4.19-list-network-protocols
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
at d17a600c4da api/utils/ui: List protocol numbers and icmp types
This branch includes the following new commits:
new d17a600c4da api/utils/ui: List protocol numbers and icmp types
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(cloudstack) 01/01: api/utils/ui: List protocol numbers and icmp types
Posted by we...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
weizhou pushed a commit to branch 4.19-list-network-protocols
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
commit d17a600c4dac3a52bef67a9164bd7ab9306b22f9
Author: Wei Zhou <we...@apache.org>
AuthorDate: Fri Dec 1 11:55:15 2023 +0100
api/utils/ui: List protocol numbers and icmp types
---
.../org/apache/cloudstack/api/ApiConstants.java | 1 +
.../user/network/ListNetworkProtocolsCmd.java | 109 +++++++
.../api/response/NetworkProtocolResponse.java | 89 ++++++
.../network/security/SecurityGroupManagerImpl.java | 26 +-
.../cloud/network/vpc/NetworkACLServiceImpl.java | 5 +-
.../com/cloud/server/ManagementServerImpl.java | 2 +
ui/src/views/network/AclListRulesTab.vue | 96 +++++-
ui/src/views/network/EgressRulesTab.vue | 62 +++-
ui/src/views/network/FirewallRules.vue | 63 +++-
.../views/network/IngressEgressRuleConfigure.vue | 77 ++++-
.../main/java/com/cloud/utils/net/NetUtils.java | 15 +
.../java/com/cloud/utils/net/NetworkProtocols.java | 344 +++++++++++++++++++++
12 files changed, 844 insertions(+), 45 deletions(-)
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 4b437516bd8..c434db8b6bc 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -316,6 +316,7 @@ public class ApiConstants {
public static final String IS_DEFAULT_USE = "defaultuse";
public static final String OLD_FORMAT = "oldformat";
public static final String OP = "op";
+ public static final String OPTION = "option";
public static final String OPTIONS = "options";
public static final String OS_CATEGORY_ID = "oscategoryid";
public static final String OS_CATEGORY_NAME = "oscategoryname";
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmd.java
new file mode 100644
index 00000000000..3008d1a8191
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworkProtocolsCmd.java
@@ -0,0 +1,109 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.command.user.network;
+
+import com.cloud.utils.net.NetworkProtocols;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.NetworkProtocolResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.log4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@APICommand(name = "listNetworkProtocols", description = "Lists details of network protocols", responseObject = NetworkProtocolResponse.class,
+ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false,
+ authorized = { RoleType.Admin, RoleType.DomainAdmin, RoleType.ResourceAdmin, RoleType.User}, since = "4.19.0")
+public class ListNetworkProtocolsCmd extends BaseCmd {
+ public static final Logger s_logger = Logger.getLogger(ListNetworkProtocolsCmd.class.getName());
+
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name = ApiConstants.OPTION, type = CommandType.STRING, required = true,
+ description = "The option of network protocols. Supported values are: protocolnumber, icmptype.")
+ private String option;
+
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public String getOption() {
+ return option;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public void execute() {
+ ListResponse<NetworkProtocolResponse> response = new ListResponse<>();
+ List<NetworkProtocolResponse> networkProtocolResponses = new ArrayList<>();
+
+ NetworkProtocols.Option option = NetworkProtocols.Option.getOption(getOption());
+ switch (option) {
+ case ProtocolNumber:
+ updateResponseWithProtocolNumbers(networkProtocolResponses);
+ break;
+ case IcmpType:
+ updateResponseWithIcmpTypes(networkProtocolResponses);
+ break;
+ default:
+ break;
+ }
+
+ response.setResponses(networkProtocolResponses);
+ response.setResponseName(getCommandName());
+ setResponseObject(response);
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return CallContext.current().getCallingAccount().getId();
+ }
+
+ private void updateResponseWithProtocolNumbers(List<NetworkProtocolResponse> responses) {
+ for (NetworkProtocols.ProtocolNumber protocolNumber : NetworkProtocols.ProtocolNumbers) {
+ NetworkProtocolResponse networkProtocolResponse = new NetworkProtocolResponse(protocolNumber.getNumber(),
+ protocolNumber.getKeyword(), protocolNumber.getProtocol());
+ networkProtocolResponse.setObjectName("networkprotocol");
+ responses.add(networkProtocolResponse);
+ }
+ }
+
+ private void updateResponseWithIcmpTypes(List<NetworkProtocolResponse> responses) {
+ for (NetworkProtocols.IcmpType icmpType : NetworkProtocols.IcmpTypes) {
+ NetworkProtocolResponse networkProtocolResponse = new NetworkProtocolResponse(icmpType.getType(),
+ null, icmpType.getDescription());
+ for (NetworkProtocols.IcmpCode code : icmpType.getIcmpCodes()) {
+ networkProtocolResponse.addDetail(String.valueOf(code.getCode()), code.getDescription());
+ }
+ networkProtocolResponse.setObjectName("networkprotocol");
+ responses.add(networkProtocolResponse);
+ }
+ }
+}
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkProtocolResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkProtocolResponse.java
new file mode 100644
index 00000000000..775333f7192
--- /dev/null
+++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkProtocolResponse.java
@@ -0,0 +1,89 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package org.apache.cloudstack.api.response;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class NetworkProtocolResponse extends BaseResponse {
+ @SerializedName(ApiConstants.INDEX)
+ @Param(description = "the index (ID, Value, Code, Type, Option, etc) of the protocol parameter")
+ private Integer index;
+
+ @SerializedName(ApiConstants.NAME)
+ @Param(description = "the name of the protocol parameter")
+ private String name;
+
+ @SerializedName(ApiConstants.DESCRIPTION)
+ @Param(description = "the description of the protocol parameter")
+ private String description;
+
+ @SerializedName(ApiConstants.DETAILS)
+ @Param(description = "the details of the protocol parameter")
+ private Map details;
+
+ public NetworkProtocolResponse(Integer index, String name, String description) {
+ this.index = index;
+ this.name = name;
+ this.description = description;
+ }
+
+ public Integer getIndex() {
+ return index;
+ }
+
+ public void setIndex(Integer index) {
+ this.index = index;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Map getDetails() {
+ return details;
+ }
+
+ public void setDetails(Map details) {
+ this.details = details;
+ }
+
+ public void addDetail(String key, String value) {
+ if (this.details == null) {
+ this.details = new LinkedHashMap();
+ }
+ this.details.put(key, value);
+ }
+}
diff --git a/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java
index f13e6ac7a4b..1ea481992ed 100644
--- a/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/security/SecurityGroupManagerImpl.java
@@ -661,10 +661,14 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
if(StringUtils.isNumeric(protocol)){
int protoNumber = Integer.parseInt(protocol);
// Deal with ICMP(protocol number 1) specially because it need to be paired with icmp type and code
- if (protoNumber == 1) {
- protocol = "icmp";
- icmpCode = -1;
- icmpType = -1;
+ if (protoNumber == NetUtils.ICMP_PROTO_NUMBER) {
+ protocol = NetUtils.ICMP_PROTO;
+ if (icmpCode == null) {
+ icmpCode = -1;
+ }
+ if (icmpType == null) {
+ icmpType = -1;
+ }
} else if(protoNumber < 0 || protoNumber > 255){
throw new InvalidParameterValueException("Invalid protocol number: " + protoNumber);
}
@@ -676,18 +680,7 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
}
}
if (protocol.equals(NetUtils.ICMP_PROTO)) {
- if ((icmpType == null) || (icmpCode == null)) {
- throw new InvalidParameterValueException("Invalid ICMP type/code specified, icmpType = " + icmpType + ", icmpCode = " + icmpCode);
- }
- if (icmpType == -1 && icmpCode != -1) {
- throw new InvalidParameterValueException("Invalid icmp code");
- }
- if (icmpType != -1 && icmpCode == -1) {
- throw new InvalidParameterValueException("Invalid icmp code: need non-negative icmp code ");
- }
- if (icmpCode > 255 || icmpType > 255 || icmpCode < -1 || icmpType < -1) {
- throw new InvalidParameterValueException("Invalid icmp type/code ");
- }
+ NetUtils.validateIcmpTypeAndCode(icmpType, icmpCode);
startPortOrType = icmpType;
endPortOrCode = icmpCode;
} else if (protocol.equals(NetUtils.ALL_PROTO)) {
@@ -788,6 +781,7 @@ public class SecurityGroupManagerImpl extends ManagerBase implements SecurityGro
SecurityGroupRuleVO securityGroupRule = _securityGroupRuleDao.findByProtoPortsAndAllowedGroupId(securityGroup.getId(), protocolFinal, startPortOrTypeFinal,
endPortOrCodeFinal, ngVO.getId());
if ((securityGroupRule != null) && (securityGroupRule.getRuleType() == ruleType)) {
+ s_logger.warn("The rule already exists. id= " + securityGroupRule.getUuid());
continue; // rule already exists.
}
securityGroupRule = new SecurityGroupRuleVO(ruleType, securityGroup.getId(), startPortOrTypeFinal, endPortOrCodeFinal, protocolFinal, ngVO.getId());
diff --git a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java
index 8139ac1c49e..e544a244a53 100644
--- a/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java
+++ b/server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java
@@ -583,10 +583,13 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ
Integer icmpCode = networkACLItemVO.getIcmpCode();
Integer icmpType = networkACLItemVO.getIcmpType();
// icmp code and icmp type can't be passed in for any other protocol rather than icmp
- boolean isIcmpProtocol = protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO);
+ boolean isIcmpProtocol = protocol.equalsIgnoreCase(NetUtils.ICMP_PROTO) || protocol.equalsIgnoreCase(String.valueOf(NetUtils.ICMP_PROTO_NUMBER));
if (!isIcmpProtocol && (icmpCode != null || icmpType != null)) {
throw new InvalidParameterValueException("Can specify icmpCode and icmpType for ICMP protocol only");
}
+ if (isIcmpProtocol) {
+ NetUtils.validateIcmpTypeAndCode(icmpType, icmpCode);
+ }
Integer sourcePortStart = networkACLItemVO.getSourcePortStart();
Integer sourcePortEnd = networkACLItemVO.getSourcePortEnd();
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index 7548b768327..f9908592455 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -433,6 +433,7 @@ import org.apache.cloudstack.api.command.user.network.ListNetworkACLListsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkACLsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkOfferingsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworkPermissionsCmd;
+import org.apache.cloudstack.api.command.user.network.ListNetworkProtocolsCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.MoveNetworkAclItemCmd;
import org.apache.cloudstack.api.command.user.network.RemoveNetworkPermissionsCmd;
@@ -3607,6 +3608,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(DeleteNetworkCmd.class);
cmdList.add(ListNetworkACLsCmd.class);
cmdList.add(ListNetworkOfferingsCmd.class);
+ cmdList.add(ListNetworkProtocolsCmd.class);
cmdList.add(ListNetworksCmd.class);
cmdList.add(RestartNetworkCmd.class);
cmdList.add(UpdateNetworkCmd.class);
diff --git a/ui/src/views/network/AclListRulesTab.vue b/ui/src/views/network/AclListRulesTab.vue
index 6675500ed80..65be39e1012 100644
--- a/ui/src/views/network/AclListRulesTab.vue
+++ b/ui/src/views/network/AclListRulesTab.vue
@@ -64,19 +64,19 @@
<div class="list__label">{{ $t('label.protocol') }}</div>
<div>{{ element.protocol }}</div>
</div>
- <div class="list__col" v-if="element.startport">
+ <div class="list__col" v-if="element.startport !== undefined">
<div class="list__label">{{ $t('label.startport') }}</div>
<div>{{ element.startport }}</div>
</div>
- <div class="list__col" v-if="element.endport">
+ <div class="list__col" v-if="element.endport !== undefined">
<div class="list__label">{{ $t('label.endport') }}</div>
<div>{{ element.endport }}</div>
</div>
- <div class="list__col" v-if="element.icmpcode">
+ <div class="list__col" v-if="element.icmpcode !== undefined">
<div class="list__label">{{ $t('label.icmpcode') }}</div>
<div>{{ element.icmpcode }}</div>
</div>
- <div class="list__col" v-if="element.icmptype">
+ <div class="list__col" v-if="element.icmptype !== undefined">
<div class="list__label">{{ $t('label.icmptype') }}</div>
<div>{{ element.icmptype }}</div>
</div>
@@ -208,19 +208,50 @@
:label="$t('label.protocolnumber')"
ref="protocolnumber"
name="protocolnumber">
- <a-input v-model:value="form.protocolnumber" />
+ <a-select
+ v-model:value="form.protocolnumber"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt, optIndex) in protocolNumbers" :key="optIndex" :label="opt.name">
+ {{ opt.index + ' - ' + opt.name }}
+ </a-select-option>
+ </a-select>
</a-form-item>
- <div v-if="['icmp', 'protocolnumber'].includes(form.protocol)">
+ <div v-if="form.protocol === 'icmp' || (form.protocol === 'protocolnumber' && form.protocolnumber === 1)">
<a-form-item :label="$t('label.icmptype')" ref="icmptype" name="icmptype">
- <a-input v-model:value="form.icmptype" :placeholder="$t('icmp.type.desc')" />
+ <a-select
+ v-model:value="form.icmptype"
+ @change="val => { updateIcmpCodes(val) }"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpTypes" :key="opt.index" :label="opt.description">
+ {{ opt.index + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</a-form-item>
<a-form-item :label="$t('label.icmpcode')" ref="icmpcode" name="icmpcode">
- <a-input v-model:value="form.icmpcode" :placeholder="$t('icmp.code.desc')" />
+ <a-select
+ v-model:value="form.icmpcode"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpCodes" :key="opt.code" :label="opt.description">
+ {{ opt.code + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</a-form-item>
</div>
- <div v-show="['tcp', 'udp', 'protocolnumber'].includes(form.protocol)">
+ <div v-show="['tcp', 'udp', 'protocolnumber'].includes(form.protocol) && !(form.protocol === 'protocolnumber' && form.protocolnumber === 1)">
<a-form-item :label="$t('label.startport')" ref="startport" name="startport">
<a-input-number style="width: 100%" v-model:value="form.startport" />
</a-form-item>
@@ -285,6 +316,9 @@ export default {
return {
acls: [],
fetchLoading: false,
+ protocolNumbers: [],
+ icmpTypes: [],
+ icmpCodes: [],
tags: [],
selectedAcl: null,
tagsModalVisible: false,
@@ -296,6 +330,7 @@ export default {
},
created () {
this.initForm()
+ this.fetchNetworkProtocols()
this.fetchData()
},
watch: {
@@ -310,6 +345,8 @@ export default {
this.formRef = ref()
this.form = reactive({})
this.rules = reactive({})
+ this.form.icmptype = -1
+ this.form.icmpcode = -1
},
csv ({ data = null, columnDelimiter = ',', lineDelimiter = '\n' }) {
let result = null
@@ -341,6 +378,34 @@ export default {
return result
},
+ fetchNetworkProtocols () {
+ api('listNetworkProtocols', {
+ option: 'protocolnumber'
+ }).then(json => {
+ this.protocolNumbers = json.listnetworkprotocolsresponse?.networkprotocol || []
+ })
+ api('listNetworkProtocols', {
+ option: 'icmptype'
+ }).then(json => {
+ this.icmpTypes.push({ index: -1, description: this.$t('label.all') })
+ const results = json.listnetworkprotocolsresponse?.networkprotocol || []
+ for (const result of results) {
+ this.icmpTypes.push(result)
+ }
+ })
+ },
+ updateIcmpCodes (val) {
+ this.form.icmpcode = -1
+ this.icmpCodes = []
+ this.icmpCodes.push({ code: -1, description: this.$t('label.all') })
+ const icmpType = this.icmpTypes.find(icmpType => icmpType.index === val)
+ if (icmpType && icmpType.details) {
+ const icmpTypeDetails = icmpType.details
+ for (const k of Object.keys(icmpTypeDetails)) {
+ this.icmpCodes.push({ code: parseInt(k), description: icmpTypeDetails[k] })
+ }
+ }
+ },
fetchData () {
this.fetchLoading = true
api('listNetworkACLs', { aclid: this.resource.id }).then(json => {
@@ -466,8 +531,15 @@ export default {
self.form.cidrlist = acl.cidrlist
self.form.action = acl.action
self.form.protocol = acl.protocol
+ if (!['tcp', 'udp', 'icmp', 'all'].includes(acl.protocol)) {
+ self.form.protocol = 'protocolnumber'
+ self.form.protocolnumber = parseInt(acl.protocol)
+ }
self.form.startport = acl.startport
self.form.endport = acl.endport
+ self.form.icmptype = parseInt(acl.icmptype)
+ this.updateIcmpCodes(self.form.icmptype)
+ self.form.icmpcode = acl.icmpcode
self.form.traffictype = acl.traffictype
self.form.reason = acl.reason
}, 200)
@@ -487,9 +559,9 @@ export default {
data.endport = values.endport || ''
}
- if (values.protocol === 'icmp') {
- data.icmptype = values.icmptype || -1
- data.icmpcode = values.icmpcode || -1
+ if (values.protocol === 'icmp' || (values.protocol === 'protocolnumber' && values.protocolnumber === 1)) {
+ data.icmptype = values.icmptype
+ data.icmpcode = values.icmpcode
}
if (values.protocol === 'protocolnumber') {
diff --git a/ui/src/views/network/EgressRulesTab.vue b/ui/src/views/network/EgressRulesTab.vue
index a0fb7085534..4e9d3b8d649 100644
--- a/ui/src/views/network/EgressRulesTab.vue
+++ b/ui/src/views/network/EgressRulesTab.vue
@@ -63,11 +63,32 @@
</div>
<div v-show="newRule.protocol === 'icmp'" class="form__item">
<div class="form__label">{{ $t('label.icmptype') }}</div>
- <a-input v-model:value="newRule.icmptype"></a-input>
+ <a-select
+ v-model:value="newRule.icmptype"
+ @change="val => { updateIcmpCodes(val) }"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpTypes" :key="opt.index" :label="opt.description">
+ {{ opt.index + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</div>
<div v-show="newRule.protocol === 'icmp'" class="form__item">
<div class="form__label">{{ $t('label.icmpcode') }}</div>
- <a-input v-model:value="newRule.icmpcode"></a-input>
+ <a-select
+ v-model:value="newRule.icmpcode"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpCodes" :key="opt.code" :label="opt.description">
+ {{ opt.code + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</div>
<div class="form__item">
<a-button ref="submit" :disabled="!('createEgressFirewallRule' in $store.getters.apis)" type="primary" @click="addRule">
@@ -97,15 +118,16 @@
:pagination="false"
:rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
:rowKey="record => record.id">
+<<<<<<< HEAD
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'protocol'">
{{ getCapitalise(record.protocol) }}
</template>
<template v-if="column.key === 'startport'">
- {{ record.icmptype || record.startport >= 0 ? record.icmptype || record.startport : 'All' }}
+ {{ record.icmptype >= 0 ? String(record.icmptype): record.startport >= 0 ? String(record.startport): 'All' }}
</template>
<template v-if="column.key === 'endport'">
- {{ record.icmpcode || record.endport >= 0 ? record.icmpcode || record.endport : 'All' }}
+ {{ record.icmpcode >= 0 ? String(record.icmpcode): record.endport >= 0 ? String(record.endport): 'All' }}
</template>
<template v-if="column.key === 'actions'">
<tooltip-button
@@ -196,6 +218,9 @@ export default {
startport: null,
endport: null
},
+ protocolNumbers: [],
+ icmpTypes: [],
+ icmpCodes: [],
totalCount: 0,
page: 1,
pageSize: 10,
@@ -233,6 +258,7 @@ export default {
}
},
created () {
+ this.fetchNetworkProtocols()
this.fetchData()
},
watch: {
@@ -248,6 +274,34 @@ export default {
},
inject: ['parentFetchData'],
methods: {
+ fetchNetworkProtocols () {
+ api('listNetworkProtocols', {
+ option: 'protocolnumber'
+ }).then(json => {
+ this.protocolNumbers = json.listnetworkprotocolsresponse?.networkprotocol || []
+ })
+ api('listNetworkProtocols', {
+ option: 'icmptype'
+ }).then(json => {
+ this.icmpTypes.push({ index: -1, description: this.$t('label.all') })
+ const results = json.listnetworkprotocolsresponse?.networkprotocol || []
+ for (const result of results) {
+ this.icmpTypes.push(result)
+ }
+ })
+ },
+ updateIcmpCodes (val) {
+ this.newRule.icmpcode = -1
+ this.icmpCodes = []
+ this.icmpCodes.push({ code: -1, description: this.$t('label.all') })
+ const icmpType = this.icmpTypes.find(icmpType => icmpType.index === val)
+ if (icmpType && icmpType.details) {
+ const icmpTypeDetails = icmpType.details
+ for (const k of Object.keys(icmpTypeDetails)) {
+ this.icmpCodes.push({ code: parseInt(k), description: icmpTypeDetails[k] })
+ }
+ }
+ },
fetchData () {
this.loading = true
api('listEgressFirewallRules', {
diff --git a/ui/src/views/network/FirewallRules.vue b/ui/src/views/network/FirewallRules.vue
index 787f5c2d8e2..43ee9536be5 100644
--- a/ui/src/views/network/FirewallRules.vue
+++ b/ui/src/views/network/FirewallRules.vue
@@ -49,11 +49,32 @@
</div>
<div v-show="newRule.protocol === 'icmp'" class="form__item">
<div class="form__label">{{ $t('label.icmptype') }}</div>
- <a-input v-model:value="newRule.icmptype"></a-input>
+ <a-select
+ v-model:value="newRule.icmptype"
+ @change="val => { updateIcmpCodes(val) }"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpTypes" :key="opt.index" :label="opt.description">
+ {{ opt.index + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</div>
<div v-show="newRule.protocol === 'icmp'" class="form__item">
<div class="form__label">{{ $t('label.icmpcode') }}</div>
- <a-input v-model:value="newRule.icmpcode"></a-input>
+ <a-select
+ v-model:value="newRule.icmpcode"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpCodes" :key="opt.code" :label="opt.description">
+ {{ opt.code + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</div>
<div class="form__item" style="margin-left: auto;">
<a-button :disabled="!('createFirewallRule' in $store.getters.apis)" type="primary" ref="submit" @click="addRule">{{ $t('label.add') }}</a-button>
@@ -85,10 +106,10 @@
{{ getCapitalise(record.protocol) }}
</template>
<template v-if="column.key === 'startport'">
- {{ record.icmptype || record.startport >= 0 ? record.icmptype || record.startport : $t('label.all') }}
+ {{ record.icmptype >= 0 ? String(record.icmptype): record.startport >= 0 ? String(record.startport): 'All' }}
</template>
<template v-if="column.key === 'endport'">
- {{ record.icmpcode || record.endport >= 0 ? record.icmpcode || record.endport : $t('label.all') }}
+ {{ record.icmpcode >= 0 ? String(record.icmpcode): record.endport >= 0 ? String(record.endport): 'All' }}
</template>
<template v-if="column.key === 'actions'">
<div class="actions">
@@ -238,6 +259,9 @@ export default {
startport: null,
endport: null
},
+ protocolNumbers: [],
+ icmpTypes: [],
+ icmpCodes: [],
tagsModalVisible: false,
selectedRule: null,
tags: [],
@@ -279,6 +303,7 @@ export default {
},
created () {
this.initForm()
+ this.fetchNetworkProtocols()
this.fetchData()
},
watch: {
@@ -301,6 +326,34 @@ export default {
value: [{ required: true, message: this.$t('message.specify.tag.value') }]
})
},
+ fetchNetworkProtocols () {
+ api('listNetworkProtocols', {
+ option: 'protocolnumber'
+ }).then(json => {
+ this.protocolNumbers = json.listnetworkprotocolsresponse?.networkprotocol || []
+ })
+ api('listNetworkProtocols', {
+ option: 'icmptype'
+ }).then(json => {
+ this.icmpTypes.push({ index: -1, description: this.$t('label.all') })
+ const results = json.listnetworkprotocolsresponse?.networkprotocol || []
+ for (const result of results) {
+ this.icmpTypes.push(result)
+ }
+ })
+ },
+ updateIcmpCodes (val) {
+ this.newRule.icmpcode = -1
+ this.icmpCodes = []
+ this.icmpCodes.push({ code: -1, description: this.$t('label.all') })
+ const icmpType = this.icmpTypes.find(icmpType => icmpType.index === val)
+ if (icmpType && icmpType.details) {
+ const icmpTypeDetails = icmpType.details
+ for (const k of Object.keys(icmpTypeDetails)) {
+ this.icmpCodes.push({ code: parseInt(k), description: icmpTypeDetails[k] })
+ }
+ }
+ },
fetchData () {
this.loading = true
api('listFirewallRules', {
@@ -620,7 +673,7 @@ export default {
&__item {
display: flex;
flex-direction: column;
- /*flex: 1;*/
+ flex: 1;
padding-right: 20px;
margin-bottom: 20px;
diff --git a/ui/src/views/network/IngressEgressRuleConfigure.vue b/ui/src/views/network/IngressEgressRuleConfigure.vue
index adf013cb9aa..0063adf91dc 100644
--- a/ui/src/views/network/IngressEgressRuleConfigure.vue
+++ b/ui/src/views/network/IngressEgressRuleConfigure.vue
@@ -47,25 +47,56 @@
<a-select-option value="protocolnumber" :label="$t('label.protocol.number')">{{ capitalise($t('label.protocol.number')) }}</a-select-option>
</a-select>
</div>
- <div v-show="newRule.protocol === 'tcp' || newRule.protocol === 'udp'" class="form__item">
+ <div v-show="['tcp', 'udp', 'protocolnumber'].includes(newRule.protocol) && !(newRule.protocol === 'protocolnumber' && newRule.protocolnumber === 1)" class="form__item">
<div class="form__label">{{ $t('label.startport') }}</div>
<a-input v-model:value="newRule.startport"></a-input>
</div>
- <div v-show="newRule.protocol === 'tcp' || newRule.protocol === 'udp'" class="form__item">
+ <div v-show="['tcp', 'udp', 'protocolnumber'].includes(newRule.protocol) && !(newRule.protocol === 'protocolnumber' && newRule.protocolnumber === 1)" class="form__item">
<div class="form__label">{{ $t('label.endport') }}</div>
<a-input v-model:value="newRule.endport"></a-input>
</div>
<div v-show="newRule.protocol === 'protocolnumber'" class="form__item">
<div class="form__label">{{ $t('label.protocol.number') }}</div>
- <a-input v-model:value="newRule.protocolnumber"></a-input>
+ <a-select
+ v-model:value="newRule.protocolnumber"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt, optIndex) in protocolNumbers" :key="optIndex" :label="opt.name">
+ {{ opt.index + ' - ' + opt.name }}
+ </a-select-option>
+ </a-select>
</div>
- <div v-show="newRule.protocol === 'icmp'" class="form__item">
+ <div v-show="newRule.protocol === 'icmp' || (newRule.protocol === 'protocolnumber' && newRule.protocolnumber === 1)" class="form__item">
<div class="form__label">{{ $t('label.icmptype') }}</div>
- <a-input v-model:value="newRule.icmptype"></a-input>
+ <a-select
+ v-model:value="newRule.icmptype"
+ @change="val => { updateIcmpCodes(val) }"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpTypes" :key="opt.index" :label="opt.description">
+ {{ opt.index + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</div>
- <div v-show="newRule.protocol === 'icmp'" class="form__item">
+ <div v-show="newRule.protocol === 'icmp' || (newRule.protocol === 'protocolnumber' && newRule.protocolnumber === 1)" class="form__item">
<div class="form__label">{{ $t('label.icmpcode') }}</div>
- <a-input v-model:value="newRule.icmpcode"></a-input>
+ <a-select
+ v-model:value="newRule.icmpcode"
+ showSearch
+ optionFilterProp="label"
+ :filterOption="(input, option) => {
+ return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+ }" >
+ <a-select-option v-for="(opt) in icmpCodes" :key="opt.code" :label="opt.description">
+ {{ opt.code + ' - ' + opt.description }}
+ </a-select-option>
+ </a-select>
</div>
<div class="form__item" v-if="addType === 'cidr'">
<div class="form__label">{{ $t('label.cidr') }}</div>
@@ -211,6 +242,9 @@ export default {
group: null
}
},
+ protocolNumbers: [],
+ icmpTypes: [],
+ icmpCodes: [],
tagsModalVisible: false,
tags: [],
newTag: {
@@ -275,6 +309,7 @@ export default {
},
created () {
this.initForm()
+ this.fetchNetworkProtocols()
this.fetchData()
},
methods: {
@@ -286,6 +321,34 @@ export default {
value: [{ required: true, message: this.$t('message.specify.tag.value') }]
})
},
+ fetchNetworkProtocols () {
+ api('listNetworkProtocols', {
+ option: 'protocolnumber'
+ }).then(json => {
+ this.protocolNumbers = json.listnetworkprotocolsresponse?.networkprotocol || []
+ })
+ api('listNetworkProtocols', {
+ option: 'icmptype'
+ }).then(json => {
+ this.icmpTypes.push({ index: -1, description: this.$t('label.all') })
+ const results = json.listnetworkprotocolsresponse?.networkprotocol || []
+ for (const result of results) {
+ this.icmpTypes.push(result)
+ }
+ })
+ },
+ updateIcmpCodes (val) {
+ this.newRule.icmpcode = -1
+ this.icmpCodes = []
+ this.icmpCodes.push({ code: -1, description: this.$t('label.all') })
+ const icmpType = this.icmpTypes.find(icmpType => icmpType.index === val)
+ if (icmpType && icmpType.details) {
+ const icmpTypeDetails = icmpType.details
+ for (const k of Object.keys(icmpTypeDetails)) {
+ this.icmpCodes.push({ code: parseInt(k), description: icmpTypeDetails[k] })
+ }
+ }
+ },
fetchData () {
this.tabType = this.$route.query.tab === 'ingress.rule' ? 'ingress' : 'egress'
this.rules = this.tabType === 'ingress' ? this.resource.ingressrule : this.resource.egressrule
diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
index 018912a2140..2a39b12afdf 100644
--- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java
@@ -78,6 +78,7 @@ public class NetUtils {
public final static String ANY_PROTO = "any";
public final static String ICMP_PROTO = "icmp";
public static final String ICMP6_PROTO = "icmp6";
+ public final static int ICMP_PROTO_NUMBER = 1;
public final static String ALL_PROTO = "all";
public final static String HTTP_PROTO = "http";
public final static String HTTPS_PROTO = "https";
@@ -1771,4 +1772,18 @@ public class NetUtils {
}
}
+ public static void validateIcmpTypeAndCode(Integer icmpType, Integer icmpCode) {
+ if ((icmpType == null) || (icmpCode == null)) {
+ throw new CloudRuntimeException("Invalid ICMP type/code specified, icmpType = " + icmpType + ", icmpCode = " + icmpCode);
+ }
+ if (icmpType == -1 && icmpCode != -1) {
+ throw new CloudRuntimeException("Invalid icmp code");
+ }
+ if (icmpType != -1 && icmpCode == -1) {
+ throw new CloudRuntimeException("Invalid icmp code: need non-negative icmp code ");
+ }
+ if (icmpCode > 255 || icmpType > 255 || icmpCode < -1 || icmpType < -1) {
+ throw new CloudRuntimeException("Invalid icmp type/code ");
+ }
+ }
}
diff --git a/utils/src/main/java/com/cloud/utils/net/NetworkProtocols.java b/utils/src/main/java/com/cloud/utils/net/NetworkProtocols.java
new file mode 100644
index 00000000000..dbc58104f15
--- /dev/null
+++ b/utils/src/main/java/com/cloud/utils/net/NetworkProtocols.java
@@ -0,0 +1,344 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.utils.net;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Network protocols and parameters.
+ * see <a href="https://www.iana.org/protocols">Protocol Registries</a>
+ *
+ */
+public class NetworkProtocols {
+
+ public enum Option {
+ ProtocolNumber, IcmpType;
+
+ public static Option getOption(String value) {
+ return Arrays.stream(Option.values())
+ .filter(option -> option.name().equalsIgnoreCase(value))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException(String.format("Option " + value + " is not supported. Supported values are %s", Arrays.toString(Option.values()))));
+ }
+ }
+
+ // Refer to https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+ public static List<ProtocolNumber> ProtocolNumbers = new ArrayList<>();
+ static {
+ ProtocolNumbers.add(new ProtocolNumber(0, "HOPOPT", "IPv6 Hop-by-Hop Option"));
+ ProtocolNumbers.add(new ProtocolNumber(1, "ICMP", "Internet Control Message"));
+ ProtocolNumbers.add(new ProtocolNumber(2, "IGMP", "Internet Group Management"));
+ ProtocolNumbers.add(new ProtocolNumber(3, "GGP", "Gateway-to-Gateway"));
+ ProtocolNumbers.add(new ProtocolNumber(4, "IPv4", "IPv4 encapsulation"));
+ ProtocolNumbers.add(new ProtocolNumber(5, "ST", "Stream"));
+ ProtocolNumbers.add(new ProtocolNumber(6, "TCP", "Transmission Control"));
+ ProtocolNumbers.add(new ProtocolNumber(7, "CBT", "CBT"));
+ ProtocolNumbers.add(new ProtocolNumber(8, "EGP", "Exterior Gateway Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(9, "IGP", "any private interior gateway"));
+ ProtocolNumbers.add(new ProtocolNumber(10, "BBN-RCC-MON", "BBN RCC Monitoring"));
+ ProtocolNumbers.add(new ProtocolNumber(11, "NVP-II", "Network Voice Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(12, "PUP", "PUP"));
+ ProtocolNumbers.add(new ProtocolNumber(13, "ARGUS (deprecated)", "ARGUS"));
+ ProtocolNumbers.add(new ProtocolNumber(14, "EMCON", "EMCON"));
+ ProtocolNumbers.add(new ProtocolNumber(15, "XNET", "Cross Net Debugger"));
+ ProtocolNumbers.add(new ProtocolNumber(16, "CHAOS", "Chaos"));
+ ProtocolNumbers.add(new ProtocolNumber(17, "UDP", "User Datagram"));
+ ProtocolNumbers.add(new ProtocolNumber(18, "MUX", "Multiplexing"));
+ ProtocolNumbers.add(new ProtocolNumber(19, "DCN-MEAS", "DCN Measurement Subsystems"));
+ ProtocolNumbers.add(new ProtocolNumber(20, "HMP", "Host Monitoring"));
+ ProtocolNumbers.add(new ProtocolNumber(21, "PRM", "Packet Radio Measurement"));
+ ProtocolNumbers.add(new ProtocolNumber(22, "XNS-IDP", "XEROX NS IDP"));
+ ProtocolNumbers.add(new ProtocolNumber(23, "TRUNK-1", "Trunk-1"));
+ ProtocolNumbers.add(new ProtocolNumber(24, "TRUNK-2", "Trunk-2"));
+ ProtocolNumbers.add(new ProtocolNumber(25, "LEAF-1", "Leaf-1"));
+ ProtocolNumbers.add(new ProtocolNumber(26, "LEAF-2", "Leaf-2"));
+ ProtocolNumbers.add(new ProtocolNumber(27, "RDP", "Reliable Data Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(28, "IRTP", "Internet Reliable Transaction"));
+ ProtocolNumbers.add(new ProtocolNumber(29, "ISO-TP4", "ISO Transport Protocol Class 4"));
+ ProtocolNumbers.add(new ProtocolNumber(30, "NETBLT", "Bulk Data Transfer Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(31, "MFE-NSP", "MFE Network Services Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(32, "MERIT-INP", "MERIT Internodal Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(33, "DCCP", "Datagram Congestion Control Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(34, "3PC", "Third Party Connect Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(35, "IDPR", "Inter-Domain Policy Routing Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(36, "XTP", "XTP"));
+ ProtocolNumbers.add(new ProtocolNumber(37, "DDP", "Datagram Delivery Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(38, "IDPR-CMTP", "IDPR Control Message Transport Proto"));
+ ProtocolNumbers.add(new ProtocolNumber(39, "TP++", "TP++ Transport Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(40, "IL", "IL Transport Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(41, "IPv6", "IPv6 encapsulation"));
+ ProtocolNumbers.add(new ProtocolNumber(42, "SDRP", "Source Demand Routing Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(43, "IPv6-Route", "Routing Header for IPv6"));
+ ProtocolNumbers.add(new ProtocolNumber(44, "IPv6-Frag", "Fragment Header for IPv6"));
+ ProtocolNumbers.add(new ProtocolNumber(45, "IDRP", "Inter-Domain Routing Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(46, "RSVP", "Reservation Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(47, "GRE", "Generic Routing Encapsulation"));
+ ProtocolNumbers.add(new ProtocolNumber(48, "DSR", "Dynamic Source Routing Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(49, "BNA", "BNA"));
+ ProtocolNumbers.add(new ProtocolNumber(50, "ESP", "Encap Security Payload"));
+ ProtocolNumbers.add(new ProtocolNumber(51, "AH", "Authentication Header"));
+ ProtocolNumbers.add(new ProtocolNumber(52, "I-NLSP", "Integrated Net Layer Security TUBA"));
+ ProtocolNumbers.add(new ProtocolNumber(53, "SWIPE (deprecated)", "IP with Encryption"));
+ ProtocolNumbers.add(new ProtocolNumber(54, "NARP", "NBMA Address Resolution Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(55, "MOBILE", "Minimal IPv4 Encapsulation"));
+ ProtocolNumbers.add(new ProtocolNumber(56, "TLSP", "Transport Layer Security Protocol using Kryptonet key management"));
+ ProtocolNumbers.add(new ProtocolNumber(57, "SKIP", "SKIP"));
+ ProtocolNumbers.add(new ProtocolNumber(58, "IPv6-ICMP", "ICMP for IPv6"));
+ ProtocolNumbers.add(new ProtocolNumber(59, "IPv6-NoNxt", "No Next Header for IPv6"));
+ ProtocolNumbers.add(new ProtocolNumber(60, "IPv6-Opts", "Destination Options for IPv6"));
+ ProtocolNumbers.add(new ProtocolNumber(61, "Any host internal protocol", "Any host internal protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(62, "CFTP", "CFTP"));
+ ProtocolNumbers.add(new ProtocolNumber(63, "Any local network", "Any local network"));
+ ProtocolNumbers.add(new ProtocolNumber(64, "SAT-EXPAK", "SATNET and Backroom EXPAK"));
+ ProtocolNumbers.add(new ProtocolNumber(65, "KRYPTOLAN", "Kryptolan"));
+ ProtocolNumbers.add(new ProtocolNumber(66, "RVD", "MIT Remote Virtual Disk Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(67, "IPPC", "Internet Pluribus Packet Core"));
+ ProtocolNumbers.add(new ProtocolNumber(68, "Any distributed file system", "Any distributed file system"));
+ ProtocolNumbers.add(new ProtocolNumber(69, "SAT-MON", "SATNET Monitoring"));
+ ProtocolNumbers.add(new ProtocolNumber(70, "VISA", "VISA Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(71, "IPCV", "Internet Packet Core Utility"));
+ ProtocolNumbers.add(new ProtocolNumber(72, "CPNX", "Computer Protocol Network Executive"));
+ ProtocolNumbers.add(new ProtocolNumber(73, "CPHB", "Computer Protocol Heart Beat"));
+ ProtocolNumbers.add(new ProtocolNumber(74, "WSN", "Wang Span Network"));
+ ProtocolNumbers.add(new ProtocolNumber(75, "PVP", "Packet Video Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(76, "BR-SAT-MON", "Backroom SATNET Monitoring"));
+ ProtocolNumbers.add(new ProtocolNumber(77, "SUN-ND", "SUN ND PROTOCOL-Temporary"));
+ ProtocolNumbers.add(new ProtocolNumber(78, "WB-MON", "WIDEBAND Monitoring"));
+ ProtocolNumbers.add(new ProtocolNumber(79, "WB-EXPAK", "WIDEBAND EXPAK"));
+ ProtocolNumbers.add(new ProtocolNumber(80, "ISO-IP", "ISO Internet Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(81, "VMTP", "VMTP"));
+ ProtocolNumbers.add(new ProtocolNumber(82, "SECURE-VMTP", "SECURE-VMTP"));
+ ProtocolNumbers.add(new ProtocolNumber(83, "VINES", "VINES"));
+ ProtocolNumbers.add(new ProtocolNumber(84, "TTP or IPTM", "Internet Protocol Traffic Manager"));
+ ProtocolNumbers.add(new ProtocolNumber(85, "NSFNET-IGP", "NSFNET-IGP"));
+ ProtocolNumbers.add(new ProtocolNumber(86, "DGP", "Dissimilar Gateway Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(87, "TCF", "TCF"));
+ ProtocolNumbers.add(new ProtocolNumber(88, "EIGRP", "EIGRP"));
+ ProtocolNumbers.add(new ProtocolNumber(89, "OSPFIGP", "OSPFIGP"));
+ ProtocolNumbers.add(new ProtocolNumber(90, "Sprite-RPC", "Sprite RPC Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(91, "LARP", "Locus Address Resolution Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(92, "MTP", "Multicast Transport Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(93, "AX.25", "AX.25 Frames"));
+ ProtocolNumbers.add(new ProtocolNumber(94, "IPIP", "IP-within-IP Encapsulation Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(95, "MICP (deprecated)", "Mobile Internetworking Control Pro."));
+ ProtocolNumbers.add(new ProtocolNumber(96, "SCC-SP", "Semaphore Communications Sec. Pro."));
+ ProtocolNumbers.add(new ProtocolNumber(97, "ETHERIP", "Ethernet-within-IP Encapsulation"));
+ ProtocolNumbers.add(new ProtocolNumber(98, "ENCAP", "Encapsulation Header"));
+ ProtocolNumbers.add(new ProtocolNumber(99, "Any private encryption scheme", "Any private encryption scheme"));
+ ProtocolNumbers.add(new ProtocolNumber(100, "GMTP", "GMTP"));
+ ProtocolNumbers.add(new ProtocolNumber(101, "IFMP", "Ipsilon Flow Management Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(102, "PNNI", "PNNI over IP"));
+ ProtocolNumbers.add(new ProtocolNumber(103, "PIM", "Protocol Independent Multicast"));
+ ProtocolNumbers.add(new ProtocolNumber(104, "ARIS", "ARIS"));
+ ProtocolNumbers.add(new ProtocolNumber(105, "SCPS", "SCPS"));
+ ProtocolNumbers.add(new ProtocolNumber(106, "QNX", "QNX"));
+ ProtocolNumbers.add(new ProtocolNumber(107, "A/N", "Active Networks"));
+ ProtocolNumbers.add(new ProtocolNumber(108, "IPComp", "IP Payload Compression Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(109, "SNP", "Sitara Networks Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(110, "Compaq-Peer", "Compaq Peer Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(111, "IPX-in-IP", "IPX in IP"));
+ ProtocolNumbers.add(new ProtocolNumber(112, "VRRP", "Virtual Router Redundancy Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(113, "PGM", "PGM Reliable Transport Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(114, "Any 0-hop protocol", "Any 0-hop protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(115, "L2TP", "Layer Two Tunneling Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(116, "DDX", "D-II Data Exchange (DDX)"));
+ ProtocolNumbers.add(new ProtocolNumber(117, "IATP", "Interactive Agent Transfer Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(118, "STP", "Schedule Transfer Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(119, "SRP", "SpectraLink Radio Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(120, "UTI", "UTI"));
+ ProtocolNumbers.add(new ProtocolNumber(121, "SMP", "Simple Message Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(122, "SM (deprecated)", "Simple Multicast Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(123, "PTP", "Performance Transparency Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(124, "ISIS over IPv4", ""));
+ ProtocolNumbers.add(new ProtocolNumber(125, "FIRE", ""));
+ ProtocolNumbers.add(new ProtocolNumber(126, "CRTP", "Combat Radio Transport Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(127, "CRUDP", "Combat Radio User Datagram"));
+ ProtocolNumbers.add(new ProtocolNumber(128, "SSCOPMCE", ""));
+ ProtocolNumbers.add(new ProtocolNumber(129, "IPLT", ""));
+ ProtocolNumbers.add(new ProtocolNumber(130, "SPS", "Secure Packet Shield"));
+ ProtocolNumbers.add(new ProtocolNumber(131, "PIPE", "Private IP Encapsulation within IP"));
+ ProtocolNumbers.add(new ProtocolNumber(132, "SCTP", "Stream Control Transmission Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(133, "FC", "Fibre Channel"));
+ ProtocolNumbers.add(new ProtocolNumber(134, "RSVP-E2E-IGNORE", ""));
+ ProtocolNumbers.add(new ProtocolNumber(135, "Mobility Header", ""));
+ ProtocolNumbers.add(new ProtocolNumber(136, "UDPLite", ""));
+ ProtocolNumbers.add(new ProtocolNumber(137, "MPLS-in-IP", ""));
+ ProtocolNumbers.add(new ProtocolNumber(138, "manet", "MANET Protocols"));
+ ProtocolNumbers.add(new ProtocolNumber(139, "HIP", "Host Identity Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(140, "Shim6", "Shim6 Protocol"));
+ ProtocolNumbers.add(new ProtocolNumber(141, "WESP", "Wrapped Encapsulating Security Payload"));
+ ProtocolNumbers.add(new ProtocolNumber(142, "ROHC", "Robust Header Compression"));
+ ProtocolNumbers.add(new ProtocolNumber(143, "Ethernet", "Ethernet"));
+ ProtocolNumbers.add(new ProtocolNumber(144, "AGGFRAG", "AGGFRAG encapsulation payload for ESP"));
+ ProtocolNumbers.add(new ProtocolNumber(145, "NSH", "Network Service Header"));
+ }
+ /**
+ * Different types of ICMP.
+ */
+ public static class ProtocolNumber {
+
+ private final Integer number;
+
+ private final String keyword;
+
+ private final String protocol;
+
+ public ProtocolNumber(Integer number, String keyword, String protocol) {
+ this.number = number;
+ this.keyword = keyword;
+ this.protocol = protocol;
+ }
+
+ public Integer getNumber() {
+ return number;
+ }
+
+ public String getKeyword() {
+ return keyword;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+ }
+
+ // Refer to https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml
+ public static List<IcmpType> IcmpTypes = new ArrayList<>();
+ static {
+ IcmpTypes.add(new IcmpType(0, "Echo Reply"));
+ IcmpTypes.add(new IcmpType(3, "Destination Unreachable"));
+ IcmpTypes.add(new IcmpType(5, "Redirect"));
+ IcmpTypes.add(new IcmpType(8, "Echo"));
+ IcmpTypes.add(new IcmpType(9, "Router Advertisement"));
+ IcmpTypes.add(new IcmpType(10, "Router Solicitation"));
+ IcmpTypes.add(new IcmpType(11, "Time Exceeded"));
+ IcmpTypes.add(new IcmpType(12, "Parameter Problem"));
+ IcmpTypes.add(new IcmpType(13, "Timestamp"));
+ IcmpTypes.add(new IcmpType(14, "Timestamp Reply"));
+ IcmpTypes.add(new IcmpType(40, "Photuris"));
+ IcmpTypes.add(new IcmpType(42, "Extended Echo Request"));
+ IcmpTypes.add(new IcmpType(43, "Extended Echo Reply"));
+ }
+
+ /**
+ * Different types of ICMP.
+ */
+ public static class IcmpType {
+
+ private final Integer type;
+
+ private final String description;
+
+ private final List<IcmpCode> icmpCodes = new ArrayList<>();
+
+ public IcmpType(Integer type, String description) {
+ this.type = type;
+ this.description = description;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public List<IcmpCode> getIcmpCodes() {
+ return icmpCodes;
+ }
+
+ public void addIcmpCodes(IcmpCode code) {
+ this.icmpCodes.add(code);
+ }
+ }
+
+ static void addIcmpCode(IcmpCode code) {
+ IcmpType type = IcmpTypes.stream().filter(icmpType -> icmpType.getType().equals(code.getType())).findFirst().get();
+ type.addIcmpCodes(code);
+ }
+
+ static {
+ addIcmpCode(new IcmpCode(0, 0, "Echo reply"));
+ addIcmpCode(new IcmpCode(3, 0, "Net unreachable"));
+ addIcmpCode(new IcmpCode(3, 1, "Host unreachable"));
+ addIcmpCode(new IcmpCode(3, 2, "Protocol unreachable"));
+ addIcmpCode(new IcmpCode(3, 3, "Port unreachable"));
+ addIcmpCode(new IcmpCode(3, 4, "Fragmentation needed and DF set"));
+ addIcmpCode(new IcmpCode(3, 5, "Source route failed"));
+ addIcmpCode(new IcmpCode(3, 6, "Destination network unknown"));
+ addIcmpCode(new IcmpCode(3, 7, "Destination host unknown"));
+ addIcmpCode(new IcmpCode(3, 9, "Network administratively prohibited"));
+ addIcmpCode(new IcmpCode(3, 10, "Host administratively prohibited"));
+ addIcmpCode(new IcmpCode(3, 11, "Network unreachable for ToS"));
+ addIcmpCode(new IcmpCode(3, 12, "Host unreachable for ToS"));
+ addIcmpCode(new IcmpCode(3, 13, "Communication administratively prohibited"));
+ addIcmpCode(new IcmpCode(3, 14, "Host Precedence Violation"));
+ addIcmpCode(new IcmpCode(3, 15, "Precedence cutoff in effect"));
+ addIcmpCode(new IcmpCode(5, 0, "Redirect Datagram for the Network"));
+ addIcmpCode(new IcmpCode(5, 1, "Redirect Datagram for the Host"));
+ addIcmpCode(new IcmpCode(5, 2, "Redirect Datagram for the ToS & network"));
+ addIcmpCode(new IcmpCode(5, 3, "Redirect Datagram for the ToS & host"));
+ addIcmpCode(new IcmpCode(8, 0, "Echo request"));
+ addIcmpCode(new IcmpCode(9, 0, "Router advertisement"));
+ addIcmpCode(new IcmpCode(9, 16, "Does not route common traffic"));
+ addIcmpCode(new IcmpCode(10, 0, "Router solicitation"));
+ addIcmpCode(new IcmpCode(11, 0, "TTL expired in transit"));
+ addIcmpCode(new IcmpCode(11, 1, "Fragment reassembly time exceeded"));
+ addIcmpCode(new IcmpCode(12, 0, "Parameter problem: Pointer indicates the error"));
+ addIcmpCode(new IcmpCode(12, 1, "Parameter problem: Missing a required option"));
+ addIcmpCode(new IcmpCode(12, 2, "Parameter problem: Bad length"));
+ addIcmpCode(new IcmpCode(13, 0, "Timestamp"));
+ addIcmpCode(new IcmpCode(14, 0, "Timestamp reply"));
+ addIcmpCode(new IcmpCode(40, 0, "Photuris: Security failures"));
+ addIcmpCode(new IcmpCode(40, 1, "Photuris: Authentication failed"));
+ addIcmpCode(new IcmpCode(40, 2, "Photuris: Decompression failed"));
+ addIcmpCode(new IcmpCode(40, 3, "Photuris: Decryption failed"));
+ addIcmpCode(new IcmpCode(40, 4, "Photuris: Need authentication"));
+ addIcmpCode(new IcmpCode(40, 5, "Photuris: Need authorization"));
+ }
+
+ /**
+ * Different codes of ICMP.
+ */
+ public static class IcmpCode {
+
+ private final Integer type;
+ private final Integer code;
+ private final String description;
+
+ public IcmpCode(Integer type, Integer code, String description) {
+ this.type = type;
+ this.code = code;
+ this.description = description;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+ }
+}