summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-rdp_drdynvc.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-09-19 04:14:33 +0000
commit9f153fbfec0fb9c9ce38e749a7c6f4a5e115d4e9 (patch)
tree2784370cda9bbf2da9114d70f05399c0b229d28c /epan/dissectors/packet-rdp_drdynvc.c
parentAdding debian version 4.2.6-1. (diff)
downloadwireshark-9f153fbfec0fb9c9ce38e749a7c6f4a5e115d4e9.tar.xz
wireshark-9f153fbfec0fb9c9ce38e749a7c6f4a5e115d4e9.zip
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-rdp_drdynvc.c')
-rw-r--r--epan/dissectors/packet-rdp_drdynvc.c368
1 files changed, 216 insertions, 152 deletions
diff --git a/epan/dissectors/packet-rdp_drdynvc.c b/epan/dissectors/packet-rdp_drdynvc.c
index ddd3ec4b..7e9ed0b8 100644
--- a/epan/dissectors/packet-rdp_drdynvc.c
+++ b/epan/dissectors/packet-rdp_drdynvc.c
@@ -22,44 +22,45 @@
void proto_register_rdp_drdynvc(void);
void proto_reg_handoff_drdynvc(void);
-static int proto_rdp_drdynvc = -1;
-
-static int hf_rdp_drdynvc_cbId = -1;
-static int hf_rdp_drdynvc_sp = -1;
-static int hf_rdp_drdynvc_pri = -1;
-static int hf_rdp_drdynvc_cmd = -1;
-static int hf_rdp_drdynvc_capa_version = -1;
-static int hf_rdp_drdynvc_capa_prio0 = -1;
-static int hf_rdp_drdynvc_capa_prio1 = -1;
-static int hf_rdp_drdynvc_capa_prio2 = -1;
-static int hf_rdp_drdynvc_capa_prio3 = -1;
-static int hf_rdp_drdynvc_channelId = -1;
-static int hf_rdp_drdynvc_pad = -1;
-static int hf_rdp_drdynvc_channelName = -1;
-static int hf_rdp_drdynvc_creationStatus = -1;
-static int hf_rdp_drdynvc_createresp_channelname = -1;
-static int hf_rdp_drdynvc_length = -1;
-static int hf_rdp_drdynvc_softsync_req_length = -1;
-static int hf_rdp_drdynvc_softsync_req_flags = -1;
-static int hf_rdp_drdynvc_softsync_req_ntunnels = -1;
-static int hf_rdp_drdynvc_softsync_req_channel_tunnelType = -1;
-static int hf_rdp_drdynvc_softsync_req_channel_ndvc = -1;
-static int hf_rdp_drdynvc_softsync_req_channel_dvcid = -1;
-static int hf_rdp_drdynvc_softsync_resp_ntunnels = -1;
-static int hf_rdp_drdynvc_softsync_resp_tunnel = -1;
-static int hf_rdp_drdynvc_data = -1;
-static int hf_rdp_drdynvc_data_progress = -1;
-
-
-static int ett_rdp_drdynvc = -1;
-static int ett_rdp_drdynvc_softsync_channels = -1;
-static int ett_rdp_drdynvc_softsync_channel = -1;
-static int ett_rdp_drdynvc_softsync_dvc = -1;
+static int proto_rdp_drdynvc;
+
+static int hf_rdp_drdynvc_cbId;
+static int hf_rdp_drdynvc_sp;
+static int hf_rdp_drdynvc_pri;
+static int hf_rdp_drdynvc_cmd;
+static int hf_rdp_drdynvc_capa_version;
+static int hf_rdp_drdynvc_capa_prio0;
+static int hf_rdp_drdynvc_capa_prio1;
+static int hf_rdp_drdynvc_capa_prio2;
+static int hf_rdp_drdynvc_capa_prio3;
+static int hf_rdp_drdynvc_channelId;
+static int hf_rdp_drdynvc_pad;
+static int hf_rdp_drdynvc_channelName;
+static int hf_rdp_drdynvc_creationStatus;
+static int hf_rdp_drdynvc_createresp_channelname;
+static int hf_rdp_drdynvc_length;
+static int hf_rdp_drdynvc_softsync_req_length;
+static int hf_rdp_drdynvc_softsync_req_flags;
+static int hf_rdp_drdynvc_softsync_req_ntunnels;
+static int hf_rdp_drdynvc_softsync_req_channel_tunnelType;
+static int hf_rdp_drdynvc_softsync_req_channel_ndvc;
+static int hf_rdp_drdynvc_softsync_req_channel_dvcid;
+static int hf_rdp_drdynvc_softsync_resp_ntunnels;
+static int hf_rdp_drdynvc_softsync_resp_tunnel;
+static int hf_rdp_drdynvc_data;
+static int hf_rdp_drdynvc_data_progress;
+
+
+static int ett_rdp_drdynvc;
+static int ett_rdp_drdynvc_softsync_channels;
+static int ett_rdp_drdynvc_softsync_channel;
+static int ett_rdp_drdynvc_softsync_dvc;
dissector_handle_t egfx_handle;
dissector_handle_t rail_handle;
dissector_handle_t cliprdr_handle;
dissector_handle_t snd_handle;
+dissector_handle_t ear_handle;
#define PNAME "RDP Dynamic Channel Protocol"
#define PSNAME "DRDYNVC"
@@ -93,22 +94,22 @@ typedef enum {
DRDYNVC_CHANNEL_RAIL, /* MS-RDPERP */
DRDYNVC_CHANNEL_CLIPRDR, /* MS-RDPECLIP */
+ DRDYNVC_CHANNEL_DR, /* MS-RDPDR */
} drdynvc_known_channel_t;
enum {
DRDYNVC_CHANNEL_PDUS_KEY = 1,
};
-typedef struct {
- guint32 length;
- guint8* data;
-} drdynvc_pdu_t;
typedef struct {
- drdynvc_pdu_t key;
- gboolean fragmented;
- guint32 packetLen;
- guint32 progress;
+ bool reassembled;
+ bool decodePayload;
+ uint32_t progressStart;
+ uint32_t progressEnd;
+ uint32_t packetLen;
+ uint32_t startReassemblyFrame;
+ uint32_t endReassemblyFrame;
tvbuff_t* tvb;
} drdynvc_pdu_info_t;
@@ -117,16 +118,19 @@ typedef struct {
} drdynvc_pinfo_t;
typedef struct {
- wmem_array_t *packet;
- guint32 packetLen;
- guint32 pendingLen;
- guint32 startFrame;
+ wmem_array_t *currentPacket;
+ uint32_t packetLen;
+ uint32_t pendingLen;
+ uint32_t startFrame;
+ uint32_t endReassemblyFrame;
+ wmem_array_t *chunks;
} drdynvc_pending_packet_t;
+/** @brief context associated with a dynamic channel */
typedef struct {
drdynvc_known_channel_t type;
char *name;
- guint32 channelId;
+ uint32_t channelId;
drdynvc_pending_packet_t pending_cs;
drdynvc_pending_packet_t pending_sc;
@@ -160,6 +164,7 @@ static drdynvc_know_channel_def knownChannels[] = {
/* static channels that can be reopened on the dynamic channel */
{"rail", "rail", DRDYNVC_CHANNEL_RAIL},
{"cliprdr", "cliprdr", DRDYNVC_CHANNEL_CLIPRDR},
+ {"rdpdr", "rdpdr", DRDYNVC_CHANNEL_DR},
};
static const value_string drdynvc_tunneltype_vals[] = {
@@ -196,10 +201,21 @@ static const value_string rdp_drdynvc_cmd_vals[] = {
{ 0x0, NULL},
};
+static void
+drdynvc_pending_packet_init(drdynvc_pending_packet_t *pending, uint32_t startFrame)
+{
+ pending->packetLen = 0;
+ pending->pendingLen = 0;
+ pending->startFrame = startFrame;
+ pending->endReassemblyFrame = 0;
+ pending->currentPacket = NULL;
+ pending->chunks = NULL;
+}
+
static drdynvc_known_channel_t
drdynvc_find_channel_type(const char *name)
{
- guint i;
+ unsigned i;
for (i = 0; i < array_length(knownChannels); i++)
{
@@ -235,22 +251,22 @@ drdynvc_get_conversation_data(packet_info *pinfo)
static int
-dissect_rdp_vlength(tvbuff_t *tvb, int hf_index, int offset, guint8 vlen, proto_tree *tree, guint32 *ret)
+dissect_rdp_vlength(tvbuff_t *tvb, int hf_index, int offset, uint8_t vlen, proto_tree *tree, uint32_t *ret)
{
int len;
- guint32 value;
+ uint32_t value;
switch (vlen) {
case 0:
- value = tvb_get_guint8(tvb, offset);
+ value = tvb_get_uint8(tvb, offset);
len = 1;
break;
case 1:
- value = tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN);
+ value = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
len = 2;
break;
case 2:
- value = tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN);
+ value = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
len = 4;
break;
default:
@@ -266,7 +282,7 @@ dissect_rdp_vlength(tvbuff_t *tvb, int hf_index, int offset, guint8 vlen, proto_
}
static const char *
-find_channel_name_by_id(packet_info *pinfo, drdynvc_conv_info_t *dyninfo, guint32 dvcId) {
+find_channel_name_by_id(packet_info *pinfo, drdynvc_conv_info_t *dyninfo, uint32_t dvcId) {
drdynvc_channel_def_t *dynChannel = wmem_multimap_lookup32_le(dyninfo->channels, GUINT_TO_POINTER(dvcId), pinfo->num);
if (dynChannel)
return dynChannel->name;
@@ -292,14 +308,15 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
{
proto_item *item;
proto_tree *tree;
- gint offset = 0;
- guint8 cbIdSpCmd, cmdId;
- guint8 cbId, Len;
- gboolean haveChannelId, havePri, haveLen;
- gboolean isServerTarget = rdp_isServerAddressTarget(pinfo);
- guint32 channelId = 0;
- guint32 pduLen = 0;
+ int offset = 0;
+ uint8_t cbIdSpCmd, cmdId;
+ uint8_t cbId, Len;
+ bool haveChannelId, havePri, haveLen;
+ bool isServerTarget = rdp_isServerAddressTarget(pinfo);
+ uint32_t channelId = 0;
+ uint32_t fullPduLen = 0;
drdynvc_conv_info_t *info;
+ drdynvc_channel_def_t *channel = NULL;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDYNVC");
col_clear(pinfo->cinfo, COL_INFO);
@@ -308,7 +325,7 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
item = proto_tree_add_item(parent_tree, proto_rdp_drdynvc, tvb, 0, -1, ENC_NA);
tree = proto_item_add_subtree(item, ett_rdp_drdynvc);
- cbIdSpCmd = tvb_get_guint8(tvb, offset);
+ cbIdSpCmd = tvb_get_uint8(tvb, offset);
cmdId = (cbIdSpCmd >> 4) & 0xf;
cbId = (cbIdSpCmd & 0x3);
@@ -342,48 +359,45 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
proto_tree_add_item(tree, hf_rdp_drdynvc_cmd, tvb, offset, 1, ENC_NA);
offset++;
- if (haveChannelId)
+
+ info = drdynvc_get_conversation_data(pinfo);
+ if (haveChannelId) {
offset += dissect_rdp_vlength(tvb, hf_rdp_drdynvc_channelId, offset, cbId, tree, &channelId);
+ channel = wmem_multimap_lookup32_le(info->channels, GUINT_TO_POINTER(channelId), pinfo->num);
+ }
+
if (haveLen) {
Len = (cbIdSpCmd >> 2) & 0x3;
- offset += dissect_rdp_vlength(tvb, hf_rdp_drdynvc_length, offset, Len, tree, &pduLen);
+ offset += dissect_rdp_vlength(tvb, hf_rdp_drdynvc_length, offset, Len, tree, &fullPduLen);
}
- info = drdynvc_get_conversation_data(pinfo);
switch (cmdId) {
case DRDYNVC_CREATE_REQUEST_PDU:
if (!isServerTarget) {
- guint nameLen = tvb_strsize(tvb, offset);
+ unsigned nameLen = tvb_strsize(tvb, offset);
col_set_str(pinfo->cinfo, COL_INFO, "CreateChannel Request");
proto_tree_add_item(tree, hf_rdp_drdynvc_channelName, tvb, offset, -1, ENC_ASCII);
- drdynvc_channel_def_t *channel;
if (!PINFO_FD_VISITED(pinfo)) {
channel = wmem_alloc(wmem_file_scope(), sizeof(*channel));
channel->channelId = channelId;
channel->name = tvb_get_string_enc(wmem_file_scope(), tvb, offset, nameLen, ENC_ASCII);
channel->type = drdynvc_find_channel_type(channel->name);
- channel->pending_cs.pendingLen = 0;
- channel->pending_cs.packet = NULL;
- channel->pending_cs.startFrame = pinfo->num;
- channel->pending_sc.pendingLen = 0;
- channel->pending_sc.packet = NULL;
- channel->pending_sc.startFrame = pinfo->num;
- //printf("dynamic %s -> 0x%x\n", channel->name, channel->channelId);
+ drdynvc_pending_packet_init(&channel->pending_cs, pinfo->num);
+ drdynvc_pending_packet_init(&channel->pending_sc, pinfo->num);
wmem_multimap_insert32(info->channels, GUINT_TO_POINTER(channelId), pinfo->num, channel);
}
} else {
- drdynvc_channel_def_t *channel = wmem_multimap_lookup32_le(info->channels, GUINT_TO_POINTER(channelId), pinfo->num);
-
col_set_str(pinfo->cinfo, COL_INFO, "CreateChannel Response");
if (channel) {
- proto_item *channelName = proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_createresp_channelname, tvb, offset, 0, NULL, "%s", channel->name);
- proto_item_set_generated(channelName);
+ proto_item_set_generated(
+ proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_createresp_channelname, tvb, offset, 0, NULL, "%s", channel->name)
+ );
}
proto_tree_add_item(tree, hf_rdp_drdynvc_creationStatus, tvb, offset, 4, ENC_NA);
@@ -394,7 +408,7 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
proto_tree_add_item(tree, hf_rdp_drdynvc_pad, tvb, offset, 1, ENC_NA);
offset++;
- guint32 version;
+ uint32_t version;
proto_tree_add_item_ret_uint(tree, hf_rdp_drdynvc_capa_version, tvb, offset, 2, ENC_LITTLE_ENDIAN, &version);
offset += 2;
@@ -419,22 +433,55 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
case DRDYNVC_DATA_FIRST_PDU: {
col_set_str(pinfo->cinfo, COL_INFO, "Data first");
- drdynvc_channel_def_t *channel = wmem_multimap_lookup32_le(info->channels, GUINT_TO_POINTER(channelId), pinfo->num);
if (channel) {
+ drdynvc_pdu_info_t *pduInfo = NULL;
drdynvc_pending_packet_t *pendingPacket = isServerTarget ? &channel->pending_cs : &channel->pending_sc;
- gint payloadLen = tvb_reported_length_remaining(tvb, offset);
- proto_item *channelName = proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_createresp_channelname, tvb, offset, 0, NULL, "%s", channel->name);
- proto_item_set_generated(channelName);
+ int payloadLen = tvb_reported_length_remaining(tvb, offset);
+ bool isSinglePacket = (fullPduLen == (uint32_t)payloadLen);
+ drdynvc_pinfo_t *drdynvcPinfo = getDrDynPacketInfo(pinfo);
+ uint32_t key = crc32_ccitt_tvb_offset(tvb, offset, payloadLen);
+
+ proto_item_set_generated(
+ proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_createresp_channelname, tvb, offset, 0, NULL, "%s", channel->name)
+ );
proto_item_set_generated(
- proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_data_progress, tvb, offset, 0, NULL, "0-%d/%d", payloadLen, pduLen)
+ proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_data_progress, tvb, offset, 0, NULL, "0-%d/%d", payloadLen, fullPduLen)
);
- pendingPacket->packetLen = pduLen;
- pendingPacket->pendingLen = pduLen - payloadLen;
- pendingPacket->startFrame = pinfo->num;
+ if (!PINFO_FD_VISITED(pinfo)) {
+ if (!isSinglePacket) {
+ if (pendingPacket->chunks)
+ wmem_destroy_array(pendingPacket->chunks);
+ pendingPacket->chunks = wmem_array_new(wmem_file_scope(), sizeof(drdynvc_pdu_info_t*));
+
+ pduInfo = wmem_alloc(wmem_file_scope(), sizeof(*pduInfo));
+ pduInfo->reassembled = true;
+ pduInfo->startReassemblyFrame = pinfo->num;
+ pduInfo->progressStart = 0;
+ pduInfo->progressEnd = fullPduLen;
+ pduInfo->tvb = NULL;
+
+ wmem_tree_insert32(drdynvcPinfo->pdus, key, pduInfo);
+ wmem_array_append(pendingPacket->chunks, &pduInfo, 1);
+
+ pendingPacket->packetLen = fullPduLen;
+ pendingPacket->pendingLen = fullPduLen - payloadLen;
+ pendingPacket->startFrame = pinfo->num;
+ pendingPacket->currentPacket = wmem_array_sized_new(wmem_file_scope(), 1, fullPduLen);
+ wmem_array_append(pendingPacket->currentPacket, tvb_get_ptr(tvb, offset, payloadLen), payloadLen);
+ } else {
+ if (pendingPacket->pendingLen || pendingPacket->chunks)
+ printf("(%d) looks like we have a non completed packet...\n", pinfo->num);
+ if (pendingPacket->chunks)
+ wmem_destroy_array(pendingPacket->chunks);
+ memset(pendingPacket, 0, sizeof(*pendingPacket));
+ }
+ } else {
+ pduInfo = (drdynvc_pdu_info_t*)wmem_tree_lookup32(drdynvcPinfo->pdus, key);
+ }
- if (!pendingPacket->pendingLen) {
+ if (isSinglePacket) {
switch (channel->type) {
case DRDYNVC_CHANNEL_EGFX:
call_dissector(egfx_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
@@ -448,6 +495,9 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
case DRDYNVC_CHANNEL_AUDIOUT:
call_dissector(snd_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
break;
+ case DRDYNVC_CHANNEL_AUTH_REDIR:
+ call_dissector(ear_handle, tvb_new_subset_remaining(tvb, offset), pinfo, tree);
+ break;
default:
proto_tree_add_item(tree, hf_rdp_drdynvc_data, tvb, offset, -1, ENC_NA);
break;
@@ -455,10 +505,8 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
offset += payloadLen;
return offset;
- } else {
- pendingPacket->packet = wmem_array_sized_new(wmem_file_scope(), 1, pduLen);
- wmem_array_append(pendingPacket->packet, tvb_get_ptr(tvb, offset, -1), payloadLen);
}
+
}
proto_tree_add_item(tree, hf_rdp_drdynvc_data, tvb, offset, -1, ENC_NA);
@@ -467,54 +515,67 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
case DRDYNVC_DATA_PDU: {
col_set_str(pinfo->cinfo, COL_INFO, "Data");
- drdynvc_channel_def_t *channel = wmem_multimap_lookup32_le(info->channels, GUINT_TO_POINTER(channelId), pinfo->num);
if (channel) {
tvbuff_t *targetTvb = NULL;
- gboolean fragmented = FALSE;
- proto_item *channelName = proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_createresp_channelname, tvb, offset, 0, NULL, "%s", channel->name);
- proto_item_set_generated(channelName);
+ proto_item_set_generated(
+ proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_createresp_channelname, tvb, offset, 0, NULL, "%s", channel->name)
+ );
drdynvc_pinfo_t *drdynvcPinfo = getDrDynPacketInfo(pinfo);
- drdynvc_pdu_info_t *pduInfo;
- gint payloadLen = tvb_reported_length_remaining(tvb, offset);
- guint32 key = crc32_ccitt_tvb_offset(tvb, offset, payloadLen);
+ drdynvc_pdu_info_t *pduInfo = NULL;
+ int payloadLen = tvb_reported_length_remaining(tvb, offset);
+ uint32_t key = crc32_ccitt_tvb_offset(tvb, offset, payloadLen);
if (!PINFO_FD_VISITED(pinfo)) {
drdynvc_pending_packet_t *pendingPacket = isServerTarget ? &channel->pending_cs : &channel->pending_sc;
- /*printf("num=%d payloadLen=%d pendingLen=%d/%d\n", pinfo->num, payloadLen,
- pendingPacket->pendingLen, pendingPacket->packetLen);*/
+ pduInfo = wmem_alloc(wmem_file_scope(), sizeof(*pduInfo));
+ wmem_tree_insert32(drdynvcPinfo->pdus, key, pduInfo);
+
if (pendingPacket->pendingLen) {
- if ((guint32)payloadLen > pendingPacket->pendingLen) {
+ /* we have a fragmented packet in progress */
+ if ((uint32_t)payloadLen > pendingPacket->pendingLen) {
// TODO: error
- /*printf("num=%d error\n", pinfo->num);*/
+ printf("num=%d error payload too big\n", pinfo->num);
return offset;
}
- pendingPacket->pendingLen -= payloadLen;
- wmem_array_append(pendingPacket->packet, tvb_get_ptr(tvb, offset, -1), payloadLen);
- fragmented = TRUE;
- }
+ pduInfo->reassembled = true;
+ pduInfo->decodePayload = false;
+ pduInfo->progressStart = pendingPacket->packetLen - pendingPacket->pendingLen;
+ pduInfo->progressEnd = pduInfo->progressStart + payloadLen;
+ pduInfo->packetLen = pendingPacket->packetLen;
- if (!pendingPacket->pendingLen) {
- pendingPacket->packetLen = 0;
+ wmem_array_append(pendingPacket->chunks, &pduInfo, 1);
- if (!fragmented) {
- targetTvb = tvb_new_subset_remaining(tvb, offset);
- } else {
- gint reassembled_len = wmem_array_get_count(pendingPacket->packet);
- targetTvb = tvb_new_real_data(wmem_array_get_raw(pendingPacket->packet), reassembled_len, reassembled_len);
+ pendingPacket->pendingLen -= payloadLen;
+ wmem_array_append(pendingPacket->currentPacket, tvb_get_ptr(tvb, offset, payloadLen), payloadLen);
+
+ if (!pendingPacket->pendingLen) {
+ /* last packet of the reassembly */
+ int reassembled_len = wmem_array_get_count(pendingPacket->currentPacket);
+ pduInfo->tvb = tvb_new_real_data(wmem_array_get_raw(pendingPacket->currentPacket), reassembled_len, reassembled_len);
+ pduInfo->decodePayload = true;
+ pendingPacket->currentPacket = NULL;
+
+ for (unsigned i = 0; i < wmem_array_get_count(pendingPacket->chunks); i++) {
+ drdynvc_pdu_info_t *chunk = *(drdynvc_pdu_info_t **)wmem_array_index(pendingPacket->chunks, i);
+ chunk->endReassemblyFrame = pinfo->num;
+ }
+ wmem_destroy_array(pendingPacket->chunks);
+ pendingPacket->chunks = NULL;
}
+ } else {
+ /* single data packet */
+ pduInfo->reassembled = false;
+ pduInfo->decodePayload = true;
+ pduInfo->progressStart = 0;
+ pduInfo->progressEnd = payloadLen;
+ pduInfo->packetLen = payloadLen;
+ pduInfo->tvb = NULL;
+ pduInfo->startReassemblyFrame = pduInfo->endReassemblyFrame = pinfo->num;
}
-
- pduInfo = wmem_alloc(wmem_file_scope(), sizeof(*pduInfo));
- pduInfo->fragmented = fragmented;
- pduInfo->packetLen = pendingPacket->packetLen ? pendingPacket->packetLen : (guint32)payloadLen;
- pduInfo->progress = pendingPacket->packetLen - pendingPacket->pendingLen;
- pduInfo->tvb = fragmented ? targetTvb : NULL;
-
- wmem_tree_insert32(drdynvcPinfo->pdus, key, pduInfo);
} else {
pduInfo = (drdynvc_pdu_info_t*)wmem_tree_lookup32(drdynvcPinfo->pdus, key);
}
@@ -522,19 +583,22 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
if (pduInfo) {
proto_item_set_generated(
proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_data_progress, tvb, offset, 0, NULL, "%d-%d/%d",
- pduInfo->progress, pduInfo->progress + payloadLen, pduInfo->packetLen)
+ pduInfo->progressStart, pduInfo->progressEnd, pduInfo->packetLen)
);
- }
-
- if (!pduInfo->fragmented)
- targetTvb = tvb_new_subset_remaining(tvb, offset);
- else
- targetTvb = pduInfo->tvb;
- if(targetTvb) {
- if (pduInfo->fragmented)
+ if (pduInfo->tvb) {
+ targetTvb = pduInfo->tvb;
add_new_data_source(pinfo, targetTvb, "Reassembled DRDYNVC");
+ } else {
+ targetTvb = tvb_new_subset_remaining(tvb, offset);
+ }
+
+ if (pduInfo->endReassemblyFrame && (pduInfo->endReassemblyFrame != pinfo->num)) {
+ // TODO: show a link to the end frame ?
+ }
+ }
+ if (pduInfo && pduInfo->decodePayload) {
switch (channel->type) {
case DRDYNVC_CHANNEL_EGFX:
call_dissector(egfx_handle, targetTvb, pinfo, tree);
@@ -548,8 +612,11 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
case DRDYNVC_CHANNEL_AUDIOUT:
call_dissector(snd_handle, targetTvb, pinfo, tree);
break;
+ case DRDYNVC_CHANNEL_AUTH_REDIR:
+ call_dissector(ear_handle, targetTvb, pinfo, tree);
+ break;
default:
- proto_tree_add_item(tree, hf_rdp_drdynvc_data, targetTvb, offset, -1, ENC_NA);
+ proto_tree_add_item(tree, hf_rdp_drdynvc_data, targetTvb, 0, -1, ENC_NA);
break;
}
return tvb_reported_length(tvb);
@@ -566,8 +633,8 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
col_set_str(pinfo->cinfo, COL_INFO, "Data compressed");
break;
case DRDYNVC_SOFT_SYNC_REQUEST_PDU: {
- guint32 ntunnels;
- guint32 flags;
+ uint32_t ntunnels;
+ uint32_t flags;
col_set_str(pinfo->cinfo, COL_INFO, "SoftSync Request");
@@ -586,14 +653,14 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
offset += 2;
if (flags & 0x02) { /* SOFT_SYNC_CHANNEL_LIST_PRESENT */
- guint16 i;
+ uint16_t i;
proto_tree *tunnels_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_rdp_drdynvc_softsync_channels, NULL, "Channels");
for (i = 0; i < ntunnels; i++) {
- guint16 j;
- guint32 tunnelType = tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN);
- guint16 ndvcs = tvb_get_guint16(tvb, offset + 4, ENC_LITTLE_ENDIAN);
- gint channelSz = 4 + 2 + (ndvcs * 4);
+ uint16_t j;
+ uint32_t tunnelType = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
+ uint16_t ndvcs = tvb_get_uint16(tvb, offset + 4, ENC_LITTLE_ENDIAN);
+ int channelSz = 4 + 2 + (ndvcs * 4);
proto_tree *channel_tree;
const char *label = (tunnelType == 0x1) ? "Reliable channels" : "Lossy channels";
@@ -607,10 +674,10 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
for (j = 0; j < ndvcs; j++, offset += 4) {
proto_tree *dvc_tree;
- guint32 dvcId;
+ uint32_t dvcId;
const char *showLabel;
- dvcId = tvb_get_guint32(tvb, offset, ENC_LITTLE_ENDIAN);
+ dvcId = tvb_get_uint32(tvb, offset, ENC_LITTLE_ENDIAN);
showLabel = label = find_channel_name_by_id(pinfo, info, dvcId);
if (!label)
showLabel = "DVC";
@@ -627,7 +694,7 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
break;
}
case DRDYNVC_SOFT_SYNC_RESPONSE_PDU: {
- guint32 ntunnels, i;
+ uint32_t ntunnels, i;
col_set_str(pinfo->cinfo, COL_INFO, "SoftSync Response");
@@ -647,12 +714,11 @@ dissect_rdp_drdynvc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
break;
}
case DRDYNVC_CLOSE_REQUEST_PDU: {
- drdynvc_channel_def_t *channel = wmem_multimap_lookup32_le(info->channels, GUINT_TO_POINTER(channelId), pinfo->num);
-
col_set_str(pinfo->cinfo, COL_INFO, "Close request");
if (channel) {
- proto_item *channelName = proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_channelName, tvb, offset, 0, NULL, "%s", channel->name);
- proto_item_set_generated(channelName);
+ proto_item_set_generated(
+ proto_tree_add_string_format_value(tree, hf_rdp_drdynvc_channelName, tvb, offset, 0, NULL, "%s", channel->name)
+ );
}
break;
}
@@ -769,21 +835,18 @@ void proto_register_rdp_drdynvc(void) {
};
/* List of subtrees */
- static gint *ett[] = {
- &ett_rdp_drdynvc,
- &ett_rdp_drdynvc_softsync_channels,
- &ett_rdp_drdynvc_softsync_channel,
- &ett_rdp_drdynvc_softsync_dvc
+ static int *ett[] = {
+ &ett_rdp_drdynvc,
+ &ett_rdp_drdynvc_softsync_channels,
+ &ett_rdp_drdynvc_softsync_channel,
+ &ett_rdp_drdynvc_softsync_dvc
};
- //module_t *drdynvc_module;
proto_rdp_drdynvc = proto_register_protocol(PNAME, PSNAME, PFNAME);
/* Register fields and subtrees */
proto_register_field_array(proto_rdp_drdynvc, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
- /*drdynvc_module = prefs_register_protocol(proto_rdp_drdynvc, NULL);*/
-
register_dissector("rdp_drdynvc", dissect_rdp_drdynvc, proto_rdp_drdynvc);
}
@@ -792,6 +855,7 @@ void proto_reg_handoff_drdynvc(void) {
rail_handle = find_dissector("rdp_rail");
cliprdr_handle = find_dissector("rdp_cliprdr");
snd_handle = find_dissector("rdp_snd");
+ ear_handle = find_dissector("rdp_ear");
}
/*