diff options
author | Uli Heilmeier <uh@heilmeier.eu> | 2018-11-08 22:10:24 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-11-09 07:46:38 +0000 |
commit | 9b1daa36296a39d94f22b1207544ba6b1b27709d (patch) | |
tree | 0c650fbbc42acb21f8fd03042d2b07be8020456e /epan/dissectors/packet-icmp.c | |
parent | 1e71786f200b94f3c4e70eef05de1dce4fd86aca (diff) |
ICMP: Add Extended Echo (Probe) RFC8335
Implementing ICMP extended echo (RFC8335) for IPv4.
Ping-Bug: 14457
Change-Id: Id7ae6fce88ef43f8b6a62b06285257416acd0a77
Reviewed-on: https://code.wireshark.org/review/30552
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-icmp.c')
-rw-r--r-- | epan/dissectors/packet-icmp.c | 256 |
1 files changed, 255 insertions, 1 deletions
diff --git a/epan/dissectors/packet-icmp.c b/epan/dissectors/packet-icmp.c index 04cc23e376..8cdd9c5235 100644 --- a/epan/dissectors/packet-icmp.c +++ b/epan/dissectors/packet-icmp.c @@ -33,6 +33,7 @@ #include <epan/ipproto.h> #include <epan/capture_dissectors.h> #include <epan/proto_data.h> +#include <epan/afn.h> #include <wsutil/pint.h> @@ -167,6 +168,24 @@ static expert_field ei_icmp_resp_not_found = EI_INIT; static expert_field ei_icmp_checksum = EI_INIT; static expert_field ei_icmp_ext_checksum = EI_INIT; +/* Extended Echo - Probe */ +static int hf_icmp_ext_echo_seq_num = -1; +static int hf_icmp_ext_echo_req_reserved = -1; +static int hf_icmp_ext_echo_req_local = -1; +static int hf_icmp_ext_echo_rsp_state = -1; +static int hf_icmp_ext_echo_rsp_reserved = -1; +static int hf_icmp_ext_echo_rsp_active = -1; +static int hf_icmp_ext_echo_rsp_ipv4 = -1; +static int hf_icmp_ext_echo_rsp_ipv6 = -1; +static int hf_icmp_int_ident_name_string = -1; +static int hf_icmp_int_ident_index = -1; +static int hf_icmp_int_ident_afi = -1; +static int hf_icmp_int_ident_addr_length = -1; +static int hf_icmp_int_ident_reserved = -1; +static int hf_icmp_int_ident_ipv4 = -1; +static int hf_icmp_int_ident_ipv6 = -1; +static int hf_icmp_int_ident_address = -1; + static dissector_handle_t icmp_handle; @@ -188,6 +207,8 @@ static dissector_handle_t icmp_handle; #define ICMP_MASKREQ 17 #define ICMP_MASKREPLY 18 #define ICMP_PHOTURIS 40 +#define ICMP_EXTECHO 42 +#define ICMP_EXTECHOREPLY 43 /* ICMP UNREACHABLE */ #define ICMP_NET_UNREACH 0 /* Network Unreachable */ @@ -246,6 +267,8 @@ static const value_string icmp_type_str[] = { {39, "SKIP"}, {ICMP_PHOTURIS, "Photuris"}, {41, "Experimental mobility protocols"}, + {ICMP_EXTECHO, "Extended Echo request"}, + {ICMP_EXTECHOREPLY, "Extended Echo reply"}, {0, NULL} }; @@ -311,6 +334,42 @@ static const value_string photuris_code_str[] = { {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} +}; + +#define ICMP_EXT_ECHO_IDENT_NAME 1 +#define ICMP_EXT_ECHO_IDENT_INDEX 2 +#define ICMP_EXT_ECHO_IDENT_ADDRESS 3 + +static const value_string ext_echo_ident_str[] = { + {ICMP_EXT_ECHO_IDENT_NAME, "Identifies Interface By Name"}, + {ICMP_EXT_ECHO_IDENT_INDEX, "Identifies Interface By Index"}, + {ICMP_EXT_ECHO_IDENT_ADDRESS, "Identifies Interface By Address"}, + {0, NULL} +}; + static const value_string mip_extensions[] = { {ICMP_MIP_EXTENSION_PAD, "One byte padding extension"}, /* RFC 2002 */ {ICMP_MIP_MOB_AGENT_ADV, "Mobility Agent Advertisement Extension"}, @@ -323,6 +382,7 @@ static const value_string mip_extensions[] = { static const value_string icmp_ext_class_str[] = { {1, "MPLS Label Stack Class"}, {2, "Interface Information Object"}, + {3, "Interface Identification Object"}, {0, NULL} }; @@ -346,6 +406,8 @@ static const value_string interface_role_str[] = { #define INTERFACE_INFORMATION_OBJECT_CLASS 2 +#define INTERFACE_IDENTIFICATION_OBJECT_CLASS 3 + #define MPLS_STACK_ENTRY_OBJECT_CLASS 1 #define MPLS_EXTENDED_PAYLOAD_OBJECT_CLASS 0 @@ -750,7 +812,6 @@ dissect_interface_information_object(tvbuff_t * tvb, gint offset, /*if ifIndex is set, next 32 bits are ifIndex */ if (if_index_flag) { - proto_tree_add_item(ext_object_tree, hf_icmp_int_info_index, tvb, offset, 4, ENC_NA); offset += 4; } @@ -810,6 +871,76 @@ dissect_interface_information_object(tvbuff_t * tvb, gint offset, } /*end dissect_interface_information_object */ +/* Dissect Interface Identification Object RFC 8335*/ +static gboolean +dissect_interface_identification_object(tvbuff_t * tvb, gint offset, + proto_tree * ext_object_tree, + proto_item * tf_object) +{ + proto_item *ti; + guint16 obj_length; + guint8 c_type; + gboolean unknown_object; + guint32 afi; + guint32 addr_length; + + unknown_object = FALSE; + /* Object length */ + obj_length = tvb_get_ntohs(tvb, offset); + + /* C-Type */ + c_type = tvb_get_guint8(tvb, offset + 3); + + proto_item_set_text(tf_object, "Interface Identification Object"); + if (tvb_reported_length_remaining(tvb, offset) < 5) { + /* Not enough room in the packet ! return unknown_object = TRUE */ + return TRUE; + } + + ti = proto_tree_add_uint(ext_object_tree, hf_icmp_ext_c_type, tvb, offset + 3, 1, c_type); + proto_item_append_text(ti, " (%s)", val_to_str(c_type, ext_echo_ident_str, "Unknown C-Type %u")); + offset += 4; + + switch(c_type) { + case ICMP_EXT_ECHO_IDENT_NAME: + proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_name_string, tvb, offset, obj_length - 4, ENC_ASCII|ENC_NA); + offset += (obj_length - 4); + break; + case ICMP_EXT_ECHO_IDENT_INDEX: + proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_index, tvb, offset, 4, ENC_NA); + offset += 4; + break; + case ICMP_EXT_ECHO_IDENT_ADDRESS: + proto_tree_add_item_ret_uint(ext_object_tree, hf_icmp_int_ident_afi, tvb, offset, 2, ENC_BIG_ENDIAN, &afi); + offset += 2; + proto_tree_add_item_ret_uint(ext_object_tree, hf_icmp_int_ident_addr_length, tvb, offset, 1, ENC_BIG_ENDIAN, &addr_length); + offset += 1; + proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + switch(afi){ + case AFNUM_INET: /* IPv4 */ + while(addr_length >= 4 && tvb_reported_length_remaining(tvb, offset) >= 4) { + proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + addr_length -= 4; + } + break; + case AFNUM_INET6: /* IPv6 */ + while(addr_length >= 16 && tvb_reported_length_remaining(tvb, offset) >= 16) { + proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_ipv6, tvb, offset, 16, ENC_NA); + offset += 16; + addr_length -= 16; + } + break; + default: /* Unknown ?! */ + proto_tree_add_item(ext_object_tree, hf_icmp_int_ident_address, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); + } + } + + return unknown_object; + +} /*end dissect_interface_identification_object */ + static void dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree * tree) { @@ -930,6 +1061,13 @@ dissect_extensions(tvbuff_t * tvb, packet_info *pinfo, gint offset, proto_tree * ext_object_tree, tf_object); break; + case INTERFACE_IDENTIFICATION_OBJECT_CLASS: + unknown_object = + dissect_interface_identification_object(tvb, + offset, + ext_object_tree, + tf_object); + break; default: unknown_object = TRUE; @@ -1311,6 +1449,16 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) val_to_str(icmp_code, photuris_code_str, "Unknown code: %u"); break; + case ICMP_EXTECHO: + code_str = + val_to_str(icmp_code, ext_echo_req_code_str, + "Unknown code: %u"); + break; + case ICMP_EXTECHOREPLY: + code_str = + val_to_str(icmp_code, ext_echo_reply_code_str, + "Unknown code: %u"); + break; default: code_str = NULL; break; @@ -1445,8 +1593,42 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) icmp_original_dgram_length * 4); PROTO_ITEM_SET_GENERATED(ti); } + break; + + case ICMP_EXTECHO: + proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2, + ENC_LITTLE_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_seq_num, tvb, 6, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_req_reserved, tvb, 7, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_req_local, tvb, 7, 1, + ENC_BIG_ENDIAN); + break; + + case ICMP_EXTECHOREPLY: + proto_tree_add_item(icmp_tree, hf_icmp_ident, tvb, 4, 2, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ident_le, tvb, 4, 2, + ENC_LITTLE_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_seq_num, tvb, 6, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_state, tvb, 7, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_reserved, tvb, 7, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_active, tvb, 7, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_ipv4, tvb, 7, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(icmp_tree, hf_icmp_ext_echo_rsp_ipv6, tvb, 7, 1, + ENC_BIG_ENDIAN); + break; } + /* Decode the additional information in the packet. */ switch (icmp_type) { case ICMP_UNREACH: @@ -1641,6 +1823,12 @@ dissect_icmp(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data) case ICMP_MASKREPLY: proto_tree_add_item(icmp_tree, hf_icmp_address_mask, tvb, 8, 4, ENC_BIG_ENDIAN); break; + + case ICMP_EXTECHO: + if (tvb_reported_length(tvb) > 8) { + dissect_extensions(tvb, pinfo, 8, icmp_tree); + } + break; } if (!PINFO_FD_VISITED(pinfo)) { @@ -2041,6 +2229,72 @@ void proto_register_icmp(void) {"Name", "icmp.int_info.name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + + {&hf_icmp_ext_echo_seq_num, + {"Sequence number", "icmp.ext.echo.seq", FT_UINT8, + BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_ext_echo_req_reserved, + {"Reserved", "icmp.ext.echo.req.res", FT_UINT8, + BASE_HEX, NULL, 0xFE, + NULL, HFILL}}, + {&hf_icmp_ext_echo_req_local, + {"Local bit", "icmp.ext.echo.req.local", FT_BOOLEAN, + 8, TFS(&tfs_set_notset), 0x01, + NULL, HFILL}}, + {&hf_icmp_ext_echo_rsp_state, + {"State", "icmp.ext.echo.rsp.state", FT_UINT8, + BASE_DEC, VALS(ext_echo_reply_state_str), 0xE0, + NULL, HFILL}}, + {&hf_icmp_ext_echo_rsp_reserved, + {"Reserved", "icmp.ext.echo.rsp.res", FT_UINT8, + BASE_HEX, NULL, 0x18, + NULL, HFILL}}, + {&hf_icmp_ext_echo_rsp_active, + {"Active bit", "icmp.ext.echo.rsp.active", FT_BOOLEAN, + 8, TFS(&tfs_set_notset), 0x04, + NULL, HFILL}}, + {&hf_icmp_ext_echo_rsp_ipv4, + {"IPv4 bit", "icmp.ext.echo.rsp.ipv4", FT_BOOLEAN, + 8, TFS(&tfs_set_notset), 0x02, + NULL, HFILL}}, + {&hf_icmp_ext_echo_rsp_ipv6, + {"IPv6 bit", "icmp.ext.echo.rsp.ipv6", FT_BOOLEAN, + 8, TFS(&tfs_set_notset), 0x01, + NULL, HFILL}}, + {&hf_icmp_int_ident_name_string, + {"Name", "icmp.int_ident.name", FT_STRING, + BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_int_ident_index, + {"Interface Index", "icmp.int_ident.index", FT_UINT32, + BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_int_ident_afi, + {"Address Family Identifier", "icmp.int_ident.afi", FT_UINT16, + BASE_DEC, VALS(afn_vals), 0x0, + "Address Family of the interface address", HFILL}}, + {&hf_icmp_int_ident_addr_length, + {"Address Length", "icmp.int_ident.addr_length", FT_UINT8, + BASE_DEC, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_int_ident_reserved, + {"Reserved", "icmp.int_ident.reserved", FT_BYTES, + BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_int_ident_ipv4, + {"Address", "icmp.int_ident.ipv4", FT_IPv4, + BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_int_ident_ipv6, + {"Address", "icmp.int_ident.ipv6", FT_IPv6, + BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + {&hf_icmp_int_ident_address, + {"Address", "icmp.int_ident.address", FT_BYTES, + BASE_NONE, NULL, 0x0, + NULL, HFILL}}, + }; static gint *ett[] = { |