Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-aruba-papi.c
1 /* packet-aruba-papi.c
2  * Routines for Aruba PAPI dissection
3  * Copyright 2010, Alexis La Goutte <alexis.lagoutte at gmail dot com>
4  *
5  * Real name of PAPI : Protocol Application Program Interface
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #if 0
32 /* Include only as needed */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #endif
37
38 #include <glib.h>
39
40 #include <epan/packet.h>
41 #include <epan/prefs.h>
42
43 /* This is not IANA assigned nor registered */
44 #define UDP_PORT_PAPI 8211
45
46
47 /* Initialize the protocol and registered fields */
48 static int proto_papi = -1;
49 static int hf_papi_hdr_id = -1;
50 static int hf_papi_hdr_version = -1;
51 static int hf_papi_hdr_ip_destination = -1;
52 static int hf_papi_hdr_ip_source = -1;
53 static int hf_papi_hdr_port_destination = -1;
54 static int hf_papi_hdr_port_source = -1;
55 static int hf_papi_hdr_unknown = -1;
56 static int hf_papi_hdr_sequence = -1;
57 static int hf_papi_hdr_checksum = -1;
58
59 static int hf_papi_debug = -1;
60 static int hf_papi_debug_text = -1;
61 static int hf_papi_debug_text_length = -1;
62 static int hf_papi_debug_48bits = -1;
63 static int hf_papi_debug_8bits = -1;
64 static int hf_papi_debug_16bits = -1;
65 static int hf_papi_debug_32bits = -1;
66 static int hf_papi_debug_ipv4 = -1;
67 static int hf_papi_debug_64bits = -1;
68 static int hf_papi_debug_bytes = -1;
69 static int hf_papi_debug_bytes_length = -1;
70
71 /* Global PAPI Debug Preference */
72 static gboolean g_papi_debug = FALSE;
73
74 static dissector_handle_t data_handle;
75
76 /* Initialize the subtree pointers */
77 static gint ett_papi = -1;
78
79 /* PAPI Debug loop ! */
80 static int
81 dissect_papi_debug(tvbuff_t *tvb, guint offset, proto_tree *tree)
82 {
83         proto_item *ti;
84         proto_tree *debug_tree, *debug_sub_tree;
85
86
87         ti = proto_tree_add_item(tree, hf_papi_debug, tvb, offset, -1, ENC_NA);
88         debug_tree = proto_item_add_subtree(ti, ett_papi);
89
90         while(offset < tvb_reported_length(tvb)) {
91                 switch(tvb_get_guint8(tvb,offset)) {
92                 case 0x00:
93                     ti = proto_tree_add_item(debug_tree, hf_papi_debug_text, tvb, offset+3, tvb_get_ntohs(tvb,offset+1), FALSE);
94                     debug_sub_tree = proto_item_add_subtree(ti, ett_papi);
95                     proto_tree_add_item(debug_sub_tree, hf_papi_debug_text_length, tvb, offset+1, 2, FALSE);
96                     offset += tvb_get_ntohs(tvb, offset+1) + 3;
97                 break;
98                 case 0x01:
99                     proto_tree_add_item(debug_tree, hf_papi_debug_48bits, tvb, offset+1, 6, FALSE);
100                     offset += 7;
101                 break;
102                 case 0x02:
103                     proto_tree_add_item(debug_tree, hf_papi_debug_8bits, tvb, offset+1, 1, FALSE);
104                     offset += 2;
105                 break;
106                 case 0x03:
107                     proto_tree_add_item(debug_tree, hf_papi_debug_16bits, tvb, offset+1, 2, FALSE);
108                     offset += 3;
109                 break;
110                 case 0x04:
111                     proto_tree_add_item(debug_tree, hf_papi_debug_32bits, tvb, offset+1, 4, FALSE);
112                     offset += 5;
113                 break;
114                 case 0x05:
115                     proto_tree_add_item(debug_tree, hf_papi_debug_ipv4, tvb, offset+1, 4, FALSE);
116                     offset += 5;
117                 break;
118                 case 0x07:
119                     proto_tree_add_item(debug_tree, hf_papi_debug_16bits, tvb, offset+1, 2, FALSE);
120                     offset += 3;
121                 break;
122                 case 0x08:
123                     ti = proto_tree_add_item(debug_tree, hf_papi_debug_bytes, tvb, offset+3, tvb_get_ntohs(tvb,offset+1), ENC_NA);
124                     debug_sub_tree = proto_item_add_subtree(ti, ett_papi);
125                     proto_tree_add_item(debug_sub_tree, hf_papi_debug_bytes_length, tvb, offset+1, 2, FALSE);
126                     offset += tvb_get_ntohs(tvb,offset+1) + 3;
127                 break;
128                 case 0x09:
129                     proto_tree_add_item(debug_tree, hf_papi_debug_64bits, tvb, offset+1, 8, FALSE);
130                     offset += 9;
131                 break;
132                 default:
133                     proto_tree_add_text(debug_tree, tvb, offset, 1, "Unknown (%d)", tvb_get_guint8(tvb, offset));
134                     offset +=1;
135                }
136         }
137
138         return offset;
139 }
140
141 static gboolean
142 dissect_papi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
143 {
144         proto_item *ti;
145         proto_tree *papi_tree;
146         guint     offset = 0;
147         tvbuff_t *next_tvb;
148
149
150         /* All PAPI packet start with 0x4972 !  */
151         if ( tvb_get_ntohs(tvb, offset) != 0x4972 )
152                 return FALSE;
153
154         col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAPI");
155         col_set_str(pinfo->cinfo, COL_INFO, "PAPI - Aruba AP Control Protocol");
156
157         if (tree) {
158
159                 ti = proto_tree_add_item(tree, proto_papi, tvb, 0, -1, FALSE);
160
161                 papi_tree = proto_item_add_subtree(ti, ett_papi);
162
163                 proto_tree_add_item(papi_tree, hf_papi_hdr_id, tvb, offset, 2, FALSE);
164                 offset += 2;
165
166                 proto_tree_add_item(papi_tree, hf_papi_hdr_version, tvb, offset, 2, FALSE);
167                 offset += 2;
168
169                 proto_tree_add_item(papi_tree, hf_papi_hdr_ip_destination, tvb, offset, 4, FALSE);
170                 offset += 4;
171
172                 proto_tree_add_item(papi_tree, hf_papi_hdr_ip_source, tvb, offset, 4, FALSE);
173                 offset += 4;
174
175                 proto_tree_add_item(papi_tree, hf_papi_hdr_unknown, tvb, offset, 2, FALSE);
176                 offset += 2;
177
178                 proto_tree_add_item(papi_tree, hf_papi_hdr_unknown, tvb, offset, 2, FALSE);
179                 offset += 2;
180
181                 proto_tree_add_item(papi_tree, hf_papi_hdr_port_source, tvb, offset, 2, FALSE);
182                 offset += 2;
183
184                 proto_tree_add_item(papi_tree, hf_papi_hdr_port_destination, tvb, offset, 2, FALSE);
185                 offset += 2;
186
187                 proto_tree_add_item(papi_tree, hf_papi_hdr_unknown, tvb, offset, 2, FALSE);
188                 offset += 2;
189
190                 proto_tree_add_item(papi_tree, hf_papi_hdr_unknown, tvb, offset, 2, FALSE);
191                 offset += 2;
192
193                 proto_tree_add_item(papi_tree, hf_papi_hdr_sequence, tvb, offset, 2, FALSE);
194                 offset += 2;
195
196                 proto_tree_add_item(papi_tree, hf_papi_hdr_unknown, tvb, offset, 2, FALSE);
197                 offset += 2;
198
199                 proto_tree_add_item(papi_tree, hf_papi_hdr_checksum, tvb, offset, 16, ENC_NA);
200                 offset += 16;
201
202                 if(g_papi_debug)
203                 {
204                         offset = dissect_papi_debug(tvb, offset, papi_tree);
205                 }
206
207                 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
208                 call_dissector(data_handle,next_tvb, pinfo, tree);
209         }
210
211         return(TRUE);
212 }
213
214 void
215 proto_register_papi(void)
216 {
217         module_t *papi_module;
218
219         static hf_register_info hf[] = {
220                 { &hf_papi_hdr_id,
221                         { "ID",           "papi.hdr.id",
222                         FT_UINT16, BASE_HEX, NULL, 0x0,
223                         "PAPI Header ID (Magic Number ?)", HFILL }
224                 },
225                 { &hf_papi_hdr_version,
226                         { "Version",           "papi.hdr.version",
227                         FT_UINT16, BASE_DEC, NULL, 0x0,
228                         "PAPI Protocol Version", HFILL }
229                 },
230                 { &hf_papi_hdr_ip_destination,
231                         { "IP Destination",           "papi.hdr.ip.dst",
232                         FT_IPv4, BASE_NONE, NULL, 0x0,
233                         NULL, HFILL }
234                 },
235                 { &hf_papi_hdr_ip_source,
236                         { "IP Source",           "papi.hdr.ip.src",
237                         FT_IPv4, BASE_NONE, NULL, 0x0,
238                         NULL, HFILL }
239                 },
240                 { &hf_papi_hdr_port_source,
241                         { "Port Source",           "papi.hdr.port.src",
242                         FT_UINT16, BASE_DEC, NULL, 0x0,
243                         NULL, HFILL }
244                 },
245                 { &hf_papi_hdr_port_destination,
246                         { "Port Destination",       "papi.hdr.port.destination",
247                         FT_UINT16, BASE_DEC, NULL, 0x0,
248                         NULL, HFILL }
249                 },
250                 { &hf_papi_hdr_unknown,
251                         { "Unknown",       "papi.hdr.unknown",
252                         FT_UINT16, BASE_DEC|BASE_HEX, NULL, 0x0,
253                         NULL, HFILL }
254                 },
255                 { &hf_papi_hdr_sequence,
256                         { "Sequence",       "papi.hdr.sequence",
257                         FT_UINT16, BASE_DEC, NULL, 0x0,
258                         NULL, HFILL }
259                 },
260                 { &hf_papi_hdr_checksum,
261                         { "Checksum",       "papi.hdr.checksum",
262                         FT_BYTES, BASE_NONE, NULL, 0x0,
263                         NULL, HFILL }
264                 },
265
266                 { &hf_papi_debug,
267                         { "Debug",       "papi.debug",
268                         FT_NONE, BASE_NONE, NULL, 0x0,
269                         NULL, HFILL }
270                 },
271                 { &hf_papi_debug_text,
272                         { "Debug (Text)",       "papi.debug.text",
273                         FT_STRING, BASE_NONE, NULL, 0x0,
274                         NULL, HFILL }
275                 },
276                 { &hf_papi_debug_text_length,
277                         { "Debug Text Length",       "papi.debug.text_length",
278                         FT_UINT16, BASE_DEC, NULL, 0x0,
279                         NULL, HFILL }
280                 },
281                 { &hf_papi_debug_bytes,
282                         { "Debug (Bytes)",       "papi.debug.bytes",
283                         FT_BYTES, BASE_NONE, NULL, 0x0,
284                         NULL, HFILL }
285                 },
286                 { &hf_papi_debug_bytes_length,
287                         { "Debug Bytes Length",       "papi.debug.bytes_length",
288                         FT_UINT16, BASE_DEC, NULL, 0x0,
289                         NULL, HFILL }
290                 },
291                 { &hf_papi_debug_48bits,
292                         { "Debug (48 Bits)",       "papi.debug.48bits",
293                         FT_UINT64, BASE_DEC, NULL, 0x0,
294                         NULL, HFILL }
295                 },
296                 { &hf_papi_debug_8bits,
297                         { "Debug (8 Bits)",       "papi.debug.8bits",
298                         FT_UINT8, BASE_DEC, NULL, 0x0,
299                         NULL, HFILL }
300                 },
301                 { &hf_papi_debug_16bits,
302                         { "Debug (16 Bits)",       "papi.debug.16bits",
303                         FT_UINT16, BASE_DEC, NULL, 0x0,
304                         NULL, HFILL }
305                 },
306                 { &hf_papi_debug_32bits,
307                         { "Debug (32 Bits)",       "papi.debug.32bits",
308                         FT_UINT32, BASE_DEC, NULL, 0x0,
309                         NULL, HFILL }
310                 },
311                 { &hf_papi_debug_ipv4,
312                         { "Debug (IPv4)",       "papi.debug.ipv4",
313                         FT_IPv4, BASE_NONE, NULL, 0x0,
314                         NULL, HFILL }
315                 },
316                 { &hf_papi_debug_64bits,
317                         { "Debug (64 Bits)",       "papi.debug.64bits",
318                         FT_UINT64, BASE_DEC, NULL, 0x0,
319                         NULL, HFILL }
320                 },
321         };
322
323         /* Setup protocol subtree array */
324         static gint *ett[] = {
325                 &ett_papi
326         };
327
328         proto_papi = proto_register_protocol("Aruba PAPI", "PAPI", "papi");
329
330         proto_register_field_array(proto_papi, hf, array_length(hf));
331         proto_register_subtree_array(ett, array_length(ett));
332
333         papi_module = prefs_register_protocol(proto_papi, NULL);
334
335         prefs_register_bool_preference(papi_module, "experimental_decode",
336                                        "Do experimental decode",
337                                        "Attempt to decode parts of the message that aren't fully understood yet",
338                                        &g_papi_debug);
339 }
340
341
342 void
343 proto_reg_handoff_papi(void)
344 {
345         dissector_handle_t papi_handle;
346
347         papi_handle = new_create_dissector_handle(dissect_papi, proto_papi);
348         dissector_add_uint("udp.port", UDP_PORT_PAPI, papi_handle);
349         data_handle = find_dissector("data");
350 }