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
This commit is contained in:
Jeff Morriss 2010-11-16 17:00:50 +00:00
parent b7b98d4315
commit 3c7ac06886
7 changed files with 162 additions and 1 deletions

View File

@ -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>

View 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

View File

@ -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

View File

@ -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;
}

View File

@ -39,3 +39,10 @@ typedef struct _ParserEntry
int iRequestId;
fctServiceParser pParser;
} ParserEntry;
typedef struct _ExtensionObjectParserEntry
{
int iRequestId;
fctComplexTypeParser pParser;
gchar *typeName;
} ExtensionObjectParserEntry;

View 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;
}

View 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);