From 4990a8e4ee1685905e42973b19711a8e3e959836 Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Sun, 6 Apr 2014 16:31:53 -0400 Subject: Added support for MQTT protocol. Bug 9930 Change-Id: I04fc3a6225c56af9905f4f9bbbca5bc10f214843 Reviewed-on: https://code.wireshark.org/review/873 Reviewed-by: Evan Huus Reviewed-by: Michael Mann --- epan/CMakeLists.txt | 1 + epan/dissectors/Makefile.common | 1 + epan/dissectors/packet-mqtt.c | 587 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 589 insertions(+) create mode 100644 epan/dissectors/packet-mqtt.c (limited to 'epan') diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index 34e38b2dbf..4d85d3b211 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -950,6 +950,7 @@ set(DISSECTOR_SRC dissectors/packet-mq-base.c dissectors/packet-mq-pcf.c dissectors/packet-mq.c + dissectors/packet-mqtt.c dissectors/packet-mrcpv2.c dissectors/packet-mrdisc.c dissectors/packet-mrp-mmrp.c diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index a82c4d0bf1..79ea758932 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -870,6 +870,7 @@ DISSECTOR_SRC = \ packet-mq-base.c \ packet-mq-pcf.c \ packet-mq.c \ + packet-mqtt.c \ packet-mrcpv2.c \ packet-mrdisc.c \ packet-mrp-mmrp.c \ diff --git a/epan/dissectors/packet-mqtt.c b/epan/dissectors/packet-mqtt.c new file mode 100644 index 0000000000..0810d298cd --- /dev/null +++ b/epan/dissectors/packet-mqtt.c @@ -0,0 +1,587 @@ +/* packet-mqtt.c + * Routines for MQTT Protocol dissection + * http://mqtt.org + * This dissector dissects, MQTT data transfers as per MQTT V3.1 Protocol Specification + * + * By Lakshmi Narayana Madala + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include "packet-tcp.h" + +#define MQTT_DEFAULT_PORT 1883 +#define MQTT_HDR_SIZE_BEFORE_LEN 1 + +/* MQTT MEssage Types */ +#define MQTT_RESERVED 0 +#define MQTT_CONNECT 1 +#define MQTT_CONNACK 2 +#define MQTT_PUBLISH 3 +#define MQTT_PUBACK 4 +#define MQTT_PUBREC 5 +#define MQTT_PUBREL 6 +#define MQTT_PUBCOMP 7 +#define MQTT_SUBSCRIBE 8 +#define MQTT_SUBACK 9 +#define MQTT_UNSUBSCRIBE 10 +#define MQTT_UNSUBACK 11 +#define MQTT_PINGREQ 12 +#define MQTT_PINGRESP 13 +#define MQTT_DISCONNECT 14 +#define MQTT_RESERVED_15 15 + +/* Flag Values to extract fields */ +#define MQTT_MASK_MSG_TYPE 0xF0 +#define MQTT_MASK_QOS 0x06 +#define MQTT_MASK_DUP_FLAG 0x08 +#define MQTT_MASK_RETAIN 0x01 + +#define MQTT_MASK_SUBQOS 0x03 + +static const value_string mqtt_msgtype_vals[] = { + { MQTT_RESERVED, "Reserved" }, + { MQTT_CONNECT, "Connect Command" }, + { MQTT_CONNACK, "Connect Ack" }, + { MQTT_PUBLISH, "Publish Message" }, + { MQTT_PUBACK, "Publish Ack" }, + { MQTT_PUBREC, "Publish Received" }, + { MQTT_PUBREL, "Publish Release" }, + { MQTT_PUBCOMP, "Publish Complete" }, + { MQTT_SUBSCRIBE, "Subscribe Request" }, + { MQTT_SUBACK, "Subscribe Ack" }, + { MQTT_UNSUBSCRIBE, "Unsubscribe Request" }, + { MQTT_UNSUBACK, "Unsubscribe Ack" }, + { MQTT_PINGREQ, "Ping Request" }, + { MQTT_PINGRESP, "Ping Response" }, + { MQTT_DISCONNECT, "Disconnect Req" }, + { MQTT_RESERVED_15, "Reserved" }, + { 0, NULL } +}; + +#define MQTT_QOS_ATMOST_ONCE 0 +#define MQTT_QOS_ATLEAST_ONCE 1 +#define MQTT_QOS_EXACTLY_ONCE 2 +#define MQTT_QOS_RESERVED 3 + +static const value_string mqtt_qos_vals[] = { + { MQTT_QOS_ATMOST_ONCE, "Fire and Forget" }, + { MQTT_QOS_ATLEAST_ONCE, "Acknowledged deliver" }, + { MQTT_QOS_EXACTLY_ONCE, "Assured Delivery" }, + { MQTT_QOS_RESERVED, "Reserved" }, + { 0, NULL } +}; + +#define MQTT_CON_ACCEPTED 0 +#define MQTT_CON_REFUSED_VERSION_MISMATCH 1 +#define MQTT_CON_REFUSED_ID_REJECTED 2 +#define MQTT_CON_REFUSED_SERVER_UNAVAILABLE 3 +#define MQTT_CON_REFUSED_BAD_USER_PASSWD 4 +#define MQTT_CON_REFUSED_UNAUTHORIZED 5 + +static const value_string mqtt_conack_vals[] = { + { MQTT_CON_ACCEPTED, "Connection Accepted" }, + { MQTT_CON_REFUSED_VERSION_MISMATCH, "Connection Refused: unacceptable protocol version" }, + { MQTT_CON_REFUSED_ID_REJECTED, "Connection Refused: identifier rejected" }, + { MQTT_CON_REFUSED_SERVER_UNAVAILABLE, "Connection Refused: server unavailable" }, + { MQTT_CON_REFUSED_BAD_USER_PASSWD, "Connection Refused: bad user name or password" }, + { MQTT_CON_REFUSED_UNAUTHORIZED, "Connection Refused: not authorized" }, + { 0, NULL } +}; + +#define MQTT_MASK_CONACK 0x00FF /*Only byte2 is used */ + +#define MQTT_CONMASK_FLAGS 0xFE /* Last bit is reserved */ +#define MQTT_CONMASK_USER 0x80 +#define MQTT_CONMASK_PASSWD 0x40 +#define MQTT_CONMASK_RETAIN 0x20 +#define MQTT_CONMASK_QOS 0x18 +#define MQTT_CONMASK_WILLFLAG 0x04 +#define MQTT_CONMASK_CLEANSESS 0x02 + +static dissector_handle_t mqtt_handle; + +/* Initialize the protocol and registered fields */ +static int proto_mqtt = -1; + +/* Message */ +static int hf_mqtt_msg = -1; +static int hf_mqtt_hdrflags = -1; +static int hf_mqtt_msg_len = -1; +static int hf_mqtt_msg_type = -1; +static int hf_mqtt_dup_flag = -1; +static int hf_mqtt_qos_level = -1; +static int hf_mqtt_retain = -1; +static int hf_mqtt_conack = -1; +static int hf_mqtt_msgid = -1; +static int hf_mqtt_subqos = -1; +static int hf_mqtt_topic = -1; +static int hf_mqtt_will_topic = -1; +static int hf_mqtt_will_msg = -1; +static int hf_mqtt_username = -1; +static int hf_mqtt_passwd = -1; +static int hf_mqtt_pubmsg = -1; +static int hf_mqtt_proto_name = -1; +static int hf_mqtt_client_id = -1; +static int hf_mqtt_proto_ver = -1; +static int hf_mqtt_conflags = -1; +static int hf_mqtt_conflag_user = -1; +static int hf_mqtt_conflag_passwd = -1; +static int hf_mqtt_conflag_will_retain = -1; +static int hf_mqtt_conflag_will_qos = -1; +static int hf_mqtt_conflag_will_flag = -1; +static int hf_mqtt_conflag_clean_sess = -1; +static int hf_mqtt_keep_alive = -1; + +/* Initialize the subtree pointers */ +static gint ett_mqtt_hdr = -1; +static gint ett_mqtt_msg = -1; +static gint ett_mqtt_hdr_flags = -1; +static gint ett_mqtt_con_flags = -1; + +/* Reassemble SMPP TCP segments */ +static gboolean reassemble_mqtt_over_tcp = TRUE; + +#define GET_MQTT_PDU_LEN(msg_len, len_offset) (msg_len + len_offset + MQTT_HDR_SIZE_BEFORE_LEN) + +static guint get_mqtt_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset) +{ + guint64 msg_len; + guint len_offset; + + len_offset = dissect_uleb128(tvb, (offset + MQTT_HDR_SIZE_BEFORE_LEN), &msg_len); + + /* Explicitly Downcast the value, because the length can never be more than 4 bytes */ + return (guint)(GET_MQTT_PDU_LEN(msg_len, len_offset)); +} + +/* Dissect the MQTT message */ +static int dissect_mqtt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ti = NULL; + proto_item *ti_mqtt = NULL; + + proto_tree *mqtt_tree = NULL; + proto_tree *mqtt_msg_tree = NULL; + proto_tree *mqtt_flag_tree = NULL; + + guint8 mqtt_fixed_hdr = 0; + guint8 mqtt_con_flags = 0; + guint8 mqtt_msg_type = 0; + guint64 msg_len = 0; + gint mqtt_msg_len = 0; + guint16 mqtt_str_len = 0; + guint16 mqtt_len_offset = 0; + + int offset = 0; + + /* Extract the message ID */ + mqtt_fixed_hdr = tvb_get_guint8(tvb, offset); + mqtt_msg_type = mqtt_fixed_hdr >> 4; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "MQTT"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + col_add_fstr(pinfo->cinfo, COL_INFO, " %s", val_to_str(mqtt_msg_type, mqtt_msgtype_vals, "Unknown (0x%02x)")); + + if(tree) + { + /* Add MQTT Branch to the main tree */ + ti = proto_tree_add_item(tree, proto_mqtt, tvb, 0, -1, ENC_NA); + mqtt_tree = proto_item_add_subtree(ti, ett_mqtt_hdr); + + mqtt_len_offset = dissect_uleb128(tvb, (offset + MQTT_HDR_SIZE_BEFORE_LEN), &msg_len); + + /* Explicit downcast, Typically maximum length of message could be 4 bytes */ + mqtt_msg_len = (gint) msg_len; + + /* Start PDU Dissection, Extract the message ID */ + mqtt_fixed_hdr = tvb_get_guint8(tvb, offset); + mqtt_msg_type = mqtt_fixed_hdr >> 4; + + /* Add each MQTT message as a subtree to main Tree */ + ti_mqtt = proto_tree_add_string(mqtt_tree, hf_mqtt_msg, tvb, offset, mqtt_msg_len, mqtt_msgtype_vals[mqtt_msg_type].strptr); + mqtt_msg_tree = proto_item_add_subtree(ti_mqtt, ett_mqtt_msg); + + ti_mqtt = proto_tree_add_uint_format_value(mqtt_msg_tree, hf_mqtt_hdrflags, tvb, offset, 1, mqtt_fixed_hdr, "0x%02x (%s)", + mqtt_fixed_hdr, val_to_str(mqtt_msg_type, mqtt_msgtype_vals, "Unknown (0x%02x)") ); + mqtt_flag_tree = proto_item_add_subtree(ti_mqtt, ett_mqtt_hdr_flags); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_msg_type, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_dup_flag, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_qos_level, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_retain, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + /* Add MQTT message length */ + proto_tree_add_uint64(mqtt_msg_tree, hf_mqtt_msg_len, tvb, offset, mqtt_len_offset, msg_len); + offset +=mqtt_len_offset; + + switch(mqtt_msg_type) + { + case MQTT_CONNECT: + /* TopicLen|Topic|MsgID|Message| */ + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_proto_name, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_proto_ver, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + mqtt_msg_len--; + + /* Create a new subtree for flags, and add all items under this tree */ + mqtt_con_flags = tvb_get_guint8(tvb, offset); + ti_mqtt = proto_tree_add_item(mqtt_msg_tree, hf_mqtt_conflags, tvb, offset, 1, ENC_BIG_ENDIAN); + mqtt_flag_tree = proto_item_add_subtree(ti_mqtt, ett_mqtt_con_flags); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_conflag_user, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_conflag_passwd, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_conflag_will_retain, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_conflag_will_qos, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_conflag_will_flag, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(mqtt_flag_tree, hf_mqtt_conflag_clean_sess, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + mqtt_msg_len--; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_keep_alive, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + mqtt_msg_len-=2; + + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_client_id, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + + if(mqtt_con_flags & MQTT_CONMASK_WILLFLAG) + { + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_will_topic, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + } + if(mqtt_con_flags & MQTT_CONMASK_WILLFLAG) + { + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_will_msg, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + } + if((mqtt_con_flags & MQTT_CONMASK_USER) && (tvb_reported_length_remaining(tvb, offset) > 0) ) + { + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_username, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + } + if((mqtt_con_flags & MQTT_CONMASK_PASSWD) && (tvb_reported_length_remaining(tvb, offset) > 0)) + { + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_passwd, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + /* offset += mqtt_str_len; */ + /* mqtt_msg_len -= mqtt_str_len; */ + } + break; + + case MQTT_CONNACK: + /* Connection Ack contains only Return Code */ + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_conack, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + + case MQTT_PUBLISH: + /* TopicLen|Topic|MsgID|Message| */ + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_topic, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + + /* Message ID is included only when QOS > 0 */ + if(mqtt_fixed_hdr & MQTT_MASK_QOS) + { + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset +=2; + mqtt_msg_len -=2; + } + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_pubmsg, tvb, offset, mqtt_msg_len, ENC_UTF_8|ENC_NA); + break; + + case MQTT_SUBSCRIBE: + /* Message Id followed by series of following elements + * |Length|Topic|QOS| + */ + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + for( mqtt_msg_len -=2;mqtt_msg_len >0;) + { + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_topic, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_subqos, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + mqtt_msg_len--; + } + break; + + case MQTT_UNSUBSCRIBE: + /* Message Id followed by series of following elements + * |Length|Topic| + */ + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + for( mqtt_msg_len -=2;mqtt_msg_len >0;) + { + mqtt_str_len = tvb_get_ntohs(tvb, offset); + offset +=2; + mqtt_msg_len -= 2; + + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_topic, tvb, offset, mqtt_str_len, ENC_UTF_8|ENC_NA); + offset += mqtt_str_len; + mqtt_msg_len -= mqtt_str_len; + } + break; + + case MQTT_SUBACK: + /* Message Id followed by a + * A vector of QOS information is left in the payload + * size of QOS filed is 1 byte + */ + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset+=2; + for( mqtt_msg_len -=2; mqtt_msg_len >0 ;mqtt_msg_len--) + { + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_subqos, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + } + break; + + /* The following response code contains only msg-id */ + case MQTT_PUBACK: + case MQTT_PUBREC: + case MQTT_PUBREL: + case MQTT_PUBCOMP: + case MQTT_UNSUBACK: + proto_tree_add_item(mqtt_msg_tree, hf_mqtt_msgid, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + + /* The following messages don't have variable header */ + case MQTT_PINGREQ: + case MQTT_PINGRESP: + case MQTT_DISCONNECT: + break; + } + } + return tvb_captured_length(tvb); +} + +static int dissect_mqtt_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + tcp_dissect_pdus(tvb, pinfo, tree, + reassemble_mqtt_over_tcp, + 5, /* Length can be determined within 5 bytes */ + get_mqtt_pdu_len, + dissect_mqtt, data); + + return tvb_captured_length(tvb); +} + +/* + * Register the protocol with Wireshark + */ +void proto_register_mqtt(void) +{ + static hf_register_info hf_mqtt[] = { + { &hf_mqtt_msg, + { "MQTT", "mqtt", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_msg_len, + { "Msg Len", "mqtt.len", + FT_UINT64, BASE_DEC, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_hdrflags, + { "Header Flags", "mqtt.hdrflags", + FT_UINT8, BASE_HEX, NULL, 0xFF, + NULL, HFILL }}, + { &hf_mqtt_msg_type, + { "Message Type", "mqtt.msgtype", + FT_UINT8, BASE_DEC, VALS(mqtt_msgtype_vals), MQTT_MASK_MSG_TYPE, + NULL, HFILL }}, + { &hf_mqtt_dup_flag, + { "DUP Flag", "mqtt.dupflag", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_MASK_DUP_FLAG, + NULL, HFILL }}, + { &hf_mqtt_qos_level, + { "QOS Level", "mqtt.qos", + FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals), MQTT_MASK_QOS, + NULL, HFILL }}, + { &hf_mqtt_retain, + { "Retain", "mqtt.retain", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_MASK_RETAIN, + NULL, HFILL }}, + /* Conn-Ack */ + { &hf_mqtt_conack, + { "Connection Ack", "mqtt.conack.val", + FT_UINT16, BASE_DEC, VALS(mqtt_conack_vals), MQTT_MASK_CONACK, + NULL, HFILL }}, + /* Publish-Ack / Publish-Rec / Publish-Rel / Publish-Comp / Unsubscribe-Ack */ + { &hf_mqtt_msgid, + { "Message Identifier", "mqtt.msgid", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL }}, + { &hf_mqtt_subqos, + { "Granted Qos", "mqtt.suback.id", + FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals), MQTT_MASK_SUBQOS, + NULL, HFILL }}, + { &hf_mqtt_topic, + { "Topic", "mqtt.topic", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_will_topic, + { "Will Topic", "mqtt.willtopic", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_will_msg, + { "Will Message", "mqtt.willmsg", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_username, + { "User Name", "mqtt.username", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_passwd, + { "Password", "mqtt.passwd", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_pubmsg, + { "Message", "mqtt.msg", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_proto_name, + { "Protocol Name", "mqtt.protoname", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_client_id, + { "Client ID", "mqtt.clientid", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_mqtt_proto_ver, + { "Version", "mqtt.ver", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL }}, + /* Connect Flags */ + { &hf_mqtt_conflags, + { "Connect Flags", "mqtt.conflags", + FT_UINT8, BASE_HEX, NULL, MQTT_CONMASK_FLAGS, + NULL, HFILL }}, + { &hf_mqtt_conflag_user, + { "User Name Flag", "mqtt.conflag.uname", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_CONMASK_USER, + NULL, HFILL }}, + { &hf_mqtt_conflag_passwd, + { "Password Flag", "mqtt.conflag.passwd", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_CONMASK_PASSWD, + NULL, HFILL }}, + { &hf_mqtt_conflag_will_retain, + { "Will Retain", "mqtt.conflag.retain", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_CONMASK_RETAIN, + NULL, HFILL }}, + { &hf_mqtt_conflag_will_qos, + { "QOS Level", "mqtt.conflag.qos", + FT_UINT8, BASE_DEC, VALS(mqtt_qos_vals), MQTT_CONMASK_QOS, + NULL, HFILL }}, + { &hf_mqtt_conflag_will_flag, + { "Will Flag", "mqtt.conflag.willflag", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_CONMASK_WILLFLAG, + NULL, HFILL }}, + { &hf_mqtt_conflag_clean_sess, + { "Clean Session Flag", "mqtt.conflag.cleansess", + FT_BOOLEAN, 8, TFS(&tfs_set_notset), MQTT_CONMASK_CLEANSESS, + NULL, HFILL }}, + { &hf_mqtt_keep_alive, + { "Keep Alive", "mqtt.kalive", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL }} + }; + + /* Setup protocol subtree arrays */ + static gint* ett_mqtt[] = { + &ett_mqtt_hdr, + &ett_mqtt_msg, + &ett_mqtt_hdr_flags, + &ett_mqtt_con_flags + }; + + /* Register protocol names and descriptions */ + proto_mqtt = proto_register_protocol("MQ Telemetry Transport Protocol", "MQTT", "mqtt"); + + /* Register the dissector */ + mqtt_handle = new_register_dissector("mqtt", dissect_mqtt_data, proto_mqtt); + + proto_register_field_array(proto_mqtt, hf_mqtt, array_length(hf_mqtt)); + proto_register_subtree_array(ett_mqtt, array_length(ett_mqtt)); +} + +/* + * Dissector Handoff + */ +void proto_reg_handoff_mqtt(void) +{ + dissector_add_handle("tcp.port", mqtt_handle); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 2 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=2 tabstop=2 expandtab: + * :indentSize=2:tabSize=2:noTabs=true: + */ -- cgit v1.2.3