2 * Routines for kismet packet dissection
3 * Copyright 2006, Krzysztof Burghardt <krzysztof@burghardt.pl>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Copied from packet-pop.c
11 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include <epan/packet.h>
18 #include <epan/to_str.h>
19 #include <epan/strutil.h>
20 #include <epan/expert.h>
21 #include <wsutil/strtoi.h>
23 static int proto_kismet
;
24 static int hf_kismet_response
;
25 static int hf_kismet_request
;
26 static int hf_kismet_version
;
27 static int hf_kismet_start_time
;
28 static int hf_kismet_server_name
;
29 static int hf_kismet_build_revision
;
30 static int hf_kismet_unknown_field
;
31 static int hf_kismet_extended_version_string
;
32 static int hf_kismet_time
;
34 static int ett_kismet
;
35 static int ett_kismet_reqresp
;
37 static expert_field ei_time_invalid
;
39 #define TCP_PORT_KISMET 2501 /* Not IANA registered */
41 static bool response_is_continuation(const unsigned char * data
);
42 void proto_reg_handoff_kismet(void);
43 void proto_register_kismet(void);
45 static dissector_handle_t kismet_handle
;
48 dissect_kismet(tvbuff_t
* tvb
, packet_info
* pinfo
, proto_tree
* tree
, void * data _U_
)
52 proto_tree
*kismet_tree
=NULL
, *reqresp_tree
=NULL
;
56 const unsigned char *line
;
61 const unsigned char *next_token
;
64 * Find the end of the first line.
66 * Note that "tvb_find_line_end()" will return a value that is
67 * not longer than what's in the buffer, so the "tvb_get_ptr()"
68 * call won't throw an exception.
70 linelen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, false);
71 line
= tvb_get_ptr(tvb
, offset
, linelen
);
74 * Check if it is an ASCII based protocol with reasonable length
75 * packets, if not return, and try another dissector.
83 for (i
= 0; i
< 8; ++i
) {
85 * Packet contains non-ASCII data
87 if (line
[i
] < 32 || line
[i
] > 128)
93 * If it is Kismet traffic set COL_PROTOCOL.
95 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "kismet");
98 * Check if it is request, reply or continuation.
100 if (pinfo
->match_uint
== pinfo
->destport
) {
102 is_continuation
= false;
105 is_continuation
= response_is_continuation (line
);
109 * Put the first line from the buffer into the summary
110 * if it's a kismet request or reply (but leave out the
112 * Otherwise, just call it a continuation.
115 col_set_str(pinfo
->cinfo
, COL_INFO
, "Continuation");
117 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "%s: %s",
118 is_request
? "Request" : "Response",
119 format_text(pinfo
->pool
, line
, linelen
));
122 ti
= proto_tree_add_item(tree
, proto_kismet
, tvb
, offset
, -1, ENC_NA
);
123 kismet_tree
= proto_item_add_subtree(ti
, ett_kismet
);
126 if (is_continuation
) {
128 * Put the whole packet into the tree as data.
130 call_data_dissector(tvb
, pinfo
, kismet_tree
);
131 return tvb_captured_length(tvb
);
135 tmp_item
= proto_tree_add_boolean(kismet_tree
,
136 hf_kismet_request
, tvb
, 0, 0, true);
138 tmp_item
= proto_tree_add_boolean(kismet_tree
,
139 hf_kismet_response
, tvb
, 0, 0, true);
141 proto_item_set_generated (tmp_item
);
143 while (tvb_offset_exists(tvb
, offset
)) {
145 * Find the end of the line.
147 linelen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, false);
153 reqresp_tree
= proto_tree_add_subtree(kismet_tree
, tvb
, offset
,
154 next_offset
- offset
, ett_kismet_reqresp
, NULL
,
155 tvb_format_text(pinfo
->pool
, tvb
, offset
,
156 next_offset
- offset
- 1));
157 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
160 reqresp
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_ASCII
);
163 * No request dissection
167 * *KISMET: {Version} {Start time} \001{Server name}\001 {Build Revision}
168 * two fields left undocumented: {???} {?ExtendedVersion?}
170 if (!strncmp(reqresp
, "*KISMET", 7)) {
171 offset
+= (int) (next_token
- line
);
172 linelen
-= (int) (next_token
- line
);
174 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
175 proto_tree_add_string(reqresp_tree
, hf_kismet_version
, tvb
, offset
,
176 tokenlen
, format_text(pinfo
->pool
, line
, tokenlen
));
178 offset
+= (int) (next_token
- line
);
179 linelen
-= (int) (next_token
- line
);
181 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
182 proto_tree_add_string(reqresp_tree
, hf_kismet_start_time
, tvb
, offset
,
183 tokenlen
, format_text(pinfo
->pool
, line
, tokenlen
));
185 offset
+= (int) (next_token
- line
);
186 linelen
-= (int) (next_token
- line
);
188 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
189 proto_tree_add_string(reqresp_tree
, hf_kismet_server_name
, tvb
, offset
,
190 tokenlen
, format_text(pinfo
->pool
, line
+ 1, tokenlen
- 2));
192 offset
+= (int) (next_token
- line
);
193 linelen
-= (int) (next_token
- line
);
195 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
196 proto_tree_add_string(reqresp_tree
, hf_kismet_build_revision
, tvb
, offset
,
197 tokenlen
, format_text(pinfo
->pool
, line
, tokenlen
));
199 offset
+= (int) (next_token
- line
);
200 linelen
-= (int) (next_token
- line
);
202 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
203 proto_tree_add_string(reqresp_tree
, hf_kismet_unknown_field
, tvb
, offset
,
204 tokenlen
, format_text(pinfo
->pool
, line
, tokenlen
));
206 offset
+= (int) (next_token
- line
);
207 linelen
-= (int) (next_token
- line
);
209 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
210 proto_tree_add_string(reqresp_tree
, hf_kismet_extended_version_string
, tvb
, offset
,
211 tokenlen
, format_text(pinfo
->pool
, line
, tokenlen
));
216 if (!strncmp(reqresp
, "*TIME", 5)) {
219 proto_tree
* time_item
;
223 offset
+= (int) (next_token
- line
);
224 linelen
-= (int) (next_token
- line
);
226 tokenlen
= get_token_len(line
, line
+ linelen
, &next_token
);
228 /* Convert form ascii to nstime */
229 if (ws_strtou64(format_text(pinfo
->pool
, line
, tokenlen
), NULL
, (uint64_t*)&t
.secs
)) {
232 * Format ascii representation of time
234 ptr
= abs_time_secs_to_str(pinfo
->pool
, t
.secs
, ABSOLUTE_TIME_LOCAL
, true);
236 time_item
= proto_tree_add_time_format_value(reqresp_tree
, hf_kismet_time
, tvb
, offset
,
237 tokenlen
, &t
, "%s", ptr
? ptr
: "");
239 expert_add_info(pinfo
, time_item
, &ei_time_invalid
);
243 /*offset += (int) (next_token - line);
244 linelen -= (int) (next_token - line);*/
248 offset
= next_offset
;
251 return tvb_captured_length(tvb
);
255 response_is_continuation(const unsigned char * data
)
257 if (!strncmp(data
, "*", 1))
260 if (!strncmp(data
, "!", 1))
267 proto_register_kismet(void)
269 static hf_register_info hf
[] = {
270 {&hf_kismet_response
,
271 {"Response", "kismet.response", FT_BOOLEAN
, BASE_NONE
,
272 NULL
, 0x0, "true if kismet response", HFILL
}},
275 {"Request", "kismet.request", FT_BOOLEAN
, BASE_NONE
,
276 NULL
, 0x0, "true if kismet request", HFILL
}},
279 {"Version", "kismet.version", FT_STRING
, BASE_NONE
,
280 NULL
, 0x0, NULL
, HFILL
}},
282 {&hf_kismet_start_time
,
283 {"Start time", "kismet.start_time", FT_STRING
, BASE_NONE
,
284 NULL
, 0x0, NULL
, HFILL
}},
286 {&hf_kismet_server_name
,
287 {"Server name", "kismet.server_name", FT_STRING
, BASE_NONE
,
288 NULL
, 0x0, NULL
, HFILL
}},
290 {&hf_kismet_build_revision
,
291 {"Build revision", "kismet.build_revision", FT_STRING
, BASE_NONE
,
292 NULL
, 0x0, NULL
, HFILL
}},
294 {&hf_kismet_unknown_field
,
295 {"Unknown field", "kismet.unknown_field", FT_STRING
, BASE_NONE
,
296 NULL
, 0x0, NULL
, HFILL
}},
298 {&hf_kismet_extended_version_string
,
299 {"Extended version string", "kismet.extended_version_string", FT_STRING
, BASE_NONE
,
300 NULL
, 0x0, NULL
, HFILL
}},
303 {"Time", "kismet.time", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
304 NULL
, 0x0, NULL
, HFILL
}},
307 static ei_register_info ei
[] = {
308 { &ei_time_invalid
, { "kismet.time.invalid", PI_PROTOCOL
, PI_WARN
, "Invalid time", EXPFILL
}}
311 static int *ett
[] = {
315 expert_module_t
* expert_kismet
;
317 proto_kismet
= proto_register_protocol("Kismet Client/Server Protocol", "Kismet", "kismet");
318 proto_register_field_array(proto_kismet
, hf
, array_length (hf
));
319 proto_register_subtree_array(ett
, array_length (ett
));
320 expert_kismet
= expert_register_protocol(proto_kismet
);
321 expert_register_field_array(expert_kismet
, ei
, array_length(ei
));
323 kismet_handle
= register_dissector("kismet", dissect_kismet
, proto_kismet
);
327 proto_reg_handoff_kismet(void)
329 dissector_add_uint_with_preference("tcp.port", TCP_PORT_KISMET
, kismet_handle
);
333 * Editor modelines - https://www.wireshark.org/tools/modelines.html
338 * indent-tabs-mode: t
341 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
342 * :indentSize=8:tabSize=8:noTabs=false: