Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-kt.c
blobd418631b6b07a360bafaec7652d20a582c2997cc
1 /* packet-kt.c
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
18 #include "config.h"
20 #include <epan/packet.h>
21 #include <epan/prefs.h>
24 void proto_register_kt(void);
25 void proto_reg_handoff_kt(void);
27 static int proto_kt;
30 * A few notes before we get into the thick of things...
32 * Note 1 (Abhik):
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
41 * of the server.
42 * It is possible that the dissection will break under other conditions.
43 * Hopefully, this can be fixed/improved with time.
45 * Note 2 (Abhik):
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
55 * since epoch.
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;
70 /* Sub-trees */
71 static int ett_kt;
72 static int ett_kt_rec;
74 /* Header fields */
75 static int hf_kt_magic;
76 static int hf_kt_type;
77 static int hf_kt_ts;
78 static int hf_kt_flags;
79 static int hf_kt_rnum;
80 static int hf_kt_dbidx;
81 static int hf_kt_sid;
82 static int hf_kt_xt;
83 static int hf_kt_xt_resp;
84 static int hf_kt_ksiz;
85 static int hf_kt_vsiz;
86 static int hf_kt_key;
87 static int hf_kt_val;
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;
94 static int hf_kt_log;
95 static int hf_kt_rec;
97 /* Magic Values */
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" },
114 {0, NULL}
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"},
124 {0, NULL}
127 /* Preferences */
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 */
136 static int
137 dissect_kt_replication_wait(tvbuff_t *tvb, proto_tree *tree, int offset)
139 int new_offset;
140 uint64_t ts;
141 nstime_t ns_ts;
143 new_offset = offset;
145 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
146 new_offset++;
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);
152 new_offset += 8;
154 return new_offset;
157 static int
158 dissect_kt_replication(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
160 int new_offset;
161 uint32_t next32, size;
162 uint64_t ts;
163 nstime_t ns_ts;
164 proto_item *pi;
166 new_offset = offset;
168 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
169 new_offset++;
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);
175 new_offset += 4;
177 proto_tree_add_item(tree, hf_kt_ts, tvb, new_offset, 8, ENC_BIG_ENDIAN);
178 new_offset += 8;
180 proto_tree_add_item(tree, hf_kt_sid, tvb, new_offset, 2, ENC_BIG_ENDIAN);
181 new_offset += 2;
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);
187 new_offset += 8;
189 size = tvb_get_ntohl(tvb, new_offset);
190 proto_tree_add_uint(tree, hf_kt_size, tvb, new_offset, 4, size);
191 new_offset += 4;
193 proto_tree_add_item(tree, hf_kt_log, tvb, new_offset, size, ENC_NA);
194 new_offset += size;
196 } else {
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]");
203 return new_offset;
206 static int
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;
211 proto_item *ti;
212 proto_item *pi;
213 proto_tree *rec_tree;
215 new_offset = offset;
217 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
218 new_offset++;
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);
228 new_offset += 4;
230 rnum = tvb_get_ntohl(tvb, new_offset);
231 proto_tree_add_uint(tree, hf_kt_rnum, tvb, new_offset, 4, rnum);
232 new_offset += 4;
234 while (rnum > 0) {
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);
241 new_offset += 2;
243 ksiz = tvb_get_ntohl(tvb, new_offset);
244 proto_tree_add_uint(rec_tree, hf_kt_ksiz, tvb, new_offset, 4, ksiz);
245 new_offset += 4;
247 vsiz = tvb_get_ntohl(tvb, new_offset);
248 proto_tree_add_uint(rec_tree, hf_kt_vsiz, tvb, new_offset, 4, vsiz);
249 new_offset += 4;
251 proto_tree_add_item(rec_tree, hf_kt_xt, tvb, new_offset, 8, ENC_BIG_ENDIAN);
252 new_offset += 8;
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);
259 new_offset += ksiz;
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);
266 new_offset += vsiz;
268 proto_item_set_len(ti, new_offset - rec_start_offset);
269 rnum--;
271 } else {
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);
278 new_offset += 4;
281 return new_offset;
284 static int
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;
289 proto_item *ti;
290 proto_item *pi;
291 proto_tree *rec_tree;
293 new_offset = offset;
295 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
296 new_offset++;
298 next32 = tvb_get_ntohl(tvb, new_offset);
300 if (next32 == 0) {
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);
307 new_offset += 4;
309 nsiz = tvb_get_ntohl(tvb, new_offset);
310 proto_tree_add_uint(tree, hf_kt_nsiz, tvb, new_offset, 4, nsiz);
311 new_offset += 4;
313 rnum = tvb_get_ntohl(tvb, new_offset);
314 proto_tree_add_uint(tree, hf_kt_rnum, tvb, new_offset, 4, rnum);
315 new_offset += 4;
317 proto_tree_add_item(tree, hf_kt_name, tvb, new_offset, nsiz, ENC_ASCII);
318 new_offset += nsiz;
320 while (rnum > 0) {
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);
328 new_offset += 4;
330 vsiz = tvb_get_ntohl(tvb, new_offset);
331 proto_tree_add_uint(rec_tree, hf_kt_vsiz, tvb, new_offset, 4, vsiz);
332 new_offset += 4;
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);
339 new_offset += ksiz;
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);
346 new_offset += vsiz;
348 proto_item_set_len(ti, new_offset - rec_start_offset);
349 rnum--;
351 } else {
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);
358 new_offset += 4;
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);
367 new_offset += 4;
369 while (rnum > 0) {
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);
377 new_offset += 4;
379 vsiz = tvb_get_ntohl(tvb, new_offset);
380 proto_tree_add_uint(rec_tree, hf_kt_vsiz, tvb, new_offset, 4, vsiz);
381 new_offset += 4;
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);
388 new_offset += ksiz;
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);
395 new_offset += vsiz;
397 proto_item_set_len(ti, new_offset - rec_start_offset);
398 rnum--;
402 return new_offset;
405 static int
406 dissect_kt_get_bulk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
408 uint32_t next32, rnum, ksiz, vsiz;
409 uint64_t xt;
410 nstime_t ts;
411 int new_offset, rec_start_offset;
412 proto_item *ti;
413 proto_item *pi;
414 proto_tree *rec_tree;
416 new_offset = offset;
418 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
419 new_offset++;
421 next32 = tvb_get_ntohl(tvb, new_offset);
423 if (next32 == 0) {
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);
429 new_offset += 4;
431 rnum = tvb_get_ntohl(tvb, new_offset);
432 proto_tree_add_uint(tree, hf_kt_rnum, tvb, new_offset, 4, rnum);
433 new_offset += 4;
435 while (rnum > 0) {
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);
442 new_offset += 2;
444 ksiz = tvb_get_ntohl(tvb, new_offset);
445 proto_tree_add_uint(rec_tree, hf_kt_ksiz, tvb, new_offset, 4, ksiz);
446 new_offset += 4;
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);
453 new_offset += ksiz;
455 proto_item_set_len(ti, new_offset - rec_start_offset);
456 rnum--;
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);
464 new_offset += 4;
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);
473 new_offset += 4;
475 while (rnum > 0) {
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);
482 new_offset += 2;
484 ksiz = tvb_get_ntohl(tvb, new_offset);
485 proto_tree_add_uint(rec_tree, hf_kt_ksiz, tvb, new_offset, 4, ksiz);
486 new_offset += 4;
488 vsiz = tvb_get_ntohl(tvb, new_offset);
489 proto_tree_add_uint(rec_tree, hf_kt_vsiz, tvb, new_offset, 4, vsiz);
490 new_offset += 4;
492 xt = tvb_get_ntoh64(tvb, new_offset);
493 ts.secs = (time_t)(xt&0xFFFFFFFF);
494 ts.nsecs = 0;
495 proto_tree_add_time(rec_tree, hf_kt_xt_resp, tvb, new_offset, 8, &ts);
496 new_offset += 8;
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);
503 new_offset += ksiz;
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);
510 new_offset += vsiz;
512 proto_item_set_len(ti, new_offset - rec_start_offset);
513 rnum--;
517 return new_offset;
520 static int
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;
525 proto_item *ti;
526 proto_item *pi;
527 proto_tree *rec_tree;
529 new_offset = offset;
531 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
532 new_offset++;
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);
541 new_offset += 4;
543 rnum = tvb_get_ntohl(tvb, new_offset);
544 proto_tree_add_uint(tree, hf_kt_rnum, tvb, new_offset, 4, rnum);
545 new_offset += 4;
547 while (rnum > 0) {
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);
554 new_offset += 2;
556 ksiz = tvb_get_ntohl(tvb, new_offset);
557 proto_tree_add_uint(rec_tree, hf_kt_ksiz, tvb, new_offset, 4, ksiz);
558 new_offset += 4;
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);
565 new_offset += ksiz;
567 proto_item_set_len(ti, new_offset - rec_start_offset);
568 rnum--;
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);
576 new_offset += 4;
579 return new_offset;
582 static int
583 dissect_kt_error(tvbuff_t *tvb, proto_tree *tree, int offset)
585 int new_offset;
587 new_offset = offset;
589 proto_tree_add_item(tree, hf_kt_magic, tvb, new_offset, 1, ENC_BIG_ENDIAN);
590 new_offset++;
592 return new_offset;
595 static int
596 dissect_kt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
598 int magic;
599 proto_item *ti;
600 proto_tree *kt_tree;
601 int offset, offset_start;
603 offset = 0;
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)
610 return offset;
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);
619 offset_start=offset;
621 switch (magic) {
622 case KT_MAGIC_REPL_WAIT:
623 offset = dissect_kt_replication_wait(tvb, kt_tree, offset);
624 break;
625 case KT_MAGIC_REPLICATION:
626 offset = dissect_kt_replication(tvb, pinfo, kt_tree, offset);
627 break;
628 case KT_MAGIC_PLAY_SCRIPT:
629 offset = dissect_kt_play_script(tvb, pinfo, kt_tree, offset);
630 break;
631 case KT_MAGIC_SET_BULK:
632 offset = dissect_kt_set_bulk(tvb, pinfo, kt_tree, offset);
633 break;
634 case KT_MAGIC_REMOVE_BULK:
635 offset = dissect_kt_remove_bulk(tvb, pinfo, kt_tree, offset);
636 break;
637 case KT_MAGIC_GET_BULK:
638 offset = dissect_kt_get_bulk(tvb, pinfo, kt_tree, offset);
639 break;
640 case KT_MAGIC_ERROR:
641 offset = dissect_kt_error(tvb, kt_tree, offset);
642 break;
645 proto_item_set_len(ti, offset-offset_start);
648 return tvb_captured_length(tvb);
651 void
652 proto_register_kt(void)
654 module_t *kt_module; /* preferences */
656 static hf_register_info hf[] = {
657 { &hf_kt_magic,
658 { "magic", "kt.magic", FT_UINT8, BASE_HEX,
659 VALS(kt_magic_vals), 0x0, "identifier", HFILL
662 { &hf_kt_type,
663 { "type", "kt.type", FT_UINT8, BASE_HEX,
664 VALS(kt_oper_vals), 0x0, "request/response", HFILL
667 { &hf_kt_flags,
668 { "flags", "kt.flags", FT_UINT32, BASE_HEX,
669 NULL, 0x0, "flags of bitwise-or", HFILL
672 { &hf_kt_rnum,
673 { "rnum", "kt.rnum", FT_UINT32, BASE_DEC, NULL, 0x0,
674 "the number of records", HFILL
677 { &hf_kt_dbidx,
678 { "dbidx", "kt.dbidx", FT_UINT16,
679 BASE_DEC, NULL, 0x0, "the index of the target database", HFILL
682 { &hf_kt_sid,
683 { "sid", "kt.sid", FT_UINT16, BASE_DEC,
684 NULL, 0x0, "the server ID number", HFILL
687 { &hf_kt_ts,
688 { "ts", "kt.ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
689 NULL, 0x0, "the timestamp of the log", HFILL
692 { &hf_kt_xt,
693 { "xt", "kt.xt", FT_UINT64, BASE_DEC,
694 NULL, 0x0, "the expiration time in seconds", HFILL
697 { &hf_kt_xt_resp,
698 { "xt", "kt.xt_resp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
699 NULL, 0x0, "the expiration time", HFILL
702 { &hf_kt_ksiz,
703 { "ksiz", "kt.ksiz", FT_UINT32, BASE_DEC,
704 NULL, 0x0, "the size of the key",HFILL
707 { &hf_kt_vsiz,
708 { "vsiz", "kt.vsiz", FT_UINT32, BASE_DEC,
709 NULL, 0x0, "the size of the value", HFILL
712 { &hf_kt_key,
713 { "key", "kt.key", FT_BYTES, BASE_NONE,
714 NULL, 0x0, "the key", HFILL
717 { &hf_kt_val,
718 { "value", "kt.value", FT_BYTES, BASE_NONE,
719 NULL, 0x0, "the value", HFILL
722 { &hf_kt_key_str,
723 { "key", "kt.key_str", FT_STRING, BASE_NONE,
724 NULL, 0x0, "ASCII representation of the key", HFILL
727 { &hf_kt_val_str,
728 { "value", "kt.value_str", FT_STRING, BASE_NONE,
729 NULL, 0x0, "ASCII representation of the value", HFILL
732 { &hf_kt_hits,
733 { "hits", "kt.hits", FT_UINT32, BASE_DEC,
734 NULL, 0x0, "the number of records", HFILL
737 { &hf_kt_size,
738 { "size", "kt.size", FT_UINT32, BASE_DEC,
739 NULL, 0x0, "the size of the replication log", HFILL
742 { &hf_kt_log,
743 { "log", "kt.log", FT_BYTES, BASE_NONE,
744 NULL, 0x0, "the replication log", HFILL
747 { &hf_kt_nsiz,
748 { "nsiz", "kt.nsiz", FT_UINT32, BASE_DEC,
749 NULL, 0x0, "the size of the procedure name", HFILL
752 { &hf_kt_name,
753 { "name", "kt.name", FT_STRING, BASE_NONE,
754 NULL, 0x0, "the procedure name", HFILL
757 { &hf_kt_rec,
758 { "record", "kt.record", FT_NONE, BASE_NONE,
759 NULL, 0x0, "a record", HFILL
764 static int *ett[] = {
765 &ett_kt,
766 &ett_kt_rec
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));
774 /* Preferences */
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);
783 void
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
792 * Local variables:
793 * c-basic-offset: 4
794 * tab-width: 8
795 * indent-tabs-mode: nil
796 * End:
798 * vi: set shiftwidth=4 tabstop=8 expandtab:
799 * :indentSize=4:tabSize=8:noTabs=true: