/* Globals for Modbus/TCP Preferences */
static gboolean mbtcp_desegment = TRUE;
static guint global_mbus_tcp_port = PORT_MBTCP; /* Port 502, by default */
+static guint global_mbus_udp_port = PORT_MBTCP; /* Port 502, by default */
/* Globals for Modbus RTU over TCP Preferences */
static gboolean mbrtu_desegment = TRUE;
-static guint global_mbus_rtu_port = PORT_MBRTU; /* 0, by default */
+static guint global_mbus_tcp_rtu_port = PORT_MBRTU; /* 0, by default */
+static guint global_mbus_udp_rtu_port = PORT_MBRTU; /* 0, by default */
static gboolean mbrtu_crc = FALSE;
/* Globals for Modbus Preferences */
static gint global_mbus_register_format = MODBUS_PREF_REGISTER_FORMAT_UINT16;
static int
-classify_mbtcp_packet(packet_info *pinfo)
+classify_mbtcp_packet(packet_info *pinfo, guint port)
{
/* see if nature of packets can be derived from src/dst ports */
/* if so, return as found */
/* the Modbus/TCP transaction ID for each pair of messages would allow for detection based on a new seq. number. */
/* Otherwise, we can stick with this method; a configurable port option has been added to allow for usage of */
/* user ports either than the default of 502. */
- if (( pinfo->srcport == global_mbus_tcp_port ) && ( pinfo->destport != global_mbus_tcp_port ))
+ if (( pinfo->srcport == port ) && ( pinfo->destport != port ))
return RESPONSE_PACKET;
- if (( pinfo->srcport != global_mbus_tcp_port ) && ( pinfo->destport == global_mbus_tcp_port ))
+ if (( pinfo->srcport != port ) && ( pinfo->destport == port ))
return QUERY_PACKET;
/* else, cannot classify */
}
static int
-classify_mbrtu_packet(packet_info *pinfo, tvbuff_t *tvb)
+classify_mbrtu_packet(packet_info *pinfo, tvbuff_t *tvb, guint port)
{
guint8 func, len;
/* see if nature of packets can be derived from src/dst ports */
/* if so, return as found */
- if (( pinfo->srcport == global_mbus_rtu_port ) && ( pinfo->destport != global_mbus_rtu_port ))
+ if (( pinfo->srcport == port ) && ( pinfo->destport != port ))
return RESPONSE_PACKET;
- if (( pinfo->srcport != global_mbus_rtu_port ) && ( pinfo->destport == global_mbus_rtu_port ))
+ if (( pinfo->srcport != port ) && ( pinfo->destport == port ))
return QUERY_PACKET;
/* Code to dissect Modbus/TCP packets */
static int
-dissect_mbtcp_pdu_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto)
+dissect_mbtcp_pdu_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int proto, guint port)
{
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *mi;
offset = 0;
/* "Request" or "Response" */
- packet_type = classify_mbtcp_packet(pinfo);
+ packet_type = classify_mbtcp_packet(pinfo, port);
switch ( packet_type ) {
case QUERY_PACKET :
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Modbus/TCP");
col_clear(pinfo->cinfo, COL_INFO);
- return dissect_mbtcp_pdu_common(tvb, pinfo, tree, proto_mbtcp);
+ return dissect_mbtcp_pdu_common(tvb, pinfo, tree, proto_mbtcp, global_mbus_tcp_port);
}
-/* Code to dissect Modbus RTU over TCP packets */
+/* Code to dissect Modbus RTU */
static int
-dissect_mbrtu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+dissect_mbrtu_pdu_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint port)
{
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *mi;
offset = 0;
/* "Request" or "Response" */
- packet_type = classify_mbrtu_packet(pinfo, tvb);
+ packet_type = classify_mbrtu_packet(pinfo, tvb, port);
switch ( packet_type ) {
case QUERY_PACKET :
return tvb_captured_length(tvb);
}
+/* Code to dissect Modbus RTU over TCP packets */
+static int
+dissect_mbrtu_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ return dissect_mbrtu_pdu_common(tvb, pinfo, tree, global_mbus_tcp_rtu_port);
+}
/* Return length of Modbus/TCP message */
static guint
the rest can be added as pcap examples are made available */
/* Determine "Query" or "Response" */
- packet_type = classify_mbrtu_packet(pinfo, tvb);
+ packet_type = classify_mbrtu_packet(pinfo, tvb, global_mbus_tcp_rtu_port);
switch ( packet_type ) {
case QUERY_PACKET :
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Modbus/UDP");
col_clear(pinfo->cinfo, COL_INFO);
- return dissect_mbtcp_pdu_common(tvb, pinfo, tree, proto_mbudp);
+ return dissect_mbtcp_pdu_common(tvb, pinfo, tree, proto_mbudp, global_mbus_udp_port);
}
/* Code to dissect Modbus RTU over TCP messages */
}
static int
-dissect_mbrtu_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+dissect_mbrtu_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
/* Make sure there's at least enough data to determine it's a Modbus packet */
if (tvb_reported_length(tvb) < 5)
return 0;
- return dissect_mbrtu_pdu(tvb, pinfo, tree, data);
+ return dissect_mbrtu_pdu_common(tvb, pinfo, tree, global_mbus_udp_rtu_port);
}
}
/* Build a new tvb containing just the data payload */
- next_tvb = tvb_new_subset(tvb, payload_start, payload_len, reported_len);
+ next_tvb = tvb_new_subset_length_caplen(tvb, payload_start, payload_len, reported_len);
switch ( function_code ) {
return tvb_captured_length(tvb);
}
+static void
+apply_mbtcp_prefs(void)
+{
+ /* Modbus/RTU uses the port preference to determine request/response */
+ global_mbus_tcp_port = prefs_get_uint_value("mbtcp", "tcp.port");
+ global_mbus_udp_port = prefs_get_uint_value("mbudp", "udp.port");
+}
+
+static void
+apply_mbrtu_prefs(void)
+{
+ /* Modbus/RTU uses the port preference to determine request/response */
+ global_mbus_tcp_rtu_port = prefs_get_uint_value("mbrtu", "tcp.port");
+ global_mbus_udp_rtu_port = prefs_get_uint_value("mbrtu", "udp.port");
+}
+
/* Register the protocol with Wireshark */
void
proto_register_modbus(void)
mbudp_handle = register_dissector("mbudp", dissect_mbudp, proto_mbudp);
/* Registering subdissectors table */
- modbus_data_dissector_table = register_dissector_table("modbus.data", "Modbus Data", proto_modbus, FT_STRING, BASE_NONE, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE);
- modbus_dissector_table = register_dissector_table("mbtcp.prot_id", "Modbus/TCP protocol identifier", proto_mbtcp, FT_UINT16, BASE_DEC, DISSECTOR_TABLE_NOT_ALLOW_DUPLICATE);
+ modbus_data_dissector_table = register_dissector_table("modbus.data", "Modbus Data", proto_modbus, FT_STRING, BASE_NONE);
+ modbus_dissector_table = register_dissector_table("mbtcp.prot_id", "Modbus/TCP protocol identifier", proto_mbtcp, FT_UINT16, BASE_DEC);
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_mbtcp, mbtcp_hf, array_length(mbtcp_hf));
/* Register required preferences for Modbus Protocol variants */
- mbtcp_module = prefs_register_protocol(proto_mbtcp, proto_reg_handoff_mbtcp);
- mbrtu_module = prefs_register_protocol(proto_mbrtu, proto_reg_handoff_mbrtu);
+ mbtcp_module = prefs_register_protocol(proto_mbtcp, apply_mbtcp_prefs);
+ mbrtu_module = prefs_register_protocol(proto_mbrtu, apply_mbrtu_prefs);
modbus_module = prefs_register_protocol(proto_modbus, NULL);
/* Modbus RTU Preference - Desegment, defaults to TRUE for TCP desegmentation */
"Whether the Modbus RTU dissector should desegment all messages spanning multiple TCP segments",
&mbtcp_desegment);
- /* Modbus/TCP Preference - Default TCP Port, allows for "user" port either than 502. */
- prefs_register_uint_preference(mbtcp_module, "tcp.port", "Modbus/TCP Port",
- "Set the TCP port for Modbus/TCP packets (if other"
- " than the default of 502)",
- 10, &global_mbus_tcp_port);
-
/* Modbus RTU Preference - Desegment, defaults to TRUE for TCP desegmentation */
prefs_register_bool_preference(mbrtu_module, "desegment",
"Desegment all Modbus RTU packets spanning multiple TCP segments",
"Whether to validate the CRC",
&mbrtu_crc);
- /* Modbus RTU Preference - Default TCP Port, defaults to zero, allows custom user port. */
- prefs_register_uint_preference(mbrtu_module, "tcp.port", "Modbus RTU Port",
- "Set the TCP/UDP port for encapsulated Modbus RTU packets",
- 10, &global_mbus_rtu_port);
-
/* Modbus Preference - Holding/Input Register format, this allows for deeper dissection of response data */
prefs_register_enum_preference(modbus_module, "mbus_register_format",
"Holding/Input Register Format",
"Register Format",
&global_mbus_register_format,
mbus_register_format,
- TRUE);
+ FALSE);
/* Obsolete Preferences */
prefs_register_obsolete_preference(mbtcp_module, "mbus_register_addr_type");
void
proto_reg_handoff_mbtcp(void)
{
- static unsigned int mbtcp_port;
-
- /* Make sure to use Modbus/TCP Preferences field to determine default TCP port */
- if(mbtcp_port != 0 && mbtcp_port != global_mbus_tcp_port){
- dissector_delete_uint("tcp.port", mbtcp_port, mbtcp_handle);
- dissector_delete_uint("udp.port", mbtcp_port, mbudp_handle);
- }
-
- if(global_mbus_tcp_port != 0 && mbtcp_port != global_mbus_tcp_port) {
- dissector_add_uint("tcp.port", global_mbus_tcp_port, mbtcp_handle);
- dissector_add_uint("udp.port", global_mbus_tcp_port, mbudp_handle);
- }
-
- mbtcp_port = global_mbus_tcp_port;
+ dissector_add_uint_with_preference("tcp.port", PORT_MBTCP, mbtcp_handle);
+ dissector_add_uint_with_preference("udp.port", PORT_MBTCP, mbudp_handle);
dissector_add_uint("mbtcp.prot_id", MODBUS_PROTOCOL_ID, modbus_handle);
void
proto_reg_handoff_mbrtu(void)
{
- static unsigned int mbrtu_port = 0;
dissector_handle_t mbrtu_udp_handle = create_dissector_handle(dissect_mbrtu_udp, proto_mbrtu);
/* Make sure to use Modbus RTU Preferences field to determine default TCP port */
-
- if(mbrtu_port != 0 && mbrtu_port != global_mbus_rtu_port){
- dissector_delete_uint("tcp.port", mbrtu_port, mbrtu_handle);
- dissector_delete_uint("udp.port", mbrtu_port, mbrtu_udp_handle);
- }
-
- if(global_mbus_rtu_port != 0 && mbrtu_port != global_mbus_rtu_port) {
- dissector_add_uint("tcp.port", global_mbus_rtu_port, mbrtu_handle);
- dissector_add_uint("udp.port", global_mbus_rtu_port, mbrtu_udp_handle);
- }
-
- mbrtu_port = global_mbus_rtu_port;
+ dissector_add_for_decode_as_with_preference("udp.port", mbrtu_udp_handle);
+ dissector_add_for_decode_as_with_preference("tcp.port", mbrtu_handle);
dissector_add_uint("mbtcp.prot_id", MODBUS_PROTOCOL_ID, modbus_handle);
dissector_add_for_decode_as("rtacser.data", mbrtu_handle);
+ dissector_add_for_decode_as("usb.device", mbrtu_handle);
+ dissector_add_for_decode_as("usb.product", mbrtu_handle);
+ dissector_add_for_decode_as("usb.protocol", mbrtu_handle);
}