Add support for Exif decoding (initial framework).
[obnox/wireshark/wip.git] / packet-stat.c
1 /* packet-stat.c
2  * Routines for stat dissection
3  *
4  * $Id: packet-stat.c,v 1.19 2002/11/01 00:48:39 sahlberg Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * Copied from packet-smb.c
11  *
12  * 2001  Ronnie Sahlberg <See AUTHORS for email>
13  *     Added the dissectors for STAT protocol
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34
35 #include "packet-rpc.h"
36 #include "packet-stat.h"
37
38 static int proto_stat = -1;
39 static int hf_stat_procedure_v1 = -1;
40 static int hf_stat_mon_name = -1;
41 static int hf_stat_stat_res = -1;
42 static int hf_stat_stat_res_res = -1;
43 static int hf_stat_stat_res_state = -1;
44 static int hf_stat_state = -1;
45 static int hf_stat_mon = -1;
46 static int hf_stat_mon_id_name = -1;
47 static int hf_stat_my_id = -1;
48 static int hf_stat_my_id_hostname = -1;
49 static int hf_stat_my_id_prog = -1;
50 static int hf_stat_my_id_vers = -1;
51 static int hf_stat_my_id_proc = -1;
52 static int hf_stat_priv = -1;
53 static int hf_stat_stat_chge = -1;
54
55 static gint ett_stat = -1;
56 static gint ett_stat_stat_res = -1;
57 static gint ett_stat_mon = -1;
58 static gint ett_stat_my_id = -1;
59 static gint ett_stat_stat_chge = -1;
60
61 #define STAT_SUCC       0
62 #define STAT_FAIL       1
63
64 static const value_string stat_res[] =
65 {
66         {       0,      "STAT_SUCC" },
67         {       1,      "STAT_FAIL" },
68         {       0,      NULL }
69 };
70
71 /* Calculate length (including padding) of my_id structure.
72  * First read the length of the string and round it upwards to nearest
73  * multiple of 4, then add 16 (4*uint32)
74  */
75 static int
76 my_id_len(tvbuff_t *tvb, int offset)
77 {
78         int len;
79
80         len = tvb_get_ntohl(tvb, offset);
81         if(len&0x03)
82                 len = (len&0xfc)+4;
83
84         len += 16;
85
86         return len;
87 }
88
89 /* Calculate length (including padding) of my_id structure.
90  * First read the length of the string and round it upwards to nearest
91  * multiple of 4, then add 4 (string len) and size of my_id struct.
92  */
93 static int
94 mon_id_len(tvbuff_t *tvb, int offset)
95 {
96         int len;
97
98         len = tvb_get_ntohl(tvb, offset);
99         if(len&0x03){
100                 len = (len&0xfc)+4;
101         }
102
103         len += 4;
104
105         return len+my_id_len(tvb,offset+len);
106 }
107
108 static int
109 dissect_stat_stat(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
110 {
111         if (tree)
112         {
113                 offset = dissect_rpc_string(tvb,tree,hf_stat_mon_name,offset,NULL);
114         }
115
116         return offset;
117 }
118
119 static int
120 dissect_stat_stat_res(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
121 {
122         proto_item* sub_item = NULL;
123         proto_tree* sub_tree = NULL;
124         gint32 res;
125         gint32 state;
126
127         if (tree) {
128                 sub_item = proto_tree_add_item(tree, hf_stat_stat_res, tvb,
129                                 offset, -1, FALSE);
130                 if (sub_item)
131                         sub_tree = proto_item_add_subtree(sub_item, ett_stat_stat_res);
132         }
133
134         res = tvb_get_ntohl(tvb, offset);
135         offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_stat_res_res,offset);
136
137         if (res==STAT_SUCC) {
138                 state = tvb_get_ntohl(tvb, offset);
139                 offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_stat_res_state,offset);
140         } else {
141                 offset += 4;
142         }
143
144         return offset;
145 }
146
147 static int
148 dissect_stat_my_id(tvbuff_t *tvb, int offset, proto_tree *tree)
149 {
150         proto_item* sub_item = NULL;
151         proto_tree* sub_tree = NULL;
152
153         if (tree) {
154                 sub_item = proto_tree_add_item(tree, hf_stat_my_id, tvb,
155                                 offset, my_id_len(tvb,offset), FALSE);
156                 if (sub_item)
157                         sub_tree = proto_item_add_subtree(sub_item, ett_stat_my_id);
158         }
159
160         offset = dissect_rpc_string(tvb,sub_tree,hf_stat_my_id_hostname,offset,NULL);
161         offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_my_id_prog,offset);
162         offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_my_id_vers,offset);
163         offset = dissect_rpc_uint32(tvb,sub_tree,hf_stat_my_id_proc,offset);
164
165         return offset;
166 }
167
168 static int
169 dissect_stat_mon_id(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
170 {
171         proto_item* sub_item = NULL;
172         proto_tree* sub_tree = NULL;
173
174         if (tree) {
175                 sub_item = proto_tree_add_item(tree, hf_stat_mon, tvb,
176                                 offset, mon_id_len(tvb,offset), FALSE);
177                 if (sub_item)
178                         sub_tree = proto_item_add_subtree(sub_item, ett_stat_mon);
179         }
180
181
182         offset = dissect_rpc_string(tvb,sub_tree,hf_stat_mon_id_name,offset,NULL);
183
184         offset = dissect_stat_my_id(tvb,offset,sub_tree);
185
186         return offset;
187 }
188
189 static int
190 dissect_stat_priv(tvbuff_t *tvb, int offset, proto_tree *tree)
191 {
192         proto_tree_add_item(tree, hf_stat_priv, tvb, offset, 16, FALSE);
193         offset += 16;
194
195         return offset;
196 }
197
198 static int
199 dissect_stat_mon(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
200 {
201
202         offset = dissect_stat_mon_id(tvb,offset,pinfo,tree);
203
204         offset = dissect_stat_priv(tvb,offset,tree);
205         return offset;
206 }
207
208 static int
209 dissect_stat_state(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
210 {
211         offset = dissect_rpc_uint32(tvb,tree,hf_stat_state,offset);
212
213         return offset;
214 }
215
216 static int
217 dissect_stat_notify(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
218 {
219         proto_item* sub_item = NULL;
220         proto_tree* sub_tree = NULL;
221         int start_offset = offset;
222
223         if (tree) {
224                 sub_item = proto_tree_add_item(tree, hf_stat_stat_chge, tvb,
225                                 offset, -1, FALSE);
226                 if (sub_item)
227                         sub_tree = proto_item_add_subtree(sub_item, ett_stat_stat_chge);
228         }
229
230         offset = dissect_rpc_string(tvb,sub_tree,hf_stat_mon_id_name,offset,NULL);
231
232         offset = dissect_rpc_uint32(tvb,tree,hf_stat_state,offset);
233
234         if(sub_item)
235                 proto_item_set_len(sub_item, offset - start_offset);
236
237         return offset;
238 }
239
240 static int
241 dissect_stat_umon_all(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree)
242 {
243         offset = dissect_stat_my_id(tvb,offset,tree);
244
245         return offset;
246 }
247
248 /* proc number, "proc name", dissect_request, dissect_reply */
249 /* NULL as function pointer means: type of arguments is "void". */
250
251 static const vsff stat1_proc[] = {
252     { 0, "NULL", NULL, NULL },
253     { STATPROC_STAT,   "STAT",
254                 dissect_stat_stat, dissect_stat_stat_res },
255     { STATPROC_MON,   "MON",
256                 dissect_stat_mon, dissect_stat_stat_res },
257     { STATPROC_UNMON, "UNMON",
258                 dissect_stat_mon_id, dissect_stat_state },
259     { STATPROC_UNMON_ALL, "UNMON_ALL",
260                 dissect_stat_umon_all, dissect_stat_state },
261     { STATPROC_SIMU_CRASH, "SIMU_CRASH",
262                 NULL, NULL },
263     { STATPROC_NOTIFY, "NOTIFY",
264                 dissect_stat_notify, NULL },
265     { 0, NULL, NULL, NULL }
266 };
267 static const value_string stat1_proc_vals[] = {
268     { 0, "NULL" },
269     { STATPROC_STAT,   "STAT" },
270     { STATPROC_MON,   "MON" },
271     { STATPROC_UNMON, "UNMON" },
272     { STATPROC_UNMON_ALL, "UNMON_ALL" },
273     { STATPROC_SIMU_CRASH, "SIMU_CRASH" },
274     { STATPROC_NOTIFY, "NOTIFY" },
275     { 0, NULL }
276 };
277 /* end of stat version 1 */
278
279
280 void
281 proto_register_stat(void)
282 {
283         static hf_register_info hf[] = {
284                 { &hf_stat_procedure_v1, {
285                         "V1 Procedure", "stat.procedure_v1", FT_UINT32, BASE_DEC,
286                         VALS(stat1_proc_vals), 0, "V1 Procedure", HFILL }},
287                 { &hf_stat_mon_name, {
288                         "Name", "stat.name", FT_STRING, BASE_DEC,
289                         NULL, 0, "Name", HFILL }},
290                 { &hf_stat_stat_res, {
291                         "Status Result", "stat.stat_res", FT_NONE,0,
292                         NULL, 0, "Status Result", HFILL }},
293                 { &hf_stat_stat_res_res, {
294                         "Result", "stat.stat_res.res", FT_UINT32, BASE_DEC,
295                         VALS(stat_res), 0, "Result", HFILL }},
296                 { &hf_stat_stat_res_state, {
297                         "State", "stat.stat_res.state", FT_UINT32, BASE_DEC,
298                         NULL, 0, "State", HFILL }},
299                 { &hf_stat_mon, {
300                         "Monitor", "stat.mon", FT_NONE, 0,
301                         NULL, 0, "Monitor Host", HFILL }},
302                 { &hf_stat_mon_id_name, {
303                         "Monitor ID Name", "stat.mon_id.name", FT_STRING, BASE_DEC,
304                         NULL, 0, "Monitor ID Name", HFILL }},
305                 { &hf_stat_my_id, {
306                         "My ID", "stat.my_id", FT_NONE,0,
307                         NULL, 0, "My_ID structure", HFILL }},
308                 { &hf_stat_my_id_hostname, {
309                         "Hostname", "stat.my_id.hostname", FT_STRING, BASE_DEC,
310                         NULL, 0, "My_ID Host to callback", HFILL }},
311                 { &hf_stat_my_id_prog, {
312                         "Program", "stat.my_id.prog", FT_UINT32, BASE_DEC,
313                         NULL, 0, "My_ID Program to callback", HFILL }},
314                 { &hf_stat_my_id_vers, {
315                         "Version", "stat.my_id.vers", FT_UINT32, BASE_DEC,
316                         NULL, 0, "My_ID Version of callback", HFILL }},
317                 { &hf_stat_my_id_proc, {
318                         "Procedure", "stat.my_id.proc", FT_UINT32, BASE_DEC,
319                         NULL, 0, "My_ID Procedure to callback", HFILL }},
320                 { &hf_stat_priv, {
321                         "Priv", "stat.priv", FT_BYTES, BASE_HEX,
322                         NULL, 0, "Private client supplied opaque data", HFILL }},
323                 { &hf_stat_state, {
324                         "State", "stat.state", FT_UINT32, BASE_DEC,
325                         NULL, 0, "State of local NSM", HFILL }},
326                 { &hf_stat_stat_chge, {
327                         "Status Change", "stat.stat_chge", FT_NONE, 0,
328                         NULL, 0, "Status Change structure", HFILL }},
329         };
330
331         static gint *ett[] = {
332                 &ett_stat,
333                 &ett_stat_stat_res,
334                 &ett_stat_mon,
335                 &ett_stat_my_id,
336                 &ett_stat_stat_chge,
337         };
338
339         proto_stat = proto_register_protocol("Network Status Monitor Protocol", "STAT", "stat");
340         proto_register_field_array(proto_stat, hf, array_length(hf));
341         proto_register_subtree_array(ett, array_length(ett));
342 }
343
344 void
345 proto_reg_handoff_stat(void)
346 {
347         /* Register the protocol as RPC */
348         rpc_init_prog(proto_stat, STAT_PROGRAM, ett_stat);
349         /* Register the procedure tables */
350         rpc_init_proc_table(STAT_PROGRAM, 1, stat1_proc, hf_stat_procedure_v1);
351 }