From Gerhard Gappmeier via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5410 :
authorJeff Morriss <jeff.morriss@ulticom.com>
Tue, 16 Nov 2010 17:00:50 +0000 (17:00 -0000)
committerJeff Morriss <jeff.morriss@ulticom.com>
Tue, 16 Nov 2010 17:00:50 +0000 (17:00 -0000)
This patch adds support for displaying OPC UA ExtensionObjects.

An ExtensionObject is a mechanism to transport user defined structures as
serialized blobs. Some types of ExtensionObjects are already defined by the OPC
Foundation's OPC UA Specifications.
These types can be implemented by this dissector, because they are well-known.

Real user-defined or vendor-defined types are unlikely to be implemented by a
passive dissector, because this would require browsing of the UA server's
address space to retrieve the type information.

Currently only the following types are supported:

 * DataChangeNotification
 * EventNotification

Others OPC defined types will follow.

From me: fix warnings: "format not a string literal and no format arguments"

svn path=/trunk/; revision=34906

AUTHORS
plugins/opcua/Makefile.common
plugins/opcua/opcua_extensionobjectids.h [new file with mode: 0644]
plugins/opcua/opcua_extensionobjecttable.c [new file with mode: 0644]
plugins/opcua/opcua_identifiers.h
plugins/opcua/opcua_simpletypes.c
plugins/opcua/opcua_simpletypes.h

diff --git a/AUTHORS b/AUTHORS
index 8d4d256aba930a7dd86044c7e0e10b5d6fa564f1..324a68c8e56a6a2d8f720907e5cab7a8cb561a84 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3183,6 +3183,10 @@ Thomas Boehne            <TBoehne [AT] ADwin.de> {
        ADwin and ADwin-config protocol dissectors
 }
 
+Gerhard Gappmeier      <gerhard.gappmeier [AT] ascolab.com> {
+       OPCUA dissector plugin
+}
+
 and by:
 
 Pavel Roskin            <proski [AT] gnu.org>
index 52d3ecdeee7b0b74027935cd3650a57a656be59d..5d6aa9cf794c673cfa05887c5720b517f3b51f0c 100644 (file)
@@ -42,6 +42,7 @@ DISSECTOR_INCLUDES =  \
        opcua_application_layer.h \
        opcua_security_layer.h \
        opcua_transport_layer.h \
+       opcua_extensionobjectids.h \
        opcua_serviceids.h
 
 # other sources
@@ -54,4 +55,5 @@ DISSECTOR_SUPPORT_SRC = \
        opcua_enumparser.c \
        opcua_simpletypes.c \
        opcua_servicetable.c \
+       opcua_extensionobjecttable.c \
        opcua_hfindeces.c
diff --git a/plugins/opcua/opcua_extensionobjectids.h b/plugins/opcua/opcua_extensionobjectids.h
new file mode 100644 (file)
index 0000000..b0fd5af
--- /dev/null
@@ -0,0 +1,22 @@
+/******************************************************************************
+** $Id$
+**
+** Copyright (C) 2006-2009 ascolab GmbH. All Rights Reserved.
+** Web: http://www.ascolab.com
+**
+** 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 file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** Project: OpcUa Wireshark Plugin
+**
+** Description: OpcUa Extension Object IDs
+**
+******************************************************************************/
+
+#define OpcUaId_DataChangeNotification_Encoding_DefaultBinary 811
+#define OpcUaId_EventNotificationList_Encoding_DefaultBinary 916
diff --git a/plugins/opcua/opcua_extensionobjecttable.c b/plugins/opcua/opcua_extensionobjecttable.c
new file mode 100644 (file)
index 0000000..0d0adeb
--- /dev/null
@@ -0,0 +1,86 @@
+/******************************************************************************
+** $Id$
+**
+** Copyright (C) 2006-2009 ascolab GmbH. All Rights Reserved.
+** Web: http://www.ascolab.com
+** 
+** 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 file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+** 
+** Project: OpcUa Wireshark Plugin
+**
+** Description: Service table and service dispatcher.
+**
+** This file was autogenerated on 31.03.2009.
+** DON'T MODIFY THIS FILE!
+** XXX - well, except that you may have to.  See the README.
+**
+******************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include "opcua_simpletypes.h"
+#include "opcua_complextypeparser.h"
+#include "opcua_extensionobjectids.h"
+#include "opcua_hfindeces.h"
+
+ExtensionObjectParserEntry g_arExtensionObjectParserTable[] = {
+    { OpcUaId_DataChangeNotification_Encoding_DefaultBinary, parseDataChangeNotification, "DataChangeNotification" },
+    { OpcUaId_EventNotificationList_Encoding_DefaultBinary, parseEventNotificationList, "EventNotificationList" },
+};
+const int g_NumTypes = sizeof(g_arExtensionObjectParserTable) / sizeof(ExtensionObjectParserEntry);
+
+/** Dispatch all extension objects to a special parser function. */
+void dispatchExtensionObjectType(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int TypeId)
+{
+    gint    iOffset = *pOffset;
+    int     index = 0;
+    int     bFound = 0;
+    gint32  iLen = 0;
+
+    /* get the length of the body */
+    iLen = tvb_get_letohl(tvb, iOffset);
+    iOffset += 4;
+
+    while (index < g_NumTypes)
+    {
+        if (g_arExtensionObjectParserTable[index].iRequestId == TypeId)
+        {
+            bFound = 1;
+            (*g_arExtensionObjectParserTable[index].pParser)(tree, tvb, &iOffset, g_arExtensionObjectParserTable[index].typeName);
+            break;
+        }
+        index++;
+    }
+
+    /* display contained object as ByteString if unknown type */
+    if (bFound == 0)
+    {
+        if (iLen == -1)
+        {
+            proto_tree_add_text(tree, tvb, iOffset, 0, "[OpcUa Null ByteString]");
+        }
+        else if (iLen >= 0)
+        {
+            proto_tree_add_item(tree, hf_opcua_ByteString, tvb, iOffset, iLen, TRUE);
+            iOffset += iLen; /* eat the whole bytestring */
+        }
+        else
+        {
+            char *szValue = ep_strdup_printf("[Invalid ByteString] Invalid length: %d", iLen);
+            proto_tree_add_text(tree, tvb, iOffset, 0, "%s", szValue);
+        }
+    }
+
+    *pOffset = iOffset;
+}
+
index e817612b7c725447e51bf33bd4d0bf4c6b97fc1f..7843850bb5bb8823017d8afcccded5a8c389cb97 100644 (file)
@@ -39,3 +39,10 @@ typedef struct _ParserEntry
        int iRequestId;
        fctServiceParser pParser;
 } ParserEntry;
