from Gerhard Gappmeier (ascolab):
[obnox/wireshark/wip.git] / plugins / opcua / ua_transport_layer.c
1 /******************************************************************************\r
2 ** $Id: ua_transport_layer.c,v 1.3 2007/02/08 12:17:50 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 Transport 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 "ua_security_layer.h"\r
31 #include "ua_application_layer.h"\r
32 #include "opcua_simpletypes.h"\r
33 #include <string.h>\r
34 #include <epan/emem.h>\r
35 \r
36 void dispatchService(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int ServiceId);\r
37 \r
38 static int hf_opcua_transport_sig = -1;\r
39 static int hf_opcua_transport_len = -1;\r
40 static int hf_opcua_transport_ver = -1;\r
41 static int hf_opcua_transport_cid = -1;\r
42 static int hf_opcua_transport_lifetime = -1;\r
43 static int hf_opcua_transport_sbl = -1;\r
44 static int hf_opcua_transport_rbl = -1;\r
45 static int hf_opcua_transport_endpoint = -1;\r
46 static int hf_opcua_transport_rlifetime = -1;\r
47 static int hf_opcua_transport_rsbl = -1;\r
48 static int hf_opcua_transport_rrbl = -1;\r
49 static int hf_opcua_transport_altendpoint = -1;\r
50 static int hf_opcua_transport_rqid = -1;\r
51 static int hf_opcua_transport_status = -1;\r
52 extern gint ett_opcua_nodeid;\r
53 \r
54 static hf_register_info hf[] =\r
55 {\r
56     { &hf_opcua_transport_sig,\r
57     /* full name  ,           abbreviation  ,       type     , display  , strings, bitmask, blurb, id, parent, ref_count, bitshift */\r
58     {  "Signature",           "transport.sig",      FT_STRING, BASE_NONE, NULL,    0x0,     "",    HFILL }\r
59     },\r
60     { &hf_opcua_transport_len,\r
61     {  "Message Length",      "transport.len",      FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
62     },\r
63     { &hf_opcua_transport_ver,\r
64     {  "Version",             "transport.ver",      FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
65     },\r
66     { &hf_opcua_transport_cid,\r
67     {  "ConnectionId",        "transport.cid",      FT_GUID,   BASE_NONE, NULL, 0x0,    "",    HFILL }\r
68     },\r
69     { &hf_opcua_transport_lifetime,\r
70     {  "Lifetime",            "transport.lifetime", FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
71     },\r
72     { &hf_opcua_transport_sbl,\r
73     {  "SendBufferLength",    "transport.sbl",      FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
74     },\r
75     { &hf_opcua_transport_rbl,\r
76     {  "ReceiveBufferLength", "transport.rbl",      FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
77     },\r
78     { &hf_opcua_transport_endpoint,\r
79     {  "EndPoint",            "transport.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,    "",    HFILL }\r
80     },\r
81     { &hf_opcua_transport_rlifetime,\r
82     {  "Revised Lifetime",    "transport.rlifetime", FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
83     },\r
84     { &hf_opcua_transport_rsbl,\r
85     {  "Revised SendBufferLength", "transport.rsbl", FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
86     },\r
87     { &hf_opcua_transport_rrbl,\r
88     {  "Revised ReceiveBufferLength", "transport.rrbl", FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
89     },\r
90     { &hf_opcua_transport_altendpoint,\r
91     {  "Alternate EndPoint",  "transport.altendpoint", FT_STRING, BASE_NONE, NULL, 0x0,    "",    HFILL }\r
92     },\r
93     { &hf_opcua_transport_rqid,\r
94     {  "RequestId",           "transport.rqid",     FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
95     },\r
96     { &hf_opcua_transport_status,\r
97     {  "StatusCode",          "transport.status",   FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }\r
98     }\r
99 };\r
100 \r
101 /** subtree types */\r
102 extern gint ett_opcua_extensionobject;\r
103 \r
104 /** Register transport layer types. */\r
105 void registerTransportLayerTypes(int proto)\r
106 {\r
107     proto_register_field_array(proto, hf, array_length(hf));\r
108 }\r
109 \r
110 /** helper functions for adding strings,\r
111   * that are not zero terminated.\r
112   */\r
113 void addString(proto_tree *tree,  \r
114                int  hfindex,  \r
115                tvbuff_t *tvb,  \r
116                gint  start,  \r
117                gint  length,  \r
118                const char *value)\r
119 {\r
120     char *szValue = ep_alloc(256);\r
121 \r
122     if (szValue)\r
123     {\r
124         if (length > 255) length = 255;\r
125         /* copy non null terminated string data */\r
126         strncpy(szValue, value, length);\r
127         /* set null terminator */\r
128         szValue[length] = 0;\r
129 \r
130         proto_tree_add_string(tree, hfindex, tvb, start, length, szValue);\r
131     }\r
132 }\r
133 \r
134 /* Transport Layer: message parsers */\r
135 void parseHello(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)\r
136 {\r
137     addString(tree, hf_opcua_transport_sig, tvb, *pOffset, 4, tvb->real_data); *pOffset+=4;\r
138     proto_tree_add_item(tree, hf_opcua_transport_len, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
139     proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
140     proto_tree_add_item(tree, hf_opcua_transport_cid, tvb, *pOffset, 16, TRUE); *pOffset+=16;\r
141     proto_tree_add_item(tree, hf_opcua_transport_lifetime, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
142     proto_tree_add_item(tree, hf_opcua_transport_sbl, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
143     proto_tree_add_item(tree, hf_opcua_transport_rbl, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
144     parseString(tree, tvb, pOffset, hf_opcua_transport_endpoint);\r
145 }\r
146 \r
147 void parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)\r
148 {\r
149     addString(tree, hf_opcua_transport_sig, tvb, *pOffset, 4, tvb->real_data); *pOffset+=4;\r
150     proto_tree_add_item(tree, hf_opcua_transport_len, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
151     proto_tree_add_item(tree, hf_opcua_transport_cid, tvb, *pOffset, 16, TRUE); *pOffset+=16;\r
152     proto_tree_add_item(tree, hf_opcua_transport_rlifetime, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
153     proto_tree_add_item(tree, hf_opcua_transport_rsbl, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
154     proto_tree_add_item(tree, hf_opcua_transport_rrbl, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
155     parseString(tree, tvb, pOffset, hf_opcua_transport_altendpoint);\r
156 }\r
157 \r
158 void parseDisconnect(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)\r
159 {\r
160     addString(tree, hf_opcua_transport_sig, tvb, *pOffset, 4, tvb->real_data); *pOffset+=4;\r
161     proto_tree_add_item(tree, hf_opcua_transport_len, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
162     proto_tree_add_item(tree, hf_opcua_transport_cid, tvb, *pOffset, 16, TRUE); *pOffset+=16;\r
163 }\r
164 \r
165 void parseData(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)\r
166 {\r
167     proto_item *ti;\r
168     proto_tree *encobj_tree;\r
169     proto_tree *nodeid_tree;\r
170     int ServiceId = 0;\r
171 \r
172     addString(tree, hf_opcua_transport_sig, tvb, *pOffset, 4, tvb->real_data); *pOffset+=4;\r
173     proto_tree_add_item(tree, hf_opcua_transport_len, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
174     proto_tree_add_item(tree, hf_opcua_transport_cid, tvb, *pOffset, 16, TRUE); *pOffset+=16;\r
175     proto_tree_add_item(tree, hf_opcua_transport_rqid, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
176 \r
177     /* message data contains the security layer */\r
178     parseSecurityLayer(tree, tvb, pOffset);\r
179 \r
180     /* AT THE MOMENT NO SECURITY IS IMPLEMENTED IN UA.\r
181      * WE CAN JUST JUMP INTO THE APPLICATION LAYER DATA.\r
182      * THIS WILL CHAHNGE IN THE FUTURE. */\r
183 \r
184     /* add encodeable object subtree */\r
185     ti = proto_tree_add_text(tree, tvb, 0, -1, "Message : Encodeable Object");\r
186     encobj_tree = proto_item_add_subtree(ti, ett_opcua_extensionobject);\r
187 \r
188     /* add nodeid subtree */\r
189     ti = proto_tree_add_text(encobj_tree, tvb, 0, -1, "TypeId : ExpandedNodeId");\r
190     nodeid_tree = proto_item_add_subtree(ti, ett_opcua_nodeid);\r
191     ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset, "NodeId") - 1;\r
192 \r
193     dispatchService(encobj_tree, tvb, pOffset, ServiceId);\r
194 }\r
195 \r
196 void parseAbort(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)\r
197 {\r
198     addString(tree, hf_opcua_transport_sig, tvb, *pOffset, 4, tvb->real_data); *pOffset+=4;\r
199     proto_tree_add_item(tree, hf_opcua_transport_len, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
200     proto_tree_add_item(tree, hf_opcua_transport_cid, tvb, *pOffset, 16, TRUE); *pOffset+=16;\r
201     proto_tree_add_item(tree, hf_opcua_transport_rqid, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
202 }\r
203 \r
204 void parseError(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)\r
205 {\r
206     addString(tree, hf_opcua_transport_sig, tvb, *pOffset, 4, tvb->real_data); *pOffset+=4;\r
207     proto_tree_add_item(tree, hf_opcua_transport_len, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
208     proto_tree_add_item(tree, hf_opcua_transport_cid, tvb, *pOffset, 16, TRUE); *pOffset+=16;\r
209     proto_tree_add_item(tree, hf_opcua_transport_rqid, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
210     proto_tree_add_item(tree, hf_opcua_transport_status, tvb, *pOffset, 4, TRUE); *pOffset+=4;\r
211 }\r