2007-05-15 09:05:53 +00:00
/******************************************************************************
* * Copyright ( C ) 2006 - 2007 ascolab GmbH . All Rights Reserved .
* * Web : http : //www.ascolab.com
2009-10-20 14:03:00 +00:00
* *
2007-05-15 09:05:53 +00:00
* * 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 .
2009-10-20 14:03:00 +00:00
* *
2007-05-15 09:05:53 +00:00
* * This file is provided AS IS with NO WARRANTY OF ANY KIND , INCLUDING THE
* * WARRANTY OF DESIGN , MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .
2009-10-20 14:03:00 +00:00
* *
2007-05-15 09:05:53 +00:00
* * Project : OpcUa Wireshark Plugin
* *
* * Description : Implementation of OpcUa built - in type parsers .
* * This contains all the simple types and some complex types .
* *
* * Author : Gerhard Gappmeier < gerhard . gappmeier @ ascolab . com >
* * Last change by : $ Author : gergap $
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-09-20 01:29:52 +00:00
# include "config.h"
2007-05-15 09:05:53 +00:00
2007-05-21 18:08:47 +00:00
# include <glib.h>
2007-05-15 09:05:53 +00:00
# include <epan/packet.h>
# include <epan/dissectors/packet-windows-common.h>
# include "opcua_simpletypes.h"
# include "opcua_hfindeces.h"
2010-11-16 17:00:50 +00:00
# include "opcua_extensionobjectids.h"
2014-06-10 11:36:06 +00:00
# include "opcua_statuscode.h"
2013-09-17 21:34:05 +00:00
# include <epan/wmem/wmem.h>
2007-05-15 09:05:53 +00:00
# define DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG 0x01
# define DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG 0x02
# define DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG 0x04
# define DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO_FLAG 0x08
# define DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE_FLAG 0x10
# define DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO_FLAG 0x20
# define LOCALIZEDTEXT_ENCODINGBYTE_LOCALE 0x01
# define LOCALIZEDTEXT_ENCODINGBYTE_TEXT 0x02
2014-06-10 09:25:30 +00:00
# define NODEID_NAMESPACEURIFLAG 0x80
2009-04-06 18:30:04 +00:00
# define NODEID_SERVERINDEXFLAG 0x40
2007-05-15 09:05:53 +00:00
# define DATAVALUE_ENCODINGBYTE_VALUE 0x01
# define DATAVALUE_ENCODINGBYTE_STATUSCODE 0x02
# define DATAVALUE_ENCODINGBYTE_SOURCETIMESTAMP 0x04
# define DATAVALUE_ENCODINGBYTE_SERVERTIMESTAMP 0x08
2009-04-06 18:30:04 +00:00
# define DATAVALUE_ENCODINGBYTE_SOURCEPICOSECONDS 0x10
# define DATAVALUE_ENCODINGBYTE_SERVERPICOSECONDS 0x20
2007-05-15 09:05:53 +00:00
# define EXTOBJ_ENCODINGMASK_BINBODY_FLAG 0x01
# define EXTOBJ_ENCODINGMASK_XMLBODY_FLAG 0x02
2014-06-12 08:11:06 +00:00
# define STATUSCODE_STRUCTURECHANGED 0x8000
# define STATUSCODE_SEMANTICSCHANGED 0x4000
# define STATUSCODE_INFOTYPE_DATAVALUE 0x00000400
# define STATUSCODE_INFOBIT_OVERFLOW 0x0080
# define STATUSCODE_INFOBIT_HISTORIAN_PARTIAL 0x0004
# define STATUSCODE_INFOBIT_HISTORIAN_EXTRADATA 0x0008
# define STATUSCODE_INFOBIT_HISTORIAN_MULTIVALUE 0x0010
2007-05-15 09:05:53 +00:00
2009-09-09 00:18:15 +00:00
/* Chosen arbitrarily */
# define MAX_ARRAY_LEN 10000
2007-05-15 09:05:53 +00:00
static int hf_opcua_diag_mask_symbolicflag = - 1 ;
static int hf_opcua_diag_mask_namespaceflag = - 1 ;
static int hf_opcua_diag_mask_localizedtextflag = - 1 ;
static int hf_opcua_diag_mask_additionalinfoflag = - 1 ;
static int hf_opcua_diag_mask_innerstatuscodeflag = - 1 ;
static int hf_opcua_diag_mask_innerdiaginfoflag = - 1 ;
static int hf_opcua_loctext_mask_localeflag = - 1 ;
static int hf_opcua_loctext_mask_textflag = - 1 ;
static int hf_opcua_datavalue_mask_valueflag = - 1 ;
static int hf_opcua_datavalue_mask_statuscodeflag = - 1 ;
static int hf_opcua_datavalue_mask_sourcetimestampflag = - 1 ;
static int hf_opcua_datavalue_mask_servertimestampflag = - 1 ;
2009-04-06 18:30:04 +00:00
static int hf_opcua_datavalue_mask_sourcepicoseconds = - 1 ;
static int hf_opcua_datavalue_mask_serverpicoseconds = - 1 ;
2007-05-15 09:05:53 +00:00
static int hf_opcua_nodeid_encodingmask = - 1 ;
2014-06-10 09:46:05 +00:00
static int hf_opcua_expandednodeid_mask_namespaceuri = - 1 ;
static int hf_opcua_expandednodeid_mask_serverindex = - 1 ;
2007-05-15 09:05:53 +00:00
static int hf_opcua_variant_encodingmask = - 1 ;
2014-06-10 09:25:30 +00:00
static int hf_opcua_nodeid_nsindex = - 1 ;
2007-05-15 09:05:53 +00:00
static int hf_opcua_nodeid_numeric = - 1 ;
2014-06-10 09:47:07 +00:00
static int hf_opcua_nodeid_string = - 1 ;
static int hf_opcua_nodeid_guid = - 1 ;
static int hf_opcua_nodeid_bytestring = - 1 ;
2009-04-06 18:30:04 +00:00
static int hf_opcua_localizedtext_locale = - 1 ;
static int hf_opcua_localizedtext_text = - 1 ;
static int hf_opcua_qualifiedname_id = - 1 ;
static int hf_opcua_qualifiedname_name = - 1 ;
2007-05-15 09:05:53 +00:00
static int hf_opcua_SourceTimestamp = - 1 ;
2009-04-06 18:30:04 +00:00
static int hf_opcua_SourcePicoseconds = - 1 ;
2007-05-15 09:05:53 +00:00
static int hf_opcua_ServerTimestamp = - 1 ;
2009-04-06 18:30:04 +00:00
static int hf_opcua_ServerPicoseconds = - 1 ;
2007-05-15 09:05:53 +00:00
static int hf_opcua_diag_symbolicid = - 1 ;
static int hf_opcua_diag_namespace = - 1 ;
static int hf_opcua_diag_localizedtext = - 1 ;
static int hf_opcua_diag_additionalinfo = - 1 ;
static int hf_opcua_diag_innerstatuscode = - 1 ;
static int hf_opcua_extobj_mask_binbodyflag = - 1 ;
static int hf_opcua_extobj_mask_xmlbodyflag = - 1 ;
2009-04-06 18:30:04 +00:00
static int hf_opcua_ArraySize = - 1 ;
static int hf_opcua_ServerIndex = - 1 ;
2014-06-12 08:11:06 +00:00
static int hf_opcua_status_StructureChanged = - 1 ;
static int hf_opcua_status_SemanticsChanged = - 1 ;
static int hf_opcua_status_InfoBit_Limit_Overflow = - 1 ;
static int hf_opcua_status_InfoBit_Historian_Partial = - 1 ;
static int hf_opcua_status_InfoBit_Historian_ExtraData = - 1 ;
static int hf_opcua_status_InfoBit_Historian_MultiValue = - 1 ;
static int hf_opcua_status_InfoType = - 1 ;
static int hf_opcua_status_Limit = - 1 ;
static int hf_opcua_status_Historian = - 1 ;
2007-05-15 09:05:53 +00:00
/** NodeId encoding mask table */
static const value_string g_nodeidmasks [ ] = {
2014-06-10 09:46:05 +00:00
{ 0x00 , " Two byte encoded Numeric " } ,
{ 0x01 , " Four byte encoded Numeric " } ,
{ 0x02 , " Numeric of arbitrary length " } ,
{ 0x03 , " String " } ,
{ 0x04 , " GUID " } ,
{ 0x05 , " Opaque " } ,
2007-05-15 09:05:53 +00:00
{ 0 , NULL }
} ;
2014-06-12 08:11:06 +00:00
/** StatusCode info types */
static const value_string g_infotype [ ] = {
{ 0x00 , " Not used " } ,
{ 0x01 , " DataValue " } ,
{ 0x02 , " Reserved " } ,
{ 0x03 , " Reserved " } ,
{ 0 , NULL }
} ;
/** StatusCode Limit types */
static const value_string g_limit [ ] = {
{ 0x00 , " None " } ,
{ 0x01 , " Low " } ,
{ 0x02 , " High " } ,
{ 0x03 , " Constant " } ,
{ 0 , NULL }
} ;
/** StatusCode Historian types */
static const value_string g_historian [ ] = {
{ 0x00 , " Raw " } ,
{ 0x01 , " Calculated " } ,
{ 0x02 , " Interpolated " } ,
{ 0x03 , " Reserved " } ,
{ 0 , NULL }
} ;
2007-05-15 09:05:53 +00:00
/** UA Variant Type enum */
typedef enum _OpcUa_BuiltInType
{
OpcUaType_Null = 0 ,
OpcUaType_Boolean = 1 ,
OpcUaType_SByte = 2 ,
OpcUaType_Byte = 3 ,
OpcUaType_Int16 = 4 ,
OpcUaType_UInt16 = 5 ,
OpcUaType_Int32 = 6 ,
OpcUaType_UInt32 = 7 ,
OpcUaType_Int64 = 8 ,
OpcUaType_UInt64 = 9 ,
OpcUaType_Float = 10 ,
OpcUaType_Double = 11 ,
OpcUaType_String = 12 ,
OpcUaType_DateTime = 13 ,
OpcUaType_Guid = 14 ,
OpcUaType_ByteString = 15 ,
OpcUaType_XmlElement = 16 ,
OpcUaType_NodeId = 17 ,
OpcUaType_ExpandedNodeId = 18 ,
OpcUaType_StatusCode = 19 ,
2009-04-06 18:30:04 +00:00
OpcUaType_QualifiedName = 20 ,
OpcUaType_LocalizedText = 21 ,
OpcUaType_ExtensionObject = 22 ,
OpcUaType_DataValue = 23 ,
OpcUaType_Variant = 24 ,
OpcUaType_DiagnosticInfo = 25
2007-05-15 09:05:53 +00:00
}
OpcUa_BuiltInType ;
/** Variant encoding mask table */
static const value_string g_VariantTypes [ ] = {
{ 0 , " Null " } ,
{ 1 , " Boolean " } ,
{ 2 , " SByte " } ,
{ 3 , " Byte " } ,
{ 4 , " Int16 " } ,
{ 5 , " UInt16 " } ,
{ 6 , " Int32 " } ,
{ 7 , " UInt32 " } ,
{ 8 , " Int64 " } ,
{ 9 , " UInt64 " } ,
{ 10 , " Float " } ,
{ 11 , " Double " } ,
{ 12 , " String " } ,
{ 13 , " DateTime " } ,
{ 14 , " Guid " } ,
{ 15 , " ByteString " } ,
{ 16 , " XmlElement " } ,
{ 17 , " NodeId " } ,
{ 18 , " ExpandedNodeId " } ,
{ 19 , " StatusCode " } ,
2010-12-02 20:44:18 +00:00
{ 20 , " QualifiedName " } ,
{ 21 , " LocalizedText " } ,
{ 22 , " ExtensionObject " } ,
{ 23 , " DataValue " } ,
{ 24 , " Variant " } ,
{ 25 , " DiagnosticInfo " } ,
2007-05-15 09:05:53 +00:00
{ 0x80 , " Array of Null " } ,
{ 0x80 + 1 , " Array of Boolean " } ,
{ 0x80 + 2 , " Array of SByte " } ,
{ 0x80 + 3 , " Array of Byte " } ,
{ 0x80 + 4 , " Array of Int16 " } ,
{ 0x80 + 5 , " Array of UInt16 " } ,
{ 0x80 + 6 , " Array of Int32 " } ,
{ 0x80 + 7 , " Array of UInt32 " } ,
{ 0x80 + 8 , " Array of Int64 " } ,
{ 0x80 + 9 , " Array of UInt64 " } ,
{ 0x80 + 10 , " Array of Float " } ,
{ 0x80 + 11 , " Array of Double " } ,
{ 0x80 + 12 , " Array of String " } ,
{ 0x80 + 13 , " Array of DateTime " } ,
{ 0x80 + 14 , " Array of Guid " } ,
{ 0x80 + 15 , " Array of ByteString " } ,
{ 0x80 + 16 , " Array of XmlElement " } ,
{ 0x80 + 17 , " Array of NodeId " } ,
{ 0x80 + 18 , " Array of ExpandedNodeId " } ,
{ 0x80 + 19 , " Array of StatusCode " } ,
2010-12-02 20:44:18 +00:00
{ 0x80 + 20 , " Array of QualifiedName " } ,
{ 0x80 + 21 , " Array of LocalizedText " } ,
{ 0x80 + 22 , " Array of ExtensionObject " } ,
{ 0x80 + 23 , " Array of DataValue " } ,
{ 0x80 + 24 , " Array of Variant " } ,
{ 0x80 + 25 , " Array of DiagnosticInfo " } ,
2013-02-15 15:24:39 +00:00
{ 0xC0 , " Matrix of Null " } ,
{ 0xC0 + 1 , " Matrix of Boolean " } ,
{ 0xC0 + 2 , " Matrix of SByte " } ,
{ 0xC0 + 3 , " Matrix of Byte " } ,
{ 0xC0 + 4 , " Matrix of Int16 " } ,
{ 0xC0 + 5 , " Matrix of UInt16 " } ,
{ 0xC0 + 6 , " Matrix of Int32 " } ,
{ 0xC0 + 7 , " Matrix of UInt32 " } ,
{ 0xC0 + 8 , " Matrix of Int64 " } ,
{ 0xC0 + 9 , " Matrix of UInt64 " } ,
{ 0xC0 + 10 , " Matrix of Float " } ,
{ 0xC0 + 11 , " Matrix of Double " } ,
{ 0xC0 + 12 , " Matrix of String " } ,
{ 0xC0 + 13 , " Matrix of DateTime " } ,
{ 0xC0 + 14 , " Matrix of Guid " } ,
{ 0xC0 + 15 , " Matrix of ByteString " } ,
{ 0xC0 + 16 , " Matrix of XmlElement " } ,
{ 0xC0 + 17 , " Matrix of NodeId " } ,
{ 0xC0 + 18 , " Matrix of ExpandedNodeId " } ,
{ 0xC0 + 19 , " Matrix of StatusCode " } ,
{ 0xC0 + 20 , " Matrix of QualifiedName " } ,
{ 0xC0 + 21 , " Matrix of LocalizedText " } ,
{ 0xC0 + 22 , " Matrix of ExtensionObject " } ,
{ 0xC0 + 23 , " Matrix of DataValue " } ,
{ 0xC0 + 24 , " Matrix of Variant " } ,
{ 0xC0 + 25 , " Matrix of DiagnosticInfo " } ,
2007-05-15 09:05:53 +00:00
{ 0 , NULL }
} ;
2009-04-06 18:30:04 +00:00
# define VARIANT_ARRAYDIMENSIONS 0x40
2007-05-15 09:05:53 +00:00
# define VARIANT_ARRAYMASK 0x80
/* trees */
static gint ett_opcua_array = - 1 ;
static gint ett_opcua_diagnosticinfo = - 1 ;
2014-06-12 10:22:35 +00:00
static gint ett_opcua_diagnosticinfo_encodingmask = - 1 ;
2007-05-15 09:05:53 +00:00
static gint ett_opcua_nodeid = - 1 ;
2014-06-12 10:22:35 +00:00
static gint ett_opcua_expandednodeid = - 1 ;
2007-05-15 09:05:53 +00:00
static gint ett_opcua_localizedtext = - 1 ;
2014-06-12 10:22:35 +00:00
static gint ett_opcua_localizedtext_encodingmask = - 1 ;
2007-05-15 09:05:53 +00:00
static gint ett_opcua_qualifiedname = - 1 ;
static gint ett_opcua_datavalue = - 1 ;
2014-06-12 10:22:35 +00:00
static gint ett_opcua_datavalue_encodingmask = - 1 ;
2007-05-15 09:05:53 +00:00
static gint ett_opcua_variant = - 1 ;
2014-06-12 10:22:35 +00:00
static gint ett_opcua_variant_arraydims = - 1 ;
2007-05-15 09:05:53 +00:00
static gint ett_opcua_extensionobject = - 1 ;
2014-06-12 10:22:35 +00:00
static gint ett_opcua_extensionobject_encodingmask = - 1 ;
2014-06-12 08:11:06 +00:00
static gint ett_opcua_statuscode = - 1 ;
static gint ett_opcua_statuscode_info = - 1 ;
2007-05-15 09:05:53 +00:00
static gint * ett [ ] =
{
& ett_opcua_array ,
& ett_opcua_diagnosticinfo ,
2014-06-12 10:22:35 +00:00
& ett_opcua_diagnosticinfo_encodingmask ,
2007-05-15 09:05:53 +00:00
& ett_opcua_nodeid ,
2014-06-12 10:22:35 +00:00
& ett_opcua_expandednodeid ,
2007-05-15 09:05:53 +00:00
& ett_opcua_localizedtext ,
2014-06-12 10:22:35 +00:00
& ett_opcua_localizedtext_encodingmask ,
2007-05-15 09:05:53 +00:00
& ett_opcua_qualifiedname ,
& ett_opcua_datavalue ,
2014-06-12 10:22:35 +00:00
& ett_opcua_datavalue_encodingmask ,
2007-05-15 09:05:53 +00:00
& ett_opcua_variant ,
2014-06-12 10:22:35 +00:00
& ett_opcua_variant_arraydims ,
2007-05-15 09:05:53 +00:00
& ett_opcua_extensionobject ,
2014-06-12 10:22:35 +00:00
& ett_opcua_extensionobject_encodingmask ,
2014-06-12 08:11:06 +00:00
& ett_opcua_statuscode ,
& ett_opcua_statuscode_info
2007-05-15 09:05:53 +00:00
} ;
void registerSimpleTypes ( int proto )
{
2009-06-22 04:58:08 +00:00
static hf_register_info hf [ ] =
{
2013-08-06 20:10:59 +00:00
/* full name , abbreviation , type , display , strings, bitmask, blurb, id, parent, ref_count */
2009-06-22 04:58:08 +00:00
{ & hf_opcua_diag_mask_symbolicflag ,
2010-04-26 00:15:30 +00:00
{ " has symbolic id " , " opcua.has_symbolic_id " , FT_BOOLEAN , 8 , NULL , DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_diag_mask_namespaceflag ,
2010-04-26 00:15:30 +00:00
{ " has namespace " , " opcua.has_namespace " , FT_BOOLEAN , 8 , NULL , DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_diag_mask_localizedtextflag ,
2010-04-26 00:15:30 +00:00
{ " has localizedtext " , " opcua.has_localizedtext " , FT_BOOLEAN , 8 , NULL , DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_diag_mask_additionalinfoflag ,
2010-04-26 00:15:30 +00:00
{ " has additional info " , " opcua.has_additional_info " , FT_BOOLEAN , 8 , NULL , DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO_FLAG , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_diag_mask_innerstatuscodeflag ,
2010-04-26 00:15:30 +00:00
{ " has inner statuscode " , " opcua.has_inner_statuscode " , FT_BOOLEAN , 8 , NULL , DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE_FLAG , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_diag_mask_innerdiaginfoflag ,
2010-04-26 00:15:30 +00:00
{ " has inner diagnostic info " , " opcua.has_inner_diagnostic_code " , FT_BOOLEAN , 8 , NULL , DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO_FLAG , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_loctext_mask_localeflag ,
2010-04-26 00:15:30 +00:00
{ " has locale information " , " opcua.has_locale_information " , FT_BOOLEAN , 8 , NULL , LOCALIZEDTEXT_ENCODINGBYTE_LOCALE , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_loctext_mask_textflag ,
2010-04-26 00:15:30 +00:00
{ " has text " , " opcua.has_text " , FT_BOOLEAN , 8 , NULL , LOCALIZEDTEXT_ENCODINGBYTE_TEXT , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
{ & hf_opcua_nodeid_encodingmask ,
2014-06-10 08:51:52 +00:00
{ " NodeId EncodingMask " , " application.nodeid.encodingmask " , FT_UINT8 , BASE_HEX , VALS ( g_nodeidmasks ) , 0x0F , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
2014-06-10 09:25:30 +00:00
{ & hf_opcua_nodeid_nsindex ,
{ " NodeId Namespace Index " , " application.nodeid.nsindex " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL }
2009-06-22 04:58:08 +00:00
} ,
2014-06-10 09:47:07 +00:00
{ & hf_opcua_nodeid_numeric , { " NodeId Identifier Numeric " , " application.nodeid.numeric " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_nodeid_string , { " NodeId Identifier String " , " application.nodeid.string " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_nodeid_guid , { " NodeId Identifier Guid " , " application.nodeid.guid " , FT_GUID , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_nodeid_bytestring , { " NodeId Identifier ByteString " , " application.nodeid.bytestring " , FT_BYTES , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
2014-06-10 09:46:05 +00:00
{ & hf_opcua_expandednodeid_mask_namespaceuri , { " has namespace uri " , " opcua.has_namespace_uri " , FT_BOOLEAN , 8 , NULL , NODEID_NAMESPACEURIFLAG , NULL , HFILL } } ,
{ & hf_opcua_expandednodeid_mask_serverindex , { " has server index " , " opcua.has_server_index " , FT_BOOLEAN , 8 , NULL , NODEID_SERVERINDEXFLAG , NULL , HFILL } } ,
2010-04-26 00:15:30 +00:00
{ & hf_opcua_localizedtext_locale , { " Locale " , " opcua.Locale " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_localizedtext_text , { " Text " , " opcua.Text " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_qualifiedname_id , { " Id " , " opcua.Id " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_qualifiedname_name , { " Name " , " opcua.Name " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_datavalue_mask_valueflag , { " has value " , " opcua.has_value " , FT_BOOLEAN , 8 , NULL , DATAVALUE_ENCODINGBYTE_VALUE , NULL , HFILL } } ,
{ & hf_opcua_datavalue_mask_statuscodeflag , { " has statuscode " , " opcua.has_statuscode " , FT_BOOLEAN , 8 , NULL , DATAVALUE_ENCODINGBYTE_STATUSCODE , NULL , HFILL } } ,
{ & hf_opcua_datavalue_mask_sourcetimestampflag , { " has source timestamp " , " opcua.has_source_timestamp " , FT_BOOLEAN , 8 , NULL , DATAVALUE_ENCODINGBYTE_SOURCETIMESTAMP , NULL , HFILL } } ,
{ & hf_opcua_datavalue_mask_servertimestampflag , { " has server timestamp " , " opcua.has_server_timestamp " , FT_BOOLEAN , 8 , NULL , DATAVALUE_ENCODINGBYTE_SERVERTIMESTAMP , NULL , HFILL } } ,
{ & hf_opcua_datavalue_mask_sourcepicoseconds , { " has source picoseconds " , " opcua.has_source_picoseconds " , FT_BOOLEAN , 8 , NULL , DATAVALUE_ENCODINGBYTE_SOURCEPICOSECONDS , NULL , HFILL } } ,
{ & hf_opcua_datavalue_mask_serverpicoseconds , { " has server picoseconds " , " opcua.has_server_picoseconds " , FT_BOOLEAN , 8 , NULL , DATAVALUE_ENCODINGBYTE_SERVERPICOSECONDS , NULL , HFILL } } ,
{ & hf_opcua_variant_encodingmask , { " Variant Type " , " opcua.has_value " , FT_UINT8 , BASE_HEX , VALS ( g_VariantTypes ) , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_SourceTimestamp , { " SourceTimestamp " , " opcua.SourceTimestamp " , FT_ABSOLUTE_TIME , ABSOLUTE_TIME_LOCAL , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_SourcePicoseconds , { " SourcePicoseconds " , " opcua.SourcePicoseconds " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_ServerTimestamp , { " ServerTimestamp " , " opcua.ServerTimestamp " , FT_ABSOLUTE_TIME , ABSOLUTE_TIME_LOCAL , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_ServerPicoseconds , { " ServerPicoseconds " , " opcua.ServerPicoseconds " , FT_UINT16 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_diag_symbolicid , { " SymbolicId " , " opcua.SymbolicId " , FT_INT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_diag_namespace , { " Namespace " , " opcua.Namespace " , FT_INT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_diag_localizedtext , { " LocaliezdText " , " opcua.LocaliezdText " , FT_INT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_diag_additionalinfo , { " AdditionalInfo " , " opcua.AdditionalInfo " , FT_STRING , BASE_NONE , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_diag_innerstatuscode , { " InnerStatusCode " , " opcua.InnerStatusCode " , FT_UINT32 , BASE_HEX , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_extobj_mask_binbodyflag , { " has binary body " , " opcua.has_binary_body " , FT_BOOLEAN , 8 , NULL , EXTOBJ_ENCODINGMASK_BINBODY_FLAG , NULL , HFILL } } ,
{ & hf_opcua_extobj_mask_xmlbodyflag , { " has xml body " , " opcua.has_xml_body " , FT_BOOLEAN , 8 , NULL , EXTOBJ_ENCODINGMASK_XMLBODY_FLAG , NULL , HFILL } } ,
{ & hf_opcua_ArraySize , { " ArraySize " , " opcua.ArraySize " , FT_INT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
2014-06-12 08:11:06 +00:00
{ & hf_opcua_ServerIndex , { " ServerIndex " , " opcua.ServerIndex " , FT_UINT32 , BASE_DEC , NULL , 0x0 , NULL , HFILL } } ,
{ & hf_opcua_status_StructureChanged , { " StructureChanged " , " opcua.statuscode.structureChanged " , FT_BOOLEAN , 16 , NULL , STATUSCODE_STRUCTURECHANGED , NULL , HFILL } } ,
{ & hf_opcua_status_SemanticsChanged , { " SemanticsChanged " , " opcua.statuscode.semanticsChanged " , FT_BOOLEAN , 16 , NULL , STATUSCODE_SEMANTICSCHANGED , NULL , HFILL } } ,
{ & hf_opcua_status_InfoBit_Limit_Overflow , { " Overflow " , " opcua.statuscode.overflow " , FT_BOOLEAN , 16 , NULL , STATUSCODE_INFOBIT_OVERFLOW , NULL , HFILL } } ,
{ & hf_opcua_status_InfoBit_Historian_Partial , { " HistorianBit: Partial " , " opcua.statuscode.historian.partial " , FT_BOOLEAN , 16 , NULL , STATUSCODE_INFOBIT_HISTORIAN_PARTIAL , NULL , HFILL } } ,
{ & hf_opcua_status_InfoBit_Historian_ExtraData , { " HistorianBit: ExtraData " , " opcua.statuscode.historian.extraData " , FT_BOOLEAN , 16 , NULL , STATUSCODE_INFOBIT_HISTORIAN_EXTRADATA , NULL , HFILL } } ,
{ & hf_opcua_status_InfoBit_Historian_MultiValue , { " HistorianBit: MultiValue " , " opcua.statuscode.historian.multiValue " , FT_BOOLEAN , 16 , NULL , STATUSCODE_INFOBIT_HISTORIAN_MULTIVALUE , NULL , HFILL } } ,
{ & hf_opcua_status_InfoType , { " InfoType " , " opcua.statuscode.infoType " , FT_UINT16 , BASE_HEX , VALS ( g_infotype ) , 0x0C00 , NULL , HFILL } } ,
{ & hf_opcua_status_Limit , { " Limit " , " opcua.statuscode.limit " , FT_UINT16 , BASE_HEX , VALS ( g_limit ) , 0x0300 , NULL , HFILL } } ,
{ & hf_opcua_status_Historian , { " Historian " , " opcua.statuscode.historian " , FT_UINT16 , BASE_HEX , VALS ( g_historian ) , 0x0003 , NULL , HFILL } } ,
2009-06-22 04:58:08 +00:00
} ;
2007-05-15 09:05:53 +00:00
proto_register_field_array ( proto , hf , array_length ( hf ) ) ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
}
2014-06-12 14:54:25 +00:00
proto_item * parseBoolean ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 1 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 1 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseByte ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 1 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 1 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseSByte ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 1 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 1 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseUInt16 ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 2 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 2 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseInt16 ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 2 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 2 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseUInt32 ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 4 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 4 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseInt32 ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 4 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 4 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseUInt64 ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 8 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 8 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseInt64 ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 8 , ENC_LITTLE_ENDIAN ) ;
* pOffset + = 8 ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseString ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = NULL ;
2009-09-09 00:18:15 +00:00
char * szValue ;
2007-05-15 09:05:53 +00:00
gint iOffset = * pOffset ;
gint32 iLen = tvb_get_letohl ( tvb , * pOffset ) ;
iOffset + = 4 ;
2009-09-09 00:18:15 +00:00
if ( iLen = = - 1 )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 0 , ENC_NA ) ;
2010-11-16 16:45:22 +00:00
proto_item_append_text ( item , " [OpcUa Null String] " ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( item , tvb , * pOffset + 4 ) ;
2009-09-09 00:18:15 +00:00
}
2010-11-16 16:45:22 +00:00
else if ( iLen = = 0 )
2009-09-09 00:18:15 +00:00
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 0 , ENC_NA ) ;
2010-11-16 16:45:22 +00:00
proto_item_append_text ( item , " [OpcUa Empty String] " ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( item , tvb , * pOffset + 4 ) ;
2010-11-16 16:45:22 +00:00
}
else if ( iLen > 0 )
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , iOffset , iLen , ENC_UTF_8 | ENC_NA ) ;
2009-09-09 00:18:15 +00:00
iOffset + = iLen ; /* eat the whole string */
}
else
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 0 , ENC_NA ) ;
2013-09-17 21:34:05 +00:00
szValue = wmem_strdup_printf ( wmem_packet_scope ( ) , " [Invalid String] Invalid length: %d " , iLen ) ;
2010-11-16 16:45:22 +00:00
proto_item_append_text ( item , " %s " , szValue ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( item , tvb , * pOffset + 4 ) ;
2007-05-15 09:05:53 +00:00
}
2009-09-09 00:18:15 +00:00
* pOffset = iOffset ;
2014-06-12 14:54:25 +00:00
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseStatusCode ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-10 11:36:06 +00:00
proto_item * item = NULL ;
guint32 uStatusCode = 0 ;
const gchar * szStatusCode = NULL ;
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 4 , ENC_LITTLE_ENDIAN ) ;
uStatusCode = tvb_get_letohl ( tvb , * pOffset ) ;
szStatusCode = val_to_str_const ( uStatusCode & 0xFFFF0000 , g_statusCodes , " Unknown Status Code " ) ;
proto_item_append_text ( item , " [%s] " , szStatusCode ) ;
2014-06-12 08:11:06 +00:00
/* check for status code info flags */
if ( uStatusCode & 0x0000FFFF )
{
gint iOffset = * pOffset ;
proto_tree * flags_tree ;
proto_item * ti_inner ;
flags_tree = proto_item_add_subtree ( item , ett_opcua_statuscode ) ;
proto_tree_add_item ( flags_tree , hf_opcua_status_StructureChanged , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( flags_tree , hf_opcua_status_SemanticsChanged , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
ti_inner = proto_tree_add_item ( flags_tree , hf_opcua_status_InfoType , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
switch ( uStatusCode & 0x00000C00 )
{
case STATUSCODE_INFOTYPE_DATAVALUE :
{
/* InfoType == DataValue */
proto_tree * tree_inner ;
tree_inner = proto_item_add_subtree ( ti_inner , ett_opcua_statuscode_info ) ;
proto_tree_add_item ( tree_inner , hf_opcua_status_Limit , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree_inner , hf_opcua_status_InfoBit_Limit_Overflow , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree_inner , hf_opcua_status_InfoBit_Historian_MultiValue , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree_inner , hf_opcua_status_InfoBit_Historian_ExtraData , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree_inner , hf_opcua_status_InfoBit_Historian_Partial , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( tree_inner , hf_opcua_status_Historian , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
}
default :
break ;
}
}
2007-05-15 09:05:53 +00:00
* pOffset + = 4 ;
2014-06-12 14:54:25 +00:00
return item ;
2007-05-15 09:05:53 +00:00
}
2012-04-09 20:06:27 +00:00
void parseLocalizedText ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
gint iOffset = * pOffset ;
guint8 EncodingMask ;
proto_tree * mask_tree ;
proto_tree * subtree ;
proto_item * ti ;
2013-02-15 15:24:39 +00:00
proto_item * ti_inner ;
2007-05-15 09:05:53 +00:00
2013-02-15 15:24:39 +00:00
ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: LocalizedText " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
subtree = proto_item_add_subtree ( ti , ett_opcua_localizedtext ) ;
/* parse encoding mask */
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2013-02-15 15:24:39 +00:00
ti_inner = proto_tree_add_text ( subtree , tvb , iOffset , 1 , " EncodingMask " ) ;
2014-06-12 10:22:35 +00:00
mask_tree = proto_item_add_subtree ( ti_inner , ett_opcua_localizedtext_encodingmask ) ;
2011-10-10 00:53:55 +00:00
proto_tree_add_item ( mask_tree , hf_opcua_loctext_mask_localeflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_loctext_mask_textflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
if ( EncodingMask & LOCALIZEDTEXT_ENCODINGBYTE_LOCALE )
{
2009-04-06 18:30:04 +00:00
parseString ( subtree , tvb , & iOffset , hf_opcua_localizedtext_locale ) ;
2007-05-15 09:05:53 +00:00
}
if ( EncodingMask & LOCALIZEDTEXT_ENCODINGBYTE_TEXT )
{
2009-04-06 18:30:04 +00:00
parseString ( subtree , tvb , & iOffset , hf_opcua_localizedtext_text ) ;
2007-05-15 09:05:53 +00:00
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
2014-06-12 14:54:25 +00:00
proto_item * parseGuid ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , GUID_LEN , ENC_NA ) ;
* pOffset + = GUID_LEN ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseByteString ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = NULL ;
2010-11-16 16:45:22 +00:00
char * szValue ;
2007-05-15 09:05:53 +00:00
int iOffset = * pOffset ;
gint32 iLen = tvb_get_letohl ( tvb , iOffset ) ;
iOffset + = 4 ;
if ( iLen = = - 1 )
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 0 , ENC_NA ) ;
2010-11-16 16:45:22 +00:00
proto_item_append_text ( item , " [OpcUa Null ByteString] " ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( item , tvb , * pOffset + 4 ) ;
2010-11-16 16:45:22 +00:00
}
else if ( iLen = = 0 )
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 0 , ENC_NA ) ;
2010-11-16 16:45:22 +00:00
proto_item_append_text ( item , " [OpcUa Empty ByteString] " ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( item , tvb , * pOffset + 4 ) ;
2007-05-15 09:05:53 +00:00
}
2010-11-16 16:45:22 +00:00
else if ( iLen > 0 )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , iOffset , iLen , ENC_NA ) ;
2010-11-16 16:45:22 +00:00
iOffset + = iLen ; /* eat the whole bytestring */
2007-05-15 09:05:53 +00:00
}
2010-11-16 16:45:22 +00:00
else
{
2014-06-12 14:54:25 +00:00
item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , 0 , ENC_NA ) ;
2013-09-17 21:34:05 +00:00
szValue = wmem_strdup_printf ( wmem_packet_scope ( ) , " [Invalid ByteString] Invalid length: %d " , iLen ) ;
2010-11-16 16:45:22 +00:00
proto_item_append_text ( item , " %s " , szValue ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( item , tvb , * pOffset + 4 ) ;
2010-11-16 16:45:22 +00:00
}
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
2014-06-12 14:54:25 +00:00
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseXmlElement ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
return parseByteString ( tree , tvb , pOffset , hfIndex ) ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseFloat ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , ( int ) sizeof ( gfloat ) , ENC_LITTLE_ENDIAN ) ;
* pOffset + = ( int ) sizeof ( gfloat ) ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseDouble ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = proto_tree_add_item ( tree , hfIndex , tvb , * pOffset , ( int ) sizeof ( gdouble ) , ENC_LITTLE_ENDIAN ) ;
* pOffset + = ( int ) sizeof ( gdouble ) ;
return item ;
2007-05-15 09:05:53 +00:00
}
2014-06-12 14:54:25 +00:00
proto_item * parseDateTime ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , int hfIndex )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * item = NULL ;
* pOffset = dissect_nt_64bit_time_ex ( tvb , tree , * pOffset , hfIndex , & item ) ;
return item ;
2007-05-15 09:05:53 +00:00
}
2012-04-09 20:06:27 +00:00
void parseDiagnosticInfo ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
gint iOffset = * pOffset ;
guint8 EncodingMask ;
proto_tree * mask_tree ;
proto_tree * subtree ;
proto_item * ti ;
2013-02-15 15:24:39 +00:00
proto_item * ti_inner ;
2007-05-15 09:05:53 +00:00
2013-02-15 15:24:39 +00:00
ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: DiagnosticInfo " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
subtree = proto_item_add_subtree ( ti , ett_opcua_diagnosticinfo ) ;
/* parse encoding mask */
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2013-02-15 15:24:39 +00:00
ti_inner = proto_tree_add_text ( subtree , tvb , iOffset , 1 , " EncodingMask " ) ;
2014-06-12 10:22:35 +00:00
mask_tree = proto_item_add_subtree ( ti_inner , ett_opcua_diagnosticinfo_encodingmask ) ;
2011-10-10 00:53:55 +00:00
proto_tree_add_item ( mask_tree , hf_opcua_diag_mask_symbolicflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_diag_mask_namespaceflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_diag_mask_localizedtextflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_diag_mask_additionalinfoflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_diag_mask_innerstatuscodeflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_diag_mask_innerdiaginfoflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
if ( EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG )
{
parseInt32 ( subtree , tvb , & iOffset , hf_opcua_diag_symbolicid ) ;
}
if ( EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG )
{
parseInt32 ( subtree , tvb , & iOffset , hf_opcua_diag_namespace ) ;
}
if ( EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG )
{
parseInt32 ( subtree , tvb , & iOffset , hf_opcua_diag_localizedtext ) ;
}
if ( EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO_FLAG )
{
parseString ( subtree , tvb , & iOffset , hf_opcua_diag_additionalinfo ) ;
}
if ( EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE_FLAG )
{
parseStatusCode ( subtree , tvb , & iOffset , hf_opcua_diag_innerstatuscode ) ;
}
if ( EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO_FLAG )
{
parseDiagnosticInfo ( subtree , tvb , & iOffset , " Inner DiagnosticInfo " ) ;
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
2012-04-09 20:06:27 +00:00
void parseQualifiedName ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
2013-02-15 15:24:39 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: QualifiedName " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_qualifiedname ) ;
2009-04-06 18:30:04 +00:00
parseUInt16 ( subtree , tvb , pOffset , hf_opcua_qualifiedname_id ) ;
parseString ( subtree , tvb , pOffset , hf_opcua_qualifiedname_name ) ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , * pOffset ) ;
2007-05-15 09:05:53 +00:00
}
2012-04-09 20:06:27 +00:00
void parseDataValue ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
2013-02-15 15:24:39 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: DataValue " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_datavalue ) ;
proto_tree * mask_tree ;
gint iOffset = * pOffset ;
guint8 EncodingMask ;
2013-02-15 15:24:39 +00:00
proto_item * ti_inner ;
2007-05-15 09:05:53 +00:00
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2013-02-15 15:24:39 +00:00
ti_inner = proto_tree_add_text ( subtree , tvb , iOffset , 1 , " EncodingMask " ) ;
2014-06-12 10:22:35 +00:00
mask_tree = proto_item_add_subtree ( ti_inner , ett_opcua_datavalue_encodingmask ) ;
2011-10-10 00:53:55 +00:00
proto_tree_add_item ( mask_tree , hf_opcua_datavalue_mask_valueflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_datavalue_mask_statuscodeflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_datavalue_mask_sourcetimestampflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_datavalue_mask_servertimestampflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_datavalue_mask_sourcepicoseconds , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_datavalue_mask_serverpicoseconds , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
if ( EncodingMask & DATAVALUE_ENCODINGBYTE_VALUE )
{
parseVariant ( subtree , tvb , & iOffset , " Value " ) ;
}
if ( EncodingMask & DATAVALUE_ENCODINGBYTE_STATUSCODE )
{
parseStatusCode ( subtree , tvb , & iOffset , hf_opcua_StatusCode ) ;
}
if ( EncodingMask & DATAVALUE_ENCODINGBYTE_SOURCETIMESTAMP )
{
parseDateTime ( subtree , tvb , & iOffset , hf_opcua_SourceTimestamp ) ;
}
2009-04-06 18:30:04 +00:00
if ( EncodingMask & DATAVALUE_ENCODINGBYTE_SOURCEPICOSECONDS )
{
parseUInt16 ( subtree , tvb , & iOffset , hf_opcua_SourcePicoseconds ) ;
}
2007-05-15 09:05:53 +00:00
if ( EncodingMask & DATAVALUE_ENCODINGBYTE_SERVERTIMESTAMP )
{
parseDateTime ( subtree , tvb , & iOffset , hf_opcua_ServerTimestamp ) ;
}
2009-04-06 18:30:04 +00:00
if ( EncodingMask & DATAVALUE_ENCODINGBYTE_SERVERPICOSECONDS )
{
parseUInt16 ( subtree , tvb , & iOffset , hf_opcua_ServerPicoseconds ) ;
}
2007-05-15 09:05:53 +00:00
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
2012-04-09 20:06:27 +00:00
void parseVariant ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
2013-02-15 15:24:39 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: Variant " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_variant ) ;
gint iOffset = * pOffset ;
guint8 EncodingMask ;
2013-02-15 15:24:39 +00:00
gint32 ArrayDimensions = 0 ;
2007-05-15 09:05:53 +00:00
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_variant_encodingmask , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
if ( EncodingMask & VARIANT_ARRAYMASK )
{
2009-04-06 18:30:04 +00:00
/* type is encoded in bits 0-5 */
switch ( EncodingMask & 0x3f )
2007-05-15 09:05:53 +00:00
{
case OpcUaType_Null : break ;
2014-06-12 14:54:25 +00:00
case OpcUaType_Boolean : parseArraySimple ( subtree , tvb , & iOffset , " Boolean " , " Boolean " , hf_opcua_Boolean , parseBoolean ) ; break ;
case OpcUaType_SByte : parseArraySimple ( subtree , tvb , & iOffset , " SByte " , " SByte " , hf_opcua_SByte , parseSByte ) ; break ;
case OpcUaType_Byte : parseArraySimple ( subtree , tvb , & iOffset , " Byte " , " Byte " , hf_opcua_Byte , parseByte ) ; break ;
case OpcUaType_Int16 : parseArraySimple ( subtree , tvb , & iOffset , " Int16 " , " Int16 " , hf_opcua_Int16 , parseInt16 ) ; break ;
case OpcUaType_UInt16 : parseArraySimple ( subtree , tvb , & iOffset , " UInt16 " , " UInt16 " , hf_opcua_UInt16 , parseUInt16 ) ; break ;
case OpcUaType_Int32 : parseArraySimple ( subtree , tvb , & iOffset , " Int32 " , " Int32 " , hf_opcua_Int32 , parseInt32 ) ; break ;
case OpcUaType_UInt32 : parseArraySimple ( subtree , tvb , & iOffset , " UInt32 " , " UInt32 " , hf_opcua_UInt32 , parseUInt32 ) ; break ;
case OpcUaType_Int64 : parseArraySimple ( subtree , tvb , & iOffset , " Int64 " , " Int64 " , hf_opcua_Int64 , parseInt64 ) ; break ;
case OpcUaType_UInt64 : parseArraySimple ( subtree , tvb , & iOffset , " UInt64 " , " UInt64 " , hf_opcua_UInt64 , parseUInt64 ) ; break ;
case OpcUaType_Float : parseArraySimple ( subtree , tvb , & iOffset , " Float " , " Float " , hf_opcua_Float , parseFloat ) ; break ;
case OpcUaType_Double : parseArraySimple ( subtree , tvb , & iOffset , " Double " , " Double " , hf_opcua_Double , parseDouble ) ; break ;
case OpcUaType_String : parseArraySimple ( subtree , tvb , & iOffset , " String " , " String " , hf_opcua_String , parseString ) ; break ;
case OpcUaType_DateTime : parseArraySimple ( subtree , tvb , & iOffset , " DateTime " , " DateTime " , hf_opcua_DateTime , parseDateTime ) ; break ;
case OpcUaType_Guid : parseArraySimple ( subtree , tvb , & iOffset , " Guid " , " Guid " , hf_opcua_Guid , parseGuid ) ; break ;
case OpcUaType_ByteString : parseArraySimple ( subtree , tvb , & iOffset , " ByteString " , " ByteString " , hf_opcua_ByteString , parseByteString ) ; break ;
case OpcUaType_XmlElement : parseArraySimple ( subtree , tvb , & iOffset , " XmlElement " , " XmlElement " , hf_opcua_XmlElement , parseXmlElement ) ; break ;
case OpcUaType_NodeId : parseArrayComplex ( subtree , tvb , & iOffset , " NodeId " , " NodeId " , parseNodeId ) ; break ;
case OpcUaType_ExpandedNodeId : parseArrayComplex ( subtree , tvb , & iOffset , " ExpandedNodeId " , " ExpandedNodeId " , parseExpandedNodeId ) ; break ;
case OpcUaType_StatusCode : parseArraySimple ( subtree , tvb , & iOffset , " StatusCode " , " StatusCode " , hf_opcua_StatusCode , parseStatusCode ) ; break ;
case OpcUaType_DiagnosticInfo : parseArrayComplex ( subtree , tvb , & iOffset , " DiagnosticInfo " , " DiagnosticInfo " , parseDiagnosticInfo ) ; break ;
case OpcUaType_QualifiedName : parseArrayComplex ( subtree , tvb , & iOffset , " QualifiedName " , " QualifiedName " , parseQualifiedName ) ; break ;
case OpcUaType_LocalizedText : parseArrayComplex ( subtree , tvb , & iOffset , " LocalizedText " , " LocalizedText " , parseLocalizedText ) ; break ;
case OpcUaType_ExtensionObject : parseArrayComplex ( subtree , tvb , & iOffset , " ExtensionObject " , " ExtensionObject " , parseExtensionObject ) ; break ;
case OpcUaType_DataValue : parseArrayComplex ( subtree , tvb , & iOffset , " DataValue " , " DataValue " , parseDataValue ) ; break ;
case OpcUaType_Variant : parseArrayComplex ( subtree , tvb , & iOffset , " Variant " , " Variant " , parseVariant ) ; break ;
2007-05-15 09:05:53 +00:00
}
2010-11-15 18:52:41 +00:00
if ( EncodingMask & VARIANT_ARRAYDIMENSIONS )
{
2013-02-15 15:24:39 +00:00
proto_item * ti_2 = proto_tree_add_text ( subtree , tvb , iOffset , - 1 , " ArrayDimensions " ) ;
2014-06-12 10:22:35 +00:00
proto_tree * subtree_2 = proto_item_add_subtree ( ti_2 , ett_opcua_variant_arraydims ) ;
2010-11-15 18:52:41 +00:00
int i ;
2013-02-15 15:24:39 +00:00
/* read array length */
ArrayDimensions = tvb_get_letohl ( tvb , iOffset ) ;
proto_tree_add_item ( subtree_2 , hf_opcua_ArraySize , tvb , iOffset , 4 , ENC_LITTLE_ENDIAN ) ;
if ( ArrayDimensions > MAX_ARRAY_LEN )
2010-11-15 18:52:41 +00:00
{
proto_item * pi ;
2013-02-15 15:24:39 +00:00
pi = proto_tree_add_text ( subtree_2 , tvb , iOffset , 4 , " ArrayDimensions length %d too large to process " , ArrayDimensions ) ;
2010-11-15 18:52:41 +00:00
PROTO_ITEM_SET_GENERATED ( pi ) ;
2013-02-15 15:24:39 +00:00
return ;
}
iOffset + = 4 ;
for ( i = 0 ; i < ArrayDimensions ; i + + )
{
parseInt32 ( subtree_2 , tvb , & iOffset , hf_opcua_Int32 ) ;
2010-11-15 18:52:41 +00:00
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti_2 , tvb , iOffset ) ;
2010-11-15 18:52:41 +00:00
}
2007-05-15 09:05:53 +00:00
}
else
{
2009-04-06 18:30:04 +00:00
/* type is encoded in bits 0-5 */
switch ( EncodingMask & 0x3f )
2007-05-15 09:05:53 +00:00
{
case OpcUaType_Null : break ;
case OpcUaType_Boolean : parseBoolean ( subtree , tvb , & iOffset , hf_opcua_Boolean ) ; break ;
case OpcUaType_SByte : parseSByte ( subtree , tvb , & iOffset , hf_opcua_SByte ) ; break ;
case OpcUaType_Byte : parseByte ( subtree , tvb , & iOffset , hf_opcua_Byte ) ; break ;
case OpcUaType_Int16 : parseInt16 ( subtree , tvb , & iOffset , hf_opcua_Int16 ) ; break ;
case OpcUaType_UInt16 : parseUInt16 ( subtree , tvb , & iOffset , hf_opcua_UInt16 ) ; break ;
case OpcUaType_Int32 : parseInt32 ( subtree , tvb , & iOffset , hf_opcua_Int32 ) ; break ;
case OpcUaType_UInt32 : parseUInt32 ( subtree , tvb , & iOffset , hf_opcua_UInt32 ) ; break ;
case OpcUaType_Int64 : parseInt64 ( subtree , tvb , & iOffset , hf_opcua_Int64 ) ; break ;
case OpcUaType_UInt64 : parseUInt64 ( subtree , tvb , & iOffset , hf_opcua_UInt64 ) ; break ;
case OpcUaType_Float : parseFloat ( subtree , tvb , & iOffset , hf_opcua_Float ) ; break ;
case OpcUaType_Double : parseDouble ( subtree , tvb , & iOffset , hf_opcua_Double ) ; break ;
case OpcUaType_String : parseString ( subtree , tvb , & iOffset , hf_opcua_String ) ; break ;
case OpcUaType_DateTime : parseDateTime ( subtree , tvb , & iOffset , hf_opcua_DateTime ) ; break ;
case OpcUaType_Guid : parseGuid ( subtree , tvb , & iOffset , hf_opcua_Guid ) ; break ;
case OpcUaType_ByteString : parseByteString ( subtree , tvb , & iOffset , hf_opcua_ByteString ) ; break ;
case OpcUaType_XmlElement : parseXmlElement ( subtree , tvb , & iOffset , hf_opcua_XmlElement ) ; break ;
case OpcUaType_NodeId : parseNodeId ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_ExpandedNodeId : parseExpandedNodeId ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_StatusCode : parseStatusCode ( subtree , tvb , & iOffset , hf_opcua_StatusCode ) ; break ;
case OpcUaType_DiagnosticInfo : parseDiagnosticInfo ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_QualifiedName : parseQualifiedName ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_LocalizedText : parseLocalizedText ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_ExtensionObject : parseExtensionObject ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_DataValue : parseDataValue ( subtree , tvb , & iOffset , " Value " ) ; break ;
case OpcUaType_Variant : parseVariant ( subtree , tvb , & iOffset , " Value " ) ; break ;
}
}
2009-10-20 14:03:00 +00:00
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
/** General parsing function for arrays of simple types.
* All arrays have one 4 byte signed integer length information ,
* followed by n data elements .
*/
2014-06-12 14:54:25 +00:00
void parseArraySimple ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName , const char * szTypeName , int hfIndex , fctSimpleTypeParser pParserFunction )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: Array of %s " , szFieldName , szTypeName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_array ) ;
int i ;
gint32 iLen ;
/* read array length */
iLen = tvb_get_letohl ( tvb , * pOffset ) ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_ArraySize , tvb , * pOffset , 4 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
2009-09-09 00:18:15 +00:00
if ( iLen > MAX_ARRAY_LEN )
{
2013-02-15 15:24:39 +00:00
proto_item * pi ;
2009-10-20 14:03:00 +00:00
pi = proto_tree_add_text ( tree , tvb , * pOffset , 4 , " Array length %d too large to process " , iLen ) ;
2013-02-15 15:24:39 +00:00
PROTO_ITEM_SET_GENERATED ( pi ) ;
2009-09-09 00:18:15 +00:00
return ;
}
* pOffset + = 4 ;
2007-05-15 09:05:53 +00:00
for ( i = 0 ; i < iLen ; i + + )
{
2014-06-12 14:54:25 +00:00
proto_item * arrayItem = ( * pParserFunction ) ( subtree , tvb , pOffset , hfIndex ) ;
if ( arrayItem ! = NULL )
{
proto_item_prepend_text ( arrayItem , " [%i]: " , i ) ;
}
2007-05-15 09:05:53 +00:00
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , * pOffset ) ;
2007-05-15 09:05:53 +00:00
}
/** General parsing function for arrays of enums.
* All arrays have one 4 byte signed integer length information ,
* followed by n data elements .
*/
2014-06-12 14:54:25 +00:00
void parseArrayEnum ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName , const char * szTypeName , fctEnumParser pParserFunction )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: Array of %s " , szFieldName , szTypeName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_array ) ;
int i ;
gint32 iLen ;
/* read array length */
iLen = tvb_get_letohl ( tvb , * pOffset ) ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_ArraySize , tvb , * pOffset , 4 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
2009-09-09 00:18:15 +00:00
if ( iLen > MAX_ARRAY_LEN )
{
2013-02-15 15:24:39 +00:00
proto_item * pi ;
2009-10-20 14:03:00 +00:00
pi = proto_tree_add_text ( tree , tvb , * pOffset , 4 , " Array length %d too large to process " , iLen ) ;
2013-02-15 15:24:39 +00:00
PROTO_ITEM_SET_GENERATED ( pi ) ;
2009-09-09 00:18:15 +00:00
return ;
}
* pOffset + = 4 ;
2007-05-15 09:05:53 +00:00
for ( i = 0 ; i < iLen ; i + + )
{
( * pParserFunction ) ( subtree , tvb , pOffset ) ;
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , * pOffset ) ;
2007-05-15 09:05:53 +00:00
}
/** General parsing function for arrays of complex types.
* All arrays have one 4 byte signed integer length information ,
* followed by n data elements .
*/
2014-06-12 14:54:25 +00:00
void parseArrayComplex ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName , const char * szTypeName , fctComplexTypeParser pParserFunction )
2007-05-15 09:05:53 +00:00
{
2014-06-12 14:54:25 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: Array of %s " , szFieldName , szTypeName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_array ) ;
int i ;
gint32 iLen ;
/* read array length */
iLen = tvb_get_letohl ( tvb , * pOffset ) ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_ArraySize , tvb , * pOffset , 4 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
2009-09-09 00:18:15 +00:00
if ( iLen > MAX_ARRAY_LEN )
{
2013-02-15 15:24:39 +00:00
proto_item * pi ;
2009-10-20 14:03:00 +00:00
pi = proto_tree_add_text ( tree , tvb , * pOffset , 4 , " Array length %d too large to process " , iLen ) ;
2013-02-15 15:24:39 +00:00
PROTO_ITEM_SET_GENERATED ( pi ) ;
2009-09-09 00:18:15 +00:00
return ;
}
* pOffset + = 4 ;
2007-05-15 09:05:53 +00:00
for ( i = 0 ; i < iLen ; i + + )
{
char szNum [ 20 ] ;
g_snprintf ( szNum , 20 , " [%i] " , i ) ;
( * pParserFunction ) ( subtree , tvb , pOffset , szNum ) ;
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , * pOffset ) ;
2007-05-15 09:05:53 +00:00
}
2012-04-09 20:06:27 +00:00
void parseNodeId ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
2013-02-15 15:24:39 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: NodeId " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_nodeid ) ;
gint iOffset = * pOffset ;
guint8 EncodingMask ;
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_encodingmask , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
switch ( EncodingMask )
{
case 0x00 : /* two byte node id */
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_numeric , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 1 ;
break ;
case 0x01 : /* four byte node id */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 1 ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_numeric , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 2 ;
break ;
case 0x02 : /* numeric, that does not fit into four bytes */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_numeric , tvb , iOffset , 4 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 4 ;
break ;
case 0x03 : /* string */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2014-06-10 09:47:07 +00:00
parseString ( subtree , tvb , & iOffset , hf_opcua_nodeid_string ) ;
2007-05-15 09:05:53 +00:00
break ;
2009-04-06 18:30:04 +00:00
case 0x04 : /* guid */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2014-06-10 09:47:07 +00:00
parseGuid ( subtree , tvb , & iOffset , hf_opcua_nodeid_guid ) ;
2007-05-15 09:05:53 +00:00
break ;
2009-04-06 18:30:04 +00:00
case 0x05 : /* byte string */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2012-05-05 04:57:40 +00:00
iOffset + = 2 ;
2014-06-10 09:47:07 +00:00
parseByteString ( subtree , tvb , & iOffset , hf_opcua_nodeid_bytestring ) ;
2007-05-15 09:05:53 +00:00
break ;
} ;
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
2012-04-09 20:06:27 +00:00
void parseExtensionObject ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
gint iOffset = * pOffset ;
guint8 EncodingMask ;
2010-11-16 17:00:50 +00:00
guint32 TypeId ;
2007-05-15 09:05:53 +00:00
proto_tree * extobj_tree ;
proto_tree * mask_tree ;
proto_item * ti ;
2013-02-15 15:24:39 +00:00
proto_item * ti_inner ;
2007-05-15 09:05:53 +00:00
/* add extension object subtree */
2014-06-12 14:54:25 +00:00
ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: ExtensionObject " , szFieldName ) ;
2007-05-15 09:05:53 +00:00
extobj_tree = proto_item_add_subtree ( ti , ett_opcua_extensionobject ) ;
/* add nodeid subtree */
2010-11-16 17:00:50 +00:00
TypeId = getExtensionObjectType ( tvb , & iOffset ) ;
2007-05-15 09:05:53 +00:00
parseExpandedNodeId ( extobj_tree , tvb , & iOffset , " TypeId " ) ;
/* parse encoding mask */
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2013-02-15 15:24:39 +00:00
ti_inner = proto_tree_add_text ( extobj_tree , tvb , iOffset , 1 , " EncodingMask " ) ;
2014-06-12 10:22:35 +00:00
mask_tree = proto_item_add_subtree ( ti_inner , ett_opcua_extensionobject_encodingmask ) ;
2011-10-10 00:53:55 +00:00
proto_tree_add_item ( mask_tree , hf_opcua_extobj_mask_binbodyflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( mask_tree , hf_opcua_extobj_mask_xmlbodyflag , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
if ( EncodingMask & EXTOBJ_ENCODINGMASK_BINBODY_FLAG ) /* has binary body ? */
{
2010-11-16 17:00:50 +00:00
dispatchExtensionObjectType ( extobj_tree , tvb , & iOffset , TypeId ) ;
2007-05-15 09:05:53 +00:00
}
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
2012-04-09 20:06:27 +00:00
void parseExpandedNodeId ( proto_tree * tree , tvbuff_t * tvb , gint * pOffset , const char * szFieldName )
2007-05-15 09:05:53 +00:00
{
2013-02-15 15:24:39 +00:00
proto_item * ti = proto_tree_add_text ( tree , tvb , * pOffset , - 1 , " %s: ExpandedNodeId " , szFieldName ) ;
2014-06-12 10:22:35 +00:00
proto_tree * subtree = proto_item_add_subtree ( ti , ett_opcua_expandednodeid ) ;
2007-05-15 09:05:53 +00:00
gint iOffset = * pOffset ;
2007-05-15 09:53:26 +00:00
guint8 EncodingMask ;
2007-05-15 09:05:53 +00:00
EncodingMask = tvb_get_guint8 ( tvb , iOffset ) ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_encodingmask , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2014-06-10 09:46:05 +00:00
proto_tree_add_item ( subtree , hf_opcua_expandednodeid_mask_namespaceuri , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
proto_tree_add_item ( subtree , hf_opcua_expandednodeid_mask_serverindex , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + + ;
2014-06-10 08:51:52 +00:00
switch ( EncodingMask & 0x0F )
2007-05-15 09:05:53 +00:00
{
case 0x00 : /* two byte node id */
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_numeric , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 1 ;
break ;
case 0x01 : /* four byte node id */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 1 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 1 ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_numeric , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 2 ;
break ;
case 0x02 : /* numeric, that does not fit into four bytes */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2011-10-06 14:46:34 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_numeric , tvb , iOffset , 4 , ENC_LITTLE_ENDIAN ) ;
2007-05-15 09:05:53 +00:00
iOffset + = 4 ;
break ;
case 0x03 : /* string */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2014-06-10 09:47:07 +00:00
parseString ( subtree , tvb , & iOffset , hf_opcua_nodeid_string ) ;
2007-05-15 09:05:53 +00:00
break ;
2009-04-06 18:30:04 +00:00
case 0x04 : /* guid */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2014-06-10 09:47:07 +00:00
parseGuid ( subtree , tvb , & iOffset , hf_opcua_nodeid_guid ) ;
2007-05-15 09:05:53 +00:00
break ;
2009-04-06 18:30:04 +00:00
case 0x05 : /* byte string */
2014-06-10 09:25:30 +00:00
proto_tree_add_item ( subtree , hf_opcua_nodeid_nsindex , tvb , iOffset , 2 , ENC_LITTLE_ENDIAN ) ;
2009-04-06 18:30:04 +00:00
iOffset + = 2 ;
2014-06-10 09:47:07 +00:00
parseByteString ( subtree , tvb , & iOffset , hf_opcua_nodeid_bytestring ) ;
2007-05-15 09:05:53 +00:00
break ;
} ;
2014-06-10 09:25:30 +00:00
if ( EncodingMask & NODEID_NAMESPACEURIFLAG )
2007-05-15 09:05:53 +00:00
{
2014-06-10 09:25:30 +00:00
parseString ( subtree , tvb , & iOffset , hf_opcua_NamespaceUri ) ;
2007-05-15 09:05:53 +00:00
}
2009-04-06 18:30:04 +00:00
if ( EncodingMask & NODEID_SERVERINDEXFLAG )
{
parseUInt32 ( subtree , tvb , & iOffset , hf_opcua_ServerIndex ) ;
}
2007-05-15 09:05:53 +00:00
2013-02-15 15:24:39 +00:00
proto_item_set_end ( ti , tvb , iOffset ) ;
2007-05-15 09:05:53 +00:00
* pOffset = iOffset ;
}
2010-11-16 17:00:50 +00:00
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 ) ;
2013-09-02 23:15:17 +00:00
/*iOffset+=1;*/
2010-11-16 17:00:50 +00:00
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 ;
}