summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--epan/dissectors/packet-dcerpc-netlogon.c15
-rw-r--r--epan/dissectors/packet-ositp.c77
-rw-r--r--epan/dissectors/packet-rdp.c378
-rw-r--r--epan/proto.c225
-rw-r--r--epan/proto.h88
5 files changed, 616 insertions, 167 deletions
diff --git a/epan/dissectors/packet-dcerpc-netlogon.c b/epan/dissectors/packet-dcerpc-netlogon.c
index 4ba49b5720..bf94f802bf 100644
--- a/epan/dissectors/packet-dcerpc-netlogon.c
+++ b/epan/dissectors/packet-dcerpc-netlogon.c
@@ -7383,7 +7383,8 @@ static int dissect_secchan_nl_auth_message(tvbuff_t *tvb, int offset,
{
proto_item *item = NULL;
proto_tree *subtree = NULL;
- guint32 messagetype, messageflags;
+ guint32 messagetype;
+ guint64 messageflags;
static const int *flag_fields[] = {
&hf_netlogon_secchan_nl_message_flags_nb_domain,
&hf_netlogon_secchan_nl_message_flags_nb_host,
@@ -7410,10 +7411,14 @@ static int dissect_secchan_nl_auth_message(tvbuff_t *tvb, int offset,
hf_netlogon_secchan_nl_message_type, &messagetype);
/* Flags */
- proto_tree_add_bitmask(subtree, tvb, offset, hf_netlogon_secchan_nl_message_flags, ett_secchan_nl_auth_message_flags, flag_fields, (drep[0] & DREP_LITTLE_ENDIAN));
- messageflags = ((drep[0] & DREP_LITTLE_ENDIAN)
- ? tvb_get_letohl (tvb, offset)
- : tvb_get_ntohl (tvb, offset));
+ proto_tree_add_bitmask_ret_uint64(subtree, tvb, offset,
+ hf_netlogon_secchan_nl_message_flags,
+ ett_secchan_nl_auth_message_flags,
+ flag_fields,
+ (drep[0] & DREP_LITTLE_ENDIAN) ?
+ ENC_LITTLE_ENDIAN :
+ ENC_BIG_ENDIAN,
+ &messageflags);
offset += 4;
diff --git a/epan/dissectors/packet-ositp.c b/epan/dissectors/packet-ositp.c
index 47f3851883..72f05db85f 100644
--- a/epan/dissectors/packet-ositp.c
+++ b/epan/dissectors/packet-ositp.c
@@ -146,6 +146,8 @@ static const fragment_items cotp_frag_items = {
"segments"
};
+static dissector_handle_t rdp_cr_handle;
+static dissector_handle_t rdp_cc_handle;
static dissector_handle_t data_handle;
/*
@@ -325,6 +327,10 @@ static int hf_cotp_vp_dst_tsap_bytes = -1;
/* global variables */
+/* List of dissectors to call for the variable part of CR PDUs. */
+static heur_dissector_list_t cotp_cr_heur_subdissector_list;
+/* List of dissectors to call for the variable part of CC PDUs. */
+static heur_dissector_list_t cotp_cc_heur_subdissector_list;
/* List of dissectors to call for COTP packets put atop the Inactive
Subset of CLNP. */
static heur_dissector_list_t cotp_is_heur_subdissector_list;
@@ -1496,10 +1502,10 @@ static int ositp_decode_RJ(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
} /* ositp_decode_RJ */
-static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
- packet_info *pinfo, proto_tree *tree,
- gboolean uses_inactive_subset,
- gboolean *subdissector_found)
+static int ositp_decode_CR_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
+ packet_info *pinfo, proto_tree *tree,
+ gboolean uses_inactive_subset,
+ gboolean *subdissector_found)
{
/* note: in the ATN the user is up to chose between 3 different checksums:
* standard OSI, 2 or 4 octet extended checksum.
@@ -1567,37 +1573,33 @@ static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
offset += 1;
li -= 1;
- /* Microsoft runs their Remote Desktop Protocol atop ISO COTP
- atop TPKT, and does some weird stuff in the CR packet:
-
- http://msdn.microsoft.com/en-us/library/cc240470
-
- where they might stuff a string that begins with "Cookie: ",
- possibly followed by an RDP Negotiation Request, into the
- variable part of the CR packet. (See also
-
- http://download.microsoft.com/download/5/B/C/5BC37A4E-6304-45AB-8C2D-AE712526E7F7/TS_Session_Directory.pdf
-
- a/k/a "[MSFT-SDLBTS]", as linked to, under the name "Session
- Directory and Load Balancing Using Terminal Server", on
-
- http://msdn.microsoft.com/en-us/library/E4BD6494-06AD-4aed-9823-445E921C9624
-
- which indicates that the routingToken is a string of the form
- "Cookie: msts=...".)
+ if (li > 0) {
+ /* There's more data left, so we have the variable part.
- They also may stuff an RDP Negotiation Response into the CC
- packet.
+ Microsoft's RDP hijacks the variable part of CR and CC PDUs
+ for their own user data (RDP runs atop Class 0, which doesn't
+ support user data).
- XXX - have TPKT know that a given session is an RDP session,
- and let us know, so we know whether to check for this stuff. */
- ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len , pinfo,
- cotp_tree);
- offset += li;
+ Try what heuristic dissectors we have. */
+ next_tvb = tvb_new_subset_length(tvb, offset, li);
+ if (dissector_try_heuristic((tpdu == CR_TPDU) ?
+ cotp_cr_heur_subdissector_list :
+ cotp_cc_heur_subdissector_list,
+ next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
+ /* A subdissector claimed this, so it really belongs to them. */
+ *subdissector_found = TRUE;
+ } else {
+ /* No heuristic dissector claimed it, so dissect it as a regular
+ variable part. */
+ ositp_decode_var_part(tvb, offset, li, class_option, tpdu_len, pinfo,
+ cotp_tree);
+ }
+ offset += li;
+ }
/*
- * XXX - tell the subdissector that this is user data in a CC or
- * CR packet rather than a DT packet?
+ * XXX - tell the subdissector that this is user data in a CR or
+ * CC packet rather than a DT packet?
*/
next_tvb = tvb_new_subset_remaining(tvb, offset);
if (!uses_inactive_subset){
@@ -1615,7 +1617,7 @@ static int ositp_decode_CC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
return offset;
-} /* ositp_decode_CC */
+} /* ositp_decode_CR_CC */
static int ositp_decode_DC(tvbuff_t *tvb, int offset, guint8 li, guint8 tpdu,
packet_info *pinfo, proto_tree *tree)
@@ -2138,8 +2140,8 @@ static gint dissect_ositp_internal(tvbuff_t *tvb, packet_info *pinfo,
switch (tpdu) {
case CC_TPDU :
case CR_TPDU :
- new_offset = ositp_decode_CC(tvb, offset, li, tpdu, pinfo, tree,
- uses_inactive_subset, &subdissector_found);
+ new_offset = ositp_decode_CR_CC(tvb, offset, li, tpdu, pinfo, tree,
+ uses_inactive_subset, &subdissector_found);
break;
case DR_TPDU :
new_offset = ositp_decode_DR(tvb, offset, li, tpdu, pinfo, tree);
@@ -2420,6 +2422,10 @@ void proto_register_cotp(void)
"transport PDUs\" in the CLNP protocol "
"settings.", &cotp_decode_atn);
+ /* For handling protocols hijacking the variable part of CR or CC PDUs */
+ cotp_cr_heur_subdissector_list = register_heur_dissector_list("cotp_cr");
+ cotp_cc_heur_subdissector_list = register_heur_dissector_list("cotp_cc");
+
/* subdissector code in inactive subset */
cotp_is_heur_subdissector_list = register_heur_dissector_list("cotp_is");
@@ -2464,6 +2470,8 @@ proto_reg_handoff_cotp(void)
dissector_add_uint("ip.proto", IP_PROTO_TP, ositp_handle);
data_handle = find_dissector("data");
+ rdp_cr_handle = find_dissector("rdp_cr");
+ rdp_cc_handle = find_dissector("rdp_cc");
proto_clnp = proto_get_id_by_filter_name("clnp");
}
@@ -2480,4 +2488,3 @@ proto_reg_handoff_cotp(void)
* vi: set shiftwidth=2 tabstop=8 expandtab:
* :indentSize=2:tabSize=8:noTabs=true:
*/
-
diff --git a/epan/dissectors/packet-rdp.c b/epan/dissectors/packet-rdp.c
index 4ca94747ca..92d4c5f7bd 100644
--- a/epan/dissectors/packet-rdp.c
+++ b/epan/dissectors/packet-rdp.c
@@ -22,7 +22,7 @@
*/
/*
- * See: "[MS -RDPBCGR] Remote Desktop Protocol: Basic Connectivity and Graphics Remoting"
+ * See: "[MS-RDPBCGR] Remote Desktop Protocol: Basic Connectivity and Graphics Remoting"
*/
#include "config.h"
@@ -31,6 +31,7 @@
#include <epan/prefs.h>
#include <epan/conversation.h>
#include <epan/asn1.h>
+#include <epan/expert.h>
#include "packet-ssl.h"
#include "packet-t124.h"
@@ -49,6 +50,13 @@ static void prefs_register_rdp(void);
static int proto_rdp = -1;
static int ett_rdp = -1;
+
+static int ett_negReq_flags = -1;
+static int ett_requestedProtocols = -1;
+
+static int ett_negRsp_flags = -1;
+static int ett_selectedProtocol = -1;
+
static int ett_rdp_SendData = -1;
static int ett_rdp_ClientData = -1;
@@ -88,6 +96,32 @@ static int ett_rdp_StandardDate = -1;
static int ett_rdp_DaylightDate = -1;
static int ett_rdp_clientTimeZone = -1;
+static expert_field ei_rdp_neg_len_invalid = EI_INIT;
+static expert_field ei_rdp_not_correlation_info = EI_INIT;
+
+static int hf_rdp_rt_cookie = -1;
+static int hf_rdp_neg_type = -1;
+static int hf_rdp_negReq_flags = -1;
+static int hf_rdp_negReq_flag_restricted_admin_mode_req = -1;
+static int hf_rdp_negReq_flag_correlation_info_present = -1;
+static int hf_rdp_neg_length = -1;
+static int hf_rdp_requestedProtocols = -1;
+static int hf_rdp_requestedProtocols_flag_ssl = -1;
+static int hf_rdp_requestedProtocols_flag_hybrid = -1;
+static int hf_rdp_requestedProtocols_flag_hybrid_ex = -1;
+static int hf_rdp_correlationInfo_flags;
+static int hf_rdp_correlationId = -1;
+static int hf_rdp_correlationInfo_reserved = -1;
+static int hf_rdp_negRsp_flags = -1;
+static int hf_rdp_negRsp_flag_extended_client_data_supported = -1;
+static int hf_rdp_negRsp_flag_dynvc_gfx_protocol_supported = -1;
+static int hf_rdp_negRsp_flag_restricted_admin_mode_supported = -1;
+static int hf_rdp_selectedProtocol = -1;
+static int hf_rdp_selectedProtocol_flag_ssl = -1;
+static int hf_rdp_selectedProtocol_flag_hybrid = -1;
+static int hf_rdp_selectedProtocol_flag_hybrid_ex = -1;
+static int hf_rdp_negFailure_failureCode = -1;
+
static int hf_rdp_ClientData = -1;
static int hf_rdp_SendData = -1;
static int hf_rdp_clientCoreData = -1;
@@ -334,6 +368,32 @@ static int hf_rdp_DaylightBias = -1;
static int hf_rdp_unused = -1;
+#define TYPE_RDP_NEG_REQ 0x01
+#define TYPE_RDP_NEG_RSP 0x02
+#define TYPE_RDP_NEG_FAILURE 0x03
+#define TYPE_RDP_CORRELATION_INFO 0x06
+
+static const value_string neg_type_vals[] = {
+ { TYPE_RDP_NEG_REQ, "RDP Negotiation Request" },
+ { TYPE_RDP_NEG_RSP, "RDP Negotiation Response" },
+ { TYPE_RDP_NEG_FAILURE, "RDP Negotiation Failure" },
+ { TYPE_RDP_CORRELATION_INFO, "RDP Correlation Info" },
+ { 0, NULL }
+};
+
+#define RESTRICTED_ADMIN_MODE_REQUIRED 0x01
+#define CORRELATION_INFO_PRESENT 0x08
+
+static const value_string failure_code_vals[] = {
+ { 0x00000001, "TLS required by server" },
+ { 0x00000002, "TLS not allowed by server" },
+ { 0x00000003, "TLS certificate not on server" },
+ { 0x00000004, "Inconsistent flags" },
+ { 0x00000005, "Server requires Enhanced RDP Security with CredSSP" },
+ { 0x00000006, "Server requires Enhanced RDP Security with TLS and certificate-based client authentication" },
+ { 0, NULL }
+};
+
#define CS_CORE 0xC001
#define CS_SECURITY 0xC002
#define CS_NET 0xC003
@@ -1991,12 +2051,314 @@ dissect_rdp_ServerData(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void
return tvb_captured_length(tvb);
}
+/* Dissect extra data in a CR PDU */
+static int
+dissect_rdpCorrelationInfo(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ guint32 type;
+ guint32 length;
+ proto_item *type_item, *length_item;
+
+ type_item = proto_tree_add_item_ret_uint(tree, hf_rdp_neg_type, tvb, offset, 1, ENC_NA, &type);
+ offset += 1;
+ if (type != TYPE_RDP_CORRELATION_INFO) {
+ expert_add_info(pinfo, type_item, &ei_rdp_not_correlation_info);
+ return offset;
+ }
+ proto_tree_add_item(tree, hf_rdp_correlationInfo_flags, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ length_item = proto_tree_add_item_ret_uint(tree, hf_rdp_neg_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ offset += 2;
+ if (length != 36) {
+ expert_add_info_format(pinfo, length_item, &ei_rdp_neg_len_invalid, "RDP Correlation Info length is %u, not 36", length);
+ return offset;
+ }
+ proto_tree_add_item(tree, hf_rdp_correlationId, tvb, offset, 16, ENC_NA);
+ offset += 16;
+ proto_tree_add_item(tree, hf_rdp_correlationInfo_reserved, tvb, offset, 16, ENC_NA);
+ offset += 16;
+ return offset;
+}
+
+static int
+dissect_rdpNegReq(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ guint64 flags;
+ guint32 length;
+ proto_item *length_item;
+ static const int *flag_bits[] = {
+ &hf_rdp_negReq_flag_restricted_admin_mode_req,
+ &hf_rdp_negReq_flag_correlation_info_present,
+ NULL
+ };
+ static const int *requestedProtocols_bits[] = {
+ &hf_rdp_requestedProtocols_flag_ssl,
+ &hf_rdp_requestedProtocols_flag_hybrid,
+ &hf_rdp_requestedProtocols_flag_hybrid_ex,
+ NULL
+ };
+
+ proto_tree_add_item(tree, hf_rdp_neg_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_bitmask_ret_uint64(tree, tvb, offset, hf_rdp_negReq_flags,
+ ett_negReq_flags, flag_bits,
+ ENC_LITTLE_ENDIAN, &flags);
+ offset += 1;
+ length_item = proto_tree_add_item_ret_uint(tree, hf_rdp_neg_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ offset += 2;
+ if (length != 8) {
+ expert_add_info_format(pinfo, length_item, &ei_rdp_neg_len_invalid, "RDP Negotiate Request length is %u, not 8", length);
+ return offset;
+ }
+ proto_tree_add_bitmask(tree, tvb, offset, hf_rdp_requestedProtocols,
+ ett_requestedProtocols, requestedProtocols_bits,
+ ENC_LITTLE_ENDIAN);
+ offset += 4;
+ if (flags & CORRELATION_INFO_PRESENT)
+ offset = dissect_rdpCorrelationInfo(tvb, offset, pinfo, tree);
+ return offset;
+}
+
+static int
+dissect_rdp_cr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
+{
+ int offset = 0;
+ gboolean have_cookie = FALSE;
+ gboolean have_rdpNegRequest = FALSE;
+ proto_item *item;
+ proto_tree *tree;
+ gint linelen, next_offset;
+
+ /*
+ * routingToken or cookie? Both begin with "Cookie: ".
+ */
+ if (tvb_memeql(tvb, offset, "Cookie: ", 8) == 0) {
+ /* Looks like a routing token or cookie */
+ have_cookie = TRUE;
+ } else if (tvb_bytes_exist(tvb, offset, 4) &&
+ tvb_get_guint8(tvb, offset) == TYPE_RDP_NEG_REQ &&
+ tvb_get_letohs(tvb, offset + 2) == 8) {
+ /* Looks like a Negotiate Request (TYPE_RDP_NEG_REQ, length 8) */
+ have_rdpNegRequest = TRUE;
+ }
+ if (!have_cookie && !have_rdpNegRequest) {
+ /* Doesn't look like our data */
+ return 0;
+ }
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ item = proto_tree_add_item(parent_tree, proto_rdp, tvb, 0, -1, ENC_NA);
+ tree = proto_item_add_subtree(item, ett_rdp);
+
+ if (have_cookie) {
+ /* XXX - distinguish between routing token and cookie? */
+ linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, TRUE);
+ proto_tree_add_item(tree, hf_rdp_rt_cookie, tvb, offset, linelen, ENC_ASCII|ENC_NA);
+ offset = (linelen == -1) ? tvb_captured_length(tvb) : next_offset;
+ }
+ /*
+ * rdpNegRequest?
+ */
+ if (tvb_reported_length_remaining(tvb, offset) > 0)
+ offset = dissect_rdpNegReq(tvb, offset, pinfo, tree);
+ return offset; /* returns 0 if nothing was dissected, which is what we want */
+}
+
+/* Dissect extra data in a CC PDU */
+static int
+dissect_rdpNegRsp(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ guint32 length;
+ proto_item *length_item;
+ static const int *flag_bits[] = {
+ &hf_rdp_negRsp_flag_extended_client_data_supported,
+ &hf_rdp_negRsp_flag_dynvc_gfx_protocol_supported,
+ &hf_rdp_negRsp_flag_restricted_admin_mode_supported,
+ NULL
+ };
+ static const int *selectedProtocol_bits[] = {
+ &hf_rdp_selectedProtocol_flag_ssl,
+ &hf_rdp_selectedProtocol_flag_hybrid,
+ &hf_rdp_selectedProtocol_flag_hybrid_ex,
+ NULL
+ };
+
+ proto_tree_add_item(tree, hf_rdp_neg_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_bitmask(tree, tvb, offset, hf_rdp_negRsp_flags,
+ ett_negRsp_flags, flag_bits,
+ ENC_LITTLE_ENDIAN);
+ offset += 1;
+ length_item = proto_tree_add_item_ret_uint(tree, hf_rdp_neg_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ offset += 2;
+ if (length != 8) {
+ expert_add_info_format(pinfo, length_item, &ei_rdp_neg_len_invalid, "RDP Negotiate Response length is %u, not 8", length);
+ return offset;
+ }
+ proto_tree_add_bitmask(tree, tvb, offset, hf_rdp_selectedProtocol,
+ ett_selectedProtocol, selectedProtocol_bits,
+ ENC_LITTLE_ENDIAN);
+ offset += 4;
+ return offset;
+}
+
+static int
+dissect_rdpNegFailure(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree) {
+ guint32 length;
+ proto_item *length_item;
+
+ proto_tree_add_item(tree, hf_rdp_neg_type, tvb, offset, 1, ENC_NA);
+ offset += 1;
+ proto_tree_add_item(tree, hf_rdp_negReq_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
+ offset += 1;
+ length_item = proto_tree_add_item_ret_uint(tree, hf_rdp_neg_length, tvb, offset, 1, ENC_LITTLE_ENDIAN, &length);
+ offset += 2;
+ if (length != 8) {
+ expert_add_info_format(pinfo, length_item, &ei_rdp_neg_len_invalid, "RDP Negotiate Failure length is %u, not 8", length);
+ return offset;
+ }
+ proto_tree_add_item(tree, hf_rdp_negFailure_failureCode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
+ offset += 4;
+ return offset;
+}
+
+static int
+dissect_rdp_cc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
+{
+ int offset = 0;
+ guint8 type;
+ guint16 length;
+ gboolean ours = FALSE;
+ proto_item *item;
+ proto_tree *tree;
+
+ if (tvb_bytes_exist(tvb, offset, 4)) {
+ type = tvb_get_guint8(tvb, offset);
+ length = tvb_get_letohs(tvb, offset + 2);
+ if ((type == TYPE_RDP_NEG_RSP || type == TYPE_RDP_NEG_FAILURE) &&
+ length == 8) {
+ /* Looks like a Negotiate Response (TYPE_RDP_NEG_RSP, length 8)
+ or a Negotaiate Failure (TYPE_RDP_NEG_FAILURE, length 8) */
+ ours = TRUE;
+ }
+ }
+ if (!ours) {
+ /* Doesn't look like our data */
+ return 0;
+ }
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ item = proto_tree_add_item(parent_tree, proto_rdp, tvb, 0, -1, ENC_NA);
+ tree = proto_item_add_subtree(item, ett_rdp);
+
+ switch (type) {
+
+ case TYPE_RDP_NEG_RSP:
+ offset = dissect_rdpNegRsp(tvb, offset, pinfo, tree);
+ break;
+
+ case TYPE_RDP_NEG_FAILURE:
+ offset = dissect_rdpNegFailure(tvb, offset, pinfo, tree);
+ break;
+ }
+ return offset;
+}
+
/*--- proto_register_rdp -------------------------------------------*/
void
proto_register_rdp(void) {
/* List of fields */
static hf_register_info hf[] = {
+ { &hf_rdp_rt_cookie,
+ { "Routing Token/Cookie", "rdp.rt_cookie",
+ FT_STRING, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_neg_type,
+ { "Type", "rdp.neg_type",
+ FT_UINT8, BASE_HEX, VALS(neg_type_vals), 0,
+ NULL, HFILL }},
+ { &hf_rdp_negReq_flags,
+ { "Flags", "rdp.negReq.flags",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_negReq_flag_restricted_admin_mode_req,
+ { "Restricted admin mode required", "rdp.negReq.flags.restricted_admin_mode_req",
+ FT_BOOLEAN, 8, NULL, RESTRICTED_ADMIN_MODE_REQUIRED,
+ NULL, HFILL }},
+ { &hf_rdp_negReq_flag_correlation_info_present,
+ { "Correlation info present", "rdp.negReq.flags.correlation_info_present",
+ FT_BOOLEAN, 8, NULL, CORRELATION_INFO_PRESENT,
+ NULL, HFILL }},
+ { &hf_rdp_neg_length,
+ { "Length", "rdp.neg_length",
+ FT_UINT16, BASE_DEC, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_requestedProtocols,
+ { "requestedProtocols", "rdp.negReq.requestedProtocols",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_requestedProtocols_flag_ssl,
+ { "TLS security supported", "rdp.negReq.requestedProtocols.ssl",
+ FT_BOOLEAN, 32, NULL, 0x00000001,
+ NULL, HFILL }},
+ { &hf_rdp_requestedProtocols_flag_hybrid,
+ { "CredSSP supported", "rdp.negReq.requestedProtocols.hybrid",
+ FT_BOOLEAN, 32, NULL, 0x00000002,
+ NULL, HFILL }},
+ { &hf_rdp_requestedProtocols_flag_hybrid_ex,
+ { "Early User Authorization Result PDU supported", "rdp.negReq.requestedProtocols.hybrid_ex",
+ FT_BOOLEAN, 32, NULL, 0x00000008,
+ NULL, HFILL }},
+ { &hf_rdp_correlationInfo_flags,
+ { "Flags", "rdp.correlationInfo.flags",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_correlationId,
+ { "correlationId", "rdp.correlationInfo.correlationId",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_correlationInfo_reserved,
+ { "Reserved", "rdp.correlationInfo.reserved",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_negRsp_flags,
+ { "Flags", "rdp.negRsp.flags",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_negRsp_flag_extended_client_data_supported,
+ { "Extended Client Data Blocks supported", "rdp.negRsp.flags.extended_client_data_supported",
+ FT_BOOLEAN, 8, NULL, 0x01,
+ NULL, HFILL }},
+ { &hf_rdp_negRsp_flag_dynvc_gfx_protocol_supported,
+ { "Graphics Pipeline Extension Protocol supported", "rdp.negRsp.flags.dynvc_gfx_protocol_supported",
+ FT_BOOLEAN, 8, NULL, 0x02,
+ NULL, HFILL }},
+ { &hf_rdp_negRsp_flag_restricted_admin_mode_supported,
+ { "Restricted admin mode supported", "rdp.negRsp.flags.restricted_admin_mode_supported",
+ FT_BOOLEAN, 8, NULL, 0x08,
+ NULL, HFILL }},
+ { &hf_rdp_selectedProtocol,
+ { "selectedProtocol", "rdp.negReq.selectedProtocol",
+ FT_UINT32, BASE_HEX, NULL, 0,
+ NULL, HFILL }},
+ { &hf_rdp_selectedProtocol_flag_ssl,
+ { "TLS security selected", "rdp.negReq.selectedProtocol.ssl",
+ FT_BOOLEAN, 32, NULL, 0x00000001,
+ NULL, HFILL }},
+ { &hf_rdp_selectedProtocol_flag_hybrid,
+ { "CredSSP selected", "rdp.negReq.selectedProtocol.hybrid",
+ FT_BOOLEAN, 32, NULL, 0x00000002,
+ NULL, HFILL }},
+ { &hf_rdp_selectedProtocol_flag_hybrid_ex,
+ { "Early User Authorization Result PDU selected", "rdp.negReq.selectedProtocol.hybrid_ex",
+ FT_BOOLEAN, 32, NULL, 0x00000008,
+ NULL, HFILL }},
+ { &hf_rdp_negFailure_failureCode,
+ { "failureCode", "rdp.negFailure.failureCode",
+ FT_UINT32, BASE_HEX, VALS(failure_code_vals), 0,
+ NULL, HFILL }},
{ &hf_rdp_ClientData,
{ "ClientData", "rdp.clientData",
FT_NONE, BASE_NONE, NULL, 0,
@@ -2876,6 +3238,10 @@ proto_register_rdp(void) {
/* List of subtrees */
static gint *ett[] = {
&ett_rdp,
+ &ett_negReq_flags,
+ &ett_requestedProtocols,
+ &ett_negRsp_flags,
+ &ett_selectedProtocol,
&ett_rdp_ClientData,
&ett_rdp_ServerData,
&ett_rdp_SendData,
@@ -2913,13 +3279,20 @@ proto_register_rdp(void) {
&ett_rdp_DaylightDate,
&ett_rdp_clientTimeZone,
};
+ static ei_register_info ei[] = {
+ { &ei_rdp_neg_len_invalid, { "rdp.neg_len.invalid", PI_PROTOCOL, PI_ERROR, "Invalid length", EXPFILL }},
+ { &ei_rdp_not_correlation_info, { "rdp.not_correlation_info", PI_PROTOCOL, PI_ERROR, "What follows RDP Negotiation Request is not an RDP Correlation Info", EXPFILL }},
+ };
module_t *rdp_module;
+ expert_module_t* expert_rdp;
/* Register protocol */
proto_rdp = proto_register_protocol(PNAME, PSNAME, PFNAME);
/* Register fields and subtrees */
proto_register_field_array(proto_rdp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+ expert_rdp = expert_register_protocol(proto_rdp);
+ expert_register_field_array(expert_rdp, ei, array_length(ei));
/* register_dissector("rdp", dissect_rdp, proto_rdp); */
@@ -2941,6 +3314,9 @@ proto_reg_handoff_rdp(void)
/* remember the tpkt handler for change in preferences */
tpkt_handle = find_dissector("tpkt");
+ heur_dissector_add("cotp_cr", dissect_rdp_cr, "RDP", "rdp_cr", proto_rdp, HEURISTIC_ENABLE);
+ heur_dissector_add("cotp_cc", dissect_rdp_cc, "RDP", "rdp_cc", proto_rdp, HEURISTIC_ENABLE);
+
prefs_register_rdp();
register_t124_ns_dissector("Duca", dissect_rdp_ClientData, proto_rdp);
diff --git a/epan/proto.c b/epan/proto.c
index 0100c06cba..7c7c4b9891 100644
--- a/epan/proto.c
+++ b/epan/proto.c
@@ -1367,12 +1367,6 @@ get_uint_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const
return value;
}
-/*
- * NOTE: to support code written when proto_tree_add_item() took a
- * gboolean as its last argument, with FALSE meaning "big-endian"
- * and TRUE meaning "little-endian", we treat any non-zero value of
- * "encoding" as meaning "little-endian".
- */
static inline guint64
get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, const guint encoding)
{
@@ -1435,12 +1429,6 @@ get_uint64_value(proto_tree *tree, tvbuff_t *tvb, gint offset, guint length, con
return value;
}
-/*
- * NOTE: to support code written when proto_tree_add_item() took a
- * gboolean as its last argument, with FALSE meaning "big-endian"
- * and TRUE meaning "little-endian", we treat any non-zero value of
- * "encoding" as meaning "little-endian".
- */
static gint32
get_int_value(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, const guint encoding)
{
@@ -8716,71 +8704,25 @@ proto_construct_match_selected_string(field_info *finfo, epan_dissect_t *edt)
return filter;
}
-/* This function is common code for both proto_tree_add_bitmask() and
- * proto_tree_add_bitmask_text() functions.
+/* This function is common code for all proto_tree_add_bitmask... functions.
*/
-/* NOTE: to support code written when proto_tree_add_bitmask() and
- * proto_tree_add_bitmask_text took a
- * gboolean as its last argument, with FALSE meaning "big-endian"
- * and TRUE meaning "little-endian", we treat any non-zero value of
- * "encoding" as meaning "little-endian".
- */
static gboolean
proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
const int len, const gint ett, const int **fields,
- const guint encoding, const int flags,
- gboolean first, gboolean use_parent_tree, gboolean use_value,
+ const int flags, gboolean first,
+ gboolean use_parent_tree,
proto_tree* tree, guint64 value)
{
+ guint bitshift;
guint64 available_bits = 0;
guint64 tmpval;
header_field_info *hf;
- switch (len) {
- case 1:
- if (use_value == FALSE)
- value = tvb_get_guint8(tvb, offset);
- available_bits = 0xFF;
- break;
- case 2:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset);
- available_bits = 0xFFFF;
- break;
- case 3:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letoh24(tvb, offset) : tvb_get_ntoh24(tvb, offset);
- available_bits = 0xFFFFFF;
- break;
- case 4:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset);
- available_bits = 0xFFFFFFFF;
- break;
- case 5:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letoh40(tvb, offset) : tvb_get_ntoh40(tvb, offset);
- available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFF);
- break;
- case 6:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letoh48(tvb, offset) : tvb_get_ntoh48(tvb, offset);
- available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFF);
- break;
- case 7:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letoh56(tvb, offset) : tvb_get_ntoh56(tvb, offset);
- available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFF);
- break;
- case 8:
- if (use_value == FALSE)
- value = encoding ? tvb_get_letoh64(tvb, offset) : tvb_get_ntoh64(tvb, offset);
- available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF);
- break;
- default:
- g_assert_not_reached();
- }
+ if (len <= 0 || len > 8)
+ g_assert_not_reached();
+ bitshift = (8 - (guint)len)*8;
+ available_bits = G_GUINT64_CONSTANT(0xFFFFFFFFFFFFFFFF) >> bitshift;
if (use_parent_tree == FALSE)
tree = proto_item_add_subtree(item, ett);
@@ -8797,43 +8739,36 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
continue;
}
- if (use_value)
- {
- switch (hf->type) {
- case FT_INT8:
- case FT_UINT8:
- case FT_INT16:
- case FT_UINT16:
- case FT_INT24:
- case FT_UINT24:
- case FT_INT32:
- case FT_UINT32:
- proto_tree_add_uint(tree, **fields, tvb, offset, len, (guint32)value);
- break;
+ switch (hf->type) {
+ case FT_INT8:
+ case FT_UINT8:
+ case FT_INT16:
+ case FT_UINT16:
+ case FT_INT24:
+ case FT_UINT24:
+ case FT_INT32:
+ case FT_UINT32:
+ proto_tree_add_uint(tree, **fields, tvb, offset, len, (guint32)value);
+ break;
- case FT_INT40:
- case FT_UINT40:
- case FT_INT48:
- case FT_UINT48:
- case FT_INT56:
- case FT_UINT56:
- case FT_INT64:
- case FT_UINT64:
- proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
- break;
+ case FT_INT40:
+ case FT_UINT40:
+ case FT_INT48:
+ case FT_UINT48:
+ case FT_INT56:
+ case FT_UINT56:
+ case FT_INT64:
+ case FT_UINT64:
+ proto_tree_add_uint64(tree, **fields, tvb, offset, len, value);
+ break;
- case FT_BOOLEAN:
- proto_tree_add_boolean64(tree, **fields, tvb, offset, len, value);
- break;
+ case FT_BOOLEAN:
+ proto_tree_add_boolean64(tree, **fields, tvb, offset, len, value);
+ break;
- default:
- DISSECTOR_ASSERT_NOT_REACHED();
- break;
- }
- }
- else
- {
- proto_tree_add_item(tree, **fields, tvb, offset, len, encoding);
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
}
if (flags & BMT_NO_APPEND) {
fields++;
@@ -8921,11 +8856,38 @@ proto_item_add_bitmask_tree(proto_item *item, tvbuff_t *tvb, const int offset,
}
/* This function will dissect a sequence of bytes that describe a
+ * bitmask and supply the value of that sequence through a pointer.
+ * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
+ * to be dissected.
+ * This field will form an expansion under which the individual fields of the
+ * bitmask is dissected and displayed.
+ * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
+ *
+ * fields is an array of pointers to int that lists all the fields of the
+ * bitmask. These fields can be either of the type FT_BOOLEAN for flags
+ * or another integer of the same type/size as hf_hdr with a mask specified.
+ * This array is terminated by a NULL entry.
+ *
+ * FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
+ * FT_integer fields that have a value_string attached will have the
+ * matched string displayed on the expansion line.
+ */
+proto_item *
+proto_tree_add_bitmask_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb,
+ const guint offset, const int hf_hdr,
+ const gint ett, const int **fields,
+ const guint encoding, guint64 *retval)
+{
+ return proto_tree_add_bitmask_with_flags_ret_uint64(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, retval);
+}
+
+/* This function will dissect a sequence of bytes that describe a
* bitmask.
- * hf_hdr is a 8/16/24/32 bit integer that describes the bitmask to be dissected.
+ * hf_hdr is a 8/16/24/32/40/48/56/64 bit integer that describes the bitmask
+ * to be dissected.
* This field will form an expansion under which the individual fields of the
* bitmask is dissected and displayed.
- * This field must be of the type FT_[U]INT{8|16|24|32}.
+ * This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
*
* fields is an array of pointers to int that lists all the fields of the
* bitmask. These fields can be either of the type FT_BOOLEAN for flags
@@ -8945,7 +8907,35 @@ proto_tree_add_bitmask(proto_tree *parent_tree, tvbuff_t *tvb,
return proto_tree_add_bitmask_with_flags(parent_tree, tvb, offset, hf_hdr, ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS);
}
-/* The same as proto_tree_add_bitmask(), but uses user-supplied flags to determine
+/* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
+ * what data is appended to the header.
+ */
+proto_item *
+proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *parent_tree, tvbuff_t *tvb, const guint offset,
+ const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags,
+ guint64 *retval)
+{
+ proto_item *item = NULL;
+ header_field_info *hf;
+ int len;
+ guint64 value;
+
+ PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
+ DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
+ len = ftype_length(hf->type);
+ value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
+
+ if (parent_tree) {
+ item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
+ proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
+ flags, FALSE, FALSE, NULL, value);
+ }
+
+ *retval = value;
+ return item;
+}
+
+/* The same as proto_tree_add_bitmask_ret_uint64(), but uses user-supplied flags to determine
* what data is appended to the header.
*/
proto_item *
@@ -8955,15 +8945,17 @@ proto_tree_add_bitmask_with_flags(proto_tree *parent_tree, tvbuff_t *tvb, const
proto_item *item = NULL;
header_field_info *hf;
int len;
+ guint64 value;
PROTO_REGISTRAR_GET_NTH(hf_hdr,hf);
DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
- len = ftype_length(hf->type);
if (parent_tree) {
+ len = ftype_length(hf->type);
item = proto_tree_add_item(parent_tree, hf_hdr, tvb, offset, len, encoding);
- proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
- flags, FALSE, FALSE, FALSE, NULL, 0);
+ value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
+ proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
+ flags, FALSE, FALSE, NULL, value);
}
return item;
@@ -8999,8 +8991,7 @@ proto_tree_add_bitmask_value_with_flags(proto_tree *parent_tree, tvbuff_t *tvb,
item = proto_tree_add_uint64(parent_tree, hf_hdr, tvb, offset, len, value);
proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
- 0, flags, FALSE, FALSE, TRUE, NULL, value);
-
+ flags, FALSE, FALSE, NULL, value);
}
return item;
@@ -9011,9 +9002,13 @@ void
proto_tree_add_bitmask_list(proto_tree *tree, tvbuff_t *tvb, const guint offset,
const int len, const int **fields, const guint encoding)
{
- if (tree)
+ guint64 value;
+
+ if (tree) {
+ value = get_uint64_value(tree, tvb, offset, len, encoding);
proto_item_add_bitmask_tree(NULL, tvb, offset, len, -1, fields,
- encoding, BMT_NO_APPEND, FALSE, TRUE, FALSE, tree, 0);
+ BMT_NO_APPEND, FALSE, TRUE, tree, value);
+ }
}
@@ -9039,6 +9034,7 @@ proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
guint decodable_len;
guint decodable_offset;
guint32 decodable_value;
+ guint64 value;
PROTO_REGISTRAR_GET_NTH(hf_hdr, hf);
DISSECTOR_ASSERT_FIELD_TYPE_IS_INTEGRAL(hf);
@@ -9070,8 +9066,9 @@ proto_tree_add_bitmask_len(proto_tree *parent_tree, tvbuff_t *tvb,
}
if (item) {
+ value = get_uint64_value(parent_tree, tvb, decodable_offset, decodable_len, encoding);
proto_item_add_bitmask_tree(item, tvb, decodable_offset, decodable_len,
- ett, fields, encoding, BMT_NO_INT|BMT_NO_TFS, FALSE, FALSE, FALSE, NULL, 0);
+ ett, fields, BMT_NO_INT|BMT_NO_TFS, FALSE, FALSE, NULL, value);
}
return item;
@@ -9086,11 +9083,13 @@ proto_tree_add_bitmask_text(proto_tree *parent_tree, tvbuff_t *tvb,
const guint encoding, const int flags)
{
proto_item *item = NULL;
+ guint64 value;
if (parent_tree) {
item = proto_tree_add_text_internal(parent_tree, tvb, offset, len, "%s", name ? name : "");
- if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields, encoding,
- flags, TRUE, FALSE, FALSE, NULL, 0) && fallback) {
+ value = get_uint64_value(parent_tree, tvb, offset, len, encoding);
+ if (proto_item_add_bitmask_tree(item, tvb, offset, len, ett, fields,
+ flags, TRUE, FALSE, NULL, value) && fallback) {
/* Still at first item - append 'fallback' text if any */
proto_item_append_text(item, "%s", fallback);
}
diff --git a/epan/proto.h b/epan/proto.h
index b31cf23a8f..93bcc9ccee 100644
--- a/epan/proto.h
+++ b/epan/proto.h
@@ -1048,8 +1048,8 @@ Integers of 8, 16, 24 and 32 bits can be retrieved with these functions.
@param start start of data in tvb (cannot be negative)
@param length length of data in tvb (for strings can be -1 for remaining)
@param encoding data encoding (e.g, ENC_LITTLE_ENDIAN, ENC_BIG_ENDIAN, ENC_ASCII|ENC_STRING, etc.)
-@param[out] retval points to a gint/guint 8/16/32/64 or gfloat/gdouble which will be set
-@return the newly created item, and value is set to the decoded value
+@param[out] retval points to a gint32 or guint32 which will be set
+@return the newly created item, and *retval is set to the decoded value
*/
WS_DLL_PUBLIC proto_item *
proto_tree_add_item_ret_int(proto_tree *tree, int hfindex, tvbuff_t *tvb,
@@ -2349,10 +2349,11 @@ proto_find_undecoded_data(proto_tree *tree, guint length);
@param tree the tree to append this item to
@param tvb the tv buffer of the current data
@param offset start of data in tvb
- @param hf_hdr an 8/16/24/32 bit integer that describes the bitmask to be dissected.
- This field will form an expansion under which the individual fields of the
- bitmask is dissected and displayed.
- This field must be of the type FT_[U]INT{8|16|24|32}.
+ @param hf_hdr an 8/16/24/32/40/48/56/64 bit integer that describes the
+ bitmask to be dissected.
+ This field will form an expansion under which the individual fields
+ of the bitmask are dissected and displayed.
+ This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
@param ett subtree index
@param fields an array of pointers to int that lists all the fields of the
bitmask. These fields can be either of the type FT_BOOLEAN for flags
@@ -2368,16 +2369,45 @@ proto_tree_add_bitmask(proto_tree *tree, tvbuff_t *tvb, const guint offset,
const int hf_hdr, const gint ett, const int **fields, const guint encoding);
/** This function will dissect a sequence of bytes that describe a bitmask.
-* This has "filterable" bitmask header functionality of proto_tree_add_bitmask
-* with the ability to control what data is appended to the header like
-* proto_tree_add_bitmask_text
+ The value of the integer containing the bitmask is returned through
+ a pointer.
@param tree the tree to append this item to
@param tvb the tv buffer of the current data
@param offset start of data in tvb
- @param hf_hdr an 8/16/24/32 bit integer that describes the bitmask to be dissected.
- This field will form an expansion under which the individual fields of the
- bitmask is dissected and displayed.
- This field must be of the type FT_[U]INT{8|16|24|32}.
+ @param hf_hdr an 8/16/24/32/40/48/56/64 bit integer that describes the
+ bitmask to be dissected.
+ This field will form an expansion under which the individual fields
+ of the bitmask are dissected and displayed.
+ This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
+ @param ett subtree index
+ @param fields an array of pointers to int that lists all the fields of the
+ bitmask. These fields can be either of the type FT_BOOLEAN for flags
+ or another integer of the same type/size as hf_hdr with a mask specified.
+ This array is terminated by a NULL entry.
+ FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
+ FT_integer fields that have a value_string attached will have the
+ matched string displayed on the expansion line.
+ @param encoding big or little endian byte representation (ENC_BIG_ENDIAN/ENC_LITTLE_ENDIAN/ENC_HOST_ENDIAN)
+ @param[out] retval points to a guint64 which will be set
+ @return the newly created item, and *retval is set to the decoded value
+ */
+WS_DLL_PUBLIC proto_item *
+proto_tree_add_bitmask_ret_uint64(proto_tree *tree, tvbuff_t *tvb, const guint offset,
+ const int hf_hdr, const gint ett, const int **fields,
+ const guint encoding, guint64 *retval);
+
+/** This function will dissect a sequence of bytes that describe a bitmask.
+ This has "filterable" bitmask header functionality of proto_tree_add_bitmask
+ with the ability to control what data is appended to the header like
+ proto_tree_add_bitmask_text
+ @param tree the tree to append this item to
+ @param tvb the tv buffer of the current data
+ @param offset start of data in tvb
+ @param hf_hdr an 8/16/24/32/40/48/56/64 bit integer that describes the
+ bitmask to be dissected.
+ This field will form an expansion under which the individual fields
+ of the bitmask are dissected and displayed.
+ This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
@param ett subtree index
@param fields an array of pointers to int that lists all the fields of the
bitmask. These fields can be either of the type FT_BOOLEAN for flags
@@ -2393,6 +2423,38 @@ WS_DLL_PUBLIC proto_item *
proto_tree_add_bitmask_with_flags(proto_tree *tree, tvbuff_t *tvb, const guint offset,
const int hf_hdr, const gint ett, const int **fields, const guint encoding, const int flags);
+/** This function will dissect a sequence of bytes that describe a bitmask.
+ This has "filterable" bitmask header functionality of proto_tree_add_bitmask
+ with the ability to control what data is appended to the header like
+ proto_tree_add_bitmask_text
+ The value of the integer containing the bitmask is returned through
+ a pointer.
+ @param tree the tree to append this item to
+ @param tvb the tv buffer of the current data
+ @param offset start of data in tvb
+ @param hf_hdr an 8/16/24/32/40/48/56/64 bit integer that describes the
+ bitmask to be dissected.
+ This field will form an expansion under which the individual fields
+ of the bitmask are dissected and displayed.
+ This field must be of the type FT_[U]INT{8|16|24|32|40|48|56|64}.
+ @param ett subtree index
+ @param fields an array of pointers to int that lists all the fields of the
+ bitmask. These fields can be either of the type FT_BOOLEAN for flags
+ or another integer of the same type/size as hf_hdr with a mask specified.
+ This array is terminated by a NULL entry.
+ FT_BOOLEAN bits that are set to 1 will have the name added to the expansion.
+ FT_integer fields that have a value_string attached will have the
+ matched string displayed on the expansion line.
+ @param encoding big or little endian byte representation (ENC_BIG_ENDIAN/ENC_LITTLE_ENDIAN/ENC_HOST_ENDIAN)
+ @param flags bitmask field using BMT_NO_* flags to determine behavior
+ @param[out] retval points to a guint64 which will be set
+ @return the newly created item, and *retval is set to the decoded value
+ */
+WS_DLL_PUBLIC proto_item *
+proto_tree_add_bitmask_with_flags_ret_uint64(proto_tree *tree, tvbuff_t *tvb, const guint offset,
+ const int hf_hdr, const gint ett, const int **fields,
+ const guint encoding, const int flags, guint64 *retval);
+
/** This function will dissect a value that describe a bitmask. Similar to proto_tree_add_bitmask(),
but with a passed in value (presumably because it can't be retrieved directly from tvb)
@param tree the tree to append this item to