* Routines for Sinec H1 packet disassembly
* Gerrit Gehnen <G.Gehnen@atrie.de>
*
- * $Id: packet-h1.c,v 1.2 2000/03/02 07:38:02 guy Exp $
+ * $Id: packet-h1.c,v 1.20 2001/06/18 02:17:46 guy Exp $
*
* Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@zing.org>
+ * By Gerald Combs <gerald@ethereal.com>
* Copyright 1998 Gerald Combs
- *
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <glib.h>
#include "packet.h"
-#include "globals.h"
-#include "packet-h1.h"
static int proto_h1 = -1;
static int hf_h1_header = -1;
{0x00, "No error"},
{0x02, "Requested block does not exist"},
{0x03, "Requested block too small"},
- {0xFF, "Error, reason unkown"},
+ {0xFF, "Error, reason unknown"},
{0, NULL}
};
static gint ett_response = -1;
static gint ett_empty = -1;
-
-void
-dissect_h1 (const u_char * pd, int offset, frame_data * fd, proto_tree * tree)
+static gboolean dissect_h1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
+ tvbuff_t *next_tvb;
+
proto_tree *h1_tree = NULL;
+
proto_item *ti;
proto_tree *opcode_tree = NULL;
proto_tree *org_tree = NULL;
proto_tree *response_tree = NULL;
proto_tree *empty_tree = NULL;
- unsigned int position = 2;
+ unsigned int position = 3;
+ unsigned int offset=0;
- if (pd[offset] == 'S' && pd[offset + 1] == '5')
+ if (tvb_length_remaining(tvb, 0) < 2)
{
- if (check_col (fd, COL_PROTOCOL))
- col_add_str (fd, COL_PROTOCOL, "H1");
- if (check_col (fd, COL_INFO))
- col_add_str (fd, COL_INFO, "S5: ");
- if (tree)
- {
- ti = proto_tree_add_item (tree, proto_h1, offset, 16, NULL);
- h1_tree = proto_item_add_subtree (ti, ett_h1);
- proto_tree_add_item (h1_tree, hf_h1_header, offset, 2,
- pd[offset] * 0x100 + pd[offset + 1]);
- proto_tree_add_item (h1_tree, hf_h1_len, offset + 2, 1,
- pd[offset + 2]);
- }
-
- while (position < pd[offset + 2])
- {
- switch (pd[offset + position])
- {
- case OPCODE_BLOCK:
- if (h1_tree)
- {
- ti = proto_tree_add_item (h1_tree, hf_h1_opfield,
- offset + position,
- pd[offset + position + 1],
- pd[offset + position]);
- opcode_tree = proto_item_add_subtree (ti, ett_opcode);
- proto_tree_add_item (opcode_tree, hf_h1_oplen,
- offset + position + 1, 1,
- pd[offset + position + 1]);
- proto_tree_add_item (opcode_tree, hf_h1_opcode,
- offset + position + 2, 1,
- pd[offset + position + 2]);
- }
- if (check_col (fd, COL_INFO))
- {
- col_append_str (fd, COL_INFO,
- match_strval (pd[offset + position + 2],
- opcode_vals));
- }
- break;
- case REQUEST_BLOCK:
- if (h1_tree)
- {
- ti = proto_tree_add_item (h1_tree, hf_h1_requestblock,
- offset + position,
- pd[offset + position + 1],
- pd[offset + position]);
- org_tree = proto_item_add_subtree (ti, ett_org);
- proto_tree_add_item (org_tree, hf_h1_requestlen,
- offset + position + 1, 1,
- pd[offset + position + 1]);
- proto_tree_add_item (org_tree, hf_h1_org,
- offset + position + 2, 1,
- pd[offset + position + 2]);
- proto_tree_add_item (org_tree, hf_h1_dbnr,
- offset + position + 3, 1,
- pd[offset + position + 3]);
- proto_tree_add_item (org_tree, hf_h1_dwnr,
- offset + position + 4, 2,
- pd[offset + position + 4] * 0x100 +
- pd[offset + position + 5]);
- proto_tree_add_item (org_tree, hf_h1_dlen,
- offset + position + 6, 2,
- pd[offset + position + 6] * 0x100 +
- pd[offset + position + 7]);
- }
- if (check_col (fd, COL_INFO))
- {
- col_append_fstr (fd, COL_INFO, " %s %d",
- match_strval (pd[offset + position + 2],
- org_vals),
- pd[offset + position + 3]);
- col_append_fstr (fd, COL_INFO, " DW %d",
- pd[offset + position + 4] * 0x100 +
- pd[offset + position + 5]);
- col_append_fstr (fd, COL_INFO, " Count %d",
- pd[offset + position + 6] * 0x100 +
- pd[offset + position + 7]);
- }
- break;
- case RESPONSE_BLOCK:
- if (h1_tree)
- {
- ti = proto_tree_add_item (h1_tree, hf_h1_response,
- offset + position,
- pd[offset + position + 1],
- pd[offset + position]);
- response_tree = proto_item_add_subtree (ti, ett_response);
- proto_tree_add_item (response_tree, hf_h1_response_len,
- offset + position + 1, 1,
- pd[offset + position + 1]);
- proto_tree_add_item (response_tree, hf_h1_response_value,
- offset + position + 2, 1,
- pd[offset + position + 2]);
- }
- if (check_col (fd, COL_INFO))
- {
- col_append_fstr (fd, COL_INFO, " %s",
- match_strval (pd[offset + position + 2],
- returncode_vals));
- }
- break;
- case EMPTY_BLOCK:
- if (h1_tree)
- {
- ti = proto_tree_add_item (h1_tree, hf_h1_empty,
- offset + position,
- pd[offset + position + 1],
- pd[offset + position]);
- empty_tree = proto_item_add_subtree (ti, ett_empty);
-
- proto_tree_add_item (empty_tree, hf_h1_empty_len,
- offset + position + 1, 1,
- pd[offset + position + 1]);
- }
- break;
- default:
- /* TODO: Add Default Handler. */
- }
- position += pd[offset + position + 1]; /* Goto next section */
- } /* ..while */
+ /* Not enough data captured to hold the "S5" header; don't try
+ to interpret it as H1. */
+ return FALSE;
+ }
- dissect_data (pd, offset + pd[offset + 2], fd, tree);
+ if (!(tvb_get_guint8(tvb,offset) == 'S' && tvb_get_guint8(tvb,offset+1) == '5'))
+ {
+ return FALSE;
}
- else
+
+ if (check_col (pinfo->fd, COL_PROTOCOL))
+ col_set_str (pinfo->fd, COL_PROTOCOL, "H1");
+ if (check_col (pinfo->fd, COL_INFO))
+ col_add_str (pinfo->fd, COL_INFO, "S5: ");
+ if (tree)
{
- dissect_data (pd, offset, fd, tree);
+ ti = proto_tree_add_item (tree, proto_h1, tvb, offset, 16, FALSE);
+ 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:
+ if (h1_tree)
+ {
+ 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));
+ }
+ if (check_col (pinfo->fd, COL_INFO))
+ {
+ col_append_str (pinfo->fd, COL_INFO,
+ val_to_str (tvb_get_guint8(tvb,offset + position + 2),
+ opcode_vals,"Unknown Opcode (0x%2.2x)"));
+ }
+ break;
+ case REQUEST_BLOCK:
+ if (h1_tree)
+ {
+ 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));
+ }
+ if (check_col (pinfo->fd, COL_INFO))
+ {
+ col_append_fstr (pinfo->fd, 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->fd, COL_INFO, " DW %d",
+ tvb_get_ntohs(tvb,offset+position+4));
+ col_append_fstr (pinfo->fd, COL_INFO, " Count %d",
+ tvb_get_ntohs(tvb,offset+position+6));
+ }
+ break;
+ case RESPONSE_BLOCK:
+ if (h1_tree)
+ {
+ 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));
+ }
+ if (check_col (pinfo->fd, COL_INFO))
+ {
+ col_append_fstr (pinfo->fd, COL_INFO, " %s",
+ val_to_str (tvb_get_guint8(tvb,offset + position + 2),
+ returncode_vals,"Unknown Returcode (0x%2.2x"));
+ }
+ break;
+ case EMPTY_BLOCK:
+ if (h1_tree)
+ {
+ 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));
+ }
+ break;
+ default:
+ /* This is not a valid telegram. So cancel dissection
+ and try the next dissector */
+ return FALSE;
+ break;
+ }
+ position += tvb_get_guint8(tvb,offset + position + 1); /* Goto next section */
+ } /* ..while */
+ next_tvb = tvb_new_subset(tvb, offset+tvb_get_guint8(tvb,offset+2), -1, -1);
+ dissect_data(next_tvb, 0, pinfo, tree);
+
+ return TRUE;
}
static hf_register_info hf[] = {
{&hf_h1_header,
{"H1-Header", "h1.header", FT_UINT16, BASE_HEX, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_len,
{"Length indicator", "h1.len", FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_opfield,
{"Operation identifier", "h1.opfield", FT_UINT8, BASE_HEX, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_oplen,
- {"Operation length", "h1.oplen", FT_UINT8, BASE_HEX, NULL, 0x0, ""}},
+ {"Operation length", "h1.oplen", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
{&hf_h1_opcode,
{"Opcode", "h1.opcode", FT_UINT8, BASE_HEX, VALS (opcode_vals), 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_requestblock,
{"Request identifier", "h1.request", FT_UINT8, BASE_HEX, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_requestlen,
{"Request length", "h1.reqlen", FT_UINT8, BASE_HEX, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_org,
{"Memory type", "h1.org", FT_UINT8, BASE_HEX, VALS (org_vals), 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_dbnr,
- {"Memory block number", "h1.dbnr", FT_UINT8, BASE_DEC, NULL, 0x0, ""}},
+ {"Memory block number", "h1.dbnr", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
{&hf_h1_dwnr,
{"Address within memory block", "h1.dwnr", FT_UINT16, BASE_DEC, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_dlen,
- {"Length in words", "h1.dlen", FT_INT16, BASE_DEC, NULL, 0x0, ""}},
+ {"Length in words", "h1.dlen", FT_INT16, BASE_DEC, NULL, 0x0, "", HFILL }},
{&hf_h1_response,
- {"Response identifier", "h1.response", FT_UINT8, BASE_DEC, NULL, 0x0, ""}},
+ {"Response identifier", "h1.response", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
{&hf_h1_response_len,
{"Response length", "h1.reslen", FT_UINT8, BASE_DEC, NULL, 0x0,
- ""}},
+ "", HFILL }},
{&hf_h1_response_value,
{"Response value", "h1.resvalue", FT_UINT8, BASE_DEC,
- VALS (returncode_vals), 0x0, ""}},
+ VALS (returncode_vals), 0x0, "", HFILL }},
{&hf_h1_empty,
- {"Emtpy field", "h1.empty", FT_UINT8, BASE_HEX, NULL, 0x0,
- ""}},
+ {"Empty field", "h1.empty", FT_UINT8, BASE_HEX, NULL, 0x0,
+ "", HFILL }},
{&hf_h1_empty_len,
{"Empty field length", "h1.empty_len", FT_UINT8, BASE_DEC, NULL, 0x0,
- ""}}
+ "", HFILL }}
};
static gint *ett[] = {
&ett_empty
};
- proto_h1 = proto_register_protocol ("Sinec H1 Protocol", "h1");
+ 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_is", dissect_h1, proto_h1);
+}