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