2019-01-15 19:26:10 +00:00
/* packet-autosar-nm.c
* AUTOSAR - NM Dissector
2017-05-01 03:31:26 +00:00
* By Dr . Lars Voelker < lars . voelker @ bmw . de >
* Copyright 2014 - 2017 Dr . Lars Voelker , BMW
2019-01-15 19:26:10 +00:00
* Copyright 2019 Maksim Salau < maksim . salau @ gmail . com >
2017-05-01 03:31:26 +00:00
*
* Wireshark - Network traffic analyzer
* By Gerald Combs < gerald @ wireshark . org >
* Copyright 1998 Gerald Combs
*
2018-02-12 11:23:27 +00:00
* SPDX - License - Identifier : GPL - 2.0 - or - later
2017-05-01 03:31:26 +00:00
*/
/*
2019-01-15 19:26:10 +00:00
* AUTOSAR - NM is an automotive communication protocol as standardized by
* AUTOSAR ( www . autosar . org ) and is specified in AUTOSAR_SWS_UDPNetworkManagement . pdf
* and AUTOSAR_SWS_CANNetworkManagement . pdf which can be accessed on :
2017-05-01 03:31:26 +00:00
* autosar . org - > Classic Platform - > Software Arch - > Comm Stack .
*/
# include <config.h>
# include <epan/packet.h>
# include <epan/prefs.h>
# include <epan/uat.h>
2019-01-15 19:26:10 +00:00
# include "packet-socketcan.h"
2017-05-01 03:31:26 +00:00
2019-01-15 19:26:10 +00:00
void proto_reg_handoff_autosar_nm ( void ) ;
void proto_register_autosar_nm ( void ) ;
2017-05-01 03:31:26 +00:00
typedef struct _user_data_field_t {
gchar * udf_name ;
gchar * udf_desc ;
guint32 udf_offset ;
guint32 udf_length ;
guint32 udf_mask ;
gchar * udf_value_desc ;
} user_data_field_t ;
2019-01-15 19:26:10 +00:00
static int proto_autosar_nm = - 1 ;
static int proto_can = - 1 ;
static int proto_canfd = - 1 ;
static int proto_caneth = - 1 ;
static int proto_udp = - 1 ;
2017-05-01 03:31:26 +00:00
/*** header fields ***/
2019-01-15 19:26:10 +00:00
static int hf_autosar_nm_source_node_identifier = - 1 ;
static int hf_autosar_nm_control_bit_vector = - 1 ;
static int hf_autosar_nm_control_bit_vector_repeat_msg_req = - 1 ;
static int hf_autosar_nm_control_bit_vector_reserved1 = - 1 ;
static int hf_autosar_nm_control_bit_vector_reserved2 = - 1 ;
static int hf_autosar_nm_control_bit_vector_nm_coord_id = - 1 ;
static int hf_autosar_nm_control_bit_vector_nm_coord_sleep = - 1 ;
static int hf_autosar_nm_control_bit_vector_active_wakeup = - 1 ;
static int hf_autosar_nm_control_bit_vector_reserved5 = - 1 ;
static int hf_autosar_nm_control_bit_vector_pni = - 1 ;
static int hf_autosar_nm_control_bit_vector_reserved7 = - 1 ;
static int hf_autosar_nm_user_data = - 1 ;
2017-05-01 03:31:26 +00:00
/*** protocol tree items ***/
2019-01-15 19:26:10 +00:00
static gint ett_autosar_nm = - 1 ;
static gint ett_autosar_nm_cbv = - 1 ;
static gint ett_autosar_nm_user_data = - 1 ;
2017-05-01 03:31:26 +00:00
/*** Bit meanings ***/
2019-01-15 19:26:10 +00:00
static const true_false_string tfs_autosar_nm_control_rep_msg_req = {
2017-05-01 03:31:26 +00:00
" Repeat Message State requested " , " Repeat Message State not requested " } ;
2019-01-15 19:26:10 +00:00
static const true_false_string tfs_autosar_nm_control_sleep_bit = {
2017-05-01 03:31:26 +00:00
" Start of synchronized shutdown requested " , " Start of synchronized shutdown not requested " } ;
2019-01-15 19:26:10 +00:00
static const true_false_string tfs_autosar_nm_control_active_wakeup = {
2017-05-01 03:31:26 +00:00
" Node has woken up the network " , " Node has not woken up the network " } ;
2019-01-15 19:26:10 +00:00
static const true_false_string tfs_autosar_nm_control_pni = {
2017-05-01 03:31:26 +00:00
" NM message contains no Partial Network request information " , " NM message contains Partial Network request information " } ;
/*** Configuration items ***/
/* Set the order of the first two fields (Source Node Identifier and Control Bit Vector */
2019-01-15 19:26:10 +00:00
static gboolean g_autosar_nm_swap_first_fields = TRUE ;
/* Read bits 1 and 2 of Control Bit Vector as NM Coordinator Id */
static gboolean g_autosar_nm_interpret_coord_id = FALSE ;
/* Id and mask of CAN frames to be dissected */
static guint32 g_autosar_nm_can_id = 0 ;
static guint32 g_autosar_nm_can_id_mask = 0 ;
2017-05-01 03:31:26 +00:00
/*******************************
* * * * * * User data fields * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*** stolen from the HTTP disector ;-) ***/
2018-05-30 07:00:16 +00:00
static user_data_field_t * user_data_fields ;
static guint num_user_data_fields ;
static GHashTable * user_data_fields_hash_hf ;
static hf_register_info * dynamic_hf ;
static guint dynamic_hf_size ;
static wmem_map_t * user_data_fields_hash_ett ;
2017-05-01 03:31:26 +00:00
static gboolean
user_data_fields_update_cb ( void * r , char * * err )
{
user_data_field_t * rec = ( user_data_field_t * ) r ;
char c ;
* err = NULL ;
if ( rec - > udf_length = = 0 ) {
* err = g_strdup_printf ( " length of user data field can't be 0 Bytes (name: %s offset: %i length: %i) " , rec - > udf_name , rec - > udf_offset , rec - > udf_length ) ;
return ( * err = = NULL ) ;
}
if ( rec - > udf_length > 4 ) {
* err = g_strdup_printf ( " length of user data field can't be greater 4 Bytes (name: %s offset: %i length: %i) " , rec - > udf_name , rec - > udf_offset , rec - > udf_length ) ;
return ( * err = = NULL ) ;
}
if ( rec - > udf_offset < 2 ) {
* err = g_strdup_printf ( " offset of user data field can't be short than 2 (name: %s offset: %i length: %i) " , rec - > udf_name , rec - > udf_offset , rec - > udf_length ) ;
return ( * err = = NULL ) ;
}
if ( rec - > udf_mask > = G_MAXUINT32 ) {
* err = g_strdup_printf ( " mask can only be up to 32bits (name: %s) " , rec - > udf_name ) ;
return ( * err = = NULL ) ;
}
if ( rec - > udf_name = = NULL ) {
* err = g_strdup_printf ( " Name of user data field can't be empty " ) ;
return ( * err = = NULL ) ;
}
g_strstrip ( rec - > udf_name ) ;
if ( rec - > udf_name [ 0 ] = = 0 ) {
* err = g_strdup_printf ( " Name of user data field can't be empty " ) ;
return ( * err = = NULL ) ;
}
/* Check for invalid characters (to avoid asserting out when
* registering the field ) .
*/
c = proto_check_field_name ( rec - > udf_name ) ;
if ( c ) {
* err = g_strdup_printf ( " Name of user data field can't contain '%c' " , c ) ;
return ( * err = = NULL ) ;
}
return ( * err = = NULL ) ;
}
static void *
user_data_fields_copy_cb ( void * n , const void * o , size_t siz _U_ )
{
user_data_field_t * new_rec = ( user_data_field_t * ) n ;
const user_data_field_t * old_rec = ( const user_data_field_t * ) o ;
2017-08-26 08:30:47 +00:00
new_rec - > udf_name = g_strdup ( old_rec - > udf_name ) ;
new_rec - > udf_desc = g_strdup ( old_rec - > udf_desc ) ;
new_rec - > udf_offset = old_rec - > udf_offset ;
new_rec - > udf_length = old_rec - > udf_length ;
new_rec - > udf_mask = old_rec - > udf_mask ;
new_rec - > udf_value_desc = g_strdup ( old_rec - > udf_value_desc ) ;
2017-05-01 03:31:26 +00:00
return new_rec ;
}
static void
user_data_fields_free_cb ( void * r )
{
user_data_field_t * rec = ( user_data_field_t * ) r ;
2017-08-26 08:30:47 +00:00
g_free ( rec - > udf_name ) ;
g_free ( rec - > udf_desc ) ;
g_free ( rec - > udf_value_desc ) ;
2017-05-01 03:31:26 +00:00
}
UAT_CSTRING_CB_DEF ( user_data_fields , udf_name , user_data_field_t )
UAT_CSTRING_CB_DEF ( user_data_fields , udf_desc , user_data_field_t )
UAT_DEC_CB_DEF ( user_data_fields , udf_offset , user_data_field_t )
UAT_DEC_CB_DEF ( user_data_fields , udf_length , user_data_field_t )
UAT_HEX_CB_DEF ( user_data_fields , udf_mask , user_data_field_t )
UAT_CSTRING_CB_DEF ( user_data_fields , udf_value_desc , user_data_field_t )
static guint64
calc_ett_key ( guint32 offset , guint32 length )
{
guint64 ret = offset ;
return ( ret * 0x100000000 ) ^ length ;
}
/*
* This creates a string for you that can be used as key for the hash table .
* YOU must g_free that string !
*/
static gchar *
calc_hf_key ( user_data_field_t udf )
{
gchar * ret = NULL ;
ret = g_strdup_printf ( " %i-%i-%i-%s " , udf . udf_offset , udf . udf_length , udf . udf_mask , udf . udf_name ) ;
return ret ;
}
/*
*
*/
static gint *
get_hf_for_user_data ( gchar * key )
{
gint * hf_id = NULL ;
if ( user_data_fields_hash_hf ) {
hf_id = ( gint * ) g_hash_table_lookup ( user_data_fields_hash_hf , key ) ;
}
else {
hf_id = NULL ;
}
return hf_id ;
}
/*
*
*/
static gint *
get_ett_for_user_data ( guint32 offset , guint32 length )
{
gint * ett_id = NULL ;
guint64 key = calc_ett_key ( offset , length ) ;
if ( user_data_fields_hash_ett ) {
2018-05-30 07:00:16 +00:00
ett_id = ( gint * ) wmem_map_lookup ( user_data_fields_hash_ett , & key ) ;
2017-05-01 03:31:26 +00:00
}
else {
ett_id = NULL ;
}
return ett_id ;
}
/*
*
*/
2018-05-30 07:00:16 +00:00
static void
deregister_user_data ( void )
{
if ( dynamic_hf ) {
/* Unregister all fields */
for ( guint i = 0 ; i < dynamic_hf_size ; i + + ) {
2019-01-15 19:26:10 +00:00
proto_deregister_field ( proto_autosar_nm , * ( dynamic_hf [ i ] . p_id ) ) ;
2018-05-30 07:00:16 +00:00
g_free ( dynamic_hf [ i ] . p_id ) ;
}
proto_add_deregistered_data ( dynamic_hf ) ;
dynamic_hf = NULL ;
dynamic_hf_size = 0 ;
}
if ( user_data_fields_hash_hf ) {
g_hash_table_destroy ( user_data_fields_hash_hf ) ;
user_data_fields_hash_hf = NULL ;
}
}
2017-05-01 03:31:26 +00:00
static void
user_data_post_update_cb ( void )
{
gint * hf_id ;
2018-05-30 07:00:16 +00:00
gint * ett_id ;
2017-05-01 03:31:26 +00:00
gchar * tmp = NULL ;
guint64 * key = NULL ;
static gint ett_dummy = - 1 ;
static gint * ett [ ] = {
& ett_dummy ,
} ;
2018-05-30 07:00:16 +00:00
deregister_user_data ( ) ;
2017-05-01 03:31:26 +00:00
// we cannot unregister ETTs, so we should try to limit the damage of an update
if ( num_user_data_fields ) {
2018-05-30 07:00:16 +00:00
user_data_fields_hash_hf = g_hash_table_new_full ( g_str_hash , g_str_equal , g_free , NULL ) ;
dynamic_hf = g_new0 ( hf_register_info , num_user_data_fields ) ;
dynamic_hf_size = num_user_data_fields ;
2017-05-01 03:31:26 +00:00
if ( user_data_fields_hash_ett = = NULL ) {
2018-05-30 07:00:16 +00:00
user_data_fields_hash_ett = wmem_map_new ( wmem_epan_scope ( ) , g_int64_hash , g_int64_equal ) ;
2017-05-01 03:31:26 +00:00
}
2018-05-30 07:00:16 +00:00
for ( guint i = 0 ; i < dynamic_hf_size ; i + + ) {
2017-05-01 03:31:26 +00:00
hf_id = g_new ( gint , 1 ) ;
* hf_id = - 1 ;
2018-05-30 07:00:16 +00:00
dynamic_hf [ i ] . p_id = hf_id ;
dynamic_hf [ i ] . hfinfo . strings = NULL ;
dynamic_hf [ i ] . hfinfo . bitmask = user_data_fields [ i ] . udf_mask ;
dynamic_hf [ i ] . hfinfo . same_name_next = NULL ;
dynamic_hf [ i ] . hfinfo . same_name_prev_id = - 1 ;
2017-05-01 03:31:26 +00:00
if ( user_data_fields [ i ] . udf_mask = = 0 | | user_data_fields [ i ] . udf_length < = 0 | | user_data_fields [ i ] . udf_length > 4 ) {
2018-05-30 07:00:16 +00:00
dynamic_hf [ i ] . hfinfo . name = g_strdup ( user_data_fields [ i ] . udf_name ) ;
dynamic_hf [ i ] . hfinfo . abbrev = g_strdup_printf ( " nm.user_data.%s " , user_data_fields [ i ] . udf_name ) ;
dynamic_hf [ i ] . hfinfo . type = FT_BYTES ;
dynamic_hf [ i ] . hfinfo . display = BASE_NONE ;
dynamic_hf [ i ] . hfinfo . bitmask = 0 ;
dynamic_hf [ i ] . hfinfo . blurb = g_strdup ( user_data_fields [ i ] . udf_desc ) ;
2017-05-01 03:31:26 +00:00
}
else {
2018-05-30 07:00:16 +00:00
dynamic_hf [ i ] . hfinfo . name = g_strdup ( user_data_fields [ i ] . udf_value_desc ) ;
dynamic_hf [ i ] . hfinfo . abbrev = g_strdup_printf ( " nm.user_data.%s.%s " , user_data_fields [ i ] . udf_name , user_data_fields [ i ] . udf_value_desc ) ;
dynamic_hf [ i ] . hfinfo . type = FT_BOOLEAN ;
dynamic_hf [ i ] . hfinfo . display = 8 * ( user_data_fields [ i ] . udf_length ) ;
// dynamic_hf[i].hfinfo.bitmask = 0;
dynamic_hf [ i ] . hfinfo . blurb = g_strdup ( user_data_fields [ i ] . udf_value_desc ) ;
2017-05-01 03:31:26 +00:00
}
tmp = calc_hf_key ( user_data_fields [ i ] ) ;
g_hash_table_insert ( user_data_fields_hash_hf , tmp , hf_id ) ;
// generate etts for new fields only
if ( get_ett_for_user_data ( user_data_fields [ i ] . udf_offset , user_data_fields [ i ] . udf_length ) = = NULL ) {
ett_dummy = - 1 ;
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
2018-05-30 07:00:16 +00:00
ett_id = wmem_new ( wmem_epan_scope ( ) , gint ) ;
2017-05-01 03:31:26 +00:00
* ett_id = ett_dummy ;
2018-05-30 07:00:16 +00:00
key = wmem_new ( wmem_epan_scope ( ) , guint64 ) ;
2017-05-01 03:31:26 +00:00
* key = calc_ett_key ( user_data_fields [ i ] . udf_offset , user_data_fields [ i ] . udf_length ) ;
2018-05-30 07:00:16 +00:00
wmem_map_insert ( user_data_fields_hash_ett , key , ett_id ) ;
2017-05-01 03:31:26 +00:00
}
}
2019-01-15 19:26:10 +00:00
proto_register_field_array ( proto_autosar_nm , dynamic_hf , dynamic_hf_size ) ;
2017-05-01 03:31:26 +00:00
}
}
2018-05-30 07:00:16 +00:00
static void
user_data_reset_cb ( void )
{
deregister_user_data ( ) ;
}
2017-05-01 03:31:26 +00:00
/**********************************
* * * * * * The dissector itself * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int
2019-01-15 19:26:10 +00:00
dissect_autosar_nm ( tvbuff_t * tvb , packet_info * pinfo _U_ , proto_tree * tree , void * data )
2017-05-01 03:31:26 +00:00
{
2019-01-15 19:26:10 +00:00
wmem_list_frame_t * prev_layer ;
2017-05-01 03:31:26 +00:00
proto_item * ti ;
2019-01-15 19:26:10 +00:00
proto_tree * autosar_nm_tree ;
proto_tree * autosar_nm_subtree = NULL ;
2017-05-01 03:31:26 +00:00
gchar * tmp = NULL ;
guint32 offset = 0 ;
guint32 length = 0 ;
guint32 msg_length = 0 ;
guint32 ctrl_bit_vector ;
2017-05-09 12:42:18 +00:00
guint32 src_node_id = 0 ;
2017-05-01 03:31:26 +00:00
guint i = 0 ;
int * hf_id ;
int ett_id ;
// AUTOSAR says default is Source Node ID first and Ctrl Bit Vector second but this can be also swapped
guint32 offset_ctrl_bit_vector = 1 ;
guint32 offset_src_node_id = 0 ;
2019-01-15 19:26:10 +00:00
static const int * control_bits_legacy [ ] = {
& hf_autosar_nm_control_bit_vector_repeat_msg_req ,
& hf_autosar_nm_control_bit_vector_nm_coord_id ,
& hf_autosar_nm_control_bit_vector_nm_coord_sleep ,
& hf_autosar_nm_control_bit_vector_active_wakeup ,
& hf_autosar_nm_control_bit_vector_reserved5 ,
& hf_autosar_nm_control_bit_vector_pni ,
& hf_autosar_nm_control_bit_vector_reserved7 ,
NULL
} ;
static const int * control_bits [ ] = {
& hf_autosar_nm_control_bit_vector_repeat_msg_req ,
& hf_autosar_nm_control_bit_vector_reserved1 ,
& hf_autosar_nm_control_bit_vector_reserved2 ,
& hf_autosar_nm_control_bit_vector_nm_coord_sleep ,
& hf_autosar_nm_control_bit_vector_active_wakeup ,
& hf_autosar_nm_control_bit_vector_reserved5 ,
& hf_autosar_nm_control_bit_vector_pni ,
& hf_autosar_nm_control_bit_vector_reserved7 ,
2017-05-01 03:31:26 +00:00
NULL
2019-01-15 19:26:10 +00:00
} ;
prev_layer = wmem_list_frame_prev ( wmem_list_tail ( pinfo - > layers ) ) ;
if ( prev_layer ) {
const int prev_proto = GPOINTER_TO_INT ( wmem_list_frame_data ( prev_layer ) ) ;
if ( prev_proto ! = proto_udp ) {
const can_identifier_t * can_id = ( can_identifier_t * ) data ;
const gboolean is_can_frame =
( prev_proto = = proto_can ) | |
( prev_proto = = proto_canfd ) | |
( wmem_list_find ( pinfo - > layers , GINT_TO_POINTER ( proto_caneth ) ) ! = NULL ) ;
if ( ! is_can_frame ) {
/* Only UDP and CAN transports are supported. */
return 0 ;
}
DISSECTOR_ASSERT ( can_id ) ;
if ( can_id - > id & ( CAN_ERR_FLAG | CAN_RTR_FLAG ) ) {
/* Error and RTR frames are not for us. */
return 0 ;
}
if ( ( can_id - > id & g_autosar_nm_can_id_mask ) ! = ( g_autosar_nm_can_id & g_autosar_nm_can_id_mask ) ) {
/* Id doesn't match. The frame is not for us. */
return 0 ;
}
}
}
2017-05-01 03:31:26 +00:00
2019-01-15 19:26:10 +00:00
if ( g_autosar_nm_swap_first_fields = = TRUE ) {
2017-05-01 03:31:26 +00:00
offset_ctrl_bit_vector = 0 ;
offset_src_node_id = 1 ;
}
2019-01-15 19:26:10 +00:00
col_set_str ( pinfo - > cinfo , COL_PROTOCOL , " AUTOSAR NM " ) ;
2017-05-01 03:31:26 +00:00
col_clear ( pinfo - > cinfo , COL_INFO ) ;
msg_length = tvb_reported_length ( tvb ) ;
2019-01-15 19:26:10 +00:00
ti = proto_tree_add_item ( tree , proto_autosar_nm , tvb , 0 , - 1 , ENC_NA ) ;
autosar_nm_tree = proto_item_add_subtree ( ti , ett_autosar_nm ) ;
2017-05-01 03:31:26 +00:00
2019-01-15 19:26:10 +00:00
if ( g_autosar_nm_swap_first_fields = = FALSE ) {
proto_tree_add_item_ret_uint ( autosar_nm_tree , hf_autosar_nm_source_node_identifier , tvb , offset_src_node_id , 1 , ENC_BIG_ENDIAN , & src_node_id ) ;
2017-05-01 03:31:26 +00:00
}
2019-01-15 19:26:10 +00:00
proto_tree_add_bitmask ( autosar_nm_tree , tvb , offset_ctrl_bit_vector , hf_autosar_nm_control_bit_vector , ett_autosar_nm_cbv ,
( g_autosar_nm_interpret_coord_id ? control_bits_legacy : control_bits ) , ENC_BIG_ENDIAN ) ;
2017-05-01 03:31:26 +00:00
ctrl_bit_vector = tvb_get_guint8 ( tvb , offset_ctrl_bit_vector ) ;
2019-01-15 19:26:10 +00:00
if ( g_autosar_nm_swap_first_fields = = TRUE ) {
proto_tree_add_item_ret_uint ( autosar_nm_tree , hf_autosar_nm_source_node_identifier , tvb , offset_src_node_id , 1 , ENC_BIG_ENDIAN , & src_node_id ) ;
2017-05-01 03:31:26 +00:00
}
col_add_fstr ( pinfo - > cinfo , COL_INFO , " Control Bit Vector: 0x%02x, Source Node: 0x%02x " , ctrl_bit_vector , src_node_id ) ;
proto_item_append_text ( ti , " , Control Bit Vector: 0x%02x, Source Node: %i " , ctrl_bit_vector , src_node_id ) ;
offset = 2 ;
/* now we need to process the user defined fields ... */
2019-01-15 19:26:10 +00:00
ti = proto_tree_add_item ( autosar_nm_tree , hf_autosar_nm_user_data , tvb , offset , msg_length - offset , ENC_NA ) ;
autosar_nm_tree = proto_item_add_subtree ( ti , ett_autosar_nm_user_data ) ;
2017-05-01 03:31:26 +00:00
for ( i = 0 ; i < num_user_data_fields ; i + + ) {
tmp = calc_hf_key ( user_data_fields [ i ] ) ;
hf_id = get_hf_for_user_data ( tmp ) ;
offset = user_data_fields [ i ] . udf_offset ;
length = user_data_fields [ i ] . udf_length ;
ett_id = * ( get_ett_for_user_data ( offset , length ) ) ;
if ( hf_id & & msg_length > = length + offset ) {
if ( user_data_fields [ i ] . udf_mask = = 0 ) {
2019-01-15 19:26:10 +00:00
ti = proto_tree_add_item ( autosar_nm_tree , * hf_id , tvb , offset , length , ENC_BIG_ENDIAN ) ;
autosar_nm_subtree = proto_item_add_subtree ( ti , ett_id ) ;
2017-05-01 03:31:26 +00:00
}
else {
2019-01-15 19:26:10 +00:00
if ( autosar_nm_subtree ! = NULL ) {
proto_tree_add_item ( autosar_nm_subtree , * hf_id , tvb , offset , length , ENC_BIG_ENDIAN ) ;
2017-05-01 03:31:26 +00:00
}
}
}
else {
/* should we warn? */
}
g_free ( tmp ) ;
}
return 8 ;
}
2019-01-15 19:26:10 +00:00
void proto_register_autosar_nm ( void )
2017-05-01 03:31:26 +00:00
{
2019-01-15 19:26:10 +00:00
module_t * autosar_nm_module ;
2017-05-01 03:31:26 +00:00
uat_t * user_data_fields_uat ;
2019-01-15 19:26:10 +00:00
static hf_register_info hf_autosar_nm [ ] = {
{ & hf_autosar_nm_control_bit_vector ,
{ " Control Bit Vector " , " autosar-nm.ctrl " , FT_UINT8 , BASE_HEX , NULL , 0x0 , " The Control Bit Vector " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_repeat_msg_req ,
{ " Repeat Message Request " , " autosar-nm.ctrl.repeat_msg_req " , FT_BOOLEAN , 8 , TFS ( & tfs_autosar_nm_control_rep_msg_req ) , 0x01 , " The Repeat Message Request Bit " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_reserved1 ,
{ " Reserved Bit 1 " , " autosar-nm.ctrl.reserved1 " , FT_UINT8 , BASE_DEC , NULL , 0x02 , " The Reserved Bit 1 " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_reserved2 ,
{ " Reserved Bit 2 " , " autosar-nm.ctrl.reserved2 " , FT_UINT8 , BASE_DEC , NULL , 0x04 , " The Reserved Bit 2 " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_nm_coord_id ,
{ " NM Coordinator Id " , " autosar-nm.ctrl.nm_coord_id " , FT_UINT8 , BASE_DEC , NULL , 0x06 , " The NM Coordinator Identifier " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_nm_coord_sleep ,
{ " NM Coordinator Sleep " , " autosar-nm.ctrl.nm_coord_sleep " , FT_BOOLEAN , 8 , TFS ( & tfs_autosar_nm_control_sleep_bit ) , 0x08 , " NM Coordinator Sleep Bit " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_active_wakeup ,
{ " Active Wakeup " , " autosar-nm.ctrl.active_wakeup " , FT_BOOLEAN , 8 , TFS ( & tfs_autosar_nm_control_active_wakeup ) , 0x10 , " Active Wakeup Bit " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_reserved5 ,
{ " Reserved Bit 5 " , " autosar-nm.ctrl.reserved5 " , FT_UINT8 , BASE_DEC , NULL , 0x20 , " The Reserved Bit 5 " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_pni ,
{ " Partial Network Information " , " autosar-nm.ctrl.pni " , FT_BOOLEAN , 8 , TFS ( & tfs_autosar_nm_control_pni ) , 0x40 , " Partial Network Information Bit " , HFILL } } ,
{ & hf_autosar_nm_control_bit_vector_reserved7 ,
{ " Reserved Bit 7 " , " autosar-nm.ctrl.reserved7 " , FT_UINT8 , BASE_DEC , NULL , 0x80 , " The Reserved Bit 7 " , HFILL } } ,
{ & hf_autosar_nm_source_node_identifier ,
{ " Source Node Identifier " , " autosar-nm.src " , FT_UINT8 , BASE_DEC , NULL , 0x0 , " The identification of the sending node " , HFILL } } ,
{ & hf_autosar_nm_user_data ,
{ " User Data " , " autosar-nm.user_data " , FT_BYTES , BASE_NONE , NULL , 0x0 , " The User Data " , HFILL } } ,
2017-05-01 03:31:26 +00:00
} ;
static gint * ett [ ] = {
2019-01-15 19:26:10 +00:00
& ett_autosar_nm ,
& ett_autosar_nm_cbv ,
& ett_autosar_nm_user_data ,
2017-05-01 03:31:26 +00:00
} ;
/* UAT for user_data fields */
static uat_field_t user_data_uat_fields [ ] = {
UAT_FLD_CSTRING ( user_data_fields , udf_name , " User data name " , " Name of user data field " ) ,
UAT_FLD_CSTRING ( user_data_fields , udf_desc , " User data desc " , " Description of user data field " ) ,
2019-01-15 19:26:10 +00:00
UAT_FLD_DEC ( user_data_fields , udf_offset , " User data offset " , " Offset of the user data field in the AUTOSAR-NM message (uint32) " ) ,
UAT_FLD_DEC ( user_data_fields , udf_length , " User data length " , " Length of the user data field in the AUTOSAR-NM message (uint32) " ) ,
UAT_FLD_DEC ( user_data_fields , udf_mask , " User data mask " , " Relevant bits of the user data field in the AUTOSAR-NM message (uint32) " ) ,
2017-05-01 03:31:26 +00:00
UAT_FLD_CSTRING ( user_data_fields , udf_value_desc , " User data value " , " Description what the masked bits mean " ) ,
UAT_END_FIELDS
} ;
/* Register the protocol name and description */
2019-01-15 19:26:10 +00:00
proto_autosar_nm = proto_register_protocol ( " AUTOSAR Network Management " , " AUTOSAR NM " , " autosar-nm " ) ;
proto_register_field_array ( proto_autosar_nm , hf_autosar_nm , array_length ( hf_autosar_nm ) ) ;
proto_register_alias ( proto_autosar_nm , " nm " ) ;
2017-05-01 03:31:26 +00:00
proto_register_subtree_array ( ett , array_length ( ett ) ) ;
/* Register configuration options */
2019-01-15 19:26:10 +00:00
autosar_nm_module = prefs_register_protocol ( proto_autosar_nm , NULL ) ;
prefs_register_bool_preference ( autosar_nm_module , " swap_ctrl_and_src " ,
2017-05-01 03:31:26 +00:00
" Swap Source Node Identifier and Control Bit Vector " ,
" In the standard the Source Node Identifier is the first byte "
" and the Control Bit Vector is the second byte. "
" Using this parameter they can be swapped " ,
2019-01-15 19:26:10 +00:00
& g_autosar_nm_swap_first_fields ) ;
prefs_register_bool_preference ( autosar_nm_module , " interpret_coord_id " ,
" Interpret bits 1 and 2 of Control Bit Vector as 'NM Coordinator Id' " ,
" Revision 4.3.1 of the specification doesn't have 'NM Coordinator Id' in Control Bit Vector. "
" Using this parameter one may switch to a mode compatible with revision 3.2 of the specification. " ,
& g_autosar_nm_interpret_coord_id ) ;
prefs_register_uint_preference (
autosar_nm_module , " can_id " ,
" CAN id " ,
" Identifier that is used to filter packets that should be dissected. "
" Set bit 31 when defining an extended id. "
" (works with the mask defined below) " ,
16 , & g_autosar_nm_can_id ) ;
prefs_register_uint_preference (
autosar_nm_module , " can_id_mask " ,
" CAN id mask " ,
" Mask applied to CAN identifiers when decoding whether a packet should dissected. "
" Use 0xFFFFFFFF mask to require exact match. " ,
16 , & g_autosar_nm_can_id_mask ) ;
2017-05-01 03:31:26 +00:00
/* UAT */
user_data_fields_uat = uat_new ( " NM User Data Fields Table " ,
sizeof ( user_data_field_t ) , /* record size */
" NM_user_data_fields " , /* filename */
TRUE , /* from_profile */
& user_data_fields , /* data_ptr */
& num_user_data_fields , /* numitems_ptr */
UAT_AFFECTS_DISSECTION | UAT_AFFECTS_FIELDS , /* specifies named fields, so affects dissection and the set of named fields */
NULL , /* help */
user_data_fields_copy_cb , /* copy callback */
user_data_fields_update_cb , /* update callback */
user_data_fields_free_cb , /* free callback */
user_data_post_update_cb , /* post update callback */
2018-05-30 07:00:16 +00:00
user_data_reset_cb , /* reset callback */
2017-05-01 03:31:26 +00:00
user_data_uat_fields ) ; /* UAT field definitions */
2019-01-15 19:26:10 +00:00
prefs_register_uat_preference ( autosar_nm_module , " autosar_nm_user_data_fields " , " User Data Field Configuration " ,
2017-05-01 03:31:26 +00:00
" A table to define user defined fields in the NM payload " ,
user_data_fields_uat ) ;
}
2019-01-15 19:26:10 +00:00
void proto_reg_handoff_autosar_nm ( void )
2017-05-01 03:31:26 +00:00
{
2019-01-15 19:26:10 +00:00
dissector_handle_t nm_handle = create_dissector_handle ( dissect_autosar_nm , proto_autosar_nm ) ;
2017-05-01 03:31:26 +00:00
dissector_add_for_decode_as_with_preference ( " udp.port " , nm_handle ) ;
dissector_add_for_decode_as ( " can.subdissector " , nm_handle ) ;
2019-01-15 19:26:10 +00:00
proto_can = proto_get_id_by_filter_name ( " can " ) ;
proto_canfd = proto_get_id_by_filter_name ( " canfd " ) ;
proto_caneth = proto_get_id_by_filter_name ( " caneth " ) ;
proto_udp = proto_get_id_by_filter_name ( " udp " ) ;
2017-05-01 03:31:26 +00:00
}
/*
* Editor modelines
*
* Local Variables :
* c - basic - offset : 2
* tab - width : 8
* indent - tabs - mode : nil
* End :
*
* ex : set shiftwidth = 2 tabstop = 8 expandtab :
* : indentSize = 2 : tabSize = 8 : noTabs = true :
*/