Don't include config.h in header files.
[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 #include <string.h>
34 #include <epan/emem.h>
35
36 void dispatchService(proto_tree *tree, tvbuff_t *tvb, gint *pOffset, int ServiceId);
37
38 static int hf_opcua_transport_type = -1;
39 static int hf_opcua_transport_chunk = -1;
40 static int hf_opcua_transport_size = -1;
41 static int hf_opcua_transport_ver = -1;
42 static int hf_opcua_transport_scid = -1;
43 static int hf_opcua_transport_lifetime = -1;
44 static int hf_opcua_transport_rbs = -1;
45 static int hf_opcua_transport_sbs = -1;
46 static int hf_opcua_transport_mms = -1;
47 static int hf_opcua_transport_mcc = -1;
48 static int hf_opcua_transport_endpoint = -1;
49 static int hf_opcua_transport_error = -1;
50 static int hf_opcua_transport_reason = -1;
51 static int hf_opcua_transport_spu = -1;
52 static int hf_opcua_transport_scert = -1;
53 static int hf_opcua_transport_rcthumb = -1;
54 static int hf_opcua_transport_seq = -1;
55 static int hf_opcua_transport_rqid = -1;
56 extern gint ett_opcua_nodeid;
57
58 /** subtree types */
59 extern gint ett_opcua_extensionobject;
60
61 /** Register transport layer types. */
62 void registerTransportLayerTypes(int proto)
63 {
64     static hf_register_info hf[] =
65     {
66         { &hf_opcua_transport_type,
67         /* full name  ,           abbreviation  ,       type     , display  , strings, bitmask, blurb, id, parent, ref_count, bitshift */
68         {  "Message Type",        "transport.type",     FT_STRING, BASE_NONE, NULL,    0x0,     NULL,    HFILL }
69         },
70         { &hf_opcua_transport_chunk,
71         {  "Chunk Type",          "transport.chunk",    FT_STRING, BASE_NONE, NULL,    0x0,     NULL,    HFILL }
72         },
73         { &hf_opcua_transport_size,
74         {  "Message Size",        "transport.size",     FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
75         },
76         { &hf_opcua_transport_ver,
77         {  "Version",             "transport.ver",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
78         },
79         { &hf_opcua_transport_scid,
80         {  "SecureChannelId",     "transport.scid",     FT_UINT32, BASE_DEC, NULL, 0x0,    NULL,    HFILL }
81         },
82         { &hf_opcua_transport_lifetime,
83         {  "Lifetime",            "transport.lifetime", FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
84         },
85         { &hf_opcua_transport_rbs,
86         {  "ReceiveBufferSize",   "transport.rbs",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
87         },
88         { &hf_opcua_transport_sbs,
89         {  "SendBufferSize",      "transport.sbs",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
90         },
91         { &hf_opcua_transport_mms,
92         {  "MaxMessageSize",      "transport.mms",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
93         },
94         { &hf_opcua_transport_mcc,
95         {  "MaxChunkCount",       "transport.mcc",      FT_UINT32, BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
96         },
97         { &hf_opcua_transport_endpoint,
98         {  "EndPointUrl",         "transport.endpoint", FT_STRING, BASE_NONE, NULL, 0x0,    NULL,    HFILL }
99         },
100         { &hf_opcua_transport_error,
101         {  "Error",               "transport.error",    FT_UINT32, BASE_HEX,  NULL, 0x0,    NULL,    HFILL }
102         },
103         { &hf_opcua_transport_reason,
104         {  "Reason",              "transport.reason",   FT_STRING, BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
105         },
106     /*    { &hf_opcua_transport_spul,
107         {  "SecurityPolicyUriLength", "transport.spul", FT_UINT32, BASE_DEC,  NULL, 0x0,    "",    HFILL }
108         },*/
109         { &hf_opcua_transport_spu,
110         {  "SecurityPolicyUri",   "security.spu",      FT_STRING, BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
111         },
112         { &hf_opcua_transport_scert,
113         {  "SenderCertificate",   "security.scert",    FT_BYTES,  BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
114         },
115         { &hf_opcua_transport_rcthumb,
116         {  "ReceiverCertificateThumbprint", "security.rcthumb", FT_BYTES,  BASE_NONE,  NULL, 0x0,    NULL,    HFILL }
117         },
118         { &hf_opcua_transport_seq,
119         {  "SequenceNumber", "security.seq",           FT_UINT32,  BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
120         },
121         { &hf_opcua_transport_rqid,
122         {  "RequestId", "security.rqid",                FT_UINT32,  BASE_DEC,  NULL, 0x0,    NULL,    HFILL }
123         },
124     };
125
126     proto_register_field_array(proto, hf, array_length(hf));
127 }
128
129 /* Transport Layer: message parsers */
130 void parseHello(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
131 {
132     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
133     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
134     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
135     proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, TRUE); *pOffset+=4;
136     proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, TRUE); *pOffset+=4;
137     proto_tree_add_item(tree, hf_opcua_transport_sbs, tvb, *pOffset, 4, TRUE); *pOffset+=4;
138     proto_tree_add_item(tree, hf_opcua_transport_mms, tvb, *pOffset, 4, TRUE); *pOffset+=4;
139     proto_tree_add_item(tree, hf_opcua_transport_mcc, tvb, *pOffset, 4, TRUE); *pOffset+=4;
140     parseString(tree, tvb, pOffset, hf_opcua_transport_endpoint);
141 }
142
143 void parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
144 {
145     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
146     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
147     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
148     proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, TRUE); *pOffset+=4;
149     proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, TRUE); *pOffset+=4;
150     proto_tree_add_item(tree, hf_opcua_transport_sbs, tvb, *pOffset, 4, TRUE); *pOffset+=4;
151     proto_tree_add_item(tree, hf_opcua_transport_mms, tvb, *pOffset, 4, TRUE); *pOffset+=4;
152     proto_tree_add_item(tree, hf_opcua_transport_mcc, tvb, *pOffset, 4, TRUE); *pOffset+=4;
153 }
154
155 void 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, TRUE); *pOffset+=1;
159     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
160     proto_tree_add_item(tree, hf_opcua_transport_error, tvb, *pOffset, 4, TRUE); *pOffset+=4;
161     parseString(tree, tvb, pOffset, hf_opcua_transport_reason);
162 }
163
164 void parseMessage(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
165 {
166     proto_item *ti;
167     proto_tree *encobj_tree;
168     proto_tree *nodeid_tree;
169     int ServiceId = 0;
170
171     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
172     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
173     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
174     proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
175
176     /* message data contains the security layer */
177     parseSecurityLayer(tree, tvb, pOffset);
178
179     /* AT THE MOMENT NO SECURITY IS IMPLEMENTED IN UA.
180      * WE CAN JUST JUMP INTO THE APPLICATION LAYER DATA.
181      * THIS WILL CHAHNGE IN THE FUTURE. */
182
183     /* add encodeable object subtree */
184     ti = proto_tree_add_text(tree, tvb, 0, -1, "Message : Encodeable Object");
185     encobj_tree = proto_item_add_subtree(ti, ett_opcua_extensionobject);
186
187     /* add nodeid subtree */
188     ti = proto_tree_add_text(encobj_tree, tvb, 0, -1, "TypeId : ExpandedNodeId");
189     nodeid_tree = proto_item_add_subtree(ti, ett_opcua_nodeid);
190     ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset, "NodeId");
191
192     dispatchService(encobj_tree, tvb, pOffset, ServiceId);
193 }
194
195 void parseOpenSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
196 {
197     proto_item *ti;
198     proto_tree *encobj_tree;
199     proto_tree *nodeid_tree;
200     int ServiceId = 0;
201     
202     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
203     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
204     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
205     proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
206     parseString(tree, tvb, pOffset, hf_opcua_transport_spu);
207     parseByteString(tree, tvb, pOffset, hf_opcua_transport_scert);
208     parseByteString(tree, tvb, pOffset, hf_opcua_transport_rcthumb);
209     proto_tree_add_item(tree, hf_opcua_transport_seq, tvb, *pOffset, 4, TRUE); *pOffset+=4;
210     proto_tree_add_item(tree, hf_opcua_transport_rqid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
211     
212     /* add encodeable object subtree */
213     ti = proto_tree_add_text(tree, tvb, 0, -1, "Message : Encodeable Object");
214     encobj_tree = proto_item_add_subtree(ti, ett_opcua_extensionobject);
215
216     /* add nodeid subtree */
217     ti = proto_tree_add_text(encobj_tree, tvb, 0, -1, "TypeId : ExpandedNodeId");
218     nodeid_tree = proto_item_add_subtree(ti, ett_opcua_nodeid);
219     ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset, "NodeId");
220
221     dispatchService(encobj_tree, tvb, pOffset, ServiceId);
222 }
223
224 void parseCloseSecureChannel(proto_tree *tree, tvbuff_t *tvb, gint *pOffset)
225 {
226     proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, TRUE); *pOffset+=3;
227     proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, TRUE); *pOffset+=1;
228     proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, TRUE); *pOffset+=4;
229     proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, TRUE); *pOffset+=4;
230 }
231