TODO drsuapi compressed
[wireshark-sm.git] / epan / dissectors / packet-dcerpc-epm.c
blob1dc7112627b65e32a00659de3c72a0e2b35d8a49
1 /* packet-dcerpc-epm.c
2 * Routines for dcerpc endpoint mapper dissection
3 * Copyright 2001, Todd Sabin <tas@webspan.net>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include <epan/packet.h>
15 #include <epan/to_str.h>
16 #include <epan/expert.h>
17 #include "packet-dcerpc.h"
19 void proto_register_epm (void);
20 void proto_reg_handoff_epm (void);
22 static int proto_epm3;
23 static int proto_epm4;
25 static int hf_epm_opnum;
26 static int hf_epm_inquiry_type;
27 static int hf_epm_object;
28 static int hf_epm_if_id;
29 static int hf_epm_ver_maj;
30 static int hf_epm_ver_min;
31 static int hf_epm_ver_opt;
32 static int hf_epm_hnd;
33 static int hf_epm_max_ents;
34 static int hf_epm_num_ents;
35 static int hf_epm_uuid;
36 static int hf_epm_uuid_version;
37 static int hf_epm_tower_length;
38 /* static int hf_epm_tower_data; */
39 static int hf_epm_max_towers;
40 static int hf_epm_num_towers;
41 static int hf_epm_rc;
42 static int hf_epm_replace;
43 static int hf_epm_tower_num_floors;
44 static int hf_epm_tower_rhs_len;
45 static int hf_epm_tower_lhs_len;
46 static int hf_epm_tower_proto_id;
47 static int hf_epm_annotation;
48 static int hf_epm_ann_offset;
49 static int hf_epm_ann_len;
50 static int hf_epm_proto_named_pipes;
51 static int hf_epm_proto_netbios_name;
52 static int hf_epm_proto_ip;
53 static int hf_epm_proto_udp_port;
54 static int hf_epm_proto_tcp_port;
55 static int hf_epm_proto_http_port;
57 static int ett_epm;
58 static int ett_epm_tower_floor;
59 static int ett_epm_entry;
61 static expert_field ei_epm_proto_undecoded;
64 /* the UUID is identical for interface versions 3 and 4 */
65 static e_guid_t uuid_epm = { 0xe1af8308, 0x5d1f, 0x11c9, { 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
66 static uint16_t ver_epm3 = 3;
67 static uint16_t ver_epm4 = 4;
71 static const value_string ep_service[] = {
72 { 0, "rpc_c_ep_all_elts" },
73 { 1, "rpc_c_ep_match_by_if" },
74 { 2, "rpc_c_ep_match_by_obj" },
75 { 3, "rpc_c_ep_match_by_both" },
76 { 0, NULL },
79 /* typedef struct {
80 unsigned int tower_len,
81 [size_is(tower_len)] char tower[];
82 } twr_t, *twr_p_t;
84 static int epm_dissect_tower (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep);
87 static int
88 epm_dissect_pointer_IF_ID(tvbuff_t *tvb, int offset,
89 packet_info *pinfo, proto_tree *tree,
90 dcerpc_info *di, uint8_t *drep)
92 offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, di, drep,
93 di->hf_index, NULL);
94 offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, di, drep,
95 hf_epm_ver_maj, NULL);
96 offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, di, drep,
97 hf_epm_ver_min, NULL);
98 return offset;
101 static int
102 epm_dissect_pointer_UUID(tvbuff_t *tvb, int offset,
103 packet_info *pinfo, proto_tree *tree,
104 dcerpc_info *di, uint8_t *drep)
106 offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, di, drep,
107 di->hf_index, NULL);
108 return offset;
111 static int
112 epm_dissect_ept_lookup_rqst (tvbuff_t *tvb, int offset,
113 packet_info *pinfo, proto_tree *tree,
114 dcerpc_info *di, uint8_t *drep)
116 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
117 hf_epm_inquiry_type, NULL);
119 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
120 epm_dissect_pointer_UUID, NDR_POINTER_PTR,
121 "Object:", hf_epm_object);
123 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
124 epm_dissect_pointer_IF_ID, NDR_POINTER_PTR,
125 "Interface:", hf_epm_if_id);
127 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
128 hf_epm_ver_opt, NULL);
130 offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, di, drep,
131 hf_epm_hnd, NULL);
133 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
134 hf_epm_max_ents, NULL);
135 return offset;
139 static int
140 epm_dissect_ept_entry_t(tvbuff_t *tvb, int offset,
141 packet_info *pinfo, proto_tree *parent_tree,
142 dcerpc_info *di, uint8_t *drep)
144 proto_item *item=NULL;
145 proto_tree *tree=NULL;
146 int old_offset=offset;
147 uint32_t len;
148 const uint8_t *str;
150 if(di->conformant_run){
151 return offset;
154 if(parent_tree){
155 tree = proto_tree_add_subtree(parent_tree, tvb, offset, -1, ett_epm_entry, &item, "Entry:");
158 offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, di, drep,
159 hf_epm_object, NULL);
161 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
162 epm_dissect_tower, NDR_POINTER_PTR,
163 "Tower pointer:", -1);
165 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
166 hf_epm_ann_offset, NULL);
167 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
168 hf_epm_ann_len, &len);
169 proto_tree_add_item_ret_string(tree, hf_epm_annotation, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
170 offset += len;
172 if(str&&str[0]){
173 if(parent_tree) {
174 proto_item_append_text(item, " Service:%s ", str);
175 proto_item_append_text(tree->parent, " Service:%s ", str);
177 col_append_fstr(pinfo->cinfo, COL_INFO, ", Service:%s", str);
180 proto_item_set_len(item, offset-old_offset);
181 return offset;
184 static int
185 epm_dissect_ept_entry_t_array(tvbuff_t *tvb, int offset,
186 packet_info *pinfo, proto_tree *tree,
187 dcerpc_info *di, uint8_t *drep)
189 offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, di, drep,
190 epm_dissect_ept_entry_t);
192 return offset;
195 static int
196 epm_dissect_ept_lookup_resp (tvbuff_t *tvb, int offset,
197 packet_info *pinfo, proto_tree *tree,
198 dcerpc_info *di, uint8_t *drep)
200 offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, di, drep,
201 hf_epm_hnd, NULL);
203 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
204 hf_epm_num_ents, NULL);
206 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
207 epm_dissect_ept_entry_t_array, NDR_POINTER_REF,
208 "Entries:", -1);
210 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
211 hf_epm_rc, NULL);
213 return offset;
216 static int
217 epm_dissect_uuid (tvbuff_t *tvb, int offset,
218 packet_info *pinfo, proto_tree *tree,
219 dcerpc_info *di, uint8_t *drep)
221 offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, di, drep,
222 hf_epm_uuid, NULL);
223 return offset;
226 #define PROTO_ID_OSI_OID 0x00
227 #define PROTO_ID_DNA_SESSCTL 0x02
228 #define PROTO_ID_DNA_SESSCTL_V3 0x03
229 #define PROTO_ID_DNA_NSP 0x04
230 #define PROTO_ID_OSI_TP4 0x05
231 #define PROTO_ID_OSI_CLNS 0x06
232 #define PROTO_ID_TCP 0x07
233 #define PROTO_ID_UDP 0x08
234 #define PROTO_ID_IP 0x09
235 #define PROTO_ID_RPC_CL 0x0a
236 #define PROTO_ID_RPC_CO 0x0b
237 #define PROTO_ID_SPX 0x0c /* from DCOM spec (is this correct?) */
238 #define PROTO_ID_UUID 0x0d
239 #define PROTO_ID_IPX 0x0e /* from DCOM spec (is this correct?) */
240 #define PROTO_ID_NAMED_PIPES 0x0f
241 #define PROTO_ID_NAMED_PIPES_2 0x10
242 #define PROTO_ID_NETBIOS 0x11
243 #define PROTO_ID_NETBEUI 0x12
244 #define PROTO_ID_NETWARE_SPX 0x13
245 #define PROTO_ID_NETWARE_IPX 0x14
246 #define PROTO_ID_ATALK_STREAM 0x16
247 #define PROTO_ID_ATALK_DATAGRAM 0x17
248 #define PROTO_ID_ATALK 0x18
249 #define PROTO_ID_NETBIOS_2 0x19
250 #define PROTO_ID_VINES_SPP 0x1a
251 #define PROTO_ID_VINES_IPC 0x1b
252 #define PROTO_ID_STREETTALK 0x1c
253 #define PROTO_ID_HTTP 0x1f
254 #define PROTO_ID_UNIX_DOMAIN 0x20
255 #define PROTO_ID_NULL 0x21
256 #define PROTO_ID_NETBIOS_3 0x22
258 static const value_string proto_id_vals[] = {
259 { PROTO_ID_OSI_OID, "OSI OID"},
260 { PROTO_ID_DNA_SESSCTL, "DNA Session Control"},
261 { PROTO_ID_DNA_SESSCTL_V3, "DNA Session Control V3"},
262 { PROTO_ID_DNA_NSP, "DNA NSP Transport"},
263 { PROTO_ID_OSI_TP4, "OSI TP4"},
264 { PROTO_ID_OSI_CLNS, "OSI CLNS or DNA Routing"},
265 { PROTO_ID_TCP, "DOD TCP"},
266 { PROTO_ID_UDP, "DOD UDP"},
267 { PROTO_ID_IP, "DOD IP"},
268 { PROTO_ID_RPC_CL, "RPC connectionless protocol"},
269 { PROTO_ID_RPC_CO, "RPC connection-oriented protocol"},
270 { PROTO_ID_SPX, "SPX?"},
271 { PROTO_ID_UUID, "UUID"},
272 { PROTO_ID_IPX, "IPX?"},
273 { PROTO_ID_NAMED_PIPES, "Named Pipes"},
274 { PROTO_ID_NAMED_PIPES_2, "Named Pipes"},
275 { PROTO_ID_NETBIOS, "NetBIOS"},
276 { PROTO_ID_NETBEUI, "NetBEUI"},
277 { PROTO_ID_NETWARE_SPX, "Netware SPX"},
278 { PROTO_ID_NETWARE_IPX, "Netware IPX"},
279 { PROTO_ID_ATALK_STREAM, "Appletalk Stream"},
280 { PROTO_ID_ATALK_DATAGRAM, "Appletalk Datagram"},
281 { PROTO_ID_ATALK, "Appletalk"},
282 { PROTO_ID_NETBIOS_2, "NetBIOS"},
283 { PROTO_ID_VINES_SPP, "Vines SPP"},
284 { PROTO_ID_VINES_IPC, "Vines IPC"},
285 { PROTO_ID_STREETTALK, "StreetTalk"},
286 { PROTO_ID_HTTP, "RPC over HTTP"},
287 { PROTO_ID_UNIX_DOMAIN, "Unix Domain Socket"},
288 { PROTO_ID_NULL, "null"},
289 { PROTO_ID_NETBIOS_3, "NetBIOS"},
290 { 0, NULL},
294 /* XXX this function assumes LE encoding. can not use the NDR routines
295 since they assume padding.
297 static int
298 epm_dissect_tower_data (tvbuff_t *tvb, int offset,
299 packet_info *pinfo, proto_tree *tree,
300 dcerpc_info *di, uint8_t *drep _U_)
302 uint16_t num_floors, ii;
303 const char *uuid_name;
304 uint8_t u8little_endian = DREP_LITTLE_ENDIAN;
305 const uint8_t *str;
307 if(di->conformant_run){
308 return offset;
311 num_floors = tvb_get_letohs(tvb, offset);
312 proto_tree_add_uint(tree, hf_epm_tower_num_floors, tvb, offset, 2, num_floors);
313 offset += 2;
315 for(ii=0;ii<num_floors;ii++){
316 proto_item *it = NULL;
317 proto_tree *tr = NULL;
318 int old_offset = offset;
319 uint16_t len;
320 uint8_t proto_id;
321 e_guid_t uuid;
322 proto_item *pi;
324 tr = proto_tree_add_subtree_format(tree, tvb, offset, 0, ett_epm_tower_floor, &it, "Floor %d ", ii+1);
326 len = tvb_get_letohs(tvb, offset);
327 proto_tree_add_uint(tr, hf_epm_tower_lhs_len, tvb, offset, 2, len);
328 offset += 2;
330 proto_id = tvb_get_uint8(tvb, offset);
331 proto_tree_add_uint(tr, hf_epm_tower_proto_id, tvb, offset, 1, proto_id);
333 switch(proto_id){
334 case PROTO_ID_UUID:
335 dcerpc_tvb_get_uuid (tvb, offset+1, &u8little_endian, &uuid);
337 uuid_name = guids_get_uuid_name(&uuid, pinfo->pool);
339 if(uuid_name != NULL) {
340 proto_tree_add_guid_format (tr, hf_epm_uuid, tvb, offset+1, 16, (e_guid_t *) &uuid,
341 "UUID: %s (%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)",
342 uuid_name,
343 uuid.data1, uuid.data2, uuid.data3,
344 uuid.data4[0], uuid.data4[1],
345 uuid.data4[2], uuid.data4[3],
346 uuid.data4[4], uuid.data4[5],
347 uuid.data4[6], uuid.data4[7]);
348 } else {
349 proto_tree_add_guid_format (tr, hf_epm_uuid, tvb, offset+1, 16, (e_guid_t *) &uuid,
350 "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
351 uuid.data1, uuid.data2, uuid.data3,
352 uuid.data4[0], uuid.data4[1],
353 uuid.data4[2], uuid.data4[3],
354 uuid.data4[4], uuid.data4[5],
355 uuid.data4[6], uuid.data4[7]);
357 proto_tree_add_item(tr, hf_epm_uuid_version, tvb, offset+17, 2, ENC_BIG_ENDIAN); /* Major/minor bytes treated as big endian */
360 uint16_t version = tvb_get_ntohs(tvb, offset+17);
361 const char *service = dcerpc_get_proto_name(&uuid, version);
362 if (service || uuid_name) {
363 const char *s = service ? service : uuid_name;
364 proto_item_append_text(tr, "UUID: %s", s);
365 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", s);
366 } else {
367 proto_item_append_text(tr, "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x Version %d.%d", uuid.data1, uuid.data2, uuid.data3,
368 uuid.data4[0], uuid.data4[1],
369 uuid.data4[2], uuid.data4[3],
370 uuid.data4[4], uuid.data4[5],
371 uuid.data4[6], uuid.data4[7],
372 tvb_get_uint8(tvb, offset+17),
373 tvb_get_uint8(tvb, offset+18));
376 break;
378 offset += len;
380 len = tvb_get_letohs(tvb, offset);
381 pi = proto_tree_add_uint(tr, hf_epm_tower_rhs_len, tvb, offset, 2, len);
382 offset += 2;
384 switch(proto_id){
386 case PROTO_ID_UUID:
387 /* XXX - is this big or little endian? */
388 proto_tree_add_item(tr, hf_epm_ver_min, tvb, offset, 2, ENC_BIG_ENDIAN);
389 break;
390 case PROTO_ID_TCP: /* this one is always big endian */
391 proto_tree_add_item(tr, hf_epm_proto_tcp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
392 proto_item_append_text(tr, "TCP Port:%d", tvb_get_ntohs(tvb, offset));
393 break;
395 case PROTO_ID_UDP: /* this one is always big endian */
396 proto_tree_add_item(tr, hf_epm_proto_udp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
397 proto_item_append_text(tr, "UDP Port:%d", tvb_get_ntohs(tvb, offset));
398 break;
400 case PROTO_ID_IP: /* this one is always big endian */
401 proto_tree_add_item(tr, hf_epm_proto_ip, tvb, offset, 4, ENC_BIG_ENDIAN);
402 proto_item_append_text(tr, "IP:%s", tvb_ip_to_str(pinfo->pool, tvb, offset));
403 break;
405 case PROTO_ID_RPC_CO:
406 proto_item_append_text(tr, "RPC connection-oriented protocol");
407 break;
409 case PROTO_ID_RPC_CL:
410 proto_item_append_text(tr, "RPC connectionless protocol");
411 /* XXX - is this big or little endian? */
412 proto_tree_add_item(tr, hf_epm_ver_min, tvb, offset, 2, ENC_BIG_ENDIAN);
413 break;
415 case PROTO_ID_NAMED_PIPES: /* \\PIPE\xxx named pipe */
416 proto_tree_add_item_ret_string(tr, hf_epm_proto_named_pipes, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
417 proto_item_append_text(tr, "NamedPipe:%s", str);
418 break;
420 case PROTO_ID_NAMED_PIPES_2: /* PIPENAME named pipe */
421 proto_tree_add_item_ret_string(tr, hf_epm_proto_named_pipes, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
422 proto_item_append_text(tr, "PIPE:%s", str);
423 break;
425 case PROTO_ID_NETBIOS: /* \\NETBIOS netbios name */
426 proto_tree_add_item_ret_string(tr, hf_epm_proto_netbios_name, tvb, offset, len, ENC_ASCII|ENC_NA, pinfo->pool, &str);
427 proto_item_append_text(tr, "NetBIOS:%s", str);
428 break;
429 case PROTO_ID_HTTP: /* RPC over HTTP */
430 proto_tree_add_item(tr, hf_epm_proto_http_port, tvb, offset, 2, ENC_BIG_ENDIAN);
431 proto_item_append_text(tr, "RPC over HTTP Port:%d", tvb_get_ntohs(tvb, offset));
432 break;
434 default:
435 if(len){
436 expert_add_info_format(pinfo, pi, &ei_epm_proto_undecoded, "RightHandSide not decoded yet for proto_id 0x%x",
437 proto_id);
440 offset += len;
442 proto_item_set_len(it, offset-old_offset);
444 return offset;
447 static void
448 epm_fmt_uuid_version( char *result, uint32_t revision )
450 snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", (uint8_t)(( revision & 0xFF00 ) >> 8), (uint8_t)(revision & 0xFF) );
453 /* typedef struct {
454 unsigned int tower_len,
455 [size_is(tower_len)] char tower[];
456 } twr_t, *twr_p_t;
458 static int
459 epm_dissect_tower (tvbuff_t *tvb, int offset,
460 packet_info *pinfo, proto_tree *tree,
461 dcerpc_info *di, uint8_t *drep)
463 uint3264_t len;
465 if(di->conformant_run){
466 return offset;
469 /* first one is the header of the conformant array, second one is the
470 length field */
471 offset = dissect_ndr_uint3264 (tvb, offset, pinfo, tree, di, drep,
472 hf_epm_tower_length, &len);
473 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
474 hf_epm_tower_length, NULL);
475 offset = epm_dissect_tower_data(tvb, offset, pinfo, tree, di, drep);
477 return offset;
479 static int
480 epm_dissect_tower_pointer (tvbuff_t *tvb, int offset,
481 packet_info *pinfo, proto_tree *tree,
482 dcerpc_info *di, uint8_t *drep)
484 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
485 epm_dissect_tower, NDR_POINTER_PTR,
486 "Tower pointer:", -1);
487 return offset;
489 static int
490 epm_dissect_tower_array (tvbuff_t *tvb, int offset,
491 packet_info *pinfo, proto_tree *tree,
492 dcerpc_info *di, uint8_t *drep)
494 offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, di, drep,
495 epm_dissect_tower_pointer);
497 return offset;
500 static int
501 epm_dissect_ept_map_rqst (tvbuff_t *tvb, int offset,
502 packet_info *pinfo, proto_tree *tree,
503 dcerpc_info *di, uint8_t *drep)
505 /* [in, ptr] uuid_p_t object */
506 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
507 epm_dissect_uuid, NDR_POINTER_PTR,
508 "UUID pointer:", -1);
510 /* [in, ptr] twr_p_t map_tower */
511 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
512 epm_dissect_tower, NDR_POINTER_PTR,
513 "Tower pointer:", -1);
515 /* [in, out] ept_lookup_handle_t *entry_handle */
516 offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, di, drep,
517 hf_epm_hnd, NULL);
519 /* [in] unsigned32 max_towers */
520 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
521 hf_epm_max_towers, NULL);
523 return offset;
526 static int
527 epm_dissect_ept_map_resp (tvbuff_t *tvb, int offset,
528 packet_info *pinfo, proto_tree *tree,
529 dcerpc_info *di, uint8_t *drep)
531 /* [in, out] ept_lookup_handle_t *entry_handle */
532 offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, di, drep,
533 hf_epm_hnd, NULL);
535 /* [out, ptr] unsigned32 *num_towers */
536 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
537 hf_epm_num_towers, NULL);
539 /* [out, length_is(*num_towers), size_is(max_towers), ptr] twr_p_t towers[] */
540 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
541 epm_dissect_tower_array, NDR_POINTER_REF,
542 "Tower array:", -1);
544 /* [out] error_status_t *status */
545 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
546 hf_epm_rc, NULL);
548 return offset;
551 static int
552 epm_dissect_ept_entry_t_ucarray(tvbuff_t *tvb, int offset,
553 packet_info *pinfo, proto_tree *tree,
554 dcerpc_info *di, uint8_t *drep)
556 offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, di, drep,
557 epm_dissect_ept_entry_t);
559 return offset;
562 static int
563 epm_dissect_ept_insert_rqst (tvbuff_t *tvb, int offset,
564 packet_info *pinfo, proto_tree *tree,
565 dcerpc_info *di, uint8_t *drep)
567 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
568 hf_epm_num_ents, NULL);
570 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
571 epm_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
572 "Entries:", -1);
574 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
575 hf_epm_replace, NULL);
577 return offset;
582 static int
583 epm_dissect_ept_insert_resp (tvbuff_t *tvb, int offset,
584 packet_info *pinfo, proto_tree *tree,
585 dcerpc_info *di, uint8_t *drep)
587 /* [out] error_status_t *status */
588 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
589 hf_epm_rc, NULL);
591 return offset;
595 static int
596 epm_dissect_ept_delete_rqst (tvbuff_t *tvb, int offset,
597 packet_info *pinfo, proto_tree *tree,
598 dcerpc_info *di, uint8_t *drep)
600 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
601 hf_epm_num_ents, NULL);
603 offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, di, drep,
604 epm_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
605 "Entries:", -1);
607 return offset;
612 static int
613 epm_dissect_ept_delete_resp (tvbuff_t *tvb, int offset,
614 packet_info *pinfo, proto_tree *tree,
615 dcerpc_info *di, uint8_t *drep)
617 /* [out] error_status_t *status */
618 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
619 hf_epm_rc, NULL);
621 return offset;
626 static int
627 epm_dissect_ept_lookup_handle_free_rqst (tvbuff_t *tvb, int offset,
628 packet_info *pinfo, proto_tree *tree,
629 dcerpc_info *di, uint8_t *drep)
631 /* [in, out] ept_lookup_handle_t *entry_handle */
632 offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, di, drep,
633 hf_epm_hnd, NULL);
635 return offset;
638 static int
639 epm_dissect_ept_lookup_handle_free_resp (tvbuff_t *tvb, int offset,
640 packet_info *pinfo, proto_tree *tree,
641 dcerpc_info *di, uint8_t *drep)
643 /* [in, out] ept_lookup_handle_t *entry_handle */
644 offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, di, drep,
645 hf_epm_hnd, NULL);
647 offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep,
648 hf_epm_rc, NULL);
650 return offset;
654 static const dcerpc_sub_dissector epm_dissectors[] = {
655 { 0, "Insert",
656 epm_dissect_ept_insert_rqst,
657 epm_dissect_ept_insert_resp },
658 { 1, "Delete",
659 epm_dissect_ept_delete_rqst,
660 epm_dissect_ept_delete_resp },
661 { 2, "Lookup",
662 epm_dissect_ept_lookup_rqst,
663 epm_dissect_ept_lookup_resp },
664 { 3, "Map",
665 epm_dissect_ept_map_rqst,
666 epm_dissect_ept_map_resp },
667 { 4, "LookupHandleFree",
668 epm_dissect_ept_lookup_handle_free_rqst,
669 epm_dissect_ept_lookup_handle_free_resp },
670 { 5, "InqObject", NULL, NULL },
671 { 6, "MgmtDelete", NULL, NULL },
672 { 0, NULL, NULL, NULL }
675 void
676 proto_register_epm (void)
678 static hf_register_info hf[] = {
679 { &hf_epm_opnum,
680 { "Operation", "epm.opnum", FT_UINT16, BASE_DEC,
681 NULL, 0x0, NULL, HFILL }},
682 { &hf_epm_inquiry_type,
683 { "Inquiry type", "epm.inq_type", FT_UINT32, BASE_DEC, VALS(ep_service), 0x0, NULL, HFILL }},
684 { &hf_epm_object,
685 { "Object", "epm.object", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
686 { &hf_epm_if_id,
687 { "Interface", "epm.if_id", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
688 { &hf_epm_ver_maj,
689 { "Version Major", "epm.ver_maj", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
690 { &hf_epm_ver_min,
691 { "Version Minor", "epm.ver_min", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
692 { &hf_epm_ver_opt,
693 { "Version Option", "epm.ver_opt", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
694 { &hf_epm_hnd,
695 { "Handle", "epm.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},
696 { &hf_epm_max_ents,
697 { "Max entries", "epm.max_ents", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
698 { &hf_epm_num_ents,
699 { "Num entries", "epm.num_ents", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
700 { &hf_epm_uuid,
701 { "UUID", "epm.uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
702 { &hf_epm_uuid_version,
703 { "Version", "epm.uuid_version", FT_UINT16, BASE_CUSTOM, CF_FUNC(epm_fmt_uuid_version), 0x0, NULL, HFILL }},
704 { &hf_epm_annotation,
705 { "Annotation", "epm.annotation", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
706 { &hf_epm_proto_named_pipes,
707 { "Named Pipe", "epm.proto.named_pipe", FT_STRING, BASE_NONE, NULL, 0x0, "Name of the named pipe for this service", HFILL }},
708 { &hf_epm_proto_netbios_name,
709 { "NetBIOS Name", "epm.proto.netbios_name", FT_STRING, BASE_NONE, NULL, 0x0, "NetBIOS name where this service can be found", HFILL }},
710 { &hf_epm_tower_length,
711 { "Length", "epm.tower.len", FT_UINT32, BASE_DEC, NULL, 0x0, "Length of tower data", HFILL }},
712 #if 0
713 { &hf_epm_tower_data,
714 { "Tower", "epm.tower", FT_BYTES, BASE_NONE, NULL, 0x0, "Tower data", HFILL }},
715 #endif
716 { &hf_epm_max_towers,
717 { "Max Towers", "epm.max_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum number of towers to return", HFILL }},
718 { &hf_epm_num_towers,
719 { "Num Towers", "epm.num_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Number number of towers to return", HFILL }},
720 { &hf_epm_ann_offset,
721 { "Annotation offset", "epm.ann_offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
722 { &hf_epm_ann_len,
723 { "Annotation length", "epm.ann_len", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
724 { &hf_epm_rc,
725 { "Return code", "epm.rc", FT_UINT32, BASE_HEX, NULL, 0x0, "EPM return value", HFILL }},
726 { &hf_epm_replace,
727 { "Replace", "epm.replace", FT_UINT8, BASE_DEC, NULL, 0x0, "Replace existing objects?", HFILL }},
728 { &hf_epm_tower_num_floors,
729 { "Number of floors", "epm.tower.num_floors", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of floors in tower", HFILL }},
730 { &hf_epm_proto_udp_port,
731 { "UDP Port", "epm.proto.udp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "UDP Port where this service can be found", HFILL }},
732 { &hf_epm_proto_tcp_port,
733 { "TCP Port", "epm.proto.tcp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "TCP Port where this service can be found", HFILL }},
734 { &hf_epm_proto_http_port,
735 { "TCP Port", "epm.proto.http_port", FT_UINT16, BASE_DEC, NULL, 0x0, "TCP Port where this service can be found", HFILL }},
736 { &hf_epm_tower_rhs_len,
737 { "RHS Length", "epm.tower.rhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of RHS data", HFILL }},
738 { &hf_epm_tower_lhs_len,
739 { "LHS Length", "epm.tower.lhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of LHS data", HFILL }},
740 { &hf_epm_proto_ip,
741 { "IP", "epm.proto.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "IP address where service is located", HFILL }},
742 { &hf_epm_tower_proto_id,
743 { "Protocol", "epm.tower.proto_id", FT_UINT8, BASE_HEX, VALS(proto_id_vals), 0x0, "Protocol identifier", HFILL }}
745 static int *ett[] = {
746 &ett_epm,
747 &ett_epm_tower_floor,
748 &ett_epm_entry
751 static ei_register_info ei[] = {
752 { &ei_epm_proto_undecoded, { "epm.proto_id.undecoded", PI_UNDECODED, PI_WARN, "RightHandSide not decoded yet for proto_id", EXPFILL }},
755 expert_module_t* expert_epm3;
757 /* interface version 3 */
758 proto_epm3 = proto_register_protocol ("DCE/RPC Endpoint Mapper", "EPM", "epm");
759 proto_register_field_array (proto_epm3, hf, array_length (hf));
760 proto_register_subtree_array (ett, array_length (ett));
761 expert_epm3 = expert_register_protocol(proto_epm3);
762 expert_register_field_array(expert_epm3, ei, array_length(ei));
764 /* interface version 4 */
765 proto_epm4 = proto_register_protocol ("DCE/RPC Endpoint Mapper v4", "EPMv4", "epm4");
768 void
769 proto_reg_handoff_epm (void)
771 /* Register the protocol as dcerpc */
772 dcerpc_init_uuid (proto_epm3, ett_epm, &uuid_epm, ver_epm3, epm_dissectors, hf_epm_opnum);
773 dcerpc_init_uuid (proto_epm4, ett_epm, &uuid_epm, ver_epm4, epm_dissectors, hf_epm_opnum);
777 * Editor modelines - https://www.wireshark.org/tools/modelines.html
779 * Local variables:
780 * c-basic-offset: 4
781 * tab-width: 8
782 * indent-tabs-mode: nil
783 * End:
785 * vi: set shiftwidth=4 tabstop=8 expandtab:
786 * :indentSize=4:tabSize=8:noTabs=true: