diff options
-rw-r--r-- | epan/dissectors/packet-h1.c | 364 |
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: */ |