Removed trailing whitespaces from .h and .c files using the
[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.13 2002/08/04 00:45:49 sahlberg 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
37
38 static int proto_epm = -1;
39
40 static int hf_epm_opnum = -1;
41 static int hf_epm_inquiry_type = -1;
42 static int hf_epm_object_p = -1;
43 static int hf_epm_object = -1;
44 static int hf_epm_if_id_p = -1;
45 static int hf_epm_if_id = -1;
46 static int hf_epm_ver_maj = -1;
47 static int hf_epm_ver_min = -1;
48 static int hf_epm_ver_opt = -1;
49 static int hf_epm_hnd = -1;
50 static int hf_epm_max_ents = -1;
51 static int hf_epm_num_ents = -1;
52 static int hf_epm_uuid = -1;
53 static int hf_epm_tower_length = -1;
54 static int hf_epm_tower_data = -1;
55 static int hf_epm_max_towers = -1;
56 static int hf_epm_num_towers = -1;
57 static int hf_epm_rc = -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
63 static gint ett_epm = -1;
64 static gint ett_epm_tower_floor = -1;
65
66 static e_uuid_t uuid_epm = { 0xe1af8308, 0x5d1f, 0x11c9, { 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa } };
67 static guint16  ver_epm = 3;
68
69
70 static int
71 epm_dissect_ept_lookup_rqst (tvbuff_t *tvb, int offset, 
72                              packet_info *pinfo, proto_tree *tree, 
73                              char *drep)
74 {
75     guint32 dummy;
76     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
77                                  hf_epm_inquiry_type, NULL);
78     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
79                                  hf_epm_object_p, &dummy);
80     if (dummy) {
81         offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
82                                      hf_epm_object, NULL);
83     }
84     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
85                                  hf_epm_if_id_p, &dummy);
86     if (dummy) {
87         offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
88                                      hf_epm_if_id, NULL);
89         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
90                                      hf_epm_ver_maj, NULL);
91         offset = dissect_ndr_uint16 (tvb, offset, pinfo, tree, drep,
92                                      hf_epm_ver_min, NULL);
93     }
94     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
95                                  hf_epm_ver_opt, NULL);
96     if (tree) {
97         proto_tree_add_bytes (tree, hf_epm_hnd, tvb, offset, 20,
98                               tvb_get_ptr (tvb, offset, 20));
99     }
100     offset += 20;
101
102     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
103                                  hf_epm_max_ents, NULL);
104     return offset;
105 }
106
107
108 static int
109 epm_dissect_ept_lookup_resp (tvbuff_t *tvb, int offset, 
110                              packet_info *pinfo, proto_tree *tree, 
111                              char *drep)
112 {
113     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
114                                   hf_epm_hnd, NULL);
115
116     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
117                                  hf_epm_num_ents, NULL);
118     /* FIXME: more to do here */
119     return offset;
120 }
121
122 #if 0
123 static int
124 epm_dissect_uuid (tvbuff_t *tvb, int offset, 
125                              packet_info *pinfo, proto_tree *tree, 
126                              char *drep)
127 {
128     offset = dissect_ndr_uuid_t (tvb, offset, pinfo, tree, drep,
129                                   hf_epm_uuid, NULL);
130     return offset;
131 }
132 #endif
133
134
135
136 static const value_string proto_id_vals[] = {
137         { 0x00, "OSI OID"},
138         { 0x0d, "UUID"},
139         { 0x05, "OSI TP4"},
140         { 0x06, "OSI CLNS or DNA Routing"},
141         { 0x07, "DOD TCP"},
142         { 0x08, "DOD UDP"},
143         { 0x09, "DOD IP"},
144         { 0x0a, "RPC connectionless protocol"},
145         { 0x0b, "RPC connection-oriented protocol"},
146         { 0x02, "DNA Session Control"},
147         { 0x03, "DNA Session Control V3"},
148         { 0x04, "DNA NSP Transport"},
149         { 0x10, "Named Pipes"},
150         { 0x11, "NetBIOS"},
151         { 0x12, "NetBEUI"},
152         { 0x13, "Netware SPX"},
153         { 0x14, "Netware IPX"},
154         { 0x16, "Appletalk Stream"},
155         { 0x17, "Appletalk Datagram"},
156         { 0x18, "Appletalk"},
157         { 0x19, "NetBIOS"},
158         { 0x1a, "Vines SPP"},
159         { 0x1b, "Vines IPC"},
160         { 0x1c, "StreetTalk"},
161         { 0x20, "Unix Domain Socket"},
162         { 0x21, "null"},
163         { 0x22, "NetBIOS"},
164         { 0, NULL},
165 };
166
167
168 /* XXX this function assumes LE encoding. can not use the NDR routines
169    since they assume padding.
170 */ 
171 static int
172 epm_dissect_tower_data (tvbuff_t *tvb, int offset, 
173                              packet_info *pinfo, proto_tree *tree, 
174                              char *drep)
175 {
176     guint16 num_floors, i;
177     dcerpc_info *di;
178
179     di=pinfo->private_data;
180     if(di->conformant_run){
181         return offset;
182     }
183
184     num_floors = tvb_get_letohs(tvb, offset);
185     proto_tree_add_uint(tree, hf_epm_tower_num_floors, tvb, offset, 2, num_floors);
186     offset += 2;
187
188     for(i=1;i<=num_floors;i++){
189         proto_item *it = NULL;
190         proto_tree *tr = NULL;
191         int old_offset = offset;
192         guint16 len;
193         guint8 proto_id;
194         e_uuid_t uuid;
195
196         it = proto_tree_add_text(tree, tvb, offset, 0, "Floor %d", i);
197         tr = proto_item_add_subtree(it, ett_epm_tower_floor);
198
199         len = tvb_get_letohs(tvb, offset);
200         proto_tree_add_uint(tr, hf_epm_tower_lhs_len, tvb, offset, 2, len);
201         offset += 2;
202
203         proto_id = tvb_get_guint8(tvb, offset);
204         proto_tree_add_uint(tr, hf_epm_tower_proto_id, tvb, offset, 1, proto_id);
205         
206         switch(proto_id){
207         case 0x0d: /* UUID */
208             dcerpc_tvb_get_uuid (tvb, offset+1, drep, &uuid);
209             proto_tree_add_string_format (tr, hf_epm_uuid, tvb, offset+1, 16, "",
210                           "UUID: %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
211                           uuid.Data1, uuid.Data2, uuid.Data3,
212                           uuid.Data4[0], uuid.Data4[1],
213                           uuid.Data4[2], uuid.Data4[3],
214                           uuid.Data4[4], uuid.Data4[5],
215                           uuid.Data4[6], uuid.Data4[7]);
216             proto_tree_add_text(tr, tvb, offset+17, 2, "Version %d.%d", tvb_get_guint8(tvb, offset+18), tvb_get_guint8(tvb, offset+17));
217             break;
218         }
219         offset += len;
220       
221         len = tvb_get_letohs(tvb, offset);
222         proto_tree_add_uint(tr, hf_epm_tower_rhs_len, tvb, offset, 2, len);
223         offset += 2;
224
225         switch(proto_id){
226         case 0x07: /* TCP this one is always big endian */
227             proto_tree_add_text(tr, tvb, offset, 2, "TCP Port: %d", tvb_get_ntohs(tvb, offset));
228             break;
229         case 0x08: /* UDP this one is always big endian */
230             proto_tree_add_text(tr, tvb, offset, 2, "UDP Port: %d", tvb_get_ntohs(tvb, offset));
231             break;
232         case 0x09: /* IP this one is always big endian */
233             proto_tree_add_text(tr, tvb, offset, 4, "IP address: %s", ip_to_str(tvb_get_ptr(tvb, offset, 4)));
234             break;
235         default:
236             if(len){
237                 proto_tree_add_text(tr, tvb, offset, len, "not decoded yet");
238             }
239         }
240         offset += len;
241
242         proto_item_set_len(it, offset-old_offset);
243     }
244     return offset;
245 }
246
247 /* typedef struct {
248       unsigned int tower_len,
249       [size_is(tower_len)] char tower[];
250    } twr_t, *twr_p_t;
251 */
252 static int
253 epm_dissect_tower (tvbuff_t *tvb, int offset, 
254                              packet_info *pinfo, proto_tree *tree, 
255                              char *drep)
256 {
257     guint32 len;
258     dcerpc_info *di;
259
260     di=pinfo->private_data;
261     if(di->conformant_run){
262         return offset;
263     }
264
265     /* first one is the header of the conformant array, second one is the
266        length field */
267     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
268                                  hf_epm_tower_length, &len);
269     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
270                                  hf_epm_tower_length, NULL);
271     offset = epm_dissect_tower_data(tvb, offset, pinfo, tree, drep);
272
273     return offset;
274 }
275 static int
276 epm_dissect_tower_pointer (tvbuff_t *tvb, int offset, 
277                              packet_info *pinfo, proto_tree *tree, 
278                              char *drep)
279 {
280     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
281                              epm_dissect_tower, NDR_POINTER_PTR,
282                              "Tower pointer:", -1, 1);
283     return offset;
284 }
285 static int
286 epm_dissect_tower_array (tvbuff_t *tvb, int offset, 
287                              packet_info *pinfo, proto_tree *tree, 
288                              char *drep)
289 {
290     offset = dissect_ndr_ucvarray(tvb, offset, pinfo, tree, drep,
291                              epm_dissect_tower_pointer);
292
293     return offset;
294 }
295
296 static int
297 epm_dissect_ept_map_rqst (tvbuff_t *tvb, int offset, 
298                              packet_info *pinfo, proto_tree *tree, 
299                              char *drep)
300 {
301     /* [in] handle_t h */
302     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
303                                   hf_epm_hnd, NULL);
304
305 #if 0
306     /* according to opengroup we should have an uuid pointer here.
307        in my w2k captures i can not see any such thing */
308     /* [in, ptr] uuid_p_t object */
309     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
310                              epm_dissect_uuid, NDR_POINTER_PTR,
311                              "UUID pointer:", -1, 1);
312 #endif
313
314     /* [in, ptr] twr_p_t map_tower */
315     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
316                              epm_dissect_tower, NDR_POINTER_PTR,
317                              "Tower pointer:", -1, 1);
318
319     /* [in, out] ept_lookup_handle_t *entry_handle */
320     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
321                                   hf_epm_hnd, NULL);
322
323     /* [in] unsigned32 max_towers */
324     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
325                                  hf_epm_max_towers, NULL);
326
327     return offset;
328 }
329
330 static int
331 epm_dissect_ept_map_resp (tvbuff_t *tvb, int offset, 
332                              packet_info *pinfo, proto_tree *tree, 
333                              char *drep)
334 {
335     /* [in, out] ept_lookup_handle_t *entry_handle */
336     offset = dissect_ndr_ctx_hnd (tvb, offset, pinfo, tree, drep,
337                                   hf_epm_hnd, NULL);
338
339     /* [out, ptr] unsigned32 *num_towers */
340     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
341                                  hf_epm_num_towers, NULL);
342
343     /* [out, length_is(*num_towers), size_is(max_towers), ptr] twr_p_t towers[] */
344     offset = dissect_ndr_pointer(tvb, offset, pinfo, tree, drep,
345                              epm_dissect_tower_array, NDR_POINTER_REF,
346                              "Tower array:", -1, 1);
347
348     /* [out] error_status_t *status */
349     offset = dissect_ndr_uint32 (tvb, offset, pinfo, tree, drep,
350                                  hf_epm_rc, NULL);
351
352     return offset;
353 }
354
355 static dcerpc_sub_dissector epm_dissectors[] = {
356     { 0, "ept_insert", NULL, NULL },
357     { 1, "ept_delete", NULL, NULL },
358     { 2, "ept_lookup", 
359         epm_dissect_ept_lookup_rqst, 
360         epm_dissect_ept_lookup_resp },
361     { 3, "Map", 
362         epm_dissect_ept_map_rqst, 
363         epm_dissect_ept_map_resp },
364     { 4, "ept_lookup_handle_free", NULL, NULL },
365     { 5, "ept_inq_object", NULL, NULL },
366     { 6, "ept_mgmt_delete", NULL, NULL },
367     { 0, NULL, NULL, NULL }
368 };
369
370 static const value_string epm_opnum_vals[] = {
371         { 0, "insert" },
372         { 1, "delete" },
373         { 2, "lookup" },
374         { 3, "map" },
375         { 4, "lookup_handle_free" },
376         { 5, "inq_object" },
377         { 6, "mgmt_delete" },
378         { 0, NULL }
379 };
380
381 void
382 proto_register_epm (void)
383 {
384         static hf_register_info hf[] = {
385         { &hf_epm_opnum,
386           { "Operation", "epm.opnum", FT_UINT16, BASE_DEC,
387             VALS(epm_opnum_vals), 0x0, "Operation", HFILL }},
388         { &hf_epm_inquiry_type,
389           { "Inquiry type", "epm.inq_type", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
390         { &hf_epm_object_p,
391           { "Object pointer", "epm.object_p", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
392         { &hf_epm_object,
393           { "Object", "epm.object", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
394         { &hf_epm_if_id_p,
395           { "Interface pointer", "epm.if_id_p", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
396         { &hf_epm_if_id,
397           { "Interface", "epm.if_id", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
398         { &hf_epm_ver_maj,
399           { "Version Major", "epm.ver_maj", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
400         { &hf_epm_ver_min,
401           { "Version Minor", "epm.ver_min", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
402         { &hf_epm_ver_opt,
403           { "Version Option", "epm.ver_opt", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},      
404         { &hf_epm_hnd,
405           { "Handle", "epm.hnd", FT_BYTES, BASE_NONE, NULL, 0x0, "Context handle", HFILL }},    
406         { &hf_epm_max_ents,
407           { "Max entries", "epm.max_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
408         { &hf_epm_num_ents,
409           { "Num entries", "epm.num_ents", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
410         { &hf_epm_uuid,
411           { "UUID", "epm.uuid", FT_STRING, BASE_NONE, NULL, 0x0, "UUID", HFILL }},      
412         { &hf_epm_tower_length,
413           { "Length", "epm.tower.len", FT_UINT32, BASE_DEC, NULL, 0x0, "Length of tower data", HFILL }},
414         { &hf_epm_tower_data,
415           { "Tower", "epm.tower", FT_BYTES, BASE_HEX, NULL, 0x0, "Tower data", HFILL }},
416         { &hf_epm_max_towers,
417           { "Max Towers", "epm.max_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Maximum number of towers to return", HFILL }},
418         { &hf_epm_num_towers,
419           { "Num Towers", "epm.num_towers", FT_UINT32, BASE_DEC, NULL, 0x0, "Number number of towers to return", HFILL }},
420         { &hf_epm_rc,
421           { "Return code", "epm.rc", FT_UINT32, BASE_HEX, NULL, 0x0, "EPM return value", HFILL }},
422         { &hf_epm_tower_num_floors,
423           { "Number of floors", "epm.tower.num_floors", FT_UINT16, BASE_DEC, NULL, 0x0, "Number of floors in tower", HFILL }},
424         { &hf_epm_tower_rhs_len,
425           { "RHS Length", "epm.tower.rhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of RHS data", HFILL }},
426         { &hf_epm_tower_lhs_len,
427           { "LHS Length", "epm.tower.lhs.len", FT_UINT16, BASE_DEC, NULL, 0x0, "Length of LHS data", HFILL }},
428         { &hf_epm_tower_proto_id,
429           { "Protocol", "epm.tower.proto_id", FT_UINT8, BASE_HEX, VALS(proto_id_vals), 0x0, "Protocol identifier", HFILL }}
430     };
431
432         static gint *ett[] = {
433                 &ett_epm,
434                 &ett_epm_tower_floor
435         };
436         proto_epm = proto_register_protocol ("DCE/RPC Endpoint Mapper", "EPM", "epm");
437         proto_register_field_array (proto_epm, hf, array_length (hf));
438         proto_register_subtree_array (ett, array_length (ett));
439 }
440
441 void
442 proto_reg_handoff_epm (void)
443 {
444         /* Register the protocol as dcerpc */
445         dcerpc_init_uuid (proto_epm, ett_epm, &uuid_epm, ver_epm, epm_dissectors, hf_epm_opnum);
446 }