3 * By Dr. Lars Voelker <lars.voelker@technica-engineering.de> / <lars.voelker@bmw.de>
4 * Copyright 2014-2021 Dr. Lars Voelker
5 * Copyright 2019 Maksim Salau <maksim.salau@gmail.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
15 * AUTOSAR-NM is an automotive communication protocol as standardized by
16 * AUTOSAR (www.autosar.org) and is specified in AUTOSAR_SWS_UDPNetworkManagement.pdf
17 * and AUTOSAR_SWS_CANNetworkManagement.pdf which can be accessed on:
18 * autosar.org -> Classic Platform -> Software Arch -> Comm Stack.
23 #include <epan/packet.h>
24 #include <epan/prefs.h>
27 #include "packet-socketcan.h"
29 void proto_reg_handoff_autosar_nm(void);
30 void proto_register_autosar_nm(void);
32 #define AUTOSAR_NM_NAME "AUTOSAR NM"
34 typedef struct _user_data_field_t
{
43 static int proto_autosar_nm
;
45 static dissector_handle_t nm_handle
;
46 static dissector_handle_t nm_handle_can
;
48 /*** header fields ***/
49 static int hf_autosar_nm_source_node_identifier
;
50 static int hf_autosar_nm_control_bit_vector
;
51 static int hf_autosar_nm_control_bit_vector_repeat_msg_req
;
52 static int hf_autosar_nm_control_bit_vector_reserved1
;
53 static int hf_autosar_nm_control_bit_vector_pn_shutdown_request
;
54 static int hf_autosar_nm_control_bit_vector_reserved2
;
55 static int hf_autosar_nm_control_bit_vector_nm_coord_id
;
56 static int hf_autosar_nm_control_bit_vector_reserved3
;
57 static int hf_autosar_nm_control_bit_vector_nm_coord_sleep
;
58 static int hf_autosar_nm_control_bit_vector_reserved4
;
59 static int hf_autosar_nm_control_bit_vector_active_wakeup
;
60 static int hf_autosar_nm_control_bit_vector_reserved5
;
61 static int hf_autosar_nm_control_bit_vector_pn_learning
;
62 static int hf_autosar_nm_control_bit_vector_pni
;
63 static int hf_autosar_nm_control_bit_vector_reserved6
;
64 static int hf_autosar_nm_control_bit_vector_reserved7
;
65 static int hf_autosar_nm_user_data
;
67 /*** protocol tree items ***/
68 static int ett_autosar_nm
;
69 static int ett_autosar_nm_cbv
;
70 static int ett_autosar_nm_user_data
;
72 /*** Bit meanings ***/
73 static const true_false_string tfs_autosar_nm_control_rep_msg_req
= {
74 "Repeat Message State requested", "Repeat Message State not requested" };
76 static const true_false_string tfs_autosar_nm_control_pn_shutdown_req
= {
77 "NM message contains synchronized PN shutdown request", "NM message does not contain synchronized PN shutdown request" };
79 static const true_false_string tfs_autosar_nm_control_sleep_bit
= {
80 "Start of synchronized shutdown requested", "Start of synchronized shutdown not requested" };
82 static const true_false_string tfs_autosar_nm_control_active_wakeup
= {
83 "Node has woken up the network", "Node has not woken up the network" };
85 static const true_false_string tfs_autosar_nm_control_pn_learning
= {
86 "PNC learning is requested", "PNC learning is not requested" };
88 static const true_false_string tfs_autosar_nm_control_pni
= {
89 "NM message contains Partial Network request information", "NM message contains no Partial Network request information" };
91 /*** Configuration items ***/
93 enum parameter_byte_position_value
{
99 static const enum_val_t byte_position_vals
[] = {
100 {"0", "Byte Position 0", byte_pos_0
},
101 {"1", "Byte Position 1", byte_pos_1
},
102 {"off", "Turned off", byte_pos_off
},
106 /* Set positions of the first two fields (Source Node Identifier and Control Bit Vector */
107 static int g_autosar_nm_pos_cbv
= (int)byte_pos_0
;
108 static int g_autosar_nm_pos_sni
= (int)byte_pos_1
;
110 enum parameter_cbv_version_value
{
111 autosar_3_0_or_newer
= 0,
114 autosar_4_1_or_newer
,
118 static const enum_val_t cbv_version_vals
[] = {
119 {"3.0", "AUTOSAR 3.0 or 3.1", autosar_3_0_or_newer
},
120 {"3.2", "AUTOSAR 3.2", autosar_3_2
},
121 {"4.0", "AUTOSAR 4.0", autosar_4_0
},
122 {"4.1", "AUTOSAR 4.1 or newer", autosar_4_1_or_newer
},
123 {"20-11", "AUTOSAR 20-11", autosar_20_11
},
127 static int g_autosar_nm_cbv_version
= (int)autosar_4_1_or_newer
;
129 /* Id and mask of CAN frames to be dissected */
130 static uint32_t g_autosar_nm_can_id
;
131 static uint32_t g_autosar_nm_can_id_mask
= 0xffffffff;
134 static range_t
*g_autosar_nm_pdus
;
135 static range_t
*g_autosar_nm_ipdum_pdus
;
138 /*******************************
139 ****** User data fields ******
140 *******************************/
142 static user_data_field_t
* user_data_fields
;
143 static unsigned num_user_data_fields
;
144 static GHashTable
* user_data_fields_hash_hf
;
145 static hf_register_info
* dynamic_hf
;
146 static unsigned dynamic_hf_size
;
147 static wmem_map_t
* user_data_fields_hash_ett
;
150 user_data_fields_update_cb(void *r
, char **err
)
152 user_data_field_t
*rec
= (user_data_field_t
*)r
;
156 if (rec
->udf_length
== 0) {
157 *err
= ws_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
);
158 return (*err
== NULL
);
161 if (rec
->udf_length
> 8) {
162 *err
= ws_strdup_printf("length of user data field can't be greater 8 Bytes (name: %s offset: %i length: %i)", rec
->udf_name
, rec
->udf_offset
, rec
->udf_length
);
163 return (*err
== NULL
);
166 if (rec
->udf_mask
>= UINT64_MAX
) {
167 *err
= ws_strdup_printf("mask can only be up to 64bits (name: %s)", rec
->udf_name
);
168 return (*err
== NULL
);
171 if (rec
->udf_name
== NULL
) {
172 *err
= ws_strdup_printf("Name of user data field can't be empty");
173 return (*err
== NULL
);
176 g_strstrip(rec
->udf_name
);
177 if (rec
->udf_name
[0] == 0) {
178 *err
= ws_strdup_printf("Name of user data field can't be empty");
179 return (*err
== NULL
);
182 /* Check for invalid characters (to avoid asserting out when registering the field). */
183 c
= proto_check_field_name(rec
->udf_name
);
185 *err
= ws_strdup_printf("Name of user data field can't contain '%c'", c
);
186 return (*err
== NULL
);
189 return (*err
== NULL
);
193 user_data_fields_copy_cb(void* n
, const void* o
, size_t size _U_
)
195 user_data_field_t
* new_rec
= (user_data_field_t
*)n
;
196 const user_data_field_t
* old_rec
= (const user_data_field_t
*)o
;
198 new_rec
->udf_name
= g_strdup(old_rec
->udf_name
);
199 new_rec
->udf_desc
= g_strdup(old_rec
->udf_desc
);
200 new_rec
->udf_offset
= old_rec
->udf_offset
;
201 new_rec
->udf_length
= old_rec
->udf_length
;
202 new_rec
->udf_mask
= old_rec
->udf_mask
;
203 new_rec
->udf_value_desc
= g_strdup(old_rec
->udf_value_desc
);
209 user_data_fields_free_cb(void*r
)
211 user_data_field_t
* rec
= (user_data_field_t
*)r
;
213 g_free(rec
->udf_name
);
214 g_free(rec
->udf_desc
);
215 g_free(rec
->udf_value_desc
);
218 UAT_CSTRING_CB_DEF(user_data_fields
, udf_name
, user_data_field_t
)
219 UAT_CSTRING_CB_DEF(user_data_fields
, udf_desc
, user_data_field_t
)
220 UAT_DEC_CB_DEF(user_data_fields
, udf_offset
, user_data_field_t
)
221 UAT_DEC_CB_DEF(user_data_fields
, udf_length
, user_data_field_t
)
222 UAT_HEX64_CB_DEF(user_data_fields
, udf_mask
, user_data_field_t
)
223 UAT_CSTRING_CB_DEF(user_data_fields
, udf_value_desc
, user_data_field_t
)
226 calc_ett_key(uint32_t offset
, uint32_t length
)
228 uint64_t ret
= (uint64_t)offset
;
229 return (ret
<< 32) ^ length
;
233 * This creates a string for you that can be used as key for the hash table.
234 * YOU must g_free that string!
237 calc_hf_key(user_data_field_t udf
)
240 ret
= ws_strdup_printf("%i-%i-%" PRIu64
"-%s", udf
.udf_offset
, udf
.udf_length
, udf
.udf_mask
, udf
.udf_name
);
245 * Lookup the hf for the user data based on the key
248 get_hf_for_user_data(char* key
)
252 if (user_data_fields_hash_hf
) {
253 hf_id
= (int*)g_hash_table_lookup(user_data_fields_hash_hf
, key
);
263 * Lookup the ett for the user data based on the key
266 get_ett_for_user_data(uint32_t offset
, uint32_t length
)
270 uint64_t key
= calc_ett_key(offset
, length
);
272 if (user_data_fields_hash_ett
) {
273 ett_id
= (int*)wmem_map_lookup(user_data_fields_hash_ett
, &key
);
286 deregister_user_data(void)
289 /* Unregister all fields */
290 for (unsigned i
= 0; i
< dynamic_hf_size
; i
++) {
291 proto_deregister_field(proto_autosar_nm
, *(dynamic_hf
[i
].p_id
));
292 g_free(dynamic_hf
[i
].p_id
);
295 proto_add_deregistered_data(dynamic_hf
);
300 if (user_data_fields_hash_hf
) {
301 g_hash_table_destroy(user_data_fields_hash_hf
);
302 user_data_fields_hash_hf
= NULL
;
307 user_data_post_update_cb(void)
312 uint64_t* key
= NULL
;
314 static int ett_dummy
= -1;
315 static int *ett
[] = {
319 deregister_user_data();
321 /* we cannot unregister ETTs, so we should try to limit the damage of an update */
322 if (num_user_data_fields
) {
323 user_data_fields_hash_hf
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, NULL
);
324 dynamic_hf
= g_new0(hf_register_info
, num_user_data_fields
);
325 dynamic_hf_size
= num_user_data_fields
;
327 if (user_data_fields_hash_ett
== NULL
) {
328 user_data_fields_hash_ett
= wmem_map_new(wmem_epan_scope(), g_int64_hash
, g_int64_equal
);
331 for (unsigned i
= 0; i
< dynamic_hf_size
; i
++) {
332 hf_id
= g_new(int, 1);
335 dynamic_hf
[i
].p_id
= hf_id
;
336 dynamic_hf
[i
].hfinfo
.strings
= NULL
;
337 dynamic_hf
[i
].hfinfo
.bitmask
= user_data_fields
[i
].udf_mask
;
338 dynamic_hf
[i
].hfinfo
.same_name_next
= NULL
;
339 dynamic_hf
[i
].hfinfo
.same_name_prev_id
= -1;
341 if (user_data_fields
[i
].udf_mask
== 0 || user_data_fields
[i
].udf_length
<= 0 || user_data_fields
[i
].udf_length
>8) {
342 dynamic_hf
[i
].hfinfo
.name
= g_strdup(user_data_fields
[i
].udf_name
);
343 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("autosar-nm.user_data.%s", user_data_fields
[i
].udf_name
);
344 dynamic_hf
[i
].hfinfo
.type
= FT_BYTES
;
345 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
346 dynamic_hf
[i
].hfinfo
.bitmask
= 0;
347 dynamic_hf
[i
].hfinfo
.blurb
= g_strdup(user_data_fields
[i
].udf_desc
);
349 dynamic_hf
[i
].hfinfo
.name
= g_strdup(user_data_fields
[i
].udf_value_desc
);
350 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("autosar-nm.user_data.%s.%s", user_data_fields
[i
].udf_name
, user_data_fields
[i
].udf_value_desc
);
351 dynamic_hf
[i
].hfinfo
.type
= FT_BOOLEAN
;
352 dynamic_hf
[i
].hfinfo
.display
= 8 * (user_data_fields
[i
].udf_length
);
353 /* dynamic_hf[i].hfinfo.bitmask = 0; */
354 dynamic_hf
[i
].hfinfo
.blurb
= g_strdup(user_data_fields
[i
].udf_value_desc
);
357 tmp
= calc_hf_key(user_data_fields
[i
]);
358 g_hash_table_insert(user_data_fields_hash_hf
, tmp
, hf_id
);
360 /* generate etts for new fields only */
361 if (get_ett_for_user_data(user_data_fields
[i
].udf_offset
, user_data_fields
[i
].udf_length
) == NULL
) {
363 proto_register_subtree_array(ett
, array_length(ett
));
365 ett_id
= wmem_new(wmem_epan_scope(), int);
368 key
= wmem_new(wmem_epan_scope(), uint64_t);
369 *key
= calc_ett_key(user_data_fields
[i
].udf_offset
, user_data_fields
[i
].udf_length
);
371 wmem_map_insert(user_data_fields_hash_ett
, key
, ett_id
);
375 proto_register_field_array(proto_autosar_nm
, dynamic_hf
, dynamic_hf_size
);
380 user_data_reset_cb(void)
382 deregister_user_data();
386 /**********************************
387 ****** The dissector itself ******
388 **********************************/
391 is_relevant_can_message(void *data
)
393 const struct can_info
*can_info
= (struct can_info
*)data
;
394 DISSECTOR_ASSERT(can_info
);
396 if (can_info
->id
& (CAN_ERR_FLAG
| CAN_RTR_FLAG
)) {
397 /* Error and RTR frames are not for us. */
401 if ((can_info
->id
& CAN_EFF_MASK
& g_autosar_nm_can_id_mask
) != (g_autosar_nm_can_id
& CAN_EFF_MASK
& g_autosar_nm_can_id_mask
)) {
402 /* Id doesn't match. The frame is not for us. */
410 dissect_autosar_nm(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
413 proto_tree
*autosar_nm_tree
;
414 proto_tree
*autosar_nm_subtree
= NULL
;
418 uint32_t msg_length
= 0;
419 uint32_t ctrl_bit_vector
= 0;
420 uint32_t src_node_id
= 0;
425 static int * const control_bits_3_0
[] = {
426 &hf_autosar_nm_control_bit_vector_repeat_msg_req
,
427 &hf_autosar_nm_control_bit_vector_reserved1
,
428 &hf_autosar_nm_control_bit_vector_reserved2
,
429 &hf_autosar_nm_control_bit_vector_reserved3
,
430 &hf_autosar_nm_control_bit_vector_reserved4
,
431 &hf_autosar_nm_control_bit_vector_reserved5
,
432 &hf_autosar_nm_control_bit_vector_reserved6
,
433 &hf_autosar_nm_control_bit_vector_reserved7
,
437 static int * const control_bits_3_2
[] = {
438 &hf_autosar_nm_control_bit_vector_repeat_msg_req
,
439 &hf_autosar_nm_control_bit_vector_nm_coord_id
,
440 &hf_autosar_nm_control_bit_vector_nm_coord_sleep
,
441 &hf_autosar_nm_control_bit_vector_active_wakeup
,
442 &hf_autosar_nm_control_bit_vector_reserved5
,
443 &hf_autosar_nm_control_bit_vector_pni
,
444 &hf_autosar_nm_control_bit_vector_reserved7
,
448 static int * const control_bits_4_0
[] = {
449 &hf_autosar_nm_control_bit_vector_repeat_msg_req
,
450 &hf_autosar_nm_control_bit_vector_reserved1
,
451 &hf_autosar_nm_control_bit_vector_reserved2
,
452 &hf_autosar_nm_control_bit_vector_nm_coord_sleep
,
453 &hf_autosar_nm_control_bit_vector_reserved4
,
454 &hf_autosar_nm_control_bit_vector_reserved5
,
455 &hf_autosar_nm_control_bit_vector_reserved6
,
456 &hf_autosar_nm_control_bit_vector_reserved7
,
460 static int * const control_bits_4_1
[] = {
461 &hf_autosar_nm_control_bit_vector_repeat_msg_req
,
462 &hf_autosar_nm_control_bit_vector_reserved1
,
463 &hf_autosar_nm_control_bit_vector_reserved2
,
464 &hf_autosar_nm_control_bit_vector_nm_coord_sleep
,
465 &hf_autosar_nm_control_bit_vector_active_wakeup
,
466 &hf_autosar_nm_control_bit_vector_reserved5
,
467 &hf_autosar_nm_control_bit_vector_pni
,
468 &hf_autosar_nm_control_bit_vector_reserved7
,
472 static int * const control_bits_20_11
[] = {
473 &hf_autosar_nm_control_bit_vector_repeat_msg_req
,
474 &hf_autosar_nm_control_bit_vector_pn_shutdown_request
,
475 &hf_autosar_nm_control_bit_vector_reserved2
,
476 &hf_autosar_nm_control_bit_vector_nm_coord_sleep
,
477 &hf_autosar_nm_control_bit_vector_active_wakeup
,
478 &hf_autosar_nm_control_bit_vector_pn_learning
,
479 &hf_autosar_nm_control_bit_vector_pni
,
480 &hf_autosar_nm_control_bit_vector_reserved7
,
484 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, AUTOSAR_NM_NAME
);
485 col_clear(pinfo
->cinfo
, COL_INFO
);
487 msg_length
= tvb_reported_length(tvb
);
489 ti
= proto_tree_add_item(tree
, proto_autosar_nm
, tvb
, 0, -1, ENC_NA
);
490 autosar_nm_tree
= proto_item_add_subtree(ti
, ett_autosar_nm
);
492 if (g_autosar_nm_pos_sni
!= byte_pos_off
&& g_autosar_nm_pos_sni
< g_autosar_nm_pos_cbv
) {
493 proto_tree_add_item_ret_uint(autosar_nm_tree
, hf_autosar_nm_source_node_identifier
, tvb
, g_autosar_nm_pos_sni
, 1, ENC_BIG_ENDIAN
, &src_node_id
);
496 if (g_autosar_nm_pos_cbv
!= byte_pos_off
) {
498 switch (g_autosar_nm_cbv_version
) {
499 case autosar_3_0_or_newer
:
500 proto_tree_add_bitmask(autosar_nm_tree
, tvb
, g_autosar_nm_pos_cbv
, hf_autosar_nm_control_bit_vector
, ett_autosar_nm_cbv
, control_bits_3_0
, ENC_BIG_ENDIAN
);
503 proto_tree_add_bitmask(autosar_nm_tree
, tvb
, g_autosar_nm_pos_cbv
, hf_autosar_nm_control_bit_vector
, ett_autosar_nm_cbv
, control_bits_3_2
, ENC_BIG_ENDIAN
);
506 proto_tree_add_bitmask(autosar_nm_tree
, tvb
, g_autosar_nm_pos_cbv
, hf_autosar_nm_control_bit_vector
, ett_autosar_nm_cbv
, control_bits_4_0
, ENC_BIG_ENDIAN
);
508 case autosar_4_1_or_newer
:
509 proto_tree_add_bitmask(autosar_nm_tree
, tvb
, g_autosar_nm_pos_cbv
, hf_autosar_nm_control_bit_vector
, ett_autosar_nm_cbv
, control_bits_4_1
, ENC_BIG_ENDIAN
);
512 proto_tree_add_bitmask(autosar_nm_tree
, tvb
, g_autosar_nm_pos_cbv
, hf_autosar_nm_control_bit_vector
, ett_autosar_nm_cbv
, control_bits_20_11
, ENC_BIG_ENDIAN
);
516 ctrl_bit_vector
= tvb_get_uint8(tvb
, g_autosar_nm_pos_cbv
);
519 if (g_autosar_nm_pos_sni
!= byte_pos_off
&& g_autosar_nm_pos_sni
>= g_autosar_nm_pos_cbv
) {
520 proto_tree_add_item_ret_uint(autosar_nm_tree
, hf_autosar_nm_source_node_identifier
, tvb
, g_autosar_nm_pos_sni
, 1, ENC_BIG_ENDIAN
, &src_node_id
);
523 if (g_autosar_nm_pos_cbv
> g_autosar_nm_pos_sni
) {
524 offset
= g_autosar_nm_pos_cbv
+ 1;
526 /* This covers the case that both are turned off since -1 + 1 = 0 */
527 offset
= g_autosar_nm_pos_sni
+ 1;
530 col_set_str(pinfo
->cinfo
, COL_INFO
, "NM (");
531 if (g_autosar_nm_pos_cbv
!= byte_pos_off
) {
532 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "CBV: 0x%02x", ctrl_bit_vector
);
533 proto_item_append_text(ti
, ", Control Bit Vector: 0x%02x", ctrl_bit_vector
);
534 if (g_autosar_nm_pos_sni
!= byte_pos_off
) {
535 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", SNI: 0x%02x", src_node_id
);
536 proto_item_append_text(ti
, ", Source Node: %i", src_node_id
);
539 if (g_autosar_nm_pos_sni
!= byte_pos_off
) {
540 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "SNI: 0x%02x", src_node_id
);
541 proto_item_append_text(ti
, ", Source Node: %i", src_node_id
);
544 col_append_str(pinfo
->cinfo
, COL_INFO
, ")");
546 /* now we need to process the user defined fields ... */
547 ti
= proto_tree_add_item(autosar_nm_tree
, hf_autosar_nm_user_data
, tvb
, offset
, msg_length
- offset
, ENC_NA
);
548 autosar_nm_tree
= proto_item_add_subtree(ti
, ett_autosar_nm_user_data
);
550 for (i
= 0; i
< num_user_data_fields
; i
++) {
551 tmp
= calc_hf_key(user_data_fields
[i
]);
552 hf_id
= get_hf_for_user_data(tmp
);
554 offset
= user_data_fields
[i
].udf_offset
;
555 length
= user_data_fields
[i
].udf_length
;
556 ett_id
= (get_ett_for_user_data(offset
, length
));
558 if (hf_id
&& msg_length
>= length
+ offset
) {
559 if (user_data_fields
[i
].udf_mask
== 0) {
560 ti
= proto_tree_add_item(autosar_nm_tree
, *hf_id
, tvb
, offset
, length
, ENC_BIG_ENDIAN
);
561 if (ett_id
== NULL
) {
562 autosar_nm_subtree
= NULL
;
564 autosar_nm_subtree
= proto_item_add_subtree(ti
, *ett_id
);
567 if (autosar_nm_subtree
!= NULL
) {
568 proto_tree_add_item(autosar_nm_subtree
, *hf_id
, tvb
, offset
, length
, ENC_BIG_ENDIAN
);
572 /* should we warn? */
578 col_set_fence(pinfo
->cinfo
, COL_INFO
);
584 dissect_autosar_nm_can(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
586 if (!is_relevant_can_message(data
)) {
589 return dissect_autosar_nm(tvb
, pinfo
, tree
, data
);
593 dissect_autosar_nm_can_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
595 if (!is_relevant_can_message(data
)) {
598 dissect_autosar_nm(tvb
, pinfo
, tree
, data
);
602 void proto_register_autosar_nm(void)
604 module_t
*autosar_nm_module
;
605 uat_t
* user_data_fields_uat
;
607 static hf_register_info hf_autosar_nm
[] = {
608 { &hf_autosar_nm_control_bit_vector
,
609 { "Control Bit Vector", "autosar-nm.ctrl", FT_UINT8
, BASE_HEX
, NULL
, 0x0, "The Control Bit Vector", HFILL
} },
610 { &hf_autosar_nm_control_bit_vector_repeat_msg_req
,
611 { "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
} },
612 { &hf_autosar_nm_control_bit_vector_reserved1
,
613 { "Reserved Bit 1", "autosar-nm.ctrl.reserved1", FT_UINT8
, BASE_DEC
, NULL
, 0x02, "The Reserved Bit 1", HFILL
} },
614 { &hf_autosar_nm_control_bit_vector_pn_shutdown_request
,
615 { "PN Shutdown Request", "autosar-nm.ctrl.pn_shutdown_request", FT_BOOLEAN
, 8, TFS(&tfs_autosar_nm_control_pn_shutdown_req
), 0x02, "The Partial Network Shutdown Request Bit", HFILL
} },
616 { &hf_autosar_nm_control_bit_vector_reserved2
,
617 { "Reserved Bit 2", "autosar-nm.ctrl.reserved2", FT_UINT8
, BASE_DEC
, NULL
, 0x04, "The Reserved Bit 2", HFILL
} },
618 { &hf_autosar_nm_control_bit_vector_nm_coord_id
,
619 { "NM Coordinator ID", "autosar-nm.ctrl.nm_coord_id", FT_UINT8
, BASE_DEC
, NULL
, 0x06, "The NM Coordinator Identifier", HFILL
} },
620 { &hf_autosar_nm_control_bit_vector_reserved3
,
621 { "Reserved Bit 3", "autosar-nm.ctrl.reserved3", FT_UINT8
, BASE_DEC
, NULL
, 0x08, "The Reserved Bit 3", HFILL
} },
622 { &hf_autosar_nm_control_bit_vector_nm_coord_sleep
,
623 { "NM Coordinator Sleep Ready", "autosar-nm.ctrl.nm_coord_sleep", FT_BOOLEAN
, 8, TFS(&tfs_autosar_nm_control_sleep_bit
), 0x08, "NM Coordinator Sleep Ready Bit", HFILL
} },
624 { &hf_autosar_nm_control_bit_vector_reserved4
,
625 { "Reserved Bit 4", "autosar-nm.ctrl.reserved4", FT_UINT8
, BASE_DEC
, NULL
, 0x10, "The Reserved Bit 4", HFILL
} },
626 { &hf_autosar_nm_control_bit_vector_active_wakeup
,
627 { "Active Wakeup", "autosar-nm.ctrl.active_wakeup", FT_BOOLEAN
, 8, TFS(&tfs_autosar_nm_control_active_wakeup
), 0x10, "Active Wakeup Bit", HFILL
} },
628 { &hf_autosar_nm_control_bit_vector_reserved5
,
629 { "Reserved Bit 5", "autosar-nm.ctrl.reserved5", FT_UINT8
, BASE_DEC
, NULL
, 0x20, "The Reserved Bit 5", HFILL
} },
630 { &hf_autosar_nm_control_bit_vector_pn_learning
,
631 { "PN Learning", "autosar-nm.ctrl.pn_learning", FT_BOOLEAN
, 8, TFS(&tfs_autosar_nm_control_pn_learning
), 0x20, "The Partial Network Learning Bit", HFILL
} },
632 { &hf_autosar_nm_control_bit_vector_reserved6
,
633 { "Reserved Bit 6", "autosar-nm.ctrl.reserved6",FT_UINT8
, BASE_DEC
, NULL
, 0x40, "Partial Network Information Bit", HFILL
} },
634 { &hf_autosar_nm_control_bit_vector_pni
,
635 { "Partial Network Information", "autosar-nm.ctrl.pni", FT_BOOLEAN
, 8, TFS(&tfs_autosar_nm_control_pni
), 0x40, "Partial Network Information Bit", HFILL
} },
636 { &hf_autosar_nm_control_bit_vector_reserved7
,
637 { "Reserved Bit 7", "autosar-nm.ctrl.reserved7", FT_UINT8
, BASE_DEC
, NULL
, 0x80, "The Reserved Bit 7", HFILL
} },
639 { &hf_autosar_nm_source_node_identifier
,
640 { "Source Node Identifier", "autosar-nm.src", FT_UINT8
, BASE_DEC
, NULL
, 0x0, "The identification of the sending node", HFILL
} },
642 { &hf_autosar_nm_user_data
,
643 { "User Data", "autosar-nm.user_data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, "The User Data", HFILL
} },
646 static int *ett
[] = {
649 &ett_autosar_nm_user_data
,
652 /* UAT for user_data fields */
653 static uat_field_t user_data_uat_fields
[] = {
654 UAT_FLD_CSTRING(user_data_fields
, udf_name
, "User data name", "Name of user data field"),
655 UAT_FLD_CSTRING(user_data_fields
, udf_desc
, "User data desc", "Description of user data field"),
656 UAT_FLD_DEC(user_data_fields
, udf_offset
, "User data offset", "Offset of the user data field in the AUTOSAR-NM message (uint32)"),
657 UAT_FLD_DEC(user_data_fields
, udf_length
, "User data length", "Length of the user data field in the AUTOSAR-NM message (uint32)"),
658 UAT_FLD_HEX64(user_data_fields
, udf_mask
, "User data mask", "Relevant bits of the user data field in the AUTOSAR-NM message (uint64)"),
659 UAT_FLD_CSTRING(user_data_fields
, udf_value_desc
, "User data value", "Description what the masked bits mean"),
663 /* Register the protocol name and description */
664 proto_autosar_nm
= proto_register_protocol("AUTOSAR Network Management", AUTOSAR_NM_NAME
, "autosar-nm");
665 proto_register_field_array(proto_autosar_nm
, hf_autosar_nm
, array_length(hf_autosar_nm
));
666 proto_register_alias(proto_autosar_nm
, "nm");
667 proto_register_subtree_array(ett
, array_length(ett
));
669 /* Register configuration options */
670 autosar_nm_module
= prefs_register_protocol(proto_autosar_nm
, proto_reg_handoff_autosar_nm
);
672 prefs_register_enum_preference(autosar_nm_module
, "cbv_version",
673 "Control Bit Vector version",
674 "Define the standard version that applies to the CBV field",
675 &g_autosar_nm_cbv_version
, cbv_version_vals
, false);
677 prefs_register_enum_preference(autosar_nm_module
, "cbv_position",
678 "Control Bit Vector position",
679 "Make the NM dissector interpret this byte as Control Bit Vector (CBV)",
680 &g_autosar_nm_pos_cbv
, byte_position_vals
, false);
682 prefs_register_enum_preference(autosar_nm_module
, "sni_position",
683 "Source Node Identifier position",
684 "Make the NM dissector interpret this byte as Source Node Identifier (SNI)",
685 &g_autosar_nm_pos_sni
, byte_position_vals
, false);
688 user_data_fields_uat
= uat_new("NM User Data Fields Table",
689 sizeof(user_data_field_t
), /* record size */
690 "NM_user_data_fields", /* filename */
691 true, /* from_profile */
692 &user_data_fields
, /* data_ptr */
693 &num_user_data_fields
, /* numitems_ptr */
694 UAT_AFFECTS_DISSECTION
| UAT_AFFECTS_FIELDS
, /* specifies named fields, so affects dissection and the set of named fields */
696 user_data_fields_copy_cb
, /* copy callback */
697 user_data_fields_update_cb
, /* update callback */
698 user_data_fields_free_cb
, /* free callback */
699 user_data_post_update_cb
, /* post update callback */
700 user_data_reset_cb
, /* reset callback */
701 user_data_uat_fields
); /* UAT field definitions */
703 prefs_register_uat_preference(autosar_nm_module
, "autosar_nm_user_data_fields", "User Data Field Configuration",
704 "A table to define user defined fields in the NM payload",
705 user_data_fields_uat
);
707 prefs_register_uint_preference(
708 autosar_nm_module
, "can_id",
710 "Identifier that is used to filter packets that should be dissected. "
711 "Set bit 31 when defining an extended id. "
712 "(works with the mask defined below)",
713 16, &g_autosar_nm_can_id
);
715 prefs_register_uint_preference(
716 autosar_nm_module
, "can_id_mask",
717 "AUTOSAR NM CAN id mask",
718 "Mask applied to CAN identifiers when decoding whether a packet should dissected. "
719 "Use 0xFFFFFFFF mask to require exact match.",
720 16, &g_autosar_nm_can_id_mask
);
722 range_convert_str(wmem_epan_scope(), &g_autosar_nm_pdus
, "", 0xffffffff);
723 prefs_register_range_preference(autosar_nm_module
, "pdu_transport.ids", "AUTOSAR NM PDU IDs",
724 "PDU Transport IDs.",
725 &g_autosar_nm_pdus
, 0xffffffff);
727 range_convert_str(wmem_epan_scope(), &g_autosar_nm_ipdum_pdus
, "", 0xffffffff);
728 prefs_register_range_preference(autosar_nm_module
, "ipdum.pdu.id", "AUTOSAR I-PduM PDU IDs",
729 "I-PDU Multiplexer PDU IDs.",
730 &g_autosar_nm_ipdum_pdus
, 0xffffffff);
732 nm_handle
= register_dissector("autosar-nm", dissect_autosar_nm
, proto_autosar_nm
);
733 nm_handle_can
= register_dissector("autosar-nm.can", dissect_autosar_nm_can
, proto_autosar_nm
);
736 void proto_reg_handoff_autosar_nm(void)
738 static bool initialized
= false;
741 dissector_add_for_decode_as_with_preference("udp.port", nm_handle
);
743 dissector_add_for_decode_as("can.subdissector", nm_handle_can
);
745 /* heuristics default on since they do nothing without IDs being configured */
746 heur_dissector_add("can", dissect_autosar_nm_can_heur
, "AUTOSAR NM over CAN", "autosar_nm_can_heur", proto_autosar_nm
, HEURISTIC_ENABLE
);
750 dissector_delete_all("pdu_transport.id", nm_handle
);
751 dissector_delete_all("ipdum.pdu.id", nm_handle
);
754 dissector_add_uint_range("pdu_transport.id", g_autosar_nm_pdus
, nm_handle
);
755 dissector_add_uint_range("ipdum.pdu.id", g_autosar_nm_ipdum_pdus
, nm_handle
);
764 * indent-tabs-mode: nil
767 * ex: set shiftwidth=2 tabstop=8 expandtab:
768 * :indentSize=2:tabSize=8:noTabs=true: