Coverage Report

Created: 2025-02-15 06:25

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