From c45bf26f4cc18b0b377f6b546cf15af62bcaf00f Mon Sep 17 00:00:00 2001 From: morriss Date: Tue, 16 Nov 2010 17:00:50 +0000 Subject: [PATCH] From Gerhard Gappmeier via https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5410 : 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" git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@34906 f5534014-38df-0310-8fa8-9805f1628bb7 --- AUTHORS | 4 + plugins/opcua/Makefile.common | 2 + plugins/opcua/opcua_extensionobjectids.h | 22 ++++++ plugins/opcua/opcua_extensionobjecttable.c | 86 ++++++++++++++++++++++ plugins/opcua/opcua_identifiers.h | 7 ++ plugins/opcua/opcua_simpletypes.c | 41 ++++++++++- plugins/opcua/opcua_simpletypes.h | 1 + 7 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 plugins/opcua/opcua_extensionobjectids.h create mode 100644 plugins/opcua/opcua_extensionobjecttable.c diff --git a/AUTHORS b/AUTHORS index 8d4d256aba..324a68c8e5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3183,6 +3183,10 @@ Thomas Boehne { ADwin and ADwin-config protocol dissectors } +Gerhard Gappmeier { + OPCUA dissector plugin +} + and by: Pavel Roskin diff --git a/plugins/opcua/Makefile.common b/plugins/opcua/Makefile.common index 52d3ecdeee..5d6aa9cf79 100644 --- a/plugins/opcua/Makefile.common +++ b/plugins/opcua/Makefile.common @@ -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 index 0000000000..b0fd5aff68 --- /dev/null +++ b/plugins/opcua/opcua_extensionobjectids.h @@ -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 index 0000000000..0d0adebc04 --- /dev/null +++ b/plugins/opcua/opcua_extensionobjecttable.c @@ -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 +#include +#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; +} + diff --git a/plugins/opcua/opcua_identifiers.h b/plugins/opcua/opcua_identifiers.h index e817612b7c..7843850bb5 100644 --- a/plugins/opcua/opcua_identifiers.h +++ b/plugins/opcua/opcua_identifiers.h @@ -39,3 +39,10 @@ typedef struct _ParserEntry int iRequestId; fctServiceParser pParser; } ParserEntry; + +typedef struct _ExtensionObjectParserEntry +{ + int iRequestId; + fctComplexTypeParser pParser; + gchar *typeName; +} ExtensionObjectParserEntry; diff --git a/plugins/opcua/opcua_simpletypes.c b/plugins/opcua/opcua_simpletypes.c index 6297d1890b..31a17876cb 100644 --- a/plugins/opcua/opcua_simpletypes.c +++ b/plugins/opcua/opcua_simpletypes.c @@ -31,6 +31,7 @@ #include #include "opcua_simpletypes.h" #include "opcua_hfindeces.h" +#include "opcua_extensionobjectids.h" #include #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; +} diff --git a/plugins/opcua/opcua_simpletypes.h b/plugins/opcua/opcua_simpletypes.h index f1174b1d5e..4dfd793227 100644 --- a/plugins/opcua/opcua_simpletypes.h +++ b/plugins/opcua/opcua_simpletypes.h @@ -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); -- 2.34.1