2000-03-02 07:27:05 +00:00
|
|
|
/* packet-h1.c
|
|
|
|
* Routines for Sinec H1 packet disassembly
|
|
|
|
* Gerrit Gehnen <G.Gehnen@atrie.de>
|
|
|
|
*
|
2006-05-21 04:49:01 +00:00
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
2000-03-02 07:27:05 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2018-02-12 11:23:27 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2000-03-02 07:27:05 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-20 02:03:38 +00:00
|
|
|
#include "config.h"
|
2000-03-02 07:27:05 +00:00
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2013-11-10 15:59:37 +00:00
|
|
|
#include <epan/exceptions.h>
|
2000-03-02 07:27:05 +00:00
|
|
|
|
2013-12-15 23:44:12 +00:00
|
|
|
void proto_register_h1(void);
|
|
|
|
void proto_reg_handoff_h1(void);
|
|
|
|
|
2000-03-02 07:27:05 +00:00
|
|
|
static int proto_h1 = -1;
|
|
|
|
static int hf_h1_header = -1;
|
|
|
|
static int hf_h1_len = -1;
|
2015-08-13 21:00:29 +00:00
|
|
|
static int hf_h1_block_type = -1;
|
|
|
|
static int hf_h1_block_len = -1;
|
2000-03-02 07:27:05 +00:00
|
|
|
static int hf_h1_opcode = -1;
|
|
|
|
static int hf_h1_dbnr = -1;
|
|
|
|
static int hf_h1_dwnr = -1;
|
|
|
|
static int hf_h1_dlen = -1;
|
|
|
|
static int hf_h1_org = -1;
|
|
|
|
static int hf_h1_response_value = -1;
|
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
|
2014-10-05 19:57:05 +00:00
|
|
|
#define EMPTY_BLOCK 0xFF
|
|
|
|
#define OPCODE_BLOCK 0x01
|
|
|
|
#define REQUEST_BLOCK 0x03
|
|
|
|
#define RESPONSE_BLOCK 0x0F
|
2000-03-02 07:27:05 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
static const value_string block_type_vals[] = {
|
2016-02-25 21:34:07 +00:00
|
|
|
{ EMPTY_BLOCK, "Empty Block" },
|
|
|
|
{ OPCODE_BLOCK, "Opcode Block" },
|
|
|
|
{ REQUEST_BLOCK, "Request Block" },
|
|
|
|
{ RESPONSE_BLOCK, "Response Block" },
|
|
|
|
{0, NULL}
|
2015-08-13 21:00:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2000-03-02 07:27:05 +00:00
|
|
|
static const value_string opcode_vals[] = {
|
2016-02-25 21:34:07 +00:00
|
|
|
{3, "Write Request"},
|
|
|
|
{4, "Write Response"},
|
|
|
|
{5, "Read Request"},
|
|
|
|
{6, "Read Response"},
|
|
|
|
{0, NULL}
|
2000-03-02 07:27:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string org_vals[] = {
|
2016-02-25 21:34:07 +00:00
|
|
|
{0x01, "DB"},
|
|
|
|
{0x02, "MB"},
|
|
|
|
{0x03, "EB"},
|
|
|
|
{0x04, "AB"},
|
|
|
|
{0x05, "PB"},
|
|
|
|
{0x06, "ZB"},
|
|
|
|
{0x07, "TB"},
|
|
|
|
{0x08, "BS"},
|
|
|
|
{0x09, "AS"},
|
|
|
|
{0x0a, "DX"},
|
|
|
|
{0x10, "DE"},
|
|
|
|
{0x11, "QB"},
|
|
|
|
{0, NULL}
|
2000-03-02 07:27:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const value_string returncode_vals[] = {
|
2016-02-25 21:34:07 +00:00
|
|
|
{0x00, "No error"},
|
|
|
|
{0x02, "Requested block does not exist"},
|
|
|
|
{0x03, "Requested block too small"},
|
|
|
|
{0xFF, "Error, reason unknown"},
|
|
|
|
{0, NULL}
|
2000-03-02 07:27:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static gint ett_h1 = -1;
|
2015-08-13 21:00:29 +00:00
|
|
|
static gint ett_block = -1;
|
2000-03-02 07:27:05 +00:00
|
|
|
|
2012-09-10 21:40:21 +00:00
|
|
|
static gboolean dissect_h1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
|
2000-07-21 07:51:34 +00:00
|
|
|
{
|
2015-08-13 21:00:29 +00:00
|
|
|
proto_tree *h1_tree, *block_tree;
|
|
|
|
proto_item *h1_ti, *block_ti;
|
|
|
|
gint offset = 0, offset_block_start;
|
|
|
|
guint8 h1_len;
|
|
|
|
guint8 block_type, block_len;
|
|
|
|
tvbuff_t *next_tvb;
|
|
|
|
|
|
|
|
if (tvb_captured_length(tvb) < 2) {
|
|
|
|
/* Not enough data captured to hold the "S5" header; don't try
|
|
|
|
to interpret it as H1. */
|
|
|
|
return FALSE;
|
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
if (!(tvb_get_guint8(tvb, 0) == 'S' && tvb_get_guint8(tvb, 1) == '5')) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
2000-03-02 07:27:05 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
col_set_str (pinfo->cinfo, COL_PROTOCOL, "H1");
|
|
|
|
col_set_str(pinfo->cinfo, COL_INFO, "S5: ");
|
2000-03-02 07:27:05 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
h1_ti = proto_tree_add_item(tree, proto_h1, tvb, offset, -1, ENC_NA);
|
|
|
|
h1_tree = proto_item_add_subtree(h1_ti, ett_h1);
|
Add the "Edit:Protocols..." feature which currently only implements
the following:
It is now possible to enable/disable a particular protocol decoding
(i.e. the protocol dissector is void or not). When a protocol
is disabled, it is displayed as Data and of course, all linked
sub-protocols are disabled as well.
Disabling a protocol could be interesting:
- in case of buggy dissectors
- in case of wrong heuristics
- for performance reasons
- to decode the data as another protocol (TODO)
Currently (if I am not wrong), all dissectors but NFS can be disabled
(and dissectors that do not register protocols :-)
I do not like the way the RPC sub-dissectors are disabled (in the
sub-dissectors) since this could be done in the RPC dissector itself,
knowing the sub-protocol hfinfo entry (this is why, I've not modified
the NFS one yet).
Two functions are added in proto.c :
gboolean proto_is_protocol_enabled(int n);
void proto_set_decoding(int n, gboolean enabled);
and two MACROs which can be used in dissectors:
OLD_CHECK_DISPLAY_AS_DATA(index, pd, offset, fd, tree)
CHECK_DISPLAY_AS_DATA(index, tvb, pinfo, tree)
See also the XXX in proto_dlg.c and proto.c around the new functions.
svn path=/trunk/; revision=2267
2000-08-13 14:09:15 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
proto_tree_add_item(h1_tree, hf_h1_header, tvb, offset, 2, ENC_BIG_ENDIAN);
|
|
|
|
offset += 2;
|
2001-01-05 08:34:35 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
h1_len = tvb_get_guint8(tvb, offset);
|
|
|
|
proto_tree_add_item(h1_tree, hf_h1_len, tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
proto_item_set_len(h1_ti, h1_len);
|
|
|
|
offset++;
|
2015-08-13 20:44:29 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
while (offset < h1_len) {
|
|
|
|
offset_block_start = offset;
|
2015-08-13 20:44:29 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
block_type = tvb_get_guint8(tvb, offset);
|
|
|
|
block_len = tvb_get_guint8(tvb, offset+1);
|
2015-08-13 20:44:29 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
if (!try_val_to_str(block_type, block_type_vals)) {
|
|
|
|
/* XXX - should we skip unknown blocks? */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (block_len == 0) {
|
|
|
|
/* XXX - expert info */
|
2014-10-05 19:57:05 +00:00
|
|
|
break;
|
2015-08-13 21:00:29 +00:00
|
|
|
}
|
2015-08-13 20:44:29 +00:00
|
|
|
|
2015-08-13 21:00:29 +00:00
|
|
|
block_tree = proto_tree_add_subtree_format(h1_tree,
|
|
|
|
tvb, offset, -1, ett_block, &block_ti, "%s",
|
|
|
|
val_to_str_const(block_type, block_type_vals, "Unknown block"));
|
|
|
|
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_block_type,
|
|
|
|
tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
/* we keep increasing offset as we go though the block
|
|
|
|
however, to find the beginning of the next block,
|
|
|
|
we use the current block's start offset and its length field */
|
|
|
|
offset++;
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_block_len,
|
|
|
|
tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
proto_item_set_len(block_ti, block_len);
|
|
|
|
offset++;
|
|
|
|
|
|
|
|
switch (block_type) {
|
|
|
|
case OPCODE_BLOCK:
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_opcode,
|
|
|
|
tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
col_append_str (pinfo->cinfo, COL_INFO,
|
|
|
|
val_to_str (tvb_get_guint8(tvb, offset),
|
|
|
|
opcode_vals, "Unknown Opcode (0x%2.2x)"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQUEST_BLOCK:
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_org, tvb,
|
|
|
|
offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
|
|
|
|
val_to_str (tvb_get_guint8(tvb, offset),
|
|
|
|
org_vals,"Unknown Type (0x%2.2x)"));
|
|
|
|
offset++;
|
|
|
|
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_dbnr, tvb,
|
|
|
|
offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
col_append_fstr(pinfo->cinfo, COL_INFO, " %d",
|
|
|
|
tvb_get_guint8(tvb, offset));
|
|
|
|
offset++;
|
|
|
|
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_dwnr, tvb,
|
|
|
|
offset, 2, ENC_BIG_ENDIAN);
|
|
|
|
col_append_fstr (pinfo->cinfo, COL_INFO, " DW %d",
|
|
|
|
tvb_get_ntohs(tvb, offset));
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_dlen, tvb,
|
|
|
|
offset, 2, ENC_BIG_ENDIAN);
|
|
|
|
col_append_fstr (pinfo->cinfo, COL_INFO, " Count %d",
|
|
|
|
tvb_get_ntohs(tvb, offset));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESPONSE_BLOCK:
|
|
|
|
proto_tree_add_item(block_tree, hf_h1_response_value,
|
|
|
|
tvb, offset, 1, ENC_BIG_ENDIAN);
|
|
|
|
col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
|
|
|
|
val_to_str (tvb_get_guint8(tvb, offset),
|
|
|
|
returncode_vals,"Unknown Returncode (0x%2.2x"));
|
|
|
|
break;
|
2014-10-05 19:57:05 +00:00
|
|
|
}
|
2015-08-13 21:00:29 +00:00
|
|
|
|
|
|
|
offset = offset_block_start + block_len; /* see the comment above */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tvb_reported_length_remaining(tvb, offset) > 0) {
|
|
|
|
next_tvb = tvb_new_subset_remaining(tvb, offset);
|
2016-03-20 00:33:14 +00:00
|
|
|
call_data_dissector(next_tvb, pinfo, tree);
|
2015-08-13 21:00:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2000-03-02 07:27:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_h1 (void)
|
|
|
|
{
|
2015-08-13 21:00:29 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{&hf_h1_header,
|
|
|
|
{"H1-Header", "h1.header", FT_UINT16, BASE_HEX, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{&hf_h1_len,
|
|
|
|
{"Length indicator", "h1.len", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{&hf_h1_block_type,
|
|
|
|
{"Block type", "h1.block_type", FT_UINT8, BASE_HEX, VALS(block_type_vals), 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{&hf_h1_block_len,
|
|
|
|
{"Block length", "h1.block_len", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
|
|
|
{&hf_h1_opcode,
|
|
|
|
{"Opcode", "h1.opcode", FT_UINT8, BASE_HEX, VALS (opcode_vals), 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{&hf_h1_org,
|
|
|
|
{"Memory type", "h1.org", FT_UINT8, BASE_HEX, VALS (org_vals), 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{&hf_h1_dbnr,
|
|
|
|
{"Memory block number", "h1.dbnr", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
|
|
|
{&hf_h1_dwnr,
|
|
|
|
{"Address within memory block", "h1.dwnr", FT_UINT16, BASE_DEC, NULL, 0x0,
|
|
|
|
NULL, HFILL }},
|
|
|
|
{&hf_h1_dlen,
|
|
|
|
{"Length in words", "h1.dlen", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
|
|
|
|
{&hf_h1_response_value,
|
|
|
|
{"Response value", "h1.resvalue", FT_UINT8, BASE_DEC,
|
|
|
|
VALS (returncode_vals), 0x0, NULL, HFILL }}
|
|
|
|
};
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_h1,
|
|
|
|
&ett_block,
|
|
|
|
};
|
|
|
|
|
|
|
|
proto_h1 = proto_register_protocol ("Sinec H1 Protocol", "H1", "h1");
|
|
|
|
proto_register_field_array (proto_h1, hf, array_length (hf));
|
|
|
|
proto_register_subtree_array (ett, array_length (ett));
|
2000-03-02 07:27:05 +00:00
|
|
|
}
|
Add routines to:
register lists of "heuristic" dissectors, which are handed a
frame that may or may contain a payload for the protocol they
dissect, and that return FALSE if it's not or dissect the packet
and return TRUE if it is;
add a dissector to such a list;
go through such a list, calling each dissector until either a
dissector returns TRUE, in which case the routine returns TRUE,
or it runs out of entries in the list, in which case the routine
returns FALSE.
Have lists of heuristic dissectors for TCP and for COTP when used with
the Inactive Subset of CLNP, and add the GIOP and Yahoo Messenger
dissectors to the first list and the Sinec H1 dissector to the second
list.
Make the dissector name argument to "dissector_add()" and
"dissector_delete()" a "const char *" rarther than just a "char *".
Add "heur_dissector_add()", the routine to add a heuristic dissector to
a list of heuristic dissectors, to the set of routines we can export to
plugins through a table on platforms where dynamically-loaded code can't
call stuff in the main program, and initialize the element in the table
in question for "dissector_add()" (which we'd forgotten to do).
svn path=/trunk/; revision=1909
2000-05-05 09:32:36 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_h1(void)
|
|
|
|
{
|
2015-08-13 21:00:29 +00:00
|
|
|
heur_dissector_add("cotp", dissect_h1,
|
|
|
|
"Sinec H1 over COTP", "hi_cotp", proto_h1, HEURISTIC_ENABLE);
|
|
|
|
heur_dissector_add("cotp_is", dissect_h1,
|
|
|
|
"Sinec H1 over COTP (inactive subset)", "hi_cotp_is", proto_h1, HEURISTIC_ENABLE);
|
|
|
|
heur_dissector_add("tcp", dissect_h1,
|
|
|
|
"Sinec H1 over TCP", "hi_tcp", proto_h1, HEURISTIC_ENABLE);
|
Add routines to:
register lists of "heuristic" dissectors, which are handed a
frame that may or may contain a payload for the protocol they
dissect, and that return FALSE if it's not or dissect the packet
and return TRUE if it is;
add a dissector to such a list;
go through such a list, calling each dissector until either a
dissector returns TRUE, in which case the routine returns TRUE,
or it runs out of entries in the list, in which case the routine
returns FALSE.
Have lists of heuristic dissectors for TCP and for COTP when used with
the Inactive Subset of CLNP, and add the GIOP and Yahoo Messenger
dissectors to the first list and the Sinec H1 dissector to the second
list.
Make the dissector name argument to "dissector_add()" and
"dissector_delete()" a "const char *" rarther than just a "char *".
Add "heur_dissector_add()", the routine to add a heuristic dissector to
a list of heuristic dissectors, to the set of routines we can export to
plugins through a table on platforms where dynamically-loaded code can't
call stuff in the main program, and initialize the element in the table
in question for "dissector_add()" (which we'd forgotten to do).
svn path=/trunk/; revision=1909
2000-05-05 09:32:36 +00:00
|
|
|
}
|
2014-10-05 19:57:05 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
|
|
*
|
|
|
|
* Local Variables:
|
2015-08-13 21:00:29 +00:00
|
|
|
* c-basic-offset: 4
|
2016-02-25 21:34:07 +00:00
|
|
|
* tab-width: 8
|
2014-10-05 19:57:05 +00:00
|
|
|
* indent-tabs-mode: nil
|
|
|
|
* End:
|
|
|
|
*
|
2016-02-25 21:34:07 +00:00
|
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
2014-10-05 19:57:05 +00:00
|
|
|
*/
|