Don't do fcn calls in arg of g_?to??(); Macro may very well eval args multiple times.
[obnox/wireshark/wip.git] / epan / dissectors / packet-dcom-oxid.c
1 /* packet-dcom-oxid.c
2  * Routines for DCOM OXID Resolver
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 /* see packet-dcom.c for details about DCOM */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include "packet-dcerpc.h"
35 #include "packet-dcom.h"
36
37 static int proto_oxid = -1;
38
39 static int hf_oxid_opnum = -1;
40 static int hf_oxid_setid = -1;
41 static int hf_oxid_seqnum = -1;
42 static int hf_oxid_addtoset = -1;
43 static int hf_oxid_delfromset = -1;
44 static int hf_oxid_oid = -1;
45 static int hf_oxid_ping_backoff_factor = -1;
46 static int hf_oxid_oxid = -1;
47 static int hf_oxid_requested_protseqs = -1;
48 static int hf_oxid_protseqs = -1;
49 static int hf_oxid_bindings = -1;
50 static int hf_oxid_ipid = -1;
51 static int hf_oxid_authn_hint = -1;
52
53 static int hf_oxid_Unknown1 = -1;
54 static int hf_oxid_Unknown2 = -1;
55 static int hf_oxid_ds_array = -1;
56
57
58 static gint ett_oxid = -1;
59
60 static e_uuid_t uuid_oxid = { 0x99fcfec4, 0x5260, 0x101b, { 0xbb, 0xcb, 0x00, 0xaa, 0x00, 0x21, 0x34, 0x7a } };
61 static guint16  ver_oxid = 0;
62
63
64 static int
65 dissect_oxid_simple_ping_rqst(tvbuff_t *tvb, int offset,
66         packet_info *pinfo, proto_tree *tree, guint8 *drep)
67 {
68         offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep,
69                                                 hf_oxid_setid, NULL);
70
71         return offset;
72 }
73
74
75 static int
76 dissect_oxid_simple_ping_resp(tvbuff_t *tvb, int offset,
77         packet_info *pinfo, proto_tree *tree, guint8 *drep)
78 {
79         guint32 u32HResult;
80
81
82         offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
83                                                 &u32HResult);
84
85     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
86           val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
87
88         return offset;
89 }
90
91
92 static int
93 dissect_oxid_server_alive_resp(tvbuff_t *tvb, int offset,
94         packet_info *pinfo, proto_tree *tree, guint8 *drep)
95 {
96         guint32 u32HResult;
97
98
99         offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
100                                                 &u32HResult);
101
102     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
103           val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
104
105         return offset;
106 }
107
108
109 static int
110 dissect_oxid_complex_ping_rqst(tvbuff_t *tvb, int offset,
111         packet_info *pinfo, proto_tree *tree, guint8 *drep)
112 {
113         guint16 u16SeqNum;
114         guint16 u16AddToSet;
115         guint16 u16DelFromSet;
116         guint32 u32Pointer;
117         guint32 u32ArraySize;
118
119         offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep,
120                                                 hf_oxid_setid, NULL);
121
122         offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
123                                                 hf_oxid_seqnum, &u16SeqNum);
124         offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
125                                                 hf_oxid_addtoset, &u16AddToSet);
126         offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
127                                                 hf_oxid_delfromset, &u16DelFromSet);
128
129         col_append_fstr(pinfo->cinfo, COL_INFO, " AddToSet=%u DelFromSet=%u",
130                         u16AddToSet, u16DelFromSet);
131
132         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep,
133                                                 &u32Pointer);
134         if (u32Pointer) {
135                 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
136                                                         &u32ArraySize);
137
138                 while (u16AddToSet--) {
139                         offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep,
140                                                         hf_oxid_oid, NULL);
141                 }
142         }
143
144         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep,
145                                                 &u32Pointer);
146     if (u32Pointer) {
147                 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
148                                                         &u32ArraySize);
149
150                 while (u16DelFromSet--) {
151                         offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep,
152                                                         hf_oxid_oid, NULL);
153                 }
154         }
155
156         return offset;
157 }
158
159
160 static int
161 dissect_oxid_complex_ping_resp(tvbuff_t *tvb, int offset,
162         packet_info *pinfo, proto_tree *tree, guint8 *drep)
163 {
164         guint16 u16PingBackoffFactor;
165         guint32 u32HResult;
166
167
168         offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep,
169                                                 hf_oxid_setid, NULL);
170         offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
171                                                 hf_oxid_ping_backoff_factor, &u16PingBackoffFactor);
172
173         offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
174                                                 &u32HResult);
175
176     col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
177           val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
178
179         return offset;
180 }
181
182
183 static int
184 dissect_oxid_resolve_oxid2_rqst(tvbuff_t *tvb, int offset,
185         packet_info *pinfo, proto_tree *tree, guint8 *drep)
186 {
187         guint16 u16ProtSeqs;
188         guint32 u32ArraySize;
189         guint32 u32ItemIdx;
190
191
192         offset = dissect_dcom_ID(tvb, offset, pinfo, tree, drep,
193                                                 hf_oxid_oxid, NULL);
194
195         offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
196                         hf_oxid_requested_protseqs, &u16ProtSeqs);
197
198         offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
199                                                 &u32ArraySize);
200
201         u32ItemIdx = 1;
202         while (u32ArraySize--) {
203                 offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, drep,
204                                                         hf_oxid_protseqs, &u16ProtSeqs);
205                 u32ItemIdx++;
206         }
207
208         return offset;
209 }
210
211
212 static int
213 dissect_oxid_resolve_oxid2_resp(tvbuff_t *tvb, int offset,
214         packet_info *pinfo, proto_tree *tree, guint8 *drep)
215 {
216         guint32 u32Pointer;
217         guint32 u32ArraySize;
218         e_uuid_t ipid;
219         guint32 u32AuthnHint;
220         guint16 u16VersionMajor;
221         guint16 u16VersionMinor;
222         guint32 u32HResult;
223
224
225         offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, drep,
226                                                 &u32Pointer);
227         if (u32Pointer) {
228                 offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, drep,
229                                                         &u32ArraySize);
230
231                 offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, drep,
232                                                         hf_oxid_bindings, NULL);
233
234                 offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, drep,
235                                                         hf_oxid_ipid, &ipid);
236
237                 offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, drep,
238                                                         hf_oxid_authn_hint, &u32AuthnHint);
239
240                 offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, tree, drep,
241                                         &u16VersionMajor, &u16VersionMinor);
242         }
243
244         offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, drep,
245                                                 &u32HResult);
246
247      col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
248                 val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
249
250         return offset;
251 }
252
253
254 static int
255 dissect_oxid_server_alive2_resp(tvbuff_t *tvb, int offset, packet_info *pinfo,
256                                 proto_tree *tree, guint8 *drep) {
257     guint16     u16VersionMajor;
258     guint16 u16VersionMinor;
259
260     offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, tree, drep, &u16VersionMajor, &u16VersionMinor);
261
262     /* XXX - understand what those 8 bytes mean! don't skip'em!*/
263     dissect_dcerpc_uint64(tvb , offset, pinfo, tree, drep, hf_oxid_Unknown1, NULL);
264     offset += 8;
265
266     offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, drep, hf_oxid_ds_array, NULL);
267
268     /* unknown field 2 */
269     dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, hf_oxid_Unknown2, NULL);
270     offset += 8;
271     return offset;
272 }
273
274
275 /* XXX - some dissectors still need to be done */
276 static dcerpc_sub_dissector oxid_dissectors[] = {
277     { 0, "ResolveOxid", NULL, NULL },
278     { 1, "SimplePing", dissect_oxid_simple_ping_rqst, dissect_oxid_simple_ping_resp },
279     { 2, "ComplexPing", dissect_oxid_complex_ping_rqst, dissect_oxid_complex_ping_resp },
280     { 3, "ServerAlive", NULL /* no input parameters */, dissect_oxid_server_alive_resp },
281     { 4, "ResolveOxid2", dissect_oxid_resolve_oxid2_rqst, dissect_oxid_resolve_oxid2_resp },
282     { 5, "ServerAlive2", NULL, dissect_oxid_server_alive2_resp },
283     { 0, NULL, NULL, NULL },
284 };
285
286
287 void
288 proto_register_oxid (void)
289 {
290         static hf_register_info hf[] = {
291                 { &hf_oxid_opnum,
292                   { "Operation", "oxid.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
293
294                 { &hf_oxid_setid,
295                   { "SetId", "oxid.setid",  FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
296                 { &hf_oxid_seqnum,
297                   { "SeqNum", "oxid.seqnum",  FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
298                 { &hf_oxid_addtoset,
299                   { "AddToSet", "oxid.addtoset",  FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
300                 { &hf_oxid_delfromset,
301                   { "DelFromSet", "oxid.delfromset",  FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
302                 { &hf_oxid_oid,
303                   { "OID", "oxid.oid",  FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
304                 { &hf_oxid_ping_backoff_factor,
305                   { "PingBackoffFactor", "oxid.ping_backoff_factor", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
306                 { &hf_oxid_oxid,
307                   { "OXID", "oxid.oxid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
308
309                 { &hf_oxid_requested_protseqs,
310                   { "RequestedProtSeq", "oxid.requested_protseqs",  FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
311                 { &hf_oxid_protseqs,
312                   { "ProtSeq", "oxid.protseqs",  FT_UINT16, BASE_DEC, VALS(dcom_protseq_vals), 0x0, NULL, HFILL }},
313
314                 { &hf_oxid_bindings,
315                   { "OxidBindings", "oxid.bindings", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
316                 { &hf_oxid_ipid,
317                   { "IPID", "oxid.ipid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
318                 { &hf_oxid_authn_hint,
319                   { "AuthnHint", "oxid.authn_hint", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
320
321                 { &hf_oxid_ds_array,
322                   { "Address", "dcom.oxid.address", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
323                 { &hf_oxid_Unknown1,
324                   { "unknown 8 bytes 1", "oxid.unknown1", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }},
325                 { &hf_oxid_Unknown2,
326                   { "unknown 8 bytes 2", "oxid.unknown2", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}
327         };
328         static gint *ett[] = {
329                 &ett_oxid
330         };
331         proto_oxid = proto_register_protocol ("DCOM OXID Resolver", "IOXIDResolver", "oxid");
332         proto_register_field_array (proto_oxid, hf, array_length (hf));
333         proto_register_subtree_array (ett, array_length (ett));
334 }
335
336 void
337 proto_reg_handoff_oxid (void)
338 {
339         /* Register the protocol as dcerpc */
340         dcerpc_init_uuid (proto_oxid, ett_oxid, &uuid_oxid, ver_oxid, oxid_dissectors, hf_oxid_opnum);
341 }