2 * Routines for kismet packet dissection
3 * Copyright 2006, Krzysztof Burghardt <krzysztof@burghardt.pl>
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.
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);
55 dissect_kismet(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data _U_
)
58 gboolean is_continuation
;
59 proto_tree
*kismet_tree
=NULL
, *reqresp_tree
=NULL
;
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.
90 for (i
= 0; i
< 8; ++i
) {
92 * Packet contains non-ASCII data
94 if (line
[i
] < 32 || line
[i
] > 128)
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
) {
109 is_continuation
= 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
119 * Otherwise, just call it a continuation.
122 col_set_str(pinfo
->cinfo
, COL_INFO
, "Continuation");
124 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s: %s",
125 is_request
? "Request" : "Response",
126 format_text(line
, linelen
));
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
);
142 tmp_item
= proto_tree_add_boolean(kismet_tree
,
143 hf_kismet_request
, tvb
, 0, 0, TRUE
);
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
);
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
);
168 reqresp
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, tokenlen
);
171 * No request dissection
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
);
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
);
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
);
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
);
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
);
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
);
222 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
223 proto_tree_add_text(reqresp_tree
, tvb
, offset
,
225 "Extended version string: %s",
226 format_text(line
, tokenlen
));
231 if (!strncmp(reqresp
, "*TIME", 5)) {
235 offset
+= (gint
) (next_token
- line
);
236 linelen
-= (int) (next_token
- line
);
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);*/
259 offset
= next_offset
;
266 response_is_continuation(const guchar
* data
)
268 if (!strncmp(data
, "*", 1))
271 if (!strncmp(data
, "!", 1))
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
}},
286 {"Request", "kismet.request", FT_BOOLEAN
, BASE_NONE
,
287 NULL
, 0x0, "TRUE if kismet request", HFILL
}}
290 static gint
*ett
[] = {
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
);
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
;
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
);