aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-h1.c364
1 files changed, 166 insertions, 198 deletions
diff --git a/epan/dissectors/packet-h1.c b/epan/dissectors/packet-h1.c
index 9d2139d123..014f817d42 100644
--- a/epan/dissectors/packet-h1.c
+++ b/epan/dissectors/packet-h1.c
@@ -32,28 +32,32 @@ void proto_reg_handoff_h1(void);
static int proto_h1 = -1;
static int hf_h1_header = -1;
static int hf_h1_len = -1;
-static int hf_h1_opfield = -1;
-static int hf_h1_oplen = -1;
+static int hf_h1_block_type = -1;
+static int hf_h1_block_len = -1;
static int hf_h1_opcode = -1;
-static int hf_h1_requestblock = -1;
-static int hf_h1_requestlen = -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 = -1;
-static int hf_h1_response_len = -1;
static int hf_h1_response_value = -1;
-static int hf_h1_empty_len = -1;
-static int hf_h1_empty = -1;
static dissector_handle_t data_handle;
+
#define EMPTY_BLOCK 0xFF
#define OPCODE_BLOCK 0x01
#define REQUEST_BLOCK 0x03
#define RESPONSE_BLOCK 0x0F
+static const value_string block_type_vals[] = {
+ { EMPTY_BLOCK, "Empty Block" },
+ { OPCODE_BLOCK, "Opcode Block" },
+ { REQUEST_BLOCK, "Request Block" },
+ { RESPONSE_BLOCK, "Response Block" },
+ {0, NULL}
+};
+
+
static const value_string opcode_vals[] = {
{3, "Write Request"},
{4, "Write Response"},
@@ -87,228 +91,192 @@ static const value_string returncode_vals[] = {
};
static gint ett_h1 = -1;
-static gint ett_opcode = -1;
-static gint ett_org = -1;
-static gint ett_response = -1;
-static gint ett_empty = -1;
+static gint ett_block = -1;
static gboolean dissect_h1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
- tvbuff_t *next_tvb;
-
- proto_tree *h1_tree;
+ 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;
+ }
- proto_item *ti;
- proto_tree *opcode_tree;
- proto_tree *org_tree;
- proto_tree *response_tree;
- proto_tree *empty_tree;
+ if (!(tvb_get_guint8(tvb, 0) == 'S' && tvb_get_guint8(tvb, 1) == '5')) {
+ return FALSE;
+ }
- unsigned int position = 3;
- unsigned int offset=0;
+ col_set_str (pinfo->cinfo, COL_PROTOCOL, "H1");
+ col_set_str(pinfo->cinfo, COL_INFO, "S5: ");
- 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;
- }
+ h1_ti = proto_tree_add_item(tree, proto_h1, tvb, offset, -1, ENC_NA);
+ h1_tree = proto_item_add_subtree(h1_ti, ett_h1);
- if (!(tvb_get_guint8(tvb,offset) == 'S' && tvb_get_guint8(tvb,offset+1) == '5'))
- {
- return FALSE;
- }
+ proto_tree_add_item(h1_tree, hf_h1_header, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
- col_set_str (pinfo->cinfo, COL_PROTOCOL, "H1");
- col_set_str(pinfo->cinfo, COL_INFO, "S5: ");
-
- ti = proto_tree_add_item (tree, proto_h1, tvb, offset, 16, ENC_NA);
- h1_tree = proto_item_add_subtree (ti, ett_h1);
- proto_tree_add_uint (h1_tree, hf_h1_header, tvb, offset, 2,
- tvb_get_ntohs(tvb,offset));
- proto_tree_add_uint (h1_tree, hf_h1_len, tvb, offset + 2, 1,
- tvb_get_guint8(tvb,offset+2));
-
- while (position < tvb_get_guint8(tvb,offset+2))
- {
- switch (tvb_get_guint8(tvb,offset + position))
- {
- case OPCODE_BLOCK:
- ti = proto_tree_add_uint (h1_tree, hf_h1_opfield, tvb,
- offset + position,
- tvb_get_guint8(tvb,offset+position+1),
- tvb_get_guint8(tvb,offset+position));
- opcode_tree = proto_item_add_subtree (ti, ett_opcode);
- proto_tree_add_uint (opcode_tree, hf_h1_oplen, tvb,
- offset + position + 1, 1,
- tvb_get_guint8(tvb,offset + position + 1));
- proto_tree_add_uint (opcode_tree, hf_h1_opcode, tvb,
- offset + position + 2, 1,
- tvb_get_guint8(tvb,offset + position + 2));
-
- col_append_str (pinfo->cinfo, COL_INFO,
- val_to_str (tvb_get_guint8(tvb,offset + position + 2),
- opcode_vals,"Unknown Opcode (0x%2.2x)"));
- break;
+ 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++;
- case REQUEST_BLOCK:
- ti = proto_tree_add_uint (h1_tree, hf_h1_requestblock, tvb,
- offset + position,
- tvb_get_guint8(tvb,offset + position + 1),
- tvb_get_guint8(tvb,offset + position));
- org_tree = proto_item_add_subtree (ti, ett_org);
- proto_tree_add_uint (org_tree, hf_h1_requestlen, tvb,
- offset + position + 1, 1,
- tvb_get_guint8(tvb,offset + position+1));
- proto_tree_add_uint (org_tree, hf_h1_org, tvb,
- offset + position + 2, 1,
- tvb_get_guint8(tvb,offset + position+2));
- proto_tree_add_uint (org_tree, hf_h1_dbnr, tvb,
- offset + position + 3, 1,
- tvb_get_guint8(tvb,offset + position+3));
- proto_tree_add_uint (org_tree, hf_h1_dwnr, tvb,
- offset + position + 4, 2,
- tvb_get_ntohs(tvb,offset+position+4));
- proto_tree_add_int (org_tree, hf_h1_dlen, tvb,
- offset + position + 6, 2,
- tvb_get_ntohs(tvb,offset+position+6));
-
- col_append_fstr (pinfo->cinfo, COL_INFO, " %s %d",
- val_to_str (tvb_get_guint8(tvb,offset + position + 2),
- org_vals,"Unknown Type (0x%2.2x)"),
- tvb_get_guint8(tvb,offset + position + 3));
- col_append_fstr (pinfo->cinfo, COL_INFO, " DW %d",
- tvb_get_ntohs(tvb,offset+position+4));
- col_append_fstr (pinfo->cinfo, COL_INFO, " Count %d",
- tvb_get_ntohs(tvb,offset+position+6));
- break;
+ while (offset < h1_len) {
+ offset_block_start = offset;
- case RESPONSE_BLOCK:
- ti = proto_tree_add_uint (h1_tree, hf_h1_response, tvb,
- offset + position,
- tvb_get_guint8(tvb,offset + position + 1),
- tvb_get_guint8(tvb,offset + position));
- response_tree = proto_item_add_subtree (ti, ett_response);
- proto_tree_add_uint (response_tree, hf_h1_response_len, tvb,
- offset + position + 1, 1,
- tvb_get_guint8(tvb,offset + position+1));
- proto_tree_add_uint (response_tree, hf_h1_response_value, tvb,
- offset + position + 2, 1,
- tvb_get_guint8(tvb,offset + position+2));
-
- col_append_fstr (pinfo->cinfo, COL_INFO, " %s",
- val_to_str (tvb_get_guint8(tvb,offset + position + 2),
- returncode_vals,"Unknown Returncode (0x%2.2x"));
- break;
+ block_type = tvb_get_guint8(tvb, offset);
+ block_len = tvb_get_guint8(tvb, offset+1);
- case EMPTY_BLOCK:
- ti = proto_tree_add_uint (h1_tree, hf_h1_empty, tvb,
- offset + position,
- tvb_get_guint8(tvb,offset + position + 1),
- tvb_get_guint8(tvb,offset + position));
- empty_tree = proto_item_add_subtree (ti, ett_empty);
- proto_tree_add_uint (empty_tree, hf_h1_empty_len, tvb,
- offset + position + 1, 1,
- tvb_get_guint8(tvb,offset + position+1));
+ 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 */
break;
+ }
- default:
- /* This is not a valid telegram. So cancel dissection
- and try the next dissector */
- return FALSE;
+ 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;
}
- if (tvb_get_guint8(tvb,offset + position + 1) == 0)
- break;
- position += tvb_get_guint8(tvb,offset + position + 1); /* Goto next section */
- } /* ..while */
- next_tvb = tvb_new_subset_remaining(tvb, offset+tvb_get_guint8(tvb,offset+2));
- call_dissector(data_handle,next_tvb, pinfo, tree);
-
- return TRUE;
+
+ 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);
+ call_dissector(data_handle, next_tvb, pinfo, tree);
+ }
+
+ return TRUE;
}
void
proto_register_h1 (void)
{
- 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_opfield,
- {"Operation identifier", "h1.opfield", FT_UINT8, BASE_HEX, NULL, 0x0,
- NULL, HFILL }},
- {&hf_h1_oplen,
- {"Operation length", "h1.oplen", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
- {&hf_h1_opcode,
- {"Opcode", "h1.opcode", FT_UINT8, BASE_HEX, VALS (opcode_vals), 0x0,
- NULL, HFILL }},
- {&hf_h1_requestblock,
- {"Request identifier", "h1.request", FT_UINT8, BASE_HEX, NULL, 0x0,
- NULL, HFILL }},
- {&hf_h1_requestlen,
- {"Request length", "h1.reqlen", FT_UINT8, BASE_HEX, NULL, 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,
- {"Response identifier", "h1.response", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
- {&hf_h1_response_len,
- {"Response length", "h1.reslen", FT_UINT8, BASE_DEC, NULL, 0x0,
- NULL, HFILL }},
- {&hf_h1_response_value,
- {"Response value", "h1.resvalue", FT_UINT8, BASE_DEC,
- VALS (returncode_vals), 0x0, NULL, HFILL }},
- {&hf_h1_empty,
- {"Empty field", "h1.empty", FT_UINT8, BASE_HEX, NULL, 0x0,
- NULL, HFILL }},
- {&hf_h1_empty_len,
- {"Empty field length", "h1.empty_len", FT_UINT8, BASE_DEC, NULL, 0x0,
- NULL, HFILL }}
- };
-
- static gint *ett[] = {
- &ett_h1,
- &ett_opcode,
- &ett_response,
- &ett_org,
- &ett_empty
- };
-
- 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));
+ 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));
}
void
proto_reg_handoff_h1(void)
{
- 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);
- data_handle = find_dissector("data");
+ 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);
+
+ data_handle = find_dissector("data");
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local Variables:
- * c-basic-offset: 2
- * tab-width: 8
+ * c-basic-offset: 4
+ * tab-width: 4
* indent-tabs-mode: nil
* End:
*
- * ex: set shiftwidth=2 tabstop=8 expandtab:
- * :indentSize=2:tabSize=8:noTabs=true:
+ * ex: set shiftwidth=4 tabstop=4 expandtab:
+ * :indentSize=4:tabSize=4:noTabs=true:
*/