| File: | builds/wireshark/wireshark/epan/dissectors/packet-mqtt.c |
| Warning: | line 1227, column 29 Access to field 'topic' results in a dereference of a null pointer (loaded from variable 'pdu_data') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* packet-mqtt.c | |||
| 2 | * Routines for MQTT Protocol dissection | |||
| 3 | * | |||
| 4 | * MQTT v5.0 support sponsored by 1byt3 <customers at 1byt3.com> | |||
| 5 | * | |||
| 6 | * By Lakshmi Narayana Madala <[email protected]> | |||
| 7 | * Stig Bjorlykke <[email protected]> | |||
| 8 | * | |||
| 9 | * Wireshark - Network traffic analyzer | |||
| 10 | * By Gerald Combs <[email protected]> | |||
| 11 | * Copyright 1998 Gerald Combs | |||
| 12 | * | |||
| 13 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
| 14 | */ | |||
| 15 | ||||
| 16 | /* | |||
| 17 | * Protocol description: | |||
| 18 | * | |||
| 19 | * MQTT is a Client Server publish/subscribe messaging transport | |||
| 20 | * protocol. The protocol runs over TCP/IP, or over other network | |||
| 21 | * protocols that provide ordered, lossless, bi-directional | |||
| 22 | * connections. | |||
| 23 | * | |||
| 24 | * MQTT v3.1 specification: | |||
| 25 | * http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html | |||
| 26 | * | |||
| 27 | * MQTT v3.1.1 specification: | |||
| 28 | * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/ | |||
| 29 | * | |||
| 30 | * MQTT v5.0 specification: | |||
| 31 | * http://docs.oasis-open.org/mqtt/mqtt/v5.0/ | |||
| 32 | * | |||
| 33 | */ | |||
| 34 | ||||
| 35 | #include "config.h" | |||
| 36 | #include <epan/expert.h> | |||
| 37 | #include <epan/packet.h> | |||
| 38 | #include <epan/proto_data.h> | |||
| 39 | #include <epan/tfs.h> | |||
| 40 | #include <wsutil/array.h> | |||
| 41 | #include <epan/uat.h> | |||
| 42 | #include "packet-tcp.h" | |||
| 43 | #include "packet-tls.h" | |||
| 44 | ||||
| 45 | #define MQTT_DEFAULT_PORT1883 1883 /* IANA registered under service name as mqtt */ | |||
| 46 | #define MQTT_SSL_DEFAULT_PORT8883 8883 /* IANA registered under service name secure-mqtt */ | |||
| 47 | ||||
| 48 | /* MQTT Protocol Versions */ | |||
| 49 | #define MQTT_PROTO_V313 3 | |||
| 50 | #define MQTT_PROTO_V3114 4 | |||
| 51 | #define MQTT_PROTO_V505 5 | |||
| 52 | ||||
| 53 | #define MQTT_HDR_SIZE_BEFORE_LEN1 1 | |||
| 54 | ||||
| 55 | /* MQTT Message Types */ | |||
| 56 | #define MQTT_RESERVED0 0 | |||
| 57 | #define MQTT_CONNECT1 1 | |||
| 58 | #define MQTT_CONNACK2 2 | |||
| 59 | #define MQTT_PUBLISH3 3 | |||
| 60 | #define MQTT_PUBACK4 4 | |||
| 61 | #define MQTT_PUBREC5 5 | |||
| 62 | #define MQTT_PUBREL6 6 | |||
| 63 | #define MQTT_PUBCOMP7 7 | |||
| 64 | #define MQTT_SUBSCRIBE8 8 | |||
| 65 | #define MQTT_SUBACK9 9 | |||
| 66 | #define MQTT_UNSUBSCRIBE10 10 | |||
| 67 | #define MQTT_UNSUBACK11 11 | |||
| 68 | #define MQTT_PINGREQ12 12 | |||
| 69 | #define MQTT_PINGRESP13 13 | |||
| 70 | #define MQTT_DISCONNECT14 14 | |||
| 71 | #define MQTT_AUTH15 15 | |||
| 72 | #define MQTT_RESERVED_1616 16 | |||
| 73 | ||||
| 74 | /* Flag Values to extract fields */ | |||
| 75 | #define MQTT_MASK_MSG_TYPE0xF0 0xF0 | |||
| 76 | #define MQTT_MASK_HDR_RESERVED0x0F 0x0F | |||
| 77 | #define MQTT_MASK_HDR_DUP_RESERVED0x07 0x07 | |||
| 78 | #define MQTT_MASK_QOS0x06 0x06 | |||
| 79 | #define MQTT_MASK_DUP_FLAG0x08 0x08 | |||
| 80 | #define MQTT_MASK_RETAIN0x01 0x01 | |||
| 81 | ||||
| 82 | /* MQTT v5.0 Flag Values for the Subscription Options @ Subscribe Packet */ | |||
| 83 | #define MQTT_MASK_SUBS_QOS0x03 0x03 | |||
| 84 | #define MQTT_MASK_SUBS_NL0x04 0x04 | |||
| 85 | #define MQTT_MASK_SUBS_RAP0x08 0x08 | |||
| 86 | #define MQTT_MASK_SUBS_RETAIN0x30 0x30 | |||
| 87 | #define MQTT_MASK_SUBS_RESERVED0xC0 0xC0 | |||
| 88 | ||||
| 89 | void proto_register_mqtt(void); | |||
| 90 | void proto_reg_handoff_mqtt(void); | |||
| 91 | ||||
| 92 | static dissector_table_t media_type_dissector_table; | |||
| 93 | ||||
| 94 | static const value_string mqtt_protocol_version_vals[] = { | |||
| 95 | { MQTT_PROTO_V313, "MQTT v3.1" }, | |||
| 96 | { MQTT_PROTO_V3114, "MQTT v3.1.1" }, | |||
| 97 | { MQTT_PROTO_V505, "MQTT v5.0" }, | |||
| 98 | { 0, NULL((void*)0) } | |||
| 99 | }; | |||
| 100 | ||||
| 101 | static const enum_val_t mqtt_protocol_version_enumvals[] = { | |||
| 102 | { "none", "None", 0 }, | |||
| 103 | { "v31", "MQTT v3.1", MQTT_PROTO_V313 }, | |||
| 104 | { "v311", "MQTT v3.1.1", MQTT_PROTO_V3114 }, | |||
| 105 | { "v50", "MQTT v5.0", MQTT_PROTO_V505 }, | |||
| 106 | { NULL((void*)0), NULL((void*)0), 0 } | |||
| 107 | }; | |||
| 108 | ||||
| 109 | static const value_string mqtt_msgtype_vals[] = { | |||
| 110 | { MQTT_RESERVED0, "Reserved" }, | |||
| 111 | { MQTT_CONNECT1, "Connect Command" }, | |||
| 112 | { MQTT_CONNACK2, "Connect Ack" }, | |||
| 113 | { MQTT_PUBLISH3, "Publish Message" }, | |||
| 114 | { MQTT_PUBACK4, "Publish Ack" }, | |||
| 115 | { MQTT_PUBREC5, "Publish Received" }, | |||
| 116 | { MQTT_PUBREL6, "Publish Release" }, | |||
| 117 | { MQTT_PUBCOMP7, "Publish Complete" }, | |||
| 118 | { MQTT_SUBSCRIBE8, "Subscribe Request" }, | |||
| 119 | { MQTT_SUBACK9, "Subscribe Ack" }, | |||
| 120 | { MQTT_UNSUBSCRIBE10, "Unsubscribe Request" }, | |||
| 121 | { MQTT_UNSUBACK11, "Unsubscribe Ack" }, | |||
| 122 | { MQTT_PINGREQ12, "Ping Request" }, | |||
| 123 | { MQTT_PINGRESP13, "Ping Response" }, | |||
| 124 | { MQTT_DISCONNECT14, "Disconnect Req" }, | |||
| 125 | { MQTT_AUTH15, "Authentication Exchange" }, | |||
| 126 | { MQTT_RESERVED_1616, "Reserved" }, | |||
| 127 | { 0, NULL((void*)0) } | |||
| 128 | }; | |||
| 129 | static value_string_ext mqtt_msgtype_vals_ext = VALUE_STRING_EXT_INIT(mqtt_msgtype_vals){ _try_val_to_str_ext_init, 0, (sizeof (mqtt_msgtype_vals) / sizeof ((mqtt_msgtype_vals)[0]))-1, mqtt_msgtype_vals, "mqtt_msgtype_vals" , ((void*)0) }; | |||
| 130 | ||||
| 131 | #define MQTT_QOS_ATMOST_ONCE0 0 | |||
| 132 | #define MQTT_QOS_ATLEAST_ONCE1 1 | |||
| 133 | #define MQTT_QOS_EXACTLY_ONCE2 2 | |||
| 134 | #define MQTT_QOS_RESERVED3 3 | |||
| 135 | ||||
| 136 | static const value_string mqtt_qos_vals[] = { | |||
| 137 | { MQTT_QOS_ATMOST_ONCE0, "At most once delivery (Fire and Forget)" }, | |||
| 138 | { MQTT_QOS_ATLEAST_ONCE1, "At least once delivery (Acknowledged deliver)" }, | |||
| 139 | { MQTT_QOS_EXACTLY_ONCE2, "Exactly once delivery (Assured Delivery)" }, | |||
| 140 | { MQTT_QOS_RESERVED3, "Reserved" }, | |||
| 141 | { 0, NULL((void*)0) } | |||
| 142 | }; | |||
| 143 | ||||
| 144 | #define MQTT_SUBACK_FAILURE128 128 | |||
| 145 | ||||
| 146 | static const value_string mqtt_subqos_vals[] = { | |||
| 147 | { MQTT_QOS_ATMOST_ONCE0, "At most once delivery (Fire and Forget)" }, | |||
| 148 | { MQTT_QOS_ATLEAST_ONCE1, "At least once delivery (Acknowledged deliver)" }, | |||
| 149 | { MQTT_QOS_EXACTLY_ONCE2, "Exactly once delivery (Assured Delivery)" }, | |||
| 150 | { MQTT_QOS_RESERVED3, "Reserved" }, | |||
| 151 | { MQTT_SUBACK_FAILURE128, "Failure" }, | |||
| 152 | { 0, NULL((void*)0) } | |||
| 153 | }; | |||
| 154 | ||||
| 155 | #define MQTT_CON_ACCEPTED0 0 | |||
| 156 | #define MQTT_CON_REFUSED_VERSION_MISMATCH1 1 | |||
| 157 | #define MQTT_CON_REFUSED_ID_REJECTED2 2 | |||
| 158 | #define MQTT_CON_REFUSED_SERVER_UNAVAILABLE3 3 | |||
| 159 | #define MQTT_CON_REFUSED_BAD_USER_PASSWD4 4 | |||
| 160 | #define MQTT_CON_REFUSED_UNAUTHORIZED5 5 | |||
| 161 | ||||
| 162 | static const value_string mqtt_conack_vals[] = { | |||
| 163 | { MQTT_CON_ACCEPTED0, "Connection Accepted" }, | |||
| 164 | { MQTT_CON_REFUSED_VERSION_MISMATCH1, "Connection Refused: unacceptable protocol version" }, | |||
| 165 | { MQTT_CON_REFUSED_ID_REJECTED2, "Connection Refused: identifier rejected" }, | |||
| 166 | { MQTT_CON_REFUSED_SERVER_UNAVAILABLE3, "Connection Refused: server unavailable" }, | |||
| 167 | { MQTT_CON_REFUSED_BAD_USER_PASSWD4, "Connection Refused: bad user name or password" }, | |||
| 168 | { MQTT_CON_REFUSED_UNAUTHORIZED5, "Connection Refused: not authorized" }, | |||
| 169 | { 0, NULL((void*)0) } | |||
| 170 | }; | |||
| 171 | ||||
| 172 | #define MQTT_CONMASK_USER0x80 0x80 | |||
| 173 | #define MQTT_CONMASK_PASSWD0x40 0x40 | |||
| 174 | #define MQTT_CONMASK_RETAIN0x20 0x20 | |||
| 175 | #define MQTT_CONMASK_QOS0x18 0x18 | |||
| 176 | #define MQTT_CONMASK_WILLFLAG0x04 0x04 | |||
| 177 | #define MQTT_CONMASK_CLEANSESS0x02 0x02 | |||
| 178 | #define MQTT_CONMASK_RESERVED0x01 0x01 | |||
| 179 | ||||
| 180 | #define MQTT_CONACKMASK_RESERVED0xFE 0xFE | |||
| 181 | #define MQTT_CONACKMASK_SP0x01 0x01 | |||
| 182 | ||||
| 183 | /* The protocol version is present in the CONNECT message. */ | |||
| 184 | typedef struct { | |||
| 185 | uint8_t runtime_proto_version; | |||
| 186 | wmem_map_t *topic_alias_map; | |||
| 187 | } mqtt_conv_t; | |||
| 188 | ||||
| 189 | typedef struct _mqtt_message_decode_t { | |||
| 190 | unsigned match_criteria; | |||
| 191 | char *topic_pattern; | |||
| 192 | GRegex *topic_regex; | |||
| 193 | unsigned msg_decoding; | |||
| 194 | char *payload_proto_name; | |||
| 195 | dissector_handle_t payload_proto; | |||
| 196 | } mqtt_message_decode_t; | |||
| 197 | ||||
| 198 | typedef struct _mqtt_properties_t { | |||
| 199 | const char *content_type; | |||
| 200 | uint32_t topic_alias; | |||
| 201 | } mqtt_properties_t; | |||
| 202 | ||||
| 203 | #define MATCH_CRITERIA_EQUAL0 0 | |||
| 204 | #define MATCH_CRITERIA_CONTAINS1 1 | |||
| 205 | #define MATCH_CRITERIA_STARTS_WITH2 2 | |||
| 206 | #define MATCH_CRITERIA_ENDS_WITH3 3 | |||
| 207 | #define MATCH_CRITERIA_REGEX4 4 | |||
| 208 | ||||
| 209 | static const value_string match_criteria[] = { | |||
| 210 | { MATCH_CRITERIA_EQUAL0, "Equal to" }, | |||
| 211 | { MATCH_CRITERIA_CONTAINS1, "Contains" }, | |||
| 212 | { MATCH_CRITERIA_STARTS_WITH2, "Starts with" }, | |||
| 213 | { MATCH_CRITERIA_ENDS_WITH3, "Ends with" }, | |||
| 214 | { MATCH_CRITERIA_REGEX4, "Regular Expression" }, | |||
| 215 | { 0, NULL((void*)0) } | |||
| 216 | }; | |||
| 217 | ||||
| 218 | #define MSG_DECODING_NONE0 0 | |||
| 219 | #define MSG_DECODING_COMPRESSED1 1 | |||
| 220 | ||||
| 221 | static const value_string msg_decoding[] = { | |||
| 222 | { MSG_DECODING_NONE0, "none" }, | |||
| 223 | { MSG_DECODING_COMPRESSED1, "compressed" }, | |||
| 224 | { 0, NULL((void*)0) } | |||
| 225 | }; | |||
| 226 | ||||
| 227 | #define PROP_PAYLOAD_FORMAT_INDICATOR0x01 0x01 | |||
| 228 | #define PROP_PUBLICATION_EXPIRY_INTERVAL0x02 0x02 | |||
| 229 | #define PROP_CONTENT_TYPE0x03 0x03 | |||
| 230 | #define PROP_RESPONSE_TOPIC0x08 0x08 | |||
| 231 | #define PROP_CORRELATION_DATA0x09 0x09 | |||
| 232 | #define PROP_SUBSCRIPTION_IDENTIFIER0x0B 0x0B | |||
| 233 | #define PROP_SESSION_EXPIRY_INTERVAL0x11 0x11 | |||
| 234 | #define PROP_ASSIGNED_CLIENT_IDENTIFIER0x12 0x12 | |||
| 235 | #define PROP_SERVER_KEEP_ALIVE0x13 0x13 | |||
| 236 | #define PROP_AUTH_METHOD0x15 0x15 | |||
| 237 | #define PROP_AUTH_DATA0x16 0x16 | |||
| 238 | #define PROP_REQUEST_PROBLEM_INFORMATION0x17 0x17 | |||
| 239 | #define PROP_WILL_DELAY_INTERVAL0x18 0x18 | |||
| 240 | #define PROP_REQUEST_RESPONSE_INFORMATION0x19 0x19 | |||
| 241 | #define PROP_RESPONSE_INFORMATION0x1A 0x1A | |||
| 242 | #define PROP_SERVER_REFERENCE0x1C 0x1C | |||
| 243 | #define PROP_REASON_STRING0x1F 0x1F | |||
| 244 | #define PROP_RECEIVE_MAXIMUM0x21 0x21 | |||
| 245 | #define PROP_TOPIC_ALIAS_MAXIMUM0x22 0x22 | |||
| 246 | #define PROP_TOPIC_ALIAS0x23 0x23 | |||
| 247 | #define PROP_MAXIMUM_QOS0x24 0x24 | |||
| 248 | #define PROP_RETAIN_AVAILABLE0x25 0x25 | |||
| 249 | #define PROP_USER_PROPERTY0x26 0x26 | |||
| 250 | #define PROP_MAXIMUM_PACKET_SIZE0x27 0x27 | |||
| 251 | #define PROP_WILDCARD_SUBSCRIPTION_AVAILABLE0x28 0x28 | |||
| 252 | #define PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE0x29 0x29 | |||
| 253 | #define PROP_SHARED_SUBSCRIPTION_AVAILABLE0x2A 0x2A | |||
| 254 | ||||
| 255 | static const value_string mqtt_property_vals[] = { | |||
| 256 | { PROP_PAYLOAD_FORMAT_INDICATOR0x01, "Payload Format Indicator" }, | |||
| 257 | { PROP_PUBLICATION_EXPIRY_INTERVAL0x02, "Publication Expiry Interval" }, | |||
| 258 | { PROP_CONTENT_TYPE0x03, "Content Type" }, | |||
| 259 | { PROP_RESPONSE_TOPIC0x08, "Response Topic" }, | |||
| 260 | { PROP_CORRELATION_DATA0x09, "Correlation Data" }, | |||
| 261 | { PROP_SUBSCRIPTION_IDENTIFIER0x0B, "Subscription Identifier" }, | |||
| 262 | { PROP_SESSION_EXPIRY_INTERVAL0x11, "Session Expiry Interval" }, | |||
| 263 | { PROP_ASSIGNED_CLIENT_IDENTIFIER0x12, "Assigned Client Identifier" }, | |||
| 264 | { PROP_SERVER_KEEP_ALIVE0x13, "Server Keep Alive" }, | |||
| 265 | { PROP_AUTH_METHOD0x15, "Authentication Method" }, | |||
| 266 | { PROP_AUTH_DATA0x16, "Authentication Data" }, | |||
| 267 | { PROP_REQUEST_PROBLEM_INFORMATION0x17, "Request Problem Information" }, | |||
| 268 | { PROP_WILL_DELAY_INTERVAL0x18, "Will Delay Interval" }, | |||
| 269 | { PROP_REQUEST_RESPONSE_INFORMATION0x19, "Request Response Information" }, | |||
| 270 | { PROP_RESPONSE_INFORMATION0x1A, "Response Information" }, | |||
| 271 | { PROP_SERVER_REFERENCE0x1C, "Server Reference" }, | |||
| 272 | { PROP_REASON_STRING0x1F, "Reason String" }, | |||
| 273 | { PROP_RECEIVE_MAXIMUM0x21, "Receive Maximum" }, | |||
| 274 | { PROP_TOPIC_ALIAS_MAXIMUM0x22, "Topic Alias Maximum" }, | |||
| 275 | { PROP_TOPIC_ALIAS0x23, "Topic Alias" }, | |||
| 276 | { PROP_MAXIMUM_QOS0x24, "Maximum QoS" }, | |||
| 277 | { PROP_RETAIN_AVAILABLE0x25, "Retain Available" }, | |||
| 278 | { PROP_USER_PROPERTY0x26, "User Property" }, | |||
| 279 | { PROP_MAXIMUM_PACKET_SIZE0x27, "Maximum Packet Size" }, | |||
| 280 | { PROP_WILDCARD_SUBSCRIPTION_AVAILABLE0x28, "Wildcard Subscription Available" }, | |||
| 281 | { PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE0x29, "Subscription Identifier Available" }, | |||
| 282 | { PROP_SHARED_SUBSCRIPTION_AVAILABLE0x2A, "Shared Subscription Available" }, | |||
| 283 | { 0, NULL((void*)0) } | |||
| 284 | }; | |||
| 285 | ||||
| 286 | /* MQTT v5.0 Subscription Options, Retain Handling option */ | |||
| 287 | #define SUBSCRIPTION_RETAIN_SEND0x00 0x00 | |||
| 288 | #define SUBSCRIPTION_RETAIN_SEND_DONT_EXIST0x01 0x01 | |||
| 289 | #define SUBSCRIPTION_RETAIN_DONT_SEND0x02 0x02 | |||
| 290 | #define SUBSCRIPTION_RETAIN_RESERVED0x03 0x03 | |||
| 291 | ||||
| 292 | static const value_string mqtt_subscription_retain_handling[] = { | |||
| 293 | { SUBSCRIPTION_RETAIN_SEND0x00, "Send msgs at subscription time" }, | |||
| 294 | { SUBSCRIPTION_RETAIN_SEND_DONT_EXIST0x01, "Send msgs if subscription does not exist" }, | |||
| 295 | { SUBSCRIPTION_RETAIN_DONT_SEND0x02, "Do not send msgs at subscription time" }, | |||
| 296 | { SUBSCRIPTION_RETAIN_RESERVED0x03, "Reserved" }, | |||
| 297 | { 0, NULL((void*)0) } | |||
| 298 | }; | |||
| 299 | ||||
| 300 | /* MQTT v5.0 Reason Codes */ | |||
| 301 | #define RC_SUCCESS0x00 0x00 | |||
| 302 | #define RC_NORMAL_DISCONNECTION0x00 0x00 | |||
| 303 | #define RC_GRANTED_QOS00x00 0x00 | |||
| 304 | #define RC_GRANTED_QOS10x01 0x01 | |||
| 305 | #define RC_GRANTED_QOS20x02 0x02 | |||
| 306 | #define RC_DISCONNECT_WILL0x04 0x04 | |||
| 307 | #define RC_NO_MATCHING_SUBSCRIBERS0x10 0x10 | |||
| 308 | #define RC_NO_SUBSCRIPTION_EXISTED0x11 0x11 | |||
| 309 | #define RC_CONTINUE_AUTHENTICATION0x18 0x18 | |||
| 310 | #define RC_RE_AUTHENTICATE0x19 0x19 | |||
| 311 | #define RC_UNSPECIFIED_ERROR0x80 0x80 | |||
| 312 | #define RC_MALFORMED_PACKET0x81 0x81 | |||
| 313 | #define RC_PROTOCOL_ERROR0x82 0x82 | |||
| 314 | #define RC_IMPLEMENTATION_SPECIFIC_ERROR0x83 0x83 | |||
| 315 | #define RC_UNSUPPORTED_PROTOCOL_VERSION0x84 0x84 | |||
| 316 | #define RC_CLIENT_IDENTIFIER_NOT_VALID0x85 0x85 | |||
| 317 | #define RC_BAD_USER_NAME_OR_PASSWORD0x86 0x86 | |||
| 318 | #define RC_NOT_AUTHORIZED0x87 0x87 | |||
| 319 | #define RC_SERVER_UNAVAILABLE0x88 0x88 | |||
| 320 | #define RC_SERVER_BUSY0x89 0x89 | |||
| 321 | #define RC_BANNED0x8A 0x8A | |||
| 322 | #define RC_SERVER_SHUTTING_DOWN0x8B 0x8B | |||
| 323 | #define RC_BAD_AUTHENTICATION_METHOD0x8C 0x8C | |||
| 324 | #define RC_KEEP_ALIVE_TIMEOUT0x8D 0x8D | |||
| 325 | #define RC_SESSION_TAKEN_OVER0x8E 0x8E | |||
| 326 | #define RC_TOPIC_FILTER_INVALID0x8F 0x8F | |||
| 327 | #define RC_TOPIC_NAME_INVALID0x90 0x90 | |||
| 328 | #define RC_PACKET_IDENTIFIER_IN_USE0x91 0x91 | |||
| 329 | #define RC_PACKET_IDENTIFIER_NOT_FOUND0x92 0x92 | |||
| 330 | #define RC_RECEIVE_MAXIMUM_EXCEEDED0x93 0x93 | |||
| 331 | #define RC_TOPIC_ALIAS_INVALID0x94 0x94 | |||
| 332 | #define RC_PACKET_TOO_LARGE0x95 0x95 | |||
| 333 | #define RC_MESSAGE_RATE_TOO_HIGH0x96 0x96 | |||
| 334 | #define RC_QUOTA_EXCEEDED0x97 0x97 | |||
| 335 | #define RC_ADMINISTRATIVE_ACTION0x98 0x98 | |||
| 336 | #define RC_PAYLOAD_FORMAT_INVALID0x99 0x99 | |||
| 337 | #define RC_RETAIN_NOT_SUPPORTED0x9A 0x9A | |||
| 338 | #define RC_QOS_NOT_SUPPORTED0x9B 0x9B | |||
| 339 | #define RC_USE_ANOTHER_SERVER0x9C 0x9C | |||
| 340 | #define RC_SERVER_MOVED0x9D 0x9D | |||
| 341 | #define RC_SHARED_SUBSCRIPTION_NOT_SUPPORTED0x9E 0x9E | |||
| 342 | #define RC_CONNECTION_RATE_EXCEEDED0x9F 0x9F | |||
| 343 | #define RC_MAXIMUM_CONNECT_TIME0xA0 0xA0 | |||
| 344 | #define RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED0xA1 0xA1 | |||
| 345 | #define RC_WILDCARD_SUBSCRIPTION_NOT_SUPPORTED0xA2 0xA2 | |||
| 346 | ||||
| 347 | #define RC_SUCCESS_STR"Success" "Success" | |||
| 348 | #define RC_NORMAL_DISCONNECTION_STR"Normal disconnection" "Normal disconnection" | |||
| 349 | #define RC_GRANTED_QOS0_STR"Granted QoS 0" "Granted QoS 0" | |||
| 350 | #define RC_GRANTED_QOS1_STR"Granted QoS 1" "Granted QoS 1" | |||
| 351 | #define RC_GRANTED_QOS2_STR"Granted QoS 2" "Granted QoS 2" | |||
| 352 | #define RC_DISCONNECT_WILL_STR"Disconnect with Will Message" "Disconnect with Will Message" | |||
| 353 | #define RC_NO_MATCHING_SUBSCRIBERS_STR"No matching subscribers" "No matching subscribers" | |||
| 354 | #define RC_NO_SUBSCRIPTION_EXISTED_STR"No subscription existed" "No subscription existed" | |||
| 355 | #define RC_CONTINUE_AUTHENTICATION_STR"Continue authentication" "Continue authentication" | |||
| 356 | #define RC_RE_AUTHENTICATE_STR"Re-authenticate" "Re-authenticate" | |||
| 357 | #define RC_UNSPECIFIED_ERROR_STR"Unspecified error" "Unspecified error" | |||
| 358 | #define RC_MALFORMED_PACKET_STR"Malformed Packet" "Malformed Packet" | |||
| 359 | #define RC_PROTOCOL_ERROR_STR"Protocol Error" "Protocol Error" | |||
| 360 | #define RC_IMPLEMENTATION_SPECIFIC_ERROR_STR"Implementation specific error" "Implementation specific error" | |||
| 361 | #define RC_UNSUPPORTED_PROTOCOL_VERSION_STR"Unsupported Protocol Version" "Unsupported Protocol Version" | |||
| 362 | #define RC_CLIENT_IDENTIFIER_NOT_VALID_STR"Client Identifier not valid" "Client Identifier not valid" | |||
| 363 | #define RC_BAD_USER_NAME_OR_PASSWORD_STR"Bad User Name or Password" "Bad User Name or Password" | |||
| 364 | #define RC_NOT_AUTHORIZED_STR"Not authorized" "Not authorized" | |||
| 365 | #define RC_SERVER_UNAVAILABLE_STR"Server unavailable" "Server unavailable" | |||
| 366 | #define RC_SERVER_BUSY_STR"Server busy" "Server busy" | |||
| 367 | #define RC_BANNED_STR"Banned" "Banned" | |||
| 368 | #define RC_SERVER_SHUTTING_DOWN_STR"Server shutting down" "Server shutting down" | |||
| 369 | #define RC_BAD_AUTHENTICATION_METHOD_STR"Bad authentication method" "Bad authentication method" | |||
| 370 | #define RC_KEEP_ALIVE_TIMEOUT_STR"Keep Alive timeout" "Keep Alive timeout" | |||
| 371 | #define RC_SESSION_TAKEN_OVER_STR"Session taken over" "Session taken over" | |||
| 372 | #define RC_TOPIC_FILTER_INVALID_STR"Topic Filter invalid" "Topic Filter invalid" | |||
| 373 | #define RC_TOPIC_NAME_INVALID_STR"Topic Name invalid" "Topic Name invalid" | |||
| 374 | #define RC_PACKET_IDENTIFIER_IN_USE_STR"Packet Identifier in use" "Packet Identifier in use" | |||
| 375 | #define RC_PACKET_IDENTIFIER_NOT_FOUND_STR"Packet Identifier not found" "Packet Identifier not found" | |||
| 376 | #define RC_RECEIVE_MAXIMUM_EXCEEDED_STR"Receive Maximum exceeded" "Receive Maximum exceeded" | |||
| 377 | #define RC_TOPIC_ALIAS_INVALID_STR"Topic Alias invalid" "Topic Alias invalid" | |||
| 378 | #define RC_PACKET_TOO_LARGE_STR"Packet too large" "Packet too large" | |||
| 379 | #define RC_MESSAGE_RATE_TOO_HIGH_STR"Message rate too high" "Message rate too high" | |||
| 380 | #define RC_QUOTA_EXCEEDED_STR"Quota exceeded" "Quota exceeded" | |||
| 381 | #define RC_ADMINISTRATIVE_ACTION_STR"Administrative action" "Administrative action" | |||
| 382 | #define RC_PAYLOAD_FORMAT_INVALID_STR"Payload format invalid" "Payload format invalid" | |||
| 383 | #define RC_RETAIN_NOT_SUPPORTED_STR"Retain not supported" "Retain not supported" | |||
| 384 | #define RC_QOS_NOT_SUPPORTED_STR"QoS not supported" "QoS not supported" | |||
| 385 | #define RC_USE_ANOTHER_SERVER_STR"Use another server" "Use another server" | |||
| 386 | #define RC_SERVER_MOVED_STR"Server moved" "Server moved" | |||
| 387 | #define RC_SHARED_SUBSCRIPTION_NOT_SUPPORTED_STR"Shared Subscription not supported" "Shared Subscription not supported" | |||
| 388 | #define RC_CONNECTION_RATE_EXCEEDED_STR"Connection rate exceeded" "Connection rate exceeded" | |||
| 389 | #define RC_MAXIMUM_CONNECT_TIME_STR"Maximum connect time" "Maximum connect time" | |||
| 390 | #define RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED_STR"Subscription Identifiers not supported" "Subscription Identifiers not supported" | |||
| 391 | #define RC_WILDCARD_SUBSCRIPTION_NOT_SUPPORTED_STR"Wildcard Subscription not supported" "Wildcard Subscription not supported" | |||
| 392 | ||||
| 393 | static const value_string mqtt_reason_code_connack_vals[] = { | |||
| 394 | { RC_SUCCESS0x00, RC_SUCCESS_STR"Success" }, | |||
| 395 | { RC_UNSPECIFIED_ERROR0x80, RC_UNSPECIFIED_ERROR_STR"Unspecified error" }, | |||
| 396 | { RC_MALFORMED_PACKET0x81, RC_MALFORMED_PACKET_STR"Malformed Packet" }, | |||
| 397 | { RC_PROTOCOL_ERROR0x82, RC_PROTOCOL_ERROR_STR"Protocol Error" }, | |||
| 398 | { RC_IMPLEMENTATION_SPECIFIC_ERROR0x83, RC_IMPLEMENTATION_SPECIFIC_ERROR_STR"Implementation specific error" }, | |||
| 399 | { RC_UNSUPPORTED_PROTOCOL_VERSION0x84, RC_UNSUPPORTED_PROTOCOL_VERSION_STR"Unsupported Protocol Version" }, | |||
| 400 | { RC_CLIENT_IDENTIFIER_NOT_VALID0x85, RC_CLIENT_IDENTIFIER_NOT_VALID_STR"Client Identifier not valid" }, | |||
| 401 | { RC_BAD_USER_NAME_OR_PASSWORD0x86, RC_BAD_USER_NAME_OR_PASSWORD_STR"Bad User Name or Password" }, | |||
| 402 | { RC_NOT_AUTHORIZED0x87, RC_NOT_AUTHORIZED_STR"Not authorized" }, | |||
| 403 | { RC_SERVER_UNAVAILABLE0x88, RC_SERVER_UNAVAILABLE_STR"Server unavailable" }, | |||
| 404 | { RC_SERVER_BUSY0x89, RC_SERVER_BUSY_STR"Server busy" }, | |||
| 405 | { RC_BANNED0x8A, RC_BANNED_STR"Banned" }, | |||
| 406 | { RC_BAD_AUTHENTICATION_METHOD0x8C, RC_BAD_AUTHENTICATION_METHOD_STR"Bad authentication method" }, | |||
| 407 | { RC_TOPIC_NAME_INVALID0x90, RC_TOPIC_NAME_INVALID_STR"Topic Name invalid" }, | |||
| 408 | { RC_PACKET_TOO_LARGE0x95, RC_PACKET_TOO_LARGE_STR"Packet too large" }, | |||
| 409 | { RC_QUOTA_EXCEEDED0x97, RC_QUOTA_EXCEEDED_STR"Quota exceeded" }, | |||
| 410 | { RC_RETAIN_NOT_SUPPORTED0x9A, RC_RETAIN_NOT_SUPPORTED_STR"Retain not supported" }, | |||
| 411 | { RC_QOS_NOT_SUPPORTED0x9B, RC_QOS_NOT_SUPPORTED_STR"QoS not supported" }, | |||
| 412 | { RC_USE_ANOTHER_SERVER0x9C, RC_USE_ANOTHER_SERVER_STR"Use another server" }, | |||
| 413 | { RC_SERVER_MOVED0x9D, RC_SERVER_MOVED_STR"Server moved" }, | |||
| 414 | { RC_CONNECTION_RATE_EXCEEDED0x9F, RC_CONNECTION_RATE_EXCEEDED_STR"Connection rate exceeded" }, | |||
| 415 | { 0, NULL((void*)0) } | |||
| 416 | }; | |||
| 417 | ||||
| 418 | static const value_string mqtt_reason_code_puback_vals[] = { | |||
| 419 | { RC_SUCCESS0x00, RC_SUCCESS_STR"Success" }, | |||
| 420 | { RC_NO_MATCHING_SUBSCRIBERS0x10, RC_NO_MATCHING_SUBSCRIBERS_STR"No matching subscribers" }, | |||
| 421 | { RC_UNSPECIFIED_ERROR0x80, RC_UNSPECIFIED_ERROR_STR"Unspecified error" }, | |||
| 422 | { RC_IMPLEMENTATION_SPECIFIC_ERROR0x83, RC_IMPLEMENTATION_SPECIFIC_ERROR_STR"Implementation specific error" }, | |||
| 423 | { RC_NOT_AUTHORIZED0x87, RC_NOT_AUTHORIZED_STR"Not authorized" }, | |||
| 424 | { RC_TOPIC_NAME_INVALID0x90, RC_TOPIC_NAME_INVALID_STR"Topic Name invalid" }, | |||
| 425 | { RC_PACKET_IDENTIFIER_IN_USE0x91, RC_PACKET_IDENTIFIER_IN_USE_STR"Packet Identifier in use" }, | |||
| 426 | { RC_QUOTA_EXCEEDED0x97, RC_QUOTA_EXCEEDED_STR"Quota exceeded" }, | |||
| 427 | { RC_PAYLOAD_FORMAT_INVALID0x99, RC_PAYLOAD_FORMAT_INVALID_STR"Payload format invalid" }, | |||
| 428 | { 0, NULL((void*)0) } | |||
| 429 | }; | |||
| 430 | ||||
| 431 | static const value_string mqtt_reason_code_pubrel_vals[] = { | |||
| 432 | { RC_SUCCESS0x00, RC_SUCCESS_STR"Success" }, | |||
| 433 | { RC_PACKET_IDENTIFIER_NOT_FOUND0x92, RC_PACKET_IDENTIFIER_NOT_FOUND_STR"Packet Identifier not found" }, | |||
| 434 | { 0, NULL((void*)0) } | |||
| 435 | }; | |||
| 436 | ||||
| 437 | static const value_string mqtt_reason_code_suback_vals[] = { | |||
| 438 | { RC_GRANTED_QOS00x00, RC_GRANTED_QOS0_STR"Granted QoS 0" }, | |||
| 439 | { RC_GRANTED_QOS10x01, RC_GRANTED_QOS1_STR"Granted QoS 1" }, | |||
| 440 | { RC_GRANTED_QOS20x02, RC_GRANTED_QOS2_STR"Granted QoS 2" }, | |||
| 441 | { RC_UNSPECIFIED_ERROR0x80, RC_UNSPECIFIED_ERROR_STR"Unspecified error" }, | |||
| 442 | { RC_IMPLEMENTATION_SPECIFIC_ERROR0x83, RC_IMPLEMENTATION_SPECIFIC_ERROR_STR"Implementation specific error" }, | |||
| 443 | { RC_NOT_AUTHORIZED0x87, RC_NOT_AUTHORIZED_STR"Not authorized" }, | |||
| 444 | { RC_TOPIC_FILTER_INVALID0x8F, RC_TOPIC_FILTER_INVALID_STR"Topic Filter invalid" }, | |||
| 445 | { RC_PACKET_IDENTIFIER_IN_USE0x91, RC_PACKET_IDENTIFIER_IN_USE_STR"Packet Identifier in use" }, | |||
| 446 | { RC_QUOTA_EXCEEDED0x97, RC_QUOTA_EXCEEDED_STR"Quota exceeded" }, | |||
| 447 | { RC_SHARED_SUBSCRIPTION_NOT_SUPPORTED0x9E, RC_SHARED_SUBSCRIPTION_NOT_SUPPORTED_STR"Shared Subscription not supported" }, | |||
| 448 | { RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED0xA1, RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED_STR"Subscription Identifiers not supported" }, | |||
| 449 | { RC_WILDCARD_SUBSCRIPTION_NOT_SUPPORTED0xA2, RC_WILDCARD_SUBSCRIPTION_NOT_SUPPORTED_STR"Wildcard Subscription not supported" }, | |||
| 450 | { 0, NULL((void*)0) } | |||
| 451 | }; | |||
| 452 | ||||
| 453 | static const value_string mqtt_reason_code_unsuback_vals[] = { | |||
| 454 | { RC_SUCCESS0x00, RC_SUCCESS_STR"Success" }, | |||
| 455 | { RC_NO_SUBSCRIPTION_EXISTED0x11, RC_NO_SUBSCRIPTION_EXISTED_STR"No subscription existed" }, | |||
| 456 | { RC_IMPLEMENTATION_SPECIFIC_ERROR0x83, RC_IMPLEMENTATION_SPECIFIC_ERROR_STR"Implementation specific error" }, | |||
| 457 | { RC_NOT_AUTHORIZED0x87, RC_NOT_AUTHORIZED_STR"Not authorized" }, | |||
| 458 | { RC_TOPIC_FILTER_INVALID0x8F, RC_TOPIC_FILTER_INVALID_STR"Topic Filter invalid" }, | |||
| 459 | { RC_PACKET_IDENTIFIER_IN_USE0x91, RC_PACKET_IDENTIFIER_IN_USE_STR"Packet Identifier in use" }, | |||
| 460 | { 0, NULL((void*)0) } | |||
| 461 | }; | |||
| 462 | ||||
| 463 | static const value_string mqtt_reason_code_disconnect_vals[] = { | |||
| 464 | { RC_NORMAL_DISCONNECTION0x00, RC_NORMAL_DISCONNECTION_STR"Normal disconnection" }, | |||
| 465 | { RC_DISCONNECT_WILL0x04, RC_DISCONNECT_WILL_STR"Disconnect with Will Message" }, | |||
| 466 | { RC_UNSPECIFIED_ERROR0x80, RC_UNSPECIFIED_ERROR_STR"Unspecified error" }, | |||
| 467 | { RC_MALFORMED_PACKET0x81, RC_MALFORMED_PACKET_STR"Malformed Packet" }, | |||
| 468 | { RC_PROTOCOL_ERROR0x82, RC_PROTOCOL_ERROR_STR"Protocol Error" }, | |||
| 469 | { RC_IMPLEMENTATION_SPECIFIC_ERROR0x83, RC_IMPLEMENTATION_SPECIFIC_ERROR_STR"Implementation specific error" }, | |||
| 470 | { RC_NOT_AUTHORIZED0x87, RC_NOT_AUTHORIZED_STR"Not authorized" }, | |||
| 471 | { RC_SERVER_BUSY0x89, RC_SERVER_BUSY_STR"Server busy" }, | |||
| 472 | { RC_SERVER_SHUTTING_DOWN0x8B, RC_SERVER_SHUTTING_DOWN_STR"Server shutting down" }, | |||
| 473 | /* Bad authentication method: check Table 2.6 and Table 3.13 */ | |||
| 474 | { RC_BAD_AUTHENTICATION_METHOD0x8C, RC_BAD_AUTHENTICATION_METHOD_STR"Bad authentication method" }, | |||
| 475 | { RC_KEEP_ALIVE_TIMEOUT0x8D, RC_KEEP_ALIVE_TIMEOUT_STR"Keep Alive timeout" }, | |||
| 476 | { RC_SESSION_TAKEN_OVER0x8E, RC_SESSION_TAKEN_OVER_STR"Session taken over" }, | |||
| 477 | { RC_TOPIC_FILTER_INVALID0x8F, RC_TOPIC_FILTER_INVALID_STR"Topic Filter invalid" }, | |||
| 478 | { RC_TOPIC_NAME_INVALID0x90, RC_TOPIC_NAME_INVALID_STR"Topic Name invalid" }, | |||
| 479 | { RC_RECEIVE_MAXIMUM_EXCEEDED0x93, RC_RECEIVE_MAXIMUM_EXCEEDED_STR"Receive Maximum exceeded" }, | |||
| 480 | { RC_TOPIC_ALIAS_INVALID0x94, RC_TOPIC_ALIAS_INVALID_STR"Topic Alias invalid" }, | |||
| 481 | { RC_PACKET_TOO_LARGE0x95, RC_PACKET_TOO_LARGE_STR"Packet too large" }, | |||
| 482 | { RC_MESSAGE_RATE_TOO_HIGH0x96, RC_MESSAGE_RATE_TOO_HIGH_STR"Message rate too high" }, | |||
| 483 | { RC_QUOTA_EXCEEDED0x97, RC_QUOTA_EXCEEDED_STR"Quota exceeded" }, | |||
| 484 | { RC_ADMINISTRATIVE_ACTION0x98, RC_ADMINISTRATIVE_ACTION_STR"Administrative action" }, | |||
| 485 | { RC_PAYLOAD_FORMAT_INVALID0x99, RC_PAYLOAD_FORMAT_INVALID_STR"Payload format invalid" }, | |||
| 486 | { RC_RETAIN_NOT_SUPPORTED0x9A, RC_RETAIN_NOT_SUPPORTED_STR"Retain not supported" }, | |||
| 487 | { RC_QOS_NOT_SUPPORTED0x9B, RC_QOS_NOT_SUPPORTED_STR"QoS not supported" }, | |||
| 488 | { RC_USE_ANOTHER_SERVER0x9C, RC_USE_ANOTHER_SERVER_STR"Use another server" }, | |||
| 489 | { RC_SERVER_MOVED0x9D, RC_SERVER_MOVED_STR"Server moved" }, | |||
| 490 | { RC_SHARED_SUBSCRIPTION_NOT_SUPPORTED0x9E, RC_SHARED_SUBSCRIPTION_NOT_SUPPORTED_STR"Shared Subscription not supported" }, | |||
| 491 | { RC_CONNECTION_RATE_EXCEEDED0x9F, RC_CONNECTION_RATE_EXCEEDED_STR"Connection rate exceeded" }, | |||
| 492 | { RC_MAXIMUM_CONNECT_TIME0xA0, RC_MAXIMUM_CONNECT_TIME_STR"Maximum connect time" }, | |||
| 493 | { RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED0xA1, RC_SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED_STR"Subscription Identifiers not supported" }, | |||
| 494 | { RC_WILDCARD_SUBSCRIPTION_NOT_SUPPORTED0xA2, RC_WILDCARD_SUBSCRIPTION_NOT_SUPPORTED_STR"Wildcard Subscription not supported" }, | |||
| 495 | { 0, NULL((void*)0) } | |||
| 496 | }; | |||
| 497 | ||||
| 498 | static const value_string mqtt_reason_code_auth_vals[] = { | |||
| 499 | { RC_SUCCESS0x00, RC_SUCCESS_STR"Success" }, | |||
| 500 | { RC_CONTINUE_AUTHENTICATION0x18, RC_CONTINUE_AUTHENTICATION_STR"Continue authentication" }, | |||
| 501 | { RC_RE_AUTHENTICATE0x19, RC_RE_AUTHENTICATE_STR"Re-authenticate" }, | |||
| 502 | { 0, NULL((void*)0) } | |||
| 503 | }; | |||
| 504 | ||||
| 505 | static mqtt_message_decode_t *mqtt_message_decodes; | |||
| 506 | static unsigned num_mqtt_message_decodes; | |||
| 507 | static int default_protocol_version; | |||
| 508 | ||||
| 509 | static dissector_handle_t mqtt_handle; | |||
| 510 | ||||
| 511 | static heur_dissector_list_t mqtt_topic_subdissector; | |||
| 512 | ||||
| 513 | /* Initialize the protocol and registered fields */ | |||
| 514 | typedef struct { | |||
| 515 | uint8_t version; | |||
| 516 | char *topic; | |||
| 517 | } mqtt_pdu_data_t; | |||
| 518 | ||||
| 519 | static int proto_mqtt; | |||
| 520 | ||||
| 521 | /* Message */ | |||
| 522 | static int hf_mqtt_hdrflags; | |||
| 523 | static int hf_mqtt_msg_len; | |||
| 524 | static int hf_mqtt_msg_type; | |||
| 525 | static int hf_mqtt_reserved; | |||
| 526 | static int hf_mqtt_dup_flag; | |||
| 527 | static int hf_mqtt_qos_level; | |||
| 528 | static int hf_mqtt_retain; | |||
| 529 | static int hf_mqtt_retain_reserved; | |||
| 530 | static int hf_mqtt_conack_reserved; | |||
| 531 | static int hf_mqtt_conack_flags; | |||
| 532 | static int hf_mqtt_conackflag_reserved; | |||
| 533 | static int hf_mqtt_conackflag_sp; | |||
| 534 | static int hf_mqtt_conack_code; | |||
| 535 | static int hf_mqtt_msgid; | |||
| 536 | static int hf_mqtt_sub_qos; | |||
| 537 | static int hf_mqtt_suback_qos; | |||
| 538 | static int hf_mqtt_topic_len; | |||
| 539 | static int hf_mqtt_topic; | |||
| 540 | static int hf_mqtt_will_topic_len; | |||
| 541 | static int hf_mqtt_will_topic; | |||
| 542 | static int hf_mqtt_will_msg_len; | |||
| 543 | static int hf_mqtt_will_msg; | |||
| 544 | static int hf_mqtt_will_msg_text; | |||
| 545 | static int hf_mqtt_username_len; | |||
| 546 | static int hf_mqtt_username; | |||
| 547 | static int hf_mqtt_passwd_len; | |||
| 548 | static int hf_mqtt_passwd; | |||
| 549 | static int hf_mqtt_pubmsg; | |||
| 550 | static int hf_mqtt_pubmsg_text; | |||
| 551 | static int hf_mqtt_pubmsg_decoded; | |||
| 552 | static int hf_mqtt_proto_len; | |||
| 553 | static int hf_mqtt_proto_name; | |||
| 554 | static int hf_mqtt_client_id_len; | |||
| 555 | static int hf_mqtt_client_id; | |||
| 556 | static int hf_mqtt_proto_ver; | |||
| 557 | static int hf_mqtt_conflags; | |||
| 558 | static int hf_mqtt_conflag_user; | |||
| 559 | static int hf_mqtt_conflag_passwd; | |||
| 560 | static int hf_mqtt_conflag_will_retain; | |||
| 561 | static int hf_mqtt_conflag_will_qos; | |||
| 562 | static int hf_mqtt_conflag_will_flag; | |||
| 563 | static int hf_mqtt_conflag_clean_sess; | |||
| 564 | static int hf_mqtt_conflag_reserved; | |||
| 565 | static int hf_mqtt_keep_alive; | |||
| 566 | static int hf_mqtt_subscription_options; | |||
| 567 | ||||
| 568 | /* MQTT v5.0 Reason Codes */ | |||
| 569 | static int hf_mqtt_reason_code_connack; | |||
| 570 | static int hf_mqtt_reason_code_puback; | |||
| 571 | static int hf_mqtt_reason_code_pubrec; | |||
| 572 | static int hf_mqtt_reason_code_pubrel; | |||
| 573 | static int hf_mqtt_reason_code_pubcomp; | |||
| 574 | static int hf_mqtt_reason_code_suback; | |||
| 575 | static int hf_mqtt_reason_code_unsuback; | |||
| 576 | static int hf_mqtt_reason_code_disconnect; | |||
| 577 | static int hf_mqtt_reason_code_auth; | |||
| 578 | ||||
| 579 | /* MQTT v5.0 Subscribe Options */ | |||
| 580 | static int hf_mqtt_subscription_qos; | |||
| 581 | static int hf_mqtt_subscription_nl; | |||
| 582 | static int hf_mqtt_subscription_rap; | |||
| 583 | static int hf_mqtt_subscription_retain; | |||
| 584 | static int hf_mqtt_subscription_reserved; | |||
| 585 | ||||
| 586 | /* MQTT v5.0 Properties */ | |||
| 587 | static int hf_mqtt_property_len; | |||
| 588 | static int hf_mqtt_property; | |||
| 589 | static int hf_mqtt_will_property; | |||
| 590 | static int hf_mqtt_property_id; | |||
| 591 | static int hf_mqtt_prop_num; | |||
| 592 | static int hf_mqtt_prop_content_type; | |||
| 593 | static int hf_mqtt_prop_max_qos; | |||
| 594 | static int hf_mqtt_prop_topic_alias; | |||
| 595 | static int hf_mqtt_prop_unknown; | |||
| 596 | static int hf_mqtt_prop_string_len; | |||
| 597 | static int hf_mqtt_prop_string; | |||
| 598 | static int hf_mqtt_prop_key_len; | |||
| 599 | static int hf_mqtt_prop_key; | |||
| 600 | static int hf_mqtt_prop_value_len; | |||
| 601 | static int hf_mqtt_prop_value; | |||
| 602 | ||||
| 603 | /* Initialize the subtree pointers */ | |||
| 604 | static int ett_mqtt_hdr; | |||
| 605 | static int ett_mqtt_msg; | |||
| 606 | static int ett_mqtt_hdr_flags; | |||
| 607 | static int ett_mqtt_con_flags; | |||
| 608 | static int ett_mqtt_conack_flags; | |||
| 609 | static int ett_mqtt_property; | |||
| 610 | static int ett_mqtt_subscription_flags; | |||
| 611 | ||||
| 612 | /* Initialize the expert fields */ | |||
| 613 | static expert_field ei_illegal_length; | |||
| 614 | static expert_field ei_unknown_version; | |||
| 615 | static expert_field ei_unknown_topic_alias; | |||
| 616 | ||||
| 617 | /* Reassemble SMPP TCP segments */ | |||
| 618 | static bool_Bool reassemble_mqtt_over_tcp = true1; | |||
| 619 | ||||
| 620 | /* Show Publish Message as text */ | |||
| 621 | static bool_Bool show_msg_as_text; | |||
| 622 | ||||
| 623 | static unsigned get_mqtt_pdu_len(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, | |||
| 624 | int offset, void *data _U___attribute__((unused))) | |||
| 625 | { | |||
| 626 | uint64_t msg_len; | |||
| 627 | unsigned len_offset; | |||
| 628 | ||||
| 629 | len_offset = tvb_get_varint(tvb, (offset + MQTT_HDR_SIZE_BEFORE_LEN1), FT_VARINT_MAX_LEN10, &msg_len, ENC_VARINT_PROTOBUF0x00000002); | |||
| 630 | ||||
| 631 | /* Explicitly downcast the value, because the length can never be more than 4 bytes */ | |||
| 632 | return (unsigned)(msg_len + len_offset + MQTT_HDR_SIZE_BEFORE_LEN1); | |||
| 633 | } | |||
| 634 | ||||
| 635 | static void *mqtt_message_decode_copy_cb(void *dest, const void *orig, size_t len _U___attribute__((unused))) | |||
| 636 | { | |||
| 637 | const mqtt_message_decode_t *o = (const mqtt_message_decode_t *)orig; | |||
| 638 | mqtt_message_decode_t *d = (mqtt_message_decode_t *)dest; | |||
| 639 | ||||
| 640 | d->match_criteria = o->match_criteria; | |||
| 641 | d->topic_pattern = g_strdup(o->topic_pattern)g_strdup_inline (o->topic_pattern); | |||
| 642 | d->msg_decoding = o->msg_decoding; | |||
| 643 | d->payload_proto_name = g_strdup(o->payload_proto_name)g_strdup_inline (o->payload_proto_name); | |||
| 644 | d->payload_proto = o->payload_proto; | |||
| 645 | ||||
| 646 | return d; | |||
| 647 | } | |||
| 648 | ||||
| 649 | static bool_Bool mqtt_message_decode_update_cb(void *record, char **error) | |||
| 650 | { | |||
| 651 | mqtt_message_decode_t *u = (mqtt_message_decode_t *)record; | |||
| 652 | ||||
| 653 | if (u->topic_pattern == NULL((void*)0) || strlen(u->topic_pattern) == 0) | |||
| 654 | { | |||
| 655 | *error = g_strdup("Missing topic pattern")g_strdup_inline ("Missing topic pattern"); | |||
| 656 | return false0; | |||
| 657 | } | |||
| 658 | ||||
| 659 | if (u->payload_proto_name == NULL((void*)0) || strlen(u->payload_proto_name) == 0) | |||
| 660 | { | |||
| 661 | *error = g_strdup("Missing payload protocol")g_strdup_inline ("Missing payload protocol"); | |||
| 662 | return false0; | |||
| 663 | } | |||
| 664 | ||||
| 665 | if (u->match_criteria == MATCH_CRITERIA_REGEX4) | |||
| 666 | { | |||
| 667 | u->topic_regex = g_regex_new(u->topic_pattern, (GRegexCompileFlags) G_REGEX_OPTIMIZE, (GRegexMatchFlags) 0, NULL((void*)0)); | |||
| 668 | if (!u->topic_regex) | |||
| 669 | { | |||
| 670 | *error = ws_strdup_printf("Invalid regex: %s", u->topic_pattern)wmem_strdup_printf(((void*)0), "Invalid regex: %s", u->topic_pattern ); | |||
| 671 | return false0; | |||
| 672 | } | |||
| 673 | } | |||
| 674 | ||||
| 675 | return true1; | |||
| 676 | } | |||
| 677 | ||||
| 678 | static void mqtt_message_decode_free_cb(void *record) | |||
| 679 | { | |||
| 680 | mqtt_message_decode_t *u = (mqtt_message_decode_t *)record; | |||
| 681 | ||||
| 682 | g_free(u->topic_pattern)(__builtin_object_size ((u->topic_pattern), 0) != ((size_t ) - 1)) ? g_free_sized (u->topic_pattern, __builtin_object_size ((u->topic_pattern), 0)) : (g_free) (u->topic_pattern); | |||
| 683 | if (u->topic_regex) | |||
| 684 | { | |||
| 685 | g_regex_unref(u->topic_regex); | |||
| 686 | } | |||
| 687 | g_free(u->payload_proto_name)(__builtin_object_size ((u->payload_proto_name), 0) != ((size_t ) - 1)) ? g_free_sized (u->payload_proto_name, __builtin_object_size ((u->payload_proto_name), 0)) : (g_free) (u->payload_proto_name ); | |||
| 688 | } | |||
| 689 | ||||
| 690 | UAT_VS_DEF(message_decode, match_criteria, mqtt_message_decode_t, unsigned, MATCH_CRITERIA_EQUAL, "Equal to")static void message_decode_match_criteria_set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* u2 __attribute__ ((unused))) { unsigned i; char* str = g_strndup(buf,len); const char* cstr; ((mqtt_message_decode_t*)rec)->match_criteria = 0; for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { if ((strcmp ((const char *) (cstr), (const char *) ( str)) == 0)) { ((mqtt_message_decode_t*)rec)->match_criteria = (unsigned)((const value_string*)vs)[i].value; (__builtin_object_size ((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size ((str), 0)) : (g_free) (str); return; } } (__builtin_object_size ((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size ((str), 0)) : (g_free) (str); } static void message_decode_match_criteria_tostr_cb (void* rec, char** out_ptr, unsigned* out_len, const void* vs , const void* u2 __attribute__((unused))) { unsigned i; for(i =0;((const value_string*)vs)[i].strptr;i++) { if ( ((const value_string *)vs)[i].value == ((mqtt_message_decode_t*)rec)->match_criteria ) { *out_ptr = g_strdup_inline (((const value_string*)vs)[i] .strptr); *out_len = (unsigned)strlen(*out_ptr); return; } } * out_ptr = g_strdup_inline ("Equal to"); *out_len = (unsigned) strlen("Equal to"); } | |||
| 691 | UAT_CSTRING_CB_DEF(message_decode, topic_pattern, mqtt_message_decode_t)static void message_decode_topic_pattern_set_cb(void* rec, const char* buf, unsigned len, const void* u1 __attribute__((unused )), const void* u2 __attribute__((unused))) { char* new_buf = g_strndup(buf,len); (__builtin_object_size (((((mqtt_message_decode_t *)rec)->topic_pattern)), 0) != ((size_t) - 1)) ? g_free_sized ((((mqtt_message_decode_t*)rec)->topic_pattern), __builtin_object_size (((((mqtt_message_decode_t*)rec)->topic_pattern)), 0)) : ( g_free) ((((mqtt_message_decode_t*)rec)->topic_pattern)); ( ((mqtt_message_decode_t*)rec)->topic_pattern) = new_buf; } static void message_decode_topic_pattern_tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* u1 __attribute__ ((unused)), const void* u2 __attribute__((unused))) { if (((mqtt_message_decode_t *)rec)->topic_pattern ) { *out_ptr = g_strdup_inline ((((mqtt_message_decode_t *)rec)->topic_pattern)); *out_len = (unsigned)strlen((((mqtt_message_decode_t *)rec)->topic_pattern)); } else { *out_ptr = g_strdup_inline (""); *out_len = 0; } } | |||
| 692 | UAT_VS_DEF(message_decode, msg_decoding, mqtt_message_decode_t, unsigned, MSG_DECODING_NONE, "none")static void message_decode_msg_decoding_set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* u2 __attribute__ ((unused))) { unsigned i; char* str = g_strndup(buf,len); const char* cstr; ((mqtt_message_decode_t*)rec)->msg_decoding = 0; for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ; i++) { if ((strcmp ((const char *) (cstr), (const char *) (str )) == 0)) { ((mqtt_message_decode_t*)rec)->msg_decoding = ( unsigned)((const value_string*)vs)[i].value; (__builtin_object_size ((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size ((str), 0)) : (g_free) (str); return; } } (__builtin_object_size ((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size ((str), 0)) : (g_free) (str); } static void message_decode_msg_decoding_tostr_cb (void* rec, char** out_ptr, unsigned* out_len, const void* vs , const void* u2 __attribute__((unused))) { unsigned i; for(i =0;((const value_string*)vs)[i].strptr;i++) { if ( ((const value_string *)vs)[i].value == ((mqtt_message_decode_t*)rec)->msg_decoding ) { *out_ptr = g_strdup_inline (((const value_string*)vs)[i] .strptr); *out_len = (unsigned)strlen(*out_ptr); return; } } * out_ptr = g_strdup_inline ("none"); *out_len = (unsigned)strlen ("none"); } | |||
| 693 | UAT_DISSECTOR_DEF(message_decode, payload_proto, payload_proto, payload_proto_name, mqtt_message_decode_t)static void message_decode_payload_proto_set_cb(void* rec, const char* buf, unsigned len, const void* u1 __attribute__((unused )), const void* u2 __attribute__((unused))) { if (len) { ((mqtt_message_decode_t *)rec)->payload_proto_name = g_strndup(buf, len); g_strchomp (g_strchug (((mqtt_message_decode_t*)rec)->payload_proto_name )); ((mqtt_message_decode_t*)rec)->payload_proto = find_dissector (((mqtt_message_decode_t*)rec)->payload_proto_name); } else { ((mqtt_message_decode_t*)rec)->payload_proto = find_dissector ("data"); ((mqtt_message_decode_t*)rec)->payload_proto_name = ((void*)0); } } static void message_decode_payload_proto_tostr_cb (void* rec, char** out_ptr, unsigned* out_len, const void* u1 __attribute__((unused)), const void* u2 __attribute__((unused ))) { if ( ((mqtt_message_decode_t*)rec)->payload_proto_name ) { *out_ptr = g_strdup_inline ((((mqtt_message_decode_t*)rec )->payload_proto_name)); *out_len = (unsigned)strlen(*out_ptr ); } else { *out_ptr = g_strdup_inline (""); *out_len = 0; } } | |||
| 694 | ||||
| 695 | static bool_Bool mqtt_user_decode_message(proto_tree *tree, proto_tree *mqtt_tree, packet_info *pinfo, const char *topic_str, tvbuff_t *msg_tvb) | |||
| 696 | { | |||
| 697 | mqtt_message_decode_t *message_decode_entry = NULL((void*)0); | |||
| 698 | size_t topic_str_len = strlen(topic_str); | |||
| 699 | size_t topic_pattern_len; | |||
| 700 | bool_Bool match_found = false0; | |||
| 701 | ||||
| 702 | if (topic_str_len == 0) | |||
| 703 | { | |||
| 704 | /* No topic to match */ | |||
| 705 | return false0; | |||
| 706 | } | |||
| 707 | ||||
| 708 | for (unsigned i = 0; i < num_mqtt_message_decodes && !match_found; i++) | |||
| 709 | { | |||
| 710 | message_decode_entry = &mqtt_message_decodes[i]; | |||
| 711 | switch (message_decode_entry->match_criteria) | |||
| 712 | { | |||
| 713 | case MATCH_CRITERIA_EQUAL0: | |||
| 714 | match_found = (strcmp(topic_str, message_decode_entry->topic_pattern) == 0); | |||
| 715 | break; | |||
| 716 | case MATCH_CRITERIA_CONTAINS1: | |||
| 717 | match_found = (strstr(topic_str, message_decode_entry->topic_pattern) != NULL((void*)0)); | |||
| 718 | break; | |||
| 719 | case MATCH_CRITERIA_STARTS_WITH2: | |||
| 720 | topic_pattern_len = strlen(message_decode_entry->topic_pattern); | |||
| 721 | match_found = ((topic_str_len >= topic_pattern_len) && | |||
| 722 | (strncmp(topic_str, message_decode_entry->topic_pattern, topic_pattern_len) == 0)); | |||
| 723 | break; | |||
| 724 | case MATCH_CRITERIA_ENDS_WITH3: | |||
| 725 | topic_pattern_len = strlen(message_decode_entry->topic_pattern); | |||
| 726 | match_found = ((topic_str_len >= topic_pattern_len) && | |||
| 727 | (strcmp(topic_str + (topic_str_len - topic_pattern_len), message_decode_entry->topic_pattern) == 0)); | |||
| 728 | break; | |||
| 729 | case MATCH_CRITERIA_REGEX4: | |||
| 730 | if (message_decode_entry->topic_regex) | |||
| 731 | { | |||
| 732 | GMatchInfo *match_info = NULL((void*)0); | |||
| 733 | /* DISSECTOR_ASSERT(g_utf8_validate(topic_str, -1, NULL)); */ | |||
| 734 | g_regex_match(message_decode_entry->topic_regex, topic_str, (GRegexMatchFlags) 0, &match_info); | |||
| 735 | match_found = g_match_info_matches(match_info); | |||
| 736 | g_match_info_free(match_info); | |||
| 737 | } | |||
| 738 | break; | |||
| 739 | default: | |||
| 740 | /* Unknown match criteria */ | |||
| 741 | break; | |||
| 742 | } | |||
| 743 | } | |||
| 744 | ||||
| 745 | if (match_found) | |||
| 746 | { | |||
| 747 | if (message_decode_entry->msg_decoding == MSG_DECODING_COMPRESSED1) | |||
| 748 | { | |||
| 749 | msg_tvb = tvb_child_uncompress_zlib(msg_tvb, msg_tvb, 0, tvb_reported_length(msg_tvb)); | |||
| 750 | if (msg_tvb) | |||
| 751 | { | |||
| 752 | add_new_data_source(pinfo, msg_tvb, "Uncompressed Message"); | |||
| 753 | } | |||
| 754 | } | |||
| 755 | ||||
| 756 | if (msg_tvb) | |||
| 757 | { | |||
| 758 | proto_item *ti = proto_tree_add_string(mqtt_tree, hf_mqtt_pubmsg_decoded, msg_tvb, 0, -1, | |||
| 759 | message_decode_entry->payload_proto_name); | |||
| 760 | proto_item_set_generated(ti); | |||
| 761 | ||||
| 762 | call_dissector(message_decode_entry->payload_proto, msg_tvb, pinfo, tree); | |||
| 763 | } | |||
| 764 | } | |||
| 765 | ||||
| 766 | return match_found; | |||
| 767 | } | |||
| 768 | ||||
| 769 | static unsigned dissect_string(tvbuff_t *tvb, proto_tree *tree, unsigned offset, int hf_len, int hf_value) | |||
| 770 | { | |||
| 771 | uint32_t prop_len; | |||
| 772 | ||||
| 773 | proto_tree_add_item_ret_uint(tree, hf_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &prop_len); | |||
| 774 | proto_tree_add_item(tree, hf_value, tvb, offset + 2, prop_len, ENC_UTF_80x00000002|ENC_NA0x00000000); | |||
| 775 | ||||
| 776 | return 2 + prop_len; | |||
| 777 | } | |||
| 778 | ||||
| 779 | /* MQTT v5.0: Reason Codes */ | |||
| 780 | static void dissect_mqtt_reason_code(proto_tree *mqtt_tree, tvbuff_t *tvb, unsigned offset, uint8_t mqtt_msg_type) | |||
| 781 | { | |||
| 782 | static int * const hf_rcode[] = { | |||
| 783 | NULL((void*)0), /* RESERVED */ | |||
| 784 | NULL((void*)0), /* CONNECT */ | |||
| 785 | &hf_mqtt_reason_code_connack, | |||
| 786 | NULL((void*)0), /* PUBLISH */ | |||
| 787 | &hf_mqtt_reason_code_puback, | |||
| 788 | &hf_mqtt_reason_code_pubrec, | |||
| 789 | &hf_mqtt_reason_code_pubrel, | |||
| 790 | &hf_mqtt_reason_code_pubcomp, | |||
| 791 | NULL((void*)0), /* SUBSCRIBE */ | |||
| 792 | &hf_mqtt_reason_code_suback, | |||
| 793 | NULL((void*)0), /* UNSUBSCRIBE */ | |||
| 794 | &hf_mqtt_reason_code_unsuback, | |||
| 795 | NULL((void*)0), /* PINGREQ */ | |||
| 796 | NULL((void*)0), /* PINGRESP */ | |||
| 797 | &hf_mqtt_reason_code_disconnect, | |||
| 798 | &hf_mqtt_reason_code_auth | |||
| 799 | }; | |||
| 800 | ||||
| 801 | if (mqtt_msg_type < array_length(hf_rcode)(sizeof (hf_rcode) / sizeof (hf_rcode)[0])) | |||
| 802 | { | |||
| 803 | const int *hfindex = hf_rcode[mqtt_msg_type]; | |||
| 804 | if (hfindex) | |||
| 805 | { | |||
| 806 | proto_tree_add_item(mqtt_tree, *hfindex, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 807 | } | |||
| 808 | } | |||
| 809 | } | |||
| 810 | ||||
| 811 | /* MQTT v5.0: dissect the MQTT properties */ | |||
| 812 | static unsigned dissect_mqtt_properties(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mqtt_tree, unsigned offset, int hf_property, mqtt_properties_t *mqtt_properties) | |||
| 813 | { | |||
| 814 | proto_tree *mqtt_prop_tree; | |||
| 815 | proto_item *ti; | |||
| 816 | uint64_t vbi; | |||
| 817 | ||||
| 818 | const unsigned mqtt_prop_offset = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN10, &vbi, ENC_VARINT_PROTOBUF0x00000002); | |||
| 819 | /* Property Length field can be stored in uint32 */ | |||
| 820 | unsigned mqtt_prop_len = (unsigned)vbi; | |||
| 821 | const unsigned remaining = tvb_reported_length_remaining(tvb, offset + mqtt_prop_offset); | |||
| 822 | if (vbi > remaining) | |||
| 823 | { | |||
| 824 | mqtt_prop_len = remaining; | |||
| 825 | expert_add_info(pinfo, mqtt_tree, &ei_illegal_length); | |||
| 826 | } | |||
| 827 | ||||
| 828 | /* Add the MQTT branch to the main tree */ | |||
| 829 | /* hf_property is usually hf_mqtt_property, but can also be | |||
| 830 | * hf_mqtt_will_property when a Will is provided in a CONNECT packet */ | |||
| 831 | ti = proto_tree_add_item(mqtt_tree, hf_property, tvb, offset, mqtt_prop_offset + mqtt_prop_len, ENC_NA0x00000000); | |||
| 832 | mqtt_prop_tree = proto_item_add_subtree(ti, ett_mqtt_property); | |||
| 833 | ||||
| 834 | proto_tree_add_item(mqtt_prop_tree, hf_mqtt_property_len, tvb, offset, mqtt_prop_offset, ENC_VARINT_PROTOBUF0x00000002); | |||
| 835 | offset += mqtt_prop_offset; | |||
| 836 | ||||
| 837 | const unsigned bytes_to_read = offset + mqtt_prop_len; | |||
| 838 | while (offset < bytes_to_read) | |||
| 839 | { | |||
| 840 | uint32_t prop_id; | |||
| 841 | proto_tree_add_item_ret_uint(mqtt_prop_tree, hf_mqtt_property_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &prop_id); | |||
| 842 | offset += 1; | |||
| 843 | ||||
| 844 | switch (prop_id) | |||
| 845 | { | |||
| 846 | case PROP_PAYLOAD_FORMAT_INDICATOR0x01: | |||
| 847 | case PROP_REQUEST_PROBLEM_INFORMATION0x17: | |||
| 848 | case PROP_REQUEST_RESPONSE_INFORMATION0x19: | |||
| 849 | case PROP_RETAIN_AVAILABLE0x25: | |||
| 850 | case PROP_WILDCARD_SUBSCRIPTION_AVAILABLE0x28: | |||
| 851 | case PROP_SUBSCRIPTION_IDENTIFIER_AVAILABLE0x29: | |||
| 852 | case PROP_SHARED_SUBSCRIPTION_AVAILABLE0x2A: | |||
| 853 | proto_tree_add_item(mqtt_prop_tree, hf_mqtt_prop_num, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 854 | offset += 1; | |||
| 855 | break; | |||
| 856 | ||||
| 857 | case PROP_MAXIMUM_QOS0x24: | |||
| 858 | proto_tree_add_item(mqtt_prop_tree, hf_mqtt_prop_max_qos, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 859 | offset += 1; | |||
| 860 | break; | |||
| 861 | ||||
| 862 | case PROP_TOPIC_ALIAS0x23: | |||
| 863 | proto_tree_add_item_ret_uint(mqtt_prop_tree, hf_mqtt_prop_topic_alias, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_properties->topic_alias); | |||
| 864 | offset += 2; | |||
| 865 | break; | |||
| 866 | ||||
| 867 | case PROP_SERVER_KEEP_ALIVE0x13: | |||
| 868 | case PROP_RECEIVE_MAXIMUM0x21: | |||
| 869 | case PROP_TOPIC_ALIAS_MAXIMUM0x22: | |||
| 870 | proto_tree_add_item(mqtt_prop_tree, hf_mqtt_prop_num, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
| 871 | offset += 2; | |||
| 872 | break; | |||
| 873 | ||||
| 874 | case PROP_PUBLICATION_EXPIRY_INTERVAL0x02: | |||
| 875 | case PROP_SESSION_EXPIRY_INTERVAL0x11: | |||
| 876 | case PROP_WILL_DELAY_INTERVAL0x18: | |||
| 877 | case PROP_MAXIMUM_PACKET_SIZE0x27: | |||
| 878 | proto_tree_add_item(mqtt_prop_tree, hf_mqtt_prop_num, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000); | |||
| 879 | offset += 4; | |||
| 880 | break; | |||
| 881 | ||||
| 882 | case PROP_SUBSCRIPTION_IDENTIFIER0x0B: | |||
| 883 | { | |||
| 884 | unsigned vbi_len; | |||
| 885 | proto_tree_add_item_ret_length(mqtt_prop_tree, hf_mqtt_prop_num, tvb, offset, -1, ENC_LITTLE_ENDIAN0x80000000|ENC_VARINT_PROTOBUF0x00000002, &vbi_len); | |||
| 886 | offset += vbi_len; | |||
| 887 | break; | |||
| 888 | } | |||
| 889 | ||||
| 890 | case PROP_CONTENT_TYPE0x03: | |||
| 891 | { | |||
| 892 | unsigned length; | |||
| 893 | proto_tree_add_item_ret_string_and_length(mqtt_prop_tree, hf_mqtt_prop_content_type, tvb, offset, 2, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t**)&mqtt_properties->content_type, &length); | |||
| 894 | offset += length; | |||
| 895 | break; | |||
| 896 | } | |||
| 897 | ||||
| 898 | case PROP_RESPONSE_TOPIC0x08: | |||
| 899 | case PROP_CORRELATION_DATA0x09: | |||
| 900 | case PROP_ASSIGNED_CLIENT_IDENTIFIER0x12: | |||
| 901 | case PROP_AUTH_METHOD0x15: | |||
| 902 | case PROP_AUTH_DATA0x16: | |||
| 903 | case PROP_RESPONSE_INFORMATION0x1A: | |||
| 904 | case PROP_SERVER_REFERENCE0x1C: | |||
| 905 | case PROP_REASON_STRING0x1F: | |||
| 906 | offset += dissect_string(tvb, mqtt_prop_tree, offset, hf_mqtt_prop_string_len, hf_mqtt_prop_string); | |||
| 907 | break; | |||
| 908 | ||||
| 909 | case PROP_USER_PROPERTY0x26: | |||
| 910 | offset += dissect_string(tvb, mqtt_prop_tree, offset, hf_mqtt_prop_key_len, hf_mqtt_prop_key); | |||
| 911 | offset += dissect_string(tvb, mqtt_prop_tree, offset, hf_mqtt_prop_value_len, hf_mqtt_prop_value); | |||
| 912 | break; | |||
| 913 | ||||
| 914 | default: | |||
| 915 | proto_tree_add_item(mqtt_prop_tree, hf_mqtt_prop_unknown, tvb, offset, bytes_to_read - offset, ENC_UTF_80x00000002); | |||
| 916 | offset += (bytes_to_read - offset); | |||
| 917 | break; | |||
| 918 | } | |||
| 919 | } | |||
| 920 | ||||
| 921 | return mqtt_prop_offset + mqtt_prop_len; | |||
| 922 | } | |||
| 923 | ||||
| 924 | /* Dissect the MQTT message */ | |||
| 925 | static int dissect_mqtt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused))) | |||
| 926 | { | |||
| 927 | uint8_t mqtt_fixed_hdr; | |||
| 928 | uint8_t mqtt_msg_type; | |||
| 929 | proto_item *ti; | |||
| 930 | const char *topic_str = ""; | |||
| 931 | proto_item *mqtt_ti; | |||
| 932 | proto_tree *mqtt_tree; | |||
| 933 | uint64_t mqtt_con_flags; | |||
| 934 | uint64_t msg_len = 0; | |||
| 935 | int mqtt_msg_len = 0; | |||
| 936 | uint32_t mqtt_str_len; | |||
| 937 | uint16_t mqtt_len_offset; | |||
| 938 | int mqtt_payload_len; | |||
| 939 | uint32_t mqtt_msgid; | |||
| 940 | conversation_t *conv; | |||
| 941 | mqtt_conv_t *mqtt; | |||
| 942 | mqtt_conv_t saved_mqtt; | |||
| 943 | mqtt_pdu_data_t *pdu_data; | |||
| 944 | unsigned pdu_idx = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_mqtt, 0))((guint) (gulong) (p_get_proto_data(pinfo->pool, pinfo, proto_mqtt , 0))); | |||
| 945 | mqtt_properties_t mqtt_properties = { 0 }; | |||
| 946 | mqtt_properties_t mqtt_will_properties = { 0 }; | |||
| 947 | unsigned offset = 0; | |||
| 948 | bool_Bool msg_handled = false0; | |||
| 949 | ||||
| 950 | static int * const publish_fields[] = { | |||
| 951 | &hf_mqtt_msg_type, | |||
| 952 | &hf_mqtt_dup_flag, | |||
| 953 | &hf_mqtt_qos_level, | |||
| 954 | &hf_mqtt_retain, | |||
| 955 | NULL((void*)0) | |||
| 956 | }; | |||
| 957 | ||||
| 958 | static int * const v31_pubrel_sub_unsub_fields[] = { | |||
| 959 | &hf_mqtt_msg_type, | |||
| 960 | &hf_mqtt_dup_flag, | |||
| 961 | &hf_mqtt_qos_level, | |||
| 962 | &hf_mqtt_retain_reserved, | |||
| 963 | NULL((void*)0) | |||
| 964 | }; | |||
| 965 | ||||
| 966 | static int * const other_fields[] = { | |||
| 967 | &hf_mqtt_msg_type, | |||
| 968 | &hf_mqtt_reserved, | |||
| 969 | NULL((void*)0) | |||
| 970 | }; | |||
| 971 | ||||
| 972 | static int * const connect_flags[] = { | |||
| 973 | &hf_mqtt_conflag_user, | |||
| 974 | &hf_mqtt_conflag_passwd, | |||
| 975 | &hf_mqtt_conflag_will_retain, | |||
| 976 | &hf_mqtt_conflag_will_qos, | |||
| 977 | &hf_mqtt_conflag_will_flag, | |||
| 978 | &hf_mqtt_conflag_clean_sess, | |||
| 979 | &hf_mqtt_conflag_reserved, | |||
| 980 | NULL((void*)0) | |||
| 981 | }; | |||
| 982 | ||||
| 983 | static int * const connack_flags[] = { | |||
| 984 | &hf_mqtt_conackflag_reserved, | |||
| 985 | &hf_mqtt_conackflag_sp, | |||
| 986 | NULL((void*)0) | |||
| 987 | }; | |||
| 988 | ||||
| 989 | static int * const v50_subscription_flags[] = { | |||
| 990 | &hf_mqtt_subscription_reserved, | |||
| 991 | &hf_mqtt_subscription_retain, | |||
| 992 | &hf_mqtt_subscription_rap, | |||
| 993 | &hf_mqtt_subscription_nl, | |||
| 994 | &hf_mqtt_subscription_qos, | |||
| 995 | NULL((void*)0) | |||
| 996 | }; | |||
| 997 | ||||
| 998 | /* Extract the message ID */ | |||
| 999 | /* A TCP frame may contain several PDUs, including reassembled PDUs. */ | |||
| 1000 | p_set_proto_data(pinfo->pool, pinfo, proto_mqtt, 0, GUINT_TO_POINTER(pdu_idx + 1)((gpointer) (gulong) (pdu_idx + 1))); | |||
| 1001 | ||||
| 1002 | mqtt_fixed_hdr = tvb_get_uint8(tvb, offset); | |||
| 1003 | mqtt_msg_type = mqtt_fixed_hdr >> 4; | |||
| 1004 | ||||
| 1005 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQTT"); | |||
| 1006 | col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", val_to_str_ext(pinfo->pool, mqtt_msg_type, &mqtt_msgtype_vals_ext, "Unknown (0x%02x)")); | |||
| 1007 | ||||
| 1008 | /* Add the MQTT branch to the main tree */ | |||
| 1009 | mqtt_ti = proto_tree_add_item(tree, proto_mqtt, tvb, 0, -1, ENC_NA0x00000000); | |||
| 1010 | mqtt_tree = proto_item_add_subtree(mqtt_ti, ett_mqtt_hdr); | |||
| 1011 | ||||
| 1012 | conv = find_or_create_conversation(pinfo); | |||
| 1013 | mqtt = (mqtt_conv_t *)conversation_get_proto_data(conv, proto_mqtt); | |||
| 1014 | if (mqtt == NULL((void*)0)) | |||
| ||||
| 1015 | { | |||
| 1016 | mqtt = wmem_new0(wmem_file_scope(), mqtt_conv_t)((mqtt_conv_t*)wmem_alloc0((wmem_file_scope()), sizeof(mqtt_conv_t ))); | |||
| 1017 | mqtt->runtime_proto_version = default_protocol_version; | |||
| 1018 | conversation_add_proto_data(conv, proto_mqtt, mqtt); | |||
| 1019 | mqtt->topic_alias_map = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); | |||
| 1020 | } | |||
| 1021 | ||||
| 1022 | mqtt_len_offset = tvb_get_varint(tvb, (offset + MQTT_HDR_SIZE_BEFORE_LEN1), FT_VARINT_MAX_LEN10, &msg_len, ENC_VARINT_PROTOBUF0x00000002); | |||
| 1023 | ||||
| 1024 | /* Explicit downcast, typically maximum length of message could be 4 bytes */ | |||
| 1025 | mqtt_msg_len = (int) msg_len; | |||
| 1026 | ||||
| 1027 | /* Add the type to the MQTT tree item */ | |||
| 1028 | proto_item_append_text(mqtt_tree, ", %s", val_to_str_ext(pinfo->pool, mqtt_msg_type, &mqtt_msgtype_vals_ext, "Unknown (0x%02x)")); | |||
| 1029 | ||||
| 1030 | /* Save each PDU's initial state, including an unresolved topic alias. */ | |||
| 1031 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) | |||
| 1032 | { | |||
| 1033 | pdu_data = wmem_new0(wmem_file_scope(), mqtt_pdu_data_t)((mqtt_pdu_data_t*)wmem_alloc0((wmem_file_scope()), sizeof(mqtt_pdu_data_t ))); | |||
| 1034 | pdu_data->version = mqtt->runtime_proto_version; | |||
| 1035 | p_add_proto_data(wmem_file_scope(), pinfo, proto_mqtt, pdu_idx, pdu_data); | |||
| 1036 | } | |||
| 1037 | else | |||
| 1038 | { | |||
| 1039 | pdu_data = (mqtt_pdu_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_mqtt, pdu_idx); | |||
| 1040 | saved_mqtt = *mqtt; | |||
| 1041 | mqtt = &saved_mqtt; | |||
| 1042 | if (pdu_data != NULL((void*)0)) | |||
| 1043 | mqtt->runtime_proto_version = pdu_data->version; | |||
| 1044 | } | |||
| 1045 | ||||
| 1046 | if ((mqtt_msg_type != MQTT_CONNECT1) && (mqtt->runtime_proto_version == 0)) | |||
| 1047 | { | |||
| 1048 | expert_add_info(pinfo, mqtt_ti, &ei_unknown_version); | |||
| 1049 | } | |||
| 1050 | ||||
| 1051 | if (mqtt_msg_type == MQTT_PUBLISH3) | |||
| 1052 | { | |||
| 1053 | proto_tree_add_bitmask(mqtt_tree, tvb, offset, hf_mqtt_hdrflags, ett_mqtt_hdr_flags, publish_fields, ENC_BIG_ENDIAN0x00000000); | |||
| 1054 | } | |||
| 1055 | else if (mqtt->runtime_proto_version == MQTT_PROTO_V313 && | |||
| 1056 | (mqtt_msg_type == MQTT_PUBREL6 || | |||
| 1057 | mqtt_msg_type == MQTT_SUBSCRIBE8 || | |||
| 1058 | mqtt_msg_type == MQTT_UNSUBSCRIBE10)) | |||
| 1059 | { | |||
| 1060 | proto_tree_add_bitmask(mqtt_tree, tvb, offset, hf_mqtt_hdrflags, ett_mqtt_hdr_flags, v31_pubrel_sub_unsub_fields, ENC_BIG_ENDIAN0x00000000); | |||
| 1061 | } | |||
| 1062 | else | |||
| 1063 | { | |||
| 1064 | proto_tree_add_bitmask(mqtt_tree, tvb, offset, hf_mqtt_hdrflags, ett_mqtt_hdr_flags, other_fields, ENC_BIG_ENDIAN0x00000000); | |||
| 1065 | } | |||
| 1066 | ||||
| 1067 | offset += 1; | |||
| 1068 | ||||
| 1069 | /* Add the MQTT message length */ | |||
| 1070 | proto_tree_add_uint64(mqtt_tree, hf_mqtt_msg_len, tvb, offset, mqtt_len_offset, msg_len); | |||
| 1071 | offset += mqtt_len_offset; | |||
| 1072 | ||||
| 1073 | switch (mqtt_msg_type) | |||
| 1074 | { | |||
| 1075 | case MQTT_CONNECT1: | |||
| 1076 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_proto_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1077 | offset += 2; | |||
| 1078 | ||||
| 1079 | proto_tree_add_item(mqtt_tree, hf_mqtt_proto_name, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1080 | offset += mqtt_str_len; | |||
| 1081 | ||||
| 1082 | mqtt->runtime_proto_version = tvb_get_uint8(tvb, offset); | |||
| 1083 | ||||
| 1084 | proto_tree_add_item(mqtt_tree, hf_mqtt_proto_ver, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 1085 | offset += 1; | |||
| 1086 | ||||
| 1087 | proto_tree_add_bitmask_ret_uint64(mqtt_tree, tvb, offset, hf_mqtt_conflags, | |||
| 1088 | ett_mqtt_con_flags, connect_flags, ENC_BIG_ENDIAN0x00000000, &mqtt_con_flags); | |||
| 1089 | offset += 1; | |||
| 1090 | ||||
| 1091 | proto_tree_add_item(mqtt_tree, hf_mqtt_keep_alive, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000); | |||
| 1092 | offset += 2; | |||
| 1093 | ||||
| 1094 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1095 | { | |||
| 1096 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1097 | } | |||
| 1098 | ||||
| 1099 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_client_id_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1100 | offset += 2; | |||
| 1101 | ||||
| 1102 | proto_tree_add_item(mqtt_tree, hf_mqtt_client_id, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1103 | offset += mqtt_str_len; | |||
| 1104 | ||||
| 1105 | if (mqtt_con_flags & MQTT_CONMASK_WILLFLAG0x04) | |||
| 1106 | { | |||
| 1107 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1108 | { | |||
| 1109 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_will_property, &mqtt_will_properties); | |||
| 1110 | } | |||
| 1111 | ||||
| 1112 | ti = proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_will_topic_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1113 | offset += 2; | |||
| 1114 | ||||
| 1115 | if (mqtt_str_len > 0) | |||
| 1116 | { | |||
| 1117 | proto_tree_add_item(mqtt_tree, hf_mqtt_will_topic, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1118 | offset += mqtt_str_len; | |||
| 1119 | } | |||
| 1120 | else | |||
| 1121 | { | |||
| 1122 | expert_add_info(pinfo, ti, &ei_illegal_length); | |||
| 1123 | } | |||
| 1124 | ||||
| 1125 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_will_msg_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1126 | offset += 2; | |||
| 1127 | ||||
| 1128 | if (show_msg_as_text) | |||
| 1129 | { | |||
| 1130 | proto_tree_add_item(mqtt_tree, hf_mqtt_will_msg_text, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1131 | } | |||
| 1132 | else | |||
| 1133 | { | |||
| 1134 | proto_tree_add_item(mqtt_tree, hf_mqtt_will_msg, tvb, offset, mqtt_str_len, ENC_NA0x00000000); | |||
| 1135 | } | |||
| 1136 | offset += mqtt_str_len; | |||
| 1137 | } | |||
| 1138 | ||||
| 1139 | if ((mqtt_con_flags & MQTT_CONMASK_USER0x80) && (tvb_reported_length_remaining(tvb, offset) > 0)) | |||
| 1140 | { | |||
| 1141 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_username_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1142 | offset += 2; | |||
| 1143 | ||||
| 1144 | proto_tree_add_item(mqtt_tree, hf_mqtt_username, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1145 | offset += mqtt_str_len; | |||
| 1146 | } | |||
| 1147 | ||||
| 1148 | if ((mqtt_con_flags & MQTT_CONMASK_PASSWD0x40) && (tvb_reported_length_remaining(tvb, offset) > 0)) | |||
| 1149 | { | |||
| 1150 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_passwd_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1151 | offset += 2; | |||
| 1152 | ||||
| 1153 | proto_tree_add_item(mqtt_tree, hf_mqtt_passwd, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1154 | } | |||
| 1155 | break; | |||
| 1156 | ||||
| 1157 | case MQTT_CONNACK2: | |||
| 1158 | if (mqtt->runtime_proto_version == MQTT_PROTO_V313) | |||
| 1159 | { | |||
| 1160 | /* v3.1 Connection Ack only contains a reserved byte and the Return Code. */ | |||
| 1161 | proto_tree_add_item(mqtt_tree, hf_mqtt_conack_reserved, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 1162 | } | |||
| 1163 | else | |||
| 1164 | { | |||
| 1165 | /* v3.1.1 Conn Ack contains the Conn Ack Flags and the Return Code. */ | |||
| 1166 | proto_tree_add_bitmask(mqtt_tree, tvb, offset, hf_mqtt_conack_flags, | |||
| 1167 | ett_mqtt_conack_flags, connack_flags, ENC_BIG_ENDIAN0x00000000); | |||
| 1168 | } | |||
| 1169 | offset += 1; | |||
| 1170 | ||||
| 1171 | if ((mqtt->runtime_proto_version == MQTT_PROTO_V313) || | |||
| 1172 | (mqtt->runtime_proto_version == MQTT_PROTO_V3114)) | |||
| 1173 | { | |||
| 1174 | proto_tree_add_item(mqtt_tree, hf_mqtt_conack_code, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 1175 | } | |||
| 1176 | else | |||
| 1177 | { | |||
| 1178 | dissect_mqtt_reason_code(mqtt_tree, tvb, offset, mqtt_msg_type); | |||
| 1179 | } | |||
| 1180 | offset += 1; | |||
| 1181 | ||||
| 1182 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1183 | { | |||
| 1184 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1185 | } | |||
| 1186 | break; | |||
| 1187 | ||||
| 1188 | case MQTT_PUBLISH3: | |||
| 1189 | /* TopicName|MsgID|Message| */ | |||
| 1190 | ti = proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_topic_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1191 | offset += 2; | |||
| 1192 | ||||
| 1193 | if (mqtt_str_len > 0) | |||
| 1194 | { | |||
| 1195 | /* 'topic_regex' requires topic_str to be valid UTF-8. */ | |||
| 1196 | proto_tree_add_item_ret_string(mqtt_tree, hf_mqtt_topic, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002|ENC_NA0x00000000, | |||
| 1197 | pinfo->pool, (const uint8_t**)&topic_str); | |||
| 1198 | offset += mqtt_str_len; | |||
| 1199 | } | |||
| 1200 | ||||
| 1201 | /* Message ID is included only when QoS > 0 */ | |||
| 1202 | if (mqtt_fixed_hdr & MQTT_MASK_QOS0x06) | |||
| 1203 | { | |||
| 1204 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_msgid); | |||
| 1205 | offset += 2; | |||
| 1206 | col_append_fstr(pinfo->cinfo, COL_INFO, " (id=%u)", mqtt_msgid); | |||
| 1207 | } | |||
| 1208 | ||||
| 1209 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1210 | { | |||
| 1211 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1212 | ||||
| 1213 | if (mqtt_properties.topic_alias != 0) | |||
| 1214 | { | |||
| 1215 | char *topic = NULL((void*)0); | |||
| 1216 | if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) | |||
| 1217 | { | |||
| 1218 | if (mqtt_str_len
| |||
| 1219 | { | |||
| 1220 | topic = wmem_strdup(wmem_file_scope(), topic_str); | |||
| 1221 | wmem_map_insert(mqtt->topic_alias_map, GUINT_TO_POINTER(mqtt_properties.topic_alias)((gpointer) (gulong) (mqtt_properties.topic_alias)), topic); | |||
| 1222 | } | |||
| 1223 | else | |||
| 1224 | { | |||
| 1225 | topic = (char *)wmem_map_lookup(mqtt->topic_alias_map, GUINT_TO_POINTER(mqtt_properties.topic_alias)((gpointer) (gulong) (mqtt_properties.topic_alias))); | |||
| 1226 | } | |||
| 1227 | pdu_data->topic = topic; | |||
| ||||
| 1228 | } | |||
| 1229 | else if (pdu_data != NULL((void*)0)) | |||
| 1230 | { | |||
| 1231 | topic = pdu_data->topic; | |||
| 1232 | } | |||
| 1233 | ||||
| 1234 | if (mqtt_str_len == 0) | |||
| 1235 | { | |||
| 1236 | if (topic != NULL((void*)0)) | |||
| 1237 | { | |||
| 1238 | topic_str = topic; | |||
| 1239 | } | |||
| 1240 | ||||
| 1241 | ti = proto_tree_add_string(mqtt_tree, hf_mqtt_topic, tvb, offset, 0, topic_str); | |||
| 1242 | proto_item_set_generated(ti); | |||
| 1243 | ||||
| 1244 | if (topic == NULL((void*)0)) | |||
| 1245 | { | |||
| 1246 | expert_add_info(pinfo, ti, &ei_unknown_topic_alias); | |||
| 1247 | } | |||
| 1248 | } | |||
| 1249 | } | |||
| 1250 | } | |||
| 1251 | ||||
| 1252 | if ((mqtt_str_len == 0) && (mqtt_properties.topic_alias == 0)) | |||
| 1253 | { | |||
| 1254 | expert_add_info(pinfo, ti, &ei_illegal_length); | |||
| 1255 | } | |||
| 1256 | ||||
| 1257 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", topic_str); | |||
| 1258 | ||||
| 1259 | mqtt_payload_len = tvb_reported_length(tvb) - offset; | |||
| 1260 | if (show_msg_as_text) | |||
| 1261 | { | |||
| 1262 | proto_tree_add_item(mqtt_tree, hf_mqtt_pubmsg_text, tvb, offset, mqtt_payload_len, ENC_UTF_80x00000002); | |||
| 1263 | } | |||
| 1264 | else | |||
| 1265 | { | |||
| 1266 | proto_tree_add_item(mqtt_tree, hf_mqtt_pubmsg, tvb, offset, mqtt_payload_len, ENC_NA0x00000000); | |||
| 1267 | } | |||
| 1268 | ||||
| 1269 | if (num_mqtt_message_decodes > 0) | |||
| 1270 | { | |||
| 1271 | tvbuff_t *msg_tvb = tvb_new_subset_length(tvb, offset, mqtt_payload_len); | |||
| 1272 | msg_handled = mqtt_user_decode_message(tree, mqtt_tree, pinfo, topic_str, msg_tvb); | |||
| 1273 | } | |||
| 1274 | ||||
| 1275 | if (mqtt_properties.content_type) | |||
| 1276 | { | |||
| 1277 | tvbuff_t *msg_tvb = tvb_new_subset_length(tvb, offset, mqtt_payload_len); | |||
| 1278 | int bytes_read = dissector_try_string_with_data(media_type_dissector_table, mqtt_properties.content_type, | |||
| 1279 | msg_tvb, pinfo, tree, true1, NULL((void*)0)); | |||
| 1280 | ||||
| 1281 | msg_handled = msg_handled | (bytes_read != 0); | |||
| 1282 | } | |||
| 1283 | ||||
| 1284 | /* No UAT or content property match, try the heuristic dissectors, pass the topic string as data */ | |||
| 1285 | if (!msg_handled) { | |||
| 1286 | heur_dtbl_entry_t *hdtbl_entry; | |||
| 1287 | tvbuff_t *msg_tvb = tvb_new_subset_length(tvb, offset, mqtt_payload_len); | |||
| 1288 | char *sub_data = wmem_strdup(pinfo->pool, (const char*)topic_str); | |||
| 1289 | (void) dissector_try_heuristic(mqtt_topic_subdissector, msg_tvb, pinfo, tree, &hdtbl_entry, sub_data); | |||
| 1290 | } | |||
| 1291 | break; | |||
| 1292 | ||||
| 1293 | case MQTT_SUBSCRIBE8: | |||
| 1294 | /* After the Message Id field is found, the following fields must appear | |||
| 1295 | * at least once: | |||
| 1296 | * |TopicName|QoS| | |||
| 1297 | */ | |||
| 1298 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_msgid); | |||
| 1299 | offset += 2; | |||
| 1300 | col_append_fstr(pinfo->cinfo, COL_INFO, " (id=%u)", mqtt_msgid); | |||
| 1301 | ||||
| 1302 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1303 | { | |||
| 1304 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1305 | } | |||
| 1306 | ||||
| 1307 | while (offset < tvb_reported_length(tvb)) | |||
| 1308 | { | |||
| 1309 | ti = proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_topic_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1310 | offset += 2; | |||
| 1311 | ||||
| 1312 | if (mqtt_str_len > 0) | |||
| 1313 | { | |||
| 1314 | proto_tree_add_item_ret_string(mqtt_tree, hf_mqtt_topic, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002|ENC_NA0x00000000, | |||
| 1315 | pinfo->pool, (const uint8_t**)&topic_str); | |||
| 1316 | offset += mqtt_str_len; | |||
| 1317 | } | |||
| 1318 | else | |||
| 1319 | { | |||
| 1320 | expert_add_info(pinfo, ti, &ei_illegal_length); | |||
| 1321 | } | |||
| 1322 | ||||
| 1323 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", topic_str); | |||
| 1324 | ||||
| 1325 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1326 | { | |||
| 1327 | proto_tree_add_bitmask(mqtt_tree, tvb, offset, hf_mqtt_subscription_options, | |||
| 1328 | ett_mqtt_subscription_flags, v50_subscription_flags, ENC_BIG_ENDIAN0x00000000); | |||
| 1329 | } | |||
| 1330 | else | |||
| 1331 | { | |||
| 1332 | proto_tree_add_item(mqtt_tree, hf_mqtt_sub_qos, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 1333 | } | |||
| 1334 | offset += 1; | |||
| 1335 | } | |||
| 1336 | break; | |||
| 1337 | ||||
| 1338 | case MQTT_UNSUBSCRIBE10: | |||
| 1339 | /* After the Message Id field is found, the following fields must appear | |||
| 1340 | * at least once: | |||
| 1341 | * |TopicName| | |||
| 1342 | */ | |||
| 1343 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_msgid); | |||
| 1344 | offset += 2; | |||
| 1345 | col_append_fstr(pinfo->cinfo, COL_INFO, " (id=%u)", mqtt_msgid); | |||
| 1346 | ||||
| 1347 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1348 | { | |||
| 1349 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1350 | } | |||
| 1351 | ||||
| 1352 | while (offset < tvb_reported_length(tvb)) | |||
| 1353 | { | |||
| 1354 | ti = proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_topic_len, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_str_len); | |||
| 1355 | offset += 2; | |||
| 1356 | ||||
| 1357 | if (mqtt_str_len > 0) | |||
| 1358 | { | |||
| 1359 | proto_tree_add_item(mqtt_tree, hf_mqtt_topic, tvb, offset, mqtt_str_len, ENC_UTF_80x00000002); | |||
| 1360 | offset += mqtt_str_len; | |||
| 1361 | } | |||
| 1362 | else | |||
| 1363 | { | |||
| 1364 | expert_add_info(pinfo, ti, &ei_illegal_length); | |||
| 1365 | } | |||
| 1366 | } | |||
| 1367 | break; | |||
| 1368 | ||||
| 1369 | case MQTT_SUBACK9: | |||
| 1370 | /* The SUBACK message contains a list of granted QoS levels that come | |||
| 1371 | * after the Message Id field. The size of each QoS entry is 1 byte. | |||
| 1372 | */ | |||
| 1373 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_msgid); | |||
| 1374 | offset += 2; | |||
| 1375 | col_append_fstr(pinfo->cinfo, COL_INFO, " (id=%u)", mqtt_msgid); | |||
| 1376 | ||||
| 1377 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1378 | { | |||
| 1379 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1380 | } | |||
| 1381 | ||||
| 1382 | while (offset < tvb_reported_length(tvb)) | |||
| 1383 | { | |||
| 1384 | if ((mqtt->runtime_proto_version == MQTT_PROTO_V313) || | |||
| 1385 | (mqtt->runtime_proto_version == MQTT_PROTO_V3114)) | |||
| 1386 | { | |||
| 1387 | proto_tree_add_item(mqtt_tree, hf_mqtt_suback_qos, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000); | |||
| 1388 | } | |||
| 1389 | else | |||
| 1390 | { | |||
| 1391 | dissect_mqtt_reason_code(mqtt_tree, tvb, offset, mqtt_msg_type); | |||
| 1392 | } | |||
| 1393 | offset += 1; | |||
| 1394 | } | |||
| 1395 | break; | |||
| 1396 | ||||
| 1397 | case MQTT_PUBACK4: | |||
| 1398 | case MQTT_PUBREC5: | |||
| 1399 | case MQTT_PUBREL6: | |||
| 1400 | case MQTT_PUBCOMP7: | |||
| 1401 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_msgid); | |||
| 1402 | offset += 2; | |||
| 1403 | col_append_fstr(pinfo->cinfo, COL_INFO, " (id=%u)", mqtt_msgid); | |||
| 1404 | ||||
| 1405 | /* MQTT v5.0: The Reason Code and Property Length can be omitted if the | |||
| 1406 | * Reason Code is 0x00 and there are no Properties. | |||
| 1407 | * In this case, the PUB* has a Remaining Length of 2. | |||
| 1408 | */ | |||
| 1409 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505 && mqtt_msg_len > 2) | |||
| 1410 | { | |||
| 1411 | dissect_mqtt_reason_code(mqtt_tree, tvb, offset, mqtt_msg_type); | |||
| 1412 | offset += 1; | |||
| 1413 | ||||
| 1414 | /* If the Remaining Length is less than 4, the Property Length is not | |||
| 1415 | * present and has a value of 0. | |||
| 1416 | */ | |||
| 1417 | if (mqtt_msg_len > 3) | |||
| 1418 | { | |||
| 1419 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1420 | } | |||
| 1421 | } | |||
| 1422 | break; | |||
| 1423 | ||||
| 1424 | case MQTT_UNSUBACK11: | |||
| 1425 | proto_tree_add_item_ret_uint(mqtt_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000, &mqtt_msgid); | |||
| 1426 | offset += 2; | |||
| 1427 | col_append_fstr(pinfo->cinfo, COL_INFO, " (id=%u)", mqtt_msgid); | |||
| 1428 | ||||
| 1429 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505) | |||
| 1430 | { | |||
| 1431 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1432 | ||||
| 1433 | while (offset < tvb_reported_length(tvb)) | |||
| 1434 | { | |||
| 1435 | dissect_mqtt_reason_code(mqtt_tree, tvb, offset, mqtt_msg_type); | |||
| 1436 | offset += 1; | |||
| 1437 | } | |||
| 1438 | } | |||
| 1439 | break; | |||
| 1440 | ||||
| 1441 | /* The following messages don't have variable header */ | |||
| 1442 | case MQTT_PINGREQ12: | |||
| 1443 | case MQTT_PINGRESP13: | |||
| 1444 | break; | |||
| 1445 | ||||
| 1446 | case MQTT_DISCONNECT14: | |||
| 1447 | /* MQTT v5.0: Byte 1 in the Variable Header is the Disconnect Reason Code. | |||
| 1448 | * If the Remaining Length is less than 1 the value of 0x00 | |||
| 1449 | * (Normal disconnection) is used. | |||
| 1450 | */ | |||
| 1451 | /* FALLTHROUGH */ | |||
| 1452 | case MQTT_AUTH15: | |||
| 1453 | /* MQTT v5.0: The Reason Code and Property Length can be omitted if | |||
| 1454 | * the Reason Code is 0x00 (Success) and there are no Properties. | |||
| 1455 | * In this case the AUTH has a Remaining Length of 0. | |||
| 1456 | */ | |||
| 1457 | if (mqtt->runtime_proto_version == MQTT_PROTO_V505 && mqtt_msg_len > 0) | |||
| 1458 | { | |||
| 1459 | dissect_mqtt_reason_code(mqtt_tree, tvb, offset, mqtt_msg_type); | |||
| 1460 | offset += 1; | |||
| 1461 | ||||
| 1462 | /* 3.14.2.2 DISCONNECT Properties: | |||
| 1463 | * If the Remaining Length is less than 2, a value of 0 is used. | |||
| 1464 | * Let's assume that it also applies to AUTH, why? DISCONNECT and AUTH | |||
| 1465 | * share the same structure with no payload. | |||
| 1466 | */ | |||
| 1467 | if (mqtt_msg_len >= 2) | |||
| 1468 | { | |||
| 1469 | offset += dissect_mqtt_properties(tvb, pinfo, mqtt_tree, offset, hf_mqtt_property, &mqtt_properties); | |||
| 1470 | } | |||
| 1471 | } | |||
| 1472 | break; | |||
| 1473 | } | |||
| 1474 | ||||
| 1475 | return offset; | |||
| 1476 | } | |||
| 1477 | ||||
| 1478 | /** | |||
| 1479 | "The minimum size of MQTT Packet is 2 bytes(Ping Req, Ping Rsp, | |||
| 1480 | Disconnect), and the maximum size is 256MB. Hence minimum fixed | |||
| 1481 | length should be 2 bytes for tcp_dissect_pdu. | |||
| 1482 | ||||
| 1483 | If the length field is spread across two TCP segments, then we have a | |||
| 1484 | problem, because exception will be raised. So long as MQTT length | |||
| 1485 | field(although spread over 4 bytes) is present within single TCP | |||
| 1486 | segment we shouldn't have any issue by calling tcp_dissect_pdu with | |||
| 1487 | minimum length set to 2." | |||
| 1488 | ||||
| 1489 | XXX: ToDo: Commit a fix for the case of the length field spread across TCP segments. | |||
| 1490 | **/ | |||
| 1491 | ||||
| 1492 | static int dissect_mqtt_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) | |||
| 1493 | { | |||
| 1494 | col_clear(pinfo->cinfo, COL_INFO); | |||
| 1495 | ||||
| 1496 | tcp_dissect_pdus(tvb, pinfo, tree, | |||
| 1497 | reassemble_mqtt_over_tcp, | |||
| 1498 | 2, /* Length can be determined within 5 bytes */ | |||
| 1499 | get_mqtt_pdu_len, | |||
| 1500 | dissect_mqtt, data); | |||
| 1501 | ||||
| 1502 | return tvb_captured_length(tvb); | |||
| 1503 | } | |||
| 1504 | ||||
| 1505 | /* | |||
| 1506 | * Register the protocol with Wireshark | |||
| 1507 | */ | |||
| 1508 | void proto_register_mqtt(void) | |||
| 1509 | { | |||
| 1510 | static hf_register_info hf_mqtt[] = { | |||
| 1511 | { &hf_mqtt_msg_len, | |||
| 1512 | { "Msg Len", "mqtt.len", | |||
| 1513 | FT_UINT64, BASE_DEC, NULL((void*)0), 0, | |||
| 1514 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1515 | { &hf_mqtt_hdrflags, | |||
| 1516 | { "Header Flags", "mqtt.hdrflags", | |||
| 1517 | FT_UINT8, BASE_HEX, NULL((void*)0), 0, | |||
| 1518 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1519 | { &hf_mqtt_msg_type, | |||
| 1520 | { "Message Type", "mqtt.msgtype", | |||
| 1521 | FT_UINT8, BASE_DEC | BASE_EXT_STRING0x00000200, &mqtt_msgtype_vals_ext, MQTT_MASK_MSG_TYPE0xF0, | |||
| 1522 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1523 | { &hf_mqtt_reserved, | |||
| 1524 | { "Reserved", "mqtt.hdr_reserved", | |||
| 1525 | FT_UINT8, BASE_DEC, NULL((void*)0), MQTT_MASK_HDR_RESERVED0x0F, | |||
| 1526 | "Fixed Header Reserved Field", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1527 | { &hf_mqtt_retain_reserved, | |||
| 1528 | { "Reserved", "mqtt.retain_reserved", | |||
| 1529 | FT_UINT8, BASE_DEC, NULL((void*)0), MQTT_MASK_RETAIN0x01, | |||
| 1530 | "Fixed Header Reserved Field", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1531 | { &hf_mqtt_dup_flag, | |||
| 1532 | { "DUP Flag", "mqtt.dupflag", | |||
| 1533 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_MASK_DUP_FLAG0x08, | |||
| 1534 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1535 | { &hf_mqtt_qos_level, | |||
| 1536 | { "QoS Level", "mqtt.qos", | |||
| 1537 | FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals)((0 ? (const struct _value_string*)0 : ((mqtt_qos_vals)))), MQTT_MASK_QOS0x06, | |||
| 1538 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1539 | { &hf_mqtt_retain, | |||
| 1540 | { "Retain", "mqtt.retain", | |||
| 1541 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_MASK_RETAIN0x01, | |||
| 1542 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1543 | /* Conn-Ack */ | |||
| 1544 | { &hf_mqtt_conack_reserved, | |||
| 1545 | { "Reserved", "mqtt.conack.flags.reserved", | |||
| 1546 | FT_BOOLEAN, BASE_NONE, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), 0, | |||
| 1547 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1548 | { &hf_mqtt_conack_flags, | |||
| 1549 | { "Acknowledge Flags", "mqtt.conack.flags", | |||
| 1550 | FT_UINT8, BASE_HEX, NULL((void*)0), 0, | |||
| 1551 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1552 | { &hf_mqtt_conackflag_reserved, | |||
| 1553 | { "Reserved", "mqtt.conack.flags.reserved", | |||
| 1554 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONACKMASK_RESERVED0xFE, | |||
| 1555 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1556 | { &hf_mqtt_conackflag_sp, | |||
| 1557 | { "Session Present", "mqtt.conack.flags.sp", | |||
| 1558 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONACKMASK_SP0x01, | |||
| 1559 | "Session Present (version 3.1.1)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1560 | { &hf_mqtt_conack_code, | |||
| 1561 | { "Return Code", "mqtt.conack.val", | |||
| 1562 | FT_UINT8, BASE_DEC, VALS(mqtt_conack_vals)((0 ? (const struct _value_string*)0 : ((mqtt_conack_vals)))), 0, | |||
| 1563 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1564 | /* Publish-Ack / Publish-Rec / Publish-Rel / Publish-Comp / Unsubscribe-Ack */ | |||
| 1565 | { &hf_mqtt_msgid, | |||
| 1566 | { "Message Identifier", "mqtt.msgid", | |||
| 1567 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1568 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1569 | { &hf_mqtt_sub_qos, | |||
| 1570 | { "Requested QoS", "mqtt.sub.qos", | |||
| 1571 | FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals)((0 ? (const struct _value_string*)0 : ((mqtt_qos_vals)))), 0, | |||
| 1572 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1573 | { &hf_mqtt_suback_qos, | |||
| 1574 | { "Granted QoS", "mqtt.suback.qos", | |||
| 1575 | FT_UINT8, BASE_DEC, VALS(mqtt_subqos_vals)((0 ? (const struct _value_string*)0 : ((mqtt_subqos_vals)))), 0, | |||
| 1576 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1577 | { &hf_mqtt_topic_len, | |||
| 1578 | { "Topic Length", "mqtt.topic_len", | |||
| 1579 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1580 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1581 | { &hf_mqtt_topic, | |||
| 1582 | { "Topic", "mqtt.topic", | |||
| 1583 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1584 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1585 | { &hf_mqtt_will_topic_len, | |||
| 1586 | { "Will Topic Length", "mqtt.willtopic_len", | |||
| 1587 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1588 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1589 | { &hf_mqtt_will_topic, | |||
| 1590 | { "Will Topic", "mqtt.willtopic", | |||
| 1591 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1592 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1593 | { &hf_mqtt_will_msg, | |||
| 1594 | { "Will Message", "mqtt.willmsg", | |||
| 1595 | FT_BYTES, BASE_NONE, NULL((void*)0), 0, | |||
| 1596 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1597 | { &hf_mqtt_will_msg_text, | |||
| 1598 | { "Will Message", "mqtt.willmsg_text", | |||
| 1599 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1600 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1601 | { &hf_mqtt_will_msg_len, | |||
| 1602 | { "Will Message Length", "mqtt.willmsg_len", | |||
| 1603 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1604 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1605 | { &hf_mqtt_username_len, | |||
| 1606 | { "User Name Length", "mqtt.username_len", | |||
| 1607 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1608 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1609 | { &hf_mqtt_username, | |||
| 1610 | { "User Name", "mqtt.username", | |||
| 1611 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1612 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1613 | { &hf_mqtt_passwd_len, | |||
| 1614 | { "Password Length", "mqtt.passwd_len", | |||
| 1615 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1616 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1617 | { &hf_mqtt_passwd, | |||
| 1618 | { "Password", "mqtt.passwd", | |||
| 1619 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1620 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1621 | { &hf_mqtt_pubmsg, | |||
| 1622 | { "Message", "mqtt.msg", | |||
| 1623 | FT_BYTES, BASE_NONE, NULL((void*)0), 0, | |||
| 1624 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1625 | { &hf_mqtt_pubmsg_text, | |||
| 1626 | { "Message", "mqtt.msg_text", | |||
| 1627 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1628 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1629 | { &hf_mqtt_pubmsg_decoded, | |||
| 1630 | { "Message decoded as", "mqtt.msg_decoded_as", | |||
| 1631 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1632 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1633 | { &hf_mqtt_proto_len, | |||
| 1634 | { "Protocol Name Length", "mqtt.proto_len", | |||
| 1635 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1636 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1637 | { &hf_mqtt_proto_name, | |||
| 1638 | { "Protocol Name", "mqtt.protoname", | |||
| 1639 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1640 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1641 | { &hf_mqtt_client_id_len, | |||
| 1642 | { "Client ID Length", "mqtt.clientid_len", | |||
| 1643 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1644 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1645 | { &hf_mqtt_client_id, | |||
| 1646 | { "Client ID", "mqtt.clientid", | |||
| 1647 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1648 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1649 | { &hf_mqtt_proto_ver, | |||
| 1650 | { "Version", "mqtt.ver", | |||
| 1651 | FT_UINT8, BASE_DEC, VALS(mqtt_protocol_version_vals)((0 ? (const struct _value_string*)0 : ((mqtt_protocol_version_vals )))), 0, | |||
| 1652 | "MQTT version", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1653 | /* Connect Flags */ | |||
| 1654 | { &hf_mqtt_conflags, | |||
| 1655 | { "Connect Flags", "mqtt.conflags", | |||
| 1656 | FT_UINT8, BASE_HEX, NULL((void*)0), 0, | |||
| 1657 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1658 | { &hf_mqtt_conflag_user, | |||
| 1659 | { "User Name Flag", "mqtt.conflag.uname", | |||
| 1660 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONMASK_USER0x80, | |||
| 1661 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1662 | { &hf_mqtt_conflag_passwd, | |||
| 1663 | { "Password Flag", "mqtt.conflag.passwd", | |||
| 1664 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONMASK_PASSWD0x40, | |||
| 1665 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1666 | { &hf_mqtt_conflag_will_retain, | |||
| 1667 | { "Will Retain", "mqtt.conflag.retain", | |||
| 1668 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONMASK_RETAIN0x20, | |||
| 1669 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1670 | { &hf_mqtt_conflag_will_qos, | |||
| 1671 | { "QoS Level", "mqtt.conflag.qos", | |||
| 1672 | FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals)((0 ? (const struct _value_string*)0 : ((mqtt_qos_vals)))), MQTT_CONMASK_QOS0x18, | |||
| 1673 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1674 | { &hf_mqtt_conflag_will_flag, | |||
| 1675 | { "Will Flag", "mqtt.conflag.willflag", | |||
| 1676 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONMASK_WILLFLAG0x04, | |||
| 1677 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1678 | { &hf_mqtt_conflag_clean_sess, | |||
| 1679 | { "Clean Session Flag", "mqtt.conflag.cleansess", | |||
| 1680 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONMASK_CLEANSESS0x02, | |||
| 1681 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1682 | { &hf_mqtt_conflag_reserved, | |||
| 1683 | { "(Reserved)", "mqtt.conflag.reserved", | |||
| 1684 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_CONMASK_RESERVED0x01, | |||
| 1685 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1686 | { &hf_mqtt_keep_alive, | |||
| 1687 | { "Keep Alive", "mqtt.kalive", | |||
| 1688 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1689 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1690 | { &hf_mqtt_subscription_options, | |||
| 1691 | { "Subscription Options", "mqtt.subscription_options", | |||
| 1692 | FT_UINT8, BASE_HEX, NULL((void*)0), 0, | |||
| 1693 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1694 | { &hf_mqtt_subscription_qos, | |||
| 1695 | { "QoS", "mqtt.subscription_options_qos", | |||
| 1696 | FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals)((0 ? (const struct _value_string*)0 : ((mqtt_qos_vals)))), MQTT_MASK_SUBS_QOS0x03, | |||
| 1697 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1698 | { &hf_mqtt_subscription_nl, | |||
| 1699 | { "No Local", "mqtt.subscription_options_nl", | |||
| 1700 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_MASK_SUBS_NL0x04, | |||
| 1701 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1702 | { &hf_mqtt_subscription_rap, | |||
| 1703 | { "Retain As Published", "mqtt.subscription_options_rap", | |||
| 1704 | FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset )))), MQTT_MASK_SUBS_RAP0x08, | |||
| 1705 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1706 | { &hf_mqtt_subscription_retain, | |||
| 1707 | { "Retain Handling", "mqtt.subscription_options_retain", | |||
| 1708 | FT_UINT8, BASE_DEC, VALS(mqtt_subscription_retain_handling)((0 ? (const struct _value_string*)0 : ((mqtt_subscription_retain_handling )))), MQTT_MASK_SUBS_RETAIN0x30, | |||
| 1709 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1710 | { &hf_mqtt_subscription_reserved, | |||
| 1711 | { "Reserved", "mqtt.subscription_options_reserved", | |||
| 1712 | FT_UINT8, BASE_HEX, NULL((void*)0), MQTT_MASK_SUBS_RESERVED0xC0, | |||
| 1713 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1714 | ||||
| 1715 | /* v5.0 Reason Codes */ | |||
| 1716 | { &hf_mqtt_reason_code_connack, | |||
| 1717 | { "Reason Code", "mqtt.connack.reason_code", | |||
| 1718 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_connack_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_connack_vals )))), 0, | |||
| 1719 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1720 | { &hf_mqtt_reason_code_puback, | |||
| 1721 | { "Reason Code", "mqtt.puback.reason_code", | |||
| 1722 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_puback_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_puback_vals )))), 0, | |||
| 1723 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1724 | { &hf_mqtt_reason_code_pubrec, | |||
| 1725 | { "Reason Code", "mqtt.pubrec.reason_code", | |||
| 1726 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_puback_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_puback_vals )))), 0, | |||
| 1727 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1728 | { &hf_mqtt_reason_code_pubrel, | |||
| 1729 | { "Reason Code", "mqtt.pubrel.reason_code", | |||
| 1730 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_pubrel_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_pubrel_vals )))), 0, | |||
| 1731 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1732 | { &hf_mqtt_reason_code_pubcomp, | |||
| 1733 | { "Reason Code", "mqtt.pubcomp.reason_code", | |||
| 1734 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_pubrel_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_pubrel_vals )))), 0, | |||
| 1735 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1736 | { &hf_mqtt_reason_code_suback, | |||
| 1737 | { "Reason Code", "mqtt.suback.reason_code", | |||
| 1738 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_suback_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_suback_vals )))), 0, | |||
| 1739 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1740 | { &hf_mqtt_reason_code_unsuback, | |||
| 1741 | { "Reason Code", "mqtt.unsuback.reason_code", | |||
| 1742 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_unsuback_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_unsuback_vals )))), 0, | |||
| 1743 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1744 | { &hf_mqtt_reason_code_disconnect, | |||
| 1745 | { "Reason Code", "mqtt.disconnect.reason_code", | |||
| 1746 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_disconnect_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_disconnect_vals )))), 0, | |||
| 1747 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1748 | { &hf_mqtt_reason_code_auth, | |||
| 1749 | { "Reason Code", "mqtt.auth.reason_code", | |||
| 1750 | FT_UINT8, BASE_DEC, VALS(mqtt_reason_code_auth_vals)((0 ? (const struct _value_string*)0 : ((mqtt_reason_code_auth_vals )))), 0, | |||
| 1751 | "MQTT Reason Code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1752 | ||||
| 1753 | /* Properties */ | |||
| 1754 | { &hf_mqtt_property, | |||
| 1755 | { "Properties", "mqtt.properties", | |||
| 1756 | FT_NONE, BASE_NONE, NULL((void*)0), 0, | |||
| 1757 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1758 | { &hf_mqtt_will_property, | |||
| 1759 | { "Will Properties", "mqtt.will_properties", | |||
| 1760 | FT_NONE, BASE_NONE, NULL((void*)0), 0, | |||
| 1761 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1762 | { &hf_mqtt_property_len, | |||
| 1763 | { "Total Length", "mqtt.property_len", | |||
| 1764 | FT_UINT64, BASE_DEC, NULL((void*)0), 0, | |||
| 1765 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1766 | { &hf_mqtt_property_id, | |||
| 1767 | { "ID", "mqtt.property_id", | |||
| 1768 | FT_UINT8, BASE_HEX, VALS(mqtt_property_vals)((0 ? (const struct _value_string*)0 : ((mqtt_property_vals)) )), 0, | |||
| 1769 | "Property Id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1770 | { &hf_mqtt_prop_num, | |||
| 1771 | { "Value", "mqtt.prop_number", | |||
| 1772 | FT_UINT32, BASE_DEC, NULL((void*)0), 0, | |||
| 1773 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1774 | { &hf_mqtt_prop_content_type, | |||
| 1775 | { "Content Type", "mqtt.property.content_type", | |||
| 1776 | FT_UINT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1777 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1778 | { &hf_mqtt_prop_max_qos, | |||
| 1779 | { "QoS", "mqtt.property.max_qos", | |||
| 1780 | FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals)((0 ? (const struct _value_string*)0 : ((mqtt_qos_vals)))), 0, | |||
| 1781 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1782 | { &hf_mqtt_prop_topic_alias, | |||
| 1783 | { "Topic Alias", "mqtt.property.topic_alias", | |||
| 1784 | FT_UINT16, BASE_DEC, NULL((void*)0), 0, | |||
| 1785 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1786 | { &hf_mqtt_prop_unknown, | |||
| 1787 | { "Unknown Property", "mqtt.prop_unknown", | |||
| 1788 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1789 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1790 | { &hf_mqtt_prop_string_len, | |||
| 1791 | { "Length", "mqtt.prop_string_len", | |||
| 1792 | FT_UINT32, BASE_DEC, NULL((void*)0), 0, | |||
| 1793 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1794 | { &hf_mqtt_prop_string, | |||
| 1795 | { "Value", "mqtt.prop_string", | |||
| 1796 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1797 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1798 | { &hf_mqtt_prop_key_len, | |||
| 1799 | { "Key Length", "mqtt.prop_key_len", | |||
| 1800 | FT_UINT32, BASE_DEC, NULL((void*)0), 0, | |||
| 1801 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1802 | { &hf_mqtt_prop_key, | |||
| 1803 | { "Key", "mqtt.prop_key", | |||
| 1804 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1805 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1806 | { &hf_mqtt_prop_value_len, | |||
| 1807 | { "Value Length", "mqtt.prop_value_len", | |||
| 1808 | FT_UINT32, BASE_DEC, NULL((void*)0), 0, | |||
| 1809 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1810 | { &hf_mqtt_prop_value, | |||
| 1811 | { "Value", "mqtt.prop_value", | |||
| 1812 | FT_STRING, BASE_NONE, NULL((void*)0), 0, | |||
| 1813 | NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}, | |||
| 1814 | }; | |||
| 1815 | ||||
| 1816 | /* Setup protocol subtree arrays */ | |||
| 1817 | static int* ett_mqtt[] = { | |||
| 1818 | &ett_mqtt_hdr, | |||
| 1819 | &ett_mqtt_msg, | |||
| 1820 | &ett_mqtt_hdr_flags, | |||
| 1821 | &ett_mqtt_con_flags, | |||
| 1822 | &ett_mqtt_conack_flags, | |||
| 1823 | &ett_mqtt_property, | |||
| 1824 | &ett_mqtt_subscription_flags, | |||
| 1825 | }; | |||
| 1826 | ||||
| 1827 | static ei_register_info ei[] = { | |||
| 1828 | { &ei_illegal_length, | |||
| 1829 | { "mqtt.illegal_topic_length", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Length cannot be 0", 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)}} } }, | |||
| 1830 | { &ei_unknown_version, | |||
| 1831 | { "mqtt.unknown_version", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "Unknown version (missing the CONNECT packet?)", 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)}} } }, | |||
| 1832 | { &ei_unknown_topic_alias, | |||
| 1833 | { "mqtt.unknown_topic_alias", PI_PROTOCOL0x09000000, PI_NOTE0x00400000, "Unknown topic alias", 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)}} } } | |||
| 1834 | }; | |||
| 1835 | ||||
| 1836 | static uat_field_t mqtt_message_decode_flds[] = { | |||
| 1837 | UAT_FLD_VS(message_decode, match_criteria, "Match criteria", match_criteria, "Match criteria"){"match_criteria", "Match criteria", PT_TXTMOD_ENUM,{uat_fld_chk_enum ,message_decode_match_criteria_set_cb,message_decode_match_criteria_tostr_cb },{&(match_criteria),&(match_criteria),&(match_criteria )},&(match_criteria),"Match criteria",((void*)0)}, | |||
| 1838 | UAT_FLD_CSTRING(message_decode, topic_pattern, "Topic pattern", "Pattern to match for the topic"){"topic_pattern", "Topic pattern", PT_TXTMOD_STRING,{uat_fld_chk_str ,message_decode_topic_pattern_set_cb,message_decode_topic_pattern_tostr_cb },{0,0,0},0,"Pattern to match for the topic",((void*)0)}, | |||
| 1839 | UAT_FLD_VS(message_decode, msg_decoding, "Decoding", msg_decoding, "Decode message before dissecting as protocol"){"msg_decoding", "Decoding", PT_TXTMOD_ENUM,{uat_fld_chk_enum ,message_decode_msg_decoding_set_cb,message_decode_msg_decoding_tostr_cb },{&(msg_decoding),&(msg_decoding),&(msg_decoding )},&(msg_decoding),"Decode message before dissecting as protocol" ,((void*)0)}, | |||
| 1840 | UAT_FLD_DISSECTOR(message_decode, payload_proto, "Payload dissector",{"payload_proto", "Payload dissector", PT_TXTMOD_DISSECTOR,{uat_fld_chk_proto ,message_decode_payload_proto_set_cb,message_decode_payload_proto_tostr_cb },{0,0,0},0,"Dissector to be used for the message part of the matching topic" ,((void*)0)} | |||
| 1841 | "Dissector to be used for the message part of the matching topic"){"payload_proto", "Payload dissector", PT_TXTMOD_DISSECTOR,{uat_fld_chk_proto ,message_decode_payload_proto_set_cb,message_decode_payload_proto_tostr_cb },{0,0,0},0,"Dissector to be used for the message part of the matching topic" ,((void*)0)}, | |||
| 1842 | UAT_END_FIELDS{((void*)0),((void*)0),PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,((void *)0)} | |||
| 1843 | }; | |||
| 1844 | ||||
| 1845 | uat_t *message_uat = uat_new("Message Decoding", | |||
| 1846 | sizeof(mqtt_message_decode_t), | |||
| 1847 | "mqtt_message_decoding", | |||
| 1848 | true1, | |||
| 1849 | &mqtt_message_decodes, | |||
| 1850 | &num_mqtt_message_decodes, | |||
| 1851 | UAT_AFFECTS_DISSECTION0x00000001, /* affects dissection of packets, but not set of named fields */ | |||
| 1852 | NULL((void*)0), | |||
| 1853 | mqtt_message_decode_copy_cb, | |||
| 1854 | mqtt_message_decode_update_cb, | |||
| 1855 | mqtt_message_decode_free_cb, | |||
| 1856 | NULL((void*)0), | |||
| 1857 | NULL((void*)0), | |||
| 1858 | mqtt_message_decode_flds); | |||
| 1859 | ||||
| 1860 | module_t *mqtt_module; | |||
| 1861 | expert_module_t* expert_mqtt; | |||
| 1862 | ||||
| 1863 | /* Register protocol names and descriptions */ | |||
| 1864 | proto_mqtt = proto_register_protocol("MQ Telemetry Transport Protocol", "MQTT", "mqtt"); | |||
| 1865 | ||||
| 1866 | /* Register the dissector */ | |||
| 1867 | mqtt_handle = register_dissector("mqtt", dissect_mqtt_data, proto_mqtt); | |||
| 1868 | ||||
| 1869 | proto_register_field_array(proto_mqtt, hf_mqtt, array_length(hf_mqtt)(sizeof (hf_mqtt) / sizeof (hf_mqtt)[0])); | |||
| 1870 | proto_register_subtree_array(ett_mqtt, array_length(ett_mqtt)(sizeof (ett_mqtt) / sizeof (ett_mqtt)[0])); | |||
| 1871 | ||||
| 1872 | mqtt_topic_subdissector = register_heur_dissector_list_with_description("mqtt.topic", "MQTT message topic", proto_mqtt); | |||
| 1873 | ||||
| 1874 | expert_mqtt = expert_register_protocol(proto_mqtt); | |||
| 1875 | expert_register_field_array(expert_mqtt, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0])); | |||
| 1876 | ||||
| 1877 | mqtt_module = prefs_register_protocol(proto_mqtt, NULL((void*)0)); | |||
| 1878 | ||||
| 1879 | prefs_register_uat_preference(mqtt_module, "message_decode_table", | |||
| 1880 | "Message Decoding", | |||
| 1881 | "A table that enumerates custom message decodes to be used for a certain topic", | |||
| 1882 | message_uat); | |||
| 1883 | ||||
| 1884 | prefs_register_enum_preference(mqtt_module, "default_version", | |||
| 1885 | "Default Version", | |||
| 1886 | "Select the MQTT version to use as protocol version if the CONNECT packet is not captured", | |||
| 1887 | &default_protocol_version, mqtt_protocol_version_enumvals, false0); | |||
| 1888 | ||||
| 1889 | prefs_register_bool_preference(mqtt_module, "show_msg_as_text", | |||
| 1890 | "Show Message as text", | |||
| 1891 | "Show Publish Message as text", | |||
| 1892 | &show_msg_as_text); | |||
| 1893 | ||||
| 1894 | } | |||
| 1895 | ||||
| 1896 | /* | |||
| 1897 | * Dissector Handoff | |||
| 1898 | */ | |||
| 1899 | void proto_reg_handoff_mqtt(void) | |||
| 1900 | { | |||
| 1901 | dissector_add_uint_with_preference("tcp.port", MQTT_DEFAULT_PORT1883, mqtt_handle); | |||
| 1902 | ssl_dissector_add(MQTT_SSL_DEFAULT_PORT8883, mqtt_handle); | |||
| 1903 | ||||
| 1904 | media_type_dissector_table = find_dissector_table("media_type"); | |||
| 1905 | dissector_add_string("quic.proto", "mqtt", mqtt_handle); | |||
| 1906 | } | |||
| 1907 | ||||
| 1908 | /* | |||
| 1909 | * Editor modelines - https://www.wireshark.org/tools/modelines.html | |||
| 1910 | * | |||
| 1911 | * Local variables: | |||
| 1912 | * c-basic-offset: 2 | |||
| 1913 | * tab-width: 8 | |||
| 1914 | * indent-tabs-mode: nil | |||
| 1915 | * End: | |||
| 1916 | * | |||
| 1917 | * vi: set shiftwidth=2 tabstop=8 expandtab: | |||
| 1918 | * :indentSize=2:tabSize=8:noTabs=true: | |||
| 1919 | */ |