From Kovarththanan Rajaratnam via bug 3548:
[obnox/wireshark/wip.git] / epan / dissectors / packet-netdump.c
1 /* packet-netdump.c
2  * Routines for Netdump dissection
3  * Copyright 2009, Neil Horman <nhorman@tuxdriver.com> 
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
24  * USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <glib.h>
36
37 #include <epan/packet.h>
38 #include <epan/prefs.h>
39
40 /* forward reference */
41 void proto_reg_handoff_netdump(void);
42
43 /* Initialize the protocol and registered fields */
44 static int proto_netdump = -1;
45 static int hf_netdump_magic_number = -1;
46 static int hf_netdump_seq_nr = -1;
47 static int hf_netdump_command = -1;
48 static int hf_netdump_from = -1;
49 static int hf_netdump_to = -1;
50 static int hf_netdump_payload = -1;
51 static int hf_netdump_code = -1;
52 static int hf_netdump_info = -1;
53 static int hf_netdump_version = -1;
54
55 /* Global sample port pref */
56 static guint gPORT_PREF = 0;
57
58 /* Initialize the subtree pointers */
59 static gint ett_netdump = -1;
60
61 static const value_string command_names[] = {
62         { 0, "COMM_NONE" },
63         { 1, "COMM_SEND_MEM" },
64         { 2, "COMM_EXIT" },
65         { 3, "COMM_REBOOT" },
66         { 4, "COMM_HELLO" },
67         { 5, "COMM_GET_NR_PAGES" },
68         { 6, "COMM_GET_PAGE_SIZE" },
69         { 7, "COMM_START_NETDUMP_ACK" },
70         { 8, "COMM_GET_REGS" },
71         { 9, "COMM_SHOW_STATE" },
72         { 0, NULL }
73 };
74
75 static const value_string reply_code_names[] = {
76         { 0, "REPLY_NONE" },
77         { 1, "REPLY_ERROR" },
78         { 2, "REPLY_LOG" },
79         { 3, "REPLY_MEM" },
80         { 4, "REPLY_RESERVED" },
81         { 5, "REPLY_HELLO" },
82         { 6, "REPLY_NR_PAGES" },
83         { 7, "REPLY_PAGE_SIZE" },
84         { 8, "REPLY_START_NETDUMP" },
85         { 9, "REPLY_END_NETDUMP" },
86         { 10, "REPLY_REGS" },
87         { 11, "REPLY_MAGIC" },
88         { 12, "REPLY_SHOW_STATE" },
89         { 0, NULL }
90 };
91
92
93 /* Code to actually dissect the packets */
94 static void
95 dissect_netdump(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
96 {
97
98         /* Check that there's enough data */
99         if (tvb_reported_length(tvb) == 0)
100                 return;
101
102         if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
103                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Netdump");
104         }
105         /* Clear out stuff in the info column */
106         if (check_col(pinfo->cinfo,COL_INFO)) {
107                 col_clear(pinfo->cinfo,COL_INFO);
108         }
109
110         if (tree) { /* we are being asked for details */
111                 proto_item *ti = NULL;
112                 proto_tree *netdump_tree = NULL;
113                 ti = proto_tree_add_item(tree, proto_netdump, tvb, 0, -1, FALSE);
114                 netdump_tree = proto_item_add_subtree(ti, ett_netdump);
115                 if (tvb_reported_length(tvb) == 24) {
116                         /* Its a request format packet */
117                         proto_tree_add_item(netdump_tree, hf_netdump_magic_number, tvb, 0, 8, FALSE);
118                         proto_tree_add_item(netdump_tree, hf_netdump_seq_nr, tvb, 8, 4, FALSE);
119                         proto_tree_add_item(netdump_tree, hf_netdump_command, tvb, 12, 4, FALSE);
120                         proto_tree_add_item(netdump_tree, hf_netdump_from, tvb, 16, 4, FALSE);
121                         proto_tree_add_item(netdump_tree, hf_netdump_to, tvb, 20, 4, FALSE);
122                 } else {
123                         /* Its a reply packet */
124                         proto_tree_add_item(netdump_tree, hf_netdump_version, tvb, 0, 1, FALSE);
125                         proto_tree_add_item(netdump_tree, hf_netdump_seq_nr, tvb, 1, 4, FALSE);
126                         proto_tree_add_item(netdump_tree, hf_netdump_code, tvb, 5, 4, FALSE);
127                         proto_tree_add_item(netdump_tree, hf_netdump_info, tvb, 9, 4, TRUE);
128                         proto_tree_add_item(netdump_tree, hf_netdump_payload, tvb, 13, -1, FALSE);
129                 }
130         }
131 }
132
133 void proto_register_netdump(void)
134 {
135         module_t *netdump_module;
136
137         /* Setup protocol subtree array */
138         static gint *ett[] = {
139                 &ett_netdump
140         };
141
142         static hf_register_info hf[] = {
143                 { &hf_netdump_magic_number,
144                         { "Netdump Magic Number", "netdump.magic",
145                         FT_UINT64, BASE_HEX,
146                         NULL, 0x0,
147                         NULL, HFILL }
148                 },
149                 { &hf_netdump_seq_nr,
150                         {"Netdump seq number", "netdump.seq_nr",
151                         FT_UINT32, BASE_HEX,
152                         NULL, 0x0,
153                         NULL, HFILL}
154                 },
155                 { &hf_netdump_command,
156                         {"Netdump command", "netdump.command",
157                         FT_UINT32, BASE_DEC,
158                         VALS(command_names), 0x0,
159                         NULL, HFILL}
160                 },
161                 { &hf_netdump_from,
162                         {"Netdump from val", "netdump.from",
163                         FT_UINT32, BASE_HEX,
164                         NULL, 0x0,
165                         NULL, HFILL}
166                 },
167                 { &hf_netdump_to,
168                         {"Netdump to val", "netdump.to",
169                         FT_UINT32, BASE_HEX,
170                         NULL, 0x0,
171                         NULL, HFILL}
172                 },
173                 { &hf_netdump_code,
174                         {"Netdump code", "netdump.code",
175                         FT_UINT32, BASE_DEC,
176                         VALS(reply_code_names), 0x0,
177                         NULL, HFILL}
178                 },
179                 { &hf_netdump_info,
180                         {"Netdump info", "netdump.info",
181                         FT_UINT32, BASE_HEX,
182                         NULL, 0x0,
183                         NULL, HFILL}
184                 },
185                 { &hf_netdump_payload,
186                         {"Netdump payload", "netdump.payload",
187                         FT_BYTES, BASE_NONE,
188                         NULL, 0x0,
189                         NULL, HFILL}
190                 },
191                 { &hf_netdump_version,
192                         {"Netdump version", "netdump.version",
193                         FT_UINT8, BASE_HEX,
194                         NULL, 0x0,
195                         NULL, HFILL}
196                 }
197         };
198
199         proto_netdump = proto_register_protocol (
200                 "Netdump Protocol",     /* name */
201                 "Netdump",              /* short name */
202                 "netdump"               /* abbrev */
203                 );
204         proto_register_field_array(proto_netdump, hf, array_length(hf));
205         proto_register_subtree_array(ett, array_length(ett));
206
207         netdump_module = prefs_register_protocol(proto_netdump,
208                 proto_reg_handoff_netdump);
209
210         /* Register a sample port preference   */
211         prefs_register_uint_preference(netdump_module, "udp.port",
212                 "Netdump UDP port",
213                 "port if other than the default",
214                 10, &gPORT_PREF);
215 }
216
217 void proto_reg_handoff_netdump(void)
218 {
219         static gboolean initalized = FALSE;
220         static dissector_handle_t netdump_handle;
221         static int CurrentPort;
222
223         if (!initalized) {
224                 netdump_handle = create_dissector_handle(dissect_netdump,
225                                 proto_netdump);
226
227                 dissector_add_handle("udp.port", netdump_handle); /* For Decode As */
228                 initalized = TRUE;
229         } else {
230                 if (CurrentPort != 0)
231                         dissector_delete("udp.port", CurrentPort, netdump_handle);
232         }
233
234         CurrentPort = gPORT_PREF;
235
236         if (CurrentPort != 0)
237                 dissector_add("udp.port", CurrentPort, netdump_handle);
238 }
239