From Jim McDonough: add the text sservice name for a UUID/version string
[obnox/wireshark/wip.git] / packet-dcerpc-epm.c
1 /* packet-dcerpc-epm.c
2  * Routines for dcerpc endpoint mapper dissection
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  *
5  * $Id: packet-dcerpc-epm.c,v 1.22 2003/10/20 20:18:52 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30
31 #include <string.h>
32
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include "packet-dcerpc.h"
36 #include "packet-dcerpc-nt.h"
37
38
39 static int proto_epm = -1;
40
41 static int hf_epm_opnum = -1;
42 static int hf_epm_inquiry_type = -1;
43 static int hf_epm_object = -1;
44 static int hf_epm_if_id = -1;
45 static int hf_epm_ver_maj = -1;
46 static int hf_epm_ver_min = -1;
47 static int hf_epm_ver_opt = -1;
48 static int hf_epm_hnd = -1;
49 static int hf_epm_max_ents = -1;
50 static int hf_epm_num_ents = -1;
51 static int hf_epm_uuid = -1;
52 static int hf_epm_tower_length = -1;
53 static int hf_epm_tower_data = -1;
54 static int hf_epm_max_towers = -1;
55 static int hf_epm_num_towers = -1;
56 static int hf_epm_rc = -1;
57 static int hf_epm_replace = -1;
58 static int hf_epm_tower_num_floors = -1;
59 static int hf_epm_tower_rhs_len = -1;
60 static int hf_epm_tower_lhs_len = -1;
61 static int hf_epm_tower_proto_id = -1;
62 static int hf_epm_annotation = -1;
63 static int hf_epm_ann_offset = -1;
64 static int hf_epm_ann_len = -1;
65 static int hf_epm_proto_named_pipes = -1;
66 static int hf_epm_proto_netbios_name = -1;
67 static int hf_epm_proto_ip = -1;
68 static int hf_epm_proto_udp_port = -1;
69 static int hf_epm_proto_tcp_port = -1;
70
71 static gint ett_epm = -1;
72 static gint ett_epm_tower_floor = -1;
73 static gint ett_epm_entry = -1;
74
75 static e_uuid_t uuid_epm = { 0xe1af8308, 0x5d1f, 0x11c9, { 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
76 static guint16  ver_epm = 3;
77
78
79 /* typedef struct {
80       unsigned int tower_len,
81       [size_is(tower_len)] char tower[];
82    } twr_t, *twr_p_t;
83 */
84 static int epm_dissect_tower (tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *drep);
85
86
87 static int
88 epm_dissect_pointer_IF_ID(tvbuff_t *tvb, int offset,
89                              packet_info *pinfo, proto_tree *tree,
90                              char *drep)
91 {
92         dcerpc_info *di;
93
94         di=pinfo->private_data;
95         offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
96                                      di->hf_index, NULL);
97         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
98                                      hf_epm_ver_maj, NULL);
99         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
100                                      hf_epm_ver_min, NULL);
101         return offset;
102 }
103
104 static int
105 epm_dissect_pointer_UUID(tvbuff_t *tvb, int offset,
106                              packet_info *pinfo, proto_tree *tree,
107                              char *drep)
108 {
109         dcerpc_info *di;
110
111         di=pinfo->private_data;
112         offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
113                                      di->hf_index, NULL);
114         return offset;
115 }
116
117 static int
118 epm_dissect_ept_lookup_rqst (tvbuff_t *tvb, int offset,
119                              packet_info *pinfo, proto_tree *tree,
120                              char *drep)
121 {
122     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
123                                  hf_epm_inquiry_type, NULL);
124
125     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
126                              epm_dissect_pointer_UUID, NDR_POINTER_PTR,
127                              "Object:", hf_epm_object);
128
129     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
130                              epm_dissect_pointer_IF_ID, NDR_POINTER_PTR,
131                              "Interface:", hf_epm_if_id);
132
133     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
134                                  hf_epm_ver_opt, NULL);
135
136     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
137                                   hf_epm_hnd, NULL);
138
139     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
140                                  hf_epm_max_ents, NULL);
141     return offset;
142 }
143
144
145 static int
146 epm_dissect_ept_entry_t(tvbuff_t *tvb, int offset,
147                              packet_info *pinfo, proto_tree *parent_tree,
148                              char *drep)
149 {
150     proto_item *item=NULL;
151     proto_tree *tree=NULL;
152     int old_offset=offset;
153     guint32 len;
154     gint strlen;
155     dcerpc_info *di;
156     const char *str;
157     
158     di=pinfo->private_data;
159     if(di->conformant_run){
160         return offset;
161     }
162
163     if(parent_tree){
164         item = proto_tree_add_text(parent_tree, tvb, offset, -1, "Entry:");
165         tree = proto_item_add_subtree(item, ett_epm_entry);
166     }
167
168     offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
169                                  hf_epm_object, NULL);
170
171     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
172                              epm_dissect_tower, NDR_POINTER_PTR,
173                              "Tower pointer:", -1);
174
175     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
176                                  hf_epm_ann_offset, NULL);
177     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
178                                  hf_epm_ann_len, &len);
179     str=(const char *)tvb_get_ptr(tvb, offset, -1);
180     strlen=len;
181     strlen=MIN(strlen,tvb_length_remaining(tvb, offset));
182     proto_tree_add_item(tree, hf_epm_annotation, tvb, offset, len, TRUE);
183     offset += len;
184
185     if(str&&str[0]){
186         if(parent_tree) {
187             proto_item_append_text(item, " Service:%*s ", strlen, str);
188             proto_item_append_text(tree->parent, " Service:%*s ", strlen, str);
189         }
190         if (check_col(pinfo->cinfo, COL_INFO)) {
191             col_append_fstr(pinfo->cinfo, COL_INFO, ", Service:%*s", strlen, str);
192         }
193     }
194
195     proto_item_set_len(item, offset-old_offset);
196     return offset;
197 }
198
199 static int
200 epm_dissect_ept_entry_t_array(tvbuff_t *tvb, int offset,
201                              packet_info *pinfo, proto_tree *tree,
202                              char *drep)
203 {
204     offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
205                              epm_dissect_ept_entry_t);
206
207     return offset;
208 }
209
210 static int
211 epm_dissect_ept_lookup_resp (tvbuff_t *tvb, int offset,
212                              packet_info *pinfo, proto_tree *tree,
213                              char *drep)
214 {
215     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
216                                   hf_epm_hnd, NULL);
217
218     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
219                                  hf_epm_num_ents, NULL);
220
221     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
222                              epm_dissect_ept_entry_t_array, NDR_POINTER_REF,
223                              "Entries:", -1);
224
225     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
226                                  hf_epm_rc, NULL);
227
228     return offset;
229 }
230
231 #if 0
232 static int
233 epm_dissect_uuid (tvbuff_t *tvb, int offset,
234                              packet_info *pinfo, proto_tree *tree,
235                              char *drep)
236 {
237     offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
238                                   hf_epm_uuid, NULL);
239     return offset;
240 }
241 #endif
242
243 #define PROTO_ID_OSI_OID        0x00
244 #define PROTO_ID_DNA_SESSCTL    0x02
245 #define PROTO_ID_DNA_SESSCTL_V3 0x03
246 #define PROTO_ID_DNA_NSP        0x04
247 #define PROTO_ID_OSI_TP4        0x05
248 #define PROTO_ID_OSI_CLNS       0x06
249 #define PROTO_ID_TCP            0x07
250 #define PROTO_ID_UDP            0x08
251 #define PROTO_ID_IP             0x09
252 #define PROTO_ID_RPC_CL         0x0a
253 #define PROTO_ID_RPC_CO         0x0b
254 #define PROTO_ID_UUID           0x0d
255 #define PROTO_ID_NAMED_PIPES    0x0f
256 #define PROTO_ID_NAMED_PIPES_2  0x10
257 #define PROTO_ID_NETBIOS        0x11
258 #define PROTO_ID_NETBEUI        0x12
259 #define PROTO_ID_NETWARE_SPX    0x13
260 #define PROTO_ID_NETWARE_IPX    0x14
261 #define PROTO_ID_ATALK_STREAM   0x16
262 #define PROTO_ID_ATALK_DATAGRAM 0x17
263 #define PROTO_ID_ATALK          0x18
264 #define PROTO_ID_NETBIOS_2      0x19
265 #define PROTO_ID_VINES_SPP      0x1a
266 #define PROTO_ID_VINES_IPC      0x1b
267 #define PROTO_ID_STREETTALK     0x1c
268 #define PROTO_ID_UNIX_DOMAIN    0x20
269 #define PROTO_ID_NULL           0x21
270 #define PROTO_ID_NETBIOS_3      0x22
271
272 static const value_string proto_id_vals[] = {
273         { PROTO_ID_OSI_OID,             "OSI OID"},
274         { PROTO_ID_DNA_SESSCTL,         "DNA Session Control"},
275         { PROTO_ID_DNA_SESSCTL_V3,      "DNA Session Control V3"},
276         { PROTO_ID_DNA_NSP,             "DNA NSP Transport"},
277         { PROTO_ID_OSI_TP4,             "OSI TP4"},
278         { PROTO_ID_OSI_CLNS,            "OSI CLNS or DNA Routing"},
279         { PROTO_ID_TCP,                 "DOD TCP"},
280         { PROTO_ID_UDP,                 "DOD UDP"},
281         { PROTO_ID_IP,                  "DOD IP"},
282         { PROTO_ID_RPC_CL,              "RPC connectionless protocol"},
283         { PROTO_ID_RPC_CO,              "RPC connection-oriented protocol"},
284         { PROTO_ID_UUID,                "UUID"},
285         { PROTO_ID_NAMED_PIPES,         "Named Pipes"}, 
286         { PROTO_ID_NAMED_PIPES_2,       "Named Pipes"},
287         { PROTO_ID_NETBIOS,             "NetBIOS"},
288         { PROTO_ID_NETBEUI,             "NetBEUI"},
289         { PROTO_ID_NETWARE_SPX,         "Netware SPX"},
290         { PROTO_ID_NETWARE_IPX,         "Netware IPX"},
291         { PROTO_ID_ATALK_STREAM,        "Appletalk Stream"},
292         { PROTO_ID_ATALK_DATAGRAM,      "Appletalk Datagram"},
293         { PROTO_ID_ATALK,               "Appletalk"},
294         { PROTO_ID_NETBIOS_2,           "NetBIOS"},
295         { PROTO_ID_VINES_SPP,           "Vines SPP"},
296         { PROTO_ID_VINES_IPC,           "Vines IPC"},
297         { PROTO_ID_STREETTALK,          "StreetTalk"},
298         { PROTO_ID_UNIX_DOMAIN,         "Unix Domain Socket"},
299         { PROTO_ID_NULL,                "null"},
300         { PROTO_ID_NETBIOS_3,           "NetBIOS"},
301         { 0, NULL},
302 };
303
304
305 /* XXX this function assumes LE encoding. can not use the NDR routines
306    since they assume padding.
307 */
308 static int
309 epm_dissect_tower_data (tvbuff_t *tvb, int offset,
310                              packet_info *pinfo, proto_tree *tree,
311                              char *drep)
312 {
313     guint16 num_floors, i;
314     dcerpc_info *di;
315
316     di=pinfo->private_data;
317     if(di->conformant_run){
318         return offset;
319     }
320
321     num_floors = tvb_get_letohs(tvb, offset);
322     proto_tree_add_uint(tree, hf_epm_tower_num_floors, tvb, offset, 2, num_floors);
323     offset += 2;
324
325     for(i=1;i<=num_floors;i++){
326         proto_item *it = NULL;
327         proto_tree *tr = NULL;
328         int old_offset = offset;
329         guint16 len;
330         guint8 proto_id;
331         e_uuid_t uuid;
332
333         it = proto_tree_add_text(tree, tvb, offset, 0, "Floor %d  ", i);
334         tr = proto_item_add_subtree(it, ett_epm_tower_floor);
335
336         len = tvb_get_letohs(tvb, offset);
337         proto_tree_add_uint(tr, hf_epm_tower_lhs_len, tvb, offset, 2, len);
338         offset += 2;
339
340         proto_id = tvb_get_guint8(tvb, offset);
341         proto_tree_add_uint(tr, hf_epm_tower_proto_id, tvb, offset, 1, proto_id);
342
343         switch(proto_id){
344         case PROTO_ID_UUID:
345             dcerpc_tvb_get_uuid (tvb, offset+1, drep, &uuid);
346
347             proto_tree_add_string_format (tr, hf_epm_uuid, tvb, offset+1, 16, "",
348                           "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
349                           uuid.Data1, uuid.Data2, uuid.Data3,
350                           uuid.Data4[0], uuid.Data4[1],
351                           uuid.Data4[2], uuid.Data4[3],
352                           uuid.Data4[4], uuid.Data4[5],
353                           uuid.Data4[6], uuid.Data4[7]);
354             proto_tree_add_text(tr, tvb, offset+17, 2, "Version %d.%d", tvb_get_guint8(tvb, offset+18), tvb_get_guint8(tvb, offset+17));
355
356             {
357                 guint16 version = tvb_get_ntohs(tvb, offset+17);
358                 char *service = dcerpc_get_proto_name(&uuid, version);
359                 if (service)
360                     proto_item_append_text(tr, "UUID: %s", service);
361                 else
362                     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,
363                                            uuid.Data4[0], uuid.Data4[1],
364                                            uuid.Data4[2], uuid.Data4[3],
365                                            uuid.Data4[4], uuid.Data4[5],
366                                            uuid.Data4[6], uuid.Data4[7],
367                                            tvb_get_guint8(tvb, offset+18), 
368                                            tvb_get_guint8(tvb, offset+17));
369             }
370             break;
371         }
372         offset += len;
373
374         len = tvb_get_letohs(tvb, offset);
375         proto_tree_add_uint(tr, hf_epm_tower_rhs_len, tvb, offset, 2, len);
376         offset += 2;
377
378         switch(proto_id){
379
380         case PROTO_ID_TCP: /* this one is always big endian */
381             proto_tree_add_item(tr, hf_epm_proto_tcp_port, tvb, offset, 2, FALSE);
382             proto_item_append_text(tr, "TCP Port:%d", tvb_get_ntohs(tvb, offset));
383             break;
384
385         case PROTO_ID_UDP: /* this one is always big endian */
386             proto_tree_add_item(tr, hf_epm_proto_udp_port, tvb, offset, 2, FALSE);
387             proto_item_append_text(tr, "UDP Port:%d", tvb_get_ntohs(tvb, offset));
388             break;
389
390         case PROTO_ID_IP: /* this one is always big endian */
391             proto_tree_add_item(tr, hf_epm_proto_ip, tvb, offset, 4, TRUE);
392             proto_item_append_text(tr, "IP:%s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
393             break;
394
395         case PROTO_ID_RPC_CO:
396             proto_item_append_text(tr, "RPC connection-oriented protocol");
397             break;
398
399         case PROTO_ID_NAMED_PIPES: /* \\PIPE\xxx   named pipe */
400             proto_tree_add_item(tr, hf_epm_proto_named_pipes, tvb, offset, len, TRUE);
401             proto_item_append_text(tr, "NamedPipe:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1)); 
402             break;
403
404         case PROTO_ID_NAMED_PIPES_2: /* PIPENAME  named pipe */
405             proto_tree_add_item(tr, hf_epm_proto_named_pipes, tvb, offset, len, TRUE);
406             proto_item_append_text(tr, "PIPE:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1)); 
407             break;
408
409         case PROTO_ID_NETBIOS: /* \\NETBIOS   netbios name */
410             proto_tree_add_item(tr, hf_epm_proto_netbios_name, tvb, offset, len, TRUE);
411             proto_item_append_text(tr, "NetBIOS:%*s",MIN(len,tvb_length_remaining(tvb, offset)), tvb_get_ptr(tvb, offset, -1)); 
412             break;
413
414         default:
415             if(len){
416                 proto_tree_add_text(tr, tvb, offset, len, "not decoded yet");
417             }
418         }
419         offset += len;
420
421         proto_item_set_len(it, offset-old_offset);
422     }
423     return offset;
424 }
425
426 /* typedef struct {
427       unsigned int tower_len,
428       [size_is(tower_len)] char tower[];
429    } twr_t, *twr_p_t;
430 */
431 static int
432 epm_dissect_tower (tvbuff_t *tvb, int offset,
433                              packet_info *pinfo, proto_tree *tree,
434                              char *drep)
435 {
436     guint32 len;
437     dcerpc_info *di;
438
439     di=pinfo->private_data;
440     if(di->conformant_run){
441         return offset;
442     }
443
444     /* first one is the header of the conformant array, second one is the
445        length field */
446     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
447                                  hf_epm_tower_length, &len);
448     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
449                                  hf_epm_tower_length, NULL);
450     offset = epm_dissect_tower_data(tvb, offset, pinfo, tree, drep);
451
452     return offset;
453 }
454 static int
455 epm_dissect_tower_pointer (tvbuff_t *tvb, int offset,
456                              packet_info *pinfo, proto_tree *tree,
457                              char *drep)
458 {
459     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
460                              epm_dissect_tower, NDR_POINTER_PTR,
461                              "Tower pointer:", -1);
462     return offset;
463 }
464 static int
465 epm_dissect_tower_array (tvbuff_t *tvb, int offset,
466                              packet_info *pinfo, proto_tree *tree,
467                              char *drep)
468 {
469     offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
470                              epm_dissect_tower_pointer);
471
472     return offset;
473 }
474
475 static int
476 epm_dissect_ept_map_rqst (tvbuff_t *tvb, int offset,
477                              packet_info *pinfo, proto_tree *tree,
478                              char *drep)
479 {
480     /* [in] handle_t h */
481     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
482                                   hf_epm_hnd, NULL);
483
484 #if 0
485     /* according to opengroup we should have an uuid pointer here.
486        in my w2k captures i can not see any such thing */
487     /* [in, ptr] uuid_p_t object */
488     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
489                              epm_dissect_uuid, NDR_POINTER_PTR,
490                              "UUID pointer:", -1, 1);
491 #endif
492
493     /* [in, ptr] twr_p_t map_tower */
494     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
495                              epm_dissect_tower, NDR_POINTER_PTR,
496                              "Tower pointer:", -1);
497
498     /* [in, out] ept_lookup_handle_t *entry_handle */
499     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
500                                   hf_epm_hnd, NULL);
501
502     /* [in] unsigned32 max_towers */
503     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
504                                  hf_epm_max_towers, NULL);
505
506     return offset;
507 }
508
509 static int
510 epm_dissect_ept_map_resp (tvbuff_t *tvb, int offset,
511                              packet_info *pinfo, proto_tree *tree,
512                              char *drep)
513 {
514     /* [in, out] ept_lookup_handle_t *entry_handle */
515     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
516                                   hf_epm_hnd, NULL);
517
518     /* [out, ptr] unsigned32 *num_towers */
519     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
520                                  hf_epm_num_towers, NULL);
521
522     /* [out, length_is(*num_towers), size_is(max_towers), ptr] twr_p_t towers[] */
523     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
524                              epm_dissect_tower_array, NDR_POINTER_REF,
525                              "Tower array:", -1);
526
527     /* [out] error_status_t *status */
528     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
529                                  hf_epm_rc, NULL);
530
531     return offset;
532 }
533
534 static int
535 epm_dissect_ept_entry_t_ucarray(tvbuff_t *tvb, int offset,
536                              packet_info *pinfo, proto_tree *tree,
537                              char *drep)
538 {
539     offset = dissect_ndr_ucarray(tvb, offset, pinfo, tree, drep,
540                              epm_dissect_ept_entry_t);
541
542     return offset;
543 }
544
545 static int
546 epm_dissect_ept_insert_rqst (tvbuff_t *tvb, int offset,
547                              packet_info *pinfo, proto_tree *tree,
548                              char *drep)
549 {
550     /* [in, out] ept_lookup_handle_t *entry_handle */
551     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
552                                   hf_epm_hnd, NULL);
553
554     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
555                                  hf_epm_num_ents, NULL);
556
557     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
558                              epm_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
559                              "Entries:", -1);
560
561     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
562                                  hf_epm_replace, NULL);
563
564     return offset;
565 }
566
567
568
569 static int
570 epm_dissect_ept_insert_resp (tvbuff_t *tvb, int offset,
571                              packet_info *pinfo, proto_tree *tree,
572                              char *drep)
573 {
574     /* [out] error_status_t *status */
575     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
576                                  hf_epm_rc, NULL);
577
578     return offset;
579 }
580
581
582 static int
583 epm_dissect_ept_delete_rqst (tvbuff_t *tvb, int offset,
584                              packet_info *pinfo, proto_tree *tree,
585                              char *drep)
586 {
587     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
588                                   hf_epm_hnd, NULL);
589
590     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
591                                  hf_epm_num_ents, NULL);
592
593     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
594                              epm_dissect_ept_entry_t_ucarray, NDR_POINTER_REF,
595                              "Entries:", -1);
596
597     return offset;
598 }
599
600
601
602 static int
603 epm_dissect_ept_delete_resp (tvbuff_t *tvb, int offset,
604                              packet_info *pinfo, proto_tree *tree,
605                              char *drep)
606 {
607     /* [out] error_status_t *status */
608     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
609                                  hf_epm_rc, NULL);
610
611     return offset;
612 }
613
614
615
616 static int
617 epm_dissect_ept_lookup_handle_free_rqst (tvbuff_t *tvb, int offset,
618                              packet_info *pinfo, proto_tree *tree,
619                              char *drep)
620 {
621     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
622                                   hf_epm_hnd, NULL);
623
624     return offset;
625 }
626
627 static int
628 epm_dissect_ept_lookup_handle_free_resp (tvbuff_t *tvb, int offset,
629                              packet_info *pinfo, proto_tree *tree,
630                              char *drep)
631 {
632     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
633                                   hf_epm_hnd, NULL);
634
635     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
636                                  hf_epm_rc, NULL);
637
638     return offset;
639 }
640
641
642 static dcerpc_sub_dissector epm_dissectors[] = {
643     { 0, "Insert", 
644         epm_dissect_ept_insert_rqst,
645         epm_dissect_ept_insert_resp },
646     { 1, "Delete",
647         epm_dissect_ept_delete_rqst,
648         epm_dissect_ept_delete_resp },
649     { 2, "Lookup",
650         epm_dissect_ept_lookup_rqst,
651         epm_dissect_ept_lookup_resp },
652     { 3, "Map",
653         epm_dissect_ept_map_rqst,
654         epm_dissect_ept_map_resp },
655     { 4, "LookupHandleFree",
656         epm_dissect_ept_lookup_handle_free_rqst,
657         epm_dissect_ept_lookup_handle_free_resp },
658     { 5, "InqObject", NULL, NULL },
659     { 6, "MgmtDelete", NULL, NULL },
660     { 0, NULL, NULL, NULL }
661 };
662
663 void
664 proto_register_epm (void)
665 {
666         static hf_register_info hf[] = {
667         { &hf_epm_opnum,
668           { "Operation", "epm.opnum", FT_UINT16, BASE_DEC,
669             NULL, 0x0, "Operation", HFILL }},
670         { &hf_epm_inquiry_type,
671           { "Inquiry type", "epm.inq_type", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
672         { &hf_epm_object,
673           { "Object", "epm.object", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
674         { &hf_epm_if_id,
675           { "Interface", "epm.if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
676         { &hf_epm_ver_maj,
677           { "Version Major", "epm.ver_maj", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
678         { &hf_epm_ver_min,
679           { "Version Minor", "epm.ver_min", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
680         { &hf_epm_ver_opt,
681           { "Version Option", "epm.ver_opt", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
682         { &hf_epm_hnd,
683           { "Handle", "epm.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},
684         { &hf_epm_max_ents,
685           { "Max entries", "epm.max_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
686         { &hf_epm_num_ents,
687           { "Num entries", "epm.num_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
688         { &hf_epm_uuid,
689           { "UUID", "epm.uuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }},
690         { &hf_epm_annotation,
691           { "Annotation", "epm.annotation", FT_STRING, BASE_NONE, NULL, 0x0, "Annotation", HFILL }},
692         { &hf_epm_proto_named_pipes,
693           { "Named Pipe", "epm.proto.named_pipe", FT_STRING, BASE_NONE, NULL, 0x0, "Name of the named pipe for this service", HFILL }},
694         { &hf_epm_proto_netbios_name,
695           { "NetBIOS Name", "epm.proto.netbios_name", FT_STRING, BASE_NONE, NULL, 0x0, "NetBIOS name where this service can be found", HFILL }},
696         { &hf_epm_tower_length,
697           { "Length", "epm.tower.len", FT_UINT32, BASE_DEC, NULL, 0x0, "Length of tower data", HFILL }},
698         { &hf_epm_tower_data,
699           { "Tower", "epm.tower", FT_BYTES, BASE_HEX, NULL, 0x0, "Tower data", HFILL }},
700         { &hf_epm_max_towers,
701           { "Max Towers", "epm.max_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum number of towers to return", HFILL }},
702         { &hf_epm_num_towers,
703           { "Num Towers", "epm.num_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Number number of towers to return", HFILL }},
704         { &hf_epm_ann_offset,
705           { "Annotation offset", "epm.ann_offset", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
706         { &hf_epm_ann_len,
707           { "Annotation length", "epm.ann_len", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
708         { &hf_epm_rc,
709           { "Return code", "epm.rc", FT_UINT32, BASE_HEX, NULL, 0x0, "EPM return value", HFILL }},
710         { &hf_epm_replace,
711           { "Replace", "epm.replace", FT_UINT8, BASE_DEC, NULL, 0x0, "Replace existing objects?", HFILL }},
712         { &hf_epm_tower_num_floors,
713           { "Number of floors", "epm.tower.num_floors", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of floors in tower", HFILL }},
714         { &hf_epm_proto_udp_port,
715           { "UDP Port", "epm.proto.udp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "UDP Port where this service can be found", HFILL }},
716         { &hf_epm_proto_tcp_port,
717           { "TCP Port", "epm.proto.tcp_port", FT_UINT16, BASE_DEC, NULL, 0x0, "TCP Port where this service can be found", HFILL }},
718         { &hf_epm_tower_rhs_len,
719           { "RHS Length", "epm.tower.rhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of RHS data", HFILL }},
720         { &hf_epm_tower_lhs_len,
721           { "LHS Length", "epm.tower.lhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of LHS data", HFILL }},
722         { &hf_epm_proto_ip,
723           { "IP", "epm.proto.ip", FT_IPv4, BASE_NONE, NULL, 0x0, "IP address where service is located", HFILL }},
724         { &hf_epm_tower_proto_id,
725           { "Protocol", "epm.tower.proto_id", FT_UINT8, BASE_HEX, VALS(proto_id_vals), 0x0, "Protocol identifier", HFILL }}
726     };
727
728         static gint *ett[] = {
729                 &ett_epm,
730                 &ett_epm_tower_floor,
731                 &ett_epm_entry
732         };
733         proto_epm = proto_register_protocol ("DCE/RPC Endpoint Mapper", "EPM", "epm");
734         proto_register_field_array (proto_epm, hf, array_length (hf));
735         proto_register_subtree_array (ett, array_length (ett));
736 }
737
738 void
739 proto_reg_handoff_epm (void)
740 {
741         /* Register the protocol as dcerpc */
742         dcerpc_init_uuid (proto_epm, ett_epm, &uuid_epm, ver_epm, epm_dissectors, hf_epm_opnum);
743 }