Gerrit Gehnen's dissector for the Sinec H1 protocol (Siemens Industrial
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 2 Mar 2000 07:27:05 +0000 (07:27 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 2 Mar 2000 07:27:05 +0000 (07:27 +0000)
Ethernet; used for communication with Siemens S5 PLC's over Ethernet),
and his changes to display OSI COTP TSAPs that consist solely of
printable characters as text rather than as hex data and to decode the
version number resource in COTP.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@1677 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
Makefile.am
Makefile.nmake
packet-h1.c [new file with mode: 0644]
packet-h1.h [new file with mode: 0644]
packet-osi.c

diff --git a/AUTHORS b/AUTHORS
index c9ad7eff93e5e1fcb81cbfdf4008aab34bc5bcf2..a8c258f680537e46062dffcd03bd85bf03837826 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -236,6 +236,8 @@ Thomas Parvais <thomas.parvais@advalvas.be> {
 
 Gerrit Gehnen <G.Gehnen@atrie.de> {
        support for "Inactive Subset" of ISO CLNP
+       Decoding of OSI COTP TSAPs as text when they're plain text
+       Sinec H1 protocol support
 }
 
 Craig Newell <craign@cheque.uq.edu.au> {
index 1e683071af4d3d2514cb7e9e5da302b1359ebc22..38764424a3c0d55d7728d9d61d7a37da6e2a4195 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile.am
 # Automake file for Ethereal
 #
-# $Id: Makefile.am,v 1.171 2000/03/01 07:48:03 guy Exp $
+# $Id: Makefile.am,v 1.172 2000/03/02 07:27:04 guy Exp $
 #
 # Ethereal - Network traffic analyzer
 # By Gerald Combs <gerald@zing.org>
@@ -76,6 +76,7 @@ DISSECTOR_SOURCES = \
        packet-giop.h  \
        packet-gre.c   \
        packet-gre.h   \
+       packet-h1.c    \
        packet-hsrp.c  \
        packet-hsrp.h  \
        packet-http.c  \
index 4f735d9583e3ab2caa95692183696293041e0397..d98b8c05ebd8e9962415cc513c33adf9cd0ebd74 100644 (file)
@@ -38,6 +38,7 @@ DISSECTOR_OBJECTS = \
        packet-ftp.obj   \
        packet-giop.obj  \
        packet-gre.obj   \
+       packet-h1.obj    \
        packet-hsrp.obj  \
        packet-http.obj  \
        packet-icmpv6.obj\
diff --git a/packet-h1.c b/packet-h1.c
new file mode 100644 (file)
index 0000000..2b0d161
--- /dev/null
@@ -0,0 +1,310 @@
+/* packet-h1.c
+ * Routines for Sinec H1 packet disassembly
+ * Gerrit Gehnen <G.Gehnen@atrie.de>
+ *
+ * $Id: packet-h1.c,v 1.1 2000/03/02 07:27:05 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include "packet.h"
+#include "globals.h"
+#include "packet-h1.h"
+
+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_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;
+
+#define EMPTY_BLOCK    0xFF
+#define OPCODE_BLOCK   0x01
+#define REQUEST_BLOCK  0x03
+#define RESPONSE_BLOCK 0x0F
+
+static const value_string opcode_vals[] = {
+  {3, "Write Request"},
+  {4, "Write Response"},
+  {5, "Read Request"},
+  {6, "Read Response"},
+  {0, NULL}
+};
+
+static const value_string org_vals[] = {
+  {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}
+};
+
+static const value_string returncode_vals[] = {
+  {0x00, "No error"},
+  {0x02, "Requested block does not exist"},
+  {0x03, "Requested block too small"},
+  {0xFF, "Error, reason unkown"},
+  {0, NULL}
+};
+
+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;
+
+
+void
+dissect_h1 (const u_char * pd, int offset, frame_data * fd, proto_tree * tree)
+{
+  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;
+
+  if (pd[offset] == 'S' && pd[offset + 1] == '5')
+    {
+      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
+
+      dissect_data (pd, offset + pd[offset + 2], fd, tree);
+    }
+  else
+    {
+      dissect_data (pd, offset, fd, tree);
+    }
+}
+
+
+void
+proto_register_h1 (void)
+{
+  static hf_register_info hf[] = {
+    {&hf_h1_header,
+     {"H1-Header", "h1.header", FT_UINT16, BASE_HEX, NULL, 0x0,
+      ""}},
+    {&hf_h1_len,
+     {"Length indicator", "h1.len", FT_UINT16, BASE_DEC, NULL, 0x0,
+      ""}},
+    {&hf_h1_opfield,
+     {"Operation identifier", "h1.opfield", FT_UINT8, BASE_HEX, NULL, 0x0,
+      ""}},
+    {&hf_h1_oplen,
+     {"Operation length", "h1.oplen", FT_UINT8, BASE_HEX, NULL, 0x0, ""}},
+    {&hf_h1_opcode,
+     {"Opcode", "h1.opcode", FT_UINT8, BASE_HEX, VALS (opcode_vals), 0x0,
+      ""}},
+    {&hf_h1_requestblock,
+     {"Request identifier", "h1.request", FT_UINT8, BASE_HEX, NULL, 0x0,
+      ""}},
+    {&hf_h1_requestlen,
+     {"Request length", "h1.reqlen", FT_UINT8, BASE_HEX, NULL, 0x0,
+      ""}},
+    {&hf_h1_org,
+     {"Memory type", "h1.org", FT_UINT8, BASE_HEX, VALS (org_vals), 0x0,
+      ""}},
+    {&hf_h1_dbnr,
+     {"Memory block number", "h1.dbnr", FT_UINT8, BASE_DEC, NULL, 0x0, ""}},
+    {&hf_h1_dwnr,
+     {"Address within memory block", "h1.dwnr", FT_UINT16, BASE_DEC, NULL, 0x0,
+      ""}},
+    {&hf_h1_dlen,
+     {"Length in words", "h1.dlen", FT_INT16, BASE_DEC, NULL, 0x0, ""}},
+    {&hf_h1_response,
+     {"Response identifier", "h1.response", FT_UINT8, BASE_DEC, NULL, 0x0, ""}},
+    {&hf_h1_response_len,
+     {"Response length", "h1.reslen", FT_UINT8, BASE_DEC, NULL, 0x0,
+      ""}},
+    {&hf_h1_response_value,
+     {"Response value", "h1.resvalue", FT_UINT8, BASE_DEC,
+      VALS (returncode_vals), 0x0, ""}},
+    {&hf_h1_empty,
+     {"Emtpy field", "h1.empty", FT_UINT8, BASE_HEX, NULL, 0x0,
+      ""}},
+    {&hf_h1_empty_len,
+     {"Empty field length", "h1.empty_len", FT_UINT8, BASE_DEC, NULL, 0x0,
+      ""}}
+  };
+
+  static gint *ett[] = {
+    &ett_h1,
+    &ett_opcode,
+    &ett_response,
+    &ett_org,
+    &ett_empty
+  };
+
+  proto_h1 = proto_register_protocol ("Sinec H1 Protocol", "h1");
+  proto_register_field_array (proto_h1, hf, array_length (hf));
+  proto_register_subtree_array (ett, array_length (ett));
+}
diff --git a/packet-h1.h b/packet-h1.h
new file mode 100644 (file)
index 0000000..11a49db
--- /dev/null
@@ -0,0 +1,27 @@
+/* packet-h1.h
+ * Declarations of outines for Sinec H1 packet disassembly
+ * Gerrit Gehnen <G.Gehnen@atrie.de>
+ *
+ * $Id: packet-h1.h,v 1.1 2000/03/02 07:27:05 guy Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@zing.org>
+ * 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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+void dissect_h1(const u_char *, int, frame_data *, proto_tree *);
index 365781b85b1c79160ac57995b4b5a4c5ec34fce5..a831b5b00ed0c54ebdfd5d576bad3acd85cc89e8 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-osi.c
  * Routines for ISO/OSI network and transport protocol packet disassembly
  *
- * $Id: packet-osi.c,v 1.21 2000/02/15 21:02:46 gram Exp $
+ * $Id: packet-osi.c,v 1.22 2000/03/02 07:27:05 guy Exp $
  * Laurent Deniel <deniel@worldnet.fr>
  *
  * Ethereal - Network traffic analyzer
 
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 #include <glib.h>
 #include "packet.h"
 #include "packet-isis.h"
+#include "packet-h1.h"
 #include "nlpid.h"
 
 /* protocols and fields */
@@ -284,7 +286,8 @@ static int osi_decode_DR(const u_char *pd, int offset,
 } /* osi_decode_DR */
 
 static int osi_decode_DT(const u_char *pd, int offset, 
-                        frame_data *fd, proto_tree *tree) 
+                        frame_data *fd, proto_tree *tree,
+                        gboolean uses_inactive_subset)
 {
   proto_tree *cotp_tree;
   proto_item *ti;
@@ -418,7 +421,12 @@ static int osi_decode_DT(const u_char *pd, int offset,
   } /* tree */
 
   offset += li + 1;
-  dissect_data(pd, offset, fd, tree);
+  if (uses_inactive_subset){
+       dissect_h1(pd, offset, fd, tree);
+       }
+  else {
+       dissect_data(pd, offset, fd, tree);
+       }
 
   return 0;
 
@@ -609,6 +617,8 @@ static gchar *print_tsap(const u_char *tsap, int length)
   static gchar  str[3][MAX_TSAP_LEN * 2 + 1];
   static gchar *cur;
   gchar tmp[3];
+  gboolean allprintable;
+  int i;
 
   if (cur == &str[0][0]) {
     cur = &str[1][0];
@@ -618,14 +628,26 @@ static gchar *print_tsap(const u_char *tsap, int length)
     cur = &str[0][0];
   }
 
-  /* to do: test if all bytes are printable */
 
   cur[0] = '\0';
   if (length <= 0 || length > MAX_TSAP_LEN) 
     sprintf(cur, "<unsupported TSAP length>");
   else {    
+    allprintable=TRUE;
+    for (i=0;i<length;i++) {
+       if (!isprint(tsap[i])) { /* if any byte is not printable */
+         allprintable=FALSE;    /* switch to hexdump */
+         break;
+         }      
+       }
+    if (!allprintable){
+      strcat(cur,"0x");
+      }
     while (length != 0) {
-      sprintf(tmp, "%02x", *tsap ++);
+      if (allprintable)
+       sprintf(tmp, "%c", *tsap ++);
+      else
+       sprintf(tmp, "%02x", *tsap ++);
       strcat(cur, tmp);
       length --;
     }
@@ -707,7 +729,7 @@ static int osi_decode_CC(const u_char *pd, int offset,
                              "Parameter length: 0x%02x", length);
          proto_tree_add_text(cotp_tree, 
                              offset +  P_VAR_PART_CC + i + 2, length, 
-                             "Calling TSAP: 0x%s", 
+                             "Calling TSAP: %s", 
                              print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
                                         length));
          i += length + 2;
@@ -722,7 +744,7 @@ static int osi_decode_CC(const u_char *pd, int offset,
                              "Parameter length: 0x%02x", length);
          proto_tree_add_text(cotp_tree, 
                              offset +  P_VAR_PART_CC + i + 2, length, 
-                             "Called TSAP: 0x%s", 
+                             "Called TSAP: %s", 
                              print_tsap(&pd[offset + P_VAR_PART_CC + i + 2],
                                         length));
          i += length + 2;
@@ -867,10 +889,24 @@ static int osi_decode_CC(const u_char *pd, int offset,
                              "Priority: %d", s);
          i += length + 2;
          break;
+       
+       case VP_VERSION_NR  :
+         length = pd[offset + P_VAR_PART_CC + i + 1];
+         c1 = pd[offset + P_VAR_PART_CC + i + 2];
+         proto_tree_add_text(cotp_tree, 
+                             offset +  P_VAR_PART_CC + i, 1, 
+                             "Parameter code: 0x%02x (version)", code);
+         proto_tree_add_text(cotp_tree, 
+                             offset +  P_VAR_PART_CC + i + 1, 1, 
+                             "Parameter length: 0x%02x", length);
+         proto_tree_add_text(cotp_tree, 
+                             offset +  P_VAR_PART_CC + i + 2, length,
+                             "Version: %d", c1);
+         i += length + 2;
+         break;
 
        case VP_REASSIGNMENT:     /* todo */
        case VP_RES_ERROR   :
-       case VP_VERSION_NR  :
        case VP_PROTECTION  :
        case VP_PROTO_CLASS :
        default             :     /* no decoding */
@@ -1348,10 +1384,9 @@ static int osi_decode_ER(const u_char *pd, int offset,
 
 } /* osi_decode_ER */
 
-void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
-                 proto_tree *tree) 
+static void dissect_cotp_internal(const u_char *pd, int offset, frame_data *fd,
+                 proto_tree *tree, gboolean uses_inactive_subset
 {
-
   int status = -1;
 
   if (((li = pd[offset + P_LI]) == 0) ||
@@ -1373,7 +1408,7 @@ void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
       status = osi_decode_DR(pd, offset, fd, tree);
       break;
     case DT_TPDU :
-      status = osi_decode_DT(pd, offset, fd, tree);
+      status = osi_decode_DT(pd, offset, fd, tree, uses_inactive_subset);
       break;
     case ED_TPDU :
       status = osi_decode_ED(pd, offset, fd, tree);
@@ -1400,7 +1435,13 @@ void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
   if (status == -1) /* incorrect TPDU */
     dissect_data(pd, offset, fd, tree);
 
-} /* dissect_cotp */
+} /* dissect_cotp_internal */
+
+void dissect_cotp(const u_char *pd, int offset, frame_data *fd,
+                 proto_tree *tree) 
+{
+  dissect_cotp_internal(pd, offset, fd, tree, FALSE);
+}
 
 
 /*
@@ -1462,7 +1503,7 @@ void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
                                 clnp.cnf_proto_id,
                                 "Inactive subset");
     } 
-    dissect_cotp(pd, offset+1, fd, tree);
+    dissect_cotp_internal(pd, offset+1, fd, tree, TRUE);
     return;
   } 
  
@@ -1584,7 +1625,7 @@ void dissect_clnp(const u_char *pd, int offset, frame_data *fd,
   /* continue with COTP if any */
 
   if (nsel == NSEL_TP)         /* just guessing here - valid for DECNet-OSI */
-    dissect_cotp(pd, offset, fd, tree);
+    dissect_cotp_internal(pd, offset, fd, tree, FALSE);
   else
     dissect_data(pd, offset, fd, tree);