Replace enumerated preference for choosing subdissector with a subdissector table and Decode As functionality.

This makes it much easier for other subdissectors (and plugins) to associate themselves with CAN.

Change-Id: I49dd832af51651d0c91f9850c100e544d178b8c4
Reviewed-on: https://code.wireshark.org/review/7734
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Michael Mann 2015-03-18 07:59:05 -04:00
parent da3e4f92d5
commit f7b1678b12
4 changed files with 63 additions and 54 deletions

View File

@ -26,6 +26,7 @@
#include <epan/packet.h>
void proto_register_canopen(void);
void proto_reg_handoff_canopen(void);
/* Initialize the protocol and registered fields */
static int proto_canopen = -1;
@ -1376,12 +1377,19 @@ proto_register_canopen(void)
"CANOPEN",
"canopen");
new_register_dissector("canopen", dissect_canopen, proto_canopen);
proto_register_field_array(proto_canopen, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_canopen(void)
{
dissector_handle_t canopen_handle;
canopen_handle = new_create_dissector_handle( dissect_canopen, proto_canopen );
dissector_add_for_decode_as("can.subdissector", canopen_handle );
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*

View File

@ -35,6 +35,7 @@
#include "packet-cip.h"
void proto_register_devicenet(void);
void proto_reg_handoff_devicenet(void);
#define DEVICENET_CANID_MASK 0x7FF
#define MESSAGE_GROUP_1_ID 0x3FF
@ -428,6 +429,10 @@ static int dissect_devicenet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
DISSECTOR_ASSERT(data);
can_id = *((struct can_identifier*)data);
/* XXX - Not sure this is correct. But the capture provided in
* bug 8564 provides CAN ID in little endian format, so this makes it work */
can_id.id = GUINT32_SWAP_LE_BE(can_id.id);
if (can_id.id & (~DEVICENET_CANID_MASK))
{
/* Not for us */
@ -1029,8 +1034,6 @@ void proto_register_devicenet(void)
expert_devicenet = expert_register_protocol(proto_devicenet);
expert_register_field_array(expert_devicenet, ei, array_length(ei));
new_register_dissector("devicenet", dissect_devicenet, proto_devicenet);
devicenet_address_type = address_type_dissector_register("AT_DEVICENET", "DeviceNet Address", devicenet_addr_to_str, devicenet_addr_str_len, NULL, devicenet_addr_len, NULL, NULL);
devicenet_module = prefs_register_protocol(proto_devicenet, NULL);
@ -1056,6 +1059,15 @@ void proto_register_devicenet(void)
devicenet_uat);
}
void
proto_reg_handoff_devicenet(void)
{
dissector_handle_t devicenet_handle;
devicenet_handle = new_create_dissector_handle( dissect_devicenet, proto_devicenet );
dissector_add_for_decode_as("can.subdissector", devicenet_handle );
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*

View File

@ -29,6 +29,7 @@
#include <epan/to_str-int.h>
void proto_register_j1939(void);
void proto_reg_handoff_j1939(void);
#define J1939_CANID_MASK 0x1FFFFFFF
#define J1939_11BIT_ID 0x000003FF
@ -347,13 +348,20 @@ void proto_register_j1939(void)
proto_register_field_array(proto_j1939, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
new_register_dissector("j1939", dissect_j1939, proto_j1939);
subdissector_pgn_table = register_dissector_table("j1939.pgn", "PGN Handle", FT_UINT32, BASE_DEC);
j1939_address_type = address_type_dissector_register("AT_J1939", "J1939 Address", J1939_addr_to_str, J1939_addr_str_len, J1939_col_filter_str, J1939_addr_len, NULL, NULL);
}
void
proto_reg_handoff_j1939(void)
{
dissector_handle_t j1939_handle;
j1939_handle = new_create_dissector_handle( dissect_j1939, proto_j1939 );
dissector_add_for_decode_as("can.subdissector", j1939_handle );
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*

View File

@ -29,6 +29,7 @@
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/decode_as.h>
#include <wiretap/wtap.h>
#include "packet-sll.h"
@ -58,9 +59,6 @@ static gint ett_can = -1;
static int proto_can = -1;
static dissector_handle_t data_handle;
static dissector_handle_t canopen_handle;
static dissector_handle_t devicenet_handle;
static dissector_handle_t j1939_handle;
#define LINUX_CAN_STD 0
#define LINUX_CAN_EXT 1
@ -70,13 +68,6 @@ static dissector_handle_t j1939_handle;
#define CAN_LEN_OFFSET 4
#define CAN_DATA_OFFSET 8
typedef enum {
CAN_DATA_DISSECTOR = 1,
CAN_CANOPEN_DISSECTOR = 2,
CAN_DEVICENET_DISSECTOR = 3,
CAN_J1939_DISSECTOR = 4
} Dissector_Option;
/* Structure that gets passed between dissectors. Since it's just a simple 32-bit
value, no sense in creating a header file for it. Just expect subdissectors
to provide their own.
@ -86,15 +77,7 @@ struct can_identifier
guint32 id;
};
static const enum_val_t can_high_level_protocol_dissector_options[] = {
{ "raw", "Raw data (no further dissection)", CAN_DATA_DISSECTOR },
{ "CANopen", "CANopen protocol", CAN_CANOPEN_DISSECTOR },
{ "DeviceNet", "DeviceNet protocol", CAN_DEVICENET_DISSECTOR },
{ "J1939", "J1939 protocol", CAN_J1939_DISSECTOR },
{ NULL, NULL, 0 }
};
static guint can_high_level_protocol_dissector = CAN_DATA_DISSECTOR;
static dissector_table_t subdissector_table;
static const value_string frame_type_vals[] =
{
@ -105,6 +88,16 @@ static const value_string frame_type_vals[] =
{ 0, NULL }
};
static void can_prompt(packet_info *pinfo _U_, gchar* result)
{
g_snprintf(result, MAX_DECODE_AS_PROMPT_LEN, "Next level protocol as");
}
static gpointer can_value(packet_info *pinfo _U_)
{
return 0;
}
static void
dissect_socketcan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@ -157,24 +150,11 @@ dissect_socketcan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
next_tvb = tvb_new_subset_length(tvb, CAN_DATA_OFFSET, frame_len);
switch (can_high_level_protocol_dissector)
/* Functionality for choosing subdissector is controlled through Decode As as CAN doesn't
have a unique identifier to determine subdissector */
if (!dissector_try_uint_new(subdissector_table, 0, next_tvb, pinfo, tree, FALSE, &can_id))
{
case CAN_DATA_DISSECTOR:
call_dissector(data_handle, next_tvb, pinfo, tree);
break;
case CAN_CANOPEN_DISSECTOR:
call_dissector_with_data(canopen_handle, next_tvb, pinfo, tree, &can_id);
break;
case CAN_DEVICENET_DISSECTOR:
/* XXX - Not sure this is correct. But the capture provided in
* bug 8564 provides CAN ID in little endian format, so this makes it work */
can_id.id = GUINT32_SWAP_LE_BE(can_id.id);
call_dissector_with_data(devicenet_handle, next_tvb, pinfo, tree, &can_id);
break;
case CAN_J1939_DISSECTOR:
call_dissector_with_data(j1939_handle, next_tvb, pinfo, tree, &can_id);
break;
call_dissector(data_handle, next_tvb, pinfo, tree);
}
}
@ -234,8 +214,15 @@ proto_register_socketcan(void)
{
&ett_can
};
module_t *can_module;
/* Decode As handling */
static build_valid_func can_da_build_value[1] = {can_value};
static decode_as_value_t can_da_values = {can_prompt, 1, can_da_build_value};
static decode_as_t can_da = {"can", "Network", "can.subdissector", 1, 0, &can_da_values, NULL, NULL,
decode_as_default_populate_list, decode_as_default_reset, decode_as_default_change, NULL};
proto_can = proto_register_protocol(
"Controller Area Network", /* name */
"CAN", /* short name */
@ -245,17 +232,14 @@ proto_register_socketcan(void)
proto_register_field_array(proto_can, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
subdissector_table = register_dissector_table("can.subdissector",
"CAN next level dissector", FT_UINT32, BASE_HEX);
can_module = prefs_register_protocol(proto_can, NULL);
prefs_register_enum_preference(
can_module,
"protocol",
"Next level protocol",
"Next level protocol like CANopen etc.",
(gint *)&can_high_level_protocol_dissector,
can_high_level_protocol_dissector_options,
FALSE
);
prefs_register_obsolete_preference(can_module, "protocol");
register_decode_as(&can_da);
}
void
@ -267,9 +251,6 @@ proto_reg_handoff_socketcan(void)
dissector_add_uint("wtap_encap", WTAP_ENCAP_SOCKETCAN, can_handle);
dissector_add_uint("sll.ltype", LINUX_SLL_P_CAN, can_handle);
canopen_handle = find_dissector("canopen");
devicenet_handle = find_dissector("devicenet");
j1939_handle = find_dissector("j1939");
data_handle = find_dissector("data");
}