Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rdp_dr.c
Line
Count
Source
1
/* packet-rdp_dr.c
2
 * Routines for the DR RDP channel
3
 * Copyright 2025, David Fort <contact@hardening-consulting.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
 * See: "[MS-RDPEFS] "
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include <epan/prefs.h>
20
#include <epan/conversation.h>
21
#include <epan/expert.h>
22
23
#include "packet-rdp.h"
24
#include "packet-rdpudp.h"
25
#include "packet-dcerpc.h"
26
#include "packet-dcerpc-rdpdr_smartcard.h"
27
28
void proto_register_rdpdr(void);
29
void proto_reg_handoff_rdpdr(void);
30
31
static int proto_rdpdr;
32
33
static int hf_rdpdr_component;
34
static int hf_rdpdr_packetid;
35
static int hf_rdpdr_deviceCount;
36
static int hf_rdpdr_deviceType;
37
static int hf_rdpdr_deviceId;
38
static int hf_rdpdr_dosName;
39
static int hf_rdpdr_deviceDataLen;
40
static int hf_rdpdr_deviceData;
41
static int hf_rdpdr_numCapabilities;
42
static int hf_rdpdr_padding;
43
static int hf_rdpdr_capaType;
44
static int hf_rdpdr_capaLen;
45
static int hf_rdpdr_capaVersion;
46
static int hf_rdpdr_capa_gen_osType;
47
static int hf_rdpdr_capa_gen_osVersion;
48
static int hf_rdpdr_capa_gen_protocolMajor;
49
static int hf_rdpdr_capa_gen_protocolMinor;
50
static int hf_rdpdr_capa_gen_ioCode1;
51
static int hf_rdpdr_capa_gen_ioCode2;
52
static int hf_rdpdr_capa_gen_extendedPdu;
53
static int hf_rdpdr_capa_gen_extraFlags1;
54
static int hf_rdpdr_capa_gen_extraFlags2;
55
static int hf_rdpdr_capa_gen_specialTypeDeviceCap;
56
static int hf_rdpdr_fileId;
57
static int hf_rdpdr_completionId;
58
static int hf_rdpdr_ioreq_dr_majorFunction;
59
static int hf_rdpdr_ioreq_dr_minorFunction;
60
static int hf_rdpdr_ioreq_sc_majorFunction;
61
static int hf_rdpdr_ioreq_sc_minorFunction;
62
static int hf_rdpdr_ioreq_sc_command;
63
static int hf_rdpdr_ioreq_sc_returnCode;
64
static int hf_rdpdr_printer_cacheEvent;
65
static int hf_rdpdr_pnpNameLength;
66
static int hf_rdpdr_pnpName;
67
static int hf_rdpdr_driverNameLength;
68
static int hf_rdpdr_driverName;
69
static int hf_rdpdr_printerNameLength;
70
static int hf_rdpdr_printerName;
71
static int hf_rdpdr_cachedFieldsLength;
72
static int hf_rdpdr_cachedFields;
73
static int hf_rdpdr_resultCode;
74
static int hf_rdpdr_ioStatus;
75
static int hf_rdpdr_io_request_control_outputBufLen;
76
static int hf_rdpdr_io_request_control_inputBufLen;
77
static int hf_rdpdr_io_request_control_ioControlCode;
78
static int hf_rdpdr_io_request_control_padding;
79
static int hf_rdpdr_io_request_frame;
80
static int hf_rdpdr_io_result_frame;
81
static int hf_rdpdr_create_info;
82
static int hf_rdpdr_device_name;
83
84
85
static int ett_rdpdr;
86
static int ett_rdpdr_device;
87
static int ett_rdpdr_capabilities;
88
89
enum {
90
  RDPDR_CTYP_CORE = 0x4472,
91
  RDPDR_CTYP_PRN = 0x5052,
92
};
93
94
enum {
95
  PAKID_CORE_SERVER_ANNOUNCE = 0x496E,
96
  PAKID_CORE_CLIENTID_CONFIRM = 0x4343,
97
  PAKID_CORE_CLIENT_NAME = 0x434E,
98
  PAKID_CORE_DEVICELIST_ANNOUNCE = 0x4441,
99
  PAKID_CORE_DEVICE_REPLY = 0x6472,
100
  PAKID_CORE_DEVICE_IOREQUEST = 0x4952,
101
  PAKID_CORE_DEVICE_IOCOMPLETION = 0x4943,
102
  PAKID_CORE_SERVER_CAPABILITY = 0x5350,
103
  PAKID_CORE_CLIENT_CAPABILITY = 0x4350,
104
  PAKID_CORE_DEVICELIST_REMOVE = 0x444D,
105
  PAKID_PRN_CACHE_DATA = 0x5043,
106
  PAKID_CORE_USER_LOGGEDON = 0x554C,
107
  PAKID_PRN_USING_XPS = 0x5543,
108
};
109
110
enum {
111
  RDPDR_DTYP_SERIAL = 0x01,
112
  RDPDR_DTYP_PARALLEL = 0x02,
113
  RDPDR_DTYP_PRINT = 0x04,
114
  RDPDR_DTYP_FILESYSTEM = 0x08,
115
  RDPDR_DTYP_SMARTCARD = 0x20,
116
};
117
118
enum {
119
  CAP_GENERAL_TYPE = 0x0001,
120
  CAP_PRINTER_TYPE = 0x0002,
121
  CAP_PORT_TYPE = 0x0003,
122
  CAP_DRIVE_TYPE = 0x0004,
123
  CAP_SMARTCARD_TYPE = 0x0005
124
};
125
126
static const value_string rdpdr_capaType_vals[] = {
127
  { CAP_GENERAL_TYPE, "General" },
128
  { CAP_PRINTER_TYPE, "Printer" },
129
  { CAP_PORT_TYPE, "Port" },
130
  { CAP_DRIVE_TYPE, "Drive" },
131
  { CAP_SMARTCARD_TYPE, "Smartcard" },
132
  { 0x0, NULL},
133
};
134
135
enum {
136
  IRP_MJ_CREATE = 0x00000000,
137
  IRP_MJ_CLOSE = 0x00000002,
138
  IRP_MJ_READ = 0x00000003,
139
  IRP_MJ_WRITE = 0x00000004,
140
  IRP_MJ_DEVICE_CONTROL = 0x0000000E,
141
  IRP_MJ_QUERY_VOLUME_INFORMATION = 0x0000000A,
142
  IRP_MJ_SET_VOLUME_INFORMATION = 0x0000000B,
143
  IRP_MJ_QUERY_INFORMATION = 0x00000005,
144
  IRP_MJ_SET_INFORMATION = 0x00000006,
145
  IRP_MJ_DIRECTORY_CONTROL = 0x0000000C,
146
  IRP_MJ_LOCK_CONTROL = 0x00000011,
147
148
  IRP_MN_QUERY_DIRECTORY = 0x00000001,
149
  IRP_MN_NOTIFY_CHANGE_DIRECTORY = 0x00000002,
150
};
151
152
enum {
153
  FILE_SUPERSEDED = 0x00000000,
154
  FILE_OPENED = 0x00000001,
155
  FILE_OVERWRITTEN = 0x00000003,
156
};
157
158
static const value_string rdpdr_component_vals[] = {
159
  { RDPDR_CTYP_CORE, "RDPDR_CTYP_CORE"},
160
  { RDPDR_CTYP_PRN, "RDPDR_CTYP_PRN"},
161
  { 0x0, NULL},
162
};
163
164
static const value_string rdpdr_packetid_vals[] = {
165
  { PAKID_CORE_SERVER_ANNOUNCE, "PAKID_CORE_SERVER_ANNOUNCE" },
166
  { PAKID_CORE_CLIENTID_CONFIRM, "PAKID_CORE_CLIENTID_CONFIRM" },
167
  { PAKID_CORE_CLIENT_NAME, "PAKID_CORE_CLIENT_NAME" },
168
  { PAKID_CORE_DEVICELIST_ANNOUNCE, "PAKID_CORE_DEVICELIST_ANNOUNCE"},
169
  { PAKID_CORE_DEVICE_REPLY, "PAKID_CORE_DEVICE_REPLY"},
170
  { PAKID_CORE_DEVICE_IOREQUEST, "PAKID_CORE_DEVICE_IOREQUEST"},
171
  { PAKID_CORE_DEVICE_IOCOMPLETION, "PAKID_CORE_DEVICE_IOCOMPLETION"},
172
  { PAKID_CORE_SERVER_CAPABILITY, "PAKID_CORE_SERVER_CAPABILITY"},
173
  { PAKID_CORE_CLIENT_CAPABILITY, "PAKID_CORE_CLIENT_CAPABILITY"},
174
  { PAKID_CORE_DEVICELIST_REMOVE, "PAKID_CORE_DEVICELIST_REMOVE"},
175
  { PAKID_PRN_CACHE_DATA, "PAKID_PRN_CACHE_DATA"},
176
  { PAKID_CORE_USER_LOGGEDON, "PAKID_CORE_USER_LOGGEDON"},
177
  { PAKID_PRN_USING_XPS, "PAKID_PRN_USING_XPS"},
178
  { 0x0, NULL},
179
};
180
181
static const value_string rdpdr_deviceType_vals[] = {
182
  { RDPDR_DTYP_SERIAL, "RDPDR_DTYP_SERIAL"},
183
  { RDPDR_DTYP_PARALLEL, "RDPDR_DTYP_PARALLEL"},
184
  { RDPDR_DTYP_PRINT, "RDPDR_DTYP_PRINT"},
185
  { RDPDR_DTYP_FILESYSTEM, "RDPDR_DTYP_FILESYSTEM"},
186
  { RDPDR_DTYP_SMARTCARD, "RDPDR_DTYP_SMARTCARD"},
187
  { 0x0, NULL},
188
};
189
190
static const value_string rdpdr_dr_majorF_vals[] = {
191
  { IRP_MJ_CREATE, "IRP_MJ_CREATE" },
192
  { IRP_MJ_CLOSE, "IRP_MJ_CLOSE" },
193
  { IRP_MJ_READ, "IRP_MJ_READ" },
194
  { IRP_MJ_WRITE, "IRP_MJ_WRITE" },
195
  { IRP_MJ_DEVICE_CONTROL, "IRP_MJ_DEVICE_CONTROL" },
196
  { IRP_MJ_QUERY_VOLUME_INFORMATION, "IRP_MJ_QUERY_VOLUME_INFORMATION" },
197
  { IRP_MJ_SET_VOLUME_INFORMATION, "IRP_MJ_SET_VOLUME_INFORMATION" },
198
  { IRP_MJ_QUERY_INFORMATION, "IRP_MJ_QUERY_INFORMATION" },
199
  { IRP_MJ_SET_INFORMATION, "IRP_MJ_SET_INFORMATION" },
200
  { IRP_MJ_DIRECTORY_CONTROL, "IRP_MJ_DIRECTORY_CONTROL" },
201
  { IRP_MJ_LOCK_CONTROL, "IRP_MJ_LOCK_CONTROL" },
202
  { 0x0, NULL},
203
};
204
205
static const value_string rdpdr_dr_minorF_vals[] = {
206
  { IRP_MN_QUERY_DIRECTORY, "IRP_MN_QUERY_DIRECTORY" },
207
  { IRP_MN_NOTIFY_CHANGE_DIRECTORY, "IRP_MN_NOTIFY_CHANGE_DIRECTORY" },
208
  { 0x0, NULL},
209
};
210
211
static const value_string rdpdr_dr_createinfo_vals[] = {
212
    { FILE_SUPERSEDED, "FILE_SUPERSEDED" },
213
    { FILE_OPENED, "FILE_OPENED" },
214
    { FILE_OVERWRITTEN, "FILE_OVERWRITTEN" },
215
    { 0x0, NULL},
216
};
217
218
enum {
219
  SCARD_IOCTL_ESTABLISHCONTEXT = 0x00090014,
220
  SCARD_IOCTL_RELEASECONTEXT = 0x00090018,
221
  SCARD_IOCTL_ISVALIDCONTEXT = 0x0009001C,
222
  SCARD_IOCTL_LISTREADERGROUPSA = 0x00090020,
223
  SCARD_IOCTL_LISTREADERGROUPSW = 0x00090024,
224
  SCARD_IOCTL_LISTREADERSA = 0x00090028,
225
  SCARD_IOCTL_LISTREADERSW = 0x0009002C,
226
  SCARD_IOCTL_INTRODUCEREADERGROUPA = 0x00090050,
227
  SCARD_IOCTL_INTRODUCEREADERGROUPW = 0x00090054,
228
  SCARD_IOCTL_FORGETREADERGROUPA = 0x00090058,
229
  SCARD_IOCTL_FORGETREADERGROUPW = 0x0009005C,
230
  SCARD_IOCTL_INTRODUCEREADERA = 0x00090060,
231
  SCARD_IOCTL_INTRODUCEREADERW = 0x00090064,
232
  SCARD_IOCTL_FORGETREADERA = 0x00090068,
233
  SCARD_IOCTL_FORGETREADERW = 0x0009006C,
234
  SCARD_IOCTL_ADDREADERTOGROUPA = 0x00090070,
235
  SCARD_IOCTL_ADDREADERTOGROUPW = 0x00090074,
236
  SCARD_IOCTL_REMOVEREADERFROMGROUPA = 0x00090078,
237
  SCARD_IOCTL_REMOVEREADERFROMGROUPW = 0x0009007C,
238
  SCARD_IOCTL_LOCATECARDSA = 0x00090098,
239
  SCARD_IOCTL_LOCATECARDSW = 0x0009009C,
240
  SCARD_IOCTL_GETSTATUSCHANGEA = 0x000900A0,
241
  SCARD_IOCTL_GETSTATUSCHANGEW = 0x000900A4,
242
  SCARD_IOCTL_CANCEL = 0x000900A8,
243
  SCARD_IOCTL_CONNECTA = 0x000900AC,
244
  SCARD_IOCTL_CONNECTW = 0x000900B0,
245
  SCARD_IOCTL_RECONNECT = 0x000900B4,
246
  SCARD_IOCTL_DISCONNECT = 0x000900B8,
247
  SCARD_IOCTL_BEGINTRANSACTION = 0x000900BC,
248
  SCARD_IOCTL_ENDTRANSACTION = 0x000900C0,
249
  SCARD_IOCTL_STATE = 0x000900C4,
250
  SCARD_IOCTL_STATUSA = 0x000900C8,
251
  SCARD_IOCTL_STATUSW = 0x000900CC,
252
  SCARD_IOCTL_TRANSMIT = 0x000900D0,
253
  SCARD_IOCTL_CONTROL = 0x000900D4,
254
  SCARD_IOCTL_GETATTRIB = 0x000900D8,
255
  SCARD_IOCTL_SETATTRIB = 0x000900DC,
256
  SCARD_IOCTL_ACCESSSTARTEDEVENT = 0x000900E0,
257
  SCARD_IOCTL_LOCATECARDSBYATRA = 0x000900E8,
258
  SCARD_IOCTL_LOCATECARDSBYATRW = 0x000900EC,
259
  SCARD_IOCTL_READCACHEA = 0x000900F0,
260
  SCARD_IOCTL_READCACHEW = 0x000900F4,
261
  SCARD_IOCTL_WRITECACHEA = 0x000900F8,
262
  SCARD_IOCTL_WRITECACHEW = 0x000900FC,
263
  SCARD_IOCTL_GETTRANSMITCOUNT = 0x00090100,
264
  SCARD_IOCTL_RELEASETARTEDEVENT = 0x000900E4,
265
  SCARD_IOCTL_GETREADERICON = 0x00090104,
266
  SCARD_IOCTL_GETDEVICETYPEID = 0x00090108,
267
};
268
269
enum {
270
  RDPDR_ADD_PRINTER_EVENT = 0x00000001,
271
  RDPDR_UPDATE_PRINTER_EVENT = 0x00000002,
272
  RDPDR_DELETE_PRINTER_EVENT = 0x00000003,
273
  RDPDR_RENAME_PRINTER_EVENT = 0x00000004,
274
};
275
276
#define STR_VALUE(v) { v, #v }
277
static const value_string rdpdr_dr_ioControlCode_vals[] = {
278
  STR_VALUE(SCARD_IOCTL_ESTABLISHCONTEXT),
279
  STR_VALUE(SCARD_IOCTL_RELEASECONTEXT),
280
  STR_VALUE(SCARD_IOCTL_ISVALIDCONTEXT),
281
  STR_VALUE(SCARD_IOCTL_LISTREADERGROUPSA),
282
  STR_VALUE(SCARD_IOCTL_LISTREADERGROUPSW),
283
  STR_VALUE(SCARD_IOCTL_LISTREADERSA),
284
  STR_VALUE(SCARD_IOCTL_LISTREADERSW),
285
  STR_VALUE(SCARD_IOCTL_INTRODUCEREADERGROUPA),
286
  STR_VALUE(SCARD_IOCTL_INTRODUCEREADERGROUPW),
287
  STR_VALUE(SCARD_IOCTL_FORGETREADERGROUPA),
288
  STR_VALUE(SCARD_IOCTL_FORGETREADERGROUPW),
289
  STR_VALUE(SCARD_IOCTL_INTRODUCEREADERA),
290
  STR_VALUE(SCARD_IOCTL_INTRODUCEREADERW),
291
  STR_VALUE(SCARD_IOCTL_FORGETREADERA),
292
  STR_VALUE(SCARD_IOCTL_FORGETREADERW),
293
  STR_VALUE(SCARD_IOCTL_ADDREADERTOGROUPA),
294
  STR_VALUE(SCARD_IOCTL_ADDREADERTOGROUPW),
295
  STR_VALUE(SCARD_IOCTL_REMOVEREADERFROMGROUPA),
296
  STR_VALUE(SCARD_IOCTL_REMOVEREADERFROMGROUPW),
297
  STR_VALUE(SCARD_IOCTL_LOCATECARDSA),
298
  STR_VALUE(SCARD_IOCTL_LOCATECARDSW),
299
  STR_VALUE(SCARD_IOCTL_GETSTATUSCHANGEA),
300
  STR_VALUE(SCARD_IOCTL_GETSTATUSCHANGEW),
301
  STR_VALUE(SCARD_IOCTL_CANCEL),
302
  STR_VALUE(SCARD_IOCTL_CONNECTA),
303
  STR_VALUE(SCARD_IOCTL_CONNECTW),
304
  STR_VALUE(SCARD_IOCTL_RECONNECT),
305
  STR_VALUE(SCARD_IOCTL_DISCONNECT),
306
  STR_VALUE(SCARD_IOCTL_BEGINTRANSACTION),
307
  STR_VALUE(SCARD_IOCTL_ENDTRANSACTION),
308
  STR_VALUE(SCARD_IOCTL_STATE),
309
  STR_VALUE(SCARD_IOCTL_STATUSA),
310
  STR_VALUE(SCARD_IOCTL_STATUSW),
311
  STR_VALUE(SCARD_IOCTL_TRANSMIT),
312
  STR_VALUE(SCARD_IOCTL_CONTROL),
313
  STR_VALUE(SCARD_IOCTL_GETATTRIB),
314
  STR_VALUE(SCARD_IOCTL_SETATTRIB),
315
  STR_VALUE(SCARD_IOCTL_ACCESSSTARTEDEVENT),
316
  STR_VALUE(SCARD_IOCTL_LOCATECARDSBYATRA),
317
  STR_VALUE(SCARD_IOCTL_LOCATECARDSBYATRW),
318
  STR_VALUE(SCARD_IOCTL_READCACHEA),
319
  STR_VALUE(SCARD_IOCTL_READCACHEW),
320
  STR_VALUE(SCARD_IOCTL_WRITECACHEA),
321
  STR_VALUE(SCARD_IOCTL_WRITECACHEW),
322
  STR_VALUE(SCARD_IOCTL_GETTRANSMITCOUNT),
323
  STR_VALUE(SCARD_IOCTL_RELEASETARTEDEVENT),
324
  STR_VALUE(SCARD_IOCTL_GETREADERICON),
325
  STR_VALUE(SCARD_IOCTL_GETDEVICETYPEID),
326
  { 0x0, NULL},
327
};
328
329
static const value_string rdpdr_printer_cacheEvent_vals[] = {
330
  STR_VALUE(RDPDR_ADD_PRINTER_EVENT),
331
  STR_VALUE(RDPDR_UPDATE_PRINTER_EVENT),
332
  STR_VALUE(RDPDR_DELETE_PRINTER_EVENT),
333
  STR_VALUE(RDPDR_RENAME_PRINTER_EVENT),
334
  { 0x0, NULL},
335
};
336
337
#undef STR_VALUE
338
339
typedef struct {
340
  uint32_t completionId;
341
  uint32_t reqFrame;
342
  uint32_t resFrame;
343
  uint32_t majorFn;
344
  uint32_t minorFn;
345
  uint32_t ioControlCode;
346
} DrIoRequest;
347
348
typedef struct {
349
  uint32_t deviceType;
350
  uint32_t deviceId;
351
  char name[9];
352
  wmem_multimap_t *ioRequests;
353
} DrDevice;
354
355
typedef struct {
356
  wmem_multimap_t *channels;
357
} rdpdr_conv_info_t;
358
359
0
static unsigned idptr_hashFunc(const void *key) {
360
0
  uint32_t *intPtr = (uint32_t *)key;
361
362
0
  return *intPtr;
363
0
}
364
365
0
static gboolean idptr_equalFunc(const void *a, const void *b) {
366
0
  uint32_t *aPtr = (uint32_t *)a;
367
0
  uint32_t *bPtr = (uint32_t *)b;
368
369
0
  return (*aPtr == *bPtr);
370
0
}
371
372
373
static rdpdr_conv_info_t *
374
rdpdr_get_conversation_data(packet_info *pinfo)
375
0
{
376
0
  conversation_t *conversation, *conversation_tcp;
377
0
  rdpdr_conv_info_t *info;
378
379
0
  conversation = find_or_create_conversation(pinfo);
380
381
0
  info = (rdpdr_conv_info_t *)conversation_get_proto_data(conversation, proto_rdpdr);
382
0
  if (!info) {
383
0
    conversation_tcp = rdp_find_tcp_conversation_from_udp(conversation);
384
0
    if (conversation_tcp)
385
0
      info = (rdpdr_conv_info_t *)conversation_get_proto_data(conversation_tcp, proto_rdpdr);
386
0
  }
387
388
0
  if (info == NULL) {
389
0
    info = wmem_new0(wmem_file_scope(), rdpdr_conv_info_t);
390
0
    info->channels = wmem_multimap_new(wmem_file_scope(), idptr_hashFunc, idptr_equalFunc);
391
0
    conversation_add_proto_data(conversation, proto_rdpdr, info);
392
0
  }
393
394
0
  return info;
395
0
}
396
397
static int
398
dissect_smartcard_req(tvbuff_t *in_tvb, int in_offset, packet_info *pinfo, proto_tree *tree, uint32_t ioControlCode)
399
0
{
400
0
  col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s req", val_to_str_const(ioControlCode, rdpdr_dr_ioControlCode_vals, "<unknown>"));
401
0
  if (ioControlCode == SCARD_IOCTL_ACCESSSTARTEDEVENT)
402
0
    return in_offset + 4;
403
404
0
  dcerpc_info di = { 0 };
405
0
  uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00};
406
407
0
  dcerpc_call_value call_data = { 0 };
408
0
  di.conformant_run = 0;
409
0
  di.call_data = &call_data;
410
0
  init_ndr_pointer_list(&di);
411
412
0
  int offset = 16;
413
0
  tvbuff_t *tvb = tvb_new_subset_remaining(in_tvb, in_offset);
414
415
0
  switch (ioControlCode) {
416
0
  case SCARD_IOCTL_ESTABLISHCONTEXT:
417
0
    offset = scard_pack_dissect_struct_EstablishContext_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
418
0
    break;
419
0
  case SCARD_IOCTL_ISVALIDCONTEXT:
420
0
  case SCARD_IOCTL_RELEASECONTEXT:
421
0
  case SCARD_IOCTL_CANCEL:
422
0
    offset = scard_pack_dissect_struct_Context_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
423
0
    break;
424
0
  case SCARD_IOCTL_LISTREADERSA:
425
0
    offset = scard_pack_dissect_struct_ListReadersA_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
426
0
    break;
427
0
  case SCARD_IOCTL_LISTREADERSW:
428
0
    offset = scard_pack_dissect_struct_ListReadersW_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
429
0
    break;
430
0
  case SCARD_IOCTL_GETDEVICETYPEID:
431
0
    offset = scard_pack_dissect_struct_GetDeviceTypeId_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
432
0
    break;
433
0
  case SCARD_IOCTL_GETSTATUSCHANGEA:
434
0
    offset = scard_pack_dissect_struct_GetStatusChangeA_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
435
0
    break;
436
0
  case SCARD_IOCTL_GETSTATUSCHANGEW:
437
0
    offset = scard_pack_dissect_struct_GetStatusChangeW_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
438
0
    break;
439
0
  case SCARD_IOCTL_CONNECTA:
440
0
    offset = scard_pack_dissect_struct_ConnectA_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
441
0
    break;
442
0
  case SCARD_IOCTL_CONNECTW:
443
0
    offset = scard_pack_dissect_struct_ConnectW_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
444
0
    break;
445
0
  case SCARD_IOCTL_DISCONNECT:
446
0
  case SCARD_IOCTL_BEGINTRANSACTION:
447
0
  case SCARD_IOCTL_ENDTRANSACTION:
448
0
    offset = scard_pack_dissect_struct_HCardAndDisposition_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
449
0
    break;
450
0
  case SCARD_IOCTL_STATE:
451
0
    offset = scard_pack_dissect_struct_State_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
452
0
    break;
453
0
  case SCARD_IOCTL_STATUSA:
454
0
  case SCARD_IOCTL_STATUSW:
455
0
    offset = scard_pack_dissect_struct_Status_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
456
0
    break;
457
0
  case SCARD_IOCTL_TRANSMIT:
458
0
    offset = scard_pack_dissect_struct_Transmit_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
459
0
    break;
460
0
  case SCARD_IOCTL_READCACHEA:
461
0
    offset = scard_pack_dissect_struct_ReadCacheA_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
462
0
    break;
463
0
  case SCARD_IOCTL_READCACHEW:
464
0
    offset = scard_pack_dissect_struct_ReadCacheW_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
465
0
    break;
466
0
  case SCARD_IOCTL_WRITECACHEA:
467
0
    offset = scard_pack_dissect_struct_WriteCacheA_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
468
0
    break;
469
0
  case SCARD_IOCTL_WRITECACHEW:
470
0
    offset = scard_pack_dissect_struct_WriteCacheW_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
471
0
    break;
472
0
  case SCARD_IOCTL_GETATTRIB:
473
0
    offset = scard_pack_dissect_struct_GetAttrib_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
474
0
    break;
475
0
  case SCARD_IOCTL_RECONNECT:
476
0
    offset = scard_pack_dissect_struct_Reconnect_Call(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
477
0
    break;
478
0
  default:
479
0
    return in_offset;
480
0
  }
481
0
  return in_offset + dissect_deferred_pointers(pinfo, tvb, offset, &di, drep);
482
0
}
483
484
static int
485
dissect_smartcard_resp(tvbuff_t *in_tvb, int in_offset, packet_info *pinfo, proto_tree *tree, uint32_t ioControlCode)
486
0
{
487
0
  col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s resp", val_to_str_const(ioControlCode, rdpdr_dr_ioControlCode_vals, "<unknown>"));
488
489
0
  dcerpc_info di = { 0 };
490
0
  uint8_t drep[4] = { 0x10, 0x00, 0x00, 0x00};
491
492
0
  dcerpc_call_value call_data = { 0 };
493
0
  di.conformant_run = 0;
494
0
  di.call_data = &call_data;
495
0
  init_ndr_pointer_list(&di);
496
497
0
  int offset = 16;
498
0
  proto_tree_add_item(tree, hf_rdpdr_ioreq_sc_returnCode, in_tvb, in_offset + 16, 4, ENC_LITTLE_ENDIAN);
499
0
  offset += 4;
500
0
  tvbuff_t *tvb = tvb_new_subset_remaining(in_tvb, in_offset);
501
502
0
  switch (ioControlCode) {
503
0
  case SCARD_IOCTL_ESTABLISHCONTEXT:
504
0
    offset = scard_pack_dissect_struct_EstablishContext_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
505
0
    break;
506
0
  case SCARD_IOCTL_ACCESSSTARTEDEVENT:
507
0
  case SCARD_IOCTL_ISVALIDCONTEXT:
508
0
  case SCARD_IOCTL_RELEASECONTEXT:
509
0
  case SCARD_IOCTL_DISCONNECT:
510
0
  case SCARD_IOCTL_CANCEL:
511
0
  case SCARD_IOCTL_BEGINTRANSACTION:
512
0
  case SCARD_IOCTL_ENDTRANSACTION:
513
0
  case SCARD_IOCTL_WRITECACHEA:
514
0
  case SCARD_IOCTL_WRITECACHEW:
515
0
  case SCARD_IOCTL_SETATTRIB:
516
0
  case SCARD_IOCTL_INTRODUCEREADERGROUPA:
517
0
  case SCARD_IOCTL_INTRODUCEREADERGROUPW:
518
0
  case SCARD_IOCTL_FORGETREADERGROUPA:
519
0
  case SCARD_IOCTL_FORGETREADERGROUPW:
520
0
  case SCARD_IOCTL_INTRODUCEREADERA:
521
0
  case SCARD_IOCTL_INTRODUCEREADERW:
522
0
  case SCARD_IOCTL_FORGETREADERA:
523
0
  case SCARD_IOCTL_FORGETREADERW:
524
0
  case SCARD_IOCTL_ADDREADERTOGROUPA:
525
0
  case SCARD_IOCTL_ADDREADERTOGROUPW:
526
0
  case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
527
0
  case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
528
0
    offset = scard_pack_dissect_struct_long_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
529
0
    break;
530
0
  case SCARD_IOCTL_LISTREADERSA:
531
0
  case SCARD_IOCTL_LISTREADERSW:
532
0
    offset = scard_pack_dissect_struct_ListReaders_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
533
0
    break;
534
0
  case SCARD_IOCTL_GETDEVICETYPEID:
535
0
    offset = scard_pack_dissect_struct_GetDeviceTypeId_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
536
0
    break;
537
0
  case SCARD_IOCTL_GETSTATUSCHANGEA:
538
0
  case SCARD_IOCTL_GETSTATUSCHANGEW:
539
0
    offset = scard_pack_dissect_struct_GetStatusChange_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
540
0
    break;
541
0
  case SCARD_IOCTL_CONNECTA:
542
0
  case SCARD_IOCTL_CONNECTW:
543
0
    offset = scard_pack_dissect_struct_Connect_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
544
0
    break;
545
0
  case SCARD_IOCTL_RECONNECT:
546
0
    offset = scard_pack_dissect_struct_Reconnect_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
547
0
    break;
548
0
  case SCARD_IOCTL_STATUSA:
549
0
  case SCARD_IOCTL_STATUSW:
550
0
    offset = scard_pack_dissect_struct_Status_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
551
0
    break;
552
0
  case SCARD_IOCTL_TRANSMIT:
553
0
    offset = scard_pack_dissect_struct_Transmit_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
554
0
    break;
555
0
  case SCARD_IOCTL_READCACHEA:
556
0
  case SCARD_IOCTL_READCACHEW:
557
0
    offset = scard_pack_dissect_struct_ReadCache_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
558
0
    break;
559
0
  case SCARD_IOCTL_GETATTRIB:
560
0
    offset = scard_pack_dissect_struct_GetAttrib_Return(tvb, offset, pinfo, tree, &di, drep, hf_rdpdr_ioreq_sc_command, 0);
561
0
    break;
562
0
  default:
563
0
    return in_offset;
564
0
  }
565
566
0
  return in_offset + dissect_deferred_pointers(pinfo, tvb, offset, &di, drep);
567
0
}
568
569
570
static int
571
dissect_rdpdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree _U_, void *data _U_)
572
0
{
573
0
  proto_item *item;
574
0
  unsigned offset = 0;
575
0
  proto_tree *tree;
576
  //bool packetToServer = rdp_isServerAddressTarget(pinfo);
577
578
0
  parent_tree = proto_tree_get_root(parent_tree);
579
0
  item = proto_tree_add_item(parent_tree, proto_rdpdr, tvb, 0, -1, ENC_NA);
580
0
  tree = proto_item_add_subtree(item, ett_rdpdr);
581
582
0
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "RDPDR");
583
0
  col_clear(pinfo->cinfo, COL_INFO);
584
585
0
  uint32_t component, packetId;
586
0
  proto_tree_add_item_ret_uint(tree, hf_rdpdr_component, tvb, offset, 2, ENC_LITTLE_ENDIAN, &component);
587
0
  offset += 2;
588
0
  proto_tree_add_item_ret_uint(tree, hf_rdpdr_packetid, tvb, offset, 2, ENC_LITTLE_ENDIAN, &packetId);
589
0
  offset += 2;
590
591
0
  rdpdr_conv_info_t *info = rdpdr_get_conversation_data(pinfo);
592
0
  uint32_t deviceId;
593
594
0
  if (component == RDPDR_CTYP_CORE) {
595
0
    switch(packetId) {
596
0
    case PAKID_CORE_SERVER_ANNOUNCE:
597
0
      col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Server announce");
598
0
      break;
599
0
    case PAKID_CORE_DEVICELIST_ANNOUNCE: {
600
0
      col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "Device list announce");
601
0
      uint32_t deviceCount;
602
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_deviceCount, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceCount);
603
0
      offset += 4;
604
605
0
      for (uint32_t i = 0; i < deviceCount; i++) {
606
0
        uint32_t deviceDataLen = tvb_get_uint32(tvb, offset + 16, ENC_LITTLE_ENDIAN);
607
0
        char dosName[8];
608
0
        tvb_get_raw_bytes_as_string(tvb, offset + 8, dosName, 8);
609
610
0
        proto_tree *dev_tree = proto_tree_add_subtree(tree, tvb, offset, 16 + deviceDataLen, ett_rdpdr_device, NULL, dosName);
611
612
0
        uint32_t deviceType;
613
0
        proto_tree_add_item_ret_uint(dev_tree, hf_rdpdr_deviceType, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceType);
614
0
        offset += 4;
615
0
        proto_tree_add_item_ret_uint(dev_tree, hf_rdpdr_deviceId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceId);
616
0
        offset += 4;
617
0
        proto_tree_add_item(dev_tree, hf_rdpdr_dosName, tvb, offset, 8, ENC_ASCII);
618
0
        offset += 8;
619
0
        proto_tree_add_item(dev_tree, hf_rdpdr_deviceDataLen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
620
0
        offset += 4;
621
0
        proto_tree_add_item(dev_tree, hf_rdpdr_deviceData, tvb, offset, deviceDataLen, ENC_NA);
622
0
        offset += deviceDataLen;
623
624
0
        if (!PINFO_FD_VISITED(pinfo)) {
625
0
          DrDevice *device = wmem_alloc(wmem_file_scope(), sizeof(*device));
626
0
          device->deviceId = deviceId;
627
0
          device->deviceType = deviceType;
628
0
          memcpy(device->name, dosName, 8);
629
0
          device->name[8] = 0;
630
0
          device->ioRequests = wmem_multimap_new(wmem_file_scope(), idptr_hashFunc, idptr_equalFunc);
631
632
0
          wmem_multimap_insert32(info->channels, &device->deviceId, pinfo->num, device);
633
0
        }
634
0
      }
635
0
      break;
636
0
    }
637
0
    case PAKID_CORE_DEVICE_IOREQUEST: {
638
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_deviceId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceId);
639
0
      offset += 4;
640
641
0
      DrDevice *device = wmem_multimap_lookup32_le(info->channels, &deviceId, pinfo->num);
642
643
0
      uint32_t dtype = RDPDR_DTYP_FILESYSTEM;
644
0
      if (device)
645
0
        dtype = device->deviceType;
646
647
0
      int majorFnIdx;
648
0
      int minorFnIdx;
649
0
      switch(dtype) {
650
0
      case RDPDR_DTYP_SMARTCARD:
651
0
        majorFnIdx = hf_rdpdr_ioreq_sc_majorFunction;
652
0
        minorFnIdx = hf_rdpdr_ioreq_sc_minorFunction;
653
0
        break;
654
0
      case RDPDR_DTYP_FILESYSTEM:
655
0
      default:
656
0
        majorFnIdx = hf_rdpdr_ioreq_dr_majorFunction;
657
0
        minorFnIdx = hf_rdpdr_ioreq_dr_minorFunction;
658
0
        break;
659
0
      }
660
661
0
      uint32_t fileId, completionId;
662
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_fileId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &fileId);
663
0
      offset += 4;
664
665
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_completionId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &completionId);
666
0
      offset += 4;
667
668
0
      uint32_t majorFn;
669
0
      proto_tree_add_item_ret_uint(tree, majorFnIdx, tvb, offset, 4, ENC_LITTLE_ENDIAN, &majorFn);
670
0
      offset += 4;
671
672
0
      uint32_t minorFn;
673
0
      proto_tree_add_item_ret_uint(tree, minorFnIdx, tvb, offset, 4, ENC_LITTLE_ENDIAN, &minorFn);
674
0
      offset += 4;
675
676
0
      DrIoRequest *ioReq = NULL;
677
0
      if (!PINFO_FD_VISITED(pinfo)) {
678
0
        if (device) {
679
0
          ioReq = wmem_alloc(wmem_file_scope(), sizeof(*ioReq));
680
681
0
          ioReq->completionId = completionId;
682
0
          ioReq->majorFn = majorFn;
683
0
          ioReq->minorFn = minorFn;
684
0
          ioReq->reqFrame = pinfo->num;
685
0
          ioReq->resFrame = 0;
686
687
0
          wmem_multimap_insert32(device->ioRequests, &ioReq->completionId, pinfo->num, ioReq);
688
0
        }
689
0
      } else {
690
0
        if (device)
691
0
          ioReq = wmem_multimap_lookup32_le(device->ioRequests, &completionId, pinfo->num);
692
0
      }
693
694
0
      switch(majorFn) {
695
0
      case IRP_MJ_CREATE:
696
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_CREATE");
697
0
        break;
698
0
      case IRP_MJ_CLOSE:
699
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_CLOSE");
700
0
        break;
701
0
      case IRP_MJ_READ:
702
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_READ");
703
0
        break;
704
0
      case IRP_MJ_WRITE:
705
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_WRITE");
706
0
        break;
707
0
      case IRP_MJ_DEVICE_CONTROL: {
708
0
        uint32_t inputBufLen;
709
0
        uint32_t ioControlCode;
710
        //col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_DEVICE_CONTROL");
711
0
        proto_tree_add_item(tree, hf_rdpdr_io_request_control_outputBufLen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
712
0
        offset += 4;
713
714
0
        proto_tree_add_item_ret_uint(tree, hf_rdpdr_io_request_control_inputBufLen, tvb, offset, 4, ENC_LITTLE_ENDIAN, &inputBufLen);
715
0
        offset += 4;
716
717
0
        proto_tree_add_item_ret_uint(tree, hf_rdpdr_io_request_control_ioControlCode, tvb, offset, 4, ENC_LITTLE_ENDIAN, &ioControlCode);
718
0
        offset += 4;
719
720
0
        proto_tree_add_item(tree, hf_rdpdr_io_request_control_padding, tvb, offset, 20, ENC_NA);
721
0
        offset += 20;
722
723
0
        if (!PINFO_FD_VISITED(pinfo) && ioReq)
724
0
          ioReq->ioControlCode = ioControlCode;
725
726
0
        if (device && device->deviceType == RDPDR_DTYP_SMARTCARD)
727
0
          dissect_smartcard_req(tvb, offset, pinfo, tree, ioControlCode);
728
0
        break;
729
0
      }
730
0
      case IRP_MJ_QUERY_VOLUME_INFORMATION:
731
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_QUERY_VOLUME_INFORMATION");
732
0
        break;
733
0
      case IRP_MJ_SET_VOLUME_INFORMATION:
734
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_SET_VOLUME_INFORMATION");
735
0
        break;
736
0
      case IRP_MJ_QUERY_INFORMATION:
737
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_QUERY_INFORMATION");
738
0
        break;
739
0
      case IRP_MJ_SET_INFORMATION:
740
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_SET_INFORMATION");
741
0
        break;
742
0
      case IRP_MJ_DIRECTORY_CONTROL:
743
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_DIRECTORY_CONTROL");
744
0
        break;
745
0
      case IRP_MJ_LOCK_CONTROL:
746
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS IRP_MJ_LOCK_CONTROL");
747
0
        break;
748
0
      default:
749
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "FS unhandled");
750
0
        break;
751
0
      }
752
753
0
      if (ioReq) {
754
0
        if (ioReq->resFrame) {
755
0
          proto_item_set_generated(
756
0
            proto_tree_add_uint(tree, hf_rdpdr_io_result_frame, tvb, 0, 0, ioReq->resFrame)
757
0
          );
758
0
        }
759
0
      }
760
0
      break;
761
0
    }
762
0
    case PAKID_CORE_DEVICE_REPLY: {
763
0
      uint32_t statusCode;
764
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_deviceId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceId);
765
0
      offset += 4;
766
767
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_resultCode, tvb, offset, 4, ENC_LITTLE_ENDIAN, &statusCode);
768
0
      offset += 4;
769
770
0
      DrDevice *device = wmem_multimap_lookup32_le(info->channels, &deviceId, pinfo->num);
771
0
      if (device)
772
0
        col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s, status=0x%x", device->name, statusCode);
773
0
      break;
774
0
    }
775
0
    case PAKID_CORE_DEVICE_IOCOMPLETION: {
776
0
      uint32_t statusCode, completionId;
777
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_deviceId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceId);
778
0
      offset += 4;
779
780
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_completionId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &completionId);
781
0
      offset += 4;
782
783
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_ioStatus, tvb, offset, 4, ENC_LITTLE_ENDIAN, &statusCode);
784
0
      offset += 4;
785
786
      //const char *name = NULL;
787
0
      DrIoRequest *ioReq = NULL;
788
0
      DrDevice *device = wmem_multimap_lookup32_le(info->channels, &deviceId, pinfo->num);
789
0
      if (device) {
790
        //name = device->name;
791
0
        ioReq = wmem_multimap_lookup32_le(device->ioRequests, &completionId, pinfo->num);
792
0
        if (ioReq) {
793
0
          if (!PINFO_FD_VISITED(pinfo))
794
0
            ioReq->resFrame = pinfo->num;
795
0
        }
796
0
      }
797
798
0
      if (ioReq) {
799
0
        proto_item_set_generated(
800
0
          proto_tree_add_uint(tree, hf_rdpdr_io_request_frame, tvb, 0, 0, ioReq->reqFrame)
801
0
        );
802
803
0
        if (device->deviceType == RDPDR_DTYP_FILESYSTEM) {
804
0
          switch(ioReq->majorFn) {
805
0
          case IRP_MJ_CREATE:
806
0
            if (tvb_captured_length_remaining(tvb, offset)) {
807
0
              proto_tree_add_item(tree, hf_rdpdr_create_info, tvb, offset, 1, ENC_LITTLE_ENDIAN);
808
0
            }
809
0
            break;
810
0
          }
811
0
        } else if (device->deviceType == RDPDR_DTYP_SMARTCARD) {
812
0
          if (ioReq->majorFn == IRP_MJ_DEVICE_CONTROL)
813
0
            return dissect_smartcard_resp(tvb, offset, pinfo, tree, ioReq->ioControlCode);
814
0
        }
815
0
      }
816
      //col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s%sIO completion completionId=0x%x status=0x%x", name ? name : "", name ? " " : "", completionId, statusCode);
817
0
      break;
818
0
    }
819
820
0
    case PAKID_CORE_CLIENT_CAPABILITY:
821
0
    case PAKID_CORE_SERVER_CAPABILITY: {
822
0
      col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s", val_to_str_const(packetId, rdpdr_packetid_vals, "<unknown command>"));
823
824
0
      uint32_t ncapa;
825
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_numCapabilities, tvb, offset, 2, ENC_LITTLE_ENDIAN, &ncapa);
826
0
      offset += 2;
827
828
0
      proto_tree_add_item(tree, hf_rdpdr_padding, tvb, offset, 2, ENC_LITTLE_ENDIAN);
829
0
      offset += 2;
830
831
832
0
      for (uint32_t i = 0; i < ncapa; i++) {
833
0
        uint32_t capaType = tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN);
834
0
        uint32_t capaLen = tvb_get_uint16(tvb, offset + 2, ENC_LITTLE_ENDIAN);
835
836
837
0
        tvbuff_t *capaTvb = tvb_new_subset_length(tvb, offset, capaLen);
838
0
        offset += capaLen;
839
840
0
        int subOffset = 0;
841
0
        proto_tree *subtree = proto_tree_add_subtree(tree, capaTvb, 0, capaLen, ett_rdpdr_capabilities, NULL, val_to_str_const(capaType, rdpdr_capaType_vals, "<unknown>"));
842
0
        proto_tree_add_item(subtree, hf_rdpdr_capaType, capaTvb, subOffset, 2, ENC_LITTLE_ENDIAN);
843
0
        subOffset += 2;
844
845
0
        proto_tree_add_item(subtree, hf_rdpdr_capaLen, capaTvb, subOffset, 2, ENC_LITTLE_ENDIAN);
846
0
        subOffset += 2;
847
848
0
        uint32_t capaVersion;
849
0
        proto_tree_add_item_ret_uint(subtree, hf_rdpdr_capaVersion, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN, &capaVersion);
850
0
        subOffset += 4;
851
852
0
        switch (capaType) {
853
0
        case CAP_GENERAL_TYPE:
854
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_osType, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
855
0
          subOffset += 4;
856
857
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_osVersion, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
858
0
          subOffset += 4;
859
860
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_protocolMajor, capaTvb, subOffset, 2, ENC_LITTLE_ENDIAN);
861
0
          subOffset += 2;
862
863
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_protocolMinor, capaTvb, subOffset, 2, ENC_LITTLE_ENDIAN);
864
0
          subOffset += 2;
865
866
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_ioCode1, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
867
0
          subOffset += 4;
868
869
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_ioCode2, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
870
0
          subOffset += 4;
871
872
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_extendedPdu, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
873
0
          subOffset += 4;
874
875
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_extraFlags1, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
876
0
          subOffset += 4;
877
878
0
          proto_tree_add_item(subtree, hf_rdpdr_capa_gen_extraFlags2, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
879
0
          subOffset += 4;
880
881
0
          if (capaVersion == 0x00000002)
882
0
            proto_tree_add_item(subtree, hf_rdpdr_capa_gen_specialTypeDeviceCap, capaTvb, subOffset, 4, ENC_LITTLE_ENDIAN);
883
0
          break;
884
885
0
        case CAP_PRINTER_TYPE:
886
0
        case CAP_SMARTCARD_TYPE:
887
0
        case CAP_PORT_TYPE:
888
0
        case CAP_DRIVE_TYPE:
889
0
          break;
890
0
        }
891
0
      }
892
0
      break;
893
0
    }
894
0
    default:
895
0
      col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s", val_to_str_const(packetId, rdpdr_packetid_vals, "<unknown command>"));
896
0
      break;
897
0
    }
898
0
  } else if (component == RDPDR_CTYP_PRN) {
899
0
    switch (packetId) {
900
0
    case PAKID_PRN_USING_XPS: {
901
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_deviceId, tvb, offset, 4, ENC_LITTLE_ENDIAN, &deviceId);
902
0
      offset += 4;
903
904
0
      DrDevice *device = wmem_multimap_lookup32_le(info->channels, &deviceId, pinfo->num);
905
0
      if (device) {
906
0
        proto_item_set_generated(
907
0
          proto_tree_add_string(tree, hf_rdpdr_device_name, tvb, 0, 0, device->name)
908
0
        );
909
910
0
        col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "PAKID_PRN_USING_XPS %s", device->name);
911
0
      } else {
912
0
        col_append_sep_str(pinfo->cinfo, COL_INFO, ",", "PAKID_PRN_USING_XPS");
913
0
      }
914
0
      break;
915
0
    }
916
0
    case PAKID_PRN_CACHE_DATA: {
917
0
      uint32_t eventId;
918
0
      proto_tree_add_item_ret_uint(tree, hf_rdpdr_printer_cacheEvent, tvb, offset, 4, ENC_LITTLE_ENDIAN, &eventId);
919
0
      offset += 4;
920
921
0
      col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "%s", val_to_str_const(eventId, rdpdr_printer_cacheEvent_vals, "<unknown command>"));
922
0
      switch (eventId) {
923
0
      case RDPDR_ADD_PRINTER_EVENT: {
924
0
        uint32_t pnpNameLength, driveNameLength, printerNameLength, cachedFieldsLength;
925
926
0
        proto_tree_add_item(tree, hf_rdpdr_dosName, tvb, offset, 8, ENC_ASCII);
927
0
        offset += 8;
928
929
0
        proto_tree_add_item_ret_uint(tree, hf_rdpdr_pnpNameLength, tvb, offset, 4, ENC_LITTLE_ENDIAN, &pnpNameLength);
930
0
        offset += 4;
931
932
0
        proto_tree_add_item_ret_uint(tree, hf_rdpdr_driverNameLength, tvb, offset, 4, ENC_LITTLE_ENDIAN, &driveNameLength);
933
0
        offset += 4;
934
935
0
        proto_tree_add_item_ret_uint(tree, hf_rdpdr_printerNameLength, tvb, offset, 4, ENC_LITTLE_ENDIAN, &printerNameLength);
936
0
        offset += 4;
937
938
0
        proto_tree_add_item_ret_uint(tree, hf_rdpdr_cachedFieldsLength, tvb, offset, 4, ENC_LITTLE_ENDIAN, &cachedFieldsLength);
939
0
        offset += 4;
940
941
0
        proto_tree_add_item(tree, hf_rdpdr_pnpName, tvb, offset, pnpNameLength, ENC_UTF_16|ENC_LITTLE_ENDIAN);
942
0
        offset += pnpNameLength;
943
944
0
        proto_tree_add_item(tree, hf_rdpdr_driverName, tvb, offset, driveNameLength, ENC_UTF_16|ENC_LITTLE_ENDIAN);
945
0
        offset += driveNameLength;
946
947
0
        proto_tree_add_item(tree, hf_rdpdr_printerName, tvb, offset, printerNameLength, ENC_UTF_16|ENC_LITTLE_ENDIAN);
948
0
        offset += printerNameLength;
949
950
0
        proto_tree_add_item(tree, hf_rdpdr_cachedFields, tvb, offset, cachedFieldsLength, ENC_NA);
951
0
        break;
952
0
      }
953
0
      case RDPDR_UPDATE_PRINTER_EVENT:
954
0
        break;
955
0
      case RDPDR_DELETE_PRINTER_EVENT:
956
0
        break;
957
0
      case RDPDR_RENAME_PRINTER_EVENT:
958
0
        break;
959
0
      default:
960
0
        break;
961
0
      }
962
0
      break;
963
0
    }
964
0
    default:
965
0
      break;
966
0
    }
967
968
0
  }
969
970
0
  return offset;
971
0
}
972
973
974
16
void proto_register_rdpdr(void) {
975
16
  static hf_register_info hf[] = {
976
16
    { &hf_rdpdr_component,
977
16
      { "Component", "rdpdr.component",
978
16
        FT_UINT16, BASE_HEX, VALS(rdpdr_component_vals), 0x0,
979
16
      NULL, HFILL }
980
16
    },
981
16
    { &hf_rdpdr_packetid,
982
16
      { "PacketId", "rdpdr.packetid",
983
16
      FT_UINT16, BASE_HEX, VALS(rdpdr_packetid_vals), 0x0,
984
16
      NULL, HFILL }
985
16
    },
986
16
    { &hf_rdpdr_deviceCount,
987
16
      { "Device count", "rdpdr.devicecount",
988
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
989
16
      NULL, HFILL }
990
16
    },
991
16
    { &hf_rdpdr_deviceType,
992
16
      { "Device type", "rdpdr.devicetype",
993
16
      FT_UINT32, BASE_HEX, VALS(rdpdr_deviceType_vals), 0x0,
994
16
      NULL, HFILL }
995
16
    },
996
16
    { &hf_rdpdr_deviceId,
997
16
      { "Device id", "rdpdr.deviceid",
998
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
999
16
      NULL, HFILL }
1000
16
    },
1001
16
    { &hf_rdpdr_dosName,
1002
16
      { "DOS name", "rdpdr.dosname",
1003
16
      FT_STRINGZ, BASE_NONE, NULL, 0x0,
1004
16
      NULL, HFILL }
1005
16
    },
1006
16
    { &hf_rdpdr_deviceDataLen,
1007
16
      { "Device data length", "rdpdr.devicedatalen",
1008
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1009
16
      NULL, HFILL }
1010
16
    },
1011
16
    { &hf_rdpdr_deviceData,
1012
16
      { "Device data", "rdpdr.devicedata",
1013
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
1014
16
      NULL, HFILL }
1015
16
    },
1016
16
    { &hf_rdpdr_fileId,
1017
16
      { "File id", "rdpdr.fileid",
1018
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1019
16
      NULL, HFILL }
1020
16
    },
1021
16
    { &hf_rdpdr_completionId,
1022
16
      { "Completion id", "rdpdr.completionid",
1023
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1024
16
      NULL, HFILL }
1025
16
    },
1026
16
    { &hf_rdpdr_ioreq_dr_majorFunction,
1027
16
      { "Major function", "rdpdr.majorfunction",
1028
16
      FT_UINT32, BASE_HEX, VALS(rdpdr_dr_majorF_vals), 0x0,
1029
16
      NULL, HFILL }
1030
16
    },
1031
16
    { &hf_rdpdr_ioreq_dr_minorFunction,
1032
16
      { "Minor function", "rdpdr.minorfunction",
1033
16
      FT_UINT32, BASE_HEX, VALS(rdpdr_dr_minorF_vals), 0x0,
1034
16
      NULL, HFILL }
1035
16
    },
1036
16
    { &hf_rdpdr_ioreq_sc_majorFunction,
1037
16
      { "Major function", "rdpdr.majorfunction",
1038
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1039
16
      NULL, HFILL }
1040
16
    },
1041
16
    { &hf_rdpdr_ioreq_sc_minorFunction,
1042
16
      { "Minor function", "rdpdr.minorfunction",
1043
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1044
16
      NULL, HFILL }
1045
16
    },
1046
16
    { &hf_rdpdr_resultCode,
1047
16
      { "Result code", "rdpdr.resultcode",
1048
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1049
16
      NULL, HFILL }
1050
16
    },
1051
16
    { &hf_rdpdr_ioStatus,
1052
16
      { "IoStatus", "rdpdr.iostatus",
1053
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1054
16
      NULL, HFILL }
1055
16
    },
1056
16
    { &hf_rdpdr_io_request_control_outputBufLen,
1057
16
      { "OutputBufferLen", "rdpdr.outputbuflen",
1058
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1059
16
      NULL, HFILL }
1060
16
    },
1061
16
    { &hf_rdpdr_io_request_control_inputBufLen,
1062
16
      { "InputBufferLen", "rdpdr.inputbuflen",
1063
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1064
16
      NULL, HFILL }
1065
16
    },
1066
16
    { &hf_rdpdr_io_request_control_ioControlCode,
1067
16
      { "IoControlCode", "rdpdr.iocontrolcode",
1068
16
      FT_UINT32, BASE_HEX, VALS(rdpdr_dr_ioControlCode_vals), 0x0,
1069
16
      NULL, HFILL }
1070
16
    },
1071
16
    { &hf_rdpdr_io_request_control_padding,
1072
16
      { "Padding", "rdpdr.padding20",
1073
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
1074
16
      NULL, HFILL }
1075
16
    },
1076
16
    { &hf_rdpdr_io_request_frame,
1077
16
      { "Request in frame", "rdpdr.iorequestframe",
1078
16
      FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
1079
16
      NULL, HFILL }
1080
16
    },
1081
16
    { &hf_rdpdr_io_result_frame,
1082
16
      { "IO result in frame", "rdpdr.ioresultframe",
1083
16
      FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
1084
16
      NULL, HFILL }
1085
16
    },
1086
16
    { &hf_rdpdr_create_info,
1087
16
      { "Information", "rdpdr.dr.create.info",
1088
16
      FT_UINT8, BASE_HEX, VALS(rdpdr_dr_createinfo_vals), 0x0,
1089
16
      NULL, HFILL }
1090
16
    },
1091
16
    { &hf_rdpdr_numCapabilities,
1092
16
      { "numCapabilities", "rdpdr.numcapabilities",
1093
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
1094
16
      NULL, HFILL }
1095
16
    },
1096
16
    { &hf_rdpdr_padding,
1097
16
      { "Padding", "rdpdr.padding",
1098
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
1099
16
      NULL, HFILL }
1100
16
    },
1101
16
    { &hf_rdpdr_capaType,
1102
16
      { "Type", "rdpdr.capa.type",
1103
16
      FT_UINT16, BASE_HEX, VALS(rdpdr_capaType_vals), 0x0,
1104
16
      NULL, HFILL }
1105
16
    },
1106
16
    { &hf_rdpdr_capaLen,
1107
16
      { "Length", "rdpdr.capa.length",
1108
16
      FT_UINT16, BASE_DEC, NULL, 0x0,
1109
16
      NULL, HFILL }
1110
16
    },
1111
16
    { &hf_rdpdr_capaVersion,
1112
16
      { "Version", "rdpdr.capa.version",
1113
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1114
16
      NULL, HFILL }
1115
16
    },
1116
16
    { &hf_rdpdr_capa_gen_osType,
1117
16
      { "osType", "rdpdr.capa.gen.ostype",
1118
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1119
16
      NULL, HFILL }
1120
16
    },
1121
16
    { &hf_rdpdr_capa_gen_osVersion,
1122
16
      { "osVersion", "rdpdr.capa.gen.osversion",
1123
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1124
16
      NULL, HFILL }
1125
16
    },
1126
16
    { &hf_rdpdr_capa_gen_protocolMajor,
1127
16
      { "protocolMajorVersion", "rdpdr.capa.gen.protocolmajor",
1128
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
1129
16
      NULL, HFILL }
1130
16
    },
1131
16
    { &hf_rdpdr_capa_gen_protocolMinor,
1132
16
      { "protocolMinorVersion", "rdpdr.capa.gen.protocolminor",
1133
16
      FT_UINT16, BASE_HEX, NULL, 0x0,
1134
16
      NULL, HFILL }
1135
16
    },
1136
16
    { &hf_rdpdr_capa_gen_ioCode1,
1137
16
      { "ioCode1", "rdpdr.capa.gen.iocode1",
1138
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1139
16
      NULL, HFILL }
1140
16
    },
1141
16
    { &hf_rdpdr_capa_gen_ioCode2,
1142
16
      { "ioCode2", "rdpdr.capa.gen.iocode2",
1143
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1144
16
      NULL, HFILL }
1145
16
    },
1146
16
    { &hf_rdpdr_capa_gen_extendedPdu,
1147
16
      { "extendedPDU", "rdpdr.capa.gen.extendedpdu",
1148
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1149
16
      NULL, HFILL }
1150
16
    },
1151
16
    { &hf_rdpdr_capa_gen_extraFlags1,
1152
16
      { "extraFlags1", "rdpdr.capa.gen.extraflags1",
1153
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1154
16
      NULL, HFILL }
1155
16
    },
1156
16
    { &hf_rdpdr_capa_gen_extraFlags2,
1157
16
      { "extraFlags2", "rdpdr.capa.gen.extraflags2",
1158
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1159
16
      NULL, HFILL }
1160
16
    },
1161
16
    { &hf_rdpdr_capa_gen_specialTypeDeviceCap,
1162
16
      { "specialTypeDeviceCap", "rdpdr.capa.gen.specialtypedevicecap",
1163
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1164
16
      NULL, HFILL }
1165
16
    },
1166
16
    { &hf_rdpdr_ioreq_sc_command,
1167
16
      { "Command", "rdpdr.sc.command",
1168
16
      FT_BYTES, BASE_NONE, NULL, 0,
1169
16
      NULL, HFILL }
1170
16
    },
1171
16
    { &hf_rdpdr_ioreq_sc_returnCode,
1172
16
      { "ReturnCode", "rdpdr.sc.returnCode",
1173
16
      FT_UINT32, BASE_HEX, NULL, 0x0,
1174
16
      NULL, HFILL }
1175
16
    },
1176
1177
16
    { &hf_rdpdr_device_name,
1178
16
      { "Device", "rdpdr.device",
1179
16
      FT_STRINGZ, BASE_NONE, NULL, 0x0,
1180
16
      NULL, HFILL }
1181
16
    },
1182
16
    { &hf_rdpdr_printer_cacheEvent,
1183
16
      { "EventId", "rdpdr.printer.eventid",
1184
16
      FT_UINT32, BASE_HEX, VALS(rdpdr_printer_cacheEvent_vals), 0x0,
1185
16
      NULL, HFILL }
1186
16
    },
1187
16
    { &hf_rdpdr_pnpNameLength,
1188
16
      { "PnPNameLen", "rdpdr.printer.pnpnamelen",
1189
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1190
16
      NULL, HFILL }
1191
16
    },
1192
16
    { &hf_rdpdr_pnpName,
1193
16
      { "PnPName", "rdpdr.printer.pnpname",
1194
16
      FT_STRINGZ, BASE_NONE, NULL, 0x0,
1195
16
      NULL, HFILL }
1196
16
    },
1197
16
    { &hf_rdpdr_driverNameLength,
1198
16
      { "DriverNameLen", "rdpdr.printer.drivernamelen",
1199
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1200
16
      NULL, HFILL }
1201
16
    },
1202
16
    { &hf_rdpdr_driverName,
1203
16
      { "DriverName", "rdpdr.printer.drivername",
1204
16
      FT_STRINGZ, BASE_NONE, NULL, 0x0,
1205
16
      NULL, HFILL }
1206
16
    },
1207
16
    { &hf_rdpdr_printerNameLength,
1208
16
      { "PrintNameLen", "rdpdr.printer.printnamelen",
1209
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1210
16
      NULL, HFILL }
1211
16
    },
1212
16
    { &hf_rdpdr_printerName,
1213
16
      { "PrinterName", "rdpdr.printer.printername",
1214
16
      FT_STRINGZ, BASE_NONE, NULL, 0x0,
1215
16
      NULL, HFILL }
1216
16
    },
1217
16
    { &hf_rdpdr_cachedFieldsLength,
1218
16
      { "CacheFieldsLen", "rdpdr.printer.cachefieldslen",
1219
16
      FT_UINT32, BASE_DEC, NULL, 0x0,
1220
16
      NULL, HFILL }
1221
16
    },
1222
16
    { &hf_rdpdr_cachedFields,
1223
16
      { "CacheFields", "rdpdr.printer.cachefields",
1224
16
      FT_BYTES, BASE_NONE, NULL, 0x0,
1225
16
      NULL, HFILL }
1226
16
    },
1227
16
  };
1228
1229
16
  static int *ett[] = {
1230
16
    &ett_rdpdr,
1231
16
    &ett_rdpdr_device,
1232
16
    &ett_rdpdr_capabilities,
1233
16
  };
1234
1235
16
  proto_rdpdr = proto_register_protocol("RDP disk redirection virtual channel Protocol", "RDPDR", "rdpdr");
1236
1237
  /* Register fields and subtrees */
1238
16
  proto_register_field_array(proto_rdpdr, hf, array_length(hf));
1239
16
  proto_register_subtree_array(ett, array_length(ett));
1240
1241
16
  register_dissector("rdpdr", dissect_rdpdr, proto_rdpdr);
1242
16
}
1243
1244
16
void proto_reg_handoff_rdpdr(void) {
1245
16
}