Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-lin.c
blob86e78fc61bcd742b34fbd7050fe4865bd88d6b62
1 /* packet-lin.c
3 * LIN dissector.
4 * By Dr. Lars Voelker <lars.voelker@technica-engineering.de>
5 * Copyright 2021-2023 Dr. Lars Voelker
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
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/decode_as.h>
18 #include <epan/prefs.h>
19 #include <wiretap/wtap.h>
20 #include <epan/expert.h>
21 #include <epan/uat.h>
23 #include "packet-lin.h"
26 * Dissector for the Local Interconnect Network (LIN) bus.
28 * see ISO 17987 or search for "LIN Specification 2.2a" online.
31 #define LIN_NAME "LIN"
32 #define LIN_NAME_LONG "LIN Protocol"
33 #define LIN_NAME_FILTER "lin"
35 static heur_dissector_list_t heur_subdissector_list;
36 static heur_dtbl_entry_t *heur_dtbl_entry;
38 static int proto_lin;
40 static dissector_handle_t lin_handle;
42 /* header field */
43 static int hf_lin_msg_format_rev;
44 static int hf_lin_reserved1;
45 static int hf_lin_payload_length;
46 static int hf_lin_message_type;
47 static int hf_lin_checksum_type;
48 static int hf_lin_pid;
49 static int hf_lin_id;
50 static int hf_lin_parity;
51 static int hf_lin_checksum;
52 static int hf_lin_err_errors;
53 static int hf_lin_err_no_slave_response;
54 static int hf_lin_err_framing;
55 static int hf_lin_err_parity;
56 static int hf_lin_err_checksum;
57 static int hf_lin_err_invalidid;
58 static int hf_lin_err_overflow;
59 static int hf_lin_event_id;
61 static int ett_lin;
62 static int ett_lin_pid;
63 static int ett_errors;
65 static int * const error_fields[] = {
66 &hf_lin_err_overflow,
67 &hf_lin_err_invalidid,
68 &hf_lin_err_checksum,
69 &hf_lin_err_parity,
70 &hf_lin_err_framing,
71 &hf_lin_err_no_slave_response,
72 NULL
75 static dissector_table_t subdissector_table;
77 #define LIN_MSG_TYPE_FRAME 0
78 #define LIN_MSG_TYPE_EVENT 3
80 static const value_string lin_msg_type_names[] = {
81 { LIN_MSG_TYPE_FRAME, "Frame" },
82 { LIN_MSG_TYPE_EVENT, "Event" },
83 {0, NULL}
86 #define LIN_CHKSUM_TYPE_UNKN_ERR 0
87 #define LIN_CHKSUM_TYPE_CLASSIC 1
88 #define LIN_CHKSUM_TYPE_ENHANCED 2
89 #define LIN_CHKSUM_TYPE_UNDEF 3
91 static const value_string lin_checksum_type_names[] = {
92 { LIN_CHKSUM_TYPE_UNKN_ERR, "Unknown/Error" },
93 { LIN_CHKSUM_TYPE_CLASSIC, "Classic" },
94 { LIN_CHKSUM_TYPE_ENHANCED, "Enhanced" },
95 { LIN_CHKSUM_TYPE_UNDEF, "Undefined" },
96 {0, NULL}
99 #define LIN_EVENT_TYPE_GO_TO_SLEEP_EVENT_BY_GO_TO_SLEEP 0xB0B00001
100 #define LIN_EVENT_TYPE_GO_TO_SLEEP_EVENT_BY_INACTIVITY 0xB0B00002
101 #define LIN_EVENT_TYPE_WAKE_UP_BY_WAKE_UP_SIGNAL 0xB0B00004
103 static const value_string lin_event_type_names[] = {
104 { LIN_EVENT_TYPE_GO_TO_SLEEP_EVENT_BY_GO_TO_SLEEP, "Go-to-Sleep event by Go-to-Sleep frame" },
105 { LIN_EVENT_TYPE_GO_TO_SLEEP_EVENT_BY_INACTIVITY, "Go-to-Sleep event by Inactivity for more than 4s" },
106 { LIN_EVENT_TYPE_WAKE_UP_BY_WAKE_UP_SIGNAL, "Wake-up event by Wake-up signal" },
107 {0, NULL}
110 void proto_reg_handoff_lin(void);
111 void proto_register_lin(void);
113 /********* UATs *********/
115 /* Interface Config UAT */
116 typedef struct _interface_config {
117 unsigned interface_id;
118 char *interface_name;
119 unsigned bus_id;
120 } interface_config_t;
122 #define DATAFILE_LIN_INTERFACE_MAPPING "LIN_interface_mapping"
124 static GHashTable *data_lin_interfaces_by_id;
125 static GHashTable *data_lin_interfaces_by_name;
126 static interface_config_t* interface_configs;
127 static unsigned interface_config_num;
129 UAT_HEX_CB_DEF(interface_configs, interface_id, interface_config_t)
130 UAT_CSTRING_CB_DEF(interface_configs, interface_name, interface_config_t)
131 UAT_HEX_CB_DEF(interface_configs, bus_id, interface_config_t)
133 static void *
134 copy_interface_config_cb(void *n, const void *o, size_t size _U_) {
135 interface_config_t *new_rec = (interface_config_t *)n;
136 const interface_config_t *old_rec = (const interface_config_t *)o;
138 new_rec->interface_id = old_rec->interface_id;
139 new_rec->interface_name = g_strdup(old_rec->interface_name);
140 new_rec->bus_id = old_rec->bus_id;
141 return new_rec;
144 static bool
145 update_interface_config(void *r, char **err) {
146 interface_config_t *rec = (interface_config_t *)r;
148 if (rec->interface_id > 0xffffffff) {
149 *err = ws_strdup_printf("We currently only support 32 bit identifiers (ID: 0x%x Name: %s)",
150 rec->interface_id, rec->interface_name);
151 return false;
154 if (rec->bus_id > 0xffff) {
155 *err = ws_strdup_printf("We currently only support 16 bit bus identifiers (ID: 0x%x Name: %s Bus-ID: 0x%x)",
156 rec->interface_id, rec->interface_name, rec->bus_id);
157 return false;
160 return true;
163 static void
164 free_interface_config_cb(void *r) {
165 interface_config_t *rec = (interface_config_t *)r;
166 /* freeing result of g_strdup */
167 g_free(rec->interface_name);
168 rec->interface_name = NULL;
171 static void
172 post_update_lin_interfaces_cb(void) {
173 unsigned i;
175 /* destroy old hash tables, if they exist */
176 if (data_lin_interfaces_by_id) {
177 g_hash_table_destroy(data_lin_interfaces_by_id);
179 if (data_lin_interfaces_by_name) {
180 g_hash_table_destroy(data_lin_interfaces_by_name);
183 /* create new hash table */
184 data_lin_interfaces_by_id = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, NULL);
185 data_lin_interfaces_by_name = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
187 for (i = 0; i < interface_config_num; i++) {
188 if (interface_configs[i].interface_id != 0xfffffff) {
189 g_hash_table_insert(data_lin_interfaces_by_id, GUINT_TO_POINTER(interface_configs[i].interface_id), &interface_configs[i]);
192 if (interface_configs[i].interface_name != NULL && interface_configs[i].interface_name[0] != 0) {
193 g_hash_table_insert(data_lin_interfaces_by_name, interface_configs[i].interface_name, &interface_configs[i]);
198 /* We match based on the config in the following order:
199 * - interface_name matches and interface_id matches
200 * - interface_name matches and interface_id = 0xffffffff
201 * - interface_name = "" and interface_id matches
204 static unsigned
205 get_bus_id(packet_info *pinfo) {
206 if (!(pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID)) {
207 return 0;
210 uint32_t interface_id = pinfo->rec->rec_header.packet_header.interface_id;
211 unsigned section_number = pinfo->rec->presence_flags & WTAP_HAS_SECTION_NUMBER ? pinfo->rec->section_number : 0;
212 const char *interface_name = epan_get_interface_name(pinfo->epan, interface_id, section_number);
213 interface_config_t *tmp = NULL;
215 if (interface_name != NULL && interface_name[0] != 0) {
216 tmp = g_hash_table_lookup(data_lin_interfaces_by_name, interface_name);
218 if (tmp != NULL && (tmp->interface_id == 0xffffffff || tmp->interface_id == interface_id)) {
219 /* name + id match or name match and id = any */
220 return tmp->bus_id;
223 tmp = g_hash_table_lookup(data_lin_interfaces_by_id, GUINT_TO_POINTER(interface_id));
225 if (tmp != NULL && (tmp->interface_name == NULL || tmp->interface_name[0] == 0)) {
226 /* id matches and name is any */
227 return tmp->bus_id;
231 /* we found nothing */
232 return 0;
235 /* Senders and Receivers UAT */
236 typedef struct _sender_receiver_config {
237 unsigned bus_id;
238 unsigned lin_id;
239 char *sender_name;
240 char *receiver_name;
241 } sender_receiver_config_t;
243 #define DATAFILE_LIN_SENDER_RECEIVER "LIN_senders_receivers"
245 static GHashTable *data_sender_receiver;
246 static sender_receiver_config_t* sender_receiver_configs;
247 static unsigned sender_receiver_config_num;
249 UAT_HEX_CB_DEF(sender_receiver_configs, bus_id, sender_receiver_config_t)
250 UAT_HEX_CB_DEF(sender_receiver_configs, lin_id, sender_receiver_config_t)
251 UAT_CSTRING_CB_DEF(sender_receiver_configs, sender_name, sender_receiver_config_t)
252 UAT_CSTRING_CB_DEF(sender_receiver_configs, receiver_name, sender_receiver_config_t)
254 static void *
255 copy_sender_receiver_config_cb(void *n, const void *o, size_t size _U_) {
256 sender_receiver_config_t *new_rec = (sender_receiver_config_t *)n;
257 const sender_receiver_config_t *old_rec = (const sender_receiver_config_t *)o;
259 new_rec->bus_id = old_rec->bus_id;
260 new_rec->lin_id = old_rec->lin_id;
261 new_rec->sender_name = g_strdup(old_rec->sender_name);
262 new_rec->receiver_name = g_strdup(old_rec->receiver_name);
263 return new_rec;
266 static bool
267 update_sender_receiver_config(void *r, char **err) {
268 sender_receiver_config_t *rec = (sender_receiver_config_t *)r;
270 if (rec->lin_id > 0x3f) {
271 *err = ws_strdup_printf("LIN IDs need to be between 0x00 and 0x3f (Bus ID: %i LIN ID: %i)", rec->bus_id, rec->lin_id);
272 return false;
275 if (rec->bus_id > 0xffff) {
276 *err = ws_strdup_printf("We currently only support 16 bit bus identifiers (Bus ID: %i LIN ID: %i)", rec->bus_id, rec->lin_id);
277 return false;
280 return true;
283 static void
284 free_sender_receiver_config_cb(void *r) {
285 sender_receiver_config_t *rec = (sender_receiver_config_t *)r;
286 /* freeing result of g_strdup */
287 g_free(rec->sender_name);
288 rec->sender_name = NULL;
289 g_free(rec->receiver_name);
290 rec->receiver_name = NULL;
293 static uint64_t
294 sender_receiver_key(uint16_t bus_id, uint32_t lin_id) {
295 return ((uint64_t)bus_id << 32) | lin_id;
298 static sender_receiver_config_t *
299 ht_lookup_sender_receiver_config(uint16_t bus_id, uint32_t lin_id) {
300 sender_receiver_config_t *tmp;
301 uint64_t key;
303 key = sender_receiver_key(bus_id, lin_id);
304 tmp = g_hash_table_lookup(data_sender_receiver, &key);
306 if (tmp == NULL) {
307 key = sender_receiver_key(0, lin_id);
308 tmp = g_hash_table_lookup(data_sender_receiver, &key);
311 return tmp;
314 static void
315 post_update_sender_receiver_cb(void) {
316 unsigned i;
317 uint64_t *key;
319 /* destroy old hash table, if it exist */
320 if (data_sender_receiver) {
321 g_hash_table_destroy(data_sender_receiver);
324 /* create new hash table */
325 data_sender_receiver = g_hash_table_new_full(g_int64_hash, g_int64_equal, g_free, NULL);
327 for (i = 0; i < sender_receiver_config_num; i++) {
328 key = g_new(uint64_t, 1);
329 *key = sender_receiver_key(sender_receiver_configs[i].bus_id, sender_receiver_configs[i].lin_id);
330 g_hash_table_insert(data_sender_receiver, key, &sender_receiver_configs[i]);
334 bool
335 lin_set_source_and_destination_columns(packet_info* pinfo, lin_info_t *lininfo) {
336 sender_receiver_config_t *tmp = ht_lookup_sender_receiver_config(lininfo->bus_id, lininfo->id);
338 if (tmp != NULL) {
339 /* remove all addresses to support LIN as payload (e.g., TECMP) */
340 clear_address(&pinfo->net_src);
341 clear_address(&pinfo->dl_src);
342 clear_address(&pinfo->src);
343 clear_address(&pinfo->net_dst);
344 clear_address(&pinfo->dl_dst);
345 clear_address(&pinfo->dst);
347 col_add_str(pinfo->cinfo, COL_DEF_SRC, tmp->sender_name);
348 col_add_str(pinfo->cinfo, COL_DEF_DST, tmp->receiver_name);
349 return true;
351 return false;
354 static int
355 dissect_lin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
356 proto_item *ti;
357 proto_item *ti_root;
358 proto_tree *lin_tree;
359 proto_tree *lin_id_tree;
360 tvbuff_t *next_tvb;
362 unsigned payload_length;
363 unsigned msg_type;
364 lin_info_t lininfo;
365 uint64_t errors;
367 col_set_str(pinfo->cinfo, COL_PROTOCOL, LIN_NAME);
368 col_clear(pinfo->cinfo, COL_INFO);
370 ti_root = proto_tree_add_item(tree, proto_lin, tvb, 0, -1, ENC_NA);
371 lin_tree = proto_item_add_subtree(ti_root, ett_lin);
373 proto_tree_add_item(lin_tree, hf_lin_msg_format_rev, tvb, 0, 1, ENC_BIG_ENDIAN);
374 ti = proto_tree_add_item(lin_tree, hf_lin_reserved1, tvb, 1, 3, ENC_BIG_ENDIAN);
375 proto_item_set_hidden(ti);
377 proto_tree_add_item_ret_uint(lin_tree, hf_lin_payload_length, tvb, 4, 1, ENC_BIG_ENDIAN, &payload_length);
378 proto_tree_add_item_ret_uint(lin_tree, hf_lin_message_type, tvb, 4, 1, ENC_BIG_ENDIAN, &msg_type);
379 if (msg_type != LIN_MSG_TYPE_EVENT) {
380 proto_tree_add_item(lin_tree, hf_lin_checksum_type, tvb, 4, 1, ENC_BIG_ENDIAN);
382 ti = proto_tree_add_item(lin_tree, hf_lin_pid, tvb, 5, 1, ENC_BIG_ENDIAN);
383 lin_id_tree = proto_item_add_subtree(ti, ett_lin_pid);
384 proto_tree_add_item(lin_id_tree, hf_lin_parity, tvb, 5, 1, ENC_BIG_ENDIAN);
385 proto_tree_add_item_ret_uint(lin_id_tree, hf_lin_id, tvb, 5, 1, ENC_BIG_ENDIAN, &(lininfo.id));
387 proto_tree_add_item(lin_tree, hf_lin_checksum, tvb, 6, 1, ENC_BIG_ENDIAN);
389 lininfo.bus_id = (uint16_t)get_bus_id(pinfo);
390 lininfo.len = 0;
391 lin_set_source_and_destination_columns(pinfo, &lininfo);
393 proto_tree_add_bitmask_ret_uint64(lin_tree, tvb, 7, hf_lin_err_errors, ett_errors, error_fields, ENC_BIG_ENDIAN, &errors);
395 col_add_fstr(pinfo->cinfo, COL_INFO, "LIN %s", val_to_str(msg_type, lin_msg_type_names, "(0x%02x)"));
397 if (errors != 0) {
398 col_append_str(pinfo->cinfo, COL_INFO, " - ERR");
399 proto_item_set_end(ti_root, tvb, 8);
400 return 8;
403 switch (msg_type) {
404 case LIN_MSG_TYPE_EVENT: {
405 unsigned event_id;
406 proto_tree_add_item_ret_uint(lin_tree, hf_lin_event_id, tvb, 8, 4, ENC_BIG_ENDIAN, &event_id);
407 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str(event_id, lin_event_type_names, "0x%08x"));
408 proto_item_set_end(ti_root, tvb, 12);
409 return 12; /* 8 Byte header + 4 Byte payload */
411 break;
413 case LIN_MSG_TYPE_FRAME:
414 if (payload_length > 0) {
415 next_tvb = tvb_new_subset_length(tvb, 8, payload_length);
416 proto_item_set_end(ti_root, tvb, 8 + payload_length);
417 lininfo.len = (uint16_t)payload_length;
419 uint32_t bus_frame_id = lininfo.id | (lininfo.bus_id << 16);
420 if (!dissector_try_uint_with_data(subdissector_table, bus_frame_id, next_tvb, pinfo, tree, true, &lininfo)) {
421 if (!dissector_try_uint_with_data(subdissector_table, lininfo.id, next_tvb, pinfo, tree, true, &lininfo)) {
422 if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &heur_dtbl_entry, &lininfo)) {
423 call_data_dissector(next_tvb, pinfo, tree);
428 break;
431 /* format pads to 4 bytes*/
432 if (payload_length <= 4) {
433 proto_item_set_end(ti_root, tvb, 12);
434 return 12;
435 } else if (payload_length <= 8) {
436 proto_item_set_end(ti_root, tvb, 16);
437 return 16;
438 } else {
439 return tvb_captured_length(tvb);
443 void
444 proto_register_lin(void) {
445 module_t *lin_module;
446 uat_t *lin_interface_uat = NULL;
447 uat_t *sender_receiver_uat = NULL;
449 static hf_register_info hf[] = {
450 { &hf_lin_msg_format_rev,
451 { "Message Format Revision", "lin.message_format",
452 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
453 { &hf_lin_reserved1,
454 { "Reserved", "lin.reserved",
455 FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL }},
456 { &hf_lin_payload_length,
457 { "Length", "lin.length",
458 FT_UINT8, BASE_DEC, NULL, 0xf0, NULL, HFILL }},
459 { &hf_lin_message_type,
460 { "Message Type", "lin.message_type",
461 FT_UINT8, BASE_DEC, VALS(lin_msg_type_names), 0x0c, NULL, HFILL }},
462 { &hf_lin_checksum_type,
463 { "Checksum Type", "lin.checksum_type",
464 FT_UINT8, BASE_DEC, VALS(lin_checksum_type_names), 0x03, NULL, HFILL }},
465 { &hf_lin_pid,
466 { "Protected ID", "lin.protected_id",
467 FT_UINT8, BASE_HEX_DEC, NULL, 0x00, NULL, HFILL }},
468 { &hf_lin_id,
469 { "Frame ID", "lin.frame_id",
470 FT_UINT8, BASE_HEX_DEC, NULL, 0x3f, NULL, HFILL }},
471 { &hf_lin_parity,
472 { "Parity", "lin.frame_parity",
473 FT_UINT8, BASE_HEX_DEC, NULL, 0xc0, NULL, HFILL }},
474 { &hf_lin_checksum,
475 { "Checksum", "lin.checksum",
476 FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
477 { &hf_lin_err_errors,
478 { "Errors", "lin.errors",
479 FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
480 { &hf_lin_err_no_slave_response,
481 { "No Slave Response Error", "lin.errors.no_slave_response",
482 FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
483 { &hf_lin_err_framing,
484 { "Framing Error", "lin.errors.framing_error",
485 FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
486 { &hf_lin_err_parity,
487 { "Parity Error", "lin.errors.parity_error",
488 FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
489 { &hf_lin_err_checksum,
490 { "Checksum Error", "lin.errors.checksum_error",
491 FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
492 { &hf_lin_err_invalidid,
493 { "Invalid ID Error", "lin.errors.invalid_id_error",
494 FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }},
495 { &hf_lin_err_overflow,
496 { "Overflow Error", "lin.errors.overflow_error",
497 FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }},
498 { &hf_lin_event_id,
499 { "Event ID", "lin.event_id",
500 FT_UINT32, BASE_HEX_DEC, VALS(lin_event_type_names), 0x00, NULL, HFILL }},
503 static int *ett[] = {
504 &ett_lin,
505 &ett_lin_pid,
506 &ett_errors,
509 proto_lin = proto_register_protocol(LIN_NAME_LONG, LIN_NAME, LIN_NAME_FILTER);
510 lin_module = prefs_register_protocol(proto_lin, NULL);
512 proto_register_field_array(proto_lin, hf, array_length(hf));
513 proto_register_subtree_array(ett, array_length(ett));
515 lin_handle = register_dissector(LIN_NAME_FILTER, dissect_lin, proto_lin);
517 /* the lin.frame_id subdissector table carries the bus id in the higher 16 bits */
518 subdissector_table = register_dissector_table("lin.frame_id", "LIN Frame ID", proto_lin, FT_UINT8, BASE_HEX);
519 heur_subdissector_list = register_heur_dissector_list_with_description(LIN_NAME_FILTER, "LIN Message data fallback", proto_lin);
521 static uat_field_t lin_interface_mapping_uat_fields[] = {
522 UAT_FLD_HEX(interface_configs, interface_id, "Interface ID", "ID of the Interface with 0xffffffff = any (hex uint32 without leading 0x)"),
523 UAT_FLD_CSTRING(interface_configs, interface_name, "Interface Name", "Name of the Interface, empty = any (string)"),
524 UAT_FLD_HEX(interface_configs, bus_id, "Bus ID", "Bus ID of the Interface (hex uint16 without leading 0x)"),
525 UAT_END_FIELDS
528 lin_interface_uat = uat_new("LIN Interface Mapping",
529 sizeof(interface_config_t), /* record size */
530 DATAFILE_LIN_INTERFACE_MAPPING, /* filename */
531 true, /* from profile */
532 (void**)&interface_configs, /* data_ptr */
533 &interface_config_num, /* numitems_ptr */
534 UAT_AFFECTS_DISSECTION, /* but not fields */
535 NULL, /* help */
536 copy_interface_config_cb, /* copy callback */
537 update_interface_config, /* update callback */
538 free_interface_config_cb, /* free callback */
539 post_update_lin_interfaces_cb, /* post update callback */
540 NULL, /* reset callback */
541 lin_interface_mapping_uat_fields /* UAT field definitions */
544 prefs_register_uat_preference(lin_module, "_lin_interface_mapping", "Interface Mapping",
545 "A table to define the mapping between interface and Bus ID.", lin_interface_uat);
547 static uat_field_t sender_receiver_mapping_uat_fields[] = {
548 UAT_FLD_HEX(sender_receiver_configs, bus_id, "Bus ID", "Bus ID of the Interface with 0 meaning any (hex uint16 without leading 0x)."),
549 UAT_FLD_HEX(sender_receiver_configs, lin_id, "LIN ID", "ID of the LIN Message (hex uint6 without leading 0x)"),
550 UAT_FLD_CSTRING(sender_receiver_configs, sender_name, "Sender Name", "Name of Sender(s)"),
551 UAT_FLD_CSTRING(sender_receiver_configs, receiver_name, "Receiver Name", "Name of Receiver(s)"),
552 UAT_END_FIELDS
555 sender_receiver_uat = uat_new("Sender Receiver Config",
556 sizeof(sender_receiver_config_t), /* record size */
557 DATAFILE_LIN_SENDER_RECEIVER, /* filename */
558 true, /* from profile */
559 (void**)&sender_receiver_configs, /* data_ptr */
560 &sender_receiver_config_num, /* numitems_ptr */
561 UAT_AFFECTS_DISSECTION, /* but not fields */
562 NULL, /* help */
563 copy_sender_receiver_config_cb, /* copy callback */
564 update_sender_receiver_config, /* update callback */
565 free_sender_receiver_config_cb, /* free callback */
566 post_update_sender_receiver_cb, /* post update callback */
567 NULL, /* reset callback */
568 sender_receiver_mapping_uat_fields /* UAT field definitions */
571 prefs_register_uat_preference(lin_module, "_sender_receiver_config", "Sender Receiver Config",
572 "A table to define the mapping between Bus ID and LIN ID to Sender and Receiver.", sender_receiver_uat);
575 void
576 proto_reg_handoff_lin(void) {
577 dissector_add_uint("wtap_encap", WTAP_ENCAP_LIN, lin_handle);
581 * Editor modelines - https://www.wireshark.org/tools/modelines.html
583 * Local variables:
584 * c-basic-offset: 4
585 * tab-width: 8
586 * indent-tabs-mode: nil
587 * End:
589 * vi: set shiftwidth=4 tabstop=8 expandtab:
590 * :indentSize=4:tabSize=8:noTabs=true: