HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-kismet.c
blobb3502a86bfc4b73664eddfbd28630df34be9e586
1 /* packet-kismet.c
2 * Routines for kismet packet dissection
3 * Copyright 2006, Krzysztof Burghardt <krzysztof@burghardt.pl>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-pop.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "config.h"
30 #include <stdlib.h>
31 #include <string.h>
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/strutil.h>
35 #include <epan/prefs.h>
37 static int proto_kismet = -1;
38 static int hf_kismet_response = -1;
39 static int hf_kismet_request = -1;
41 static gint ett_kismet = -1;
42 static gint ett_kismet_reqresp = -1;
44 static dissector_handle_t data_handle;
46 #define TCP_PORT_KISMET 2501
48 static guint global_kismet_tcp_port = TCP_PORT_KISMET;
50 static gboolean response_is_continuation(const guchar * data);
51 void proto_reg_handoff_kismet(void);
52 void proto_register_kismet(void);
54 static gboolean
55 dissect_kismet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_)
57 gboolean is_request;
58 gboolean is_continuation;
59 proto_tree *kismet_tree=NULL, *reqresp_tree=NULL;
60 proto_item *ti;
61 proto_item *tmp_item;
62 gint offset = 0;
63 const guchar *line;
64 gint next_offset;
65 int linelen;
66 int tokenlen;
67 int i;
68 const guchar *next_token;
71 * Find the end of the first line.
73 * Note that "tvb_find_line_end()" will return a value that is
74 * not longer than what's in the buffer, so the "tvb_get_ptr()"
75 * call won't throw an exception.
77 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
78 line = tvb_get_ptr(tvb, offset, linelen);
81 * Check if it is an ASCII based protocol with reasonable length
82 * packets, if not return, and try annother dissector.
84 if (linelen < 8) {
86 * Packet is too short
88 return FALSE;
89 } else {
90 for (i = 0; i < 8; ++i) {
92 * Packet contains non-ASCII data
94 if (line[i] < 32 || line[i] > 128)
95 return FALSE;
100 * If it is Kismet traffic set COL_PROTOCOL.
102 col_set_str(pinfo->cinfo, COL_PROTOCOL, "kismet");
105 * Check if it is request, reply or continuation.
107 if (pinfo->match_uint == pinfo->destport) {
108 is_request = TRUE;
109 is_continuation = FALSE;
110 } else {
111 is_request = FALSE;
112 is_continuation = response_is_continuation (line);
116 * Put the first line from the buffer into the summary
117 * if it's a kismet request or reply (but leave out the
118 * line terminator).
119 * Otherwise, just call it a continuation.
121 if (is_continuation)
122 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
123 else
124 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
125 is_request ? "Request" : "Response",
126 format_text(line, linelen));
128 if (tree) {
129 ti = proto_tree_add_item(tree, proto_kismet, tvb, offset, -1, ENC_NA);
130 kismet_tree = proto_item_add_subtree(ti, ett_kismet);
133 if (is_continuation) {
135 * Put the whole packet into the tree as data.
137 call_dissector(data_handle, tvb, pinfo, kismet_tree);
138 return TRUE;
141 if (is_request) {
142 tmp_item = proto_tree_add_boolean(kismet_tree,
143 hf_kismet_request, tvb, 0, 0, TRUE);
144 } else {
145 tmp_item = proto_tree_add_boolean(kismet_tree,
146 hf_kismet_response, tvb, 0, 0, TRUE);
148 PROTO_ITEM_SET_GENERATED (tmp_item);
150 while (tvb_offset_exists(tvb, offset)) {
152 * Find the end of the line.
154 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
156 if (linelen) {
158 * Put this line.
160 ti = proto_tree_add_text(kismet_tree, tvb, offset,
161 next_offset - offset, "%s",
162 tvb_format_text(tvb, offset,
163 next_offset - offset - 1));
164 reqresp_tree = proto_item_add_subtree(ti, ett_kismet_reqresp);
165 tokenlen = get_token_len(line, line + linelen, &next_token);
166 if (tokenlen != 0) {
167 guint8 *reqresp;
168 reqresp = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
169 if (is_request) {
171 * No request dissection
173 } else {
175 * *KISMET: {Version} {Start time} \001{Server name}\001 {Build Revision}
176 * two fields left undocumented: {???} {?ExtendedVersion?}
178 if (!strncmp(reqresp, "*KISMET", 7)) {
179 offset += (gint) (next_token - line);
180 linelen -= (int) (next_token - line);
181 line = next_token;
182 tokenlen = get_token_len(line, line + linelen, &next_token);
183 proto_tree_add_text(reqresp_tree, tvb, offset,
184 tokenlen, "Kismet version: %s",
185 format_text(line, tokenlen));
187 offset += (gint) (next_token - line);
188 linelen -= (int) (next_token - line);
189 line = next_token;
190 tokenlen = get_token_len(line, line + linelen, &next_token);
191 proto_tree_add_text(reqresp_tree, tvb, offset,
192 tokenlen, "Start time: %s",
193 format_text(line, tokenlen));
195 offset += (gint) (next_token - line);
196 linelen -= (int) (next_token - line);
197 line = next_token;
198 tokenlen = get_token_len(line, line + linelen, &next_token);
199 proto_tree_add_text(reqresp_tree, tvb, offset,
200 tokenlen, "Server name: %s",
201 format_text(line + 1, tokenlen - 2));
203 offset += (gint) (next_token - line);
204 linelen -= (int) (next_token - line);
205 line = next_token;
206 tokenlen = get_token_len(line, line + linelen, &next_token);
207 proto_tree_add_text(reqresp_tree, tvb, offset,
208 tokenlen, "Build revision: %s",
209 format_text(line, tokenlen));
211 offset += (gint) (next_token - line);
212 linelen -= (int) (next_token - line);
213 line = next_token;
214 tokenlen = get_token_len(line, line + linelen, &next_token);
215 proto_tree_add_text(reqresp_tree, tvb, offset,
216 tokenlen, "Unknown field: %s",
217 format_text(line, tokenlen));
219 offset += (gint) (next_token - line);
220 linelen -= (int) (next_token - line);
221 line = next_token;
222 tokenlen = get_token_len(line, line + linelen, &next_token);
223 proto_tree_add_text(reqresp_tree, tvb, offset,
224 tokenlen,
225 "Extended version string: %s",
226 format_text(line, tokenlen));
229 * *TIME: {Time}
231 if (!strncmp(reqresp, "*TIME", 5)) {
232 time_t t;
233 char *ptr;
235 offset += (gint) (next_token - line);
236 linelen -= (int) (next_token - line);
237 line = next_token;
238 tokenlen = get_token_len(line, line + linelen, &next_token);
241 * Convert form ascii to time_t
243 t = atoi(format_text (line, tokenlen));
246 * Format ascii representaion of time
248 ptr = abs_time_secs_to_str(t, ABSOLUTE_TIME_LOCAL, TRUE);
249 proto_tree_add_text(reqresp_tree, tvb, offset,
250 tokenlen, "Time: %s", ptr);
254 /*offset += (gint) (next_token - line);
255 linelen -= (int) (next_token - line);*/
256 line = next_token;
259 offset = next_offset;
262 return TRUE;
265 static gboolean
266 response_is_continuation(const guchar * data)
268 if (!strncmp(data, "*", 1))
269 return FALSE;
271 if (!strncmp(data, "!", 1))
272 return FALSE;
274 return TRUE;
277 void
278 proto_register_kismet(void)
280 static hf_register_info hf[] = {
281 {&hf_kismet_response,
282 {"Response", "kismet.response", FT_BOOLEAN, BASE_NONE,
283 NULL, 0x0, "TRUE if kismet response", HFILL}},
285 {&hf_kismet_request,
286 {"Request", "kismet.request", FT_BOOLEAN, BASE_NONE,
287 NULL, 0x0, "TRUE if kismet request", HFILL}}
290 static gint *ett[] = {
291 &ett_kismet,
292 &ett_kismet_reqresp,
294 module_t *kismet_module;
296 proto_kismet = proto_register_protocol("Kismet Client/Server Protocol", "Kismet", "kismet");
297 proto_register_field_array(proto_kismet, hf, array_length (hf));
298 proto_register_subtree_array(ett, array_length (ett));
300 /* Register our configuration options for Kismet, particularly our port */
302 kismet_module = prefs_register_protocol(proto_kismet, proto_reg_handoff_kismet);
304 prefs_register_uint_preference(kismet_module, "tcp.port",
305 "Kismet Server TCP Port",
306 "Set the port for Kismet Client/Server messages (if other"
307 " than the default of 2501)", 10,
308 &global_kismet_tcp_port);
311 void
312 proto_reg_handoff_kismet(void)
314 static gboolean kismet_prefs_initialized = FALSE;
315 static dissector_handle_t kismet_handle;
316 static guint tcp_port;
318 if (!kismet_prefs_initialized) {
319 kismet_handle = new_create_dissector_handle(dissect_kismet, proto_kismet);
320 data_handle = find_dissector("data");
321 kismet_prefs_initialized = TRUE;
322 } else {
323 dissector_delete_uint("tcp.port", tcp_port, kismet_handle);
326 /* Set our port number for future use */
327 tcp_port = global_kismet_tcp_port;
329 dissector_add_uint("tcp.port", global_kismet_tcp_port, kismet_handle);