1 /* packet-lbmpdm.c
2  * Routines for LBM PDM Packet dissection
3  *
4  * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved.
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/exceptions.h>
16 #include "packet-lbm.h"
17 
18 /* Magic number for message header to check if data is big-endian or little-endian. */
19 #define PDM_MSG_HDR_BE_MAGIC_BYTE_1 0xA7
20 #define PDM_MSG_HDR_BE_MAGIC_BYTE_2 0x1C
21 #define PDM_MSG_HDR_BE_MAGIC_BYTE_3 0xCA
22 #define PDM_MSG_HDR_BE_MAGIC_BYTE_4 0xFE
23 #define PDM_MSG_HDR_LE_MAGIC_BYTE_1 0xFE
24 #define PDM_MSG_HDR_LE_MAGIC_BYTE_2 0xCA
25 #define PDM_MSG_HDR_LE_MAGIC_BYTE_3 0x1C
26 #define PDM_MSG_HDR_LE_MAGIC_BYTE_4 0xA7
27 
28 void proto_register_lbmpdm(void);
29 
30 /*------------*/
31 /* PDM header */
32 /*------------*/
33 typedef struct lbmpdm_msg_hdr_stct_t
34 {
35     guint32 magic;
36     guint8 ver_type;
37     guint8 next_hdr;
38     guint8 def_major_ver;
39     guint8 def_minor_ver;
40     guint32 def_id;
41     guint32 len;
42 } lbmpdm_msg_hdr_t;
43 #define O_LBMPDM_MSG_HDR_T_MAGIC OFFSETOF(lbmpdm_msg_hdr_t, magic)
44 #define L_LBMPDM_MSG_HDR_T_MAGIC SIZEOF(lbmpdm_msg_hdr_t, magic)
45 #define O_LBMPDM_MSG_HDR_T_VER_TYPE OFFSETOF(lbmpdm_msg_hdr_t, ver_type)
46 #define L_LBMPDM_MSG_HDR_T_VER_TYPE SIZEOF(lbmpdm_msg_hdr_t, ver_type)
47 #define O_LBMPDM_MSG_HDR_T_NEXT_HDR OFFSETOF(lbmpdm_msg_hdr_t, next_hdr)
48 #define L_LBMPDM_MSG_HDR_T_NEXT_HDR SIZEOF(lbmpdm_msg_hdr_t, next_hdr)
49 #define O_LBMPDM_MSG_HDR_T_DEF_MAJOR_VER OFFSETOF(lbmpdm_msg_hdr_t, def_major_ver)
50 #define L_LBMPDM_MSG_HDR_T_DEF_MAJOR_VER SIZEOF(lbmpdm_msg_hdr_t, def_major_ver)
51 #define O_LBMPDM_MSG_HDR_T_DEF_MINOR_VER OFFSETOF(lbmpdm_msg_hdr_t, def_minor_ver)
52 #define L_LBMPDM_MSG_HDR_T_DEF_MINOR_VER SIZEOF(lbmpdm_msg_hdr_t, def_minor_ver)
53 #define O_LBMPDM_MSG_HDR_T_DEF_ID OFFSETOF(lbmpdm_msg_hdr_t, def_id)
54 #define L_LBMPDM_MSG_HDR_T_DEF_ID SIZEOF(lbmpdm_msg_hdr_t, def_id)
55 #define O_LBMPDM_MSG_HDR_T_LEN OFFSETOF(lbmpdm_msg_hdr_t, len)
56 #define L_LBMPDM_MSG_HDR_T_LEN SIZEOF(lbmpdm_msg_hdr_t, len)
57 #define L_LBMPDM_MSG_HDR_T (gint) sizeof(lbmpdm_msg_hdr_t)
58 
59 /*---------------------*/
60 /* PDM segment header. */
61 /*---------------------*/
62 typedef struct lbmpdm_seg_hdr_stct_t
63 {
64     guint8 next_hdr;
65     guint8 flags;
66     guint16 res;
67     guint32 len;
68 } lbmpdm_seg_hdr_t;
69 #define O_LBMPDM_SEG_HDR_T_NEXT_HDR OFFSETOF(lbmpdm_seg_hdr_t, next_hdr)
70 #define L_LBMPDM_SEG_HDR_T_NEXT_HDR SIZEOF(lbmpdm_seg_hdr_t, next_hdr)
71 #define O_LBMPDM_SEG_HDR_T_FLAGS OFFSETOF(lbmpdm_seg_hdr_t, flags)
72 #define L_LBMPDM_SEG_HDR_T_FLAGS SIZEOF(lbmpdm_seg_hdr_t, flags)
73 #define O_LBMPDM_SEG_HDR_T_RES OFFSETOF(lbmpdm_seg_hdr_t, res)
74 #define L_LBMPDM_SEG_HDR_T_RES SIZEOF(lbmpdm_seg_hdr_t, res)
75 #define O_LBMPDM_SEG_HDR_T_LEN OFFSETOF(lbmpdm_seg_hdr_t, len)
76 #define L_LBMPDM_SEG_HDR_T_LEN SIZEOF(lbmpdm_seg_hdr_t, len)
77 #define L_LBMPDM_SEG_HDR_T (gint) sizeof(lbmpdm_seg_hdr_t)
78 
79 /*--------------------------------*/
80 /* PDM definition segment header. */
81 /*--------------------------------*/
82 typedef struct lbmpdm_defn_stct_t
83 {
84     gint32 id;
85     gint32 num_fields;
86     guint8 field_names_type;
87     guint8 finalized;
88     guint8 msg_vers_major;
89     guint8 msg_vers_minor;
90     guint32 fixed_req_section_len;
91     guint32 field_info_len;
92 } lbmpdm_defn_t;
93 #define O_LBMPDM_DEFN_T_ID OFFSETOF(lbmpdm_defn_t, id)
94 #define L_LBMPDM_DEFN_T_ID SIZEOF(lbmpdm_defn_t, id)
95 #define O_LBMPDM_DEFN_T_NUM_FIELDS OFFSETOF(lbmpdm_defn_t, num_fields)
96 #define L_LBMPDM_DEFN_T_NUM_FIELDS SIZEOF(lbmpdm_defn_t, num_fields)
97 #define O_LBMPDM_DEFN_T_FIELD_NAMES_TYPE OFFSETOF(lbmpdm_defn_t, field_names_type)
98 #define L_LBMPDM_DEFN_T_FIELD_NAMES_TYPE SIZEOF(lbmpdm_defn_t, field_names_type)
99 #define O_LBMPDM_DEFN_T_FINALIZED OFFSETOF(lbmpdm_defn_t, finalized)
100 #define L_LBMPDM_DEFN_T_FINALIZED SIZEOF(lbmpdm_defn_t, finalized)
101 #define O_LBMPDM_DEFN_T_MSG_VERS_MAJOR OFFSETOF(lbmpdm_defn_t, msg_vers_major)
102 #define L_LBMPDM_DEFN_T_MSG_VERS_MAJOR SIZEOF(lbmpdm_defn_t, msg_vers_major)
103 #define O_LBMPDM_DEFN_T_MSG_VERS_MINOR OFFSETOF(lbmpdm_defn_t, msg_vers_minor)
104 #define L_LBMPDM_DEFN_T_MSG_VERS_MINOR SIZEOF(lbmpdm_defn_t, msg_vers_minor)
105 #define O_LBMPDM_DEFN_T_FIXED_REQ_SECTION_LEN OFFSETOF(lbmpdm_defn_t, fixed_req_section_len)
106 #define L_LBMPDM_DEFN_T_FIXED_REQ_SECTION_LEN SIZEOF(lbmpdm_defn_t, fixed_req_section_len)
107 #define O_LBMPDM_DEFN_T_FIELD_INFO_LEN OFFSETOF(lbmpdm_defn_t, field_info_len)
108 #define L_LBMPDM_DEFN_T_FIELD_INFO_LEN SIZEOF(lbmpdm_defn_t, field_info_len)
109 #define L_LBMPDM_DEFN_T (gint) sizeof(lbmpdm_defn_t)
110 
111 /*----------------------------*/
112 /* PDM definition field info. */
113 /*----------------------------*/
114 typedef struct lbmpdm_field_info_stct_t
115 {
116     guint32 id;
117     guint32 len;
118     guint32 fixed_str_len;
119     guint32 num_arr_elem;
120     guint8 req;
121     guint8 fixed;
122     gint32 fld_int_name;
123     gint32 str_name_len;
124     /* NUL-terminated field name, if str_name_len != 0 */
125     /* int16_t fld_type */
126 } lbmpdm_field_info_t;
127 #define O_LBMPDM_FIELD_INFO_T_ID OFFSETOF(lbmpdm_field_info_t, id)
128 #define L_LBMPDM_FIELD_INFO_T_ID SIZEOF(lbmpdm_field_info_t, id)
129 #define O_LBMPDM_FIELD_INFO_T_LEN OFFSETOF(lbmpdm_field_info_t, len)
130 #define L_LBMPDM_FIELD_INFO_T_LEN SIZEOF(lbmpdm_field_info_t, len)
131 #define O_LBMPDM_FIELD_INFO_T_FIXED_STR_LEN OFFSETOF(lbmpdm_field_info_t, fixed_str_len)
132 #define L_LBMPDM_FIELD_INFO_T_FIXED_STR_LEN SIZEOF(lbmpdm_field_info_t, fixed_str_len)
133 #define O_LBMPDM_FIELD_INFO_T_NUM_ARR_ELEM OFFSETOF(lbmpdm_field_info_t, num_arr_elem)
134 #define L_LBMPDM_FIELD_INFO_T_NUM_ARR_ELEM SIZEOF(lbmpdm_field_info_t, num_arr_elem)
135 #define O_LBMPDM_FIELD_INFO_T_REQ OFFSETOF(lbmpdm_field_info_t, req)
136 #define L_LBMPDM_FIELD_INFO_T_REQ SIZEOF(lbmpdm_field_info_t, req)
137 #define O_LBMPDM_FIELD_INFO_T_FIXED OFFSETOF(lbmpdm_field_info_t, fixed)
138 #define L_LBMPDM_FIELD_INFO_T_FIXED SIZEOF(lbmpdm_field_info_t, fixed)
139 #define O_LBMPDM_FIELD_INFO_T_FLD_INT_NAME (O_LBMPDM_FIELD_INFO_T_FIXED + L_LBMPDM_FIELD_INFO_T_FIXED)
140 #define L_LBMPDM_FIELD_INFO_T_FLD_INT_NAME 4
141 #define O_LBMPDM_FIELD_INFO_T_STR_NAME_LEN (O_LBMPDM_FIELD_INFO_T_FLD_INT_NAME + L_LBMPDM_FIELD_INFO_T_FLD_INT_NAME)
142 #define L_LBMPDM_FIELD_INFO_T_STR_NAME_LEN 4
143 #define L_LBMPDM_FIELD_INFO_T (O_LBMPDM_FIELD_INFO_T_STR_NAME_LEN + L_LBMPDM_FIELD_INFO_T_STR_NAME_LEN)
144 #define L_LBMPDM_FIELD_INFO_T_INT_NAME (gint) (L_LBMPDM_FIELD_INFO_T + 2)
145 
146 /*---------------------------------*/
147 /* PDM offset table segment entry. */
148 /*---------------------------------*/
149 typedef struct
150 {
151     guint32 id;
152     guint32 offset;
153 } lbmpdm_offset_entry_t;
154 #define O_LBMPDM_OFFSET_ENTRY_T_ID OFFSETOF(lbmpdm_offset_entry_t, id)
155 #define L_LBMPDM_OFFSET_ENTRY_T_ID SIZEOF(lbmpdm_offset_entry_t, id)
156 #define O_LBMPDM_OFFSET_ENTRY_T_OFFSET OFFSETOF(lbmpdm_offset_entry_t, offset)
157 #define L_LBMPDM_OFFSET_ENTRY_T_OFFSET SIZEOF(lbmpdm_offset_entry_t, offset)
158 #define L_LBMPDM_OFFSET_ENTRY_T (gint) sizeof(lbmpdm_offset_entry_t)
159 
160 /*-----------------------------------*/
161 /* Header types (value of next_hdr). */
162 /*-----------------------------------*/
163 #define PDM_HDR_TYPE_DATA 0
164 #define PDM_HDR_TYPE_OFSTTBLE 1
165 #define PDM_HDR_TYPE_DEFN 2
166 #define PDM_HDR_TYPE_EOM 0xFF
167 
168 
169 /* PDM protocol version number.
170  */
171 #define PDM_VERS   1
172 
173 /*------------------*/
174 /* PDM field types. */
175 /*------------------*/
176 #define PDM_TYPE_BOOLEAN 0
177 #define PDM_TYPE_INT8 1
178 #define PDM_TYPE_UINT8 2
179 #define PDM_TYPE_INT16 3
180 #define PDM_TYPE_UINT16 4
181 #define PDM_TYPE_INT32 5
182 #define PDM_TYPE_UINT32 6
183 #define PDM_TYPE_INT64 7
184 #define PDM_TYPE_UINT64 8
185 #define PDM_TYPE_FLOAT 9
186 #define PDM_TYPE_DOUBLE 10
187 #define PDM_TYPE_DECIMAL 11
188 #define PDM_TYPE_TIMESTAMP 12
189 #define PDM_TYPE_FIX_STRING 13
190 #define PDM_TYPE_STRING 14
191 #define PDM_TYPE_FIX_UNICODE 15
192 #define PDM_TYPE_UNICODE 16
193 #define PDM_TYPE_BLOB 17
194 #define PDM_TYPE_MESSAGE 18
195 #define PDM_TYPE_BOOLEAN_ARR 19
196 #define PDM_TYPE_INT8_ARR 20
197 #define PDM_TYPE_UINT8_ARR 21
198 #define PDM_TYPE_INT16_ARR 22
199 #define PDM_TYPE_UINT16_ARR 23
200 #define PDM_TYPE_INT32_ARR 24
201 #define PDM_TYPE_UINT32_ARR 25
202 #define PDM_TYPE_INT64_ARR 26
203 #define PDM_TYPE_UINT64_ARR 27
204 #define PDM_TYPE_FLOAT_ARR 28
205 #define PDM_TYPE_DOUBLE_ARR 29
206 #define PDM_TYPE_DECIMAL_ARR 30
207 #define PDM_TYPE_TIMESTAMP_ARR 31
208 #define PDM_TYPE_FIX_STRING_ARR 32
209 #define PDM_TYPE_STRING_ARR 33
210 #define PDM_TYPE_FIX_UNICODE_ARR 34
211 #define PDM_TYPE_UNICODE_ARR 35
212 #define PDM_TYPE_BLOB_ARR 36
213 #define PDM_TYPE_MESSAGE_ARR 37
214 
215 /* Macros for protocol version number and pdm message type.
216  */
217 #define PDM_HDR_VER(x) (x >> 4)
218 #define PDM_HDR_TYPE(x) (x & 0xF)
219 #define PDM_HDR_VER_TYPE(v,t) ((v << 4)|(t & 0xF))
220 #define PDM_HDR_VER_TYPE_VER_MASK 0xf0
221 #define PDM_HDR_VER_TYPE_TYPE_MASK 0x0f
222 
223 #define PDM_IGNORE_FLAG 0x80
224 
225 #define PDM_DEFN_STR_FIELD_NAMES 0
226 #define PDM_DEFN_INT_FIELD_NAMES 1
227 
228 #define PDM_DEFN_OPTIONAL_FIELD 0
229 #define PDM_DEFN_REQUIRED_FIELD 1
230 
231 #define PDM_DEFN_VARIABLE_LENGTH_FIELD 0
232 #define PDM_DEFN_FIXED_LENGTH_FIELD 1
233 
234 typedef struct
235 {
236     guint32 num_flds;
237     gint32 * min_set_offset;
238     gint32 * offset_list;
239 } lbmpdm_offset_table_t;
240 
241 struct lbmpdm_definition_field_t_stct;
242 typedef struct lbmpdm_definition_field_t_stct lbmpdm_definition_field_t;
243 
244 struct lbmpdm_definition_t_stct;
245 typedef struct lbmpdm_definition_t_stct lbmpdm_definition_t;
246 
247 struct lbmpdm_definition_field_t_stct
248 {
249     guint32 id;
250     guint32 len;
251     guint32 fixed_string_len;
252     guint32 num_array_elem;
253     guint8 required;
254     guint8 fixed;
255     guint16 field_type;
256     guint16 base_type;
257     gint32 field_int_name;
258     guint32 field_string_name_len;
259     char * field_string_name;
260     int fixed_required_offset;
261     lbmpdm_definition_field_t * next_fixed_required;
262     lbmpdm_definition_t * definition;
263 };
264 
265 struct lbmpdm_definition_t_stct
266 {
267     guint64 channel;
268     guint32 id;
269     guint8 vers_major;
270     guint8 vers_minor;
271     gint32 num_fields;
272     guint8 field_names_type;
273     guint8 finalized;
274     guint32 fixed_req_section_len;
275     guint32 fixed_required_count;
276     lbmpdm_definition_field_t * first_fixed_required;
277     wmem_tree_t * field_list;
278 };
279 
280 typedef struct
281 {
282     guint64 channel;
283     guint32 msg_def_id;
284     guint8 ver_major;
285     guint8 ver_minor;
286     lbmpdm_offset_table_t * offset_table;
287 } lbmpdm_msg_definition_id_t;
288 
289 #define LBMPDM_DEFINITION_KEY_ELEMENT_COUNT 5
290 #define LBMPDM_DEFINITION_KEY_ELEMENT_CHANNEL_HIGH 0
291 #define LBMPDM_DEFINITION_KEY_ELEMENT_CHANNEL_LOW 1
292 #define LBMPDM_DEFINITION_KEY_ELEMENT_ID 2
293 #define LBMPDM_DEFINITION_KEY_ELEMENT_VERS_MAJOR 3
294 #define LBMPDM_DEFINITION_KEY_ELEMENT_VERS_MINOR 4
295 
296 static wmem_tree_t * lbmpdm_definition_table = NULL;
297 
298 /*----------------------------------------------------------------------------*/
299 /* Handles of all types.                                                      */
300 /*----------------------------------------------------------------------------*/
301 
302 /* Protocol handle */
303 static int proto_lbmpdm = -1;
304 
305 /* Protocol fields */
306 static int hf_lbmpdm_magic = -1;
307 static int hf_lbmpdm_encoding = -1;
308 static int hf_lbmpdm_ver = -1;
309 static int hf_lbmpdm_type = -1;
310 static int hf_lbmpdm_next_hdr = -1;
311 static int hf_lbmpdm_def_major_ver = -1;
312 static int hf_lbmpdm_def_minor_ver = -1;
313 static int hf_lbmpdm_def_id = -1;
314 static int hf_lbmpdm_len = -1;
315 static int hf_lbmpdm_segments = -1;
316 static int hf_lbmpdm_segment = -1;
317 static int hf_lbmpdm_segment_next_hdr = -1;
318 static int hf_lbmpdm_segment_flags = -1;
319 static int hf_lbmpdm_segment_res = -1;
320 static int hf_lbmpdm_segment_len = -1;
321 static int hf_lbmpdm_segment_def_id = -1;
322 static int hf_lbmpdm_segment_def_num_fields = -1;
323 static int hf_lbmpdm_segment_def_field_names_type = -1;
324 static int hf_lbmpdm_segment_def_finalized = -1;
325 static int hf_lbmpdm_segment_def_msg_vers_major = -1;
326 static int hf_lbmpdm_segment_def_msg_vers_minor = -1;
327 static int hf_lbmpdm_segment_def_fixed_req_section_len = -1;
328 static int hf_lbmpdm_segment_def_field_info_len = -1;
329 static int hf_lbmpdm_segment_def_field = -1;
330 static int hf_lbmpdm_segment_def_field_def_len = -1;
331 static int hf_lbmpdm_segment_def_field_id = -1;
332 static int hf_lbmpdm_segment_def_field_len = -1;
333 static int hf_lbmpdm_segment_def_field_fixed_str_len = -1;
334 static int hf_lbmpdm_segment_def_field_num_arr_elem = -1;
335 static int hf_lbmpdm_segment_def_field_req = -1;
336 static int hf_lbmpdm_segment_def_field_fixed = -1;
337 static int hf_lbmpdm_segment_def_field_fld_int_name = -1;
338 static int hf_lbmpdm_segment_def_field_str_name_len = -1;
339 static int hf_lbmpdm_segment_def_field_str_name = -1;
340 static int hf_lbmpdm_segment_def_field_fld_type = -1;
341 static int hf_lbmpdm_offset_entry = -1;
342 static int hf_lbmpdm_offset_entry_id = -1;
343 static int hf_lbmpdm_offset_entry_offset = -1;
344 static int hf_lbmpdm_segment_data = -1;
345 static int hf_lbmpdm_field = -1;
346 static int hf_lbmpdm_field_id = -1;
347 static int hf_lbmpdm_field_string_name = -1;
348 static int hf_lbmpdm_field_int_name = -1;
349 static int hf_lbmpdm_field_type = -1;
350 static int hf_lbmpdm_field_total_length = -1;
351 static int hf_lbmpdm_field_length = -1;
352 static int hf_lbmpdm_field_value_boolean = -1;
353 static int hf_lbmpdm_field_value_int8 = -1;
354 static int hf_lbmpdm_field_value_uint8 = -1;
355 static int hf_lbmpdm_field_value_int16 = -1;
356 static int hf_lbmpdm_field_value_uint16 = -1;
357 static int hf_lbmpdm_field_value_int32 = -1;
358 static int hf_lbmpdm_field_value_uint32 = -1;
359 static int hf_lbmpdm_field_value_int64 = -1;
360 static int hf_lbmpdm_field_value_uint64 = -1;
361 static int hf_lbmpdm_field_value_float = -1;
362 static int hf_lbmpdm_field_value_double = -1;
363 static int hf_lbmpdm_field_value_decimal = -1;
364 static int hf_lbmpdm_field_value_timestamp = -1;
365 static int hf_lbmpdm_field_value_fixed_string = -1;
366 static int hf_lbmpdm_field_value_string = -1;
367 static int hf_lbmpdm_field_value_fixed_unicode = -1;
368 static int hf_lbmpdm_field_value_unicode = -1;
369 static int hf_lbmpdm_field_value_blob = -1;
370 static int hf_lbmpdm_field_value_message = -1;
371 
372 /* Protocol trees */
373 static gint ett_lbmpdm = -1;
374 static gint ett_lbmpdm_segments = -1;
375 static gint ett_lbmpdm_segment = -1;
376 static gint ett_lbmpdm_offset_entry = -1;
377 static gint ett_lbmpdm_segment_def_field = -1;
378 static gint ett_lbmpdm_field = -1;
379 
380 /*----------------------------------------------------------------------------*/
381 /* Value translation tables.                                                  */
382 /*----------------------------------------------------------------------------*/
383 
384 /* Value tables */
385 static const value_string lbmpdm_field_type[] =
386 {
387     { PDM_TYPE_BOOLEAN, "Boolean" },
388     { PDM_TYPE_INT8, "8-bit integer" },
389     { PDM_TYPE_UINT8, "8-bit unsigned integer" },
390     { PDM_TYPE_INT16, "16-bit integer" },
391     { PDM_TYPE_UINT16, "16-bit unsigned integer" },
392     { PDM_TYPE_INT32, "32-bit integer" },
393     { PDM_TYPE_UINT32, "32-bit unsigned integer" },
394     { PDM_TYPE_INT64, "64-bit integer" },
395     { PDM_TYPE_UINT64, "64-bit unsigned integer" },
396     { PDM_TYPE_FLOAT, "Float" },
397     { PDM_TYPE_DOUBLE, "Double" },
398     { PDM_TYPE_DECIMAL, "Decimal" },
399     { PDM_TYPE_TIMESTAMP, "Timestamp" },
400     { PDM_TYPE_FIX_STRING, "Fixed-length string" },
401     { PDM_TYPE_STRING, "String" },
402     { PDM_TYPE_FIX_UNICODE, "Fixed-length unicode string" },
403     { PDM_TYPE_UNICODE, "Unicode string" },
404     { PDM_TYPE_BLOB, "Binary Large OBject" },
405     { PDM_TYPE_MESSAGE, "Message" },
406     { PDM_TYPE_BOOLEAN_ARR, "Array of booleans" },
407     { PDM_TYPE_INT8_ARR, "Array of 8-bit integers" },
408     { PDM_TYPE_UINT8_ARR, "Array of 8-bit unsigned integers" },
409     { PDM_TYPE_INT16_ARR, "Array of 16-bit integers" },
410     { PDM_TYPE_UINT16_ARR, "Array of 16-bit unsigned integers" },
411     { PDM_TYPE_INT32_ARR, "Array of 32-bit integers" },
412     { PDM_TYPE_UINT32_ARR, "Array of 32-bit unsigned integers" },
413     { PDM_TYPE_INT64_ARR, "Array of 64-bit integers" },
414     { PDM_TYPE_UINT64_ARR, "Array of 64-bit unsigned integers" },
415     { PDM_TYPE_FLOAT_ARR, "Array of floats" },
416     { PDM_TYPE_DOUBLE_ARR, "Array of doubles" },
417     { PDM_TYPE_DECIMAL_ARR, "Array of decimals" },
418     { PDM_TYPE_TIMESTAMP_ARR, "Array of timestamps" },
419     { PDM_TYPE_FIX_STRING_ARR, "Array of fixed-length strings" },
420     { PDM_TYPE_STRING_ARR, "Array of strings" },
421     { PDM_TYPE_FIX_UNICODE_ARR, "Array of fixed-length unicode strings" },
422     { PDM_TYPE_UNICODE_ARR, "Array of unicode strings" },
423     { PDM_TYPE_BLOB_ARR, "Array of Binary Large OBjects" },
424     { PDM_TYPE_MESSAGE_ARR, "Array of messages" },
425     { 0x0, NULL }
426 };
427 
428 static const value_string lbmpdm_next_header[] =
429 {
430     { PDM_HDR_TYPE_DATA, "Data" },
431     { PDM_HDR_TYPE_OFSTTBLE, "Offset table" },
432     { PDM_HDR_TYPE_DEFN, "Definition" },
433     { PDM_HDR_TYPE_EOM, "End of message" },
434     { 0x0, NULL }
435 };
436 
437 static const value_string lbmpdm_field_name_type[] =
438 {
439     { PDM_DEFN_STR_FIELD_NAMES, "String" },
440     { PDM_DEFN_INT_FIELD_NAMES, "Integer" },
441     { 0x0, NULL }
442 };
443 
444 static const value_string lbmpdm_field_required[] =
445 {
446     { PDM_DEFN_OPTIONAL_FIELD, "Field is optional" },
447     { PDM_DEFN_REQUIRED_FIELD, "Field is required" },
448     { 0x0, NULL }
449 };
450 
451 static const value_string lbmpdm_field_fixed_length[] =
452 {
453     { PDM_DEFN_VARIABLE_LENGTH_FIELD, "Field is variable-length" },
454     { PDM_DEFN_FIXED_LENGTH_FIELD, "Field is fixed-length" },
455     { 0x0, NULL }
456 };
457 
lbmpdm_get_segment_length(tvbuff_t * tvb,int offset,int encoding,int * data_length)458 static int lbmpdm_get_segment_length(tvbuff_t * tvb, int offset, int encoding, int * data_length)
459 {
460     guint32 datalen = 0;
461     int seglen = 0;
462 
463     datalen = tvb_get_guint32(tvb, offset + O_LBMPDM_SEG_HDR_T_LEN, encoding);
464     seglen = ((int)datalen) + L_LBMPDM_SEG_HDR_T;
465     *data_length = (int) datalen;
466     return (seglen);
467 }
468 
lbmpdm_definition_build_key(guint32 * key_value,wmem_tree_key_t * key,guint64 channel,guint32 id,guint8 version_major,guint8 version_minor)469 static void lbmpdm_definition_build_key(guint32 * key_value, wmem_tree_key_t * key, guint64 channel, guint32 id, guint8 version_major, guint8 version_minor)
470 {
471     key_value[LBMPDM_DEFINITION_KEY_ELEMENT_CHANNEL_HIGH] = (guint32) ((channel >> 32) & 0xffffffff);
472     key_value[LBMPDM_DEFINITION_KEY_ELEMENT_CHANNEL_LOW] = (guint32) (channel & 0xffffffff);
473     key_value[LBMPDM_DEFINITION_KEY_ELEMENT_ID] = id;
474     key_value[LBMPDM_DEFINITION_KEY_ELEMENT_VERS_MAJOR] = version_major;
475     key_value[LBMPDM_DEFINITION_KEY_ELEMENT_VERS_MINOR] = version_minor;
476     key[0].length = LBMPDM_DEFINITION_KEY_ELEMENT_COUNT;
477     key[0].key = key_value;
478     key[1].length = 0;
479     key[1].key = NULL;
480 }
481 
lbmpdm_definition_find(guint64 channel,guint32 ID,guint8 version_major,guint8 version_minor)482 static lbmpdm_definition_t * lbmpdm_definition_find(guint64 channel, guint32 ID, guint8 version_major, guint8 version_minor)
483 {
484     lbmpdm_definition_t * entry = NULL;
485     guint32 keyval[LBMPDM_DEFINITION_KEY_ELEMENT_COUNT];
486     wmem_tree_key_t tkey[2];
487 
488     lbmpdm_definition_build_key(keyval, tkey, channel, ID, version_major, version_minor);
489     entry = (lbmpdm_definition_t *) wmem_tree_lookup32_array(lbmpdm_definition_table, tkey);
490     return (entry);
491 }
492 
lbmpdm_definition_add(guint64 channel,guint32 id,guint8 version_major,guint8 version_minor)493 static lbmpdm_definition_t * lbmpdm_definition_add(guint64 channel, guint32 id, guint8 version_major, guint8 version_minor)
494 {
495     lbmpdm_definition_t * entry = NULL;
496     guint32 keyval[LBMPDM_DEFINITION_KEY_ELEMENT_COUNT];
497     wmem_tree_key_t tkey[2];
498 
499     entry = lbmpdm_definition_find(channel, id, version_major, version_minor);
500     if (entry != NULL)
501     {
502         return (entry);
503     }
504     entry = wmem_new(wmem_file_scope(), lbmpdm_definition_t);
505     entry->channel = channel;
506     entry->id = id;
507     entry->vers_major = version_major;
508     entry->vers_minor = version_minor;
509     entry->field_list = wmem_tree_new(wmem_file_scope());
510     lbmpdm_definition_build_key(keyval, tkey, channel, id, version_major, version_minor);
511     wmem_tree_insert32_array(lbmpdm_definition_table, tkey, (void *) entry);
512     return (entry);
513 }
514 
lbmpdm_definition_field_find(lbmpdm_definition_t * definition,guint32 id)515 static lbmpdm_definition_field_t * lbmpdm_definition_field_find(lbmpdm_definition_t * definition, guint32 id)
516 {
517     lbmpdm_definition_field_t * entry = NULL;
518 
519     entry = (lbmpdm_definition_field_t *) wmem_tree_lookup32(definition->field_list, id);
520     return (entry);
521 }
522 
lbmpdm_definition_field_add(lbmpdm_definition_t * definition,guint32 id)523 static lbmpdm_definition_field_t * lbmpdm_definition_field_add(lbmpdm_definition_t * definition, guint32 id)
524 {
525     lbmpdm_definition_field_t * entry = NULL;
526 
527     entry = lbmpdm_definition_field_find(definition, id);
528     if (entry != NULL)
529     {
530         return (entry);
531     }
532     entry = wmem_new0(wmem_file_scope(), lbmpdm_definition_field_t);
533     entry->id = id;
534     entry->definition = definition;
535     wmem_tree_insert32(definition->field_list, id, (void *) entry);
536     return (entry);
537 }
538 
539 /*----------------------------------------------------------------------------*/
540 /* Dissection functions.                                                      */
541 /*----------------------------------------------------------------------------*/
dissect_field_value(tvbuff_t * tvb,int offset,proto_tree * tree,guint16 field_type,int field_length,int encoding)542 static void dissect_field_value(tvbuff_t * tvb, int offset, proto_tree * tree, guint16 field_type, int field_length, int encoding)
543 {
544     switch (field_type)
545     {
546         case PDM_TYPE_BOOLEAN:
547             proto_tree_add_item(tree, hf_lbmpdm_field_value_boolean, tvb, offset, field_length, encoding);
548             break;
549         case PDM_TYPE_INT8:
550             proto_tree_add_item(tree, hf_lbmpdm_field_value_int8, tvb, offset, field_length, encoding);
551             break;
552         case PDM_TYPE_UINT8:
553             proto_tree_add_item(tree, hf_lbmpdm_field_value_uint8, tvb, offset, field_length, encoding);
554             break;
555         case PDM_TYPE_INT16:
556             proto_tree_add_item(tree, hf_lbmpdm_field_value_int16, tvb, offset, field_length, encoding);
557             break;
558         case PDM_TYPE_UINT16:
559             proto_tree_add_item(tree, hf_lbmpdm_field_value_uint16, tvb, offset, field_length, encoding);
560             break;
561         case PDM_TYPE_INT32:
562             proto_tree_add_item(tree, hf_lbmpdm_field_value_int32, tvb, offset, field_length, encoding);
563             break;
564         case PDM_TYPE_UINT32:
565             proto_tree_add_item(tree, hf_lbmpdm_field_value_uint32, tvb, offset, field_length, encoding);
566             break;
567         case PDM_TYPE_INT64:
568             proto_tree_add_item(tree, hf_lbmpdm_field_value_int64, tvb, offset, field_length, encoding);
569             break;
570         case PDM_TYPE_UINT64:
571             proto_tree_add_item(tree, hf_lbmpdm_field_value_uint64, tvb, offset, field_length, encoding);
572             break;
573         case PDM_TYPE_FLOAT:
574             proto_tree_add_item(tree, hf_lbmpdm_field_value_float, tvb, offset, field_length, encoding);
575             break;
576         case PDM_TYPE_DOUBLE:
577             proto_tree_add_item(tree, hf_lbmpdm_field_value_double, tvb, offset, field_length, encoding);
578             break;
579         case PDM_TYPE_DECIMAL:
580             {
581                 gint64 mantissa;
582                 gint8 exponent;
583                 gint64 whole = 0;
584                 guint64 fraction = 0;
585                 gint8 shift_count;
586 
587                 exponent = tvb_get_gint8(tvb, offset);
588                 mantissa = tvb_get_gint64(tvb, offset + 1, encoding);
589                 if (exponent >= 0)
590                 {
591                     whole = mantissa;
592                     shift_count = exponent;
593                     while (shift_count > 0)
594                     {
595                         whole *= 10;
596                         shift_count--;
597                     }
598                     proto_tree_add_none_format(tree, hf_lbmpdm_field_value_decimal, tvb, offset, field_length,
599                         "DECIMAL Value: %" G_GINT64_FORMAT " (%" G_GINT64_FORMAT "e%d)", whole, mantissa, exponent);
600                 }
601                 else
602                 {
603                     guint64 divisor = 1;
604                     int decimal_digits = -exponent;
605                     shift_count = decimal_digits;
606                     while (shift_count > 0)
607                     {
608                         divisor *= 10;
609                         shift_count--;
610                     }
611                     if (mantissa < 0)
612                     {
613                         whole = -mantissa;
614                     }
615                     else
616                     {
617                         whole = mantissa;
618                     }
619                     fraction = whole % divisor;
620                     whole /= divisor;
621                     if (mantissa < 0)
622                     {
623                         whole *= -1;
624                     }
625                     proto_tree_add_none_format(tree, hf_lbmpdm_field_value_decimal, tvb, offset, field_length,
626                         "DECIMAL Value: %" G_GINT64_FORMAT ".%0*" G_GUINT64_FORMAT " (%" G_GINT64_FORMAT "e%d)",
627                         whole, decimal_digits, fraction, mantissa, exponent);
628                 }
629             }
630             break;
631         case PDM_TYPE_TIMESTAMP:
632             {
633                 nstime_t timestamp;
634 
635                 timestamp.secs = (time_t)tvb_get_guint32(tvb, offset, encoding);
636                 timestamp.nsecs = (int)(tvb_get_guint32(tvb, offset + 4, encoding) * 1000);
637                 proto_tree_add_time(tree, hf_lbmpdm_field_value_timestamp, tvb, offset, field_length, &timestamp);
638             }
639             break;
640         case PDM_TYPE_FIX_STRING:
641             proto_tree_add_item(tree, hf_lbmpdm_field_value_fixed_string, tvb, offset, field_length, encoding);
642             break;
643         case PDM_TYPE_STRING:
644             proto_tree_add_item(tree, hf_lbmpdm_field_value_string, tvb, offset, field_length, encoding);
645             break;
646         case PDM_TYPE_FIX_UNICODE:
647             proto_tree_add_item(tree, hf_lbmpdm_field_value_fixed_unicode, tvb, offset, field_length, encoding);
648             break;
649         case PDM_TYPE_UNICODE:
650             proto_tree_add_item(tree, hf_lbmpdm_field_value_unicode, tvb, offset, field_length, encoding);
651             break;
652         case PDM_TYPE_BLOB:
653             proto_tree_add_item(tree, hf_lbmpdm_field_value_blob, tvb, offset, field_length, encoding);
654             break;
655         case PDM_TYPE_MESSAGE:
656             proto_tree_add_item(tree, hf_lbmpdm_field_value_message, tvb, offset, field_length, encoding);
657             break;
658         default:
659             break;
660     }
661 }
662 
dissect_field(tvbuff_t * tvb,int offset,proto_tree * tree,lbmpdm_definition_field_t * field,gboolean string_field_names,int encoding)663 static int dissect_field(tvbuff_t * tvb, int offset, proto_tree * tree, lbmpdm_definition_field_t * field, gboolean string_field_names, int encoding)
664 {
665     proto_item * field_item = NULL;
666     proto_tree * field_tree = NULL;
667     proto_item * ti = NULL;
668     int ofs = offset;
669     guint32 element_count = 0;
670     guint32 idx;
671     int len_dissected = 0;
672 
673     field_item = proto_tree_add_item(tree, hf_lbmpdm_field, tvb, offset, field->len, ENC_NA);
674     field_tree = proto_item_add_subtree(field_item, ett_lbmpdm_field);
675     ti = proto_tree_add_uint(field_tree, hf_lbmpdm_field_id, tvb, 0, 0, field->id);
676     proto_item_set_generated(ti);
677     if (string_field_names)
678     {
679         ti = proto_tree_add_string(field_tree, hf_lbmpdm_field_string_name, tvb, 0, 0, field->field_string_name);
680     }
681     else
682     {
683         ti = proto_tree_add_uint(field_tree, hf_lbmpdm_field_int_name, tvb, 0, 0, field->field_int_name);
684     }
685     proto_item_set_generated(ti);
686     ti = proto_tree_add_uint(field_tree, hf_lbmpdm_field_type, tvb, 0, 0, field->field_type);
687     proto_item_set_generated(ti);
688     if (field->num_array_elem == 0)
689     {
690         element_count = 1;
691     }
692     else
693     {
694         element_count = field->num_array_elem;
695         if (field->fixed == PDM_DEFN_VARIABLE_LENGTH_FIELD)
696         {
697             proto_tree_add_item(field_tree, hf_lbmpdm_field_total_length, tvb, ofs, 4, encoding);
698             len_dissected += 4;
699             ofs += 4;
700         }
701     }
702     for (idx = 0; idx < element_count; ++idx)
703     {
704         /* field_len is length of the entire entry, including any length prefix. */
705         guint32 field_len = field->len / element_count;
706         /* value_len is the length of the data only. */
707         guint32 value_len = field_len;
708         /* value_offset is the offset of the actual value. */
709         int value_offset = ofs;
710 
711         if (field->fixed == PDM_DEFN_VARIABLE_LENGTH_FIELD)
712         {
713             proto_tree_add_item(field_tree, hf_lbmpdm_field_length, tvb, ofs, 4, encoding);
714             value_len = tvb_get_guint32(tvb, ofs, encoding);
715             field_len = value_len + 4;
716             value_offset += 4;
717         }
718         else if (field->fixed_string_len > 0)
719         {
720             value_len = field->fixed_string_len;
721         }
722         dissect_field_value(tvb, value_offset, field_tree, field->base_type, value_len, encoding);
723         ofs += (int)field_len;
724         len_dissected += (int)field_len;
725     }
726     return (len_dissected);
727 }
728 
dissect_segment_data(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,lbmpdm_msg_definition_id_t * id,int encoding)729 static int dissect_segment_data(tvbuff_t * tvb, int offset, packet_info * pinfo _U_, proto_tree * tree, lbmpdm_msg_definition_id_t * id, int encoding)
730 {
731     proto_item * subtree_item = NULL;
732     proto_tree * subtree = NULL;
733     int datalen = 0;
734     int seglen = 0;
735     lbmpdm_definition_t * def = NULL;
736 
737     seglen = lbmpdm_get_segment_length(tvb, offset, encoding, &datalen);
738     subtree_item = proto_tree_add_none_format(tree, hf_lbmpdm_segment, tvb, offset, seglen, "Data Segment");
739     subtree = proto_item_add_subtree(subtree_item, ett_lbmpdm_segment);
740     proto_tree_add_item(subtree, hf_lbmpdm_segment_next_hdr, tvb, offset + O_LBMPDM_SEG_HDR_T_NEXT_HDR, L_LBMPDM_SEG_HDR_T_NEXT_HDR, encoding);
741     proto_tree_add_item(subtree, hf_lbmpdm_segment_flags, tvb, offset + O_LBMPDM_SEG_HDR_T_FLAGS, L_LBMPDM_SEG_HDR_T_FLAGS, encoding);
742     proto_tree_add_item(subtree, hf_lbmpdm_segment_res, tvb, offset + O_LBMPDM_SEG_HDR_T_RES, L_LBMPDM_SEG_HDR_T_RES, encoding);
743     proto_tree_add_item(subtree, hf_lbmpdm_segment_len, tvb, offset + O_LBMPDM_SEG_HDR_T_LEN, L_LBMPDM_SEG_HDR_T_LEN, encoding);
744     if ((id != NULL) && (id->offset_table != NULL))
745     {
746         def = lbmpdm_definition_find(id->channel, id->msg_def_id, id->ver_major, id->ver_minor);
747     }
748     if (def == NULL)
749     {
750         proto_tree_add_item(subtree, hf_lbmpdm_segment_data, tvb, offset + L_LBMPDM_SEG_HDR_T, datalen, ENC_NA);
751     }
752     else
753     {
754         int fld_offset = offset + L_LBMPDM_SEG_HDR_T;
755         lbmpdm_definition_field_t * field = NULL;
756         gboolean string_field_names = FALSE;
757         guint32 idx;
758 
759         if (def->field_names_type == PDM_DEFN_STR_FIELD_NAMES)
760         {
761             string_field_names = TRUE;
762         }
763         else
764         {
765             string_field_names = FALSE;
766         }
767 
768         /* Handle any fixed required fields first. */
769         for (field = def->first_fixed_required; field != NULL; field = field->next_fixed_required)
770         {
771             fld_offset += dissect_field(tvb, fld_offset, subtree, field, string_field_names, encoding);
772         }
773         /* Step through the offset table. */
774         for (idx = 0; idx < id->offset_table->num_flds; ++idx)
775         {
776             gint32 ofs = id->offset_table->offset_list[idx];
777             if (ofs != -1)
778             {
779                 field = lbmpdm_definition_field_find(def, idx);
780                 if (field != NULL)
781                 {
782                     (void)dissect_field(tvb, offset + L_LBMPDM_SEG_HDR_T + ofs, subtree, field, string_field_names, encoding);
783                 }
784             }
785         }
786     }
787     return (seglen);
788 }
789 
dissect_segment_ofstable(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,lbmpdm_offset_table_t ** offset_table,int encoding)790 static int dissect_segment_ofstable(tvbuff_t * tvb, int offset, packet_info * pinfo _U_, proto_tree * tree, lbmpdm_offset_table_t * * offset_table, int encoding)
791 {
792     proto_item * subtree_item = NULL;
793     proto_tree * subtree = NULL;
794     int datalen = 0;
795     int seglen = 0;
796     int ofs = 0;
797     int field_count = 0;
798     int idx;
799     gint32 * id_list = NULL;
800     gint32 * ofs_list = NULL;
801     gint32 max_index = -1;
802     gint32 min_offset = G_MAXINT32;
803     lbmpdm_offset_table_t * ofs_table = NULL;
804 
805     seglen = lbmpdm_get_segment_length(tvb, offset, encoding, &datalen);
806     subtree_item = proto_tree_add_none_format(tree, hf_lbmpdm_segment, tvb, offset, seglen, "Offset Table Segment");
807     subtree = proto_item_add_subtree(subtree_item, ett_lbmpdm_segment);
808     proto_tree_add_item(subtree, hf_lbmpdm_segment_next_hdr, tvb, offset + O_LBMPDM_SEG_HDR_T_NEXT_HDR, L_LBMPDM_SEG_HDR_T_NEXT_HDR, encoding);
809     proto_tree_add_item(subtree, hf_lbmpdm_segment_flags, tvb, offset + O_LBMPDM_SEG_HDR_T_FLAGS, L_LBMPDM_SEG_HDR_T_FLAGS, encoding);
810     proto_tree_add_item(subtree, hf_lbmpdm_segment_res, tvb, offset + O_LBMPDM_SEG_HDR_T_RES, L_LBMPDM_SEG_HDR_T_RES, encoding);
811     proto_tree_add_item(subtree, hf_lbmpdm_segment_len, tvb, offset + O_LBMPDM_SEG_HDR_T_LEN, L_LBMPDM_SEG_HDR_T_LEN, encoding);
812     field_count = datalen / L_LBMPDM_OFFSET_ENTRY_T;
813     id_list = wmem_alloc_array(pinfo->pool, gint32, field_count);
814     ofs_list = wmem_alloc_array(pinfo->pool, gint32, field_count);
815     for (idx = 0; idx < field_count; ++idx)
816     {
817         id_list[idx] = -1;
818         ofs_list[idx] = -1;
819     }
820     ofs = offset + L_LBMPDM_SEG_HDR_T;
821     for (idx = 0; idx < field_count; idx++, ofs += L_LBMPDM_OFFSET_ENTRY_T)
822     {
823         proto_item * offset_item = NULL;
824         proto_tree * offset_tree = NULL;
825 
826         offset_item = proto_tree_add_item(subtree, hf_lbmpdm_offset_entry, tvb, ofs, L_LBMPDM_OFFSET_ENTRY_T, ENC_NA);
827         offset_tree = proto_item_add_subtree(offset_item, ett_lbmpdm_offset_entry);
828         proto_tree_add_item(offset_tree, hf_lbmpdm_offset_entry_id, tvb, ofs + O_LBMPDM_OFFSET_ENTRY_T_ID, L_LBMPDM_OFFSET_ENTRY_T_ID, encoding);
829         id_list[idx] = (gint32)tvb_get_guint32(tvb, ofs + O_LBMPDM_OFFSET_ENTRY_T_ID, encoding);
830         proto_tree_add_item(offset_tree, hf_lbmpdm_offset_entry_offset, tvb, ofs + O_LBMPDM_OFFSET_ENTRY_T_OFFSET, L_LBMPDM_OFFSET_ENTRY_T_OFFSET, encoding);
831         ofs_list[idx] = (gint32)tvb_get_guint32(tvb, ofs + O_LBMPDM_OFFSET_ENTRY_T_OFFSET, encoding);
832         if (id_list[idx] < 0 || ofs_list[idx] < 0) {
833             THROW(ReportedBoundsError);
834         }
835         if (id_list[idx] > max_index)
836         {
837             max_index = id_list[idx];
838         }
839         if (ofs_list[idx] < min_offset)
840         {
841             min_offset = ofs_list[idx];
842         }
843     }
844     ofs_table = wmem_new(pinfo->pool, lbmpdm_offset_table_t);
845     ofs_table->num_flds = max_index + 1;
846     ofs_table->min_set_offset = NULL;
847     ofs_table->offset_list = wmem_alloc_array(pinfo->pool, gint32, ofs_table->num_flds);
848     for (idx = 0; idx < (int)ofs_table->num_flds; ++idx)
849     {
850         ofs_table->offset_list[idx] = -1;
851     }
852     for (idx = 0; idx < field_count; ++idx)
853     {
854         ofs_table->offset_list[id_list[idx]] = ofs_list[idx];
855         if (ofs_list[idx] == min_offset)
856         {
857             ofs_table->min_set_offset = &(ofs_table->offset_list[id_list[idx]]);
858         }
859     }
860     if (offset_table != NULL)
861     {
862         *offset_table = ofs_table;
863     }
864     return (seglen);
865 }
866 
dissect_segment_defn(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint64 channel,int encoding)867 static int dissect_segment_defn(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, guint64 channel, int encoding)
868 {
869     proto_item * subtree_item = NULL;
870     proto_tree * subtree = NULL;
871     int seglen = 0;
872     int ofs = 0;
873     gboolean string_field_name = FALSE;
874     int remaining_datalen = 0;
875     guint32 num_fields = 0;
876     lbmpdm_definition_t * def = NULL;
877     gboolean add_definition = FALSE;
878     guint32 def_id = 0;
879     guint8 vers_major = 0;
880     guint8 vers_minor = 0;
881     lbmpdm_definition_field_t * last_fixed_required_field = NULL;
882 
883     seglen = lbmpdm_get_segment_length(tvb, offset, encoding, &remaining_datalen);
884     if (pinfo->fd->visited == 0)
885     {
886         add_definition = TRUE;
887     }
888     subtree_item = proto_tree_add_none_format(tree, hf_lbmpdm_segment, tvb, offset, seglen, "Definition Segment");
889     subtree = proto_item_add_subtree(subtree_item, ett_lbmpdm_segment);
890     proto_tree_add_item(subtree, hf_lbmpdm_segment_next_hdr, tvb, offset + O_LBMPDM_SEG_HDR_T_NEXT_HDR, L_LBMPDM_SEG_HDR_T_NEXT_HDR, encoding);
891     proto_tree_add_item(subtree, hf_lbmpdm_segment_flags, tvb, offset + O_LBMPDM_SEG_HDR_T_FLAGS, L_LBMPDM_SEG_HDR_T_FLAGS, encoding);
892     proto_tree_add_item(subtree, hf_lbmpdm_segment_res, tvb, offset + O_LBMPDM_SEG_HDR_T_RES, L_LBMPDM_SEG_HDR_T_RES, encoding);
893     proto_tree_add_item(subtree, hf_lbmpdm_segment_len, tvb, offset + O_LBMPDM_SEG_HDR_T_LEN, L_LBMPDM_SEG_HDR_T_LEN, encoding);
894     ofs = offset + L_LBMPDM_SEG_HDR_T;
895     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_id, tvb, ofs + O_LBMPDM_DEFN_T_ID, L_LBMPDM_DEFN_T_ID, encoding);
896     def_id = tvb_get_guint32(tvb, ofs + O_LBMPDM_DEFN_T_ID, encoding);
897     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_num_fields, tvb, ofs + O_LBMPDM_DEFN_T_NUM_FIELDS, L_LBMPDM_DEFN_T_NUM_FIELDS, encoding);
898     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_field_names_type, tvb, ofs + O_LBMPDM_DEFN_T_FIELD_NAMES_TYPE, L_LBMPDM_DEFN_T_FIELD_NAMES_TYPE, encoding);
899     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_finalized, tvb, ofs + O_LBMPDM_DEFN_T_FINALIZED, L_LBMPDM_DEFN_T_FINALIZED, encoding);
900     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_msg_vers_major, tvb, ofs + O_LBMPDM_DEFN_T_MSG_VERS_MAJOR, L_LBMPDM_DEFN_T_MSG_VERS_MAJOR, encoding);
901     vers_major = tvb_get_guint8(tvb, ofs + O_LBMPDM_DEFN_T_MSG_VERS_MAJOR);
902     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_msg_vers_minor, tvb, ofs + O_LBMPDM_DEFN_T_MSG_VERS_MINOR, L_LBMPDM_DEFN_T_MSG_VERS_MINOR, encoding);
903     vers_minor = tvb_get_guint8(tvb, ofs + O_LBMPDM_DEFN_T_MSG_VERS_MINOR);
904     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_fixed_req_section_len, tvb, ofs + O_LBMPDM_DEFN_T_FIXED_REQ_SECTION_LEN, L_LBMPDM_DEFN_T_FIXED_REQ_SECTION_LEN, encoding);
905     proto_tree_add_item(subtree, hf_lbmpdm_segment_def_field_info_len, tvb, ofs + O_LBMPDM_DEFN_T_FIELD_INFO_LEN, L_LBMPDM_DEFN_T_FIELD_INFO_LEN, encoding);
906     if (tvb_get_guint8(tvb, ofs + O_LBMPDM_DEFN_T_FIELD_NAMES_TYPE) == PDM_DEFN_STR_FIELD_NAMES)
907     {
908         string_field_name = TRUE;
909     }
910     num_fields = tvb_get_guint32(tvb, ofs + O_LBMPDM_DEFN_T_NUM_FIELDS, encoding);
911     if (add_definition)
912     {
913         def = lbmpdm_definition_find(channel, def_id, vers_major, vers_minor);
914         if (def == NULL)
915         {
916             def = lbmpdm_definition_add(channel, def_id, vers_major, vers_minor);
917             def->num_fields = num_fields;
918             def->field_names_type = tvb_get_guint8(tvb, ofs + O_LBMPDM_DEFN_T_FIELD_NAMES_TYPE);
919             def->fixed_req_section_len = tvb_get_guint32(tvb, ofs + O_LBMPDM_DEFN_T_FIXED_REQ_SECTION_LEN, encoding);
920             def->first_fixed_required = NULL;
921             def->fixed_required_count = 0;
922         }
923     }
924     ofs += L_LBMPDM_DEFN_T;
925     remaining_datalen = seglen - L_LBMPDM_SEG_HDR_T - L_LBMPDM_DEFN_T;
926     while ((remaining_datalen > 0) && (num_fields > 0))
927     {
928         proto_item * field_item = NULL;
929         proto_tree * field_tree = NULL;
930         guint32 def_len = L_LBMPDM_FIELD_INFO_T_INT_NAME;
931         int def_ofs = 0;
932         int type_ofs = L_LBMPDM_FIELD_INFO_T;
933         guint32 string_name_len = 0;
934         int string_name_ofs = -1;
935 
936         if (string_field_name)
937         {
938             def_len = tvb_get_guint32(tvb, ofs, encoding) + 4;
939         }
940         field_item = proto_tree_add_item(subtree, hf_lbmpdm_segment_def_field, tvb, ofs, def_len, ENC_NA);
941         field_tree = proto_item_add_subtree(field_item, ett_lbmpdm_segment_def_field);
942         if (string_field_name)
943         {
944             proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_def_len, tvb, ofs, 4, encoding);
945             def_ofs = 4;
946             type_ofs += def_ofs;
947         }
948         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_id, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_ID, L_LBMPDM_FIELD_INFO_T_ID, encoding);
949         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_len, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_LEN, L_LBMPDM_FIELD_INFO_T_LEN, encoding);
950         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_fixed_str_len, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_FIXED_STR_LEN, L_LBMPDM_FIELD_INFO_T_FIXED_STR_LEN, encoding);
951         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_num_arr_elem, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_NUM_ARR_ELEM, L_LBMPDM_FIELD_INFO_T_NUM_ARR_ELEM, encoding);
952         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_req, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_REQ, L_LBMPDM_FIELD_INFO_T_REQ, encoding);
953         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_fixed, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_FIXED, L_LBMPDM_FIELD_INFO_T_FIXED, encoding);
954         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_fld_int_name, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_FLD_INT_NAME, L_LBMPDM_FIELD_INFO_T_FLD_INT_NAME, encoding);
955         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_str_name_len, tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_STR_NAME_LEN, L_LBMPDM_FIELD_INFO_T_STR_NAME_LEN, encoding);
956         if (string_field_name)
957         {
958             string_name_len = tvb_get_guint32(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_STR_NAME_LEN, encoding);
959             if (string_name_len > 0)
960             {
961                 string_name_ofs = ofs + def_ofs + L_LBMPDM_FIELD_INFO_T;
962                 proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_str_name, tvb, string_name_ofs, (int)string_name_len, ENC_ASCII|ENC_NA);
963                 type_ofs += string_name_len;
964             }
965         }
966         proto_tree_add_item(field_tree, hf_lbmpdm_segment_def_field_fld_type, tvb, ofs + type_ofs, 2, encoding);
967         if (add_definition && (def != NULL))
968         {
969             lbmpdm_definition_field_t * field = NULL;
970             guint32 field_id;
971 
972             field_id = tvb_get_guint32(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_ID, encoding);
973             field = lbmpdm_definition_field_find(def, field_id);
974             if (field == NULL)
975             {
976                 field = lbmpdm_definition_field_add(def, field_id);
977                 if (field != NULL)
978                 {
979                     field->len = tvb_get_guint32(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_LEN, encoding);
980                     field->fixed_string_len = tvb_get_guint32(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_FIXED_STR_LEN, encoding);
981                     field->num_array_elem = tvb_get_guint32(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_NUM_ARR_ELEM, encoding);
982                     field->required = tvb_get_guint8(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_REQ);
983                     field->fixed = tvb_get_guint8(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_FIXED);
984                     field->field_int_name = tvb_get_guint32(tvb, ofs + def_ofs + O_LBMPDM_FIELD_INFO_T_FLD_INT_NAME, encoding);
985                     if (string_field_name && (string_name_len > 0))
986                     {
987                         field->field_string_name_len = string_name_len;
988                         field->field_string_name = tvb_get_string_enc(wmem_file_scope(), tvb, string_name_ofs, string_name_len, ENC_ASCII);
989                     }
990                     else
991                     {
992                         field->field_string_name_len = 0;
993                         field->field_string_name = NULL;
994                     }
995                     field->field_type = tvb_get_guint16(tvb, ofs + type_ofs, encoding);
996                     switch (field->field_type)
997                     {
998                         case PDM_TYPE_BOOLEAN:
999                         case PDM_TYPE_BOOLEAN_ARR:
1000                             field->base_type = PDM_TYPE_BOOLEAN;
1001                             break;
1002                         case PDM_TYPE_INT8:
1003                         case PDM_TYPE_INT8_ARR:
1004                             field->base_type = PDM_TYPE_INT8;
1005                             break;
1006                         case PDM_TYPE_UINT8:
1007                         case PDM_TYPE_UINT8_ARR:
1008                             field->base_type = PDM_TYPE_UINT8;
1009                             break;
1010                         case PDM_TYPE_INT16:
1011                         case PDM_TYPE_INT16_ARR:
1012                             field->base_type = PDM_TYPE_INT16;
1013                             break;
1014                         case PDM_TYPE_UINT16:
1015                         case PDM_TYPE_UINT16_ARR:
1016                             field->base_type = PDM_TYPE_UINT16;
1017                             break;
1018                         case PDM_TYPE_INT32:
1019                         case PDM_TYPE_INT32_ARR:
1020                             field->base_type = PDM_TYPE_INT32;
1021                             break;
1022                         case PDM_TYPE_UINT32:
1023                         case PDM_TYPE_UINT32_ARR:
1024                             field->base_type = PDM_TYPE_UINT32;
1025                             break;
1026                         case PDM_TYPE_INT64:
1027                         case PDM_TYPE_INT64_ARR:
1028                             field->base_type = PDM_TYPE_INT64;
1029                             break;
1030                         case PDM_TYPE_UINT64:
1031                         case PDM_TYPE_UINT64_ARR:
1032                             field->base_type = PDM_TYPE_UINT64;
1033                             break;
1034                         case PDM_TYPE_FLOAT:
1035                         case PDM_TYPE_FLOAT_ARR:
1036                             field->base_type = PDM_TYPE_FLOAT;
1037                             break;
1038                         case PDM_TYPE_DOUBLE:
1039                         case PDM_TYPE_DOUBLE_ARR:
1040                             field->base_type = PDM_TYPE_DOUBLE;
1041                             break;
1042                         case PDM_TYPE_DECIMAL:
1043                         case PDM_TYPE_DECIMAL_ARR:
1044                             field->base_type = PDM_TYPE_DECIMAL;
1045                             break;
1046                         case PDM_TYPE_TIMESTAMP:
1047                         case PDM_TYPE_TIMESTAMP_ARR:
1048                             field->base_type = PDM_TYPE_TIMESTAMP;
1049                             break;
1050                         case PDM_TYPE_FIX_STRING:
1051                         case PDM_TYPE_FIX_STRING_ARR:
1052                             field->base_type = PDM_TYPE_FIX_STRING;
1053                             break;
1054                         case PDM_TYPE_STRING:
1055                         case PDM_TYPE_STRING_ARR:
1056                             field->base_type = PDM_TYPE_STRING;
1057                             break;
1058                         case PDM_TYPE_FIX_UNICODE:
1059                         case PDM_TYPE_FIX_UNICODE_ARR:
1060                             field->base_type = PDM_TYPE_FIX_UNICODE;
1061                             break;
1062                         case PDM_TYPE_UNICODE:
1063                         case PDM_TYPE_UNICODE_ARR:
1064                             field->base_type = PDM_TYPE_UNICODE;
1065                             break;
1066                         case PDM_TYPE_BLOB:
1067                         case PDM_TYPE_BLOB_ARR:
1068                         default:
1069                             field->base_type = PDM_TYPE_BLOB;
1070                             break;
1071                         case PDM_TYPE_MESSAGE:
1072                         case PDM_TYPE_MESSAGE_ARR:
1073                             field->base_type = PDM_TYPE_MESSAGE;
1074                             break;
1075                     }
1076                     if ((field->fixed == PDM_DEFN_FIXED_LENGTH_FIELD) && (field->required == PDM_DEFN_REQUIRED_FIELD))
1077                     {
1078                         if (last_fixed_required_field == NULL)
1079                         {
1080                             def->first_fixed_required = field;
1081                             field->fixed_required_offset = 0;
1082                         }
1083                         else
1084                         {
1085                             last_fixed_required_field->next_fixed_required = field;
1086                             field->fixed_required_offset = last_fixed_required_field->fixed_required_offset + last_fixed_required_field->len;
1087                         }
1088                         last_fixed_required_field = field;
1089                         def->fixed_required_count++;
1090                     }
1091                 }
1092             }
1093         }
1094         ofs += def_len;
1095         remaining_datalen -= def_len;
1096         num_fields--;
1097     }
1098     return (seglen);
1099 }
1100 
dissect_segment_unknown(tvbuff_t * tvb,int offset,packet_info * pinfo _U_,proto_tree * tree,int encoding)1101 static int dissect_segment_unknown(tvbuff_t * tvb, int offset, packet_info * pinfo _U_, proto_tree * tree, int encoding)
1102 {
1103     proto_item * subtree_item = NULL;
1104     proto_tree * subtree = NULL;
1105     int datalen = 0;
1106     int seglen = 0;
1107 
1108     seglen = lbmpdm_get_segment_length(tvb, offset, encoding, &datalen);
1109     subtree_item = proto_tree_add_none_format(tree, hf_lbmpdm_segment, tvb, offset, seglen, "Unknown Segment");
1110     subtree = proto_item_add_subtree(subtree_item, ett_lbmpdm_segment);
1111     proto_tree_add_item(subtree, hf_lbmpdm_segment_next_hdr, tvb, offset + O_LBMPDM_SEG_HDR_T_NEXT_HDR, L_LBMPDM_SEG_HDR_T_NEXT_HDR, encoding);
1112     proto_tree_add_item(subtree, hf_lbmpdm_segment_flags, tvb, offset + O_LBMPDM_SEG_HDR_T_FLAGS, L_LBMPDM_SEG_HDR_T_FLAGS, encoding);
1113     proto_tree_add_item(subtree, hf_lbmpdm_segment_res, tvb, offset + O_LBMPDM_SEG_HDR_T_RES, L_LBMPDM_SEG_HDR_T_RES, encoding);
1114     proto_tree_add_item(subtree, hf_lbmpdm_segment_len, tvb, offset + O_LBMPDM_SEG_HDR_T_LEN, L_LBMPDM_SEG_HDR_T_LEN, encoding);
1115     proto_tree_add_item(subtree, hf_lbmpdm_segment_data, tvb, offset + L_LBMPDM_SEG_HDR_T, datalen, ENC_NA);
1116     return (seglen);
1117 }
1118 
check_lbmpdm_encoding(tvbuff_t * tvb,int offset,int * encoding)1119 static gboolean check_lbmpdm_encoding(tvbuff_t * tvb, int offset, int * encoding)
1120 {
1121     guint8 magic_byte_1;
1122     guint8 magic_byte_2;
1123     guint8 magic_byte_3;
1124     guint8 magic_byte_4;
1125     gboolean result = TRUE;
1126 
1127     magic_byte_1 = tvb_get_guint8(tvb, offset);
1128     magic_byte_2 = tvb_get_guint8(tvb, offset + 1);
1129     magic_byte_3 = tvb_get_guint8(tvb, offset + 2);
1130     magic_byte_4 = tvb_get_guint8(tvb, offset + 3);
1131     if ((magic_byte_1 == PDM_MSG_HDR_BE_MAGIC_BYTE_1) && (magic_byte_2 == PDM_MSG_HDR_BE_MAGIC_BYTE_2)
1132         && (magic_byte_3 == PDM_MSG_HDR_BE_MAGIC_BYTE_3) && (magic_byte_4 == PDM_MSG_HDR_BE_MAGIC_BYTE_4))
1133     {
1134         *encoding = ENC_BIG_ENDIAN;
1135     }
1136     else if ((magic_byte_1 == PDM_MSG_HDR_LE_MAGIC_BYTE_1) && (magic_byte_2 == PDM_MSG_HDR_LE_MAGIC_BYTE_2)
1137             && (magic_byte_3 == PDM_MSG_HDR_LE_MAGIC_BYTE_3) && (magic_byte_4 == PDM_MSG_HDR_LE_MAGIC_BYTE_4))
1138     {
1139         *encoding = ENC_LITTLE_ENDIAN;
1140     }
1141     else
1142     {
1143         result = FALSE;
1144     }
1145     return (result);
1146 }
1147 
lbmpdm_verify_payload(tvbuff_t * tvb,int offset,int * encoding,int * length)1148 gboolean lbmpdm_verify_payload(tvbuff_t * tvb, int offset, int * encoding, int * length)
1149 {
1150     guint8 next_header;
1151     guint32 len = 0;
1152 
1153     if (!tvb_bytes_exist(tvb, offset, L_LBMPDM_MSG_HDR_T))
1154     {
1155         return (FALSE);
1156     }
1157     if (!check_lbmpdm_encoding(tvb, offset, encoding))
1158     {
1159         return (FALSE);
1160     }
1161     next_header = tvb_get_guint8(tvb, offset + O_LBMPDM_MSG_HDR_T_NEXT_HDR);
1162     switch (next_header)
1163     {
1164         case PDM_HDR_TYPE_DATA:
1165         case PDM_HDR_TYPE_OFSTTBLE:
1166         case PDM_HDR_TYPE_DEFN:
1167         case PDM_HDR_TYPE_EOM:
1168             break;
1169         default:
1170             return (FALSE);
1171             break;
1172     }
1173     len = tvb_get_guint32(tvb, offset + O_LBMPDM_MSG_HDR_T_LEN, *encoding);
1174     if (len > G_MAXINT)
1175     {
1176         return (FALSE);
1177     }
1178     *length = (int)len;
1179     return (TRUE);
1180 }
1181 
lbmpdm_dissect_lbmpdm_payload(tvbuff_t * tvb,int offset,packet_info * pinfo,proto_tree * tree,guint64 channel)1182 int lbmpdm_dissect_lbmpdm_payload(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, guint64 channel)
1183 {
1184     proto_item * subtree_item = NULL;
1185     proto_tree * subtree = NULL;
1186     proto_item * segments_item = NULL;
1187     proto_tree * segments_tree = NULL;
1188     proto_item * pi = NULL;
1189     guint8 next_hdr;
1190     int dissected_len = 0;
1191     int encoding;
1192     int msglen = 0;
1193     int len_remaining = 0;
1194     int ofs = 0;
1195     int segment_len = 0;
1196     int datalen = 0;
1197     guint32 raw_msglen = 0;
1198     lbmpdm_msg_definition_id_t msgid;
1199 
1200     if (!lbmpdm_verify_payload(tvb, offset, &encoding, &raw_msglen))
1201     {
1202         return (0);
1203     }
1204     msglen = (int)raw_msglen;
1205 
1206     msgid.channel = channel;
1207     msgid.offset_table = NULL;
1208     subtree_item = proto_tree_add_protocol_format(tree, proto_lbmpdm, tvb, offset, msglen, "LBMPDM Protocol");
1209     subtree = proto_item_add_subtree(subtree_item, ett_lbmpdm);
1210     proto_tree_add_item(subtree, hf_lbmpdm_magic, tvb, offset + O_LBMPDM_MSG_HDR_T_MAGIC, L_LBMPDM_MSG_HDR_T_MAGIC, encoding);
1211     pi = proto_tree_add_string(subtree, hf_lbmpdm_encoding, tvb, offset + O_LBMPDM_MSG_HDR_T_MAGIC, L_LBMPDM_MSG_HDR_T_MAGIC,
1212         ((encoding == ENC_BIG_ENDIAN) ? "Big-Endian" : "Little-Endian"));
1213     proto_item_set_generated(pi);
1214     proto_tree_add_item(subtree, hf_lbmpdm_ver, tvb, offset + O_LBMPDM_MSG_HDR_T_VER_TYPE, L_LBMPDM_MSG_HDR_T_VER_TYPE, encoding);
1215     proto_tree_add_item(subtree, hf_lbmpdm_type, tvb, offset + O_LBMPDM_MSG_HDR_T_VER_TYPE, L_LBMPDM_MSG_HDR_T_VER_TYPE, encoding);
1216     proto_tree_add_item(subtree, hf_lbmpdm_next_hdr, tvb, offset + O_LBMPDM_MSG_HDR_T_NEXT_HDR, L_LBMPDM_MSG_HDR_T_NEXT_HDR, encoding);
1217     proto_tree_add_item(subtree, hf_lbmpdm_def_major_ver, tvb, offset + O_LBMPDM_MSG_HDR_T_DEF_MAJOR_VER, L_LBMPDM_MSG_HDR_T_DEF_MAJOR_VER, encoding);
1218     msgid.ver_major = tvb_get_guint8(tvb, offset + O_LBMPDM_MSG_HDR_T_DEF_MAJOR_VER);
1219     proto_tree_add_item(subtree, hf_lbmpdm_def_minor_ver, tvb, offset + O_LBMPDM_MSG_HDR_T_DEF_MINOR_VER, L_LBMPDM_MSG_HDR_T_DEF_MINOR_VER, encoding);
1220     msgid.ver_minor = tvb_get_guint8(tvb, offset + O_LBMPDM_MSG_HDR_T_DEF_MINOR_VER);
1221     proto_tree_add_item(subtree, hf_lbmpdm_def_id, tvb, offset + O_LBMPDM_MSG_HDR_T_DEF_ID, L_LBMPDM_MSG_HDR_T_DEF_ID, encoding);
1222     msgid.msg_def_id = tvb_get_guint32(tvb, offset + O_LBMPDM_MSG_HDR_T_DEF_ID, encoding);
1223     proto_tree_add_item(subtree, hf_lbmpdm_len, tvb, offset + O_LBMPDM_MSG_HDR_T_LEN, L_LBMPDM_MSG_HDR_T_LEN, encoding);
1224 
1225     next_hdr = tvb_get_guint8(tvb, offset + O_LBMPDM_MSG_HDR_T_NEXT_HDR);
1226     len_remaining = msglen - L_LBMPDM_MSG_HDR_T;
1227     ofs = offset + L_LBMPDM_MSG_HDR_T;
1228     dissected_len = L_LBMPDM_MSG_HDR_T;
1229     datalen = msglen - L_LBMPDM_MSG_HDR_T;
1230     if (len_remaining > 0)
1231     {
1232         guint8 this_hdr = next_hdr;
1233 
1234         segments_item = proto_tree_add_item(subtree, hf_lbmpdm_segments, tvb, ofs, datalen, encoding);
1235         segments_tree = proto_item_add_subtree(segments_item, ett_lbmpdm_segments);
1236         while ((this_hdr != PDM_HDR_TYPE_EOM) && (len_remaining >= L_LBMPDM_SEG_HDR_T))
1237         {
1238             next_hdr = tvb_get_guint8(tvb, ofs + O_LBMPDM_SEG_HDR_T_NEXT_HDR);
1239             switch (this_hdr)
1240             {
1241                 case PDM_HDR_TYPE_DATA:
1242                     segment_len = dissect_segment_data(tvb, ofs, pinfo, segments_tree, &msgid, encoding);
1243                     break;
1244                 case PDM_HDR_TYPE_OFSTTBLE:
1245                     segment_len = dissect_segment_ofstable(tvb, ofs, pinfo, segments_tree, &(msgid.offset_table), encoding);
1246                     break;
1247                 case PDM_HDR_TYPE_DEFN:
1248                     segment_len = dissect_segment_defn(tvb, ofs, pinfo, segments_tree, channel, encoding);
1249                     break;
1250                 default:
1251                     segment_len = dissect_segment_unknown(tvb, ofs, pinfo, segments_tree, encoding);
1252                     break;
1253             }
1254             this_hdr = next_hdr;
1255             dissected_len += segment_len;
1256             len_remaining -= segment_len;
1257             ofs += segment_len;
1258         }
1259     }
1260     return (dissected_len);
1261 }
1262 
lbmpdm_get_minimum_length(void)1263 int lbmpdm_get_minimum_length(void)
1264 {
1265     return (L_LBMPDM_MSG_HDR_T);
1266 }
1267 
1268 /* Register all the bits needed with the filtering engine */
proto_register_lbmpdm(void)1269 void proto_register_lbmpdm(void)
1270 {
1271     static hf_register_info hf[] =
1272     {
1273         { &hf_lbmpdm_magic,
1274             { "Magic", "lbmpdm.magic", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1275         { &hf_lbmpdm_encoding,
1276             { "Encoding", "lbmpdm.encoding", FT_STRING, BASE_NONE, NULL, 0x0, "encoding as determined by magic number", HFILL } },
1277         { &hf_lbmpdm_ver,
1278             { "Version", "lbmpdm.ver", FT_UINT8, BASE_DEC, NULL, PDM_HDR_VER_TYPE_VER_MASK, NULL, HFILL } },
1279         { &hf_lbmpdm_type,
1280             { "Type", "lbmpdm.type", FT_UINT8, BASE_DEC, NULL, PDM_HDR_VER_TYPE_TYPE_MASK, NULL, HFILL } },
1281         { &hf_lbmpdm_next_hdr,
1282             { "Next Header", "lbmpdm.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbmpdm_next_header), 0x0, NULL, HFILL } },
1283         { &hf_lbmpdm_def_major_ver,
1284             { "Definition Major Version", "lbmpdm.def_major_ver", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1285         { &hf_lbmpdm_def_minor_ver,
1286             { "Definition Minor Version", "lbmpdm.def_minor_ver", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1287         { &hf_lbmpdm_def_id,
1288             { "Definition ID", "lbmpdm.def_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1289         { &hf_lbmpdm_len,
1290             { "Length", "lbmpdm.len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1291         { &hf_lbmpdm_segments,
1292             { "Segments", "lbmpdm.segments", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1293         { &hf_lbmpdm_segment,
1294             { "Segment", "lbmpdm.segment", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1295         { &hf_lbmpdm_segment_next_hdr,
1296             { "Next Header", "lbmpdm.segment.next_hdr", FT_UINT8, BASE_DEC_HEX, VALS(lbmpdm_next_header), 0x0, NULL, HFILL } },
1297         { &hf_lbmpdm_segment_flags,
1298             { "Flags", "lbmpdm.segment.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1299         { &hf_lbmpdm_segment_res,
1300             { "Reserved", "lbmpdm.segment.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1301         { &hf_lbmpdm_segment_len,
1302             { "Length", "lbmpdm.segment.len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1303         { &hf_lbmpdm_segment_def_id,
1304             { "Definition ID", "lbmpdm.segment_def.id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1305         { &hf_lbmpdm_segment_def_num_fields,
1306             { "Number Of Fields", "lbmpdm.segment_def.num_fields", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1307         { &hf_lbmpdm_segment_def_field_names_type,
1308             { "Field Names Type", "lbmpdm.segment_def.field_names_type", FT_UINT8, BASE_HEX, VALS(lbmpdm_field_name_type), 0x0, NULL, HFILL } },
1309         { &hf_lbmpdm_segment_def_finalized,
1310             { "Finalized", "lbmpdm.segment_def.finalized", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1311         { &hf_lbmpdm_segment_def_msg_vers_major,
1312             { "Definition Major Version", "lbmpdm.segment_def.msg_vers_major", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1313         { &hf_lbmpdm_segment_def_msg_vers_minor,
1314             { "Definition Minor Version", "lbmpdm.segment_def.msg_vers_minor", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1315         { &hf_lbmpdm_segment_def_fixed_req_section_len,
1316             { "Fixed Required Section Length", "lbmpdm.segment_def.fixed_req_section_len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1317         { &hf_lbmpdm_segment_def_field_info_len,
1318             { "Field Information Length", "lbmpdm.segment_def.field_info_len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1319         { &hf_lbmpdm_segment_def_field,
1320             { "Field Definition", "lbmpdm.segment_def.field", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1321         { &hf_lbmpdm_segment_def_field_def_len,
1322             { "Definition Length", "lbmpdm.segment_def.field.def_len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1323         { &hf_lbmpdm_segment_def_field_id,
1324             { "ID", "lbmpdm.segment_def.field.id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1325         { &hf_lbmpdm_segment_def_field_len,
1326             { "Length", "lbmpdm.segment_def.field.len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1327         { &hf_lbmpdm_segment_def_field_fixed_str_len,
1328             { "Fixed String Length", "lbmpdm.segment_def.field.fixed_str_len", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1329         { &hf_lbmpdm_segment_def_field_num_arr_elem,
1330             { "Number Of Array Elements", "lbmpdm.segment_def.field.num_arr_elem", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1331         { &hf_lbmpdm_segment_def_field_req,
1332             { "Required", "lbmpdm.segment_def.field.req", FT_UINT8, BASE_HEX, VALS(lbmpdm_field_required), 0x0, NULL, HFILL } },
1333         { &hf_lbmpdm_segment_def_field_fixed,
1334             { "Fixed Length Field", "lbmpdm.segment_def.field.fixed", FT_UINT8, BASE_HEX, VALS(lbmpdm_field_fixed_length), 0x0, NULL, HFILL } },
1335         { &hf_lbmpdm_segment_def_field_fld_int_name,
1336             { "Field Integer Name", "lbmpdm.segment_def.field.fld_int_name", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1337         { &hf_lbmpdm_segment_def_field_str_name_len,
1338             { "String Name Length", "lbmpdm.segment_def.field.str_name_len", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1339         { &hf_lbmpdm_segment_def_field_str_name,
1340             { "String Name", "lbmpdm.segment_def.field.str_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1341         { &hf_lbmpdm_segment_def_field_fld_type,
1342             { "Field Type", "lbmpdm.segment_def.field.fld_type", FT_UINT16, BASE_DEC_HEX, VALS(lbmpdm_field_type), 0x0, NULL, HFILL } },
1343         { &hf_lbmpdm_offset_entry,
1344             { "Offset Entry", "lbmpdm.segment_ofs.entry", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1345         { &hf_lbmpdm_offset_entry_id,
1346             { "ID", "lbmpdm.segment_ofs.entry.id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1347         { &hf_lbmpdm_offset_entry_offset,
1348             { "Offset", "lbmpdm.segment_ofs.entry.offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1349         { &hf_lbmpdm_segment_data,
1350             { "Data", "lbmpdm.segment.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1351         { &hf_lbmpdm_field,
1352             { "Field", "lbmpdm.field", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1353         { &hf_lbmpdm_field_id,
1354             { "ID", "lbmpdm.field.id", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1355         { &hf_lbmpdm_field_string_name,
1356             { "String Name", "lbmpdm.field.string_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1357         { &hf_lbmpdm_field_int_name,
1358             { "Integer Name", "lbmpdm.field.int_name", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1359         { &hf_lbmpdm_field_type,
1360             { "Type", "lbmpdm.field.type", FT_UINT16, BASE_DEC_HEX, VALS(lbmpdm_field_type), 0x0, NULL, HFILL } },
1361         { &hf_lbmpdm_field_total_length,
1362             { "Total Length", "lbmpdm.field.total_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1363         { &hf_lbmpdm_field_length,
1364             { "Length", "lbmpdm.field.length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
1365         { &hf_lbmpdm_field_value_boolean,
1366             { "Boolean Value", "lbmpdm.field.value_boolean", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1367         { &hf_lbmpdm_field_value_int8,
1368             { "INT8 Value", "lbmpdm.field.value_int8", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1369         { &hf_lbmpdm_field_value_uint8,
1370             { "UINT8 Value", "lbmpdm.field.value_uint8", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1371         { &hf_lbmpdm_field_value_int16,
1372             { "INT16 Value", "lbmpdm.field.value_int16", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1373         { &hf_lbmpdm_field_value_uint16,
1374             { "UINT16 Value", "lbmpdm.field.value_uint16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1375         { &hf_lbmpdm_field_value_int32,
1376             { "INT32 Value", "lbmpdm.field.value_int32", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1377         { &hf_lbmpdm_field_value_uint32,
1378             { "UINT32 Value", "lbmpdm.field.value_uint32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1379         { &hf_lbmpdm_field_value_int64,
1380             { "INT64 Value", "lbmpdm.field.value_int64", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1381         { &hf_lbmpdm_field_value_uint64,
1382             { "UINT64 Value", "lbmpdm.field.value_uint64", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1383         { &hf_lbmpdm_field_value_float,
1384             { "FLOAT Value", "lbmpdm.field.value_float", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1385         { &hf_lbmpdm_field_value_double,
1386             { "DOUBLE Value", "lbmpdm.field.value_double", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1387         { &hf_lbmpdm_field_value_decimal,
1388             { "DECIMAL Value", "lbmpdm.field.value_decimal", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1389         { &hf_lbmpdm_field_value_timestamp,
1390             { "TIMESTAMP Value", "lbmpdm.field.value_timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } },
1391         { &hf_lbmpdm_field_value_fixed_string,
1392             { "FIXED STRING Value", "lbmpdm.field.value_fixed_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1393         { &hf_lbmpdm_field_value_string,
1394             { "STRING Value", "lbmpdm.field.value_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1395         { &hf_lbmpdm_field_value_fixed_unicode,
1396             { "FIXED UNICODE Value", "lbmpdm.field.value_fixed_unicode", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1397         { &hf_lbmpdm_field_value_unicode,
1398             { "UNICODE Value", "lbmpdm.field.value_unicode", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1399         { &hf_lbmpdm_field_value_blob,
1400             { "BLOB Value", "lbmpdm.field.value_blob", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1401         { &hf_lbmpdm_field_value_message,
1402             { "MESSAGE Value", "lbmpdm.field.value_message", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }
1403     };
1404     static gint * ett[] =
1405     {
1406         &ett_lbmpdm,
1407         &ett_lbmpdm_segments,
1408         &ett_lbmpdm_segment,
1409         &ett_lbmpdm_offset_entry,
1410         &ett_lbmpdm_segment_def_field,
1411         &ett_lbmpdm_field
1412     };
1413 
1414     proto_lbmpdm = proto_register_protocol("LBMPDM Protocol", "LBMPDM", "lbmpdm");
1415 
1416     proto_register_field_array(proto_lbmpdm, hf, array_length(hf));
1417     proto_register_subtree_array(ett, array_length(ett));
1418     lbmpdm_definition_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1419 }
1420 
1421 /*
1422  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1423  *
1424  * Local variables:
1425  * c-basic-offset: 4
1426  * tab-width: 8
1427  * indent-tabs-mode: nil
1428  * End:
1429  *
1430  * vi: set shiftwidth=4 tabstop=8 expandtab:
1431  * :indentSize=4:tabSize=8:noTabs=true:
1432  */
1433