+
+typedef struct _ExtensionObjectParserEntry
+{
+       int iRequestId;
+       fctComplexTypeParser pParser;
+       gchar *typeName;
+} ExtensionObjectParserEntry;
index 6297d1890beac41a506286af4939ba762b268cd5..31a17876cb90fa17af8db210388c8a2f237b6a6a 100644 (file)
@@ -31,6 +31,7 @@
 #include <epan/dissectors/packet-windows-common.h>
 #include "opcua_simpletypes.h"
 #include "opcua_hfindeces.h"
+#include "opcua_extensionobjectids.h"
 #include <epan/emem.h>
 
 #define DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG           0x01
@@ -55,6 +56,8 @@
 /* Chosen arbitrarily */
 #define MAX_ARRAY_LEN 10000
 
+void dispatchExtensionObjectType(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int TypeId);
+
 static int hf_opcua_diag_mask_symbolicflag = -1;
 static int hf_opcua_diag_mask_namespaceflag = -1;
 static int hf_opcua_diag_mask_localizedtextflag = -1;
@@ -824,6 +827,7 @@ void parseExtensionObject(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *
 {
     gint    iOffset = *pOffset;
     guint8  EncodingMask;
+    guint32 TypeId;
     proto_tree *extobj_tree;
     proto_tree *mask_tree;
     proto_item *ti;
@@ -833,6 +837,7 @@ void parseExtensionObject(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *
     extobj_tree = proto_item_add_subtree(ti, ett_opcua_extensionobject);
 
     /* add nodeid subtree */
+    TypeId = getExtensionObjectType(tvb, &iOffset);
     parseExpandedNodeId(extobj_tree, tvb, &iOffset, "TypeId");
 
     /* parse encoding mask */
@@ -845,7 +850,7 @@ void parseExtensionObject(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *
 
     if (EncodingMask & EXTOBJ_ENCODINGMASK_BINBODY_FLAG) /* has binary body ? */
     {
-        parseByteString(extobj_tree, tvb, &iOffset, hf_opcua_ByteString);
+        dispatchExtensionObjectType(extobj_tree, tvb, &iOffset, TypeId);
     }
 
     *pOffset = iOffset;
@@ -908,3 +913,37 @@ void parseExpandedNodeId(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *s
 
     *pOffset = iOffset;
 }
+
+guint32 getExtensionObjectType(tvbuff_t *tvb, gint *pOffset)
+{
+    gint    iOffset = *pOffset;
+    guint8  EncodingMask;
+    guint32 Numeric = 0;
+
+    EncodingMask = tvb_get_guint8(tvb, iOffset);
+    iOffset++;
+
+    switch(EncodingMask)
+    {
+    case 0x00: /* two byte node id */
+        Numeric = tvb_get_guint8(tvb, iOffset);
+        iOffset+=1;
+        break;
+    case 0x01: /* four byte node id */
+        iOffset+=1;
+        Numeric = tvb_get_letohs(tvb, iOffset);
+        break;
+    case 0x02: /* numeric, that does not fit into four bytes */
+        iOffset+=4;
+        Numeric = tvb_get_letohl(tvb, iOffset);
+        break;
+    case 0x03: /* string */
+    case 0x04: /* uri */
+    case 0x05: /* guid */
+    case 0x06: /* byte string */
+        /* NOT USED */
+        break;
+    };
+
+    return Numeric;
+}
index f1174b1d5e1f20c2f21046d977385cdd1a26f4e0..4dfd7932270d681d63a456322bbd55e01996ba2d 100644 (file)
@@ -54,3 +54,4 @@ void parseArraySimple(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int hfInde
 void parseArrayEnum(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, fctEnumParser pParserFunction);
 void parseArrayComplex(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *szFieldName, fctComplexTypeParser pParserFunction);
 void registerSimpleTypes(int proto);
+guint32 getExtensionObjectType(tvbuff_t *tvb, gint *pOffset);