Squelch an MSVC++ complaint.
[obnox/wireshark/wip.git] / packet-h1.c
index a2858b4b15d517b903ffb21ffba5d544c15aad3b..d03a333660808299aaf8c568a4a72ff43374ee08 100644 (file)
@@ -2,12 +2,11 @@
  * 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
@@ -36,8 +35,6 @@
 
 #include <glib.h>
 #include "packet.h"
-#include "globals.h"
-#include "packet-h1.h"
 
 static int proto_h1 = -1;
 static int hf_h1_header = -1;
@@ -90,7 +87,7 @@ static const value_string returncode_vals[] = {
   {0x00, "No error"},
   {0x02, "Requested block does not exist"},
   {0x03, "Requested block too small"},
-  {0xFF, "Error, reason unkown"},
+  {0xFF, "Error, reason unknown"},
   {0, NULL}
 };
 
@@ -100,149 +97,157 @@ static gint ett_org = -1;
 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;
 }
 
 
@@ -252,48 +257,48 @@ proto_register_h1 (void)
   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[] = {
@@ -304,7 +309,13 @@ proto_register_h1 (void)
     &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);
+}