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 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 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 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 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 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 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 /*----------------------------------------------------------------------------*/ 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, ×tamp); 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 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 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 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 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 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 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 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 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 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 */ 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