from Gerhard Gappmeier (ascolab):
[obnox/wireshark/wip.git] / plugins / opcua / ua_application_layer.c
1 /******************************************************************************\r
2 ** $Id: ua_application_layer.c,v 1.3 2007/02/08 11:31:56 gergap Exp $\r
3 **\r
4 ** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved.\r
5 ** Web: http://www.ascolab.com\r
6 ** \r
7 ** This program is free software; you can redistribute it and/or\r
8 ** modify it under the terms of the GNU General Public License\r
9 ** as published by the Free Software Foundation; either version 2\r
10 ** of the License, or (at your option) any later version.\r
11 ** \r
12 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE\r
13 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.\r
14 ** \r
15 ** Project: OpcUa Wireshark Plugin\r
16 **\r
17 ** Description: OpcUa Application Layer Decoder.\r
18 **\r
19 ** Author: Gerhard Gappmeier <gerhard.gappmeier@ascolab.com>\r
20 ** Last change by: $Author: gergap $\r
21 **\r
22 ******************************************************************************/\r
23 \r
24 #ifdef HAVE_CONFIG_H\r
25 # include "config.h"\r
26 #endif\r
27 \r
28 #include <gmodule.h>\r
29 #include <epan/packet.h>\r
30 #include "opcua_simpletypes.h"\r
31 \r
32 /** NodeId encoding mask table */\r
33 static const value_string g_nodeidmasks[] = {\r
34     { 0, "Two byte encoded Numeric" },\r
35     { 1, "Four byte encoded Numeric" },\r
36     { 2, "Numeric of arbitrary length" },\r
37     { 3, "String" },\r
38     { 4, "URI" },\r
39     { 5, "GUID" },\r
40     { 6, "ByteString" },\r
41     { 0x80, "UriMask" },\r
42     { 0, NULL }\r
43 };\r
44 \r
45 /** Service type table */\r
46 extern const value_string g_requesttypes[];\r
47 \r
48 static int hf_opcua_nodeid_encodingmask = -1;\r
49 static int hf_opcua_app_nsid = -1;\r
50 static int hf_opcua_app_numeric = -1;\r
51 \r
52 /** header field definitions */\r
53 static hf_register_info hf[] =\r
54 {\r
55     { &hf_opcua_nodeid_encodingmask,\r
56     {  "NodeId EncodingMask",        "application.nodeid.encodingmask", FT_UINT8,   BASE_HEX,  VALS(g_nodeidmasks), 0x0,    "",    HFILL }\r
57     },\r
58     { &hf_opcua_app_nsid,\r
59     {  "NodeId EncodingMask",        "application.nodeid.nsid",         FT_UINT8,   BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
60     },\r
61     { &hf_opcua_app_numeric,\r
62     {  "NodeId Identifier Numeric",  "application.nodeid.numeric",      FT_UINT32,  BASE_DEC,  VALS(g_requesttypes), 0x0,    "",    HFILL }\r
63     }\r
64 };\r
65 \r
66 /** Register application layer types. */\r
67 void registerApplicationLayerTypes(int proto)\r
68 {\r
69     proto_register_field_array(proto, hf, array_length(hf));\r
70 }\r
71 \r
72 /** Parses an OpcUa Service NodeId and returns the service type.\r
73  * In this cases the NodeId is always from type numeric and NSId = 0.\r
74  */\r
75 int parseServiceNodeId(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, char *szFieldName)\r
76 {\r
77     gint    iOffset = *pOffset;\r
78     guint8  EncodingMask, NSId = 0;\r
79     guint32 Numeric = 0;\r
80 \r
81         szFieldName = 0; /* avoid warning */\r
82 \r
83     EncodingMask = tvb_get_guint8(tvb, iOffset);\r
84     proto_tree_add_item(tree, hf_opcua_nodeid_encodingmask, tvb, iOffset, 1, TRUE);\r
85     iOffset++;\r
86 \r
87     switch(EncodingMask)\r
88     {\r
89     case 0x00: /* two byte node id */\r
90         Numeric = tvb_get_guint8(tvb, iOffset);\r
91         proto_tree_add_item(tree, hf_opcua_app_numeric, tvb, iOffset, 1, TRUE);\r
92         iOffset+=1;\r
93         break;\r
94     case 0x01: /* four byte node id */\r
95         NSId = tvb_get_guint8(tvb, iOffset);\r
96         proto_tree_add_item(tree, hf_opcua_app_nsid, tvb, iOffset, 1, TRUE);\r
97         iOffset+=1;\r
98         Numeric = tvb_get_letohs(tvb, iOffset);\r
99         proto_tree_add_item(tree, hf_opcua_app_numeric, tvb, iOffset, 2, TRUE);\r
100         iOffset+=2;\r
101         break;\r
102     case 0x02: /* numeric, that does not fit into four bytes */\r
103         NSId = tvb_get_letohl(tvb, iOffset);\r
104         proto_tree_add_item(tree, hf_opcua_app_nsid, tvb, iOffset, 4, TRUE);\r
105         iOffset+=4;\r
106         Numeric = tvb_get_letohl(tvb, iOffset);\r
107         proto_tree_add_item(tree, hf_opcua_app_numeric, tvb, iOffset, 4, TRUE);\r
108         iOffset+=4;\r
109         break;\r
110     case 0x03: /* string */\r
111     case 0x04: /* uri */\r
112     case 0x05: /* guid */\r
113     case 0x06: /* byte string */\r
114         /* NOT USED */\r
115         break;\r
116     };\r
117 \r
118     *pOffset = iOffset;\r
119 \r
120     return Numeric;\r
121 }\r
122 \r