1 /* packet-uds.c
2  * Routines for uds protocol packet disassembly
3  *
4  * Wireshark - Network traffic analyzer
5  * By Gerald Combs <gerald@wireshark.org>
6  * Copyright 1998 Gerald Combs
7  *
8  * SPDX-License-Identifier: GPL-2.0-or-later
9  */
10 
11 #include "config.h"
12 
13 #include <epan/packet.h>
14 #include <epan/uat.h>
15 #include <wsutil/bits_ctz.h>
16 #include <epan/dissectors/packet-doip.h>
17 #include <epan/dissectors/packet-iso10681.h>
18 #include <epan/dissectors/packet-iso15765.h>
19 
20 void proto_register_uds(void);
21 void proto_reg_handoff_uds(void);
22 
23 #define DATAFILE_UDS_ROUTINE_IDS "UDS_routine_identifiers"
24 #define DATAFILE_UDS_DATA_IDS    "UDS_data_identifiers"
25 
26 #define UDS_SERVICES_DSC     0x10
27 #define UDS_SERVICES_ER      0x11
28 #define UDS_SERVICES_CDTCI   0x14
29 #define UDS_SERVICES_RDTCI   0x19
30 #define UDS_SERVICES_RDBI    0x22
31 #define UDS_SERVICES_RMBA    0x23
32 #define UDS_SERVICES_RSDBI   0x24
33 #define UDS_SERVICES_SA      0x27
34 #define UDS_SERVICES_CC      0x28
35 #define UDS_SERVICES_RDBPI   0x2A
36 #define UDS_SERVICES_DDDI    0x2C
37 #define UDS_SERVICES_WDBI    0x2E
38 #define UDS_SERVICES_IOCBI   0x2F
39 #define UDS_SERVICES_RC      0x31
40 #define UDS_SERVICES_RD      0x34
41 #define UDS_SERVICES_RU      0x35
42 #define UDS_SERVICES_TD      0x36
43 #define UDS_SERVICES_RTE     0x37
44 #define UDS_SERVICES_RFT     0x38
45 #define UDS_SERVICES_WMBA    0x3D
46 #define UDS_SERVICES_TP      0x3E
47 #define UDS_SERVICES_ERR     0x3F
48 #define UDS_SERVICES_CDTCS   0x85
49 
50 #define UDS_RESPONSE_CODES_GR       0x10
51 #define UDS_RESPONSE_CODES_SNS      0x11
52 #define UDS_RESPONSE_CODES_SFNS     0x12
53 #define UDS_RESPONSE_CODES_IMLOIF   0x13
54 #define UDS_RESPONSE_CODES_RTL      0x14
55 #define UDS_RESPONSE_CODES_BRR      0x21
56 #define UDS_RESPONSE_CODES_CNC      0x22
57 #define UDS_RESPONSE_CODES_RSE      0x24
58 #define UDS_RESPONSE_CODES_NRFSC    0x25
59 #define UDS_RESPONSE_CODES_FPEORA   0x26
60 #define UDS_RESPONSE_CODES_ROOR     0x31
61 #define UDS_RESPONSE_CODES_SAD      0x33
62 #define UDS_RESPONSE_CODES_IK       0x35
63 #define UDS_RESPONSE_CODES_ENOA     0x36
64 #define UDS_RESPONSE_CODES_RTDNE    0x37
65 #define UDS_RESPONSE_CODES_UDNA     0x70
66 #define UDS_RESPONSE_CODES_TDS      0x71
67 #define UDS_RESPONSE_CODES_GPF      0x72
68 #define UDS_RESPONSE_CODES_WBSC     0x73
69 #define UDS_RESPONSE_CODES_RCRRP    0x78
70 #define UDS_RESPONSE_CODES_SFNSIAS  0x7E
71 #define UDS_RESPONSE_CODES_SNSIAS   0x7F
72 
73 
74 #define UDS_SID_MASK    0xBF
75 #define UDS_REPLY_MASK  0x40
76 #define UDS_SID_OFFSET  0
77 #define UDS_SID_LEN     1
78 #define UDS_DATA_OFFSET 1
79 
80 #define UDS_DSC_TYPE_OFFSET      (UDS_DATA_OFFSET + 0)
81 #define UDS_DSC_TYPE_LEN         1
82 #define UDS_DSC_PARAMETER_RECORD_OFFSET  (UDS_DSC_TYPE_OFFSET + UDS_DSC_TYPE_LEN)
83 
84 #define UDS_DSC_TYPES_DEFAULT_SESSION                   1
85 #define UDS_DSC_TYPES_PROGRAMMING_SESSION               2
86 #define UDS_DSC_TYPES_EXTENDED_DIAGNOSTIC_SESSION       3
87 #define UDS_DSC_TYPES_SAFETY_SYSTEM_DIAGNOSTIC_SESSION  4
88 
89 #define UDS_ER_TYPE_OFFSET   (UDS_DATA_OFFSET + 0)
90 #define UDS_ER_TYPE_LEN      1
91 
92 #define UDS_ER_TYPES_HARD_RESET                   1
93 #define UDS_ER_TYPES_KEY_ON_OFF_RESET             2
94 #define UDS_ER_TYPES_SOFT_RESET                   3
95 #define UDS_ER_TYPES_ENABLE_RAPID_POWER_SHUTDOWN  4
96 #define UDS_ER_TYPES_DISABLE_RAPID_POWER_SHUTDOWN 5
97 
98 #define UDS_RDTCI_TYPE_OFFSET   (UDS_DATA_OFFSET + 0)
99 #define UDS_RDTCI_TYPE_LEN      1
100 #define UDS_RDTCI_RECORD_OFFSET (UDS_RDTCI_TYPE_OFFSET + UDS_RDTCI_TYPE_LEN)
101 
102 #define UDS_RDTCI_TYPES_NUMBER_BY_STATUS_MASK     0x1
103 #define UDS_RDTCI_TYPES_BY_STATUS_MASK            0x2
104 #define UDS_RDTCI_TYPES_SNAPSHOT_IDENTIFICATION   0x3
105 #define UDS_RDTCI_TYPES_SNAPSHOT_RECORD_BY_DTC    0x4
106 #define UDS_RDTCI_TYPES_SNAPSHOT_RECORD_BY_RECORD 0x5
107 #define UDS_RDTCI_TYPES_EXTENDED_RECARD_BY_DTC    0x6
108 #define UDS_RDTCI_TYPES_SUPPORTED_DTC             0xA
109 
110 #define UDS_RDBI_DATA_IDENTIFIER_OFFSET (UDS_DATA_OFFSET + 0)
111 #define UDS_RDBI_DATA_IDENTIFIER_LEN    2
112 #define UDS_RDBI_DATA_RECORD_OFFSET     (UDS_RDBI_DATA_IDENTIFIER_OFFSET + UDS_RDBI_DATA_IDENTIFIER_LEN)
113 
114 #define UDS_SA_TYPE_OFFSET (UDS_DATA_OFFSET + 0)
115 #define UDS_SA_TYPE_LEN    1
116 #define UDS_SA_KEY_OFFSET  (UDS_SA_TYPE_OFFSET + UDS_SA_TYPE_LEN)
117 #define UDS_SA_SEED_OFFSET (UDS_SA_TYPE_OFFSET + UDS_SA_TYPE_LEN)
118 
119 #define UDS_SA_TYPES_SEED   1
120 #define UDS_SA_TYPES_KEY    2
121 #define UDS_SA_TYPES_SEED_2 3
122 #define UDS_SA_TYPES_KEY_2  4
123 
124 #define UDS_WDBI_DATA_IDENTIFIER_OFFSET (UDS_DATA_OFFSET + 0)
125 #define UDS_WDBI_DATA_IDENTIFIER_LEN    2
126 #define UDS_WDBI_DATA_RECORD_OFFSET     (UDS_WDBI_DATA_IDENTIFIER_OFFSET + UDS_WDBI_DATA_IDENTIFIER_LEN)
127 
128 #define UDS_IOCBI_DATA_IDENTIFIER_OFFSET (UDS_DATA_OFFSET + 0)
129 #define UDS_IOCBI_DATA_IDENTIFIER_LEN    2
130 #define UDS_IOCBI_PARAMETER_OFFSET       (UDS_IOCBI_DATA_IDENTIFIER_OFFSET + UDS_IOCBI_DATA_IDENTIFIER_LEN)
131 #define UDS_IOCBI_PARAMETER_LEN          1
132 #define UDS_IOCBI_STATE_OFFSET           (UDS_IOCBI_PARAMETER_OFFSET + UDS_IOCBI_PARAMETER_LEN)
133 
134 #define UDS_IOCBI_PARAMETERS_RETURN_CONTROL_TO_ECU 0
135 #define UDS_IOCBI_PARAMETERS_RESET_TO_DEFAULT      1
136 #define UDS_IOCBI_PARAMETERS_FREEZE_CURRENT_STATE  2
137 #define UDS_IOCBI_PARAMETERS_SHORT_TERM_ADJUSTMENT 3
138 
139 #define UDS_RC_TYPE_OFFSET          (UDS_DATA_OFFSET + 0)
140 #define UDS_RC_TYPE_LEN             1
141 #define UDS_RC_ROUTINE_OFFSET       (UDS_RC_TYPE_OFFSET + UDS_RC_TYPE_LEN)
142 #define UDS_RC_ROUTINE_LEN          2
143 #define UDS_RC_OPTION_RECORD_OFFSET (UDS_RC_ROUTINE_OFFSET + UDS_RC_ROUTINE_LEN)
144 #define UDS_RC_INFO_OFFSET          (UDS_RC_ROUTINE_OFFSET + UDS_RC_ROUTINE_LEN)
145 #define UDS_RC_INFO_LEN             1
146 #define UDS_RC_STATUS_RECORD_OFFSET (UDS_RC_INFO_OFFSET + UDS_RC_INFO_LEN)
147 
148 #define UDS_RC_TYPES_START   1
149 #define UDS_RC_TYPES_STOP    2
150 #define UDS_RC_TYPES_REQUEST 3
151 
152 #define UDS_RD_DATA_FORMAT_IDENTIFIER_OFFSET               (UDS_DATA_OFFSET + 0)
153 #define UDS_RD_DATA_FORMAT_IDENTIFIER_LEN                  1
154 #define UDS_RD_COMPRESSION_METHOD_MASK                     0xF0
155 #define UDS_RD_ENCRYPTING_METHOD_MASK                      0x0F
156 #define UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_OFFSET (UDS_RD_DATA_FORMAT_IDENTIFIER_OFFSET + UDS_RD_DATA_FORMAT_IDENTIFIER_LEN)
157 #define UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_LEN    1
158 #define UDS_RD_MEMORY_SIZE_LENGTH_MASK                     0xF0
159 #define UDS_RD_MEMORY_ADDRESS_LENGTH_MASK                  0x0F
160 #define UDS_RD_MEMORY_ADDRESS_OFFSET                       (UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_OFFSET + UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_LEN)
161 #define UDS_RD_LENGTH_FORMAT_IDENTIFIER_OFFSET             (UDS_DATA_OFFSET + 0)
162 #define UDS_RD_LENGTH_FORMAT_IDENTIFIER_LEN                1
163 #define UDS_RD_MAX_NUMBER_OF_BLOCK_LENGTH_LENGTH_MASK      0xF0
164 #define UDS_RD_MAX_NUMBER_OF_BLOCK_LENGTH_OFFSET           (UDS_RD_LENGTH_FORMAT_IDENTIFIER_OFFSET + UDS_RD_LENGTH_FORMAT_IDENTIFIER_LEN)
165 
166 #define UDS_TD_SEQUENCE_COUNTER_OFFSET                (UDS_DATA_OFFSET + 0)
167 #define UDS_TD_SEQUENCE_COUNTER_LEN                   1
168 
169 #define UDS_TP_SUB_FUNCTION_OFFSET                    (UDS_DATA_OFFSET + 0)
170 #define UDS_TP_SUB_FUNCTION_LEN                       1
171 #define UDS_TP_SUB_FUNCTION_MASK                      0x7f
172 #define UDS_TP_SUPPRESS_POS_RSP_MSG_INDIFICATION_MASK 0x80
173 
174 #define UDS_ERR_SID_OFFSET   (UDS_DATA_OFFSET + 0)
175 #define UDS_ERR_SID_LEN      1
176 #define UDS_ERR_CODE_OFFSET  (UDS_ERR_SID_OFFSET + UDS_ERR_SID_LEN)
177 #define UDS_ERR_CODE_LEN     1
178 
179 #define UDS_CDTCS_TYPE_OFFSET (UDS_DATA_OFFSET + 0)
180 #define UDS_CDTCS_TYPE_LEN    1
181 
182 #define UDS_CDTCS_ACTIONS_ON  1
183 #define UDS_CDTCS_ACTIONS_OFF 2
184 
185 /*
186  * Enums
187  */
188 
189 /* Services */
190 static const value_string uds_services[]= {
191         {UDS_SERVICES_DSC,   "Diagnostic Session Control"},
192         {UDS_SERVICES_ER,    "ECU Reset"},
193         {UDS_SERVICES_CDTCI, "Clear Diagnostic Information"},
194         {UDS_SERVICES_RDTCI, "Read DTC Information"},
195         {UDS_SERVICES_RDBI,  "Read Data By Identifier"},
196         {UDS_SERVICES_RMBA,  "Read Memory By Address"},
197         {UDS_SERVICES_RSDBI, "Read Scaling Data By Identifier"},
198         {UDS_SERVICES_SA,    "Security Access"},
199         {UDS_SERVICES_CC,    "Communication Control"},
200         {UDS_SERVICES_RDBPI, "Read Data By Periodic Identifier"},
201         {UDS_SERVICES_DDDI,  "Dynamically Define Data Identifier"},
202         {UDS_SERVICES_WDBI,  "Write Data By Identifier"},
203         {UDS_SERVICES_IOCBI, "Input Output Control By Identifier"},
204         {UDS_SERVICES_RC,    "Routine Control"},
205         {UDS_SERVICES_RD,    "Request Download"},
206         {UDS_SERVICES_RU,    "Request Upload"},
207         {UDS_SERVICES_TD,    "Transfer Data"},
208         {UDS_SERVICES_RTE,   "Request Transfer Exit"},
209         {UDS_SERVICES_RFT,   "Request File Transfer"},
210         {UDS_SERVICES_WMBA,  "Write Memory By Address"},
211         {UDS_SERVICES_TP,    "Tester Present"},
212         {UDS_SERVICES_ERR,   "Error"},
213         {UDS_SERVICES_CDTCS, "Control DTC Setting"},
214         {0, NULL}
215 };
216 /* Response code */
217 static const value_string uds_response_codes[]= {
218         {UDS_RESPONSE_CODES_GR,      "General reject"},
219         {UDS_RESPONSE_CODES_SNS,     "Service not supported"},
220         {UDS_RESPONSE_CODES_SFNS,    "Sub-Function Not Supported"},
221         {UDS_RESPONSE_CODES_IMLOIF,  "Incorrect Message Length or Invalid Format"},
222         {UDS_RESPONSE_CODES_RTL,     "Response too long"},
223         {UDS_RESPONSE_CODES_BRR,     "Busy repeat request"},
224         {UDS_RESPONSE_CODES_CNC,     "Conditions Not Correct"},
225         {UDS_RESPONSE_CODES_RSE,     "Request Sequence Error"},
226         {UDS_RESPONSE_CODES_NRFSC,   "No response from sub-net component"},
227         {UDS_RESPONSE_CODES_FPEORA,  "Failure prevents execution of requested action"},
228         {UDS_RESPONSE_CODES_ROOR,    "Request Out of Range"},
229         {UDS_RESPONSE_CODES_SAD,     "Security Access Denied"},
230         {UDS_RESPONSE_CODES_IK,      "Invalid Key"},
231         {UDS_RESPONSE_CODES_ENOA,    "Exceeded Number Of Attempts"},
232         {UDS_RESPONSE_CODES_RTDNE,   "Required Time Delay Not Expired"},
233         {UDS_RESPONSE_CODES_UDNA,    "Upload/Download not accepted"},
234         {UDS_RESPONSE_CODES_TDS,     "Transfer data suspended"},
235         {UDS_RESPONSE_CODES_GPF,     "General Programming Failure"},
236         {UDS_RESPONSE_CODES_WBSC,    "Wrong Block Sequence Counter"},
237         {UDS_RESPONSE_CODES_RCRRP,   "Request correctly received, but response is pending"},
238         {UDS_RESPONSE_CODES_SFNSIAS, "Sub-Function not supported in active session"},
239         {UDS_RESPONSE_CODES_SNSIAS,  "Service not supported in active session"},
240         {0, NULL}
241 };
242 
243 /* DSC */
244 static const value_string uds_dsc_types[] = {
245         {0,                                             "Reserved"},
246         {UDS_DSC_TYPES_DEFAULT_SESSION,                 "Default Session"},
247         {UDS_DSC_TYPES_PROGRAMMING_SESSION,             "Programming Session"},
248         {UDS_DSC_TYPES_EXTENDED_DIAGNOSTIC_SESSION,     "Extended Diagnostic Session"},
249         {UDS_DSC_TYPES_SAFETY_SYSTEM_DIAGNOSTIC_SESSION, "Safety System Diagnostic Session"},
250         {0, NULL}
251 };
252 
253 /* ER */
254 static const value_string uds_er_types[] = {
255         {0,                                         "Reserved"},
256         {UDS_ER_TYPES_HARD_RESET,                   "Hard Reset"},
257         {UDS_ER_TYPES_KEY_ON_OFF_RESET,             "Key On Off Reset"},
258         {UDS_ER_TYPES_SOFT_RESET,                   "Soft Reset"},
259         {UDS_ER_TYPES_ENABLE_RAPID_POWER_SHUTDOWN,  "Enable Rapid Power Shutdown"},
260         {UDS_ER_TYPES_DISABLE_RAPID_POWER_SHUTDOWN, "Disable Rapid Power Shutdown"},
261         {0, NULL}
262 };
263 
264 /* SA */
265 static const value_string uds_sa_types[] = {
266         {UDS_SA_TYPES_SEED,   "Request Seed"},
267         {UDS_SA_TYPES_KEY,    "Send Key"},
268         {UDS_SA_TYPES_SEED_2, "Request Seed"},
269         {UDS_SA_TYPES_KEY_2,  "Send Key"},
270         {0, NULL}
271 };
272 
273 /* RDTCI */
274 static const value_string uds_rdtci_types[] = {
275         {UDS_RDTCI_TYPES_NUMBER_BY_STATUS_MASK,     "Report Number of DTC by Status Mask"},
276         {UDS_RDTCI_TYPES_BY_STATUS_MASK,            "Report DTC by Status Mask"},
277         {UDS_RDTCI_TYPES_SNAPSHOT_IDENTIFICATION,   "Report DTC Snapshot Identification"},
278         {UDS_RDTCI_TYPES_SNAPSHOT_RECORD_BY_DTC,    "Report DTC Snapshot Record by DTC Number"},
279         {UDS_RDTCI_TYPES_SNAPSHOT_RECORD_BY_RECORD, "Report DTC Snapshot Record by Record Number"},
280         {UDS_RDTCI_TYPES_EXTENDED_RECARD_BY_DTC,    "Report DTC Extended Data Record by DTC Number"},
281         {UDS_RDTCI_TYPES_SUPPORTED_DTC,             "Report Supported DTC"},
282         {0, NULL}
283 };
284 
285 /* IOCBI */
286 static const value_string uds_iocbi_parameters[] = {
287         {UDS_IOCBI_PARAMETERS_RETURN_CONTROL_TO_ECU, "Return Control To ECU"},
288         {UDS_IOCBI_PARAMETERS_RESET_TO_DEFAULT,      "Reset To Default"},
289         {UDS_IOCBI_PARAMETERS_FREEZE_CURRENT_STATE,  "Freeze Current State"},
290         {UDS_IOCBI_PARAMETERS_SHORT_TERM_ADJUSTMENT, "Short Term Adjustment"},
291         {0, NULL}
292 };
293 
294 /* RC */
295 static const value_string uds_rc_types[] = {
296         {0,                    "Reserved"},
297         {UDS_RC_TYPES_START,   "Start routine"},
298         {UDS_RC_TYPES_STOP,    "Stop routine"},
299         {UDS_RC_TYPES_REQUEST, "Request routine result"},
300         {0, NULL}
301 };
302 
303 /* CDTCS */
304 static const value_string uds_cdtcs_types[] = {
305         {0,                     "Reserved"},
306         {UDS_CDTCS_ACTIONS_ON,  "On"},
307         {UDS_CDTCS_ACTIONS_OFF, "Off"},
308         {0, NULL}
309 };
310 
311 /*
312  * Fields
313  */
314 static int hf_uds_service = -1;
315 static int hf_uds_reply = -1;
316 
317 static int hf_uds_dsc_type = -1;
318 static int hf_uds_dsc_parameter_record = -1;
319 
320 static int hf_uds_er_type = -1;
321 
322 static int hf_uds_rdtci_type = -1;
323 static int hf_uds_rdtci_record = -1;
324 
325 static int hf_uds_rdbi_data_identifier = -1;
326 static int hf_uds_rdbi_data_record = -1;
327 
328 static int hf_uds_sa_type = -1;
329 static int hf_uds_sa_key = -1;
330 static int hf_uds_sa_seed = -1;
331 
332 static int hf_uds_wdbi_data_identifier = -1;
333 static int hf_uds_wdbi_data_record = -1;
334 
335 static int hf_uds_iocbi_data_identifier = -1;
336 static int hf_uds_iocbi_parameter = -1;
337 static int hf_uds_iocbi_state = -1;
338 
339 static int hf_uds_rc_type = -1;
340 static int hf_uds_rc_identifier = -1;
341 static int hf_uds_rc_option_record = -1;
342 static int hf_uds_rc_info = -1;
343 static int hf_uds_rc_status_record = -1;
344 
345 static int hf_uds_rd_compression_method = -1;
346 static int hf_uds_rd_encrypting_method = -1;
347 static int hf_uds_rd_memory_size_length = -1;
348 static int hf_uds_rd_memory_address_length = -1;
349 static int hf_uds_rd_memory_address = -1;
350 static int hf_uds_rd_memory_size = -1;
351 static int hf_uds_rd_max_number_of_block_length_length = -1;
352 static int hf_uds_rd_max_number_of_block_length = -1;
353 
354 static int hf_uds_td_sequence_counter = -1;
355 
356 static int hf_uds_tp_sub_function = -1;
357 static int hf_uds_tp_suppress_pos_rsp_msg_indification = -1;
358 
359 static int hf_uds_err_sid = -1;
360 static int hf_uds_err_code = -1;
361 
362 static int hf_uds_cdtcs_type = -1;
363 
364 /*
365  * Trees
366  */
367 static gint ett_uds = -1;
368 static gint ett_uds_dsc = -1;
369 static gint ett_uds_er = -1;
370 static gint ett_uds_rdtci = -1;
371 static gint ett_uds_rdbi = -1;
372 static gint ett_uds_sa = -1;
373 static gint ett_uds_wdbi = -1;
374 static gint ett_uds_iocbi = -1;
375 static gint ett_uds_rc = -1;
376 static gint ett_uds_rd = -1;
377 static gint ett_uds_td = -1;
378 static gint ett_uds_tp = -1;
379 static gint ett_uds_err = -1;
380 static gint ett_uds_cdtcs = -1;
381 
382 static int proto_uds = -1;
383 
384 static dissector_handle_t uds_handle;
385 static dissector_handle_t uds_handle_doip;
386 static dissector_handle_t uds_handle_iso10681;
387 static dissector_handle_t uds_handle_iso15765;
388 
389 
390 /*** Configuration ***/
391 typedef struct _generic_addr_id_string {
392     guint32  address;
393     guint    id;
394     gchar   *name;
395 } generic_addr_id_string_t;
396 
397 static void *
copy_generic_one_id_string_cb(void * n,const void * o,size_t size _U_)398 copy_generic_one_id_string_cb(void *n, const void *o, size_t size _U_) {
399     generic_addr_id_string_t *new_rec = (generic_addr_id_string_t *)n;
400     const generic_addr_id_string_t *old_rec = (const generic_addr_id_string_t *)o;
401 
402     new_rec->name = g_strdup(old_rec->name);
403     new_rec->id = old_rec->id;
404     new_rec->address = old_rec->address;
405     return new_rec;
406 }
407 
408 static gboolean
update_generic_addr_id_16bit(void * r,char ** err)409 update_generic_addr_id_16bit(void *r, char **err) {
410     generic_addr_id_string_t *rec = (generic_addr_id_string_t *)r;
411 
412     if (rec->id > 0xffff) {
413         *err = g_strdup_printf("We currently only support 16 bit identifiers (Addr: %x ID: %i  Name: %s)", rec->address, rec->id, rec->name);
414         return FALSE;
415     }
416 
417     if (rec->address > 0xffff && rec->address != G_MAXUINT32) {
418         *err = g_strdup_printf("We currently only support 16 bit addresses with 0xffffffff = \"don't care\" (Addr: %x  ID: %i  Name: %s)",
419                                 rec->address, rec->id, rec->name);
420         return FALSE;
421     }
422 
423     if (rec->name == NULL || rec->name[0] == 0) {
424         *err = g_strdup("Name cannot be empty");
425         return FALSE;
426     }
427 
428     return TRUE;
429 }
430 
431 static void
free_generic_one_id_string_cb(void * r)432 free_generic_one_id_string_cb(void *r) {
433     generic_addr_id_string_t *rec = (generic_addr_id_string_t *)r;
434 
435     /* freeing result of g_strdup */
436     g_free(rec->name);
437     rec->name = NULL;
438 }
439 
440 static gint64
calc_key(guint32 addr,guint16 id)441 calc_key(guint32 addr, guint16 id) {
442     return ((gint64)id << 32) | (gint64)addr;
443 }
444 
445 static void
post_update_one_id_string_template_cb(generic_addr_id_string_t * data,guint data_num,GHashTable * ht)446 post_update_one_id_string_template_cb(generic_addr_id_string_t *data, guint data_num, GHashTable *ht) {
447     guint   i;
448     gint64 *key = NULL;
449 
450     for (i = 0; i < data_num; i++) {
451         key = wmem_new(wmem_epan_scope(), gint64);
452         *key = calc_key(data[i].address, data[i].id);
453 
454         g_hash_table_insert(ht, key, g_strdup(data[i].name));
455     }
456 }
457 
458 static char *
generic_lookup_addr_id(guint32 addr,guint16 id,GHashTable * ht)459 generic_lookup_addr_id(guint32 addr, guint16 id, GHashTable *ht) {
460     char *ret = NULL;
461 
462     /* we only currently allow 16bit + MAXUINT32 as any */
463     if (addr > G_MAXUINT16 && addr != G_MAXUINT32) {
464         addr = G_MAXUINT32;
465     }
466 
467     guint64 tmp = calc_key(addr, id);
468 
469     if (ht == NULL) {
470         return NULL;
471     }
472 
473     ret = (char *)g_hash_table_lookup(ht, &tmp);
474     if (ret == NULL) {
475         tmp = calc_key(G_MAXUINT32, id);
476         return (char *)g_hash_table_lookup(ht, &tmp);
477     }
478 
479     return ret;
480 }
481 
482 static void
simple_free_key(gpointer key)483 simple_free_key(gpointer key) {
484     wmem_free(wmem_epan_scope(), key);
485 }
486 
487 static void
simple_free(gpointer data)488 simple_free(gpointer data) {
489     /* we need to free because of the g_strdup in post_update*/
490     g_free(data);
491 }
492 
493 
494 /* Routine IDs */
495 static generic_addr_id_string_t *uds_uat_routine_ids = NULL;
496 static guint uds_uat_routine_id_num = 0;
497 static GHashTable *uds_ht_routine_ids = NULL;
498 
UAT_HEX_CB_DEF(uds_uat_routine_ids,address,generic_addr_id_string_t)499 UAT_HEX_CB_DEF(uds_uat_routine_ids, address, generic_addr_id_string_t)
500 UAT_HEX_CB_DEF(uds_uat_routine_ids, id, generic_addr_id_string_t)
501 UAT_CSTRING_CB_DEF(uds_uat_routine_ids, name, generic_addr_id_string_t)
502 
503 static void
504 post_update_uds_routine_cb(void) {
505     /* destroy old hash table, if it exists */
506     if (uds_ht_routine_ids) {
507         g_hash_table_destroy(uds_ht_routine_ids);
508     }
509 
510     /* create new hash table */
511     uds_ht_routine_ids = g_hash_table_new_full(g_int64_hash, g_int64_equal, &simple_free_key, &simple_free);
512     post_update_one_id_string_template_cb(uds_uat_routine_ids, uds_uat_routine_id_num, uds_ht_routine_ids);
513 }
514 
515 static char *
uds_lookup_routine_name(guint32 addr,guint16 id)516 uds_lookup_routine_name(guint32 addr, guint16 id) {
517     return generic_lookup_addr_id(addr, id, uds_ht_routine_ids);
518 }
519 
520 static void
protoitem_append_routine_name(proto_item * ti,guint32 addr,guint16 data_identifier)521 protoitem_append_routine_name(proto_item *ti, guint32 addr, guint16 data_identifier) {
522     gchar *routine_name = uds_lookup_routine_name(addr, data_identifier);
523     if (routine_name != NULL) {
524         proto_item_append_text(ti, " (%s)", routine_name);
525     }
526 }
527 
528 static void
infocol_append_routine_name(packet_info * pinfo,guint32 addr,guint16 routine_identifier)529 infocol_append_routine_name(packet_info *pinfo, guint32 addr, guint16 routine_identifier) {
530     gchar *routine_name = uds_lookup_routine_name(addr, routine_identifier);
531     if (routine_name != NULL) {
532         col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", routine_name);
533     }
534 }
535 
536 
537 /* Data IDs */
538 static generic_addr_id_string_t *uds_uat_data_ids = NULL;
539 static guint uds_uat_data_id_num = 0;
540 static GHashTable *uds_ht_data_ids = NULL;
541 
UAT_HEX_CB_DEF(uds_uat_data_ids,address,generic_addr_id_string_t)542 UAT_HEX_CB_DEF(uds_uat_data_ids, address, generic_addr_id_string_t)
543 UAT_HEX_CB_DEF(uds_uat_data_ids, id, generic_addr_id_string_t)
544 UAT_CSTRING_CB_DEF(uds_uat_data_ids, name, generic_addr_id_string_t)
545 
546 static void
547 post_update_uds_data_cb(void) {
548     /* destroy old hash table, if it exists */
549     if (uds_ht_data_ids) {
550         g_hash_table_destroy(uds_ht_data_ids);
551     }
552 
553     /* create new hash table */
554     uds_ht_data_ids = g_hash_table_new_full(g_int64_hash, g_int64_equal, &simple_free_key, &simple_free);
555     post_update_one_id_string_template_cb(uds_uat_data_ids, uds_uat_data_id_num, uds_ht_data_ids);
556 }
557 
558 static char *
uds_lookup_data_name(guint32 addr,guint16 id)559 uds_lookup_data_name(guint32 addr, guint16 id) {
560     return generic_lookup_addr_id(addr, id, uds_ht_data_ids);
561 }
562 
563 static void
protoitem_append_data_name(proto_item * ti,guint32 addr,guint16 data_identifier)564 protoitem_append_data_name(proto_item *ti, guint32 addr, guint16 data_identifier) {
565     gchar *data_name = uds_lookup_data_name(addr, data_identifier);
566     if (data_name != NULL) {
567         proto_item_append_text(ti, " (%s)", data_name);
568     }
569 }
570 
571 static void
infocol_append_data_name(packet_info * pinfo,guint32 addr,guint16 data_identifier)572 infocol_append_data_name(packet_info *pinfo, guint32 addr, guint16 data_identifier) {
573     gchar *data_name = uds_lookup_data_name(addr, data_identifier);
574     if (data_name != NULL) {
575         col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", data_name);
576     }
577 }
578 
579 /*** Configuration End ***/
580 
581 
582 static
masked_guint8_value(const guint8 value,const guint8 mask)583 guint8 masked_guint8_value(const guint8 value, const guint8 mask)
584 {
585     return (value & mask) >> ws_ctz(mask);
586 }
587 
588 static guint64
tvb_get_guintX(tvbuff_t * tvb,const gint offset,const gint size,const guint encoding)589 tvb_get_guintX(tvbuff_t *tvb, const gint offset, const gint size, const guint encoding) {
590     switch (size) {
591         case 1:
592             return tvb_get_guint8(tvb, offset);
593         case 2:
594             return tvb_get_guint16(tvb, offset, encoding);
595         case 3:
596             return tvb_get_guint24(tvb, offset, encoding);
597         case 4:
598             return tvb_get_guint32(tvb, offset, encoding);
599         case 5:
600             return tvb_get_guint40(tvb, offset, encoding);
601         case 6:
602             return tvb_get_guint48(tvb, offset, encoding);
603         case 7:
604             return tvb_get_guint56(tvb, offset, encoding);
605         case 8:
606             return tvb_get_guint64(tvb, offset, encoding);
607     }
608 
609     return 0;
610 }
611 
612 static int
dissect_uds_internal(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,guint16 source_address,guint16 target_address,guint8 number_of_addresses_valid)613 dissect_uds_internal(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 source_address, guint16 target_address, guint8 number_of_addresses_valid)
614 {
615     proto_tree *uds_tree, *subtree;
616     proto_item *ti;
617     guint8      sid, service;
618     guint32     enum_val;
619     const char *service_name;
620     guint32     ecu_address;
621     guint32     data_length = tvb_reported_length(tvb);
622 
623     col_set_str(pinfo->cinfo, COL_PROTOCOL, "UDS");
624     col_clear(pinfo->cinfo,COL_INFO);
625 
626     sid = tvb_get_guint8(tvb, UDS_SID_OFFSET);
627     service = sid & UDS_SID_MASK;
628     service_name = val_to_str(service, uds_services, "Unknown (0x%02x)");
629 
630     col_add_fstr(pinfo->cinfo, COL_INFO, "%-7s   %-36s", (sid & UDS_REPLY_MASK)? "Reply": "Request", service_name);
631 
632     ti = proto_tree_add_item(tree, proto_uds, tvb, 0, -1, ENC_NA);
633     uds_tree = proto_item_add_subtree(ti, ett_uds);
634     proto_tree_add_item(uds_tree, hf_uds_service, tvb, UDS_SID_OFFSET, UDS_SID_LEN, ENC_BIG_ENDIAN);
635     proto_tree_add_item(uds_tree, hf_uds_reply, tvb, UDS_SID_OFFSET, UDS_SID_LEN, ENC_BIG_ENDIAN);
636 
637     if (sid & UDS_REPLY_MASK) {
638         ecu_address = source_address;
639     } else {
640         ecu_address = target_address;
641     }
642 
643     switch (number_of_addresses_valid) {
644     case 0:
645         ecu_address = G_MAXUINT32;
646         break;
647     case 1:
648         proto_item_append_text(ti, ", Address: 0x%04x", source_address);
649         break;
650     case 2:
651         proto_item_append_text(ti, ", Source: 0x%04x, Target: 0x%04x", source_address, target_address);
652         break;
653     }
654 
655     switch (service) {
656         case UDS_SERVICES_DSC:
657             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_dsc, NULL, service_name);
658             proto_tree_add_item_ret_uint(subtree, hf_uds_dsc_type, tvb, UDS_DSC_TYPE_OFFSET, UDS_DSC_TYPE_LEN,
659                                 ENC_BIG_ENDIAN, &enum_val);
660             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s", val_to_str(enum_val, uds_dsc_types, "Unknown (0x%02x)"));
661 
662             if (sid & UDS_REPLY_MASK) {
663                 guint32 parameter_record_length = data_length - UDS_DSC_PARAMETER_RECORD_OFFSET;
664                 proto_tree_add_item(subtree, hf_uds_dsc_parameter_record, tvb,
665                                     UDS_DSC_PARAMETER_RECORD_OFFSET, parameter_record_length, ENC_NA);
666                 col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
667                                 tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_DSC_PARAMETER_RECORD_OFFSET,
668                                                        parameter_record_length, ' '));
669             }
670             break;
671 
672         case UDS_SERVICES_ER:
673             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_er, NULL, service_name);
674             proto_tree_add_item_ret_uint(subtree, hf_uds_er_type, tvb, UDS_ER_TYPE_OFFSET, UDS_ER_TYPE_LEN, ENC_BIG_ENDIAN, &enum_val);
675             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s", val_to_str(enum_val, uds_er_types, "Unknown (0x%02x)"));
676             break;
677 
678         case UDS_SERVICES_RDTCI: {
679             guint32 record_length = data_length - UDS_RDTCI_RECORD_OFFSET;
680 
681             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_rdtci, NULL, service_name);
682             proto_tree_add_item_ret_uint(subtree, hf_uds_rdtci_type, tvb, UDS_RDTCI_TYPE_OFFSET,
683                                 UDS_RDTCI_TYPE_LEN, ENC_BIG_ENDIAN, &enum_val);
684             proto_tree_add_item(subtree, hf_uds_rdtci_record, tvb,
685                                 UDS_RDTCI_RECORD_OFFSET, record_length, ENC_NA);
686             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s    %s", val_to_str(enum_val, uds_rdtci_types, "Unknown (0x%02x)"),
687                             tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_RDTCI_RECORD_OFFSET, record_length, ' '));
688             break;
689         }
690         case UDS_SERVICES_RDBI:
691             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_rdbi, NULL, service_name);
692             if (sid & UDS_REPLY_MASK) {
693                 /* Can't know the size of the data for each identifier, Decode like if there is only one idenfifier */
694                 guint32 record_length = data_length - UDS_RDBI_DATA_RECORD_OFFSET;
695                 guint32 data_identifier;
696                 ti = proto_tree_add_item_ret_uint(subtree, hf_uds_rdbi_data_identifier, tvb,
697                                                   UDS_RDBI_DATA_IDENTIFIER_OFFSET, UDS_RDBI_DATA_IDENTIFIER_LEN,
698                                                   ENC_BIG_ENDIAN, &data_identifier);
699                 protoitem_append_data_name(ti, ecu_address, (guint16)data_identifier);
700 
701                 proto_tree_add_item(subtree, hf_uds_rdbi_data_record, tvb, UDS_RDBI_DATA_RECORD_OFFSET,
702                                     record_length, ENC_NA);
703                 col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%04x", data_identifier);
704                 infocol_append_data_name(pinfo, ecu_address, data_identifier);
705                 col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
706                                 tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_RDBI_DATA_RECORD_OFFSET,
707                                                        record_length, ' '));
708             } else {
709                 guint32 identifier_length = data_length - UDS_RDBI_DATA_IDENTIFIER_OFFSET;
710                 guint32 offset = UDS_RDBI_DATA_IDENTIFIER_OFFSET;
711                 while (identifier_length > 0) {
712                     guint32 data_identifier;
713                     ti = proto_tree_add_item_ret_uint(subtree, hf_uds_rdbi_data_identifier, tvb, offset,
714                                                       UDS_RDBI_DATA_IDENTIFIER_LEN, ENC_BIG_ENDIAN, &data_identifier);
715                     protoitem_append_data_name(ti, ecu_address, (guint16)data_identifier);
716 
717                     col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%04x", data_identifier);
718                     infocol_append_data_name(pinfo, ecu_address, data_identifier);
719                     offset += UDS_RDBI_DATA_IDENTIFIER_LEN;
720                     identifier_length -= UDS_RDBI_DATA_IDENTIFIER_LEN;
721                 }
722             }
723             break;
724 
725         case UDS_SERVICES_SA:
726             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_sa, NULL, service_name);
727             proto_tree_add_item_ret_uint(subtree, hf_uds_sa_type, tvb, UDS_SA_TYPE_OFFSET,
728                                 UDS_SA_TYPE_LEN, ENC_BIG_ENDIAN, &enum_val);
729             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
730                             val_to_str(enum_val, uds_sa_types, "Unknown (0x%02x)"));
731 
732             if (sid & UDS_REPLY_MASK) {
733                 guint32 seed_length = data_length - UDS_SA_SEED_OFFSET;
734                 if (seed_length > 0) {
735                     proto_tree_add_item(subtree, hf_uds_sa_seed, tvb, UDS_SA_SEED_OFFSET, seed_length, ENC_NA);
736                     col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
737                                     tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_SA_SEED_OFFSET, seed_length,
738                                                            ' '));
739                 }
740             } else {
741                 guint32 key_length = data_length - UDS_SA_KEY_OFFSET;
742                 if (key_length > 0) {
743                     proto_tree_add_item(subtree, hf_uds_sa_key, tvb, UDS_SA_KEY_OFFSET, key_length, ENC_NA);
744                     col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
745                                     tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_SA_KEY_OFFSET, key_length,
746                                                            ' '));
747                 }
748             }
749             break;
750 
751         case UDS_SERVICES_WDBI:
752             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_wdbi, NULL, service_name);
753             ti = proto_tree_add_item_ret_uint(subtree, hf_uds_wdbi_data_identifier, tvb,
754                                               UDS_WDBI_DATA_IDENTIFIER_OFFSET, UDS_WDBI_DATA_IDENTIFIER_LEN,
755                                               ENC_BIG_ENDIAN, &enum_val);
756             protoitem_append_data_name(ti, ecu_address, (guint16)enum_val);
757             if (sid & UDS_REPLY_MASK) {
758                 col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%04x", enum_val);
759                 infocol_append_data_name(pinfo, ecu_address, enum_val);
760             } else {
761                 guint32 record_length = data_length - UDS_WDBI_DATA_RECORD_OFFSET;
762                 proto_tree_add_item(subtree, hf_uds_wdbi_data_record, tvb, UDS_WDBI_DATA_RECORD_OFFSET,
763                                     record_length, ENC_NA);
764                 col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%04x", enum_val);
765                 infocol_append_data_name(pinfo, ecu_address, enum_val);
766                 col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
767                                 tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_WDBI_DATA_RECORD_OFFSET,
768                                                        record_length, ' '));
769             }
770             break;
771 
772         case UDS_SERVICES_IOCBI: {
773             guint32 data_identifier;
774             guint32 state_length = data_length - UDS_IOCBI_STATE_OFFSET;
775 
776             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_iocbi, NULL, service_name);
777             ti = proto_tree_add_item_ret_uint(subtree, hf_uds_iocbi_data_identifier, tvb,
778                                               UDS_IOCBI_DATA_IDENTIFIER_OFFSET, UDS_IOCBI_DATA_IDENTIFIER_LEN,
779                                               ENC_BIG_ENDIAN, &data_identifier);
780             protoitem_append_data_name(ti, ecu_address, (guint16)data_identifier);
781 
782             proto_tree_add_item_ret_uint(subtree, hf_uds_iocbi_parameter, tvb, UDS_IOCBI_PARAMETER_OFFSET,
783                                          UDS_IOCBI_PARAMETER_LEN, ENC_BIG_ENDIAN, &enum_val);
784 
785             proto_tree_add_item(subtree, hf_uds_iocbi_state, tvb, UDS_IOCBI_STATE_OFFSET,
786                                 state_length, ENC_NA);
787             col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%04x", data_identifier);
788             infocol_append_data_name(pinfo, ecu_address, data_identifier);
789             col_append_fstr(pinfo->cinfo, COL_INFO, "  %s %s",
790                             val_to_str(enum_val, uds_iocbi_parameters, "Unknown (0x%02x)"),
791                             tvb_bytes_to_str_punct(pinfo->pool, tvb, UDS_IOCBI_STATE_OFFSET,
792                                                    state_length, ' '));
793             break;
794         }
795         case UDS_SERVICES_RC: {
796             guint32 identifier;
797 
798             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_rc, NULL, service_name);
799             proto_tree_add_item_ret_uint(subtree, hf_uds_rc_type, tvb, UDS_RC_TYPE_OFFSET,
800                                 UDS_RC_TYPE_LEN, ENC_BIG_ENDIAN, &enum_val);
801 
802             ti = proto_tree_add_item_ret_uint(subtree, hf_uds_rc_identifier, tvb, UDS_RC_ROUTINE_OFFSET,
803                                 UDS_RC_ROUTINE_LEN, ENC_BIG_ENDIAN, &identifier);
804             protoitem_append_routine_name(ti, ecu_address, identifier);
805 
806             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s 0x%04x",
807                             val_to_str(enum_val, uds_rc_types, "Unknown (0x%02x)"), identifier);
808             infocol_append_routine_name(pinfo, ecu_address, identifier);
809             if (sid & UDS_REPLY_MASK) {
810                 guint32 rc_data_len = data_length - UDS_RC_INFO_OFFSET;
811                 if (rc_data_len > 0) {
812                     guint8 info = tvb_get_guint8(tvb, UDS_RC_INFO_OFFSET);
813                     proto_tree_add_item(subtree, hf_uds_rc_info, tvb,
814                                         UDS_RC_INFO_OFFSET, UDS_RC_INFO_LEN, ENC_BIG_ENDIAN);
815                     col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%x", info);
816                     if (rc_data_len > 1) {
817                         guint32 status_record_len = data_length - UDS_RC_STATUS_RECORD_OFFSET;
818                         proto_tree_add_item(subtree, hf_uds_rc_status_record, tvb,
819                                             UDS_RC_STATUS_RECORD_OFFSET, status_record_len, ENC_NA);
820                         col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
821                                         tvb_bytes_to_str_punct(pinfo->pool, tvb,
822                                                                UDS_RC_STATUS_RECORD_OFFSET, status_record_len, ' '));
823                     }
824                 }
825             } else {
826                 guint32 option_record_len = data_length - UDS_RC_OPTION_RECORD_OFFSET;
827                 if (option_record_len > 0) {
828                     proto_tree_add_item(subtree, hf_uds_rc_option_record, tvb,
829                                         UDS_RC_OPTION_RECORD_OFFSET, option_record_len, ENC_NA);
830                     col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
831                                     tvb_bytes_to_str_punct(pinfo->pool, tvb,
832                                                            UDS_RC_OPTION_RECORD_OFFSET, option_record_len, ' '));
833                 }
834             }
835             break;
836         }
837         case UDS_SERVICES_RD:
838             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_rd, NULL, service_name);
839             if (sid & UDS_REPLY_MASK) {
840                 guint8 length_format_identifier, max_number_of_block_length_length;
841                 guint64 max_number_of_block_length;
842 
843                 length_format_identifier = tvb_get_guint8(tvb, UDS_RD_LENGTH_FORMAT_IDENTIFIER_OFFSET);
844                 max_number_of_block_length_length = masked_guint8_value(length_format_identifier,
845                                                                         UDS_RD_MAX_NUMBER_OF_BLOCK_LENGTH_LENGTH_MASK);
846                 proto_tree_add_item(subtree, hf_uds_rd_max_number_of_block_length_length, tvb,
847                                     UDS_RD_LENGTH_FORMAT_IDENTIFIER_OFFSET,
848                                     UDS_RD_LENGTH_FORMAT_IDENTIFIER_LEN, ENC_BIG_ENDIAN);
849 
850                 max_number_of_block_length = tvb_get_guintX(tvb, UDS_RD_MAX_NUMBER_OF_BLOCK_LENGTH_OFFSET,
851                                                             max_number_of_block_length_length, ENC_BIG_ENDIAN);
852                 proto_tree_add_item(subtree, hf_uds_rd_max_number_of_block_length, tvb,
853                                     UDS_RD_MAX_NUMBER_OF_BLOCK_LENGTH_OFFSET,
854                                     max_number_of_block_length_length, ENC_BIG_ENDIAN);
855 
856                 col_append_fstr(pinfo->cinfo, COL_INFO, "   Max Number Of Block Length 0x%" G_GINT64_MODIFIER "x",
857                                 max_number_of_block_length);
858             } else {
859                 guint8 data_format_identifier, compression, encryting;
860                 guint8 address_and_length_format_idenfifier, memory_size_length, memory_address_length;
861                 guint64 memory_size, memory_address;
862 
863                 data_format_identifier = tvb_get_guint8(tvb, UDS_RD_DATA_FORMAT_IDENTIFIER_OFFSET);
864 
865                 compression = masked_guint8_value(data_format_identifier, UDS_RD_COMPRESSION_METHOD_MASK);
866                 proto_tree_add_item(subtree, hf_uds_rd_compression_method, tvb,
867                                     UDS_RD_DATA_FORMAT_IDENTIFIER_OFFSET,
868                                     UDS_RD_DATA_FORMAT_IDENTIFIER_LEN, ENC_BIG_ENDIAN);
869 
870                 encryting = masked_guint8_value(data_format_identifier, UDS_RD_ENCRYPTING_METHOD_MASK);
871                 proto_tree_add_item(subtree, hf_uds_rd_encrypting_method, tvb, UDS_RD_DATA_FORMAT_IDENTIFIER_OFFSET,
872                                     UDS_RD_DATA_FORMAT_IDENTIFIER_LEN, ENC_BIG_ENDIAN);
873 
874                 address_and_length_format_idenfifier = tvb_get_guint8(tvb, UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_OFFSET);
875 
876                 memory_size_length = masked_guint8_value(address_and_length_format_idenfifier,
877                                                          UDS_RD_COMPRESSION_METHOD_MASK);
878                 proto_tree_add_item(subtree, hf_uds_rd_memory_size_length, tvb,
879                                     UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_OFFSET,
880                                     UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_LEN, ENC_BIG_ENDIAN);
881 
882                 memory_address_length = masked_guint8_value(address_and_length_format_idenfifier,
883                                                             UDS_RD_ENCRYPTING_METHOD_MASK);
884                 proto_tree_add_item(subtree, hf_uds_rd_memory_address_length, tvb,
885                                     UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_OFFSET,
886                                     UDS_RD_ADDRESS_AND_LENGTH_FORMAT_IDENTIFIER_LEN, ENC_BIG_ENDIAN);
887 
888                 memory_address = tvb_get_guintX(tvb, UDS_RD_MEMORY_ADDRESS_OFFSET, memory_address_length,
889                                                 ENC_BIG_ENDIAN);
890                 proto_tree_add_item(subtree, hf_uds_rd_memory_address, tvb, UDS_RD_MEMORY_ADDRESS_OFFSET,
891                                     memory_address_length, ENC_BIG_ENDIAN);
892                 memory_size = tvb_get_guintX(tvb, UDS_RD_MEMORY_ADDRESS_OFFSET + memory_address_length,
893                                              memory_size_length, ENC_BIG_ENDIAN);
894                 proto_tree_add_item(subtree, hf_uds_rd_memory_size, tvb,
895                                     UDS_RD_MEMORY_ADDRESS_OFFSET + memory_address_length,
896                                     memory_size_length, ENC_BIG_ENDIAN);
897 
898                 col_append_fstr(pinfo->cinfo, COL_INFO, "   0x%" G_GINT64_MODIFIER "x bytes at 0x%" G_GINT64_MODIFIER "x", memory_size, memory_address);
899 
900                 col_append_fstr(pinfo->cinfo, COL_INFO, "   (Compression:0x%x Encrypting:0x%x)", compression,
901                                 encryting);
902             }
903             break;
904 
905         case UDS_SERVICES_TD: {
906             guint32 sequence_no;
907             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_td, NULL, service_name);
908 
909             proto_tree_add_item_ret_uint(subtree, hf_uds_td_sequence_counter, tvb,
910                                      UDS_TD_SEQUENCE_COUNTER_OFFSET, UDS_TD_SEQUENCE_COUNTER_LEN, ENC_NA, &sequence_no);
911             col_append_fstr(pinfo->cinfo, COL_INFO, "   Block Sequence Counter %d", sequence_no);
912             break;
913         }
914         case UDS_SERVICES_TP: {
915             guint8 sub_function_a, sub_function;
916             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_tp, NULL, service_name);
917 
918             sub_function_a = tvb_get_guint8(tvb, UDS_TP_SUB_FUNCTION_OFFSET);
919             sub_function = masked_guint8_value(sub_function_a, UDS_TP_SUB_FUNCTION_MASK);
920             proto_tree_add_item(subtree, hf_uds_tp_sub_function, tvb,
921                                 UDS_TP_SUB_FUNCTION_OFFSET, UDS_TP_SUB_FUNCTION_LEN, ENC_BIG_ENDIAN);
922 
923             col_append_fstr(pinfo->cinfo, COL_INFO, "   Sub-function %x", sub_function);
924 
925             if (!(sid & UDS_REPLY_MASK)) {
926                 guint8 suppress = masked_guint8_value(sub_function_a, UDS_TP_SUPPRESS_POS_RSP_MSG_INDIFICATION_MASK);
927 
928                 proto_tree_add_item(subtree, hf_uds_tp_suppress_pos_rsp_msg_indification, tvb,
929                                     UDS_TP_SUB_FUNCTION_OFFSET, UDS_TP_SUB_FUNCTION_LEN, ENC_BIG_ENDIAN);
930 
931                 if (suppress) {
932                     col_append_fstr(pinfo->cinfo, COL_INFO, "   (Reply suppressed)");
933                 }
934             }
935             break;
936         }
937         case UDS_SERVICES_ERR: {
938             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_err, NULL, service_name);
939 
940             proto_tree_add_item_ret_uint(subtree, hf_uds_err_sid, tvb, UDS_ERR_SID_OFFSET, UDS_ERR_SID_LEN, ENC_BIG_ENDIAN, &enum_val);
941             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s", val_to_str(enum_val, uds_services, "Unknown (0x%02x)"));
942             proto_tree_add_item_ret_uint(subtree, hf_uds_err_code, tvb, UDS_ERR_CODE_OFFSET, UDS_ERR_CODE_LEN,
943                                 ENC_BIG_ENDIAN, &enum_val);
944             col_append_fstr(pinfo->cinfo, COL_INFO, " (SID: %s)", val_to_str(enum_val, uds_response_codes, "Unknown (0x%02x)"));
945             break;
946         }
947         case UDS_SERVICES_CDTCS: {
948             subtree = proto_tree_add_subtree(uds_tree, tvb, 0, -1, ett_uds_cdtcs, NULL, service_name);
949             proto_tree_add_item_ret_uint(subtree, hf_uds_cdtcs_type, tvb,
950                                 UDS_CDTCS_TYPE_OFFSET, UDS_CDTCS_TYPE_LEN, ENC_BIG_ENDIAN, &enum_val);
951             col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
952                             val_to_str(enum_val, uds_cdtcs_types, "Unknown (0x%02x)"));
953             break;
954         }
955     }
956 
957     return tvb_captured_length(tvb);
958 }
959 
960 static int
dissect_uds_no_data(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree _U_,void * data _U_)961 dissect_uds_no_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_) {
962     return dissect_uds_internal(tvb, pinfo, tree, 0, 0, 0);
963 }
964 
965 static int
dissect_uds_doip(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree _U_,void * data)966 dissect_uds_doip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data) {
967     DISSECTOR_ASSERT(data);
968 
969     doip_info_t *doip_info = (doip_info_t *)data;
970     return dissect_uds_internal(tvb, pinfo, tree, doip_info->source_address, doip_info->target_address, 2);
971 }
972 
973 static int
dissect_uds_iso15765(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree _U_,void * data)974 dissect_uds_iso15765(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data) {
975     DISSECTOR_ASSERT(data);
976 
977     iso15765_info_t *info = (iso15765_info_t *)data;
978     return dissect_uds_internal(tvb, pinfo, tree, info->source_address, info->target_address, info->number_of_addresses_valid);
979 }
980 
981 static int
dissect_uds_iso10681(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree _U_,void * data)982 dissect_uds_iso10681(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data) {
983     DISSECTOR_ASSERT(data);
984 
985     iso10681_info_t *info = (iso10681_info_t *)data;
986     return dissect_uds_internal(tvb, pinfo, tree, info->source_address, info->target_address, 2);
987 }
988 
989 static void
pref_update_uds(void)990 pref_update_uds(void) {
991     if (uds_ht_routine_ids && uds_uat_routine_id_num == 0) {
992         g_hash_table_destroy(uds_ht_routine_ids);
993         uds_ht_routine_ids = NULL;
994     }
995 
996     if (uds_ht_data_ids && uds_uat_data_id_num == 0) {
997         g_hash_table_destroy(uds_ht_data_ids);
998         uds_ht_data_ids = NULL;
999     }
1000 }
1001 
1002 void
proto_register_uds(void)1003 proto_register_uds(void)
1004 {
1005     module_t* uds_module;
1006     static hf_register_info hf[] = {
1007             {
1008                     &hf_uds_service,
1009                     {
1010                             "Service Identifier",    "uds.sid",
1011                             FT_UINT8,  BASE_HEX,
1012                             VALS(uds_services), UDS_SID_MASK,
1013                             NULL, HFILL
1014                     }
1015             },
1016             {
1017                     &hf_uds_reply,
1018                     {
1019                             "Reply Flag", "uds.reply",
1020                             FT_UINT8, BASE_HEX,
1021                             NULL, UDS_REPLY_MASK,
1022                             NULL, HFILL
1023                     }
1024             },
1025 
1026 
1027             {
1028                     &hf_uds_dsc_type,
1029                     {
1030                             "Type", "uds.dsc.type",
1031                             FT_UINT8, BASE_HEX,
1032                             VALS(uds_dsc_types), 0x0,
1033                             NULL, HFILL
1034                     }
1035             },
1036             {
1037                     &hf_uds_dsc_parameter_record,
1038                     {
1039                             "Parameter Record", "uds.dsc.parameter_record",
1040                             FT_BYTES, BASE_NONE,
1041                             NULL, 0x0,
1042                             NULL, HFILL
1043                     }
1044             },
1045 
1046             {
1047                     &hf_uds_er_type,
1048                     {
1049                             "Type", "uds.er.type",
1050                             FT_UINT8, BASE_HEX,
1051                             VALS(uds_er_types), 0x0,
1052                             NULL, HFILL
1053                     }
1054             },
1055 
1056 
1057             {
1058                     &hf_uds_rdtci_type,
1059                     {
1060                             "Type", "uds.rdtci.type",
1061                             FT_UINT8, BASE_HEX,
1062                             VALS(uds_rdtci_types), 0x0,
1063                             NULL, HFILL
1064                     }
1065             },
1066             {
1067                     &hf_uds_rdtci_record,
1068                     {
1069                             "Record", "uds.rdtci.record",
1070                             FT_BYTES, BASE_NONE,
1071                             NULL, 0x0,
1072                             NULL, HFILL
1073                     }
1074             },
1075 
1076 
1077             {
1078                     &hf_uds_rdbi_data_identifier,
1079                     {
1080                             "Data Identifier", "uds.rdbi.data_identifier",
1081                             FT_UINT16, BASE_HEX,
1082                             NULL, 0x0,
1083                             NULL, HFILL
1084                     }
1085             },
1086             {
1087                     &hf_uds_rdbi_data_record,
1088                     {
1089                             "Data Record", "uds.rdbi.data_record",
1090                             FT_BYTES, BASE_NONE,
1091                             NULL, 0x0,
1092                             NULL, HFILL
1093                     }
1094             },
1095 
1096 
1097             {
1098                     &hf_uds_sa_type,
1099                     {
1100                             "Type", "uds.sa.type",
1101                             FT_UINT8, BASE_HEX,
1102                             NULL, 0x0,
1103                             NULL, HFILL
1104                     }
1105             },
1106             {
1107                     &hf_uds_sa_key,
1108                     {
1109                             "Key", "uds.sa.key",
1110                             FT_BYTES, BASE_NONE,
1111                             NULL, 0x0,
1112                             NULL, HFILL
1113                     }
1114             },
1115             {
1116                     &hf_uds_sa_seed,
1117                     {
1118                             "Seed", "uds.sa.seed",
1119                             FT_BYTES, BASE_NONE,
1120                             NULL, 0x0,
1121                             NULL, HFILL
1122                     }
1123             },
1124 
1125 
1126             {
1127                     &hf_uds_wdbi_data_identifier,
1128                     {
1129                             "Data Identifier", "uds.wdbi.data_identifier",
1130                             FT_UINT8, BASE_HEX,
1131                             NULL, 0x0,
1132                             NULL, HFILL
1133                     }
1134             },
1135             {
1136                     &hf_uds_wdbi_data_record,
1137                     {
1138                             "Data Record", "uds.wdbi.data_record",
1139                             FT_BYTES, BASE_NONE,
1140                             NULL, 0x0,
1141                             NULL, HFILL
1142                     }
1143             },
1144 
1145             {
1146                     &hf_uds_iocbi_data_identifier,
1147                     {
1148                             "Data Identifier", "uds.iocbi.data_identifier",
1149                             FT_UINT8, BASE_HEX,
1150                             NULL, 0x0,
1151                             NULL, HFILL
1152                     }
1153             },
1154             {
1155                     &hf_uds_iocbi_parameter,
1156                     {
1157                             "Parameter", "uds.iocbi.parameter",
1158                             FT_UINT8, BASE_HEX,
1159                             VALS(uds_iocbi_parameters), 0x0,
1160                             NULL, HFILL
1161                     }
1162             },
1163             {
1164                     &hf_uds_iocbi_state,
1165                     {
1166                             "State", "uds.iocbi.state",
1167                             FT_BYTES, BASE_NONE,
1168                             NULL, 0x0,
1169                             NULL, HFILL
1170                     }
1171             },
1172 
1173             {
1174                     &hf_uds_rc_type,
1175                     {
1176                             "Type", "uds.rc.type",
1177                             FT_UINT8, BASE_HEX,
1178                             VALS(uds_rc_types), 0x0,
1179                             NULL, HFILL
1180                     }
1181             },
1182             {
1183                     &hf_uds_rc_identifier,
1184                     {
1185                             "Identifier", "uds.rc.identifier",
1186                             FT_UINT16, BASE_HEX,
1187                             NULL, 0x0,
1188                             NULL, HFILL
1189                     }
1190             },
1191             {
1192                     &hf_uds_rc_option_record,
1193                     {
1194                             "Option record", "uds.rc.option_record",
1195                             FT_BYTES, BASE_NONE,
1196                             NULL, 0x0,
1197                             NULL, HFILL
1198                     }
1199             },
1200             {
1201                     &hf_uds_rc_info,
1202                     {
1203                             "Info", "uds.rc.info",
1204                             FT_UINT8, BASE_HEX,
1205                             NULL, 0x0,
1206                             NULL, HFILL
1207                     }
1208             },
1209             {
1210                     &hf_uds_rc_status_record,
1211                     {
1212                             "Status Record", "uds.rc.status_record",
1213                             FT_BYTES, BASE_NONE,
1214                             NULL, 0x0,
1215                             NULL, HFILL
1216                     }
1217             },
1218 
1219             {
1220                     &hf_uds_rd_compression_method,
1221                     {
1222                             "Compression Method", "uds.rd.compression_method",
1223                             FT_UINT8, BASE_HEX,
1224                             NULL, UDS_RD_COMPRESSION_METHOD_MASK,
1225                             NULL, HFILL
1226                     }
1227             },
1228             {
1229                     &hf_uds_rd_encrypting_method,
1230                     {
1231                             "Encrypting Method", "uds.rd.encrypting_method",
1232                             FT_UINT8, BASE_HEX,
1233                             NULL, UDS_RD_ENCRYPTING_METHOD_MASK,
1234                             NULL, HFILL
1235                     }
1236             },
1237             {
1238                     &hf_uds_rd_memory_size_length,
1239                     {
1240                             "Memory size length", "uds.rd.memory_size_length",
1241                             FT_UINT8, BASE_HEX,
1242                             NULL, UDS_RD_MEMORY_SIZE_LENGTH_MASK,
1243                             NULL, HFILL
1244                     }
1245             },
1246             {
1247                     &hf_uds_rd_memory_address_length,
1248                     {
1249                             "Memory address length", "uds.rd.memory_address_length",
1250                             FT_UINT8, BASE_HEX,
1251                             NULL, UDS_RD_MEMORY_ADDRESS_LENGTH_MASK,
1252                             NULL, HFILL
1253                     }
1254             },
1255             {
1256                     &hf_uds_rd_memory_address,
1257                     {
1258                             "Memory Address", "uds.rd.memory_address",
1259                             FT_UINT64, BASE_HEX,
1260                             NULL, 0x0,
1261                             NULL, HFILL
1262                     }
1263             },
1264             {
1265                     &hf_uds_rd_memory_size,
1266                     {
1267                             "Memory Size", "uds.rd.memory_size",
1268                             FT_UINT64, BASE_HEX,
1269                             NULL, 0x0,
1270                             NULL, HFILL
1271                     }
1272             },
1273             {
1274                     &hf_uds_rd_max_number_of_block_length_length,
1275                     {
1276                             "Memory address length", "uds.rd.max_number_of_block_length_length",
1277                             FT_UINT8, BASE_HEX,
1278                             NULL, UDS_RD_MAX_NUMBER_OF_BLOCK_LENGTH_LENGTH_MASK,
1279                             NULL, HFILL
1280                     }
1281             },
1282             {
1283                     &hf_uds_rd_max_number_of_block_length,
1284                     {
1285                             "Memory Size", "uds.rd.max_number_of_block_length",
1286                             FT_UINT64, BASE_HEX,
1287                             NULL, 0x0,
1288                             NULL, HFILL
1289                     }
1290             },
1291 
1292 
1293             {
1294                     &hf_uds_td_sequence_counter,
1295                     {
1296                             "Block Sequence Counter", "uds.td.block_sequence_counter",
1297                             FT_UINT8, BASE_DEC,
1298                             NULL, 0x0,
1299                             NULL, HFILL
1300                     }
1301             },
1302 
1303             {
1304                     &hf_uds_tp_sub_function,
1305                     {
1306                             "Suppress reply", "uds.tp.suppress_reply",
1307                             FT_UINT8, BASE_HEX,
1308                             NULL, UDS_TP_SUB_FUNCTION_MASK,
1309                             NULL, HFILL
1310                     }
1311             },
1312             {
1313                     &hf_uds_tp_suppress_pos_rsp_msg_indification,
1314                     {
1315                             "Suppress reply", "uds.tp.suppress_reply.indification",
1316                             FT_BOOLEAN, 8,
1317                             NULL, UDS_TP_SUPPRESS_POS_RSP_MSG_INDIFICATION_MASK,
1318                             NULL, HFILL
1319                     }
1320             },
1321 
1322             {
1323                     &hf_uds_err_sid,
1324                     {
1325                             "Service Identifier", "uds.err.sid",
1326                             FT_UINT8, BASE_HEX,
1327                             VALS(uds_services), 0x0,
1328                             NULL, HFILL
1329                     }
1330             },
1331             {
1332                     &hf_uds_err_code,
1333                     {
1334                             "Code", "uds.err.code",
1335                             FT_UINT8, BASE_HEX,
1336                             VALS(uds_response_codes), 0x0,
1337                             NULL, HFILL
1338                     }
1339             },
1340 
1341             {
1342                     &hf_uds_cdtcs_type,
1343                     {
1344                             "Type", "uds.cdtcs.type",
1345                             FT_UINT8, BASE_HEX,
1346                             VALS(uds_cdtcs_types), 0x0,
1347                             NULL, HFILL
1348                     }
1349             },
1350     };
1351 
1352     uat_t* uds_routine_ids_uat;
1353     uat_t* uds_data_ids_uat;
1354 
1355     /* Setup protocol subtree array */
1356     static gint *ett[] =
1357             {
1358                     &ett_uds,
1359                     &ett_uds_dsc,
1360                     &ett_uds_er,
1361                     &ett_uds_rdtci,
1362                     &ett_uds_rdbi,
1363                     &ett_uds_sa,
1364                     &ett_uds_wdbi,
1365                     &ett_uds_iocbi,
1366                     &ett_uds_rc,
1367                     &ett_uds_rd,
1368                     &ett_uds_td,
1369                     &ett_uds_tp,
1370                     &ett_uds_err,
1371                     &ett_uds_cdtcs,
1372             };
1373 
1374     proto_uds = proto_register_protocol (
1375             "Unified Diagnostic Services", /* name       */
1376             "UDS",          /* short name */
1377             "uds"           /* abbrev     */
1378     );
1379 
1380     proto_register_field_array(proto_uds, hf, array_length(hf));
1381     proto_register_subtree_array(ett, array_length(ett));
1382 
1383     uds_handle = register_dissector("uds", dissect_uds_no_data, proto_uds);
1384     uds_handle_doip = register_dissector("uds_over_doip", dissect_uds_doip, proto_uds);
1385     uds_handle_iso10681 = register_dissector("uds_over_iso10681", dissect_uds_iso10681, proto_uds);
1386     uds_handle_iso15765 = register_dissector("uds_over_iso15765", dissect_uds_iso15765, proto_uds);
1387 
1388     /* Register preferences */
1389     uds_module = prefs_register_protocol(proto_uds, &pref_update_uds);
1390 
1391     /* UATs for user_data fields */
1392     static uat_field_t uds_routine_id_uat_fields[] = {
1393         UAT_FLD_HEX(uds_uat_routine_ids, address, "Address", "Address (16bit hex without leading 0x, 0xffffffff for 'any')"),
1394         UAT_FLD_HEX(uds_uat_routine_ids, id, "Routine ID", "Routine Identifier (16bit hex without leading 0x)"),
1395         UAT_FLD_CSTRING(uds_uat_routine_ids, name, "Routine Name", "Name of the Routine ID (string)"),
1396         UAT_END_FIELDS
1397     };
1398 
1399     /* UATs */
1400     uds_routine_ids_uat = uat_new("UDS Routine Identifier List",
1401         sizeof(generic_addr_id_string_t),           /* record size           */
1402         DATAFILE_UDS_ROUTINE_IDS,                   /* filename              */
1403         TRUE,                                       /* from profile          */
1404         (void**)&uds_uat_routine_ids,               /* data_ptr              */
1405         &uds_uat_routine_id_num,                    /* numitems_ptr          */
1406         UAT_AFFECTS_DISSECTION,                     /* but not fields        */
1407         NULL,                                       /* help                  */
1408         copy_generic_one_id_string_cb,              /* copy callback         */
1409         update_generic_addr_id_16bit,               /* update callback       */
1410         free_generic_one_id_string_cb,              /* free callback         */
1411         post_update_uds_routine_cb,                 /* post update callback  */
1412         NULL,                                       /* reset callback        */
1413         uds_routine_id_uat_fields                   /* UAT field definitions */
1414     );
1415 
1416     prefs_register_uat_preference(uds_module, "_uds_routine_id_list", "UDS Routine Identifier List",
1417         "A table to define names of UDS Routines", uds_routine_ids_uat);
1418 
1419     static uat_field_t uds_data_id_uat_fields[] = {
1420         UAT_FLD_HEX(uds_uat_data_ids, address, "Address", "Address (16bit hex without leading 0x, 0xffffffff for 'any')"),
1421         UAT_FLD_HEX(uds_uat_data_ids, id, "Data ID", "Data Identifier (16bit hex without leading 0x)"),
1422         UAT_FLD_CSTRING(uds_uat_data_ids, name, "Data Name", "Name of the Data ID (string)"),
1423         UAT_END_FIELDS
1424     };
1425 
1426     uds_data_ids_uat = uat_new("UDS Data Identifier List",
1427         sizeof(generic_addr_id_string_t),           /* record size           */
1428         DATAFILE_UDS_DATA_IDS,                      /* filename              */
1429         TRUE,                                       /* from profile          */
1430         (void**)&uds_uat_data_ids,                  /* data_ptr              */
1431         &uds_uat_data_id_num,                       /* numitems_ptr          */
1432         UAT_AFFECTS_DISSECTION,                     /* but not fields        */
1433         NULL,                                       /* help                  */
1434         copy_generic_one_id_string_cb,              /* copy callback         */
1435         update_generic_addr_id_16bit,               /* update callback       */
1436         free_generic_one_id_string_cb,              /* free callback         */
1437         post_update_uds_data_cb,                    /* post update callback  */
1438         NULL,                                       /* reset callback        */
1439         uds_data_id_uat_fields                      /* UAT field definitions */
1440     );
1441 
1442     prefs_register_uat_preference(uds_module, "_uds_data_id_list", "UDS Data Identifier List",
1443         "A table to define names of UDS Data Identifier", uds_data_ids_uat);
1444 }
1445 
1446 void
proto_reg_handoff_uds(void)1447 proto_reg_handoff_uds(void)
1448 {
1449     dissector_add_for_decode_as("iso10681.subdissector", uds_handle_iso10681);
1450     dissector_add_for_decode_as("iso15765.subdissector", uds_handle_iso15765);
1451 }
1452 
1453 /*
1454  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1455  *
1456  * Local variables:
1457  * c-basic-offset: 4
1458  * tab-width: 8
1459  * indent-tabs-mode: nil
1460  * End:
1461  *
1462  * vi: set shiftwidth=4 tabstop=8 expandtab:
1463  * :indentSize=4:tabSize=8:noTabs=true:
1464  */
1465