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