ICMPv6: Add Extended Echo (Probe) RFC8335

Implementing ICMP extended echo (RFC8335) for IPv6.
To dissect ICMP Extension objects we use the IPv4
implementation.

Bug: 14457
Change-Id: I5be59ccf9058466369c072cfed3ad1cd17bf243b
Reviewed-on: https://code.wireshark.org/review/30563
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Uli Heilmeier 2018-11-09 08:18:18 +01:00 committed by Anders Broman
parent 811d5f7fac
commit 57c3ebb396
3 changed files with 136 additions and 6 deletions

View File

@ -0,0 +1,16 @@
/* packet-icmp-int.h
* Functions which are shared between ICMPv4 and ICMPv6
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef __PACKET_ICMP_INT_H__
#define __PACKET_ICMP_INT_H__
gint dissect_icmp_extension_structure(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree * tree);
#endif

View File

@ -39,6 +39,7 @@
#include "packet-ip.h"
#include "packet-icmp.h"
#include "packet-icmp-int.h"
void proto_register_icmp(void);
void proto_reg_handoff_icmp(void);
@ -941,8 +942,7 @@ dissect_interface_identification_object(tvbuff_t * tvb, gint offset,
} /*end dissect_interface_identification_object */
static void
dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree * tree)
gint dissect_icmp_extension_structure(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree * tree)
{
guint8 version;
guint8 class_num;
@ -965,7 +965,7 @@ dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree *
"ICMP Multi-Part Extensions");
if (reported_length < 4 /* Common header */ ) {
return;
return offset;
}
ext_tree = proto_item_add_subtree(ti, ett_icmp_ext);
@ -993,7 +993,7 @@ dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree *
if (version != 1 && version != 2) {
/* Unsupported version */
proto_item_append_text(ti, " (unsupported version)");
return;
return offset;
}
/* Skip the common header */
@ -1100,6 +1100,7 @@ dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree *
offset = obj_end_offset;
}
return offset;
}
/* ======================================================================= */
@ -1690,7 +1691,7 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
if ((tvb_reported_length(tvb) > 8 + 128)
&& (tvb_get_ntohs(tvb, 8 + 2) <= 128
|| favor_icmp_mpls_ext)) {
dissect_extensions(tvb, pinfo, 8 + 128, icmp_tree);
dissect_icmp_extension_structure(tvb, pinfo, 8 + 128, icmp_tree);
}
break;
case ICMP_ECHOREPLY:
@ -1826,7 +1827,7 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data)
case ICMP_EXTECHO:
if (tvb_reported_length(tvb) > 8) {
dissect_extensions(tvb, pinfo, 8, icmp_tree);
dissect_icmp_extension_structure(tvb, pinfo, 8, icmp_tree);
}
break;
}

View File

