Convert plugin files proto_tree_add_item() 'encoding' arg for field types FT_STRING...
[obnox/wireshark/wip.git] / plugins / opcua / opcua_transport_layer.c
1 /******************************************************************************
2 ** $Id$
3 **
4 ** Copyright (C) 2006-2009 ascolab GmbH. All Rights Reserved.
5 ** Web: http://www.ascolab.com
6 ** 
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 ** 
12 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14 ** 
15 ** Project: OpcUa Wireshark Plugin
16 **
17 ** Description: OpcUa Transport Layer Decoder.
18 **
19 ** Author: Gerhard Gappmeier <gerhard.gappmeier@ascolab.com>
20 ** Last change by: $Author: gergap $
21 **
22 ******************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #include <glib.h>
29 #include <epan/packet.h>
30 #include "opcua_security_layer.h"
31 #include "opcua_application_layer.h"
32 #include "opcua_simpletypes.h"
33
34 void dispatchService(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int ServiceId);
35
36 static int hf_opcua_transport_type = -1;
37 static int hf_opcua_transport_chunk = -1;
38 static int hf_opcua_transport_size = -1;
39 static int hf_opcua_transport_ver = -1;
40 static int hf_opcua_transport_scid = -1;
41 static int hf_opcua_transport_lifetime = -1;
42 static int hf_opcua_transport_rbs = -1;
43 static int hf_opcua_transport_sbs = -1;
44 static int hf_opcua_transport_mms = -1;
45 static int hf_opcua_transport_mcc = -1;
46 static int hf_opcua_transport_endpoint = -1;
47 static int hf_opcua_transport_error = -1;
48 static int hf_opcua_transport_reason = -1;
49 static int hf_opcua_transport_spu = -1;
50 static int hf_opcua_transport_scert = -1;
51 static int hf_opcua_transport_rcthumb = -1;
52 static int hf_opcua_transport_seq = -1;
53 static int hf_opcua_transport_rqid = -1;
54 extern gint ett_opcua_nodeid;
55
56 /** subtree types */
57 extern gint ett_opcua_extensionobject;
58
59 /** Register transport layer types. */
60 void registerTransportLayerTypes(int proto)
61 {
62     static hf_register_info hf[] =
63     {
64         { &hf_opcua_transport_type,
65         /* full name  ,           abbreviation  ,       type     , display  , strings, bitmask, blurb, id, parent, ref_count, bitshift */
66         {  "Message Type",        "transport.type",     FT_STRING, BASE_NONE, NULL,    0x0,     NULL,    HFILL }
67         },
68         { &hf_opcua_transport_chunk,
69         {  "Chunk Type",          "transport.chunk",    FT_STRING, BASE_NONE, NULL,    0x0,     NULL,    HFILL }
70         },
71         { &hf_opcua_transport_size,
72         {  "Message Size",        "transport.size",     FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
73         },
74         { &hf_opcua_transport_ver,
75         {  "Version",             "transport.ver",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
76         },
77         { &hf_opcua_transport_scid,
78         {  "SecureChannelId",     "transport.scid",     FT_UINT32, BASE_DEC, NULL, 0x0,    NULL,    HFILL }
79         },
80         { &hf_opcua_transport_lifetime,
81         {  "Lifetime",            "transport.lifetime", FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
82         },
83         { &hf_opcua_transport_rbs,
84         {  "ReceiveBufferSize",   "transport.rbs",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
85         },
86         { &hf_opcua_transport_sbs,
87         {  "SendBufferSize",      "transport.sbs",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
88         },
89         { &hf_opcua_transport_mms,
90         {  "MaxMessageSize",      "transport.mms",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
91         },
92         { &hf_opcua_transport_mcc,
93         {  "MaxChunkCount",       "transport.mcc",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
94         },
95         { &hf_opcua_transport_endpoint,
96         {  "EndPointUrl",         "transport.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,    NULL,    HFILL }
97         },
98         { &hf_opcua_transport_error,
99         {  "Error",               "transport.error",    FT_UINT32, BASE_HEX,  NULL, 0x0,    NULL,    HFILL }
100         },
101         { &hf_opcua_transport_reason,
102         {  "Reason",              "transport.reason",   FT_STRING, BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
103         },
104     /*    { &hf_opcua_transport_spul,
105         {  "SecurityPolicyUriLength", "transport.spul", FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }
106         },*/
107         { &hf_opcua_transport_spu,
108         {  "SecurityPolicyUri",   "security.spu",      FT_STRING, BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
109         },
110         { &hf_opcua_transport_scert,
111         {  "SenderCertificate",   "security.scert",    FT_BYTES,  BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
112         },
113         { &hf_opcua_transport_rcthumb,
114         {  "ReceiverCertificateThumbprint", "security.rcthumb", FT_BYTES,  BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
115         },
116         { &hf_opcua_transport_seq,
117         {  "SequenceNumber", "security.seq",           FT_UINT32,  BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
118         },
119         { &hf_opcua_transport_rqid,
120         {  "RequestId", "security.rqid",                FT_UINT32,  BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
121         },
122     };
123
124     proto_register_field_array(proto, hf, array_length(hf));
125 }
126
127 /* Transport Layer: message parsers */
128 int parseHello(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
129 {
130     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
131     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1;
132     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
133     proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
134     proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
135     proto_tree_add_item(tree, hf_opcua_transport_sbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
136     proto_tree_add_item(tree, hf_opcua_transport_mms, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
137     proto_tree_add_item(tree, hf_opcua_transport_mcc, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
138     parseString(tree, tvb, pOffset, hf_opcua_transport_endpoint);
139     return -1;
140 }
141
142 int parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
143 {
144     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
145     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1;
146     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
147     proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
148     proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
149     proto_tree_add_item(tree, hf_opcua_transport_sbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
150     proto_tree_add_item(tree, hf_opcua_transport_mms, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
151     proto_tree_add_item(tree, hf_opcua_transport_mcc, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
152     return -1;
153 }
154
155 int parseError(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
156 {
157     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
158     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1;
159     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
160     proto_tree_add_item(tree, hf_opcua_transport_error, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
161     parseString(tree, tvb, pOffset, hf_opcua_transport_reason);
162     return -1;
163 }
164
165 int parseMessage(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
166 {
167     proto_item *ti;
168     proto_tree *encobj_tree;
169     proto_tree *nodeid_tree;
170     int ServiceId = 0;
171
172     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
173     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1;
174     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
175     proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
176
177     /* message data contains the security layer */
178     parseSecurityLayer(tree, tvb, pOffset);
179
180     /* AT THE MOMENT NO SECURITY IS IMPLEMENTED IN UA.
181      * WE CAN JUST JUMP INTO THE APPLICATION LAYER DATA.
182      * THIS WILL CHAHNGE IN THE FUTURE. */
183
184     /* add encodeable object subtree */
185     ti = proto_tree_add_text(tree, tvb, 0, -1, "Message : Encodeable Object");
186     encobj_tree = proto_item_add_subtree(ti, ett_opcua_extensionobject);
187
188     /* add nodeid subtree */
189     ti = proto_tree_add_text(encobj_tree, tvb, 0, -1, "TypeId : ExpandedNodeId");
190     nodeid_tree = proto_item_add_subtree(ti, ett_opcua_nodeid);
191     ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset);
192
193     dispatchService(encobj_tree, tvb, pOffset, ServiceId);
194     return ServiceId;
195 }
196
197 int parseOpenSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
198 {
199     proto_item *ti;
200     proto_tree *encobj_tree;
201     proto_tree *nodeid_tree;
202     int ServiceId = 0;
203     
204     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
205     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1;
206     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
207     proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
208     parseString(tree, tvb, pOffset, hf_opcua_transport_spu);
209     parseByteString(tree, tvb, pOffset, hf_opcua_transport_scert);
210     parseByteString(tree, tvb, pOffset, hf_opcua_transport_rcthumb);
211     proto_tree_add_item(tree, hf_opcua_transport_seq, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
212     proto_tree_add_item(tree, hf_opcua_transport_rqid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
213     
214     /* add encodeable object subtree */
215     ti = proto_tree_add_text(tree, tvb, 0, -1, "Message : Encodeable Object");
216     encobj_tree = proto_item_add_subtree(ti, ett_opcua_extensionobject);
217
218     /* add nodeid subtree */
219     ti = proto_tree_add_text(encobj_tree, tvb, 0, -1, "TypeId : ExpandedNodeId");
220     nodeid_tree = proto_item_add_subtree(ti, ett_opcua_nodeid);
221     ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset);
222
223     dispatchService(encobj_tree, tvb, pOffset, ServiceId);
224     return -1;
225 }
226
227 int parseCloseSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
228 {
229     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
230     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1;
231     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
232     proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4;
233     return -1;
234 }
235