diff options
author | Jaap Keuter <jaap.keuter@xs4all.nl> | 2009-04-06 18:30:04 +0000 |
---|---|---|
committer | Jaap Keuter <jaap.keuter@xs4all.nl> | 2009-04-06 18:30:04 +0000 |
commit | 8ecf45961110d5783b7c99715b7c7cf05c5b41ed (patch) | |
tree | 926b3b5c94b33b4dbdca1083214be171806a0c9e /plugins/opcua/opcua.c | |
parent | 680cf63be8e8fc8f77de645f217d33e28cd61513 (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.c | 152 |
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); +} |