aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/opcua/opcua.c
diff options
context:
space:
mode:
authorJaap Keuter <jaap.keuter@xs4all.nl>2009-04-06 18:30:04 +0000
committerJaap Keuter <jaap.keuter@xs4all.nl>2009-04-06 18:30:04 +0000
commit8ecf45961110d5783b7c99715b7c7cf05c5b41ed (patch)
tree926b3b5c94b33b4dbdca1083214be171806a0c9e /plugins/opcua/opcua.c
parent680cf63be8e8fc8f77de645f217d33e28cd61513 (diff)
From Gerhard Gappmeier:
This patch updates the plugin to fit the released OPCUA protocol version. svn path=/trunk/; revision=27974
Diffstat (limited to 'plugins/opcua/opcua.c')
-rw-r--r--plugins/opcua/opcua.c152
1 files changed, 89 insertions, 63 deletions
diff --git a/plugins/opcua/opcua.c b/plugins/opcua/opcua.c
index 0742b5137e..269fe329a5 100644
--- a/plugins/opcua/opcua.c
+++ b/plugins/opcua/opcua.c
@@ -26,6 +26,7 @@
#endif
#include <glib.h>
+#include <epan/prefs.h>
#include <epan/packet.h>
#include <epan/dissectors/packet-tcp.h>
#include "opcua_transport_layer.h"
@@ -40,11 +41,14 @@
/* forward reference */
static void dissect_opcua(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
static void dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
+void proto_reg_handoff_opcua(void);
/* declare parse function pointer */
typedef void (*FctParse)(proto_tree *tree, tvbuff_t *tvb, gint *pOffset);
static int proto_opcua = -1;
+static dissector_handle_t opcua_handle;
+static range_t *global_tcp_ports_opcua;
/** Official IANA registered port for OPC UA Binary Protocol. */
#define OPCUA_PORT 4840
@@ -58,13 +62,11 @@ enum MessageType
{
MSG_HELLO = 0,
MSG_ACKNOWLEDGE,
- MSG_DISCONNECT,
- MSG_DATA_LAST_CHUNK,
- MSG_DATA,
- MSG_ABORT,
MSG_ERROR,
- MSG_INVALID,
- MSG_UNKNOWN
+ MSG_MESSAGE,
+ MSG_OPENSECURECHANNEL,
+ MSG_CLOSESECURECHANNEL,
+ MSG_INVALID
};
/** OpcUa Transport Message Type Names */
@@ -72,13 +74,11 @@ static char* g_szMessageTypes[] =
{
"Hello message",
"Acknowledge message",
- "Disconnect message",
- "Data message, last chunk in message.",
- "Data message, further chunks must follow.",
- "Abort message",
"Error message",
- "Invalid message",
- "Unknown message"
+ "UA Secure Conversation Message",
+ "OpenSecureChannel message",
+ "CloseSecureChannel message",
+ "Invalid message"
};
@@ -95,11 +95,14 @@ static gint *ett[] =
*/
void proto_register_opcua(void)
{
+ module_t *opcua_module;
+
proto_opcua = proto_register_protocol(
"OpcUa Binary Protocol", /* name */
"OpcUa", /* short name */
"opcua" /* abbrev */
);
+
registerTransportLayerTypes(proto_opcua);
registerSecurityLayerTypes(proto_opcua);
registerApplicationLayerTypes(proto_opcua);
@@ -110,16 +113,15 @@ void proto_register_opcua(void)
registerFieldTypes(proto_opcua);
proto_register_subtree_array(ett, array_length(ett));
-}
-/** Register sub protocol.
- * For TCP port 4840.
- */
-void proto_reg_handoff_opcua(void)
-{
- dissector_handle_t opcua_handle;
- opcua_handle = create_dissector_handle(dissect_opcua, proto_opcua);
- dissector_add("tcp.port", OPCUA_PORT, opcua_handle);
+ range_convert_str(&global_tcp_ports_opcua, ep_strdup_printf("%u", OPCUA_PORT), 65535);
+
+ /* register user preferences */
+ opcua_module = prefs_register_protocol(proto_opcua, proto_reg_handoff_opcua);
+ prefs_register_range_preference(opcua_module, "tcp_ports",
+ "OPC UA TCP Ports",
+ "The TCP ports for the OPC UA TCP Binary Protocol",
+ &global_tcp_ports_opcua, 65535);
}
/** header length that is needed to compute
@@ -168,51 +170,41 @@ static void dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree
}
/* parse message type */
- if (tvb->real_data[0] == 'U' && tvb->real_data[1] == 'A')
+ if (tvb->real_data[0] == 'H' && tvb->real_data[1] == 'E' && tvb->real_data[2] == 'L')
+ {
+ msgtype = MSG_HELLO;
+ pfctParse = parseHello;
+ }
+ else if (tvb->real_data[0] == 'A' && tvb->real_data[1] == 'C' && tvb->real_data[2] == 'K')
+ {
+ msgtype = MSG_ACKNOWLEDGE;
+ pfctParse = parseAcknowledge;
+ }
+ else if (tvb->real_data[0] == 'E' && tvb->real_data[1] == 'R' && tvb->real_data[2] == 'R')
+ {
+ msgtype = MSG_ERROR;
+ pfctParse = parseError;
+ }
+ else if (tvb->real_data[0] == 'M' && tvb->real_data[1] == 'S' && tvb->real_data[2] == 'G')
+ {
+ msgtype = MSG_MESSAGE;
+ pfctParse = parseMessage;
+ }
+ else if (tvb->real_data[0] == 'O' && tvb->real_data[1] == 'P' && tvb->real_data[2] == 'N')
+ {
+ msgtype = MSG_OPENSECURECHANNEL;
+ pfctParse = parseOpenSecureChannel;
+ }
+ else if (tvb->real_data[0] == 'C' && tvb->real_data[1] == 'L' && tvb->real_data[2] == 'O')
{
- if (tvb->real_data[2] == 'T')
- {
- switch(tvb->real_data[3])
- {
- case 'H': msgtype = MSG_HELLO;
- pfctParse = parseHello;
- break;
- case 'A': msgtype = MSG_ACKNOWLEDGE;
- pfctParse = parseAcknowledge;
- break;
- case 'D': msgtype = MSG_DISCONNECT;
- pfctParse = parseDisconnect;
- break;
- default: msgtype = MSG_INVALID;
- break;
- }
- }
- else if (tvb->real_data[2] == 'M')
- {
- switch(tvb->real_data[3])
- {
- case 'G': msgtype = MSG_DATA_LAST_CHUNK;
- pfctParse = parseData;
- break;
- case 'C': msgtype = MSG_DATA;
- pfctParse = parseData;
- break;
- case 'A': msgtype = MSG_ABORT;
- pfctParse = parseAbort;
- break;
- case 'E': msgtype = MSG_ERROR;
- pfctParse = parseError;
- break;
- default: msgtype = MSG_INVALID;
- break;
- }
- }
+ msgtype = MSG_CLOSESECURECHANNEL;
+ pfctParse = parseCloseSecureChannel;
}
else
{
- msgtype = MSG_UNKNOWN;
+ msgtype = MSG_INVALID;
}
-
+
/* Clear out stuff in the info column */
if(check_col(pinfo->cinfo, COL_INFO))
{
@@ -232,10 +224,44 @@ static void dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree
/* call the transport message dissector */
(*pfctParse)(transport_tree, tvb, &offset);
-
}
-}
+}
+
+static void register_tcp_port(guint32 port)
+{
+ if (port != 0)
+ dissector_add("tcp.port", port, opcua_handle);
+}
+
+static void unregister_tcp_port(guint32 port)
+{
+ if (port != 0)
+ dissector_delete("tcp.port", port, opcua_handle);
+}
+
+void proto_reg_handoff_opcua(void)
+{
+ static gboolean opcua_initialized = FALSE;
+ static range_t *tcp_ports_opcua = NULL;
+ if(!opcua_initialized)
+ {
+ opcua_handle = create_dissector_handle(dissect_opcua, proto_opcua);
+ opcua_initialized = TRUE;
+ }
+ else
+ {
+ /* clean up ports and their lists */
+ if (tcp_ports_opcua != NULL)
+ {
+ range_foreach(tcp_ports_opcua, unregister_tcp_port);
+ g_free(tcp_ports_opcua);
+ }
+ }
+ /* If we now have a PDU tree, register for the port or ports we have */
+ tcp_ports_opcua = range_copy(global_tcp_ports_opcua);
+ range_foreach(tcp_ports_opcua, register_tcp_port);
+}