@ -41,6 +41,7 @@
#include "packet-x509af.h"
#include "packet-x509if.h"
#include "packet-icmp.h" /* same transaction_t used both both v4 and v6 */
#include "packet-icmp-int.h"
#include "packet-ieee802154.h"
#include "packet-6lowpan.h"
#include "packet-ip.h"
@ -80,6 +81,7 @@ void proto_reg_handoff_icmpv6(void);
* RFC 7112: Implications of Oversized IPv6 Header Chains
* RFC 7400: 6LoWPAN-GHC: Generic Header Compression for IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs)
* RFC 7731: MPL Control Message
* RFC 8335: PROBE: A Utility for Probing Interfaces
* http://www.iana.org/assignments/icmpv6-parameters (last updated 2016-02-24)
*/
@ -531,6 +533,16 @@ static int hf_icmpv6_mpl_seed_info_s = -1;
static int hf_icmpv6_mpl_seed_info_seed_id = -1;
static int hf_icmpv6_mpl_seed_info_sequence = -1;
/* Extended Echo - Probe (RFC8335)*/
static int hf_icmpv6_ext_echo_seq_num = -1;
static int hf_icmpv6_ext_echo_req_reserved = -1;
static int hf_icmpv6_ext_echo_req_local = -1;
static int hf_icmpv6_ext_echo_rsp_state = -1;
static int hf_icmpv6_ext_echo_rsp_reserved = -1;
static int hf_icmpv6_ext_echo_rsp_active = -1;
static int hf_icmpv6_ext_echo_rsp_ipv4 = -1;
static int hf_icmpv6_ext_echo_rsp_ipv6 = -1;
/* Conversation related data */
static int hf_icmpv6_resp_in = -1;
static int hf_icmpv6_resp_to = -1;
@ -650,6 +662,8 @@ static dissector_handle_t ipv6_handle;
#define ICMP6_6LOWPANND_DAR 157
#define ICMP6_6LOWPANND_DAC 158
#define ICMP6_MPL_CONTROL 159
#define ICMP6_EXTECHO 160
#define ICMP6_EXTECHOREPLY 161
static const value_string icmpv6_type_val[] = {
@ -692,6 +706,8 @@ static const value_string icmpv6_type_val[] = {
{ ICMP6_6LOWPANND_DAR, "Duplicate Address Request"}, /* [RFC6775] */
{ ICMP6_6LOWPANND_DAC, "Duplicate Address Confirmation"}, /* [RFC6775] */
{ ICMP6_MPL_CONTROL, "MPL Control Message"}, /* [RFC7731] */
{ ICMP6_EXTECHO, "Extended Echo request"}, /* [RFC8335] */
{ ICMP6_EXTECHOREPLY, "Extended Echo reply"}, /* [RFC8335] */
{ 200, "Private experimentation" }, /* [RFC4443] */
{ 201, "Private experimentation" }, /* [RFC4443] */
{ 255, "Reserved for expansion of ICMPv6 informational messages" }, /* [RFC4443] */
@ -1296,6 +1312,31 @@ static const value_string rdnss_infinity[] = {
{ 0, NULL}
};
static const value_string ext_echo_req_code_str[] = {
{ 0, "No error"},
{ 0, NULL}
};
static const value_string ext_echo_reply_code_str[] = {
{ 0, "No error"},
{ 1, "Malformed Query"},
{ 2, "No Such Interface"},
{ 3, "No Such Table Entry"},
{ 4, "Multiple Interfaces Satisfy Query"},
{ 0, NULL}
};
static const value_string ext_echo_reply_state_str[] = {
{ 0, "Reserved"},
{ 1, "Incomplete"},
{ 2, "Reachable"},
{ 3, "Stale"},
{ 4, "Delay"},
{ 5, "Probe"},
{ 6, "Failed"},
{ 0, NULL}
};
/* whenever a ICMPv6 packet is seen by the tap listener */
/* Add a new frame into the graph */
static gboolean
@ -3961,6 +4002,12 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
case ICMP6_RPL_CONTROL:
code_name = val_to_str(icmp6_code, rpl_code_val, "Unknown (%d)");
break;
case ICMP6_EXTECHO:
code_name = val_to_str(icmp6_code, ext_echo_req_code_str, "Unknown (%d)");
break;
case ICMP6_EXTECHOREPLY:
code_name = val_to_str(icmp6_code, ext_echo_reply_code_str, "Unknown (%d)");
break;
}
if (code_name)
@ -4561,6 +4608,46 @@ dissect_icmpv6(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
offset = dissect_mpl_control(tvb, offset, pinfo, icmp6_tree, icmp6_type, icmp6_code);
break;
}
case ICMP6_EXTECHO: /* Extended Echo - Probe - (RFC8335) */
{
proto_tree_add_item(icmp6_tree, hf_icmpv6_echo_identifier, tvb, offset, 2,
ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_seq_num, tvb, offset, 1,
ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_req_reserved, tvb, offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_req_local, tvb, offset, 1,
ENC_BIG_ENDIAN);
offset += 1;
offset = dissect_icmp_extension_structure(tvb, pinfo, offset, icmp6_tree);
break;
}
case ICMP6_EXTECHOREPLY:
{
proto_tree_add_item(icmp6_tree, hf_icmpv6_echo_identifier, tvb, offset, 2,
ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_seq_num, tvb, offset, 1,
ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_rsp_state, tvb, offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_rsp_reserved, tvb, offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_rsp_active, tvb, offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_rsp_ipv4, tvb, offset, 1,
ENC_BIG_ENDIAN);
proto_tree_add_item(icmp6_tree, hf_icmpv6_ext_echo_rsp_ipv6, tvb, offset, 1,
ENC_BIG_ENDIAN);
offset += 1;
break;
}
default:
expert_add_info_format(pinfo, ti, &ei_icmpv6_undecoded_type,
"Dissector for ICMPv6 Type (%d)"
@ -5846,6 +5933,32 @@ proto_register_icmpv6(void)
{ "Registered Address", "icmpv6.6lowpannd.da.reg_addr", FT_IPv6, BASE_NONE, NULL, 0x0,
"Carries the host address, which was contained in the IPv6 Source field in the NS that contained the ARO option sent by the host", HFILL }},
/* Extended Echo - Probe - RFC8335 */
{ &hf_icmpv6_ext_echo_seq_num,
{ "Sequence number", "icmpv6.ext.echo.seq", FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_req_reserved,
{ "Reserved", "icmpv6.ext.echo.req.res", FT_UINT8, BASE_HEX, NULL, 0xFE,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_req_local,
{ "Local bit", "icmpv6.ext.echo.req.local", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x01,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_rsp_state,
{ "State", "icmpv6.ext.echo.rsp.state", FT_UINT8, BASE_DEC, VALS(ext_echo_reply_state_str), 0xE0,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_rsp_reserved,
{ "Reserved", "icmpv6.ext.echo.rsp.res", FT_UINT8, BASE_HEX, NULL, 0x18,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_rsp_active,
{ "Active bit", "icmpv6.ext.echo.rsp.active", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x04,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_rsp_ipv4,
{ "IPv4 bit", "icmpv6.ext.echo.rsp.ipv4", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x02,
NULL, HFILL}},
{ &hf_icmpv6_ext_echo_rsp_ipv6,
{ "IPv6 bit", "icmpv6.ext.echo.rsp.ipv6", FT_BOOLEAN, 8, TFS(&tfs_set_notset), 0x01,
NULL, HFILL}},
/* Conversation-related [generated] header fields */
{ &hf_icmpv6_resp_in,
{ "Response In", "icmpv6.resp_in", FT_FRAMENUM, BASE_NONE, NULL, 0x0,