3 * Routines for Kyoto Tycoon Version 1 binary protocol dissection
4 * Copyright 2013, Abhik Sarkar <sarkar.abhik@gmail.com>
6 * http://fallabs.com/kyototycoon/spex.html#protocol
7 * (Section "Binary Protocol")
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * Adapted from packet-bzr.c
15 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <epan/packet.h>
21 #include <epan/prefs.h>
24 void proto_register_kt(void);
25 void proto_reg_handoff_kt(void);
30 * A few notes before we get into the thick of things...
33 * ============================
34 * While this is probably a very efficient protocol for the purpose
35 * for which it has been written, the way it has been written makes
36 * dissection a bit tricky. Requests and responses have the same
37 * "magic" identifier, but there is no clear cut way to distinguish
38 * between them. This means that a few dirty tricks have to be
39 * employed for dissecting... and the dissector is based on sample
40 * captures from two different clients working with the same version
42 * It is possible that the dissection will break under other conditions.
43 * Hopefully, this can be fixed/improved with time.
46 * ============================
47 * There are three fields which use 64-bit time stamps. Based on what
48 * I can see from the sample traces I have, the value in each is
49 * different. I don't know if this is something specific to the
50 * version of the client and server I have, or this is how the
51 * implementation is... however, the difference is not apparent
52 * (at least to me) from the protocol specifications.
53 * So, this note is to clarify what I have found:
54 * - The timestamp (ts) in the replication requests is nanoseconds
56 * - The timestamp (xt) in the set_bulk records is the number of
57 * seconds the record must live.
58 * - The timestamp (xt) in the get_bulk output records is the
59 * seconds since epoch.
61 * TODO: Support for reassembly of a request or response segmented over
62 * multiple frames needs to be added.
63 * A single frame containing multiple requests/responses seems unlikely
64 * due to the fact that there is no identifier for matching a request
65 * and a response. Tests suggest that the communication is synchronous.
68 static dissector_handle_t kt_handle
;
72 static int ett_kt_rec
;
75 static int hf_kt_magic
;
76 static int hf_kt_type
;
78 static int hf_kt_flags
;
79 static int hf_kt_rnum
;
80 static int hf_kt_dbidx
;
83 static int hf_kt_xt_resp
;
84 static int hf_kt_ksiz
;
85 static int hf_kt_vsiz
;
88 static int hf_kt_key_str
;
89 static int hf_kt_val_str
;
90 static int hf_kt_hits
;
91 static int hf_kt_nsiz
;
92 static int hf_kt_name
;
93 static int hf_kt_size
;
98 #define KT_MAGIC_REPL_WAIT 0xB0
99 #define KT_MAGIC_REPLICATION 0xB1
100 #define KT_MAGIC_PLAY_SCRIPT 0xB4
101 #define KT_MAGIC_SET_BULK 0xB8
102 #define KT_MAGIC_REMOVE_BULK 0xB9
103 #define KT_MAGIC_GET_BULK 0xBA
104 #define KT_MAGIC_ERROR 0xBF
106 static const value_string kt_magic_vals
[] = {
107 {KT_MAGIC_REPL_WAIT
, "replication - waiting for updates"},
108 {KT_MAGIC_REPLICATION
, "replication"},
109 {KT_MAGIC_PLAY_SCRIPT
, "play_script"},
110 {KT_MAGIC_SET_BULK
, "set_bulk" },
111 {KT_MAGIC_REMOVE_BULK
, "remove_bulk"},
112 {KT_MAGIC_GET_BULK
, "get_bulk" },
113 {KT_MAGIC_ERROR
, "error" },
117 /* Operation type (determined/generated by the dissector) */
118 #define KT_OPER_REQUEST 0x00
119 #define KT_OPER_RESPONSE 0x01
121 static const value_string kt_oper_vals
[] = {
122 {KT_OPER_REQUEST
, "request"},
123 {KT_OPER_RESPONSE
, "response"},
129 * The default port numbers are not IANA registered but used by the
130 * default configuration of the KT server all the same.
132 #define DEFAULT_KT_PORT_RANGE "1978-1979"
133 static bool kt_present_key_val_as_ascii
;
135 /* Dissection routines */
137 dissect_kt_replication_wait(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
)
145 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
148 ts
= tvb_get_ntoh64(tvb
, new_offset
);
149 ns_ts
.secs
= (time_t)(ts
/1000000000);
150 ns_ts
.nsecs
= (int)(ts
%1000000000);
151 proto_tree_add_time(tree
, hf_kt_ts
, tvb
, new_offset
, 8, &ns_ts
);
158 dissect_kt_replication(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
161 uint32_t next32
, size
;
168 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
171 if (tvb_reported_length_remaining(tvb
, new_offset
) > 0) {
172 next32
= tvb_get_ntohl(tvb
, new_offset
);
173 if (next32
<= 1) { /* This means request. the 32 bits are flags */
174 proto_tree_add_item(tree
, hf_kt_flags
, tvb
, new_offset
, 4, ENC_BIG_ENDIAN
);
177 proto_tree_add_item(tree
, hf_kt_ts
, tvb
, new_offset
, 8, ENC_BIG_ENDIAN
);
180 proto_tree_add_item(tree
, hf_kt_sid
, tvb
, new_offset
, 2, ENC_BIG_ENDIAN
);
182 } else { /* This is a response. The 32 bits are the first half of the ts */
183 ts
= tvb_get_ntoh64(tvb
, new_offset
);
184 ns_ts
.secs
= (time_t)(ts
/1000000000);
185 ns_ts
.nsecs
= (int)(ts
%1000000000);
186 proto_tree_add_time(tree
, hf_kt_ts
, tvb
, new_offset
, 8, &ns_ts
);
189 size
= tvb_get_ntohl(tvb
, new_offset
);
190 proto_tree_add_uint(tree
, hf_kt_size
, tvb
, new_offset
, 4, size
);
193 proto_tree_add_item(tree
, hf_kt_log
, tvb
, new_offset
, size
, ENC_NA
);
197 /* This is an empty ack to the message with magic 0xB0. */
198 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
199 proto_item_set_generated(pi
);
200 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
207 dissect_kt_set_bulk(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
209 uint32_t next32
, rnum
, ksiz
, vsiz
;
210 int new_offset
, rec_start_offset
;
213 proto_tree
*rec_tree
;
217 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
220 next32
= tvb_get_ntohl(tvb
, new_offset
);
222 if (tvb_reported_length_remaining(tvb
, (new_offset
+ 4)) > 0) {
223 /* There's more data after the 32 bits. This is a request */
224 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_REQUEST
);
225 proto_item_set_generated(pi
);
227 proto_tree_add_uint(tree
, hf_kt_flags
, tvb
, new_offset
, 4, next32
);
230 rnum
= tvb_get_ntohl(tvb
, new_offset
);
231 proto_tree_add_uint(tree
, hf_kt_rnum
, tvb
, new_offset
, 4, rnum
);
235 /* Create a sub-tree for each record */
236 ti
= proto_tree_add_item(tree
, hf_kt_rec
, tvb
, new_offset
, -1, ENC_NA
);
237 rec_tree
= proto_item_add_subtree(ti
, ett_kt_rec
);
238 rec_start_offset
= new_offset
;
240 proto_tree_add_item(rec_tree
, hf_kt_dbidx
, tvb
, new_offset
, 2, ENC_BIG_ENDIAN
);
243 ksiz
= tvb_get_ntohl(tvb
, new_offset
);
244 proto_tree_add_uint(rec_tree
, hf_kt_ksiz
, tvb
, new_offset
, 4, ksiz
);
247 vsiz
= tvb_get_ntohl(tvb
, new_offset
);
248 proto_tree_add_uint(rec_tree
, hf_kt_vsiz
, tvb
, new_offset
, 4, vsiz
);
251 proto_tree_add_item(rec_tree
, hf_kt_xt
, tvb
, new_offset
, 8, ENC_BIG_ENDIAN
);
254 proto_tree_add_item(rec_tree
, hf_kt_key
, tvb
, new_offset
, ksiz
, ENC_NA
);
255 if (kt_present_key_val_as_ascii
) {
256 pi
= proto_tree_add_item(rec_tree
, hf_kt_key_str
, tvb
, new_offset
, ksiz
, ENC_ASCII
);
257 proto_item_set_generated(pi
);
261 proto_tree_add_item(rec_tree
, hf_kt_val
, tvb
, new_offset
, vsiz
, ENC_NA
);
262 if (kt_present_key_val_as_ascii
) {
263 pi
= proto_tree_add_item(rec_tree
, hf_kt_val_str
, tvb
, new_offset
, vsiz
, ENC_ASCII
);
264 proto_item_set_generated(pi
);
268 proto_item_set_len(ti
, new_offset
- rec_start_offset
);
272 /* Nothing remaining after the 32 bits. This is a response. */
273 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
274 proto_item_set_generated(pi
);
275 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
277 proto_tree_add_uint(tree
, hf_kt_hits
, tvb
, new_offset
, 4, next32
);
285 dissect_kt_play_script(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
287 uint32_t next32
, rnum
, ksiz
, vsiz
, nsiz
;
288 int new_offset
, rec_start_offset
;
291 proto_tree
*rec_tree
;
295 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
298 next32
= tvb_get_ntohl(tvb
, new_offset
);
301 if (tvb_reported_length_remaining(tvb
, (new_offset
+ 4)) > 0) {
302 /* There's more data after the 32 bits. This is a request */
303 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_REQUEST
);
304 proto_item_set_generated(pi
);
306 proto_tree_add_uint(tree
, hf_kt_flags
, tvb
, new_offset
, 4, next32
);
309 nsiz
= tvb_get_ntohl(tvb
, new_offset
);
310 proto_tree_add_uint(tree
, hf_kt_nsiz
, tvb
, new_offset
, 4, nsiz
);
313 rnum
= tvb_get_ntohl(tvb
, new_offset
);
314 proto_tree_add_uint(tree
, hf_kt_rnum
, tvb
, new_offset
, 4, rnum
);
317 proto_tree_add_item(tree
, hf_kt_name
, tvb
, new_offset
, nsiz
, ENC_ASCII
);
321 /* Create a sub-tree for each record */
322 ti
= proto_tree_add_item(tree
, hf_kt_rec
, tvb
, new_offset
, -1, ENC_NA
);
323 rec_tree
= proto_item_add_subtree(ti
, ett_kt_rec
);
324 rec_start_offset
= new_offset
;
326 ksiz
= tvb_get_ntohl(tvb
, new_offset
);
327 proto_tree_add_uint(rec_tree
, hf_kt_ksiz
, tvb
, new_offset
, 4, ksiz
);
330 vsiz
= tvb_get_ntohl(tvb
, new_offset
);
331 proto_tree_add_uint(rec_tree
, hf_kt_vsiz
, tvb
, new_offset
, 4, vsiz
);
334 proto_tree_add_item(rec_tree
, hf_kt_key
, tvb
, new_offset
, ksiz
, ENC_NA
);
335 if (kt_present_key_val_as_ascii
) {
336 pi
= proto_tree_add_item(rec_tree
, hf_kt_key_str
, tvb
, new_offset
, ksiz
, ENC_ASCII
);
337 proto_item_set_generated(pi
);
341 proto_tree_add_item(rec_tree
, hf_kt_val
, tvb
, new_offset
, vsiz
, ENC_NA
);
342 if (kt_present_key_val_as_ascii
) {
343 pi
= proto_tree_add_item(rec_tree
, hf_kt_val_str
, tvb
, new_offset
, vsiz
, ENC_ASCII
);
344 proto_item_set_generated(pi
);
348 proto_item_set_len(ti
, new_offset
- rec_start_offset
);
352 /* Nothing remaining after the 32 bits. This is a response with no records. */
353 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
354 proto_item_set_generated(pi
);
355 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
357 proto_tree_add_uint(tree
, hf_kt_rnum
, tvb
, new_offset
, 4, next32
);
360 } else { /* response - one or more records */
361 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
362 proto_item_set_generated(pi
);
363 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
365 rnum
= tvb_get_ntohl(tvb
, new_offset
);
366 proto_tree_add_uint(tree
, hf_kt_hits
, tvb
, new_offset
, 4, rnum
);
370 /* Create a sub-tree for each record */
371 ti
= proto_tree_add_item(tree
, hf_kt_rec
, tvb
, new_offset
, -1, ENC_NA
);
372 rec_tree
= proto_item_add_subtree(ti
, ett_kt_rec
);
373 rec_start_offset
= new_offset
;
375 ksiz
= tvb_get_ntohl(tvb
, new_offset
);
376 proto_tree_add_uint(rec_tree
, hf_kt_ksiz
, tvb
, new_offset
, 4, ksiz
);
379 vsiz
= tvb_get_ntohl(tvb
, new_offset
);
380 proto_tree_add_uint(rec_tree
, hf_kt_vsiz
, tvb
, new_offset
, 4, vsiz
);
383 proto_tree_add_item(rec_tree
, hf_kt_key
, tvb
, new_offset
, ksiz
, ENC_NA
);
384 if (kt_present_key_val_as_ascii
) {
385 pi
= proto_tree_add_item(rec_tree
, hf_kt_key_str
, tvb
, new_offset
, ksiz
, ENC_ASCII
);
386 proto_item_set_generated(pi
);
390 proto_tree_add_item(rec_tree
, hf_kt_val
, tvb
, new_offset
, vsiz
, ENC_NA
);
391 if (kt_present_key_val_as_ascii
) {
392 pi
= proto_tree_add_item(rec_tree
, hf_kt_val_str
, tvb
, new_offset
, vsiz
, ENC_ASCII
);
393 proto_item_set_generated(pi
);
397 proto_item_set_len(ti
, new_offset
- rec_start_offset
);
406 dissect_kt_get_bulk(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
408 uint32_t next32
, rnum
, ksiz
, vsiz
;
411 int new_offset
, rec_start_offset
;
414 proto_tree
*rec_tree
;
418 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
421 next32
= tvb_get_ntohl(tvb
, new_offset
);
424 if (tvb_reported_length_remaining(tvb
, (new_offset
+ 4)) > 0) { /* request */
425 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_REQUEST
);
426 proto_item_set_generated(pi
);
428 proto_tree_add_uint(tree
, hf_kt_flags
, tvb
, new_offset
, 4, next32
);
431 rnum
= tvb_get_ntohl(tvb
, new_offset
);
432 proto_tree_add_uint(tree
, hf_kt_rnum
, tvb
, new_offset
, 4, rnum
);
436 /* Create a sub-tree for each record */
437 ti
= proto_tree_add_item(tree
, hf_kt_rec
, tvb
, new_offset
, -1, ENC_NA
);
438 rec_tree
= proto_item_add_subtree(ti
, ett_kt_rec
);
439 rec_start_offset
= new_offset
;
441 proto_tree_add_item(rec_tree
, hf_kt_dbidx
, tvb
, new_offset
, 2, ENC_BIG_ENDIAN
);
444 ksiz
= tvb_get_ntohl(tvb
, new_offset
);
445 proto_tree_add_uint(rec_tree
, hf_kt_ksiz
, tvb
, new_offset
, 4, ksiz
);
448 proto_tree_add_item(rec_tree
, hf_kt_key
, tvb
, new_offset
, ksiz
, ENC_NA
);
449 if (kt_present_key_val_as_ascii
) {
450 pi
= proto_tree_add_item(rec_tree
, hf_kt_key_str
, tvb
, new_offset
, ksiz
, ENC_ASCII
);
451 proto_item_set_generated(pi
);
455 proto_item_set_len(ti
, new_offset
- rec_start_offset
);
458 } else { /* response - no records */
459 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
460 proto_item_set_generated(pi
);
461 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
463 proto_tree_add_uint(tree
, hf_kt_hits
, tvb
, new_offset
, 4, next32
);
466 } else { /* response - one or more records */
467 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
468 proto_item_set_generated(pi
);
469 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
471 rnum
= tvb_get_ntohl(tvb
, new_offset
);
472 proto_tree_add_uint(tree
, hf_kt_hits
, tvb
, new_offset
, 4, rnum
);
476 /* Create a sub-tree for each record */
477 ti
= proto_tree_add_item(tree
, hf_kt_rec
, tvb
, new_offset
, -1, ENC_NA
);
478 rec_tree
= proto_item_add_subtree(ti
, ett_kt_rec
);
479 rec_start_offset
= new_offset
;
481 proto_tree_add_item(rec_tree
, hf_kt_dbidx
, tvb
, new_offset
, 2, ENC_BIG_ENDIAN
);
484 ksiz
= tvb_get_ntohl(tvb
, new_offset
);
485 proto_tree_add_uint(rec_tree
, hf_kt_ksiz
, tvb
, new_offset
, 4, ksiz
);
488 vsiz
= tvb_get_ntohl(tvb
, new_offset
);
489 proto_tree_add_uint(rec_tree
, hf_kt_vsiz
, tvb
, new_offset
, 4, vsiz
);
492 xt
= tvb_get_ntoh64(tvb
, new_offset
);
493 ts
.secs
= (time_t)(xt
&0xFFFFFFFF);
495 proto_tree_add_time(rec_tree
, hf_kt_xt_resp
, tvb
, new_offset
, 8, &ts
);
498 proto_tree_add_item(rec_tree
, hf_kt_key
, tvb
, new_offset
, ksiz
, ENC_NA
);
499 if (kt_present_key_val_as_ascii
) {
500 pi
= proto_tree_add_item(rec_tree
, hf_kt_key_str
, tvb
, new_offset
, ksiz
, ENC_ASCII
);
501 proto_item_set_generated(pi
);
505 proto_tree_add_item(rec_tree
, hf_kt_val
, tvb
, new_offset
, vsiz
, ENC_NA
);
506 if (kt_present_key_val_as_ascii
) {
507 pi
= proto_tree_add_item(rec_tree
, hf_kt_val_str
, tvb
, new_offset
, vsiz
, ENC_ASCII
);
508 proto_item_set_generated(pi
);
512 proto_item_set_len(ti
, new_offset
- rec_start_offset
);
521 dissect_kt_remove_bulk(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
)
523 uint32_t next32
, rnum
, ksiz
;
524 int new_offset
, rec_start_offset
;
527 proto_tree
*rec_tree
;
531 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
534 next32
= tvb_get_ntohl(tvb
, new_offset
);
536 if (tvb_reported_length_remaining(tvb
, (new_offset
+ 4)) > 0) { /* request */
537 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_REQUEST
);
538 proto_item_set_generated(pi
);
540 proto_tree_add_uint(tree
, hf_kt_flags
, tvb
, new_offset
, 4, next32
);
543 rnum
= tvb_get_ntohl(tvb
, new_offset
);
544 proto_tree_add_uint(tree
, hf_kt_rnum
, tvb
, new_offset
, 4, rnum
);
548 /* Create a sub-tree for each record */
549 ti
= proto_tree_add_item(tree
, hf_kt_rec
, tvb
, new_offset
, -1, ENC_NA
);
550 rec_tree
= proto_item_add_subtree(ti
, ett_kt_rec
);
551 rec_start_offset
= new_offset
;
553 proto_tree_add_item(rec_tree
, hf_kt_dbidx
, tvb
, new_offset
, 2, ENC_BIG_ENDIAN
);
556 ksiz
= tvb_get_ntohl(tvb
, new_offset
);
557 proto_tree_add_uint(rec_tree
, hf_kt_ksiz
, tvb
, new_offset
, 4, ksiz
);
560 proto_tree_add_item(rec_tree
, hf_kt_key
, tvb
, new_offset
, ksiz
, ENC_NA
);
561 if (kt_present_key_val_as_ascii
) {
562 pi
= proto_tree_add_item(rec_tree
, hf_kt_key_str
, tvb
, new_offset
, ksiz
, ENC_ASCII
);
563 proto_item_set_generated(pi
);
567 proto_item_set_len(ti
, new_offset
- rec_start_offset
);
570 } else { /* response */
571 pi
= proto_tree_add_uint(tree
, hf_kt_type
, tvb
, offset
, 1, KT_OPER_RESPONSE
);
572 proto_item_set_generated(pi
);
573 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, " ", "[response]");
575 proto_tree_add_uint(tree
, hf_kt_hits
, tvb
, new_offset
, 4, next32
);
583 dissect_kt_error(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
)
589 proto_tree_add_item(tree
, hf_kt_magic
, tvb
, new_offset
, 1, ENC_BIG_ENDIAN
);
596 dissect_kt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
601 int offset
, offset_start
;
605 while (tvb_reported_length_remaining(tvb
, offset
) > 0) {
606 magic
= tvb_get_uint8(tvb
, offset
);
608 /* If the magic is not one of the known values, exit */
609 if (try_val_to_str(magic
, kt_magic_vals
) == NULL
)
612 /* Otherwise, the magic value is known. Continue */
613 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "KT");
614 col_set_str(pinfo
->cinfo
, COL_INFO
, try_val_to_str(magic
, kt_magic_vals
));
616 ti
= proto_tree_add_item(tree
, proto_kt
, tvb
, offset
, -1, ENC_NA
);
617 kt_tree
= proto_item_add_subtree(ti
, ett_kt
);
622 case KT_MAGIC_REPL_WAIT
:
623 offset
= dissect_kt_replication_wait(tvb
, kt_tree
, offset
);
625 case KT_MAGIC_REPLICATION
:
626 offset
= dissect_kt_replication(tvb
, pinfo
, kt_tree
, offset
);
628 case KT_MAGIC_PLAY_SCRIPT
:
629 offset
= dissect_kt_play_script(tvb
, pinfo
, kt_tree
, offset
);
631 case KT_MAGIC_SET_BULK
:
632 offset
= dissect_kt_set_bulk(tvb
, pinfo
, kt_tree
, offset
);
634 case KT_MAGIC_REMOVE_BULK
:
635 offset
= dissect_kt_remove_bulk(tvb
, pinfo
, kt_tree
, offset
);
637 case KT_MAGIC_GET_BULK
:
638 offset
= dissect_kt_get_bulk(tvb
, pinfo
, kt_tree
, offset
);
641 offset
= dissect_kt_error(tvb
, kt_tree
, offset
);
645 proto_item_set_len(ti
, offset
-offset_start
);
648 return tvb_captured_length(tvb
);
652 proto_register_kt(void)
654 module_t
*kt_module
; /* preferences */
656 static hf_register_info hf
[] = {
658 { "magic", "kt.magic", FT_UINT8
, BASE_HEX
,
659 VALS(kt_magic_vals
), 0x0, "identifier", HFILL
663 { "type", "kt.type", FT_UINT8
, BASE_HEX
,
664 VALS(kt_oper_vals
), 0x0, "request/response", HFILL
668 { "flags", "kt.flags", FT_UINT32
, BASE_HEX
,
669 NULL
, 0x0, "flags of bitwise-or", HFILL
673 { "rnum", "kt.rnum", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
674 "the number of records", HFILL
678 { "dbidx", "kt.dbidx", FT_UINT16
,
679 BASE_DEC
, NULL
, 0x0, "the index of the target database", HFILL
683 { "sid", "kt.sid", FT_UINT16
, BASE_DEC
,
684 NULL
, 0x0, "the server ID number", HFILL
688 { "ts", "kt.ts", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
689 NULL
, 0x0, "the timestamp of the log", HFILL
693 { "xt", "kt.xt", FT_UINT64
, BASE_DEC
,
694 NULL
, 0x0, "the expiration time in seconds", HFILL
698 { "xt", "kt.xt_resp", FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_LOCAL
,
699 NULL
, 0x0, "the expiration time", HFILL
703 { "ksiz", "kt.ksiz", FT_UINT32
, BASE_DEC
,
704 NULL
, 0x0, "the size of the key",HFILL
708 { "vsiz", "kt.vsiz", FT_UINT32
, BASE_DEC
,
709 NULL
, 0x0, "the size of the value", HFILL
713 { "key", "kt.key", FT_BYTES
, BASE_NONE
,
714 NULL
, 0x0, "the key", HFILL
718 { "value", "kt.value", FT_BYTES
, BASE_NONE
,
719 NULL
, 0x0, "the value", HFILL
723 { "key", "kt.key_str", FT_STRING
, BASE_NONE
,
724 NULL
, 0x0, "ASCII representation of the key", HFILL
728 { "value", "kt.value_str", FT_STRING
, BASE_NONE
,
729 NULL
, 0x0, "ASCII representation of the value", HFILL
733 { "hits", "kt.hits", FT_UINT32
, BASE_DEC
,
734 NULL
, 0x0, "the number of records", HFILL
738 { "size", "kt.size", FT_UINT32
, BASE_DEC
,
739 NULL
, 0x0, "the size of the replication log", HFILL
743 { "log", "kt.log", FT_BYTES
, BASE_NONE
,
744 NULL
, 0x0, "the replication log", HFILL
748 { "nsiz", "kt.nsiz", FT_UINT32
, BASE_DEC
,
749 NULL
, 0x0, "the size of the procedure name", HFILL
753 { "name", "kt.name", FT_STRING
, BASE_NONE
,
754 NULL
, 0x0, "the procedure name", HFILL
758 { "record", "kt.record", FT_NONE
, BASE_NONE
,
759 NULL
, 0x0, "a record", HFILL
764 static int *ett
[] = {
769 proto_kt
= proto_register_protocol("Kyoto Tycoon Protocol", "Kyoto Tycoon", "kt");
770 kt_handle
= register_dissector("kt", dissect_kt
, proto_kt
);
771 proto_register_field_array(proto_kt
, hf
, array_length(hf
));
772 proto_register_subtree_array(ett
, array_length(ett
));
775 kt_module
= prefs_register_protocol(proto_kt
, NULL
);
777 prefs_register_bool_preference(kt_module
, "present_key_val_as_ascii",
778 "Attempt to also show ASCII string representation of keys and values",
779 "KT allows binary values in keys and values. Attempt to show an ASCII representation anyway (which might be prematurely terminated by a NULL!",
780 &kt_present_key_val_as_ascii
);
784 proto_reg_handoff_kt(void)
786 dissector_add_uint_range_with_preference("tcp.port", DEFAULT_KT_PORT_RANGE
, kt_handle
);
790 * Editor modelines - https://www.wireshark.org/tools/modelines.html
795 * indent-tabs-mode: nil
798 * vi: set shiftwidth=4 tabstop=8 expandtab:
799 * :indentSize=4:tabSize=8:noTabs=true: