diff --git a/builtin/providers/aws/network_acl_entry.go b/builtin/providers/aws/network_acl_entry.go index a8450ef520ab..c57f82222c5e 100644 --- a/builtin/providers/aws/network_acl_entry.go +++ b/builtin/providers/aws/network_acl_entry.go @@ -32,7 +32,14 @@ func expandNetworkAclEntries(configured []interface{}, entryType string) ([]*ec2 Egress: aws.Bool(entryType == "egress"), RuleAction: aws.String(data["action"].(string)), RuleNumber: aws.Int64(int64(data["rule_no"].(int))), - CidrBlock: aws.String(data["cidr_block"].(string)), + } + + if v, ok := data["ipv6_cidr_block"]; ok { + e.Ipv6CidrBlock = aws.String(v.(string)) + } + + if v, ok := data["cidr_block"]; ok { + e.CidrBlock = aws.String(v.(string)) } // Specify additional required fields for ICMP @@ -55,14 +62,24 @@ func flattenNetworkAclEntries(list []*ec2.NetworkAclEntry) []map[string]interfac entries := make([]map[string]interface{}, 0, len(list)) for _, entry := range list { - entries = append(entries, map[string]interface{}{ - "from_port": *entry.PortRange.From, - "to_port": *entry.PortRange.To, - "action": *entry.RuleAction, - "rule_no": *entry.RuleNumber, - "protocol": *entry.Protocol, - "cidr_block": *entry.CidrBlock, - }) + + newEntry := map[string]interface{}{ + "from_port": *entry.PortRange.From, + "to_port": *entry.PortRange.To, + "action": *entry.RuleAction, + "rule_no": *entry.RuleNumber, + "protocol": *entry.Protocol, + } + + if entry.CidrBlock != nil { + newEntry["cidr_block"] = *entry.CidrBlock + } + + if entry.Ipv6CidrBlock != nil { + newEntry["ipv6_cidr_block"] = *entry.Ipv6CidrBlock + } + + entries = append(entries, newEntry) } return entries diff --git a/builtin/providers/aws/resource_aws_network_acl.go b/builtin/providers/aws/resource_aws_network_acl.go index b0a3340fc3ac..cd3c6d049922 100644 --- a/builtin/providers/aws/resource_aws_network_acl.go +++ b/builtin/providers/aws/resource_aws_network_acl.go @@ -28,20 +28,20 @@ func resourceAwsNetworkAcl() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "vpc_id": &schema.Schema{ + "vpc_id": { Type: schema.TypeString, Required: true, ForceNew: true, Computed: false, }, - "subnet_id": &schema.Schema{ + "subnet_id": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: false, Deprecated: "Attribute subnet_id is deprecated on network_acl resources. Use subnet_ids instead", }, - "subnet_ids": &schema.Schema{ + "subnet_ids": { Type: schema.TypeSet, Optional: true, Computed: true, @@ -49,42 +49,46 @@ func resourceAwsNetworkAcl() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, - "ingress": &schema.Schema{ + "ingress": { Type: schema.TypeSet, Required: false, Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "from_port": &schema.Schema{ + "from_port": { Type: schema.TypeInt, Required: true, }, - "to_port": &schema.Schema{ + "to_port": { Type: schema.TypeInt, Required: true, }, - "rule_no": &schema.Schema{ + "rule_no": { Type: schema.TypeInt, Required: true, }, - "action": &schema.Schema{ + "action": { Type: schema.TypeString, Required: true, }, - "protocol": &schema.Schema{ + "protocol": { Type: schema.TypeString, Required: true, }, - "cidr_block": &schema.Schema{ + "cidr_block": { Type: schema.TypeString, Optional: true, }, - "icmp_type": &schema.Schema{ + "ipv6_cidr_block": { + Type: schema.TypeString, + Optional: true, + }, + "icmp_type": { Type: schema.TypeInt, Optional: true, }, - "icmp_code": &schema.Schema{ + "icmp_code": { Type: schema.TypeInt, Optional: true, }, @@ -92,42 +96,46 @@ func resourceAwsNetworkAcl() *schema.Resource { }, Set: resourceAwsNetworkAclEntryHash, }, - "egress": &schema.Schema{ + "egress": { Type: schema.TypeSet, Required: false, Optional: true, Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "from_port": &schema.Schema{ + "from_port": { Type: schema.TypeInt, Required: true, }, - "to_port": &schema.Schema{ + "to_port": { Type: schema.TypeInt, Required: true, }, - "rule_no": &schema.Schema{ + "rule_no": { Type: schema.TypeInt, Required: true, }, - "action": &schema.Schema{ + "action": { Type: schema.TypeString, Required: true, }, - "protocol": &schema.Schema{ + "protocol": { Type: schema.TypeString, Required: true, }, - "cidr_block": &schema.Schema{ + "cidr_block": { Type: schema.TypeString, Optional: true, }, - "icmp_type": &schema.Schema{ + "ipv6_cidr_block": { + Type: schema.TypeString, + Optional: true, + }, + "icmp_type": { Type: schema.TypeInt, Optional: true, }, - "icmp_code": &schema.Schema{ + "icmp_code": { Type: schema.TypeInt, Optional: true, }, @@ -389,25 +397,36 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2 } } - // AWS mutates the CIDR block into a network implied by the IP and - // mask provided. This results in hashing inconsistencies between - // the local config file and the state returned by the API. Error - // if the user provides a CIDR block with an inappropriate mask - if err := validateCIDRBlock(*add.CidrBlock); err != nil { - return err + if add.CidrBlock != nil { + // AWS mutates the CIDR block into a network implied by the IP and + // mask provided. This results in hashing inconsistencies between + // the local config file and the state returned by the API. Error + // if the user provides a CIDR block with an inappropriate mask + if err := validateCIDRBlock(*add.CidrBlock); err != nil { + return err + } } - // Add new Acl entry - _, connErr := conn.CreateNetworkAclEntry(&ec2.CreateNetworkAclEntryInput{ + createOpts := &ec2.CreateNetworkAclEntryInput{ NetworkAclId: aws.String(d.Id()), - CidrBlock: add.CidrBlock, Egress: add.Egress, PortRange: add.PortRange, Protocol: add.Protocol, RuleAction: add.RuleAction, RuleNumber: add.RuleNumber, IcmpTypeCode: add.IcmpTypeCode, - }) + } + + if add.CidrBlock != nil { + createOpts.CidrBlock = add.CidrBlock + } + + if add.Ipv6CidrBlock != nil { + createOpts.Ipv6CidrBlock = add.Ipv6CidrBlock + } + + // Add new Acl entry + _, connErr := conn.CreateNetworkAclEntry(createOpts) if connErr != nil { return fmt.Errorf("Error creating %s entry: %s", entryType, connErr) } @@ -520,7 +539,13 @@ func resourceAwsNetworkAclEntryHash(v interface{}) int { buf.WriteString(fmt.Sprintf("%s-", protocol)) } - buf.WriteString(fmt.Sprintf("%s-", m["cidr_block"].(string))) + if v, ok := m["cidr_block"]; ok { + buf.WriteString(fmt.Sprintf("%s-", v.(string))) + } + + if v, ok := m["ipv6_cidr_block"]; ok { + buf.WriteString(fmt.Sprintf("%s-", v.(string))) + } if v, ok := m["ssl_certificate_id"]; ok { buf.WriteString(fmt.Sprintf("%s-", v.(string))) @@ -539,11 +564,11 @@ func resourceAwsNetworkAclEntryHash(v interface{}) int { func getDefaultNetworkAcl(vpc_id string, conn *ec2.EC2) (defaultAcl *ec2.NetworkAcl, err error) { resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ Filters: []*ec2.Filter{ - &ec2.Filter{ + { Name: aws.String("default"), Values: []*string{aws.String("true")}, }, - &ec2.Filter{ + { Name: aws.String("vpc-id"), Values: []*string{aws.String(vpc_id)}, }, @@ -559,7 +584,7 @@ func getDefaultNetworkAcl(vpc_id string, conn *ec2.EC2) (defaultAcl *ec2.Network func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssociation *ec2.NetworkAclAssociation, err error) { resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ Filters: []*ec2.Filter{ - &ec2.Filter{ + { Name: aws.String("association.subnet-id"), Values: []*string{aws.String(subnetId)}, }, @@ -587,8 +612,12 @@ func networkAclEntriesToMapList(networkAcls []*ec2.NetworkAclEntry) []map[string acl := make(map[string]interface{}) acl["rule_no"] = *entry.RuleNumber acl["action"] = *entry.RuleAction - acl["cidr_block"] = *entry.CidrBlock - + if entry.CidrBlock != nil { + acl["cidr_block"] = *entry.CidrBlock + } + if entry.Ipv6CidrBlock != nil { + acl["ipv6_cidr_block"] = *entry.Ipv6CidrBlock + } // The AWS network ACL API only speaks protocol numbers, and // that's all we record. if _, err := strconv.Atoi(*entry.Protocol); err != nil { diff --git a/builtin/providers/aws/resource_aws_network_acl_test.go b/builtin/providers/aws/resource_aws_network_acl_test.go index c63f5c0087d4..bc589267f2da 100644 --- a/builtin/providers/aws/resource_aws_network_acl_test.go +++ b/builtin/providers/aws/resource_aws_network_acl_test.go @@ -20,34 +20,34 @@ func TestAccAWSNetworkAcl_EgressAndIngressRules(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclEgressNIngressConfig, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bar", &networkAcl), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.109047673.protocol", "6"), + "aws_network_acl.bar", "ingress.1871939009.protocol", "6"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.109047673.rule_no", "1"), + "aws_network_acl.bar", "ingress.1871939009.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.109047673.from_port", "80"), + "aws_network_acl.bar", "ingress.1871939009.from_port", "80"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.109047673.to_port", "80"), + "aws_network_acl.bar", "ingress.1871939009.to_port", "80"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.109047673.action", "allow"), + "aws_network_acl.bar", "ingress.1871939009.action", "allow"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "ingress.109047673.cidr_block", "10.3.0.0/18"), + "aws_network_acl.bar", "ingress.1871939009.cidr_block", "10.3.0.0/18"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.868403673.protocol", "6"), + "aws_network_acl.bar", "egress.3111164687.protocol", "6"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.868403673.rule_no", "2"), + "aws_network_acl.bar", "egress.3111164687.rule_no", "2"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.868403673.from_port", "443"), + "aws_network_acl.bar", "egress.3111164687.from_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.868403673.to_port", "443"), + "aws_network_acl.bar", "egress.3111164687.to_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.868403673.cidr_block", "10.3.0.0/18"), + "aws_network_acl.bar", "egress.3111164687.cidr_block", "10.3.0.0/18"), resource.TestCheckResourceAttr( - "aws_network_acl.bar", "egress.868403673.action", "allow"), + "aws_network_acl.bar", "egress.3111164687.action", "allow"), ), }, }, @@ -63,23 +63,22 @@ func TestAccAWSNetworkAcl_OnlyIngressRules_basic(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclIngressConfig, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), - // testAccCheckSubnetAssociation("aws_network_acl.foos", "aws_subnet.blob"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.protocol", "6"), + "aws_network_acl.foos", "ingress.4245812720.protocol", "6"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.rule_no", "2"), + "aws_network_acl.foos", "ingress.4245812720.rule_no", "2"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.from_port", "443"), + "aws_network_acl.foos", "ingress.4245812720.from_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.to_port", "443"), + "aws_network_acl.foos", "ingress.4245812720.to_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.action", "deny"), + "aws_network_acl.foos", "ingress.4245812720.action", "deny"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.cidr_block", "10.2.0.0/18"), + "aws_network_acl.foos", "ingress.4245812720.cidr_block", "10.2.0.0/18"), ), }, }, @@ -95,46 +94,46 @@ func TestAccAWSNetworkAcl_OnlyIngressRules_update(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclIngressConfig, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), testIngressRuleLength(&networkAcl, 2), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.protocol", "6"), + "aws_network_acl.foos", "ingress.401088754.protocol", "6"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.rule_no", "1"), + "aws_network_acl.foos", "ingress.401088754.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.from_port", "0"), + "aws_network_acl.foos", "ingress.401088754.from_port", "0"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.to_port", "22"), + "aws_network_acl.foos", "ingress.401088754.to_port", "22"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.action", "deny"), + "aws_network_acl.foos", "ingress.401088754.action", "deny"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.cidr_block", "10.2.0.0/18"), + "aws_network_acl.foos", "ingress.4245812720.cidr_block", "10.2.0.0/18"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.from_port", "443"), + "aws_network_acl.foos", "ingress.4245812720.from_port", "443"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.1451312565.rule_no", "2"), + "aws_network_acl.foos", "ingress.4245812720.rule_no", "2"), ), }, - resource.TestStep{ + { Config: testAccAWSNetworkAclIngressConfigChange, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), testIngressRuleLength(&networkAcl, 1), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.protocol", "6"), + "aws_network_acl.foos", "ingress.401088754.protocol", "6"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.rule_no", "1"), + "aws_network_acl.foos", "ingress.401088754.rule_no", "1"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.from_port", "0"), + "aws_network_acl.foos", "ingress.401088754.from_port", "0"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.to_port", "22"), + "aws_network_acl.foos", "ingress.401088754.to_port", "22"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.action", "deny"), + "aws_network_acl.foos", "ingress.401088754.action", "deny"), resource.TestCheckResourceAttr( - "aws_network_acl.foos", "ingress.2048097841.cidr_block", "10.2.0.0/18"), + "aws_network_acl.foos", "ingress.401088754.cidr_block", "10.2.0.0/18"), ), }, }, @@ -150,7 +149,7 @@ func TestAccAWSNetworkAcl_OnlyEgressRules(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclEgressConfig, Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bond", &networkAcl), @@ -169,13 +168,13 @@ func TestAccAWSNetworkAcl_SubnetChange(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclSubnetConfig, Check: resource.ComposeTestCheckFunc( testAccCheckSubnetIsAssociatedWithAcl("aws_network_acl.bar", "aws_subnet.old"), ), }, - resource.TestStep{ + { Config: testAccAWSNetworkAclSubnetConfigChange, Check: resource.ComposeTestCheckFunc( testAccCheckSubnetIsNotAssociatedWithAcl("aws_network_acl.bar", "aws_subnet.old"), @@ -206,7 +205,7 @@ func TestAccAWSNetworkAcl_Subnets(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclSubnet_SubnetIds, Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bar", &networkAcl), @@ -216,7 +215,7 @@ func TestAccAWSNetworkAcl_Subnets(t *testing.T) { ), }, - resource.TestStep{ + { Config: testAccAWSNetworkAclSubnet_SubnetIdsUpdate, Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.bar", &networkAcl), @@ -230,6 +229,37 @@ func TestAccAWSNetworkAcl_Subnets(t *testing.T) { }) } +func TestAccAWSNetworkAcl_ipv6Rules(t *testing.T) { + var networkAcl ec2.NetworkAcl + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + IDRefreshName: "aws_network_acl.foos", + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSNetworkAclDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSNetworkAclIpv6Config, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSNetworkAclExists("aws_network_acl.foos", &networkAcl), + resource.TestCheckResourceAttr( + "aws_network_acl.foos", "ingress.1976110835.protocol", "6"), + resource.TestCheckResourceAttr( + "aws_network_acl.foos", "ingress.1976110835.rule_no", "1"), + resource.TestCheckResourceAttr( + "aws_network_acl.foos", "ingress.1976110835.from_port", "0"), + resource.TestCheckResourceAttr( + "aws_network_acl.foos", "ingress.1976110835.to_port", "22"), + resource.TestCheckResourceAttr( + "aws_network_acl.foos", "ingress.1976110835.action", "allow"), + resource.TestCheckResourceAttr( + "aws_network_acl.foos", "ingress.1976110835.ipv6_cidr_block", "::/0"), + ), + }, + }, + }) +} + func TestAccAWSNetworkAcl_espProtocol(t *testing.T) { var networkAcl ec2.NetworkAcl @@ -239,7 +269,7 @@ func TestAccAWSNetworkAcl_espProtocol(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckAWSNetworkAclDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccAWSNetworkAclEsp, Check: resource.ComposeTestCheckFunc( testAccCheckAWSNetworkAclExists("aws_network_acl.testesp", &networkAcl), @@ -336,7 +366,7 @@ func testAccCheckSubnetIsAssociatedWithAcl(acl string, sub string) resource.Test resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ NetworkAclIds: []*string{aws.String(networkAcl.Primary.ID)}, Filters: []*ec2.Filter{ - &ec2.Filter{ + { Name: aws.String("association.subnet-id"), Values: []*string{aws.String(subnet.Primary.ID)}, }, @@ -362,7 +392,7 @@ func testAccCheckSubnetIsNotAssociatedWithAcl(acl string, subnet string) resourc resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{ NetworkAclIds: []*string{aws.String(networkAcl.Primary.ID)}, Filters: []*ec2.Filter{ - &ec2.Filter{ + { Name: aws.String("association.subnet-id"), Values: []*string{aws.String(subnet.Primary.ID)}, }, @@ -379,6 +409,33 @@ func testAccCheckSubnetIsNotAssociatedWithAcl(acl string, subnet string) resourc } } +const testAccAWSNetworkAclIpv6Config = ` +resource "aws_vpc" "foo" { + cidr_block = "10.1.0.0/16" + tags { + Name = "TestAccAWSNetworkAcl_ipv6Rules" + } +} +resource "aws_subnet" "blob" { + cidr_block = "10.1.1.0/24" + vpc_id = "${aws_vpc.foo.id}" + map_public_ip_on_launch = true +} +resource "aws_network_acl" "foos" { + vpc_id = "${aws_vpc.foo.id}" + ingress = { + protocol = "tcp" + rule_no = 1 + action = "allow" + ipv6_cidr_block = "::/0" + from_port = 0 + to_port = 22 + } + + subnet_ids = ["${aws_subnet.blob.id}"] +} +` + const testAccAWSNetworkAclIngressConfig = ` resource "aws_vpc" "foo" { cidr_block = "10.1.0.0/16" diff --git a/website/source/docs/providers/aws/r/network_acl.html.markdown b/website/source/docs/providers/aws/r/network_acl.html.markdown index b9505c5dcceb..28143f0ccf49 100644 --- a/website/source/docs/providers/aws/r/network_acl.html.markdown +++ b/website/source/docs/providers/aws/r/network_acl.html.markdown @@ -63,6 +63,7 @@ Both `egress` and `ingress` support the following keys: protocol, you must specify a from and to port of 0. * `cidr_block` - (Optional) The CIDR block to match. This must be a valid network mask. +* `ipv6_cidr_block` - (Optional) The IPv6 CIDR block. * `icmp_type` - (Optional) The ICMP type to be used. Default 0. * `icmp_code` - (Optional) The ICMP type code to be used. Default 0.