Add some additional sanity checking.
[obnox/wireshark/wip.git] / packet-dcerpc-ndr.c
1 /* packet-dcerpc-ndr.c
2  * Routines for DCERPC NDR dissection
3  * Copyright 2001, Todd Sabin <tas@webspan.net>
4  *
5  * $Id: packet-dcerpc-ndr.c,v 1.14 2003/11/21 02:48:11 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 #include <string.h>
31 #include <ctype.h>
32
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include "packet-dcerpc.h"
36
37
38 /*
39  * The NDR routines are for use by dcerpc subdissetors.  They're
40  * primarily for making sure things are aligned properly according
41  * to the rules of NDR.
42  */
43
44 int
45 dissect_ndr_uint8 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
46                    proto_tree *tree, char *drep,
47                    int hfindex, guint8 *pdata)
48 {
49     dcerpc_info *di;
50
51     di=pinfo->private_data;
52     if(di->conformant_run){
53       /* just a run to handle conformant arrays, no scalars to dissect */
54       return offset;
55     }
56
57     /* no alignment needed */
58     return dissect_dcerpc_uint8 (tvb, offset, pinfo,
59                                  tree, drep, hfindex, pdata);
60 }
61
62 int
63 dissect_ndr_uint16 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
64                     proto_tree *tree, char *drep,
65                     int hfindex, guint16 *pdata)
66 {
67     dcerpc_info *di;
68
69     di=pinfo->private_data;
70     if(di->conformant_run){
71       /* just a run to handle conformant arrays, no scalars to dissect */
72       return offset;
73     }
74
75
76     if (offset % 2) {
77         offset++;
78     }
79     return dissect_dcerpc_uint16 (tvb, offset, pinfo,
80                                   tree, drep, hfindex, pdata);
81 }
82
83 int
84 dissect_ndr_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
85                     proto_tree *tree, char *drep,
86                     int hfindex, guint32 *pdata)
87 {
88     dcerpc_info *di;
89
90     di=pinfo->private_data;
91     if(di->conformant_run){
92       /* just a run to handle conformant arrays, no scalars to dissect */
93       return offset;
94     }
95
96
97     if (offset % 4) {
98         offset += 4 - (offset % 4);
99     }
100     return dissect_dcerpc_uint32 (tvb, offset, pinfo,
101                                   tree, drep, hfindex, pdata);
102 }
103
104 int
105 dissect_ndr_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo,
106                     proto_tree *tree, char *drep,
107                     int hfindex, unsigned char *pdata)
108 {
109     dcerpc_info *di;
110
111     di=pinfo->private_data;
112     if(di->conformant_run){
113       /* just a run to handle conformant arrays, no scalars to dissect */
114       return offset;
115     }
116
117     if (offset % 4) {
118         offset += 4 - (offset % 4);
119     }
120     return dissect_dcerpc_uint64 (tvb, offset, pinfo,
121                                   tree, drep, hfindex, pdata);
122 }
123
124
125 int
126 dissect_ndr_float(tvbuff_t *tvb, gint offset, packet_info *pinfo,
127                     proto_tree *tree, char *drep, 
128                     int hfindex, gfloat *pdata)
129 {
130     dcerpc_info *di;
131
132
133     di=pinfo->private_data;
134     if(di->conformant_run){
135       /* just a run to handle conformant arrays, no scalars to dissect */
136       return offset;
137     }
138
139     if (offset % 4) {
140         offset += 4 - (offset % 4);
141     }
142     return dissect_dcerpc_float(tvb, offset, pinfo, 
143                                   tree, drep, hfindex, pdata);
144 }
145
146
147 int
148 dissect_ndr_double(tvbuff_t *tvb, gint offset, packet_info *pinfo,
149                     proto_tree *tree, char *drep, 
150                     int hfindex, gdouble *pdata)
151 {
152     dcerpc_info *di;
153
154
155     di=pinfo->private_data;
156     if(di->conformant_run){
157       /* just a run to handle conformant arrays, no scalars to dissect */
158       return offset;
159     }
160
161     if (offset % 8) {
162         offset += 8 - (offset % 8);
163     }
164     return dissect_dcerpc_double(tvb, offset, pinfo, 
165                                   tree, drep, hfindex, pdata);
166 }
167
168 /* handles unix 32 bit time_t */
169 int
170 dissect_ndr_time_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
171                     proto_tree *tree, char *drep,
172                     int hfindex, guint32 *pdata)
173 {
174     dcerpc_info *di;
175
176     di=pinfo->private_data;
177     if(di->conformant_run){
178       /* just a run to handle conformant arrays, no scalars to dissect */
179       return offset;
180     }
181
182
183     if (offset % 4) {
184         offset += 4 - (offset % 4);
185     }
186     return dissect_dcerpc_time_t (tvb, offset, pinfo,
187                                   tree, drep, hfindex, pdata);
188 }
189
190 int
191 dissect_ndr_uuid_t (tvbuff_t *tvb, gint offset, packet_info *pinfo,
192                     proto_tree *tree, char *drep,
193                     int hfindex, e_uuid_t *pdata)
194 {
195     e_uuid_t uuid;
196     dcerpc_info *di;
197     char uuid_str[DCERPC_UUID_STR_LEN]; 
198     int uuid_str_len;
199
200     di=pinfo->private_data;
201     if(di->conformant_run){
202       /* just a run to handle conformant arrays, no scalars to dissect */
203       return offset;
204     }
205
206     /* uuid's are aligned to 4 bytes, due to initial uint32 in struct */
207     if (offset % 4) {
208         offset += 4 - (offset % 4);
209     }
210     dcerpc_tvb_get_uuid (tvb, offset, drep, &uuid);
211     if (tree) {
212         /*
213          * XXX - look up the UUID to see if it's registered, and use
214          * the name of the protocol?  Unfortunately, we need the version
215          * as well.
216          */
217         uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, 
218                                 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
219                                 uuid.Data1, uuid.Data2, uuid.Data3,
220                                 uuid.Data4[0], uuid.Data4[1],
221                                 uuid.Data4[2], uuid.Data4[3],
222                                 uuid.Data4[4], uuid.Data4[5],
223                                 uuid.Data4[6], uuid.Data4[7]);
224         if (uuid_str_len >= DCERPC_UUID_STR_LEN)
225             memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
226         proto_tree_add_string_format (tree, hfindex, tvb, offset, 16, 
227                                       uuid_str, "%s: %s",
228                                       proto_registrar_get_name(hfindex),
229                                       uuid_str);
230     }
231     if (pdata) {
232         *pdata = uuid;
233     }
234     return offset + 16;
235 }
236
237 /*
238  * XXX - at least according to the DCE RPC 1.1 "nbase.idl", an
239  * "ndr_context_handle" is an unsigned32 "context_handle_attributes"
240  * and a uuid_t "context_handle_uuid".  The attributes do not appear to
241  * be used, and always appear to be set to 0, in the DCE RPC 1.1 code.
242  *
243  * Should we display an "ndr_context_handle" with a tree holding the
244  * attributes and the uuid_t?
245  */
246 int
247 dissect_ndr_ctx_hnd (tvbuff_t *tvb, gint offset, packet_info *pinfo,
248                      proto_tree *tree, char *drep,
249                      int hfindex, e_ctx_hnd *pdata)
250 {
251     static e_ctx_hnd ctx_hnd;
252     dcerpc_info *di;
253
254     di=pinfo->private_data;
255     if(di->conformant_run){
256       /* just a run to handle conformant arrays, no scalars to dissect */
257       return offset;
258     }
259
260     if (offset % 4) {
261         offset += 4 - (offset % 4);
262     }
263     ctx_hnd.attributes = dcerpc_tvb_get_ntohl (tvb, offset, drep);
264     dcerpc_tvb_get_uuid (tvb, offset+4, drep, &ctx_hnd.uuid);
265     if (tree) {
266         /* Bytes is bytes - don't worry about the data representation */
267         proto_tree_add_item (tree, hfindex, tvb, offset, 20, FALSE);
268     }
269     if (pdata) {
270         *pdata = ctx_hnd;
271     }
272     return offset + 20;
273 }