2 * Routines for DCERPC over SMB packet disassembly
3 * Copyright 2001, Tim Potter <tpot@samba.org>
5 * $Id: packet-dcerpc-nt.c,v 1.4 2002/01/21 07:36:33 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
31 #include <epan/packet.h>
32 #include "packet-dcerpc.h"
33 #include "packet-dcerpc-nt.h"
37 * This file contains helper routines that are used by the DCERPC over SMB
38 * dissectors for ethereal.
41 /* Align offset to a n-byte boundary */
43 int prs_align(int offset, int n)
46 offset += n - (offset % n);
51 /* Parse a 8-bit integer */
53 int prs_uint8(tvbuff_t *tvb, int offset, packet_info *pinfo,
54 proto_tree *tree, guint8 *data, char *name)
58 /* No alignment required */
60 i = tvb_get_guint8(tvb, offset);
64 proto_tree_add_text(tree, tvb, offset - 1, 1,
73 int prs_uint8s(tvbuff_t *tvb, int offset, packet_info *pinfo,
74 proto_tree *tree, int count, guint8 **data, char *name)
78 /* The tvb_get_ptr() function fails an assertion if count < -1 */
83 /* No alignment required */
85 ptr = tvb_get_ptr(tvb, offset, count);
88 proto_tree_add_text(tree, tvb, offset, count, "%s", name);
91 *data = (guint8 *)ptr;
98 /* Parse a 16-bit integer */
100 int prs_uint16(tvbuff_t *tvb, int offset, packet_info *pinfo,
101 proto_tree *tree, guint16 *data, char *name)
105 offset = prs_align(offset, 2);
107 i = tvb_get_letohs(tvb, offset);
111 proto_tree_add_text(tree, tvb, offset - 2, 2,
119 /* Parse a number of uint16's */
121 int prs_uint16s(tvbuff_t *tvb, int offset, packet_info *pinfo,
122 proto_tree *tree, int count, guint16 **data, char *name)
126 /* The tvb_get_ptr() function fails an assertion if count < -1 */
131 offset = prs_align(offset, 2);
133 ptr = tvb_get_ptr(tvb, offset, count * 2);
136 proto_tree_add_text(tree, tvb, offset, count * 2,
139 *data = (guint16 *)ptr;
146 /* Parse a 32-bit integer */
148 int prs_uint32(tvbuff_t *tvb, int offset, packet_info *pinfo,
149 proto_tree *tree, guint32 *data, char *name)
153 offset = prs_align(offset, 4);
155 i = tvb_get_letohl(tvb, offset);
159 proto_tree_add_text(tree, tvb, offset - 4, 4,
168 /* Parse a number of 32-bit integers */
170 int prs_uint32s(tvbuff_t *tvb, int offset, packet_info *pinfo,
171 proto_tree *tree, int count, guint32 **data, char *name)
175 /* The tvb_get_ptr() function fails an assertion if count < -1 */
180 offset = prs_align(offset, 4);
182 ptr = tvb_get_ptr(tvb, offset, count * 4);
185 proto_tree_add_text(tree, tvb, offset - 4, 4,
188 *data = (guint32 *)ptr;
195 /* Parse a NT status code */
197 int prs_ntstatus(tvbuff_t *tvb, int offset, packet_info *pinfo,
202 offset = prs_uint32(tvb, offset, pinfo, tree, &status, NULL);
205 proto_tree_add_text(tree, tvb, offset - 4, 4, "Status: %s",
206 val_to_str(status, NT_errors, "???"));
212 * We need to keep track of deferred referrents as they appear in the
213 * packet after all the non-pointer objects.
214 * to keep track of pointers as they are parsed as scalars and need to be
215 * remembered for the next call to the prs function.
217 * Pointers are stored in a linked list and pushed in the PARSE_SCALARS
218 * section of the prs function and popped in the PARSE_BUFFERS section. If
219 * we try to pop off a referrent that has a different name then we are
220 * expecting then something has gone wrong.
230 /* Create a new pointer */
232 static struct ptr *new_ptr(char *name, guint32 value)
236 p = g_malloc(sizeof(struct ptr));
238 p->name = g_strdup(name);
246 static void free_ptr(struct ptr *p)
254 /* Parse a pointer and store it's value in a linked list */
256 int prs_push_ptr(tvbuff_t *tvb, int offset, packet_info *pinfo,
257 proto_tree *tree, GList **ptr_list, char *name)
262 offset = prs_uint32(tvb, offset, pinfo, tree, &value, NULL);
265 proto_tree_add_text(tree, tvb, offset - 4, 4,
266 "%s pointer: 0x%08x", name, value);
268 p = new_ptr(name, value);
270 *ptr_list = g_list_append(*ptr_list, p);
273 fprintf(stderr, "DEBUG_PTRS: pushing %s ptr = 0x%08x, %d ptrs in "
274 "list\n", name, value, g_list_length(*ptr_list));
280 /* Pop a pointer of a given name. Return it's value. */
282 guint32 prs_pop_ptr(GList **ptr_list, char *name)
288 g_assert(g_list_length(*ptr_list) != 0); /* List too short */
290 /* Get pointer at head of list */
292 elt = g_list_first(*ptr_list);
293 p = (struct ptr *)elt->data;
297 if (strcmp(p->name, name) != 0) {
298 fprintf(stderr, "DEBUG_PTRS: wrong pointer (%s != %s)\n",
303 /* Free pointer record */
305 *ptr_list = g_list_remove_link(*ptr_list, elt);
308 fprintf(stderr, "DEBUG_PTRS: popping %s ptr = 0x%08x, %d ptrs in "
309 "list\n", p->name, p->value, g_list_length(*ptr_list));
318 * Parse a UNISTR2 structure
323 * [size_is(size/2)] [length_is(length/2)] [unique] wchar_t *string;
328 /* Convert a string from little-endian unicode to ascii. At the moment we
329 fake it by taking every odd byte. )-: The caller must free the
332 char *fake_unicode(guint16 *data, int len)
337 buffer = malloc(len + 1);
339 for (i = 0; i < len; i++)
340 buffer[i] = data[i] & 0xff;
347 /* Parse a UNISTR2 structure */
349 int prs_UNISTR2(tvbuff_t *tvb, int offset, packet_info *pinfo,
350 proto_tree *tree, int flags, char **data, char *name)
352 guint32 len = 0, unknown = 0, max_len = 0;
354 if (flags & PARSE_SCALARS) {
355 offset = prs_uint32(tvb, offset, pinfo, tree, &len, "Length");
356 offset = prs_uint32(tvb, offset, pinfo, tree, &unknown,
358 offset = prs_uint32(tvb, offset, pinfo, tree, &max_len,
362 if (flags & PARSE_BUFFERS) {
365 offset = prs_uint16s(tvb, offset, pinfo, tree, max_len,
369 *data = fake_unicode(data16, max_len);
375 /* Parse a policy handle. */
377 int prs_policy_hnd(tvbuff_t *tvb, int offset, packet_info *pinfo,
378 proto_tree *tree, const guint8 **data)
382 offset = prs_align(offset, 4);
384 proto_tree_add_text(tree, tvb, offset, 20, "Policy Handle");
386 data8 = tvb_get_ptr(tvb, offset, 20);