| File: | builds/wireshark/wireshark/epan/dissectors/packet-trdp.c |
| Warning: | line 1280, column 5 Potential leak of memory pointed to by 'bitsetenumvals' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* packet-trdp.c | |||
| 2 | * Routines for trdp packet dissection | |||
| 3 | * | |||
| 4 | * The Train Real-Time Data Protocol (TRDP) is defined in IEC 61375-2-3. The | |||
| 5 | * protocol is used to exchange Train Communication Network (TCN) process data | |||
| 6 | * and message data. | |||
| 7 | * | |||
| 8 | * Copyright Bombardier Transportation Inc. or its subsidiaries and others, 2013. Florian Weispfenning | |||
| 9 | * Copyright Universität Rostock, 2019 (substantial changes leading to GLib-only version). Thorsten Schulz | |||
| 10 | * Copyright Stadler Deutschland GmbH, 2022-2025. Thorsten Schulz | |||
| 11 | * | |||
| 12 | * The new display-filter approach contains aspects and code | |||
| 13 | * snippets from the wimaxasncp dissector by Stephen Croll. | |||
| 14 | * | |||
| 15 | * Wireshark - Network traffic analyzer | |||
| 16 | * By Gerald Combs <[email protected]> | |||
| 17 | * Copyright 1998 Gerald Combs | |||
| 18 | * | |||
| 19 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
| 20 | */ | |||
| 21 | ||||
| 22 | #include <epan/packet.h> | |||
| 23 | #include <epan/packet_info.h> | |||
| 24 | #include <epan/prefs.h> | |||
| 25 | #include <epan/crc32-tvb.h> | |||
| 26 | #include <epan/column-utils.h> | |||
| 27 | #include <epan/dissectors/packet-tcp.h> | |||
| 28 | #include <epan/expert.h> | |||
| 29 | #include <wsutil/report_message.h> | |||
| 30 | #include <wsutil/filesystem.h> | |||
| 31 | #include "packet-trdp-dict.h" | |||
| 32 | ||||
| 33 | ||||
| 34 | /* packet-trdp-env.c */ | |||
| 35 | /* | |||
| 36 | * The SC-32 generator polynomial | |||
| 37 | */ | |||
| 38 | static const uint32_t sctab[256] = { | |||
| 39 | 0x00000000U, 0xF4ACFB13U, 0x1DF50D35U, 0xE959F626U, 0x3BEA1A6AU, | |||
| 40 | 0xCF46E179U, 0x261F175FU, 0xD2B3EC4CU, 0x77D434D4U, 0x8378CFC7U, | |||
| 41 | 0x6A2139E1U, 0x9E8DC2F2U, 0x4C3E2EBEU, 0xB892D5ADU, 0x51CB238BU, | |||
| 42 | 0xA567D898U, 0xEFA869A8U, 0x1B0492BBU, 0xF25D649DU, 0x06F19F8EU, | |||
| 43 | 0xD44273C2U, 0x20EE88D1U, 0xC9B77EF7U, 0x3D1B85E4U, 0x987C5D7CU, | |||
| 44 | 0x6CD0A66FU, 0x85895049U, 0x7125AB5AU, 0xA3964716U, 0x573ABC05U, | |||
| 45 | 0xBE634A23U, 0x4ACFB130U, 0x2BFC2843U, 0xDF50D350U, 0x36092576U, | |||
| 46 | 0xC2A5DE65U, 0x10163229U, 0xE4BAC93AU, 0x0DE33F1CU, 0xF94FC40FU, | |||
| 47 | 0x5C281C97U, 0xA884E784U, 0x41DD11A2U, 0xB571EAB1U, 0x67C206FDU, | |||
| 48 | 0x936EFDEEU, 0x7A370BC8U, 0x8E9BF0DBU, 0xC45441EBU, 0x30F8BAF8U, | |||
| 49 | 0xD9A14CDEU, 0x2D0DB7CDU, 0xFFBE5B81U, 0x0B12A092U, 0xE24B56B4U, | |||
| 50 | 0x16E7ADA7U, 0xB380753FU, 0x472C8E2CU, 0xAE75780AU, 0x5AD98319U, | |||
| 51 | 0x886A6F55U, 0x7CC69446U, 0x959F6260U, 0x61339973U, 0x57F85086U, | |||
| 52 | 0xA354AB95U, 0x4A0D5DB3U, 0xBEA1A6A0U, 0x6C124AECU, 0x98BEB1FFU, | |||
| 53 | 0x71E747D9U, 0x854BBCCAU, 0x202C6452U, 0xD4809F41U, 0x3DD96967U, | |||
| 54 | 0xC9759274U, 0x1BC67E38U, 0xEF6A852BU, 0x0633730DU, 0xF29F881EU, | |||
| 55 | 0xB850392EU, 0x4CFCC23DU, 0xA5A5341BU, 0x5109CF08U, 0x83BA2344U, | |||
| 56 | 0x7716D857U, 0x9E4F2E71U, 0x6AE3D562U, 0xCF840DFAU, 0x3B28F6E9U, | |||
| 57 | 0xD27100CFU, 0x26DDFBDCU, 0xF46E1790U, 0x00C2EC83U, 0xE99B1AA5U, | |||
| 58 | 0x1D37E1B6U, 0x7C0478C5U, 0x88A883D6U, 0x61F175F0U, 0x955D8EE3U, | |||
| 59 | 0x47EE62AFU, 0xB34299BCU, 0x5A1B6F9AU, 0xAEB79489U, 0x0BD04C11U, | |||
| 60 | 0xFF7CB702U, 0x16254124U, 0xE289BA37U, 0x303A567BU, 0xC496AD68U, | |||
| 61 | 0x2DCF5B4EU, 0xD963A05DU, 0x93AC116DU, 0x6700EA7EU, 0x8E591C58U, | |||
| 62 | 0x7AF5E74BU, 0xA8460B07U, 0x5CEAF014U, 0xB5B30632U, 0x411FFD21U, | |||
| 63 | 0xE47825B9U, 0x10D4DEAAU, 0xF98D288CU, 0x0D21D39FU, 0xDF923FD3U, | |||
| 64 | 0x2B3EC4C0U, 0xC26732E6U, 0x36CBC9F5U, 0xAFF0A10CU, 0x5B5C5A1FU, | |||
| 65 | 0xB205AC39U, 0x46A9572AU, 0x941ABB66U, 0x60B64075U, 0x89EFB653U, | |||
| 66 | 0x7D434D40U, 0xD82495D8U, 0x2C886ECBU, 0xC5D198EDU, 0x317D63FEU, | |||
| 67 | 0xE3CE8FB2U, 0x176274A1U, 0xFE3B8287U, 0x0A977994U, 0x4058C8A4U, | |||
| 68 | 0xB4F433B7U, 0x5DADC591U, 0xA9013E82U, 0x7BB2D2CEU, 0x8F1E29DDU, | |||
| 69 | 0x6647DFFBU, 0x92EB24E8U, 0x378CFC70U, 0xC3200763U, 0x2A79F145U, | |||
| 70 | 0xDED50A56U, 0x0C66E61AU, 0xF8CA1D09U, 0x1193EB2FU, 0xE53F103CU, | |||
| 71 | 0x840C894FU, 0x70A0725CU, 0x99F9847AU, 0x6D557F69U, 0xBFE69325U, | |||
| 72 | 0x4B4A6836U, 0xA2139E10U, 0x56BF6503U, 0xF3D8BD9BU, 0x07744688U, | |||
| 73 | 0xEE2DB0AEU, 0x1A814BBDU, 0xC832A7F1U, 0x3C9E5CE2U, 0xD5C7AAC4U, | |||
| 74 | 0x216B51D7U, 0x6BA4E0E7U, 0x9F081BF4U, 0x7651EDD2U, 0x82FD16C1U, | |||
| 75 | 0x504EFA8DU, 0xA4E2019EU, 0x4DBBF7B8U, 0xB9170CABU, 0x1C70D433U, | |||
| 76 | 0xE8DC2F20U, 0x0185D906U, 0xF5292215U, 0x279ACE59U, 0xD336354AU, | |||
| 77 | 0x3A6FC36CU, 0xCEC3387FU, 0xF808F18AU, 0x0CA40A99U, 0xE5FDFCBFU, | |||
| 78 | 0x115107ACU, 0xC3E2EBE0U, 0x374E10F3U, 0xDE17E6D5U, 0x2ABB1DC6U, | |||
| 79 | 0x8FDCC55EU, 0x7B703E4DU, 0x9229C86BU, 0x66853378U, 0xB436DF34U, | |||
| 80 | 0x409A2427U, 0xA9C3D201U, 0x5D6F2912U, 0x17A09822U, 0xE30C6331U, | |||
| 81 | 0x0A559517U, 0xFEF96E04U, 0x2C4A8248U, 0xD8E6795BU, 0x31BF8F7DU, | |||
| 82 | 0xC513746EU, 0x6074ACF6U, 0x94D857E5U, 0x7D81A1C3U, 0x892D5AD0U, | |||
| 83 | 0x5B9EB69CU, 0xAF324D8FU, 0x466BBBA9U, 0xB2C740BAU, 0xD3F4D9C9U, | |||
| 84 | 0x275822DAU, 0xCE01D4FCU, 0x3AAD2FEFU, 0xE81EC3A3U, 0x1CB238B0U, | |||
| 85 | 0xF5EBCE96U, 0x01473585U, 0xA420ED1DU, 0x508C160EU, 0xB9D5E028U, | |||
| 86 | 0x4D791B3BU, 0x9FCAF777U, 0x6B660C64U, 0x823FFA42U, 0x76930151U, | |||
| 87 | 0x3C5CB061U, 0xC8F04B72U, 0x21A9BD54U, 0xD5054647U, 0x07B6AA0BU, | |||
| 88 | 0xF31A5118U, 0x1A43A73EU, 0xEEEF5C2DU, 0x4B8884B5U, 0xBF247FA6U, | |||
| 89 | 0x567D8980U, 0xA2D17293U, 0x70629EDFU, 0x84CE65CCU, 0x6D9793EAU, | |||
| 90 | 0x993B68F9U }; | |||
| 91 | ||||
| 92 | uint32_t trdp_sc32(const uint8_t buf[], uint32_t len, uint32_t sc) { | |||
| 93 | uint32_t i; | |||
| 94 | ||||
| 95 | for (i = 0; i < len; i++) { | |||
| 96 | sc = sctab[((uint32_t)(sc >> 24) ^ buf[i]) & 0xff] ^ (sc << 8); | |||
| 97 | } | |||
| 98 | return sc; | |||
| 99 | } | |||
| 100 | ||||
| 101 | int32_t trdp_dissect_width(uint32_t type) { | |||
| 102 | switch (type) { | |||
| 103 | case TRDP_BITSET81: // BITSET8 1 | |||
| 104 | case TRDP_CHAR82: // CHAR8 2 char, can be used also as UTF8 | |||
| 105 | case TRDP_INT84: // INT8 4 Signed integer, 8 bit | |||
| 106 | case TRDP_UINT88: // UINT8 8 Unsigned integer, 8 bit | |||
| 107 | return 1; | |||
| 108 | case TRDP_UTF163: // UTF16 3 Unicode UTF-16 character | |||
| 109 | case TRDP_INT165: // INT16 5 Signed integer, 16 bit | |||
| 110 | case TRDP_UINT169: // UINT16 9 Unsigned integer, 16 bit | |||
| 111 | return 2; | |||
| 112 | case TRDP_INT326: // INT32 6 Signed integer, 32 bit | |||
| 113 | case TRDP_UINT3210: // UINT32 10 Unsigned integer, 32 bit | |||
| 114 | case TRDP_REAL3212: // REAL32 12 Floating point real, 32 bit | |||
| 115 | case TRDP_TIMEDATE3214: // TIMEDATE32 14 32 bit UNIX time | |||
| 116 | case TRDP_SC3217: // SC32 17 SC-32, 32 bit | |||
| 117 | return 4; | |||
| 118 | case TRDP_INT647: // INT64 7 Signed integer, 64 bit | |||
| 119 | case TRDP_UINT6411: // UINT64 11 Unsigned integer, 64 bit | |||
| 120 | case TRDP_REAL6413: // REAL64 13 Floating point real, 64 bit | |||
| 121 | case TRDP_TIMEDATE6416: // TIMEDATE64 16 32 bit seconds and 32 bit | |||
| 122 | // microseconds | |||
| 123 | return 8; | |||
| 124 | case TRDP_TIMEDATE4815: // TIMEDATE48 15 48 bit TCN time (32 bit seconds | |||
| 125 | // and 16 bit ticks) | |||
| 126 | return 6; | |||
| 127 | case TRDP_UUID18: // UUID 18 UUID, not official but improves handling in WS | |||
| 128 | return 16; | |||
| 129 | default: | |||
| 130 | return -1; | |||
| 131 | } | |||
| 132 | } | |||
| 133 | /* end packet-trdp-env.c */ | |||
| 134 | ||||
| 135 | #define API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 135, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 135, __FUNCTION__); } } while (0) \ | |||
| 136 | ws_noisy("%s:%d : %s\n", __FILE__, __LINE__, __FUNCTION__)do { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 136, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 136, __FUNCTION__); } } while (0) | |||
| 137 | ||||
| 138 | /* Reply status indication names | |||
| 139 | * Signed int: <0: NOK; 0: OK; >0: user reply status | |||
| 140 | * (taken from TRDP-EKE) */ | |||
| 141 | ||||
| 142 | static const value_string reply_status_names[] = { | |||
| 143 | {-1, "Reserved"}, | |||
| 144 | {-2, "Session abort"}, | |||
| 145 | {-3, "No replier instance (at replier side)"}, | |||
| 146 | {-4, "No memory (at replier side)"}, | |||
| 147 | {-5, "No memory (local)"}, | |||
| 148 | {-6, "No reply"}, | |||
| 149 | {-7, "Not all replies"}, | |||
| 150 | {-8, "No confirm"}, | |||
| 151 | {-9, "Reserved"}, | |||
| 152 | {-10, "Sending failed"}, | |||
| 153 | {0, "Ok"}, | |||
| 154 | {0, NULL((void*)0)}}; | |||
| 155 | ||||
| 156 | /* TRDP-packet-type map */ | |||
| 157 | static const char *trdp_types[] = { | |||
| 158 | "Pr", "PD Request", | |||
| 159 | "Pp", "PD Reply ", | |||
| 160 | "Pe", "PD Error ", | |||
| 161 | "Pd", "PD Data ", | |||
| 162 | "Mn", "MD Notification (Req. w/o reply)", | |||
| 163 | "Mr", "MD Request with reply", | |||
| 164 | "Mp", "MD Reply ( w/o confrm)", | |||
| 165 | "Mq", "MD Reply (with confrm)", | |||
| 166 | "Mc", "MD Confirm", | |||
| 167 | "Me", "MD error ", | |||
| 168 | NULL((void*)0), "Unknown TRDP Type" | |||
| 169 | }; | |||
| 170 | ||||
| 171 | /* Initialize the protocol and registered fields */ | |||
| 172 | static int proto_trdp = -1; | |||
| 173 | static dissector_handle_t trdp_handle; | |||
| 174 | static dissector_handle_t trdp_TCP_handle; | |||
| 175 | ||||
| 176 | void proto_reg_handoff_trdp(void); | |||
| 177 | void proto_register_trdp(void); | |||
| 178 | ||||
| 179 | /*For All*/ | |||
| 180 | static int hf_trdp_sequencecounter; /*uint32*/ | |||
| 181 | static int hf_trdp_protocolversion; /*uint16*/ | |||
| 182 | static int hf_trdp_type; /*uint16*/ | |||
| 183 | static int hf_trdp_etb_topocount; /*uint32*/ | |||
| 184 | static int hf_trdp_op_trn_topocount; /*uint32*/ | |||
| 185 | static int hf_trdp_comid; /*uint32*/ | |||
| 186 | static int hf_trdp_datasetlength; /*uint16*/ | |||
| 187 | static int hf_trdp_padding; /*bytes */ | |||
| 188 | ||||
| 189 | /*For All (user data)*/ | |||
| 190 | static int hf_trdp_fcs_head; /*uint32*/ | |||
| 191 | static int hf_trdp_fcs_head_calc; /*uint32*/ | |||
| 192 | static int hf_trdp_userdata; /* userdata */ | |||
| 193 | ||||
| 194 | /*needed only for PD messages*/ | |||
| 195 | static int hf_trdp_reserved; /*uint32*/ | |||
| 196 | static int hf_trdp_reply_comid; /*uint32*/ /*for MD-family only*/ | |||
| 197 | static int hf_trdp_reply_ipaddress; /*uint32*/ | |||
| 198 | ||||
| 199 | /* needed only for MD messages*/ | |||
| 200 | static int hf_trdp_replystatus; /*uint32*/ | |||
| 201 | static int hf_trdp_sessionid; /*uuid*/ | |||
| 202 | static int hf_trdp_replytimeout; /*uint32*/ | |||
| 203 | static int hf_trdp_sourceURI; /*string*/ | |||
| 204 | static int hf_trdp_destinationURI; /*string*/ | |||
| 205 | ||||
| 206 | /* Needed for dynamic content (Generated from convert_proto_tree_add_text.pl) */ | |||
| 207 | //static int hf_trdp_dataset_id; | |||
| 208 | ||||
| 209 | static bool_Bool g_basexml = TRUE(!(0)); | |||
| 210 | static const char *g_customTrdpDictionary; // XML Config Files String from ..Edit/Preference menu | |||
| 211 | static unsigned int g_pd_port = TRDP_DEFAULT_UDP_PD_PORT17224; | |||
| 212 | static unsigned int g_md_port = TRDP_DEFAULT_UDPTCP_MD_PORT17225; | |||
| 213 | static bool_Bool g_scaled = TRUE(!(0)); | |||
| 214 | static bool_Bool g_strings_are_LE; | |||
| 215 | static bool_Bool g_uids_are_LE; | |||
| 216 | static bool_Bool g_char8_is_utf8 = TRUE(!(0)); | |||
| 217 | static bool_Bool g_0strings; | |||
| 218 | static bool_Bool g_time_local = TRUE(!(0)); | |||
| 219 | static bool_Bool g_time_raw; | |||
| 220 | static int g_bitset_subtype = TRDP_BITSUBTYPE_BOOL81; | |||
| 221 | static int g_endian_subtype = TRDP_ENDSUBTYPE_BIG0; | |||
| 222 | static unsigned int g_sid = TRDP_DEFAULT_SC32_SID0xFFFFFFFF; | |||
| 223 | ||||
| 224 | /* Initialize the subtree pointers */ | |||
| 225 | static int ett_trdp = -1; | |||
| 226 | ||||
| 227 | /* Expert fields */ | |||
| 228 | static expert_field ei_trdp_type_unkown; | |||
| 229 | static expert_field ei_trdp_packet_small; | |||
| 230 | static expert_field ei_trdp_userdata_empty; | |||
| 231 | static expert_field ei_trdp_userdata_wrong; | |||
| 232 | static expert_field ei_trdp_config_notparsed; | |||
| 233 | static expert_field ei_trdp_padding_not_zero; | |||
| 234 | static expert_field ei_trdp_array_wrong; | |||
| 235 | static expert_field ei_trdp_faulty_antivalent; | |||
| 236 | static expert_field ei_trdp_reserved_not_zero; | |||
| 237 | static expert_field ei_trdp_sdtv2_safetycode; | |||
| 238 | ||||
| 239 | /* static container for dynamic fields and subtree handles */ | |||
| 240 | static struct { | |||
| 241 | wmem_array_t *hf; | |||
| 242 | wmem_array_t *ett; | |||
| 243 | } trdp_build_dict; | |||
| 244 | ||||
| 245 | static TrdpDict *pTrdpParser; | |||
| 246 | ||||
| 247 | /****************************************************************************** | |||
| 248 | * Local Functions | |||
| 249 | */ | |||
| 250 | ||||
| 251 | /** | |||
| 252 | * @internal | |||
| 253 | * Compares the found CRC in a package with a calculated version | |||
| 254 | * | |||
| 255 | * @param tvb dissected package | |||
| 256 | * @param pinfo Necessary to mark status of this packet | |||
| 257 | * @param trdp_tree tree, where the information will be added as child | |||
| 258 | * @param offset the offset in the package where the (32bit) CRC is stored | |||
| 259 | * @param data_start start where the data begins, the CRC should be calculated from | |||
| 260 | * @param data_end end where the data stops, the CRC should be calculated from | |||
| 261 | */ | |||
| 262 | static void add_crc2tree(tvbuff_t *tvb, packet_info *pinfo _U___attribute__((unused)), proto_tree *trdp_tree, uint32_t offset, uint32_t data_start, uint32_t data_end) { | |||
| 263 | uint32_t calced_crc, package_crc, length; | |||
| 264 | /* this must always fit */ | |||
| 265 | if (data_start > data_end) return; | |||
| 266 | ||||
| 267 | length = data_end - data_start; | |||
| 268 | ||||
| 269 | package_crc = tvb_get_ntohl(tvb, offset); | |||
| 270 | calced_crc = g_ntohl(crc32_ccitt_tvb_offset(tvb, data_start, length))((((((guint32) ( (((guint32) (crc32_ccitt_tvb_offset(tvb, data_start , length)) & (guint32) 0x000000ffU) << 24) | (((guint32 ) (crc32_ccitt_tvb_offset(tvb, data_start, length)) & (guint32 ) 0x0000ff00U) << 8) | (((guint32) (crc32_ccitt_tvb_offset (tvb, data_start, length)) & (guint32) 0x00ff0000U) >> 8) | (((guint32) (crc32_ccitt_tvb_offset(tvb, data_start, length )) & (guint32) 0xff000000U) >> 24))))))); | |||
| 271 | ||||
| 272 | if (package_crc == calced_crc) { | |||
| 273 | proto_tree_add_uint_format_value(trdp_tree, hf_trdp_fcs_head, tvb, offset, 4, package_crc, "0x%04x [correct]", package_crc); | |||
| 274 | } else { | |||
| 275 | proto_tree_add_uint_format_value(trdp_tree, hf_trdp_fcs_head, tvb, offset, 4, package_crc, "0x%04x [mismatch]", package_crc); | |||
| 276 | proto_tree_add_uint_format_value(trdp_tree, hf_trdp_fcs_head_calc, tvb, offset, 4, calced_crc, "0x%04x [mismatch]", calced_crc); | |||
| 277 | } | |||
| 278 | } | |||
| 279 | ||||
| 280 | /* @fn *static void checkPaddingAndOffset(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset) | |||
| 281 | * | |||
| 282 | * @brief Check for correct padding | |||
| 283 | * | |||
| 284 | * @param[in] tvb Buffer with the captured data | |||
| 285 | * @param[in] pinfo Necessary to mark status of this packet | |||
| 286 | * @param[in] tree The information is appended | |||
| 287 | * @param[in] offset Actual offset where the padding starts | |||
| 288 | * | |||
| 289 | * @return position in the buffer | |||
| 290 | */ | |||
| 291 | static int32_t checkPaddingAndOffset(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset) { | |||
| 292 | int32_t remainingBytes; | |||
| 293 | bool_Bool isPaddingZero = TRUE(!(0)); | |||
| 294 | ||||
| 295 | remainingBytes = tvb_reported_length_remaining(tvb, offset); | |||
| 296 | ws_noisy("The remaining bytes are %d (padding=%d)", remainingBytes, remainingBytes%4)do { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 296, __func__, "The remaining bytes are %d (padding=%d)", remainingBytes , remainingBytes%4); } } while (0); | |||
| 297 | ||||
| 298 | if (remainingBytes < 0) { /* There is no space for user data */ | |||
| 299 | return offset; | |||
| 300 | } else if (remainingBytes > 0) { | |||
| 301 | for (int i = 0; i < remainingBytes; i++) { | |||
| 302 | if (tvb_get_uint8(tvb, offset + i) != 0) { | |||
| 303 | isPaddingZero = FALSE(0); | |||
| 304 | break; | |||
| 305 | } | |||
| 306 | } | |||
| 307 | proto_tree_add_bytes_format_value(tree, hf_trdp_padding, tvb, offset, remainingBytes, NULL((void*)0), "%s", (isPaddingZero ? "[ok]" : "not zero")); | |||
| 308 | ||||
| 309 | /* Mark this packet in the statistics also as "not perfect" */ | |||
| 310 | if (!isPaddingZero) expert_add_info_format(pinfo, tree, &ei_trdp_padding_not_zero, "Padding not zero"); | |||
| 311 | } | |||
| 312 | return remainingBytes + TRDP_FCS_LENGTH4; | |||
| 313 | } | |||
| 314 | ||||
| 315 | /** @fn uint32_t dissect_trdp_generic_body(tvbuff_t *tvb, packet_info *pinfo, | |||
| 316 | * proto_tree *trdp_tree, proto_tree *trdpRootNode, uint32_t trdp_comid, uint32_t | |||
| 317 | * offset, unsigned int clength, uint8_t dataset_level, const char *title, const int32_t | |||
| 318 | * arr_idx ) | |||
| 319 | * | |||
| 320 | * @brief Extract all information from the userdata (uses the parsebody module for unmarshalling) | |||
| 321 | * | |||
| 322 | * @param tvb buffer | |||
| 323 | * @param pinfo info for the packet | |||
| 324 | * @param trdp_tree to which the information are added | |||
| 325 | * @param trdpRootNode Root node of the view of an TRDP packet (Necessary, as this function will be called recursively) | |||
| 326 | * @param trdp_comid the already extracted comId | |||
| 327 | * @param offset where the userdata starts in the TRDP packet | |||
| 328 | * @param clength Amount of bytes, that are transported for the users | |||
| 329 | * @param dataset_level is set to 0 for the beginning | |||
| 330 | * @param title presents the instance-name of the dataset for the sub-tree | |||
| 331 | * @param arr_idx index for presentation when a dataset occurs in an array element | |||
| 332 | * | |||
| 333 | * @return the actual offset in the packet | |||
| 334 | */ | |||
| 335 | // NOLINTNEXTLINE(misc-no-recursion) -- increment_dissection_depth() is used as guard | |||
| 336 | static uint32_t dissect_trdp_generic_body( | |||
| 337 | tvbuff_t *tvb, packet_info *pinfo, proto_tree *trdp_tree, proto_tree *trdpRootNode, uint32_t trdp_comid, | |||
| 338 | uint32_t offset, unsigned int clength, uint8_t dataset_level, const char *title, const int32_t arr_idx) | |||
| 339 | { | |||
| 340 | ||||
| 341 | uint32_t start_offset = offset; /* mark beginning of the userdata in pkg */ | |||
| 342 | int length; | |||
| 343 | const Dataset *ds = NULL((void*)0); | |||
| 344 | proto_tree *trdp_userdata = NULL((void*)0); | |||
| 345 | proto_tree *userdata_element = NULL((void*)0); | |||
| 346 | proto_item *pi = NULL((void*)0); | |||
| 347 | int array_index; | |||
| 348 | int element_count = 0; | |||
| 349 | ||||
| 350 | /* make the userdata accessible for wireshark */ | |||
| 351 | if (!dataset_level) { | |||
| 352 | if (!clength) return checkPaddingAndOffset(tvb, pinfo, trdp_tree, offset); | |||
| 353 | ||||
| 354 | pi = proto_tree_add_item(trdp_tree, hf_trdp_userdata, tvb, offset, clength, ENC_NA0x00000000); | |||
| 355 | ||||
| 356 | ws_debug("Searching for comid %u", trdp_comid)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 356, __func__, "Searching for comid %u", trdp_comid); } } while (0); | |||
| 357 | const ComId *com = TrdpDict_lookup_ComId(pTrdpParser, trdp_comid); | |||
| 358 | ||||
| 359 | if (!com) { | |||
| 360 | offset += clength; | |||
| 361 | return checkPaddingAndOffset(tvb, pinfo, trdp_tree, offset); | |||
| 362 | } else | |||
| 363 | ds = com->linkedDS; | |||
| 364 | ||||
| 365 | /* so far, length was all userdata received, but this is not true for | |||
| 366 | * sub-datasets. */ | |||
| 367 | /* but here we can check it works out */ | |||
| 368 | length = ds ? ds->size : -1; | |||
| 369 | ||||
| 370 | if (length < 0) { /* No valid configuration for this ComId available */ | |||
| 371 | proto_tree_add_expert_format(trdp_userdata, pinfo, &ei_trdp_userdata_empty, tvb, offset, clength, | |||
| 372 | "Userdata should be empty or was incomplete, cannot parse. Check xml-config."); | |||
| 373 | ws_debug("No Dataset, %d byte of userdata -> end offset is %d [dataset-level: %d]", clength, offset, dataset_level)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 373, __func__, "No Dataset, %d byte of userdata -> end offset is %d [dataset-level: %d]" , clength, offset, dataset_level); } } while (0); | |||
| 374 | offset += clength; | |||
| 375 | return checkPaddingAndOffset(tvb, pinfo, trdp_tree, offset); | |||
| 376 | } | |||
| 377 | } else { | |||
| 378 | ||||
| 379 | ws_debug("Searching for dataset %u", trdp_comid)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 379, __func__, "Searching for dataset %u", trdp_comid); } } while (0); | |||
| 380 | ds = TrdpDict_get_Dataset(pTrdpParser, trdp_comid /* <- datasetID */); | |||
| 381 | ||||
| 382 | length = ds ? ds->size : -1; | |||
| 383 | if (length < 0) { /* this should actually not happen, ie. should be caught | |||
| 384 | in initial comID-round */ | |||
| 385 | proto_tree_add_expert_format(trdp_userdata, pinfo, &ei_trdp_userdata_empty, tvb, offset, length, | |||
| 386 | "Userdata should be empty or was incomplete, cannot parse. Check xml-config."); | |||
| 387 | return offset; | |||
| 388 | } | |||
| 389 | } | |||
| 390 | ||||
| 391 | ws_debug("%s aka %u ([%d] octets)", ds->name, ds->datasetId, length)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 391, __func__, "%s aka %u ([%d] octets)", ds->name, ds-> datasetId, length); } } while (0); | |||
| 392 | trdp_userdata = (arr_idx >= 0) | |||
| 393 | ? proto_tree_add_subtree_format(trdp_tree, tvb, offset, length ? length : -1, ds->ett_id, &pi, "%s.%d", title, arr_idx) | |||
| 394 | : (ds->source /* if custom, show its dataset-id*/ | |||
| 395 | ? proto_tree_add_subtree_format(trdp_tree, tvb, offset, length ? length : -1, ds->ett_id, &pi, "%s: %s (%d)", title, ds->name, ds->datasetId) | |||
| 396 | : proto_tree_add_subtree_format(trdp_tree, tvb, offset, length ? length : -1, ds->ett_id, &pi, "%s: %s", title, ds->name)); | |||
| 397 | ||||
| 398 | array_index = 0; | |||
| 399 | int potential_array_size = -1; | |||
| 400 | for (Element *el = ds->listOfElements; el; el = el->next) { | |||
| 401 | ||||
| 402 | ws_debug("[%d] Offset %5d ----> Element: type=%2d "do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 405, __func__, "[%d] Offset %5d ----> Element: type=%2d " "%s\tname=%s\tarray-size=%d\tunit=%s\tscale=%f\toffset=%d", dataset_level , offset, el->type.id, el->type.name, el->name, el-> array_size, el->unit, el->scale, el->offset); } } while (0) | |||
| 403 | "%s\tname=%s\tarray-size=%d\tunit=%s\tscale=%f\toffset=%d",do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 405, __func__, "[%d] Offset %5d ----> Element: type=%2d " "%s\tname=%s\tarray-size=%d\tunit=%s\tscale=%f\toffset=%d", dataset_level , offset, el->type.id, el->type.name, el->name, el-> array_size, el->unit, el->scale, el->offset); } } while (0) | |||
| 404 | dataset_level, offset, el->type.id, el->type.name, el->name,do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 405, __func__, "[%d] Offset %5d ----> Element: type=%2d " "%s\tname=%s\tarray-size=%d\tunit=%s\tscale=%f\toffset=%d", dataset_level , offset, el->type.id, el->type.name, el->name, el-> array_size, el->unit, el->scale, el->offset); } } while (0) | |||
| 405 | el->array_size, el->unit, el->scale, el->offset)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 405, __func__, "[%d] Offset %5d ----> Element: type=%2d " "%s\tname=%s\tarray-size=%d\tunit=%s\tscale=%f\toffset=%d", dataset_level , offset, el->type.id, el->type.name, el->name, el-> array_size, el->unit, el->scale, el->offset); } } while (0); | |||
| 406 | ||||
| 407 | // at startup of a new item, check if it is an array or not | |||
| 408 | int remainder = 0; | |||
| 409 | element_count = el->array_size; | |||
| 410 | ||||
| 411 | if (!element_count) { // handle variable element count | |||
| 412 | ||||
| 413 | if (g_0strings && (el->type.id == TRDP_CHAR82 || el->type.id == TRDP_UTF163)) { | |||
| 414 | /* handle the special elements CHAR8 and UTF16: */ | |||
| 415 | ||||
| 416 | } else { | |||
| 417 | element_count = potential_array_size; | |||
| 418 | ||||
| 419 | if (element_count < 1) { | |||
| 420 | ||||
| 421 | if (element_count == 0) { | |||
| 422 | potential_array_size = -1; | |||
| 423 | continue; /* if, at the end of the day, the array is intentionally 0, skip the element */ | |||
| 424 | } else { | |||
| 425 | expert_add_info_format(pinfo, trdp_tree, &ei_trdp_array_wrong, "%s : was introduced by an unsupported length field. (%d)", el->name, potential_array_size); | |||
| 426 | return 0; /* in this case, the whole packet is garbled */ | |||
| 427 | } | |||
| 428 | } else { | |||
| 429 | ws_debug("[%d] Offset %5d Dynamic array, with %d elements found", dataset_level, offset, element_count)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 429, __func__, "[%d] Offset %5d Dynamic array, with %d elements found" , dataset_level, offset, element_count); } } while (0); | |||
| 430 | } | |||
| 431 | ||||
| 432 | // check if the specified amount could be found in the package | |||
| 433 | remainder = tvb_reported_length_remaining(tvb, offset); | |||
| 434 | if (remainder < TrdpDict_element_size(el, element_count)) { | |||
| 435 | expert_add_info_format(pinfo, trdp_tree, &ei_trdp_userdata_wrong, "%s : has %d elements [%d byte each], but only %d left", el->name, element_count, TrdpDict_element_size(el, 1), remainder); | |||
| 436 | element_count = 0; | |||
| 437 | } | |||
| 438 | } | |||
| 439 | } | |||
| 440 | if (element_count > 1) { | |||
| 441 | ws_debug("[%d] Offset %5d -- Array found, expecting %d elements using %d bytes", dataset_level, offset, element_count, TrdpDict_element_size(el, element_count))do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 441, __func__, "[%d] Offset %5d -- Array found, expecting %d elements using %d bytes" , dataset_level, offset, element_count, TrdpDict_element_size (el, element_count)); } } while (0); | |||
| 442 | } | |||
| 443 | ||||
| 444 | /* For an array, inject a new node in the graphical dissector, tree (also the extracted dynamic information, see above are added) */ | |||
| 445 | userdata_element = ((element_count == 1) || (el->type.id == TRDP_CHAR82) || (el->type.id == TRDP_UTF163)) /* for single line */ | |||
| 446 | ? trdp_userdata /* take existing branch */ | |||
| 447 | : proto_tree_add_subtree_format( trdp_userdata, tvb, offset, | |||
| 448 | TrdpDict_element_size(el, element_count), | |||
| 449 | el->ett_id, &pi, | |||
| 450 | "%s (%d) : %s[%d]", el->type.name, el->type.id, el->name, element_count); | |||
| 451 | ||||
| 452 | do { | |||
| 453 | int64_t vals = 0; | |||
| 454 | uint64_t valu = 0; | |||
| 455 | const char *text = NULL((void*)0); | |||
| 456 | unsigned int slen = 0; | |||
| 457 | unsigned int bytelen = 0; | |||
| 458 | double real64 = 0; | |||
| 459 | nstime_t nstime = {0, 0}; | |||
| 460 | char bits[TRDP_BITSUBTYPE_BITS8+1]; | |||
| 461 | uint32_t package_crc = 0; | |||
| 462 | uint32_t calced_crc, buff_length; | |||
| 463 | uint8_t *pBuff; | |||
| 464 | e_guid_t guid; | |||
| 465 | ||||
| 466 | switch (el->type.id) { | |||
| 467 | ||||
| 468 | case TRDP_BITSET81: | |||
| 469 | switch (el->type.subtype) { | |||
| 470 | case TRDP_BITSUBTYPE_BOOL81: | |||
| 471 | valu = tvb_get_uint8(tvb, offset); | |||
| 472 | proto_tree_add_boolean(userdata_element, el->hf_id, tvb, offset, el->width, (uint32_t)valu); | |||
| 473 | offset += el->width; | |||
| 474 | break; | |||
| 475 | case TRDP_BITSUBTYPE_BITSET80: | |||
| 476 | if (!el->bitfields) { | |||
| 477 | valu = tvb_get_uint8(tvb, offset); | |||
| 478 | bits[sizeof(bits) - 1] = 0; | |||
| 479 | uint64_t v = valu; | |||
| 480 | for (int i = sizeof(bits) - 1; i--; v >>= 1) bits[i] = v & 1 ? '1' : '.'; | |||
| 481 | proto_tree_add_uint_format_value(userdata_element, el->hf_id, tvb, offset, el->width, (uint32_t)valu, | |||
| 482 | "0x%#02x ( %s )", (uint32_t)valu, bits); | |||
| 483 | } else { | |||
| 484 | proto_tree_add_bitmask(userdata_element, tvb, offset, el->hf_id, el->bits_ett_id, el->bitfields, ENC_BIG_ENDIAN0x00000000); | |||
| 485 | } | |||
| 486 | offset += el->width; | |||
| 487 | break; | |||
| 488 | case TRDP_BITSUBTYPE_ANTIVALENT82: | |||
| 489 | valu = tvb_get_uint8(tvb, offset); | |||
| 490 | switch (valu) { | |||
| 491 | case 1: | |||
| 492 | proto_tree_add_boolean(userdata_element, el->hf_id, tvb, offset, el->width, (uint32_t)FALSE(0)); | |||
| 493 | break; | |||
| 494 | ||||
| 495 | case 2: | |||
| 496 | proto_tree_add_boolean(userdata_element, el->hf_id, tvb, offset, el->width, (uint32_t)TRUE(!(0))); | |||
| 497 | break; | |||
| 498 | ||||
| 499 | default: | |||
| 500 | proto_tree_add_expert_format(userdata_element, pinfo, &ei_trdp_faulty_antivalent, tvb, offset, el->width, | |||
| 501 | "%#2x is an invalid ANTIVALENT8 value.", (uint32_t)valu); | |||
| 502 | break; | |||
| 503 | } | |||
| 504 | offset += el->width; | |||
| 505 | break; | |||
| 506 | } | |||
| 507 | break; | |||
| 508 | ||||
| 509 | case TRDP_CHAR82: | |||
| 510 | bytelen = (element_count || !g_0strings) ? (unsigned int)element_count : tvb_strsize(tvb, offset); | |||
| 511 | slen = (element_count || !g_0strings) ? bytelen : (bytelen - 1); | |||
| 512 | text = (g_char8_is_utf8 && element_count > 1) | |||
| 513 | ? (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_80x00000002) | |||
| 514 | : tvb_format_text(pinfo->pool, tvb, offset, slen); | |||
| 515 | ||||
| 516 | if (element_count == 1) | |||
| 517 | proto_tree_add_string(userdata_element, el->hf_id, tvb, offset, bytelen, text); | |||
| 518 | else | |||
| 519 | proto_tree_add_string_format_value(userdata_element, el->hf_id, tvb, offset, bytelen, text, "[%d] \"%s\"", slen, text); | |||
| 520 | offset += bytelen; | |||
| 521 | element_count = 1; | |||
| 522 | break; | |||
| 523 | ||||
| 524 | case TRDP_UTF163: | |||
| 525 | bytelen = (element_count || !g_0strings) ? (unsigned int)(2 * element_count) : tvb_unicode_strsize(tvb, offset); | |||
| 526 | slen = (element_count || !g_0strings) ? bytelen : (bytelen - 2); | |||
| 527 | text = (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset, slen, ENC_UTF_160x00000004 | (g_strings_are_LE ? ENC_LITTLE_ENDIAN0x80000000 : ENC_BIG_ENDIAN0x00000000)); | |||
| 528 | proto_tree_add_string_format_value(userdata_element, el->hf_id, tvb, offset, bytelen, text, "[%d] \"%s\"", slen / 2, text); | |||
| 529 | offset += bytelen; | |||
| 530 | element_count = 1; | |||
| 531 | break; | |||
| 532 | ||||
| 533 | case TRDP_INT84: | |||
| 534 | vals = tvb_get_int8(tvb, offset); | |||
| 535 | break; | |||
| 536 | ||||
| 537 | case TRDP_INT165: | |||
| 538 | vals = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohis(tvb, offset) : tvb_get_ntohis(tvb, offset); | |||
| 539 | break; | |||
| 540 | ||||
| 541 | case TRDP_INT326: | |||
| 542 | vals = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohil(tvb, offset) : tvb_get_ntohil(tvb, offset); | |||
| 543 | break; | |||
| 544 | ||||
| 545 | case TRDP_INT647: | |||
| 546 | vals = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohi64(tvb, offset) : tvb_get_ntohi64(tvb, offset); | |||
| 547 | break; | |||
| 548 | ||||
| 549 | case TRDP_UINT88: | |||
| 550 | valu = tvb_get_uint8(tvb, offset); | |||
| 551 | break; | |||
| 552 | ||||
| 553 | case TRDP_UINT169: | |||
| 554 | valu = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset); | |||
| 555 | break; | |||
| 556 | ||||
| 557 | case TRDP_UINT3210: | |||
| 558 | valu = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset); | |||
| 559 | break; | |||
| 560 | ||||
| 561 | case TRDP_UINT6411: | |||
| 562 | valu = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letoh64(tvb, offset) : tvb_get_ntoh64(tvb, offset); | |||
| 563 | break; | |||
| 564 | ||||
| 565 | case TRDP_REAL3212: | |||
| 566 | real64 = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohieee_float(tvb, offset) : tvb_get_ntohieee_float(tvb, offset); | |||
| 567 | break; | |||
| 568 | ||||
| 569 | case TRDP_REAL6413: | |||
| 570 | real64 = el->type.subtype == TRDP_ENDSUBTYPE_LIT1 ? tvb_get_letohieee_double(tvb, offset) : tvb_get_ntohieee_double(tvb, offset); | |||
| 571 | break; | |||
| 572 | ||||
| 573 | case TRDP_TIMEDATE3214: | |||
| 574 | /* This should be time_t from general understanding, which is UNIX time, | |||
| 575 | * seconds since 1970 time_t is a signed long in modern POSIX ABIs, ie. | |||
| 576 | * often s64! However, vos_types.h defines this as u32, which may | |||
| 577 | * introduce some odd complications -- later. IEC61375-2-1 says for | |||
| 578 | * UNIX-time: SIGNED32 - ok, will respect! | |||
| 579 | */ | |||
| 580 | vals = tvb_get_ntohil(tvb, offset); | |||
| 581 | nstime.secs = (long int)vals; | |||
| 582 | break; | |||
| 583 | ||||
| 584 | case TRDP_TIMEDATE4815: | |||
| 585 | vals = tvb_get_ntohil(tvb, offset); | |||
| 586 | nstime.secs = (time_t)vals; | |||
| 587 | valu = tvb_get_ntohs(tvb, offset + 4); | |||
| 588 | nstime.nsecs = (int)(valu * (1000000000ULL / 256ULL)) / 256; | |||
| 589 | break; | |||
| 590 | ||||
| 591 | case TRDP_TIMEDATE6416: | |||
| 592 | vals = tvb_get_ntohil(tvb, offset); | |||
| 593 | nstime.secs = (time_t)vals; | |||
| 594 | vals = tvb_get_ntohil(tvb, offset + 4); | |||
| 595 | nstime.nsecs = (int)vals * 1000; | |||
| 596 | break; | |||
| 597 | ||||
| 598 | case TRDP_SC3217: | |||
| 599 | package_crc = tvb_get_ntohl(tvb, offset); | |||
| 600 | break; | |||
| 601 | ||||
| 602 | case TRDP_UUID18: | |||
| 603 | tvb_get_guid(tvb, offset, &guid, (g_uids_are_LE ? ENC_LITTLE_ENDIAN0x80000000 : ENC_BIG_ENDIAN0x00000000)); | |||
| 604 | break; | |||
| 605 | ||||
| 606 | default: | |||
| 607 | ws_debug("Unique type %d for %s", el->type.id, el->name)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 607, __func__, "Unique type %d for %s", el->type.id, el-> name); } } while (0); | |||
| 608 | /* safe guard against excessive recursion of datasets. | |||
| 609 | * This should have been handled at dictionary reading. If it breaks here, it is some weired bug. | |||
| 610 | */ | |||
| 611 | /* use wireshark's own protection. However, in the current dev-build of WS this value's (gui.max_tree_depth) default was much higher. */ | |||
| 612 | /* be aware that each array introduces an extra level, as well as other protocol layers */ | |||
| 613 | increment_dissection_depth(pinfo); | |||
| 614 | ||||
| 615 | // NOLINTNEXTLINE(misc-no-recursion) | |||
| 616 | offset = dissect_trdp_generic_body( tvb, pinfo, userdata_element, trdpRootNode, el->type.id, offset, length - (offset - start_offset), | |||
| 617 | dataset_level + 1, el->name, (element_count != 1) ? array_index : -1); | |||
| 618 | decrement_dissection_depth(pinfo); | |||
| 619 | ||||
| 620 | if (offset == 0) return offset; /* break dissecting, if things went sideways */ | |||
| 621 | break; | |||
| 622 | } | |||
| 623 | ||||
| 624 | switch (el->type.id) { | |||
| 625 | ||||
| 626 | /* case TRDP_INT8 ... TRDP_INT64: */ | |||
| 627 | case TRDP_INT84: | |||
| 628 | case TRDP_INT165: | |||
| 629 | case TRDP_INT326: | |||
| 630 | case TRDP_INT647: | |||
| 631 | ||||
| 632 | if (g_ascii_strcasecmp(el->unit, "hide0") == 0) { | |||
| 633 | if (vals != 0) proto_tree_add_expert_format(userdata_element, pinfo, &ei_trdp_reserved_not_zero, | |||
| 634 | tvb, offset, el->width, "Element is not zero (%" G_GINT64_FORMAT"li" ").", vals); | |||
| 635 | } else if (el->scale && g_scaled) { | |||
| 636 | double formated_value = vals * el->scale + el->offset; | |||
| 637 | proto_tree_add_double_format_value(userdata_element, el->hf_id, tvb, offset, el->width, formated_value, | |||
| 638 | "%lg %s (raw=%" G_GINT64_FORMAT"li" ")", formated_value, el->unit, vals); | |||
| 639 | } else { | |||
| 640 | if (g_scaled) vals += el->offset; | |||
| 641 | proto_tree_add_int64(userdata_element, el->hf_id, tvb, offset, el->width, vals); | |||
| 642 | } | |||
| 643 | offset += el->width; | |||
| 644 | break; | |||
| 645 | ||||
| 646 | /* case TRDP_UINT8 ... TRDP_UINT64: */ | |||
| 647 | case TRDP_UINT88: | |||
| 648 | case TRDP_UINT169: | |||
| 649 | case TRDP_UINT3210: | |||
| 650 | case TRDP_UINT6411: | |||
| 651 | if (g_ascii_strcasecmp(el->unit, "hide0") == 0) { | |||
| 652 | if (valu != 0) proto_tree_add_expert_format(userdata_element, pinfo, &ei_trdp_reserved_not_zero, | |||
| 653 | tvb, offset, el->width, "Element is not zero (%" G_GUINT64_FORMAT"lu" ").", valu); | |||
| 654 | } else if (g_ascii_strcasecmp(el->unit, "version") == 0) { | |||
| 655 | proto_tree_add_uint_format_value(userdata_element, el->hf_id, tvb, offset, el->width, (uint32_t)valu, "%02"PRId64"l" "d"".%02"PRId64"l" "d""", (valu >> 8) & 0xff, (valu >> 0) & 0xff); | |||
| 656 | } else if (el->scale && g_scaled) { | |||
| 657 | double formated_value = valu * el->scale + el->offset; | |||
| 658 | proto_tree_add_double_format_value(userdata_element, el->hf_id, tvb, offset, el->width, formated_value, | |||
| 659 | "%lg %s (raw=%" G_GUINT64_FORMAT"lu" ")", formated_value, el->unit, valu); | |||
| 660 | } else { | |||
| 661 | if (g_scaled) valu += el->offset; | |||
| 662 | proto_tree_add_uint64(userdata_element, el->hf_id, tvb, offset, el->width, valu); | |||
| 663 | } | |||
| 664 | offset += el->width; | |||
| 665 | break; | |||
| 666 | ||||
| 667 | case TRDP_REAL3212: | |||
| 668 | case TRDP_REAL6413: | |||
| 669 | if (el->scale && g_scaled) { | |||
| 670 | double formated_value = real64 * el->scale + el->offset; | |||
| 671 | proto_tree_add_double_format_value(userdata_element, el->hf_id, tvb, offset, el->width, formated_value, | |||
| 672 | "%lg %s (raw=%lf)", formated_value, el->unit, real64); | |||
| 673 | } else { | |||
| 674 | if (g_scaled) real64 += el->offset; | |||
| 675 | proto_tree_add_double(userdata_element, el->hf_id, tvb, offset, el->width, real64); | |||
| 676 | } | |||
| 677 | offset += el->width; | |||
| 678 | break; | |||
| 679 | ||||
| 680 | /* case TRDP_TIMEDATE32 ... TRDP_TIMEDATE64: */ | |||
| 681 | case TRDP_TIMEDATE3214: | |||
| 682 | case TRDP_TIMEDATE4815: | |||
| 683 | case TRDP_TIMEDATE6416: | |||
| 684 | /* Is it allowed to have offset / scale?? I am not going to scale | |||
| 685 | * seconds, but there could be use for an offset, esp. when misused as | |||
| 686 | * relative time. */ | |||
| 687 | if (g_scaled) nstime.secs += el->offset; | |||
| 688 | if (g_time_raw) { | |||
| 689 | switch (el->type.id) { | |||
| 690 | case TRDP_TIMEDATE3214: | |||
| 691 | proto_tree_add_time_format_value(userdata_element, el->hf_id, tvb, offset, el->width, &nstime, | |||
| 692 | "%ld seconds", nstime.secs); | |||
| 693 | break; | |||
| 694 | case TRDP_TIMEDATE4815: | |||
| 695 | proto_tree_add_time_format_value(userdata_element, el->hf_id, tvb, offset, el->width, &nstime, | |||
| 696 | "%ld.%05ld seconds (=%" G_GUINT64_FORMAT"lu" " ticks)", nstime.secs, (nstime.nsecs + 5000L) / 10000L, valu); | |||
| 697 | break; | |||
| 698 | case TRDP_TIMEDATE6416: | |||
| 699 | proto_tree_add_time_format_value(userdata_element, el->hf_id, tvb, offset, el->width, &nstime, | |||
| 700 | "%ld.%06ld seconds", nstime.secs, nstime.nsecs / 1000L); | |||
| 701 | break; | |||
| 702 | ||||
| 703 | } | |||
| 704 | } else | |||
| 705 | proto_tree_add_time(userdata_element, el->hf_id, tvb, offset, el->width, &nstime); | |||
| 706 | ||||
| 707 | offset += el->width; | |||
| 708 | break; | |||
| 709 | ||||
| 710 | case TRDP_SC3217: | |||
| 711 | buff_length = tvb_get_ntohl(tvb, TRDP_HEADER_OFFSET_DATASETLENGTH20) - TRDP_SC32_LENGTH4; | |||
| 712 | pBuff = (uint8_t *)g_malloc(buff_length); | |||
| 713 | if (pBuff != NULL((void*)0)) { | |||
| 714 | tvb_memcpy(tvb, pBuff, TRDP_HEADER_PD_OFFSET_DATA40, buff_length); | |||
| 715 | calced_crc = trdp_sc32(pBuff, buff_length, (uint32_t)(g_sid & 0xFFFFFFFF)); | |||
| 716 | if (package_crc == calced_crc) { | |||
| 717 | proto_tree_add_uint_format_value(userdata_element, el->hf_id, tvb, offset, el->width, package_crc, "0x%04x [correct]", package_crc); | |||
| 718 | } else { | |||
| 719 | proto_tree_add_uint_format_value(userdata_element, el->hf_id, tvb, offset, el->width, package_crc, "0x%04x [incorrect, should be 0x%04x]", package_crc, calced_crc); | |||
| 720 | proto_tree_add_expert_format(userdata_element, pinfo, &ei_trdp_sdtv2_safetycode, tvb, offset, el->width, "0x%04x is an incorrect SC32 value.", (uint32_t)package_crc); | |||
| 721 | } | |||
| 722 | g_free(pBuff); | |||
| 723 | } | |||
| 724 | offset += el->width; | |||
| 725 | break; | |||
| 726 | case TRDP_UUID18: | |||
| 727 | proto_tree_add_guid(userdata_element, el->hf_id, tvb, offset, el->width, &guid); | |||
| 728 | offset += el->width; | |||
| 729 | break; | |||
| 730 | } | |||
| 731 | ||||
| 732 | if (array_index || element_count != 1) { | |||
| 733 | /* handle arrays */ | |||
| 734 | ws_debug( "[%d / %d]", array_index, element_count)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 734, __func__, "[%d / %d]", array_index, element_count); } } while (0); | |||
| 735 | if (++array_index >= element_count) { | |||
| 736 | array_index = 0; | |||
| 737 | userdata_element = trdp_userdata; | |||
| 738 | } | |||
| 739 | potential_array_size = -1; | |||
| 740 | } else { | |||
| 741 | ws_debug("[%d / %d], (type=%d) val-u=%" G_GUINT64_FORMAT " val-s=%" G_GINT64_FORMAT ".", array_index, element_count, el->type.id, valu, vals)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 741, __func__, "[%d / %d], (type=%d) val-u=%" "lu" " val-s=%" "li" ".", array_index, element_count, el->type.id, valu, vals ); } } while (0); | |||
| 742 | ||||
| 743 | potential_array_size = (el->type.id < TRDP_INT84 || el->type.id > TRDP_UINT6411) ? -1 : (el->type.id >= TRDP_UINT88 ? (int)valu : (int)vals); | |||
| 744 | } | |||
| 745 | ||||
| 746 | } while (array_index); | |||
| 747 | } | |||
| 748 | ||||
| 749 | /* Check padding of the body */ | |||
| 750 | if (!dataset_level) offset = checkPaddingAndOffset(tvb, pinfo, trdpRootNode, offset); | |||
| 751 | ||||
| 752 | return offset; | |||
| 753 | } | |||
| 754 | ||||
| 755 | static void add_dataset_reg_info(Dataset *ds); | |||
| 756 | ||||
| 757 | /** | |||
| 758 | * @internal | |||
| 759 | * Extract all information from the userdata (uses the parsebody module for | |||
| 760 | * unmarshalling) | |||
| 761 | * | |||
| 762 | * @param tvb buffer | |||
| 763 | * @param packet info for tht packet | |||
| 764 | * @param tree to which the information are added | |||
| 765 | * @param trdp_comid the already extracted comId | |||
| 766 | * @param offset where the userdata starts in the TRDP package | |||
| 767 | * | |||
| 768 | * @return size of the user data | |||
| 769 | */ | |||
| 770 | static uint32_t dissect_trdp_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *trdp_tree, uint32_t trdp_comid, uint32_t offset, uint32_t length) { | |||
| 771 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 771, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 771, __FUNCTION__); } } while (0); | |||
| 772 | return dissect_trdp_generic_body(tvb, pinfo, trdp_tree, trdp_tree, trdp_comid, offset, length, 0 /* level of cascaded datasets*/, "dataset", -1); | |||
| 773 | } | |||
| 774 | ||||
| 775 | /** | |||
| 776 | * @internal | |||
| 777 | * Build the special header for PD and MD datasets (and calls the function to extract the userdata) | |||
| 778 | * | |||
| 779 | * @param tvb buffer | |||
| 780 | * @param pinfo info for tht packet | |||
| 781 | * @param tree to which the information are added | |||
| 782 | * @param trdp_comid the already extracted comId | |||
| 783 | * @param offset where the userdata starts in the TRDP package | |||
| 784 | * | |||
| 785 | * @return size of the user data | |||
| 786 | */ | |||
| 787 | static uint32_t build_trdp_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item **ti_type, uint32_t trdp_comid, char *trdp_string) { | |||
| 788 | proto_item *ti = NULL((void*)0); | |||
| 789 | proto_tree *trdp_tree = NULL((void*)0); | |||
| 790 | proto_item *_ti_type_tmp = NULL((void*)0); | |||
| 791 | proto_item **pti_type = ti_type ? ti_type : &_ti_type_tmp; | |||
| 792 | ||||
| 793 | uint32_t datasetlength = 0; | |||
| 794 | uint32_t pdu_size = 0; | |||
| 795 | ||||
| 796 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 796, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 796, __FUNCTION__); } } while (0); | |||
| 797 | ||||
| 798 | /* when the package is big enough extract some data. */ | |||
| 799 | if (tvb_reported_length_remaining(tvb, 0) > TRDP_HEADER_PD_OFFSET_RESERVED24) { | |||
| 800 | ti = proto_tree_add_item(tree, proto_trdp, tvb, 0, -1, ENC_NA0x00000000); | |||
| 801 | trdp_tree = proto_item_add_subtree(ti, ett_trdp); | |||
| 802 | ||||
| 803 | proto_tree_add_item(trdp_tree, hf_trdp_sequencecounter, tvb, TRDP_HEADER_OFFSET_SEQCNT0, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 804 | int verMain = tvb_get_uint8(tvb, TRDP_HEADER_OFFSET_PROTOVER4); | |||
| 805 | int verSub = tvb_get_uint8(tvb, (TRDP_HEADER_OFFSET_PROTOVER4 + 1)); | |||
| 806 | proto_tree_add_bytes_format_value(trdp_tree, hf_trdp_protocolversion, tvb, 4, 2, NULL((void*)0), "%d.%d", verMain, verSub); | |||
| 807 | ||||
| 808 | *pti_type = proto_tree_add_item(trdp_tree, hf_trdp_type, tvb, TRDP_HEADER_OFFSET_TYPE6, 2, ENC_ASCII0x00000000); | |||
| 809 | proto_tree_add_item(trdp_tree, hf_trdp_comid, tvb, TRDP_HEADER_OFFSET_COMID8, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 810 | proto_tree_add_item(trdp_tree, hf_trdp_etb_topocount, tvb, TRDP_HEADER_OFFSET_ETB_TOPOCNT12, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 811 | proto_tree_add_item(trdp_tree, hf_trdp_op_trn_topocount, tvb, TRDP_HEADER_OFFSET_OP_TRN_TOPOCNT16, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 812 | proto_tree_add_item(trdp_tree, hf_trdp_datasetlength, tvb, TRDP_HEADER_OFFSET_DATASETLENGTH20, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 813 | datasetlength = tvb_get_ntohl(tvb, TRDP_HEADER_OFFSET_DATASETLENGTH20); | |||
| 814 | } else { | |||
| 815 | expert_add_info_format(pinfo, tree, &ei_trdp_packet_small, "Packet too small for header information"); | |||
| 816 | } | |||
| 817 | ||||
| 818 | if (trdp_string) { | |||
| 819 | switch (trdp_string[0]) { | |||
| 820 | case 'P': | |||
| 821 | /* PD specific stuff */ | |||
| 822 | proto_tree_add_item(trdp_tree, hf_trdp_reserved, tvb, TRDP_HEADER_PD_OFFSET_RESERVED24, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 823 | proto_tree_add_item(trdp_tree, hf_trdp_reply_comid, tvb, TRDP_HEADER_PD_OFFSET_REPLY_COMID28, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 824 | proto_tree_add_item(trdp_tree, hf_trdp_reply_ipaddress, tvb, TRDP_HEADER_PD_OFFSET_REPLY_IPADDR32, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 825 | add_crc2tree(tvb, pinfo, trdp_tree, TRDP_HEADER_PD_OFFSET_FCSHEAD36, 0, TRDP_HEADER_PD_OFFSET_FCSHEAD36); | |||
| 826 | pdu_size = dissect_trdp_body(tvb, pinfo, trdp_tree, trdp_comid, TRDP_HEADER_PD_OFFSET_DATA40, datasetlength); | |||
| 827 | break; | |||
| 828 | case 'M': | |||
| 829 | /* MD specific stuff */ | |||
| 830 | proto_tree_add_item(trdp_tree, hf_trdp_replystatus, tvb, TRDP_HEADER_MD_OFFSET_REPLY_STATUS24, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 831 | proto_tree_add_item(trdp_tree, hf_trdp_sessionid, tvb, TRDP_HEADER_MD_SESSIONID028, 16, ENC_BIG_ENDIAN0x00000000); | |||
| 832 | proto_tree_add_item(trdp_tree, hf_trdp_replytimeout, tvb, TRDP_HEADER_MD_REPLY_TIMEOUT44, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 833 | proto_tree_add_item(trdp_tree, hf_trdp_sourceURI, tvb, TRDP_HEADER_MD_SRC_URI48, 32, ENC_ASCII0x00000000); | |||
| 834 | proto_tree_add_item(trdp_tree, hf_trdp_destinationURI, tvb, TRDP_HEADER_MD_DEST_URI80, 32, ENC_ASCII0x00000000); | |||
| 835 | add_crc2tree(tvb, pinfo, trdp_tree, TRDP_HEADER_MD_OFFSET_FCSHEAD112, 0, TRDP_HEADER_MD_OFFSET_FCSHEAD112); | |||
| 836 | pdu_size = dissect_trdp_body(tvb, pinfo, trdp_tree, trdp_comid, TRDP_HEADER_MD_OFFSET_DATA116, datasetlength); | |||
| 837 | break; | |||
| 838 | default: | |||
| 839 | break; | |||
| 840 | } | |||
| 841 | } | |||
| 842 | return pdu_size; | |||
| 843 | } | |||
| 844 | ||||
| 845 | int dissect_trdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused))) { | |||
| 846 | uint32_t trdp_comid = 0; | |||
| 847 | char *trdp_string = NULL((void*)0); | |||
| 848 | uint32_t parsed_size = 0U; | |||
| 849 | proto_item *ti_type = NULL((void*)0); | |||
| 850 | ||||
| 851 | /* Load header fields and dictionary if not already done */ | |||
| 852 | if (hf_trdp_type <= 0) { | |||
| 853 | proto_registrar_get_byname("trdp.type"); | |||
| 854 | } | |||
| 855 | ||||
| 856 | /* Make entries in Protocol column ... */ | |||
| 857 | if (col_get_writable(pinfo->cinfo, COL_PROTOCOL)) col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_TRDP"TRDP"); | |||
| 858 | ||||
| 859 | /* and "info" column on summary display */ | |||
| 860 | if (col_get_writable(pinfo->cinfo, COL_INFO)) col_clear(pinfo->cinfo, COL_INFO); | |||
| 861 | ||||
| 862 | /* Read required values from the package: */ | |||
| 863 | trdp_string = (char *)tvb_format_text(pinfo->pool, tvb, TRDP_HEADER_OFFSET_TYPE6, 2); | |||
| 864 | trdp_comid = tvb_get_ntohl(tvb, TRDP_HEADER_OFFSET_COMID8); | |||
| 865 | ||||
| 866 | /* Telegram that fits into one packet, or the header of huge telegram, that was reassembled */ | |||
| 867 | parsed_size = build_trdp_tree(tvb, pinfo, tree, &ti_type, trdp_comid, trdp_string); | |||
| 868 | if (tree == NULL((void*)0)) ws_debug("Dissector did not get a tree passed (type=%s, comid=%u, parsed=%u).", trdp_string, trdp_comid, parsed_size)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 868, __func__, "Dissector did not get a tree passed (type=%s, comid=%u, parsed=%u)." , trdp_string, trdp_comid, parsed_size); } } while (0); | |||
| 869 | ||||
| 870 | /* Append the packet type into the information description */ | |||
| 871 | if (col_get_writable(pinfo->cinfo, COL_INFO)) { | |||
| 872 | /* Display a info line */ | |||
| 873 | col_append_fstr(pinfo->cinfo, COL_INFO, "comId: %5u ", trdp_comid); | |||
| 874 | ||||
| 875 | /* look-up the packet-type name */ | |||
| 876 | const char **tt = trdp_types; | |||
| 877 | while (*tt && strcmp(trdp_string, *tt)) tt+=2; | |||
| 878 | col_append_str(pinfo->cinfo, COL_INFO, *(tt+1)); | |||
| 879 | if (!*tt) expert_add_info_format(pinfo, ti_type, &ei_trdp_type_unkown, "Unknown TRDP Type: %s", trdp_string); | |||
| 880 | ||||
| 881 | /* Help with high-level name of ComId / Dataset */ | |||
| 882 | const ComId *comId = TrdpDict_lookup_ComId(pTrdpParser, trdp_comid); | |||
| 883 | if (comId) { | |||
| 884 | if (comId->name && *comId->name) { | |||
| 885 | col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", comId->name); | |||
| 886 | } else if (comId->linkedDS) { | |||
| 887 | if (*comId->linkedDS->name) { | |||
| 888 | col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%s]", comId->linkedDS->name); | |||
| 889 | } else { | |||
| 890 | col_append_fstr(pinfo->cinfo, COL_INFO, " -> [%u]", comId->linkedDS->datasetId); | |||
| 891 | } | |||
| 892 | } | |||
| 893 | } else { | |||
| 894 | const char* name = TrdpDict_lookup_ComId_Name(pTrdpParser, trdp_comid); | |||
| 895 | if (name) col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", name); | |||
| 896 | } | |||
| 897 | } | |||
| 898 | ws_debug("Returning a parsed_size=%d", parsed_size)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 898, __func__, "Returning a parsed_size=%d", parsed_size); } } while (0); // tvb_captured_length(tvb) | |||
| 899 | return parsed_size; | |||
| 900 | } | |||
| 901 | ||||
| 902 | /** @fn static unsigned int get_trdp_tcp_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) | |||
| 903 | * @internal | |||
| 904 | * @brief retrieve the expected size of the transmitted packet. | |||
| 905 | */ | |||
| 906 | static unsigned int get_trdp_tcp_message_len(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused))) { | |||
| 907 | unsigned int datasetlength = (unsigned int)tvb_get_ntohl(tvb, offset + TRDP_HEADER_OFFSET_DATASETLENGTH20); | |||
| 908 | unsigned int without_padding = datasetlength + TRDP_MD_HEADERLENGTH116/* + TRDP_FCS_LENGTH*/; | |||
| 909 | ws_debug("get_trdp_tcp_message_len (datasetlength=%d w/ padding=%d tvb_reported_length=%d / captured=%d)", datasetlength, (without_padding + 3) & (~3), tvb_reported_length(tvb), tvb_captured_length(tvb))do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 909, __func__, "get_trdp_tcp_message_len (datasetlength=%d w/ padding=%d tvb_reported_length=%d / captured=%d)" , datasetlength, (without_padding + 3) & (~3), tvb_reported_length (tvb), tvb_captured_length(tvb)); } } while (0); | |||
| 910 | return (without_padding + 3) & (~3); /* round up to add padding */ | |||
| 911 | } | |||
| 912 | ||||
| 913 | /** | |||
| 914 | * @internal | |||
| 915 | * Code to analyze the actual TRDP packet, transmitted via TCP | |||
| 916 | * | |||
| 917 | * @param tvb buffer | |||
| 918 | * @param pinfo info for the packet | |||
| 919 | * @param tree to which the information are added | |||
| 920 | * @param data Collected information | |||
| 921 | * | |||
| 922 | * @return length | |||
| 923 | */ | |||
| 924 | static int dissect_trdp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { | |||
| 925 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 925, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 925, __FUNCTION__); } } while (0); | |||
| 926 | if (!tvb_bytes_exist(tvb, 0, TRDP_MD_HEADERLENGTH116)) { | |||
| 927 | ws_debug("Missing enough bytes %d/%d", tvb_captured_length(tvb), TRDP_MD_HEADERLENGTH)do { if (1) { ws_log_full("", LOG_LEVEL_DEBUG, "epan/dissectors/packet-trdp.c" , 927, __func__, "Missing enough bytes %d/%d", tvb_captured_length (tvb), 116); } } while (0); | |||
| 928 | return 0; | |||
| 929 | } | |||
| 930 | ||||
| 931 | tcp_dissect_pdus(tvb, pinfo, tree, TRUE(!(0)), TRDP_MD_HEADERLENGTH116, get_trdp_tcp_message_len, dissect_trdp, data); | |||
| 932 | ||||
| 933 | return tvb_reported_length(tvb); | |||
| 934 | } | |||
| 935 | ||||
| 936 | /* ========================================================================= */ | |||
| 937 | /* Register the protocol fields and subtrees with Wireshark | |||
| 938 | * (strongly inspired by the wimaxasncp plugin) | |||
| 939 | */ | |||
| 940 | ||||
| 941 | /* ========================================================================= */ | |||
| 942 | /* Modify the given string to make a suitable display filter */ | |||
| 943 | /* copied from wimaxasncp plugin */ | |||
| 944 | static char *alnumerize(char *name) { | |||
| 945 | char *r = name; /* read pointer */ | |||
| 946 | char *w = name; /* write pointer */ | |||
| 947 | char c; | |||
| 948 | ||||
| 949 | for (; (c = *r); ++r) { | |||
| 950 | if (g_ascii_isalnum(c)((g_ascii_table[(guchar) (c)] & G_ASCII_ALNUM) != 0) || c == '_' || c == '.') { /* These characters are fine - copy them */ | |||
| 951 | *(w++) = c; | |||
| 952 | } else if (c == ' ' || c == '-' || c == '/') { | |||
| 953 | if (w == name) continue; /* Skip these others if haven't written any characters out yet */ | |||
| 954 | if (*(w - 1) == '_') continue; /* Skip if we would produce multiple adjacent '_'s */ | |||
| 955 | ||||
| 956 | *(w++) = '_'; /* OK, replace with underscore */ | |||
| 957 | } | |||
| 958 | /* Other undesirable characters are just skipped */ | |||
| 959 | } | |||
| 960 | *w = '\0'; /* Terminate and return modified string */ | |||
| 961 | return name; | |||
| 962 | } | |||
| 963 | ||||
| 964 | /* ========================================================================= */ | |||
| 965 | ||||
| 966 | static void add_reg_info(int *hf_ptr, const char *name, const char *abbrev, enum ftenum type, int display, int bitmask, const char *blurb) { | |||
| 967 | ||||
| 968 | hf_register_info hf = {hf_ptr, {name, abbrev, type, display, NULL((void*)0), bitmask, blurb, HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}; | |||
| 969 | ||||
| 970 | wmem_array_append_one(trdp_build_dict.hf, hf)wmem_array_append((trdp_build_dict.hf), &(hf), 1); | |||
| 971 | } | |||
| 972 | ||||
| 973 | /* ========================================================================= */ | |||
| 974 | ||||
| 975 | static void add_element_reg_info(const char *parentName, Element *el) { | |||
| 976 | char *name; | |||
| 977 | char *abbrev; | |||
| 978 | const char *blurb; | |||
| 979 | int *pett_id = &el->ett_id; | |||
| 980 | ||||
| 981 | name = g_strdup(el->name)g_strdup_inline (el->name); | |||
| 982 | abbrev = alnumerize(g_strdup_printf(PROTO_FILTERNAME_TRDP_PDU"trdp" ".pdu" ".%s.%s", parentName, el->name)); | |||
| 983 | ||||
| 984 | if (el->scale || el->offset) { | |||
| 985 | blurb = g_strdup_printf("An element of type=%s(%u) scaling *%4g plus offset %+0d in unit %s", | |||
| 986 | el->type.name, el->type.id, el->scale ? el->scale : 1.0, el->offset, el->unit); | |||
| 987 | } else { | |||
| 988 | blurb = g_strdup_printf("An element of type=%s(%u) with unit %s", | |||
| 989 | el->type.name, el->type.id, el->unit); | |||
| 990 | } | |||
| 991 | ||||
| 992 | if (!((el->array_size == 1) || (el->type.id == TRDP_CHAR82) || (el->type.id == TRDP_UTF163))) { | |||
| 993 | wmem_array_append_one(trdp_build_dict.ett, pett_id)wmem_array_append((trdp_build_dict.ett), &(pett_id), 1); | |||
| 994 | } | |||
| 995 | ||||
| 996 | switch (el->type.id) { | |||
| 997 | case TRDP_BITSET81: | |||
| 998 | if (el->type.subtype == TRDP_BITSUBTYPE_BITSET80) { | |||
| 999 | /* TODO an Array of bitsets is currently not supported */ | |||
| 1000 | if (el->bits /*&& el->array_size == 1*/) { | |||
| 1001 | int **bitfields = el->bitfields; | |||
| 1002 | int *pb_ett_id = &el->bits_ett_id; | |||
| 1003 | wmem_array_append_one(trdp_build_dict.ett, pb_ett_id)wmem_array_append((trdp_build_dict.ett), &(pb_ett_id), 1); | |||
| 1004 | for (int i=0;i<TRDP_BITSUBTYPE_BITS8;i++) { | |||
| 1005 | if (*el->bits[i].name) { | |||
| 1006 | char* abbrev2 = alnumerize(g_strdup_printf(PROTO_FILTERNAME_TRDP_PDU"trdp" ".pdu" ".%s.%s.%s", parentName, el->name, el->bits[i].name)); | |||
| 1007 | add_reg_info( &el->bits[i].hf_id, el->bits[i].name, abbrev2, FT_BOOLEAN, 8, 1<<i, NULL((void*)0)); | |||
| 1008 | *bitfields = &el->bits[i].hf_id; | |||
| 1009 | bitfields++; | |||
| 1010 | } | |||
| 1011 | } | |||
| 1012 | } | |||
| 1013 | add_reg_info(&el->hf_id, name, abbrev, FT_UINT8, BASE_HEX, 0, NULL((void*)0)); | |||
| 1014 | } else { | |||
| 1015 | add_reg_info(&el->hf_id, name, abbrev, FT_BOOLEAN, 8, 0, blurb); | |||
| 1016 | } | |||
| 1017 | break; | |||
| 1018 | case TRDP_CHAR82: | |||
| 1019 | case TRDP_UTF163: | |||
| 1020 | add_reg_info(&el->hf_id, name, abbrev, el->array_size ? FT_STRING : FT_STRINGZ, BASE_NONE, 0, blurb); | |||
| 1021 | break; | |||
| 1022 | ||||
| 1023 | /* case TRDP_INT8 ... TRDP_INT64: not supported in MSVC :( */ | |||
| 1024 | case TRDP_INT84: | |||
| 1025 | case TRDP_INT165: | |||
| 1026 | case TRDP_INT326: | |||
| 1027 | case TRDP_INT647: | |||
| 1028 | if (el->scale && g_scaled) { | |||
| 1029 | add_reg_info(&el->hf_id, name, abbrev, FT_DOUBLE, BASE_NONE, 0, blurb); | |||
| 1030 | } else | |||
| 1031 | add_reg_info(&el->hf_id, name, abbrev, FT_INT64, BASE_DEC, 0, blurb); | |||
| 1032 | break; | |||
| 1033 | ||||
| 1034 | /* case TRDP_UINT8 ... TRDP_UINT64: */ | |||
| 1035 | case TRDP_UINT88: | |||
| 1036 | case TRDP_UINT169: | |||
| 1037 | case TRDP_UINT3210: | |||
| 1038 | case TRDP_UINT6411: | |||
| 1039 | if (g_ascii_strcasecmp(el->unit, "version") == 0) { | |||
| 1040 | add_reg_info(&el->hf_id, name, abbrev, FT_UINT16, BASE_HEX, 0, blurb); | |||
| 1041 | } else if (el->scale && g_scaled) { | |||
| 1042 | add_reg_info(&el->hf_id, name, abbrev, FT_DOUBLE, BASE_NONE, 0, blurb); | |||
| 1043 | } else | |||
| 1044 | add_reg_info(&el->hf_id, name, abbrev, FT_UINT64, BASE_DEC, 0, blurb); | |||
| 1045 | break; | |||
| 1046 | ||||
| 1047 | case TRDP_REAL3212: | |||
| 1048 | case TRDP_REAL6413: | |||
| 1049 | add_reg_info(&el->hf_id, name, abbrev, FT_DOUBLE, BASE_NONE, 0, blurb); | |||
| 1050 | break; | |||
| 1051 | ||||
| 1052 | /* case TRDP_TIMEDATE32 ... TRDP_TIMEDATE64:*/ | |||
| 1053 | case TRDP_TIMEDATE3214: | |||
| 1054 | case TRDP_TIMEDATE4815: | |||
| 1055 | case TRDP_TIMEDATE6416: | |||
| 1056 | /* add_reg_info( &el->hf_id, name, abbrev, FT_DOUBLE, BASE_NONE, 0, blurb );*/ | |||
| 1057 | add_reg_info(&el->hf_id, name, abbrev, g_time_raw ? FT_RELATIVE_TIME : FT_ABSOLUTE_TIME, | |||
| 1058 | g_time_raw ? 0 : (g_time_local ? ABSOLUTE_TIME_LOCAL : ABSOLUTE_TIME_UTC), 0, blurb); | |||
| 1059 | break; | |||
| 1060 | ||||
| 1061 | case TRDP_SC3217: | |||
| 1062 | add_reg_info(&el->hf_id, name, abbrev, FT_UINT32, BASE_HEX, 0, blurb); | |||
| 1063 | break; | |||
| 1064 | ||||
| 1065 | case TRDP_UUID18: | |||
| 1066 | add_reg_info(&el->hf_id, name, abbrev, FT_GUID, BASE_NONE, 0, blurb); | |||
| 1067 | break; | |||
| 1068 | ||||
| 1069 | default: | |||
| 1070 | add_reg_info(&el->hf_id, name, abbrev, FT_BYTES, BASE_NONE, 0, blurb); | |||
| 1071 | ||||
| 1072 | /* as long as I do not track the hierarchy, do not recurse */ | |||
| 1073 | /* add_dataset_reg_info(el->linkedDS); */ | |||
| 1074 | } | |||
| 1075 | } | |||
| 1076 | ||||
| 1077 | static void add_dataset_reg_info(Dataset *ds) { | |||
| 1078 | int *pett_id = &ds->ett_id; | |||
| 1079 | ||||
| 1080 | for (Element *el = ds->listOfElements; el; el = el->next) add_element_reg_info(ds->name, el); | |||
| 1081 | ||||
| 1082 | if (ds->listOfElements) wmem_array_append_one(trdp_build_dict.ett, pett_id)wmem_array_append((trdp_build_dict.ett), &(pett_id), 1); | |||
| 1083 | } | |||
| 1084 | ||||
| 1085 | static void register_trdp_fields(const char *prefix _U___attribute__((unused))) { | |||
| 1086 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 1086, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 1086, __FUNCTION__); } } while (0); | |||
| 1087 | ||||
| 1088 | /* List of header fields. */ | |||
| 1089 | static hf_register_info hf_base[] = { | |||
| 1090 | /* All the general fields for the header */ | |||
| 1091 | // clang-format off | |||
| 1092 | {&hf_trdp_sequencecounter, {"sequenceCounter", "trdp.sequencecounter", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1093 | {&hf_trdp_protocolversion, {"protocolVersion", "trdp.protocolversion", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1094 | {&hf_trdp_type, {"msgtype", "trdp.type", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1095 | {&hf_trdp_comid, {"comId", "trdp.comid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1096 | {&hf_trdp_etb_topocount, {"etbTopoCnt", "trdp.etbtopocnt", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1097 | {&hf_trdp_op_trn_topocount,{"opTrnTopoCnt", "trdp.optrntopocnt", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1098 | {&hf_trdp_datasetlength, {"datasetLength", "trdp.datasetlength", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1099 | {&hf_trdp_padding, {"padding", "trdp.padding", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1100 | ||||
| 1101 | /* PD specific stuff */ | |||
| 1102 | {&hf_trdp_reserved, {"reserved", "trdp.reserved", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1103 | {&hf_trdp_reply_comid, {"replyComId", "trdp.replycomid", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, /* only in PD request */ | |||
| 1104 | {&hf_trdp_reply_ipaddress, {"replyIpAddress", "trdp.replyip", FT_IPv4, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1105 | ||||
| 1106 | /* MD specific stuff */ | |||
| 1107 | {&hf_trdp_replystatus, {"replyStatus", "trdp.replystatus", FT_INT32, BASE_DEC, VALS(reply_status_names)((0 ? (const struct _value_string*)0 : ((reply_status_names)) )), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1108 | {&hf_trdp_sessionid, {"sessionUUID", "trdp.sessionid", FT_GUID, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1109 | {&hf_trdp_replytimeout, {"replyTimeout", "trdp.replytimeout", FT_UINT32, BASE_DEC, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1110 | {&hf_trdp_sourceURI, {"sourceUri", "trdp.sourceUri", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1111 | {&hf_trdp_destinationURI, {"destinationURI", "trdp.destinationUri", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1112 | {&hf_trdp_userdata, {"dataset", "trdp.rawdata", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1113 | ||||
| 1114 | /* The checksum for the header (the trdp.fcsheadcalc is only set, if the | |||
| 1115 | calculated FCS differs) */ | |||
| 1116 | {&hf_trdp_fcs_head, {"headerFcs", "trdp.fcshead", FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1117 | {&hf_trdp_fcs_head_calc, {"calculatedHeaderFcs", "trdp.fcsheadcalc", FT_UINT32, BASE_HEX, NULL((void*)0), 0x0, "", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0)}}, | |||
| 1118 | ||||
| 1119 | // clang-format on | |||
| 1120 | }; | |||
| 1121 | ||||
| 1122 | /* Setup protocol subtree array */ | |||
| 1123 | static int *ett_base[] = { | |||
| 1124 | &ett_trdp, | |||
| 1125 | }; | |||
| 1126 | ||||
| 1127 | /* ------------------------------------------------------------------------ | |||
| 1128 | * load the XML dictionary | |||
| 1129 | * ------------------------------------------------------------------------ | |||
| 1130 | */ | |||
| 1131 | ||||
| 1132 | if (pTrdpParser != NULL((void*)0)) { | |||
| 1133 | /* currently the GUI callbacks are w/o effect, so always clear the filter expression */ | |||
| 1134 | // plugin_if_apply_filter("" /* empty filter */, TRUE /* apply immediately */); | |||
| 1135 | TrdpDict_delete(pTrdpParser, proto_trdp); | |||
| 1136 | proto_free_deregistered_fields(); | |||
| 1137 | } | |||
| 1138 | ||||
| 1139 | ws_info("TRDP custom dictionary is '%s' (proto=%d).", g_customTrdpDictionary, proto_trdp)do { if (1) { ws_log_full("", LOG_LEVEL_INFO, ((void*)0), -1, ((void*)0), "TRDP custom dictionary is '%s' (proto=%d).", g_customTrdpDictionary , proto_trdp); } } while (0); | |||
| 1140 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 1140, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 1140, __FUNCTION__); } } while (0); | |||
| 1141 | ||||
| 1142 | GError *err = NULL((void*)0); | |||
| 1143 | char *basepath = g_basexml ? get_datafile_path("trdp", epan_get_environment_prefix()) : NULL((void*)0); | |||
| 1144 | pTrdpParser = TrdpDict_new(basepath, g_customTrdpDictionary, g_bitset_subtype, g_endian_subtype, &err); | |||
| 1145 | ||||
| 1146 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 1146, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 1146, __FUNCTION__); } } while (0); | |||
| 1147 | if (err) { | |||
| 1148 | report_failure("TRDP | XML input failed [%d]:\n%s", err->code, err->message); | |||
| 1149 | g_error_free(err); | |||
| 1150 | } | |||
| 1151 | ||||
| 1152 | g_free(basepath); | |||
| 1153 | ||||
| 1154 | /* ------------------------------------------------------------------------ | |||
| 1155 | * build the hf and ett dictionary entries | |||
| 1156 | * ------------------------------------------------------------------------ | |||
| 1157 | */ | |||
| 1158 | ||||
| 1159 | if (trdp_build_dict.hf) wmem_free(wmem_epan_scope(), trdp_build_dict.hf); | |||
| 1160 | ||||
| 1161 | if (trdp_build_dict.ett) wmem_free(wmem_epan_scope(), trdp_build_dict.ett); | |||
| 1162 | ||||
| 1163 | trdp_build_dict.hf = wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info)); | |||
| 1164 | trdp_build_dict.ett = wmem_array_new(wmem_epan_scope(), sizeof(int *)); | |||
| 1165 | ||||
| 1166 | if (hf_trdp_type <= 0) { | |||
| 1167 | proto_register_field_array(proto_trdp, hf_base, array_length(hf_base)(sizeof (hf_base) / sizeof (hf_base)[0])); | |||
| 1168 | proto_register_subtree_array(ett_base, array_length(ett_base)(sizeof (ett_base) / sizeof (ett_base)[0])); | |||
| 1169 | } | |||
| 1170 | ||||
| 1171 | if (pTrdpParser) { | |||
| 1172 | /* arrays use the same hf */ | |||
| 1173 | /* don't care about comID linkage, as I really want to index all datasets, | |||
| 1174 | * regardless of their hierarchy */ | |||
| 1175 | for (Dataset *ds = pTrdpParser->mTableDataset; ds; ds = ds->next) add_dataset_reg_info(ds); | |||
| 1176 | } | |||
| 1177 | ||||
| 1178 | /* Required function calls to register the header fields and subtrees used */ | |||
| 1179 | ||||
| 1180 | proto_register_field_array(proto_trdp, (hf_register_info *)wmem_array_get_raw(trdp_build_dict.hf), wmem_array_get_count(trdp_build_dict.hf)); | |||
| 1181 | ||||
| 1182 | proto_register_subtree_array((int **)wmem_array_get_raw(trdp_build_dict.ett), wmem_array_get_count(trdp_build_dict.ett)); | |||
| 1183 | } | |||
| 1184 | ||||
| 1185 | void proto_reg_handoff_trdp(void) { | |||
| 1186 | static bool_Bool initialized = FALSE(0); | |||
| 1187 | static unsigned int pd_port=0; | |||
| 1188 | static unsigned int md_port=0; | |||
| 1189 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 1189, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 1189, __FUNCTION__); } } while (0); | |||
| 1190 | ||||
| 1191 | if (initialized == FALSE(0)) { | |||
| 1192 | initialized = TRUE(!(0)); | |||
| 1193 | } else { | |||
| 1194 | if (pd_port != g_pd_port) { | |||
| 1195 | dissector_delete_uint("udp.port", pd_port, trdp_handle); | |||
| 1196 | } | |||
| 1197 | if (md_port != g_md_port) { | |||
| 1198 | dissector_delete_uint("udp.port", md_port, trdp_handle); | |||
| 1199 | dissector_delete_uint("tcp.port", md_port, trdp_TCP_handle); | |||
| 1200 | } | |||
| 1201 | } | |||
| 1202 | if (pd_port != g_pd_port) { | |||
| 1203 | pd_port = g_pd_port; | |||
| 1204 | dissector_add_uint_with_preference("udp.port", pd_port, trdp_handle); | |||
| 1205 | } | |||
| 1206 | if (md_port != g_md_port) { | |||
| 1207 | md_port = g_md_port; | |||
| 1208 | dissector_add_uint_with_preference("udp.port", md_port, trdp_handle); | |||
| 1209 | dissector_add_uint_with_preference("tcp.port", md_port, trdp_TCP_handle); | |||
| 1210 | } | |||
| 1211 | ||||
| 1212 | /* Reload header fields and dictionary but only, if it's been in use before */ | |||
| 1213 | if (hf_trdp_type > 0) register_trdp_fields(NULL((void*)0)); | |||
| 1214 | } | |||
| 1215 | ||||
| 1216 | void proto_register_trdp(void) { | |||
| 1217 | module_t *trdp_module; | |||
| 1218 | ||||
| 1219 | enum_val_t *bitsetenumvals; | |||
| 1220 | gsize bitset_offset = 0; | |||
| 1221 | gsize bitset_types = 0; | |||
| 1222 | ||||
| 1223 | while (ElBasics[bitset_offset].id != TRDP_BITSET81) bitset_offset++; | |||
| ||||
| 1224 | while (ElBasics[bitset_offset+bitset_types].id == TRDP_BITSET81) bitset_types++; | |||
| 1225 | ||||
| 1226 | bitsetenumvals = g_new0(enum_val_t, bitset_types + 1)((enum_val_t *) g_malloc0_n ((bitset_types + 1), sizeof (enum_val_t ))); | |||
| 1227 | for (gsize i = 0; i < bitset_types; i++) { | |||
| 1228 | bitsetenumvals[i].description = ElBasics[i].name; | |||
| 1229 | bitsetenumvals[i].name = g_ascii_strdown(ElBasics[i].name, -1); | |||
| 1230 | bitsetenumvals[i].value = (int)ElBasics[i].subtype; | |||
| 1231 | } | |||
| 1232 | ||||
| 1233 | enum_val_t *endianenumvals = g_new0(enum_val_t, 2 + 1)((enum_val_t *) g_malloc0_n ((2 + 1), sizeof (enum_val_t))); | |||
| 1234 | endianenumvals[0].description = "BE"; | |||
| 1235 | endianenumvals[0].name = "be"; | |||
| 1236 | endianenumvals[0].value = TRDP_ENDSUBTYPE_BIG0; | |||
| 1237 | endianenumvals[1].description = "LE (non-standard)"; | |||
| 1238 | endianenumvals[1].name = "le"; | |||
| 1239 | endianenumvals[1].value = TRDP_ENDSUBTYPE_LIT1; | |||
| 1240 | ||||
| 1241 | API_TRACEdo { if (1) { ws_log_full("", LOG_LEVEL_NOISY, "epan/dissectors/packet-trdp.c" , 1241, __func__, "%s:%d : %s\n", "epan/dissectors/packet-trdp.c" , 1241, __FUNCTION__); } } while (0); | |||
| 1242 | ||||
| 1243 | /* Register the protocol name and description */ | |||
| 1244 | proto_trdp = proto_register_protocol(PROTO_NAME_TRDP"Train Real Time Data Protocol", PROTO_TAG_TRDP"TRDP", PROTO_FILTERNAME_TRDP"trdp"); | |||
| 1245 | trdp_handle = register_dissector(PROTO_DISSECTORNAME_TRDP"TRDP", (dissector_t)dissect_trdp, proto_trdp); | |||
| 1246 | trdp_TCP_handle = register_dissector(PROTO_DISSECTORNAME_TRDPTCP"TRDP.tcp", (dissector_t)dissect_trdp_tcp, proto_trdp); | |||
| 1247 | /* Delay registration of com-id and dataset-id definitions */ | |||
| 1248 | proto_register_prefix("trdp", register_trdp_fields); | |||
| 1249 | ||||
| 1250 | trdp_module = prefs_register_protocol(proto_trdp, proto_reg_handoff_trdp); | |||
| 1251 | ||||
| 1252 | /* Register the preference */ | |||
| 1253 | prefs_register_static_text_preference( trdp_module, "dissector_summary", | |||
| 1254 | "Version 20251123", | |||
| 1255 | NULL((void*)0)); | |||
| 1256 | ||||
| 1257 | prefs_register_bool_preference( trdp_module, "basexml", | |||
| 1258 | "Load basic set of comIDs and dataset definitions", | |||
| 1259 | "When ticked, basic definitions of 61375-2-3 are loaded. If that conflicts with your use or your definitions " | |||
| 1260 | "- untick. If there's a bug or data missing, please file an issue.", | |||
| 1261 | &g_basexml); | |||
| 1262 | ||||
| 1263 | prefs_register_filename_preference( trdp_module, "configfile", | |||
| 1264 | "Custom TRDP configuration file", | |||
| 1265 | "Custom TRDP configuration file", | |||
| 1266 | &g_customTrdpDictionary, FALSE(0)); | |||
| 1267 | ||||
| 1268 | prefs_set_preference_effect_fields(trdp_module, "configfile"); | |||
| 1269 | ||||
| 1270 | prefs_register_static_text_preference( trdp_module, "xml_summary", | |||
| 1271 | "If you need to include multiple files, chose a file, then manually remove the filename part above only leaving the folder path. You cannot choose a " | |||
| 1272 | "folder by itself in the dialog. Be sure, not to have conflicting versions of datasets or com-ids in that target folder - the file parser will be pesky.", | |||
| 1273 | NULL((void*)0)); | |||
| 1274 | ||||
| 1275 | prefs_register_enum_preference( trdp_module, "bitset.subtype", | |||
| 1276 | "Select default sub-type for TRDP-Element type 1", | |||
| 1277 | "Type 1 can be interpreted differently, as BOOL, ANTIVALENT or BITSET. Select the fallback, if the element type is not given literally.", | |||
| 1278 | &g_bitset_subtype, bitsetenumvals, FALSE(0)); | |||
| 1279 | ||||
| 1280 | prefs_set_preference_effect_fields( trdp_module, "bitset.subtype"); | |||
| ||||
| 1281 | ||||
| 1282 | prefs_register_enum_preference( trdp_module, "numeric.subtype", | |||
| 1283 | "Select default byte-order for TRDP-Element types (5-7,9-13)", | |||
| 1284 | "Number types can be interpreted differently, as BE or LE (non-standard). Select the fallback, if the element type is not given literally.", | |||
| 1285 | &g_endian_subtype, endianenumvals, FALSE(0)); | |||
| 1286 | ||||
| 1287 | prefs_set_preference_effect_fields( trdp_module, "numeric.subtype"); | |||
| 1288 | ||||
| 1289 | prefs_register_bool_preference( trdp_module, "time.local", | |||
| 1290 | "Display time-types as local time, untick for UTC / no offsets.", | |||
| 1291 | "Time types should be based on UTC. When ticked, Wireshark adds on local timezone offset. Untick if you like UTC to be displayed, or the source is not UTC.", | |||
| 1292 | &g_time_local); | |||
| 1293 | ||||
| 1294 | prefs_register_bool_preference( trdp_module, "time.raw", | |||
| 1295 | "Display time-types as raw seconds, not absolute time.", | |||
| 1296 | "Time types should be absolute time since the UNIX-Epoch. When ticked, they are shown as seconds.", | |||
| 1297 | &g_time_raw); | |||
| 1298 | ||||
| 1299 | prefs_register_bool_preference( trdp_module, "0strings", | |||
| 1300 | "Variable-length CHAR8 and UTF16 arrays are 0-terminated. (non-standard)", | |||
| 1301 | "When ticked, the length of a variable-length string (array-size=0) is calculated from searching for a terminator instead of using a previous length element.", | |||
| 1302 | &g_0strings); | |||
| 1303 | ||||
| 1304 | prefs_register_bool_preference( trdp_module, "char8utf8", | |||
| 1305 | "Interpret CHAR8 arrays as UTF-8.", | |||
| 1306 | "When ticked, CHAR8 arrays are interpreted as UTF-8 string. If it fails, an exception is thrown. Untick if you need to see weird ASCII as C-escapes.", | |||
| 1307 | &g_char8_is_utf8); | |||
| 1308 | ||||
| 1309 | prefs_register_bool_preference( trdp_module, "strings.le", | |||
| 1310 | "Interpret UTF-16 strings with Little-Endian wire format. (non-standard)", | |||
| 1311 | "When ticked, UTF16 arrays are interpreted as Little-Endian encoding.", | |||
| 1312 | &g_strings_are_LE); | |||
| 1313 | ||||
| 1314 | prefs_register_bool_preference( trdp_module, "scaled", | |||
| 1315 | "Use scaled value for filter.", | |||
| 1316 | "When ticked, uses scaled values for filtering and display, otherwise the raw value.", | |||
| 1317 | &g_scaled); | |||
| 1318 | ||||
| 1319 | prefs_register_uint_preference( trdp_module, "pd.udp.port", | |||
| 1320 | "PD message Port", | |||
| 1321 | "UDP port for PD messages (Default port is " TRDP_DEFAULT_STR_PD_PORT"17224" ")", | |||
| 1322 | 10 /*base */, &g_pd_port); | |||
| 1323 | ||||
| 1324 | prefs_register_uint_preference( trdp_module, "md.udptcp.port", | |||
| 1325 | "MD message Port", | |||
| 1326 | "UDP and TCP port for MD messages (Default port is " TRDP_DEFAULT_STR_MD_PORT"17225" ")", | |||
| 1327 | 10 /*base */, &g_md_port); | |||
| 1328 | ||||
| 1329 | prefs_register_uint_preference( trdp_module, "sdtv2.sid", | |||
| 1330 | "SDTv2 SID (SC-32 Initial Value)", | |||
| 1331 | "SDTv2 SID (Initial Value) for SC-32 calculation (Default is " TRDP_DEFAULT_STR_SC32_SID"0xFFFFFFFF" ")", | |||
| 1332 | 16 /*base */, &g_sid); | |||
| 1333 | ||||
| 1334 | /* abandon legacy prefs */ | |||
| 1335 | prefs_register_obsolete_preference( trdp_module, "udp.port"); | |||
| 1336 | prefs_register_obsolete_preference( trdp_module, "tcp.port"); | |||
| 1337 | ||||
| 1338 | /* Register expert information */ | |||
| 1339 | expert_module_t *expert_trdp; | |||
| 1340 | static ei_register_info ei[] = { | |||
| 1341 | {&ei_trdp_type_unkown, {"trdp.type_unkown", PI_UNDECODED0x05000000, PI_WARN0x00600000, "TRDP type unkown", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1342 | {&ei_trdp_packet_small, {"trdp.packet_size", PI_UNDECODED0x05000000, PI_WARN0x00600000, "TRDP packet too small", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1343 | {&ei_trdp_userdata_empty, {"trdp.userdata_empty", PI_UNDECODED0x05000000, PI_WARN0x00600000, "TRDP user data is empty", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1344 | {&ei_trdp_userdata_wrong, {"trdp.userdata_wrong", PI_UNDECODED0x05000000, PI_WARN0x00600000, "TRDP user data has wrong format", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1345 | {&ei_trdp_config_notparsed, {"trdp.config_unparsable", PI_UNDECODED0x05000000, PI_WARN0x00600000, "TRDP XML configuration cannot be parsed", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1346 | {&ei_trdp_padding_not_zero, {"trdp.padding_non_zero", PI_MALFORMED0x07000000, PI_WARN0x00600000, "TRDP Padding not filled with zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1347 | {&ei_trdp_array_wrong, {"trdp.array", PI_MALFORMED0x07000000, PI_WARN0x00600000, "Dynamic array has unsupported datatype for length", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1348 | {&ei_trdp_faulty_antivalent,{"trdp.faulty_antivalent", PI_MALFORMED0x07000000, PI_WARN0x00600000, "Data contains faulty antivalent value.", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1349 | {&ei_trdp_reserved_not_zero,{"trdp.reserved_non_zero", PI_MALFORMED0x07000000, PI_WARN0x00600000, "Reserved attribute is not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1350 | {&ei_trdp_sdtv2_safetycode, {"trdp.sdtv2_safetycode", PI_CHECKSUM0x01000000, PI_ERROR0x00800000, "SDTv2 SafetyCode check error.", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE , BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE , -1, ((void*)0)}}}}, | |||
| 1351 | }; | |||
| 1352 | ||||
| 1353 | expert_trdp = expert_register_protocol(proto_trdp); | |||
| 1354 | expert_register_field_array(expert_trdp, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0])); | |||
| 1355 | } |