Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-cql.c
blobc9c831c9c5060c94be913bbff535f9830331e800
1 /* packet-cql.c
2 * Routines for Apache Cassandra CQL dissection
3 * Copyright 2015, Aaron Ten Clay <aarontc@aarontc.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * CQL V3 reference: https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v3.spec
14 * CQL V4 reference: https://github.com/apache/cassandra/blob/trunk/doc/native_protocol_v4.spec
16 #include "config.h"
17 #include <epan/conversation.h>
18 #include <epan/packet.h>
19 #include "packet-tcp.h"
20 #include <epan/wmem_scopes.h>
21 #include <epan/expert.h>
22 #include <epan/to_str.h>
23 #include <epan/addr_resolv.h>
24 #ifdef HAVE_LZ4
25 #include <lz4.h>
26 #endif
27 #ifdef HAVE_SNAPPY
28 #include <snappy-c.h>
29 #endif
31 #define CQL_DEFAULT_PORT 9042 /* Not IANA registered */
33 /* the code can reasonably attempt to decompress buffer up to 10MB */
34 #define MAX_UNCOMPRESSED_SIZE (10 * 1024 * 1024)
36 void proto_reg_handoff_cql(void);
37 void proto_register_cql(void);
39 static int proto_cql;
40 /* CQL header frame fields */
41 static int hf_cql_version;
42 static int hf_cql_protocol_version;
43 static int hf_cql_direction;
44 /* CQL header frame fields */
45 static int hf_cql_flags_bitmap;
46 static int hf_cql_flag_compression;
47 static int hf_cql_flag_tracing;
48 static int hf_cql_flag_reserved3;
49 static int hf_cql_flag_custom_payload;
50 static int hf_cql_flag_warning;
51 static int hf_cql_flag_reserved4;
52 static int hf_cql_stream;
53 static int hf_cql_opcode;
54 static int hf_cql_length;
55 /* CQL data types */
57 static int hf_cql_int;
58 static int hf_cql_long;
59 static int hf_cql_uuid;
60 static int hf_cql_bytes;
61 static int hf_cql_inet;
63 /* Batch flags */
65 static int hf_cql_batch_flag_serial_consistency;
66 static int hf_cql_batch_flag_default_timestamp;
67 static int hf_cql_batch_flag_with_name_for_values;
68 static int hf_cql_batch_flags_bitmap;
69 static int ett_cql_batch_flags_bitmap;
71 static int hf_cql_consistency;
72 static int hf_cql_string_length;
73 static int hf_cql_string_map_size;
74 static int hf_cql_string;
75 static int hf_cql_auth_token;
76 static int hf_cql_value_count;
77 static int hf_cql_short_bytes_length;
78 static int hf_cql_bytes_length;
79 static int hf_cql_bytes;
80 static int hf_cql_bigint;
81 static int hf_cql_scale;
82 static int hf_cql_boolean;
83 static int hf_cql_ascii;
84 static int hf_cql_double;
85 static int hf_cql_float;
86 static int hf_cql_custom;
87 static int hf_cql_null_value;
88 static int hf_cql_int;
89 static int hf_cql_uuid;
90 static int hf_cql_tracing_uuid;
91 static int hf_cql_port;
92 static int hf_cql_timeuuid;
93 static int hf_cql_varchar;
94 static int hf_cql_varint_count8;
95 static int hf_cql_varint_count16;
96 static int hf_cql_varint_count32;
97 static int hf_cql_varint_count64;
98 static int hf_cql_raw_compressed_bytes;
99 static int hf_cql_paging_state;
100 static int hf_cql_page_size;
101 static int hf_cql_timestamp;
102 static int hf_cql_query_id;
103 static int hf_cql_event_type;
104 static int hf_cql_event_schema_change_type;
105 static int hf_cql_event_schema_change_type_target;
106 static int hf_cql_event_schema_change_keyspace;
107 static int hf_cql_event_schema_change_object;
108 static int hf_cql_result_timestamp;
109 static int hf_cql_string_list_size;
110 static int hf_cql_batch_type;
111 static int hf_cql_batch_query_type;
112 static int hf_cql_batch_query_size;
113 static int hf_cql_error_code;
114 static int hf_cql_result_kind;
115 static int hf_cql_result_rows_data_type;
117 static int hf_cql_query_flags_bitmap;
118 static int hf_cql_query_flags_values;
119 static int hf_cql_query_flags_skip_metadata;
120 static int hf_cql_query_flags_page_size;
121 static int hf_cql_query_flags_paging_state;
122 static int hf_cql_query_flags_serial_consistency;
123 static int hf_cql_query_flags_default_timestamp;
124 static int hf_cql_query_flags_names_for_values;
125 static int hf_cql_query_flags_reserved3;
127 static int hf_cql_result_rows_flags_values;
128 static int hf_cql_result_prepared_flags_values;
129 static int hf_cql_result_rows_flag_global_tables_spec;
130 static int hf_cql_result_rows_flag_has_more_pages;
131 static int hf_cql_result_rows_flag_no_metadata;
132 static int hf_cql_result_rows_column_count;
133 static int hf_cql_result_rows_tuple_size;
135 static int hf_cql_result_prepared_pk_count;
137 static int hf_cql_string_result_rows_global_table_spec_ksname;
138 static int hf_cql_string_result_rows_global_table_spec_table_name;
139 static int hf_cql_string_result_rows_table_name;
140 static int hf_cql_string_result_rows_keyspace_name;
141 static int hf_cql_string_result_rows_column_name;
142 static int hf_cql_result_rows_row_count;
143 static int hf_cql_string_result_rows_udt_name;
144 static int hf_cql_string_result_rows_udt_size;
145 static int hf_cql_string_result_rows_udt_field_name;
146 static int hf_cql_string_result_rows_list_size;
147 static int hf_cql_string_result_rows_map_size;
148 static int hf_cql_string_result_rows_set_size;
149 static int hf_cql_bytesmap_string;
151 static int ett_cql_protocol;
152 static int ett_cql_version;
153 static int ett_cql_message;
154 static int ett_cql_result_columns;
155 static int ett_cql_results_no_metadata;
156 static int ett_cql_result_map;
157 static int ett_cql_result_set;
158 static int ett_cql_result_metadata;
159 static int ett_cql_result_rows;
160 static int ett_cql_result_metadata_colspec;
161 static int ett_cql_header_flags_bitmap;
162 static int ett_cql_query_flags_bitmap;
163 static int ett_cql_custom_payload;
165 static int hf_cql_response_in;
166 static int hf_cql_response_to;
167 static int hf_cql_response_time;
169 static int hf_cql_ipv4;
170 static int hf_cql_ipv6;
172 /* desegmentation of CQL */
173 static bool cql_desegment = true;
175 static expert_field ei_cql_data_not_dissected_yet;
176 static expert_field ei_cql_unexpected_negative_value;
179 typedef struct _cql_transaction_type {
180 uint32_t req_frame;
181 uint32_t rep_frame;
182 nstime_t req_time;
183 } cql_transaction_type;
185 typedef struct _cql_conversation_info_type {
186 wmem_map_t* streams;
187 } cql_conversation_type;
189 static const value_string cql_direction_names[] = {
190 { 0x0, "Request" },
191 { 0x8, "Response" },
192 { 0x0, NULL }
195 typedef enum {
196 CQL_BATCH_FLAG_SERIAL_CONSISTENCY = 0x10,
197 CQL_BATCH_FLAG_DEFAULT_TIMESTAMP = 0x20,
198 CQL_BATCH_FLAG_WITH_NAME_FOR_VALUES = 0x40
199 } cql_batch_flags;
201 typedef enum {
202 CQL_OPCODE_ERROR = 0x00,
203 CQL_OPCODE_STARTUP = 0x01,
204 CQL_OPCODE_READY = 0x02,
205 CQL_OPCODE_AUTHENTICATE = 0x03,
206 /* Opcode 0x04 not used in CQL */
207 CQL_OPCODE_OPTIONS = 0x05,
208 CQL_OPCODE_SUPPORTED = 0x06,
209 CQL_OPCODE_QUERY = 0x07,
210 CQL_OPCODE_RESULT = 0x08,
211 CQL_OPCODE_PREPARE = 0x09,
212 CQL_OPCODE_EXECUTE = 0x0A,
213 CQL_OPCODE_REGISTER = 0x0B,
214 CQL_OPCODE_EVENT = 0x0C,
215 CQL_OPCODE_BATCH = 0x0D,
216 CQL_OPCODE_AUTH_CHALLENGE = 0x0E,
217 CQL_OPCODE_AUTH_RESPONSE = 0x0F,
218 CQL_OPCODE_AUTH_SUCCESS = 0x10
219 } cql_opcode_type;
221 static const value_string cql_opcode_names[] = {
222 { CQL_OPCODE_ERROR, "ERROR" },
223 { CQL_OPCODE_STARTUP, "STARTUP" },
224 { CQL_OPCODE_READY, "READY" },
225 { CQL_OPCODE_AUTHENTICATE, "AUTHENTICATE" },
226 { CQL_OPCODE_OPTIONS, "OPTIONS" },
227 { CQL_OPCODE_SUPPORTED, "SUPPORTED" },
228 { CQL_OPCODE_QUERY, "QUERY" },
229 { CQL_OPCODE_RESULT, "RESULT" },
230 { CQL_OPCODE_PREPARE, "PREPARE" },
231 { CQL_OPCODE_EXECUTE, "EXECUTE" },
232 { CQL_OPCODE_REGISTER, "REGISTER" },
233 { CQL_OPCODE_EVENT, "EVENT" },
234 { CQL_OPCODE_BATCH, "BATCH" },
235 { CQL_OPCODE_AUTH_CHALLENGE, "AUTH_CHALLENGE" },
236 { CQL_OPCODE_AUTH_RESPONSE, "AUTH_RESPONSE" },
237 { CQL_OPCODE_AUTH_SUCCESS, "AUTH_SUCCESS" },
238 { 0x00, NULL }
242 typedef enum {
243 CQL_HEADER_FLAG_COMPRESSION = 0x01,
244 CQL_HEADER_FLAG_TRACING = 0x02,
245 CQL_HEADER_FLAG_V3_RESERVED = 0xFC,
246 CQL_HEADER_FLAG_CUSTOM_PAYLOAD = 0x04,
247 CQL_HEADER_FLAG_WARNING = 0x08,
248 CQL_HEADER_FLAG_V4_RESERVED = 0xF0
249 } cql_flags;
251 typedef enum {
252 CQL_QUERY_FLAG_VALUES = 0x01,
253 CQL_QUERY_FLAG_SKIP_METADATA = 0x02,
254 CQL_QUERY_FLAG_PAGE_SIZE = 0x04,
255 CQL_QUERY_FLAG_PAGING_STATE = 0x08,
256 CQL_QUERY_FLAG_SERIAL_CONSISTENCY = 0x10,
257 CQL_QUERY_FLAG_DEFAULT_TIMESTAMP = 0x20,
258 CQL_QUERY_FLAG_VALUE_NAMES = 0x40,
259 CQL_QUERY_FLAG_V3_RESERVED = 0x80
260 } cql_query_flags;
263 typedef enum {
264 CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC = 0x00000001,
265 CQL_RESULT_ROWS_FLAG_HAS_MORE_PAGES = 0x00000002,
266 CQL_RESULT_ROWS_FLAG_NO_METADATA = 0x00000004
267 } cql_result_rows_flags;
269 typedef enum {
270 CQL_CONSISTENCY_ANY = 0x0000,
271 CQL_CONSISTENCY_ONE = 0x0001,
272 CQL_CONSISTENCY_TWO = 0x0002,
273 CQL_CONSISTENCY_THREE = 0x003,
274 CQL_CONSISTENCY_QUORUM = 0x0004,
275 CQL_CONSISTENCY_ALL = 0x0005,
276 CQL_CONSISTENCY_LOCAL_QUORUM = 0x0006,
277 CQL_CONSISTENCY_EACH_QUORUM = 0x0007,
278 CQL_CONSISTENCY_SERIAL = 0x0008,
279 CQL_CONSISTENCY_LOCAL_SERIAL = 0x0009,
280 CQL_CONSISTENCY_LOCAL_ONE = 0x000A
281 } cql_consistencies;
283 static const value_string cql_consistency_names[] = {
284 { CQL_CONSISTENCY_ANY, "ANY" },
285 { CQL_CONSISTENCY_ONE, "ONE" },
286 { CQL_CONSISTENCY_TWO, "TWO" },
287 { CQL_CONSISTENCY_THREE, "THREE" },
288 { CQL_CONSISTENCY_QUORUM, "QUORUM" },
289 { CQL_CONSISTENCY_ALL, "ALL" },
290 { CQL_CONSISTENCY_LOCAL_QUORUM, "LOCAL_QUORUM" },
291 { CQL_CONSISTENCY_EACH_QUORUM, "EACH_QUORUM" },
292 { CQL_CONSISTENCY_SERIAL, "SERIAL" },
293 { CQL_CONSISTENCY_LOCAL_SERIAL, "LOCAL_SERIAL" },
294 { CQL_CONSISTENCY_LOCAL_ONE, "LOCAL_ONE" },
295 { 0x00, NULL }
299 typedef enum {
300 CQL_BATCH_TYPE_LOGGED = 0,
301 CQL_BATCH_TYPE_UNLOGGED = 1,
302 CQL_BATCH_TYPE_COUNTER = 2
303 } cql_batch_types;
305 static const value_string cql_batch_type_names[] = {
306 { CQL_BATCH_TYPE_LOGGED, "LOGGED" },
307 { CQL_BATCH_TYPE_UNLOGGED, "UNLOGGED" },
308 { CQL_BATCH_TYPE_COUNTER, "COUNTER" },
309 { 0x00, NULL }
312 typedef enum {
313 CQL_BATCH_QUERY_TYPE_QUERY = 0,
314 CQL_BATCH_QUERY_TYPE_PREPARED = 1
315 } cql_batch_query_types;
317 static const value_string cql_batch_query_type_names[] = {
318 { CQL_BATCH_QUERY_TYPE_QUERY, "QUERY" },
319 { CQL_BATCH_QUERY_TYPE_PREPARED, "PREPARED" },
320 { 0x00, NULL }
323 typedef enum {
324 CQL_RESULT_KIND_VOID = 0x0001,
325 CQL_RESULT_KIND_ROWS = 0x0002,
326 CQL_RESULT_KIND_SET_KEYSPACE = 0x0003,
327 CQL_RESULT_KIND_PREPARED = 0x0004,
328 CQL_RESULT_KIND_SCHEMA_CHANGE = 0x0005
329 } cql_result_kinds;
331 static const value_string cql_result_kind_names[] = {
332 { CQL_RESULT_KIND_VOID, "VOID" },
333 { CQL_RESULT_KIND_ROWS, "Rows" },
334 { CQL_RESULT_KIND_SET_KEYSPACE, "Set Keyspace" },
335 { CQL_RESULT_KIND_PREPARED, "Prepared" },
336 { CQL_RESULT_KIND_SCHEMA_CHANGE, "Schema Change" },
337 { 0x00, NULL }
342 typedef enum {
343 CQL_RESULT_ROW_TYPE_CUSTOM = 0x0000,
344 CQL_RESULT_ROW_TYPE_ASCII = 0x0001,
345 CQL_RESULT_ROW_TYPE_BIGINT = 0x0002,
346 CQL_RESULT_ROW_TYPE_BLOB = 0x0003,
347 CQL_RESULT_ROW_TYPE_BOOLEAN = 0x0004,
348 CQL_RESULT_ROW_TYPE_COUNTER = 0x0005,
349 CQL_RESULT_ROW_TYPE_DECIMAL = 0x0006,
350 CQL_RESULT_ROW_TYPE_DOUBLE = 0x0007,
351 CQL_RESULT_ROW_TYPE_FLOAT = 0x0008,
352 CQL_RESULT_ROW_TYPE_INT = 0x0009,
353 CQL_RESULT_ROW_TYPE_TIMESTAMP = 0x000B,
354 CQL_RESULT_ROW_TYPE_UUID = 0x000C,
355 CQL_RESULT_ROW_TYPE_VARCHAR = 0x000D,
356 CQL_RESULT_ROW_TYPE_VARINT = 0x000E,
357 CQL_RESULT_ROW_TYPE_TIMEUUID = 0x000F,
358 CQL_RESULT_ROW_TYPE_INET = 0x0010,
359 CQL_RESULT_ROW_TYPE_DATE = 0x0011,
360 CQL_RESULT_ROW_TYPE_TIME = 0x0012,
361 CQL_RESULT_ROW_TYPE_SMALLINT = 0x0013,
362 CQL_RESULT_ROW_TYPE_TINYINT = 0x0014,
363 CQL_RESULT_ROW_TYPE_LIST = 0x0020,
364 CQL_RESULT_ROW_TYPE_MAP = 0x0021,
365 CQL_RESULT_ROW_TYPE_SET = 0x0022,
366 CQL_RESULT_ROW_TYPE_UDT = 0x0030,
367 CQL_RESULT_ROW_TYPE_TUPLE = 0x0031
368 } cql_result_row_data_types;
370 static const value_string cql_result_row_type_names[] = {
371 { CQL_RESULT_ROW_TYPE_CUSTOM, "CUSTOM" },
372 { CQL_RESULT_ROW_TYPE_ASCII, "ASCII" },
373 { CQL_RESULT_ROW_TYPE_BIGINT, "BIGINT" },
374 { CQL_RESULT_ROW_TYPE_BLOB, "BLOB" },
375 { CQL_RESULT_ROW_TYPE_BOOLEAN, "BOOLEAN" },
376 { CQL_RESULT_ROW_TYPE_COUNTER, "COUNTER" },
377 { CQL_RESULT_ROW_TYPE_DECIMAL, "DECIMAL" },
378 { CQL_RESULT_ROW_TYPE_DOUBLE, "DOUBLE" },
379 { CQL_RESULT_ROW_TYPE_FLOAT, "FLOAT" },
380 { CQL_RESULT_ROW_TYPE_INT, "INT" },
381 { CQL_RESULT_ROW_TYPE_TIMESTAMP, "TIMESTAMP" },
382 { CQL_RESULT_ROW_TYPE_UUID, "UUID" },
383 { CQL_RESULT_ROW_TYPE_VARCHAR, "VARCHAR" },
384 { CQL_RESULT_ROW_TYPE_VARINT, "VARINT" },
385 { CQL_RESULT_ROW_TYPE_TIMEUUID, "TIMEUUID" },
386 { CQL_RESULT_ROW_TYPE_INET, "INET" },
387 { CQL_RESULT_ROW_TYPE_DATE, "DATE" },
388 { CQL_RESULT_ROW_TYPE_TIME, "TIME" },
389 { CQL_RESULT_ROW_TYPE_SMALLINT, "SMALLINT" },
390 { CQL_RESULT_ROW_TYPE_TINYINT, "TINYINT" },
391 { CQL_RESULT_ROW_TYPE_LIST, "LIST" },
392 { CQL_RESULT_ROW_TYPE_MAP, "MAP" },
393 { CQL_RESULT_ROW_TYPE_SET, "SET" },
394 { CQL_RESULT_ROW_TYPE_UDT, "UDT" },
395 { CQL_RESULT_ROW_TYPE_TUPLE, "TUPLE" },
396 { 0x0, NULL }
399 /* From https://github.com/apache/cassandra/blob/cbf4dcb3345c7e2f42f6a897c66b6460b7acc2ca/doc/native_protocol_v4.spec#L1046 */
400 typedef enum {
401 CQL_ERROR_SERVER = 0x0000,
402 CQL_ERROR_PROTOCOL = 0x000A,
403 CQL_ERROR_AUTH = 0x0100,
404 CQL_ERROR_UNAVAILABLE = 0x1000,
405 CQL_ERROR_OVERLOADED = 0x1001,
406 CQL_ERROR_BOOTSTRAPPING = 0x1002,
407 CQL_ERROR_TRUNCATE = 0x1003,
408 CQL_ERROR_WRITE_TIMEOUT = 0x1100,
409 CQL_ERROR_READ_TIMEOUT = 0x1200,
410 CQL_ERROR_READ_FAILURE = 0x1300,
411 CQL_ERROR_FUNCTION_FAILURE = 0x1400,
412 CQL_ERROR_WRITE_FAILURE = 0x1500,
413 CQL_ERROR_SYNTAX = 0x2000,
414 CQL_ERROR_UNAUTHORIEZED = 0x2100,
415 CQL_ERROR_INVALID = 0x2200,
416 CQL_ERROR_CONFIG = 0x2300,
417 CQL_ERROR_ALREADY_EXISTS = 0x2400,
418 CQL_ERROR_UNPREPARED = 0x2500
419 } cql_error_types;
421 static const value_string cql_error_names[] = {
422 { CQL_ERROR_SERVER, "Server error" },
423 { CQL_ERROR_PROTOCOL, "Protocol error" },
424 { CQL_ERROR_AUTH, "Authentication error" },
425 { CQL_ERROR_UNAVAILABLE, "Unavailable exception" },
426 { CQL_ERROR_OVERLOADED, "Overloaded" },
427 { CQL_ERROR_BOOTSTRAPPING, "Is_bootstrapping" },
428 { CQL_ERROR_TRUNCATE, "Truncate_error" },
429 { CQL_ERROR_WRITE_TIMEOUT, "Write_timeout" },
430 { CQL_ERROR_READ_TIMEOUT, "Read_timeout" },
431 { CQL_ERROR_READ_FAILURE, "Read_failure" },
432 { CQL_ERROR_FUNCTION_FAILURE, "Function_failure" },
433 { CQL_ERROR_WRITE_FAILURE, "Write_failure" },
434 { CQL_ERROR_SYNTAX, "Syntax_error" },
435 { CQL_ERROR_UNAUTHORIEZED, "Unauthorized" },
436 { CQL_ERROR_INVALID, "Invalid" },
437 {CQL_ERROR_CONFIG, "Config_error" },
438 { CQL_ERROR_ALREADY_EXISTS, "Already_exists" },
439 { CQL_ERROR_UNPREPARED, "Unprepared" },
440 { 0x0, NULL}
443 static int
444 dissect_cql_query_parameters(proto_tree* cql_subtree, tvbuff_t* tvb, int offset, int execute)
446 int32_t bytes_length = 0;
447 uint32_t flags = 0;
448 uint64_t i = 0;
449 uint32_t string_length = 0;
450 uint32_t value_count = 0;
452 static int * const cql_query_bitmaps[] = {
453 &hf_cql_query_flags_values,
454 &hf_cql_query_flags_skip_metadata,
455 &hf_cql_query_flags_page_size,
456 &hf_cql_query_flags_paging_state,
457 &hf_cql_query_flags_serial_consistency,
458 &hf_cql_query_flags_default_timestamp,
459 &hf_cql_query_flags_names_for_values,
460 &hf_cql_query_flags_reserved3,
461 NULL
464 /* consistency */
465 proto_tree_add_item(cql_subtree, hf_cql_consistency, tvb, offset, 2, ENC_BIG_ENDIAN);
466 offset += 2;
468 /* flags */
469 proto_tree_add_bitmask(cql_subtree, tvb, offset, hf_cql_query_flags_bitmap, ett_cql_query_flags_bitmap, cql_query_bitmaps, ENC_BIG_ENDIAN);
470 flags = tvb_get_uint8(tvb, offset);
471 offset += 1;
473 if(flags & CQL_QUERY_FLAG_VALUES) {
474 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &value_count);
475 offset += 2;
476 for (i = 0; i < value_count; ++i) {
477 if (!execute && flags & CQL_QUERY_FLAG_VALUE_NAMES) {
478 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
479 offset += 2;
480 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
481 offset += string_length;
483 proto_tree_add_item_ret_int(cql_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
484 offset += 4;
485 if (bytes_length > 0) {
486 proto_tree_add_item(cql_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
487 offset += bytes_length;
492 if (flags & CQL_QUERY_FLAG_PAGE_SIZE) {
493 proto_tree_add_item(cql_subtree, hf_cql_page_size, tvb, offset, 4, ENC_BIG_ENDIAN);
494 offset += 4;
497 if (flags & CQL_QUERY_FLAG_PAGING_STATE) {
498 proto_tree_add_item_ret_int(cql_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
499 offset += 4;
500 if (bytes_length > 0) {
501 proto_tree_add_item(cql_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
502 offset += bytes_length;
506 if (flags & CQL_QUERY_FLAG_SERIAL_CONSISTENCY) {
507 proto_tree_add_item(cql_subtree, hf_cql_consistency, tvb, offset, 2, ENC_BIG_ENDIAN);
508 offset += 2;
511 if (flags & CQL_QUERY_FLAG_DEFAULT_TIMESTAMP) {
512 proto_tree_add_item(cql_subtree, hf_cql_timestamp, tvb, offset, 8, ENC_TIME_USECS|ENC_BIG_ENDIAN);
513 offset += 8;
516 return offset;
519 static unsigned
520 get_cql_pdu_len(packet_info* pinfo _U_, tvbuff_t* tvb, int offset, void* data _U_)
522 /* CQL has 32-bit length at 5th byte in frame. */
523 uint32_t length = tvb_get_ntohl(tvb, offset + 5);
525 /* Include length of frame header. */
526 return length + 9;
529 static cql_transaction_type*
530 cql_transaction_add_request(cql_conversation_type* conv,
531 packet_info* pinfo,
532 int32_t stream,
533 int fake)
535 cql_transaction_type* trans;
536 wmem_list_t* list;
538 list = (wmem_list_t*)wmem_map_lookup(conv->streams, GINT_TO_POINTER(stream));
539 if(!list) {
540 list = wmem_list_new(wmem_file_scope());
541 } else {
542 wmem_map_remove(conv->streams, GINT_TO_POINTER(stream));
545 trans = wmem_new(wmem_file_scope(), cql_transaction_type);
546 if (fake) {
547 trans->req_frame = 0;
548 } else {
549 trans->req_frame = pinfo->fd->num;
551 trans->rep_frame = 0;
552 trans->req_time = pinfo->abs_ts;
554 wmem_list_append(list, (void *)trans);
555 wmem_map_insert(conv->streams, GINT_TO_POINTER(stream), (void*)list);
557 return trans;
560 static cql_transaction_type*
561 cql_enrich_transaction_with_response(cql_conversation_type* conv,
562 packet_info* pinfo,
563 int32_t stream)
565 cql_transaction_type* trans;
566 wmem_list_frame_t* frame;
567 wmem_list_t* list;
569 list = (wmem_list_t*)wmem_map_lookup(conv->streams, GINT_TO_POINTER(stream));
570 if (!list) {
571 return NULL;
574 frame = wmem_list_tail(list);
575 if (!frame) {
576 return NULL;
579 trans = (cql_transaction_type *)wmem_list_frame_data(frame);
580 if (!trans) {
581 return NULL;
584 trans->rep_frame = pinfo->fd->num;
586 return trans;
589 static cql_transaction_type*
590 cql_transaction_lookup(cql_conversation_type* conv,
591 packet_info* pinfo,
592 int32_t stream)
594 wmem_list_frame_t* frame;
595 wmem_list_t* list;
597 list = (wmem_list_t*)wmem_map_lookup(conv->streams, GINT_TO_POINTER(stream));
598 if (!list) {
599 return NULL;
602 frame = wmem_list_head(list);
603 if (!frame) {
604 return NULL;
607 do {
608 cql_transaction_type* trans = NULL;
609 trans = (cql_transaction_type *)wmem_list_frame_data(frame);
610 if (trans->req_frame == pinfo->fd->num || trans->rep_frame == pinfo->fd->num) {
611 return trans;
613 } while ((frame = wmem_list_frame_next(frame)));
615 return NULL;
618 typedef enum {
619 CQL_COMPRESSION_NONE = 0,
620 CQL_COMPRESSION_LZ4 = 1,
621 CQL_COMPRESSION_SNAPPY = 2,
622 CQL_DECOMPRESSION_ATTEMPTED = 3,
623 } cql_compression_level;
626 // NOLINTNEXTLINE(misc-no-recursion)
627 static int parse_option(proto_tree* metadata_subtree, packet_info *pinfo, tvbuff_t* tvb, int offset)
629 uint32_t data_type = 0;
630 uint32_t string_length = 0;
631 uint32_t tuple_size = 0;
632 uint32_t udt_size = 0;
633 uint32_t i = 0;
635 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_data_type, tvb, offset, 2, ENC_BIG_ENDIAN, &data_type);
636 offset += 2;
637 increment_dissection_depth(pinfo);
638 switch (data_type) {
639 case CQL_RESULT_ROW_TYPE_LIST:
640 offset = parse_option(metadata_subtree, pinfo, tvb, offset);
641 break;
642 case CQL_RESULT_ROW_TYPE_MAP:
643 offset = parse_option(metadata_subtree, pinfo, tvb, offset);
644 offset = parse_option(metadata_subtree, pinfo, tvb, offset);
645 break;
646 case CQL_RESULT_ROW_TYPE_SET:
647 offset = parse_option(metadata_subtree, pinfo, tvb, offset);
648 break;
649 case CQL_RESULT_ROW_TYPE_UDT:
650 /* keyspace */
651 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
652 offset += 2;
653 proto_tree_add_item(metadata_subtree, hf_cql_string_result_rows_keyspace_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
654 offset += string_length;
656 /* UDT name */
657 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
658 offset += 2;
659 proto_tree_add_item(metadata_subtree, hf_cql_string_result_rows_udt_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
660 offset += string_length;
662 /* UDT size */
663 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_result_rows_udt_size, tvb, offset, 2, ENC_BIG_ENDIAN, &udt_size);
664 offset += 2;
666 for (i = 0; i < udt_size; i++) {
667 /* UDT field name */
668 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
669 offset += 2;
670 proto_tree_add_item(metadata_subtree, hf_cql_string_result_rows_udt_field_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
671 offset += string_length;
673 /* UDT field option */
674 offset = parse_option(metadata_subtree, pinfo, tvb, offset);
676 break;
677 case CQL_RESULT_ROW_TYPE_TUPLE:
678 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_tuple_size, tvb, offset, 2, ENC_BIG_ENDIAN, &tuple_size);
679 offset += 2;
680 for (i = 0; i < tuple_size; i++) {
681 offset = parse_option(metadata_subtree, pinfo, tvb, offset);
683 break;
684 default:
685 break;
687 decrement_dissection_depth(pinfo);
689 return offset;
692 static void add_varint_item(proto_tree *tree, tvbuff_t *tvb, const int offset, int length)
694 switch (length)
696 case 1:
697 proto_tree_add_item(tree, hf_cql_varint_count8, tvb, offset, 1, ENC_BIG_ENDIAN);
698 break;
699 case 2:
700 proto_tree_add_item(tree, hf_cql_varint_count16, tvb, offset, 2, ENC_BIG_ENDIAN);
701 break;
702 case 3:
703 proto_tree_add_item(tree, hf_cql_varint_count32, tvb, offset, 3, ENC_BIG_ENDIAN);
704 break;
705 case 4:
706 proto_tree_add_item(tree, hf_cql_varint_count32, tvb, offset, 4, ENC_BIG_ENDIAN);
707 break;
708 case 5:
709 proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 5, ENC_BIG_ENDIAN);
710 break;
711 case 6:
712 proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 6, ENC_BIG_ENDIAN);
713 break;
714 case 7:
715 proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 7, ENC_BIG_ENDIAN);
716 break;
717 case 8:
718 proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 8, ENC_BIG_ENDIAN);
719 break;
723 static void add_cql_uuid(proto_tree* tree, int hf_uuid, tvbuff_t* tvb, int offset)
725 e_guid_t guid;
726 int i;
728 guid.data1 = tvb_get_letohl(tvb, offset+12);
729 guid.data2 = tvb_get_letohl(tvb, offset+10);
730 guid.data3 = tvb_get_letohl(tvb, offset+8);
732 for (i = 0; i < 8; i++)
734 guid.data4[i] = tvb_get_uint8(tvb, offset+(7-i));
737 proto_tree_add_guid(tree, hf_uuid, tvb, offset, 16, &guid);
741 // NOLINTNEXTLINE(misc-no-recursion)
742 static int parse_value(proto_tree* columns_subtree, packet_info *pinfo, tvbuff_t* tvb, int* offset_metadata, int offset)
744 uint32_t data_type = 0;
745 uint32_t string_length = 0;
746 int32_t bytes_length = 0;
747 uint32_t tuple_size = 0;
748 int32_t list_size = 0;
749 int32_t map_size = 0;
750 int32_t set_size = 0;
751 uint32_t udt_size = 0;
752 proto_item *item;
753 proto_item *sub_item;
754 uint32_t i = 0;
755 int32_t j = 0;
756 int offset_metadata_backup = 0;
757 uint32_t addr4;
758 ws_in6_addr addr6;
759 uint32_t port_number;
760 proto_tree* map_subtree;
761 proto_tree* set_subtree;
763 proto_tree_add_item_ret_int(columns_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
764 offset += 4;
766 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_result_rows_data_type, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &data_type);
767 proto_item_set_hidden(item);
768 *offset_metadata += 2;
770 if (bytes_length == -1) { // value is NULL, but need to skip metadata offsets
771 proto_tree_add_item(columns_subtree, hf_cql_null_value, tvb, offset, 0, ENC_NA);
772 if (data_type == CQL_RESULT_ROW_TYPE_MAP) {
773 *offset_metadata += 4; /* skip the type fields of *both* key and value in the map in the metadata */
774 } else if (data_type == CQL_RESULT_ROW_TYPE_SET) {
775 *offset_metadata += 2; /* skip the type field of the elements in the set in the metadata */
777 return offset;
780 increment_dissection_depth(pinfo);
781 switch (data_type) {
782 case CQL_RESULT_ROW_TYPE_CUSTOM:
783 proto_tree_add_item(columns_subtree, hf_cql_custom, tvb, offset, bytes_length, ENC_UTF_8 | ENC_NA);
784 offset += bytes_length;
785 break;
786 case CQL_RESULT_ROW_TYPE_ASCII:
787 proto_tree_add_item(columns_subtree, hf_cql_ascii, tvb, offset, bytes_length, ENC_ASCII | ENC_NA);
788 offset += bytes_length;
789 break;
790 case CQL_RESULT_ROW_TYPE_BIGINT:
791 proto_tree_add_item(columns_subtree, hf_cql_bigint, tvb, offset, 8, ENC_BIG_ENDIAN);
792 offset += 8;
793 break;
794 case CQL_RESULT_ROW_TYPE_BLOB:
795 proto_tree_add_item(columns_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
796 offset += bytes_length;
797 break;
798 case CQL_RESULT_ROW_TYPE_BOOLEAN:
799 proto_tree_add_boolean(columns_subtree, hf_cql_boolean, tvb, offset, 1, true);
800 offset += 1;
801 break;
802 case CQL_RESULT_ROW_TYPE_COUNTER:
803 break;
804 case CQL_RESULT_ROW_TYPE_DECIMAL:
805 proto_tree_add_item(columns_subtree, hf_cql_scale, tvb, offset, 4, ENC_BIG_ENDIAN);
806 offset += 4;
807 add_varint_item(columns_subtree, tvb, offset, bytes_length - 4);
808 offset += bytes_length - 4;
809 break;
810 case CQL_RESULT_ROW_TYPE_DOUBLE:
811 proto_tree_add_item(columns_subtree, hf_cql_double, tvb, offset, 8, ENC_BIG_ENDIAN);
812 offset += 8;
813 break;
814 case CQL_RESULT_ROW_TYPE_FLOAT:
815 proto_tree_add_item(columns_subtree, hf_cql_float, tvb, offset, 4, ENC_BIG_ENDIAN);
816 offset += 4;
817 break;
818 case CQL_RESULT_ROW_TYPE_INT:
819 proto_tree_add_item(columns_subtree, hf_cql_int, tvb, offset, 4, ENC_BIG_ENDIAN);
820 offset += 4;
821 break;
822 case CQL_RESULT_ROW_TYPE_TIMESTAMP:
823 proto_tree_add_item(columns_subtree, hf_cql_result_timestamp, tvb, offset, 8, ENC_BIG_ENDIAN);
824 offset += 8;
825 break;
826 case CQL_RESULT_ROW_TYPE_UUID:
827 add_cql_uuid(columns_subtree, hf_cql_uuid, tvb, offset);
828 offset += 16;
829 break;
830 case CQL_RESULT_ROW_TYPE_VARCHAR:
831 proto_tree_add_item(columns_subtree, hf_cql_varchar, tvb, offset, bytes_length, ENC_ASCII);
832 offset += bytes_length;
833 break;
834 case CQL_RESULT_ROW_TYPE_VARINT:
835 add_varint_item(columns_subtree, tvb, offset, bytes_length);
836 offset += bytes_length;
837 break;
838 case CQL_RESULT_ROW_TYPE_TIMEUUID:
839 add_cql_uuid(columns_subtree, hf_cql_timeuuid, tvb, offset);
840 offset += 16;
841 break;
842 case CQL_RESULT_ROW_TYPE_INET:
843 switch (bytes_length) {
844 case 4:
845 case 8:
846 addr4 = tvb_get_ipv4(tvb, offset);
847 proto_tree_add_ipv4_format_value(columns_subtree, hf_cql_ipv4, tvb, offset, 4, addr4, "%s", get_hostname(addr4));
848 offset += 4;
849 break;
850 case 16:
851 case 20:
852 tvb_get_ipv6(tvb, offset, &addr6);
853 proto_tree_add_ipv6_format_value(columns_subtree, hf_cql_ipv6, tvb, offset, 16, &addr6, "%s", get_hostname6(&addr6));
854 offset += 16;
855 break;
856 default:
857 break;
859 /* port number is optional */
860 if (bytes_length == 16 || bytes_length == 20) {
861 sub_item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_port, tvb, offset, 4, ENC_BIG_ENDIAN, &port_number);
862 proto_item_append_text(sub_item, " (%u)", port_number);
863 offset += 4;
865 break;
866 case CQL_RESULT_ROW_TYPE_DATE:
867 break;
868 case CQL_RESULT_ROW_TYPE_TIME:
869 break;
870 case CQL_RESULT_ROW_TYPE_SMALLINT:
871 break;
872 case CQL_RESULT_ROW_TYPE_TINYINT:
873 break;
874 case CQL_RESULT_ROW_TYPE_LIST:
875 item = proto_tree_add_item_ret_int(columns_subtree, hf_cql_string_result_rows_list_size, tvb, offset, 4, ENC_BIG_ENDIAN, &list_size);
876 if (list_size < 0) {
877 expert_add_info(pinfo, item, &ei_cql_unexpected_negative_value);
878 decrement_dissection_depth(pinfo);
879 return tvb_reported_length(tvb);
881 offset += 4;
882 offset_metadata_backup = *offset_metadata;
883 for (j = 0; j < list_size; j++) {
884 *offset_metadata = offset_metadata_backup;
885 offset = parse_value(columns_subtree, pinfo, tvb, offset_metadata, offset);
887 break;
888 case CQL_RESULT_ROW_TYPE_MAP:
889 map_subtree = proto_tree_add_subtree(columns_subtree, tvb, offset, 0, ett_cql_result_map, NULL, "Map");
890 item = proto_tree_add_item_ret_int(map_subtree, hf_cql_string_result_rows_map_size, tvb, offset, 4, ENC_BIG_ENDIAN, &map_size);
891 offset += 4;
892 proto_item_append_text(map_subtree, " with %" PRId32 " element(s)", map_size);
893 if (map_size < 0) {
894 expert_add_info(pinfo, item, &ei_cql_unexpected_negative_value);
895 decrement_dissection_depth(pinfo);
896 return tvb_reported_length(tvb);
897 } else if (map_size == 0) {
898 *offset_metadata += 4; /* skip the type fields of *both* key and value in the map in the metadata */
899 } else {
900 offset_metadata_backup = *offset_metadata;
901 for (j = 0; j < map_size; j++) {
902 *offset_metadata = offset_metadata_backup;
903 offset = parse_value(map_subtree, pinfo, tvb, offset_metadata, offset);
904 offset = parse_value(map_subtree, pinfo, tvb, offset_metadata, offset);
907 break;
908 case CQL_RESULT_ROW_TYPE_SET:
909 set_subtree = proto_tree_add_subtree(columns_subtree, tvb, offset, 0, ett_cql_result_set, NULL, "Set");
910 item = proto_tree_add_item_ret_int(set_subtree, hf_cql_string_result_rows_set_size, tvb, offset, 4, ENC_BIG_ENDIAN, &set_size);
911 offset += 4;
912 if (set_size < 0) {
913 expert_add_info(pinfo, item, &ei_cql_unexpected_negative_value);
914 decrement_dissection_depth(pinfo);
915 return tvb_reported_length(tvb);
916 } else if (set_size == 0) {
917 *offset_metadata += 2; /* skip the type field of the elements in the set in the metadata */
918 } else {
919 offset_metadata_backup = *offset_metadata;
920 for (j = 0; j < set_size; j++) {
921 *offset_metadata = offset_metadata_backup;
922 offset = parse_value(set_subtree, pinfo, tvb, offset_metadata, offset);
925 break;
926 case CQL_RESULT_ROW_TYPE_UDT:
927 /* keyspace */
928 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &string_length);
929 proto_item_set_hidden(item);
930 *offset_metadata += 2;
931 item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_keyspace_name, tvb, *offset_metadata, string_length, ENC_UTF_8 | ENC_NA);
932 proto_item_set_hidden(item);
933 *offset_metadata += string_length;
935 /* UDT name */
936 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &string_length);
937 proto_item_set_hidden(item);
938 *offset_metadata += 2;
939 item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_udt_name, tvb, *offset_metadata, string_length, ENC_UTF_8 | ENC_NA);
940 proto_item_set_hidden(item);
941 *offset_metadata += string_length;
943 /* UDT size */
944 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_result_rows_udt_size, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &udt_size);
945 proto_item_set_hidden(item);
946 *offset_metadata += 2;
948 for (i = 0; i < udt_size; i++) {
949 /* UDT field name */
950 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &string_length);
951 proto_item_set_hidden(item);
952 *offset_metadata += 2;
953 item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_udt_field_name, tvb, *offset_metadata, string_length, ENC_UTF_8 | ENC_NA);
954 proto_item_set_hidden(item);
955 *offset_metadata += string_length;
957 /* UDT field option */
958 offset = parse_value(columns_subtree, pinfo, tvb, offset_metadata, offset);
960 break;
961 case CQL_RESULT_ROW_TYPE_TUPLE:
962 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_result_rows_tuple_size, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &tuple_size);
963 proto_item_set_hidden(item);
964 *offset_metadata += 2;
965 for (i = 0; i < tuple_size; i++) {
966 offset = parse_value(columns_subtree, pinfo, tvb, offset_metadata, offset);
968 break;
969 default:
970 break;
972 decrement_dissection_depth(pinfo);
974 return offset;
977 static int parse_result_metadata_more_pages(proto_tree* tree, tvbuff_t* tvb, int offset, int flags)
979 int32_t bytes_length = 0;
981 if (flags & CQL_RESULT_ROWS_FLAG_HAS_MORE_PAGES) {
982 /* show paging state */
983 proto_tree_add_item_ret_int(tree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
984 offset += 4;
985 if (bytes_length > 0) {
986 proto_tree_add_item(tree, hf_cql_paging_state, tvb, offset, bytes_length, ENC_NA);
987 offset += bytes_length;
991 return offset;
994 static int parse_result_metadata(proto_tree* tree, packet_info *pinfo, tvbuff_t* tvb,
995 int offset, int flags, int result_rows_columns_count)
997 proto_tree* col_spec_subtree = NULL;
998 uint32_t string_length = 0;
999 int j;
1001 if (flags & CQL_RESULT_ROWS_FLAG_NO_METADATA) {
1002 /* There will be no col_spec elements. */
1003 return offset;
1006 if ((flags & (CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC | CQL_RESULT_ROWS_FLAG_NO_METADATA)) == CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC) {
1007 proto_tree_add_item_ret_uint(tree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1008 offset += 2;
1009 proto_tree_add_item(tree, hf_cql_string_result_rows_global_table_spec_ksname, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1010 offset += string_length;
1012 proto_tree_add_item_ret_uint(tree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1013 offset += 2;
1014 proto_tree_add_item(tree, hf_cql_string_result_rows_global_table_spec_table_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1015 offset += string_length;
1018 for (j = 0; j < result_rows_columns_count; ++j) {
1019 col_spec_subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cql_result_metadata_colspec, NULL, "Column");
1020 proto_item_append_text(col_spec_subtree, " # %" PRId32 " specification", j + 1);
1021 if (!(flags & CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC)) {
1022 /* ksname and tablename */
1023 proto_tree_add_item_ret_uint(col_spec_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1024 offset += 2;
1025 proto_tree_add_item(col_spec_subtree, hf_cql_string_result_rows_keyspace_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1026 offset += string_length;
1027 proto_tree_add_item_ret_uint(col_spec_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1028 offset += 2;
1029 proto_tree_add_item(col_spec_subtree, hf_cql_string_result_rows_table_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1030 offset += string_length;
1033 /* column name */
1034 proto_tree_add_item_ret_uint(col_spec_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1035 offset += 2;
1036 proto_tree_add_item(col_spec_subtree, hf_cql_string_result_rows_column_name, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1037 offset += string_length;
1039 /* type "option" */
1040 offset = parse_option(col_spec_subtree, pinfo, tvb, offset);
1043 return offset;
1047 static int parse_result_schema_change(proto_tree* subtree, packet_info *pinfo, tvbuff_t* tvb,
1048 int offset)
1050 uint32_t short_bytes_length = 0;
1051 const uint8_t* string_event_type_target = NULL;
1053 proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1054 offset += 2;
1055 proto_tree_add_item(subtree, hf_cql_event_schema_change_type, tvb, offset, short_bytes_length, ENC_UTF_8 | ENC_NA);
1056 offset += short_bytes_length;
1057 proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1058 offset += 2;
1059 proto_tree_add_item_ret_string(subtree, hf_cql_event_schema_change_type_target, tvb, offset, short_bytes_length, ENC_UTF_8, pinfo->pool, &string_event_type_target);
1060 offset += short_bytes_length;
1061 /* all targets have the keyspace as the first parameter*/
1062 proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1063 offset += 2;
1064 proto_tree_add_item(subtree, hf_cql_event_schema_change_keyspace, tvb, offset, short_bytes_length, ENC_UTF_8 | ENC_NA);
1065 offset += short_bytes_length;
1066 if ((strcmp(string_event_type_target, "TABLE") == 0) || (strcmp(string_event_type_target, "TYPE") == 0)) {
1067 proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1068 offset += 2;
1069 proto_tree_add_item(subtree, hf_cql_event_schema_change_object, tvb, offset, short_bytes_length, ENC_UTF_8 | ENC_NA);
1070 } else {
1071 /* TODO: handle "FUNCTION" or "AGGREGATE" targets:
1072 - [string] the function/aggregate name
1073 - [string list] one string for each argument type (as CQL type)
1077 return offset;
1081 static int parse_row(proto_tree* columns_subtree, packet_info *pinfo, tvbuff_t* tvb,
1082 int offset_metadata, int offset, int result_rows_columns_count)
1084 int32_t result_rows_flags = 0;
1085 int string_length;
1086 int shadow_offset;
1087 proto_item *item;
1088 int j;
1090 shadow_offset = offset_metadata;
1091 for (j = 0; j < result_rows_columns_count; ++j) {
1092 if (!(result_rows_flags & CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC)) {
1093 /* ksname and tablename */
1094 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, shadow_offset, 2, ENC_BIG_ENDIAN, &string_length);
1095 proto_item_set_hidden(item);
1096 shadow_offset += 2;
1097 item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_keyspace_name, tvb, shadow_offset, string_length, ENC_UTF_8 | ENC_NA);
1098 proto_item_set_hidden(item);
1099 shadow_offset += string_length;
1100 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, shadow_offset, 2, ENC_BIG_ENDIAN, &string_length);
1101 proto_item_set_hidden(item);
1102 shadow_offset += 2;
1103 item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_table_name, tvb, shadow_offset, string_length, ENC_UTF_8 | ENC_NA);
1104 proto_item_set_hidden(item);
1105 shadow_offset += string_length;
1108 /* column name */
1109 item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, shadow_offset, 2, ENC_BIG_ENDIAN, &string_length);
1110 proto_item_set_hidden(item);
1111 shadow_offset += 2;
1112 item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_column_name, tvb, shadow_offset, string_length, ENC_UTF_8 | ENC_NA);
1113 proto_item_set_hidden(item);
1114 shadow_offset += string_length;
1116 offset = parse_value(columns_subtree, pinfo, tvb, &shadow_offset, offset);
1119 return offset;
1122 static int
1123 dissect_cql_tcp_pdu(tvbuff_t* raw_tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
1125 proto_item* ti;
1126 tvbuff_t* tvb = NULL;
1127 proto_tree* cql_tree;
1128 proto_tree* version_tree;
1129 proto_tree* cql_subtree = NULL;
1130 proto_tree* cust_payload_tree = NULL;
1131 proto_tree* rows_subtree = NULL;
1132 proto_tree* columns_subtree = NULL;
1133 proto_tree* single_column_subtree = NULL;
1134 proto_tree* metadata_subtree = NULL;
1135 proto_tree* prepared_metadata_subtree = NULL;
1137 int offset = 0;
1138 int offset_row_metadata = 0;
1139 uint8_t flags = 0;
1140 uint8_t first_byte = 0;
1141 uint8_t cql_version = 0;
1142 uint8_t server_to_client = 0;
1143 uint8_t opcode = 0;
1144 uint32_t message_length = 0;
1145 uint32_t map_size = 0;
1146 uint64_t i = 0;
1147 uint32_t string_length = 0;
1148 int32_t stream = 0;
1149 uint32_t batch_size = 0;
1150 uint32_t batch_query_type = 0;
1151 uint32_t result_kind = 0;
1152 int32_t result_rows_flags = 0;
1153 int32_t result_rows_columns_count = 0;
1154 int32_t result_prepared_flags = 0;
1155 int32_t result_prepared_pk_count = 0;
1156 int64_t j = 0;
1157 int64_t k = 0;
1158 uint32_t short_bytes_length = 0;
1159 int32_t bytes_length = 0;
1160 int32_t result_rows_row_count = 0;
1162 conversation_t* conversation;
1163 cql_conversation_type* cql_conv;
1164 cql_transaction_type* cql_trans = NULL;
1165 cql_compression_level compression_level = CQL_COMPRESSION_NONE;
1167 static int * const cql_batch_flags_bitmaps[] = {
1168 &hf_cql_batch_flag_serial_consistency,
1169 &hf_cql_batch_flag_default_timestamp,
1170 &hf_cql_batch_flag_with_name_for_values,
1171 NULL
1174 static int * const cql_header_bitmaps_v3[] = {
1175 &hf_cql_flag_compression,
1176 &hf_cql_flag_tracing,
1177 &hf_cql_flag_reserved3,
1178 NULL
1181 static int * const cql_header_bitmaps_v4[] = {
1182 &hf_cql_flag_compression,
1183 &hf_cql_flag_tracing,
1184 &hf_cql_flag_custom_payload,
1185 &hf_cql_flag_warning,
1186 &hf_cql_flag_reserved4,
1187 NULL
1190 const uint8_t* string_event_type = NULL;
1192 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CQL");
1193 col_clear(pinfo->cinfo, COL_INFO);
1195 first_byte = tvb_get_uint8(raw_tvb, 0);
1196 cql_version = first_byte & (uint8_t)0x7F;
1197 server_to_client = first_byte & (uint8_t)0x80;
1198 opcode = tvb_get_uint8(raw_tvb, 4);
1200 col_add_fstr(pinfo->cinfo, COL_INFO, "v%d %s Type %s",
1201 cql_version,
1202 server_to_client == 0 ? "C->S" : "S->C",
1203 val_to_str(opcode, cql_opcode_names, "Unknown (0x%02x)")
1206 conversation = find_or_create_conversation(pinfo);
1207 cql_conv = (cql_conversation_type*) conversation_get_proto_data(conversation, proto_cql);
1208 if(!cql_conv) {
1209 cql_conv = wmem_new(wmem_file_scope(), cql_conversation_type);
1210 cql_conv->streams = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1211 conversation_add_proto_data(conversation, proto_cql, cql_conv);
1214 ti = proto_tree_add_item(tree, proto_cql, raw_tvb, 0, -1, ENC_NA);
1215 cql_tree = proto_item_add_subtree(ti, ett_cql_protocol);
1217 ti = proto_tree_add_item(cql_tree, hf_cql_version, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1218 version_tree = proto_item_add_subtree(ti, ett_cql_version);
1219 proto_tree_add_item(version_tree, hf_cql_protocol_version, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1220 proto_tree_add_item(version_tree, hf_cql_direction, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1221 offset += 1;
1222 switch(cql_version){
1223 case 3:
1224 proto_tree_add_bitmask(cql_tree, raw_tvb, offset, hf_cql_flags_bitmap, ett_cql_header_flags_bitmap, cql_header_bitmaps_v3, ENC_BIG_ENDIAN);
1225 break;
1226 case 4:
1227 proto_tree_add_bitmask(cql_tree, raw_tvb, offset, hf_cql_flags_bitmap, ett_cql_header_flags_bitmap, cql_header_bitmaps_v4, ENC_BIG_ENDIAN);
1228 break;
1229 default:
1230 proto_tree_add_item(cql_tree, hf_cql_flags_bitmap, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1231 break;
1233 flags = tvb_get_uint8(raw_tvb, offset);
1234 offset += 1;
1235 proto_tree_add_item_ret_int(cql_tree, hf_cql_stream, raw_tvb, offset, 2, ENC_BIG_ENDIAN, &stream);
1236 offset += 2;
1237 proto_tree_add_item(cql_tree, hf_cql_opcode, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1238 offset += 1;
1239 proto_tree_add_item_ret_uint(cql_tree, hf_cql_length, raw_tvb, offset, 4, ENC_BIG_ENDIAN, &message_length);
1240 offset += 4;
1242 /* Track the request/response. */
1243 if (!pinfo->fd->visited) {
1244 if (server_to_client == 0) {
1245 /* This is a request, add it to this stream tracking */
1246 cql_trans = cql_transaction_add_request(cql_conv, pinfo, stream, 0);
1247 } else {
1248 /* This is a response, bind the response with the latest request */
1249 cql_trans = cql_enrich_transaction_with_response(cql_conv, pinfo, stream);
1251 } else {
1252 /* Search for any packet having this packed id as request or response */
1253 cql_trans = cql_transaction_lookup(cql_conv, pinfo, stream);
1256 if (!cql_trans) {
1257 /* Add a fake request to this stream tracking */
1258 cql_trans = cql_transaction_add_request(cql_conv, pinfo, stream, 1);
1261 /* Add state tracking to tree */
1262 if (server_to_client == 0 && cql_trans->rep_frame) {
1263 /* request */
1264 ti = proto_tree_add_uint(cql_tree, hf_cql_response_in, raw_tvb, 0, 0, cql_trans->rep_frame);
1265 proto_item_set_generated(ti);
1267 if (server_to_client && cql_trans->req_frame) {
1268 /* reply */
1269 nstime_t ns;
1271 ti = proto_tree_add_uint(cql_tree, hf_cql_response_to, raw_tvb, 0, 0, cql_trans->req_frame);
1272 proto_item_set_generated(ti);
1273 nstime_delta(&ns, &pinfo->abs_ts, &cql_trans->req_time);
1274 ti = proto_tree_add_time(cql_tree, hf_cql_response_time, raw_tvb, 0, 0, &ns);
1275 proto_item_set_generated(ti);
1278 /* We cannot rely on compression negotiation in the STARTUP message because the
1279 * capture can be done at a random time hence missing the negotiation.
1280 * So we will first try to decompress LZ4 then snappy
1282 if (flags & CQL_HEADER_FLAG_COMPRESSION) {
1283 compression_level = CQL_DECOMPRESSION_ATTEMPTED;
1284 #ifdef HAVE_LZ4
1285 if (tvb_captured_length_remaining(raw_tvb, offset) > 4) {
1286 /* Set ret == 0 to make it fail in case decompression is skipped
1287 * due to orig_size being too big
1289 uint32_t ret = 0, orig_size = tvb_get_ntohl(raw_tvb, offset);
1290 unsigned char *decompressed_buffer = NULL;
1291 offset += 4;
1293 /* if the decompressed size is reasonably small try to decompress data */
1294 if (orig_size <= MAX_UNCOMPRESSED_SIZE) {
1295 decompressed_buffer = (unsigned char*)wmem_alloc(pinfo->pool, orig_size);
1296 ret = LZ4_decompress_safe(tvb_get_ptr(raw_tvb, offset, -1),
1297 decompressed_buffer,
1298 tvb_captured_length_remaining(raw_tvb, offset),
1299 orig_size);
1301 /* Decompression attempt failed: rewind offset */
1302 if (ret != orig_size) {
1303 wmem_free(pinfo->pool, decompressed_buffer);
1304 offset -= 4;
1305 } else {
1306 /* Now re-setup the tvb buffer to have the new data */
1307 tvb = tvb_new_child_real_data(raw_tvb, decompressed_buffer, orig_size, orig_size);
1308 add_new_data_source(pinfo, tvb, "LZ4 Decompressed Data");
1309 /* mark the decompression as successful */
1310 compression_level = CQL_COMPRESSION_LZ4;
1311 message_length= orig_size;
1314 #endif
1315 #ifdef HAVE_SNAPPY
1316 if (compression_level == CQL_DECOMPRESSION_ATTEMPTED) {
1317 unsigned char *decompressed_buffer = NULL;
1318 size_t orig_size = 0;
1319 snappy_status ret;
1321 /* get the raw data length */
1322 ret = snappy_uncompressed_length(tvb_get_ptr(raw_tvb, offset, -1),
1323 tvb_captured_length_remaining(raw_tvb, offset),
1324 &orig_size);
1325 /* if we get the length and it's reasonably short to allocate a buffer for it
1326 * proceed to try decompressing the data
1328 if (ret == SNAPPY_OK && orig_size <= MAX_UNCOMPRESSED_SIZE) {
1329 decompressed_buffer = (unsigned char*)wmem_alloc(pinfo->pool, orig_size);
1331 ret = snappy_uncompress(tvb_get_ptr(raw_tvb, offset, -1),
1332 tvb_captured_length_remaining(raw_tvb, offset),
1333 decompressed_buffer,
1334 &orig_size);
1335 } else {
1336 /* else mark the input as invalid in order to skip the rest of the
1337 * procedure
1339 ret = SNAPPY_INVALID_INPUT;
1341 /* if the decompression succeeded build the new tvb */
1342 if (ret == SNAPPY_OK) {
1343 tvb = tvb_new_child_real_data(raw_tvb, decompressed_buffer, (uint32_t)orig_size, (uint32_t)orig_size);
1344 add_new_data_source(pinfo, tvb, "Snappy Decompressed Data");
1345 compression_level = CQL_COMPRESSION_SNAPPY;
1346 message_length = (uint32_t)orig_size;
1347 } else {
1348 wmem_free(pinfo->pool, decompressed_buffer);
1351 #endif
1353 if (compression_level == CQL_COMPRESSION_NONE) {
1354 /* In case of decompression failure or uncompressed packet */
1355 tvb = tvb_new_subset_remaining(raw_tvb, offset);
1356 } else if (compression_level == CQL_DECOMPRESSION_ATTEMPTED) {
1357 proto_tree_add_item(cql_tree, hf_cql_raw_compressed_bytes, raw_tvb, offset,
1358 tvb_captured_length_remaining(raw_tvb, offset), ENC_NA);
1359 return tvb_captured_length(raw_tvb);
1361 offset = 0;
1364 /* Dissect the operation. */
1365 if (server_to_client == 0) {
1366 switch (opcode) {
1367 case CQL_OPCODE_STARTUP:
1368 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message STARTUP");
1369 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_map_size, tvb, offset, 2, ENC_BIG_ENDIAN, &map_size);
1370 offset += 2;
1371 for(i = 0; i < map_size; ++i) {
1372 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1373 offset += 2;
1374 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1375 offset += string_length;
1377 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1378 offset += 2;
1379 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1380 offset += string_length;
1382 break;
1384 case CQL_OPCODE_AUTH_RESPONSE:
1385 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTH_RESPONSE");
1387 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1388 offset += 4;
1389 if (string_length > 0) {
1390 proto_tree_add_item(cql_subtree, hf_cql_auth_token, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1392 break;
1394 case CQL_OPCODE_OPTIONS:
1395 /* body should be empty */
1396 break;
1398 case CQL_OPCODE_QUERY:
1399 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Query");
1401 /* Query */
1402 const uint8_t *query_string;
1403 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1404 offset += 4;
1405 proto_tree_add_item_ret_string(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA, pinfo->pool, &query_string);
1406 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", query_string);
1407 offset += string_length;
1409 /* Query parameters */
1410 dissect_cql_query_parameters(cql_subtree, tvb, offset, 0);
1412 break;
1415 case CQL_OPCODE_PREPARE:
1416 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message PREPARE");
1418 /* TODO: Link for later use by EXECUTE? */
1419 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1420 offset += 4;
1421 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1422 break;
1425 case CQL_OPCODE_EXECUTE:
1426 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message EXECUTE");
1428 /* TODO: link to original PREPARE? */
1430 /* Query ID */
1431 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1432 offset += 2;
1433 proto_tree_add_item(cql_subtree, hf_cql_query_id, tvb, offset, short_bytes_length, ENC_NA);
1434 offset += short_bytes_length;
1436 /* Query parameters */
1437 dissect_cql_query_parameters(cql_subtree, tvb, offset, 1);
1438 break;
1441 case CQL_OPCODE_BATCH:
1442 /* TODO NOT DONE */
1443 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message BATCH");
1445 proto_tree_add_item(cql_subtree, hf_cql_batch_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1446 offset += 1;
1448 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_batch_query_size, tvb, offset, 2, ENC_BIG_ENDIAN, &batch_size);
1449 offset += 2;
1451 for (i = 0; i < batch_size; ++i) {
1452 uint32_t value_count = 0;
1454 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_batch_query_type, tvb, offset, 1, ENC_BIG_ENDIAN, &batch_query_type);
1455 batch_query_type = tvb_get_uint8(tvb, offset);
1456 offset += 1;
1457 if (batch_query_type == 0) {
1458 /* Query */
1459 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1460 offset += 4;
1461 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1462 offset += string_length;
1463 } else if (batch_query_type == 1) {
1464 uint32_t query_id_bytes_length;
1466 /* Query ID */
1467 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &query_id_bytes_length);
1468 offset += 2;
1469 proto_tree_add_item(cql_subtree, hf_cql_query_id, tvb, offset, query_id_bytes_length, ENC_NA);
1470 offset += query_id_bytes_length;
1473 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &value_count);
1474 offset += 2;
1475 for (k = 0; k < value_count; ++k) {
1476 int32_t batch_bytes_length = 0;
1477 proto_tree_add_item_ret_int(cql_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &batch_bytes_length);
1478 offset += 4;
1479 if (batch_bytes_length > 0) {
1480 proto_tree_add_item(cql_subtree, hf_cql_bytes, tvb, offset, batch_bytes_length, ENC_NA);
1481 offset += batch_bytes_length;
1483 /* TODO - handle both -1 and -2 batch_bytes_length values:
1484 -1 no byte should follow and the value represented is `null`.
1485 -2 no byte should follow and the value represented is `not set` not resulting in any change to the existing value.
1486 < -2 is an invalid value and results in an error. */
1489 /* consistency */
1490 proto_tree_add_item(cql_subtree, hf_cql_consistency, tvb, offset, 2, ENC_BIG_ENDIAN);
1491 offset += 2;
1492 proto_tree_add_bitmask(cql_subtree, tvb, offset, hf_cql_batch_flags_bitmap, ett_cql_batch_flags_bitmap, cql_batch_flags_bitmaps, ENC_BIG_ENDIAN);
1493 break;
1495 case CQL_OPCODE_REGISTER:
1496 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message REGISTER");
1498 /* string list */
1499 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_list_size, tvb, offset, 2, ENC_BIG_ENDIAN, &map_size);
1500 offset += 2;
1501 for(i = 0; i < map_size; ++i) {
1502 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1503 offset += 2;
1504 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1505 offset += string_length;
1508 break;
1510 default:
1511 proto_tree_add_expert(cql_tree, pinfo, &ei_cql_data_not_dissected_yet, tvb, 0, message_length);
1512 break;
1514 } else {
1515 if (flags & CQL_HEADER_FLAG_TRACING) {
1516 add_cql_uuid(cql_tree, hf_cql_tracing_uuid, tvb, offset);
1517 offset += 16;
1519 switch (opcode) {
1520 case CQL_OPCODE_ERROR:
1521 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message ERROR");
1522 uint32_t error_code;
1523 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_error_code, tvb, offset, 4, ENC_BIG_ENDIAN, &error_code);
1524 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s (0x%x)", val_to_str_const(error_code, cql_error_names, "Unknown error code"), error_code);
1525 offset += 4;
1527 /* string */
1528 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1529 offset += 2;
1530 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1531 break;
1534 case CQL_OPCODE_AUTHENTICATE:
1535 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTHENTICATE");
1537 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1538 offset += 2;
1539 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1540 break;
1543 case CQL_OPCODE_SUPPORTED:
1544 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message SUPPORTED");
1545 uint32_t multimap_count, value_count;
1547 /* string multimap */
1548 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &multimap_count);
1549 offset += 2;
1550 for (k = 0; k < multimap_count; ++k) {
1551 /* key - string */
1552 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1553 offset += 2;
1554 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1555 offset += string_length;
1557 /* value - string list */
1558 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_list_size, tvb, offset, 2, ENC_BIG_ENDIAN, &value_count);
1559 offset += 2;
1560 for(i = 0; i < value_count; ++i) {
1561 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1562 offset += 2;
1563 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1564 offset += string_length;
1567 break;
1570 case CQL_OPCODE_RESULT:
1571 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message RESULT");
1573 if (flags & CQL_HEADER_FLAG_CUSTOM_PAYLOAD) {
1574 uint32_t bytesmap_count;
1575 cust_payload_tree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_custom_payload, NULL, "Custom Payload");
1576 proto_tree_add_item_ret_uint(cust_payload_tree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &bytesmap_count);
1577 offset += 2;
1578 for(k = 0; k < bytesmap_count; ++k) {
1579 proto_tree_add_item_ret_uint(cust_payload_tree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1580 offset += 2;
1581 proto_tree_add_item(cust_payload_tree, hf_cql_bytesmap_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1582 offset += string_length;
1583 if (bytes_length > 0) {
1584 proto_tree_add_item(cust_payload_tree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
1585 offset += bytes_length;
1588 return offset;
1591 proto_tree_add_item_ret_int(cql_subtree, hf_cql_result_kind, tvb, offset, 4, ENC_BIG_ENDIAN, &result_kind);
1592 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(result_kind, cql_result_kind_names, "Unknown kind"));
1593 offset += 4;
1595 switch (result_kind) {
1596 case CQL_RESULT_KIND_VOID:
1597 /* Nothing */
1598 break;
1600 case CQL_RESULT_KIND_ROWS:
1601 metadata_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_metadata, &ti, "Rows Result Metadata");
1602 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_flags_values, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_flags);
1603 proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_global_tables_spec, tvb, offset, 4, ENC_BIG_ENDIAN);
1604 proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_has_more_pages, tvb, offset, 4, ENC_BIG_ENDIAN);
1605 proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_no_metadata, tvb, offset, 4, ENC_BIG_ENDIAN);
1606 offset += 4;
1608 ti = proto_tree_add_item_ret_int(metadata_subtree, hf_cql_result_rows_column_count, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_columns_count);
1609 if (result_rows_columns_count < 0) {
1610 expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1611 return tvb_reported_length(tvb);
1613 offset += 4;
1615 offset = parse_result_metadata_more_pages(metadata_subtree, tvb, offset, result_rows_flags);
1617 offset_row_metadata = offset;
1618 offset = parse_result_metadata(metadata_subtree, pinfo, tvb, offset, result_rows_flags, result_rows_columns_count);
1619 if (offset == offset_row_metadata) {
1620 /* there was no col spec, no row metadata available */
1621 offset_row_metadata = 0;
1624 rows_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_rows, &ti, "Rows");
1625 ti = proto_tree_add_item_ret_int(rows_subtree, hf_cql_result_rows_row_count, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_row_count);
1626 if (result_rows_row_count < 0) {
1627 expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1628 return tvb_reported_length(tvb);
1630 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d rows)", result_rows_row_count);
1631 offset += 4;
1633 if (result_rows_columns_count) {
1634 for (j = 0; j < result_rows_row_count; ++j) {
1635 columns_subtree = proto_tree_add_subtree(rows_subtree, tvb, offset, 0, ett_cql_result_columns, &ti, "Data (columns)");
1636 proto_item_append_text(columns_subtree, " for row # %" PRId64, j + 1);
1638 if (offset_row_metadata) {
1639 offset = parse_row(columns_subtree, pinfo, tvb, offset_row_metadata, offset, result_rows_columns_count);
1640 } else {
1641 for (k = 0; k < result_rows_columns_count; ++k) {
1642 proto_tree_add_item_ret_int(columns_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
1643 offset += 4;
1644 single_column_subtree = proto_tree_add_subtree(columns_subtree, tvb, offset, bytes_length > 0 ? bytes_length : 0, ett_cql_results_no_metadata, &ti, "Column data");
1645 if (bytes_length > 0) {
1646 proto_item_append_text(single_column_subtree, " for column # %" PRId64, k + 1);
1647 proto_tree_add_item(single_column_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
1648 offset += bytes_length;
1649 } else if (bytes_length == -1) {
1650 proto_item_append_text(single_column_subtree, " is NULL for column # %" PRId64, k + 1);
1651 } else if (bytes_length == -2) {
1652 proto_item_append_text(single_column_subtree, " is not set for column # %" PRId64, k + 1);
1653 } else {
1654 expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1655 return tvb_reported_length(tvb);
1662 break;
1664 case CQL_RESULT_KIND_SET_KEYSPACE:
1665 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1666 offset += 2;
1667 proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1668 break;
1671 case CQL_RESULT_KIND_PREPARED:
1672 /* <id><metadata><result_metadata> */
1674 /* Query ID */
1675 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1676 offset += 2;
1677 proto_tree_add_item(cql_subtree, hf_cql_query_id, tvb, offset, short_bytes_length, ENC_NA);
1678 offset += short_bytes_length;
1680 /* metadata: <flags><columns_count><pk_count>[<pk_index_1>...<pk_index_n>][<global_table_spec>?<col_spec_1>...<col_spec_n>] */
1681 prepared_metadata_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_metadata, &ti, "Prepared Metadata");
1682 proto_tree_add_item_ret_uint(prepared_metadata_subtree, hf_cql_result_prepared_flags_values, tvb, offset, 4, ENC_BIG_ENDIAN, &result_prepared_flags);
1683 proto_tree_add_item(prepared_metadata_subtree, hf_cql_result_rows_flag_global_tables_spec, tvb, offset, 4, ENC_BIG_ENDIAN);
1684 offset += 4;
1685 proto_tree_add_item_ret_int(prepared_metadata_subtree, hf_cql_result_rows_column_count, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_columns_count);
1686 if (result_rows_columns_count < 0) {
1687 expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1688 return tvb_reported_length(tvb);
1690 offset += 4;
1692 proto_tree_add_item_ret_int(prepared_metadata_subtree, hf_cql_result_prepared_pk_count, tvb, offset, 4, ENC_BIG_ENDIAN, &result_prepared_pk_count);
1693 if (result_prepared_pk_count < 0) {
1694 expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1695 return tvb_reported_length(tvb);
1697 offset += 4;
1699 /* TODO: skipping all pk_index elements for now*/
1700 offset += (2 * result_prepared_pk_count);
1702 offset = parse_result_metadata(prepared_metadata_subtree, pinfo, tvb, offset, result_prepared_flags, result_rows_columns_count);
1704 /* <result_metadata> is identical to rows result metadata */
1705 metadata_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_metadata, &ti, "Prepared Result Metadata");
1706 proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_flags_values, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_flags);
1707 proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_global_tables_spec, tvb, offset, 4, ENC_BIG_ENDIAN);
1708 proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_has_more_pages, tvb, offset, 4, ENC_BIG_ENDIAN);
1709 proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_no_metadata, tvb, offset, 4, ENC_BIG_ENDIAN);
1710 offset += 4;
1712 ti = proto_tree_add_item_ret_int(metadata_subtree, hf_cql_result_rows_column_count, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_columns_count);
1713 if (result_rows_columns_count < 0) {
1714 expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1715 return tvb_reported_length(tvb);
1717 offset += 4;
1719 offset = parse_result_metadata_more_pages(metadata_subtree, tvb, offset, result_rows_flags);
1721 parse_result_metadata(metadata_subtree, pinfo, tvb, offset, result_rows_flags, result_rows_columns_count);
1723 break;
1724 case CQL_RESULT_KIND_SCHEMA_CHANGE:
1725 /*offset = */parse_result_schema_change(cql_subtree, pinfo, tvb, offset);
1726 break;
1728 default:
1729 proto_tree_add_expert(cql_subtree, pinfo, &ei_cql_data_not_dissected_yet, tvb, 0, message_length);
1730 break;
1733 break;
1736 case CQL_OPCODE_EVENT:
1737 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message EVENT");
1739 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1740 offset += 2;
1742 proto_tree_add_item_ret_string(cql_subtree, hf_cql_event_type, tvb, offset, short_bytes_length, ENC_UTF_8, pinfo->pool, &string_event_type);
1743 offset += short_bytes_length;
1744 proto_item_append_text(cql_subtree, " (type: %s)", string_event_type);
1746 if (strcmp(string_event_type, "SCHEMA_CHANGE") == 0) {
1747 /*offset = */parse_result_schema_change(cql_subtree, pinfo, tvb, offset);
1748 } else {
1749 /* TODO: handle "TOPOLOGY_CHANGE" and "STATUS_CHANGE" event types as well*/
1751 break;
1754 case CQL_OPCODE_AUTH_CHALLENGE:
1755 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTH_CHALLENGE");
1757 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1758 offset += 4;
1759 proto_tree_add_item(cql_subtree, hf_cql_auth_token, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1760 break;
1763 case CQL_OPCODE_AUTH_SUCCESS:
1764 cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTH_SUCCESS");
1766 proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1767 offset += 4;
1768 if (string_length > 0) {
1769 proto_tree_add_item(cql_subtree, hf_cql_auth_token, tvb, offset, string_length, ENC_UTF_8 | ENC_NA);
1771 break;
1773 default:
1774 proto_tree_add_expert(cql_subtree, pinfo, &ei_cql_data_not_dissected_yet, tvb, 0, message_length);
1775 break;
1779 return tvb_reported_length(tvb);
1782 static int
1783 dissect_cql_tcp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
1785 uint8_t version;
1786 /* This dissector version only understands CQL protocol v3 and v4. */
1787 if (tvb_reported_length(tvb) < 1)
1788 return 0;
1790 version = tvb_get_uint8(tvb, 0) & 0x7F;
1791 if ((version != 3 && version != 4))
1792 return 0;
1794 tcp_dissect_pdus(tvb, pinfo, tree, cql_desegment, 9 /* bytes to determine length of PDU */, get_cql_pdu_len, dissect_cql_tcp_pdu, data);
1795 return tvb_reported_length(tvb);
1798 void
1799 proto_reg_handoff_cql(void)
1801 dissector_add_uint_with_preference("tcp.port", CQL_DEFAULT_PORT, find_dissector("cql"));
1805 void
1806 proto_register_cql(void)
1808 expert_module_t* expert_cql;
1809 static hf_register_info hf[] = {
1811 &hf_cql_batch_flag_serial_consistency,
1813 "Serial Consistency", "cql.batch.flags.serial_consistency",
1814 FT_BOOLEAN, 8,
1815 NULL, CQL_BATCH_FLAG_SERIAL_CONSISTENCY,
1816 NULL, HFILL
1820 &hf_cql_batch_flag_default_timestamp,
1822 "Default Timestamp", "cql.batch.flags.default_timestamp",
1823 FT_BOOLEAN, 8,
1824 NULL, CQL_BATCH_FLAG_DEFAULT_TIMESTAMP,
1825 NULL, HFILL
1829 &hf_cql_batch_flag_with_name_for_values,
1831 "With Name For Value", "cql.batch.flags.with_name_for_values",
1832 FT_BOOLEAN, 8,
1833 NULL, CQL_BATCH_FLAG_WITH_NAME_FOR_VALUES,
1834 NULL, HFILL
1838 &hf_cql_batch_flags_bitmap,
1840 "Flags", "cql.batch.flags",
1841 FT_UINT8, BASE_HEX,
1842 NULL, 0x0,
1843 NULL, HFILL
1847 &hf_cql_version,
1849 "Version", "cql.version",
1850 FT_UINT8, BASE_HEX,
1851 NULL, 0x0,
1852 "CQL protocol version (not language version)", HFILL
1856 &hf_cql_protocol_version,
1858 "Protocol version", "cql.protocol_version",
1859 FT_UINT8, BASE_DEC,
1860 NULL, 0x0F,
1861 NULL, HFILL
1865 &hf_cql_direction,
1867 "Direction", "cql.direction",
1868 FT_UINT8, BASE_HEX,
1869 VALS(cql_direction_names), 0xF0,
1870 NULL, HFILL
1874 &hf_cql_flags_bitmap,
1876 "Flags", "cql.flags",
1877 FT_UINT8, BASE_HEX,
1878 NULL, 0x0,
1879 NULL, HFILL
1883 &hf_cql_result_rows_flags_values,
1885 "Rows Result Flags", "cql.result.rows.flags",
1886 FT_UINT32, BASE_DEC,
1887 NULL, 0x0,
1888 NULL, HFILL
1892 &hf_cql_result_prepared_flags_values,
1894 "Prepared Result Flags", "cql.result.prepared.flags",
1895 FT_UINT32, BASE_DEC,
1896 NULL, 0x0,
1897 NULL, HFILL
1901 &hf_cql_result_rows_flag_global_tables_spec,
1903 "Global tables spec.", "cql.result.rows.flags.global_tables",
1904 FT_BOOLEAN, 32,
1905 NULL, CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC,
1906 NULL, HFILL
1910 &hf_cql_result_rows_flag_has_more_pages,
1912 "Has More Pages", "cql.result.rows.flags.has_more_pages",
1913 FT_BOOLEAN, 32,
1914 NULL, CQL_RESULT_ROWS_FLAG_HAS_MORE_PAGES,
1915 NULL, HFILL
1919 &hf_cql_result_rows_flag_no_metadata,
1921 "No Metadata", "cql.result.rows.flags.no_metadata",
1922 FT_BOOLEAN, 32,
1923 NULL, CQL_RESULT_ROWS_FLAG_NO_METADATA,
1924 NULL, HFILL
1928 &hf_cql_flag_compression,
1930 "Compression", "cql.flags.compression",
1931 FT_BOOLEAN, 8,
1932 NULL, CQL_HEADER_FLAG_COMPRESSION,
1933 NULL, HFILL
1937 &hf_cql_flag_tracing,
1939 "Tracing", "cql.flags.tracing",
1940 FT_BOOLEAN, 8,
1941 NULL, CQL_HEADER_FLAG_TRACING,
1942 NULL, HFILL
1946 &hf_cql_flag_custom_payload,
1948 "Custom Payload", "cql.flags.custom_payload",
1949 FT_BOOLEAN, 8,
1950 NULL, CQL_HEADER_FLAG_CUSTOM_PAYLOAD,
1951 NULL, HFILL
1955 &hf_cql_flag_warning,
1957 "Warning", "cql.flags.warning",
1958 FT_BOOLEAN, 8,
1959 NULL, CQL_HEADER_FLAG_WARNING,
1960 NULL, HFILL
1964 &hf_cql_flag_reserved3,
1966 "Reserved", "cql.flags.reserved",
1967 FT_UINT8, BASE_HEX,
1968 NULL, CQL_HEADER_FLAG_V3_RESERVED,
1969 NULL, HFILL
1973 &hf_cql_flag_reserved4,
1975 "Reserved", "cql.flags.reserved",
1976 FT_UINT8, BASE_HEX,
1977 NULL, CQL_HEADER_FLAG_V4_RESERVED,
1978 NULL, HFILL
1982 &hf_cql_query_flags_bitmap,
1984 "Flags", "cql.query.flags",
1985 FT_UINT8, BASE_HEX,
1986 NULL, 0x0,
1987 NULL, HFILL
1991 &hf_cql_query_flags_page_size,
1993 "Page Size", "cql.query.flags.page_size",
1994 FT_BOOLEAN, 8,
1995 NULL, CQL_QUERY_FLAG_PAGE_SIZE,
1996 NULL, HFILL
2000 &hf_cql_query_flags_skip_metadata,
2002 "Skip Metadata", "cql.query.flags.skip_metadata",
2003 FT_BOOLEAN, 8,
2004 NULL, CQL_QUERY_FLAG_SKIP_METADATA,
2005 NULL, HFILL
2009 &hf_cql_query_flags_values,
2011 "Values", "cql.query.flags.values",
2012 FT_BOOLEAN, 8,
2013 NULL, CQL_QUERY_FLAG_VALUES,
2014 NULL, HFILL
2018 &hf_cql_query_flags_default_timestamp,
2020 "Default Timestamp", "cql.query.flags.default_timestamp",
2021 FT_BOOLEAN, 8,
2022 NULL, CQL_QUERY_FLAG_DEFAULT_TIMESTAMP,
2023 NULL, HFILL
2027 &hf_cql_query_flags_names_for_values,
2029 "Names for Values", "cql.query.flags.value_names",
2030 FT_BOOLEAN, 8,
2031 NULL, CQL_QUERY_FLAG_VALUE_NAMES,
2032 NULL, HFILL
2036 &hf_cql_query_flags_paging_state,
2038 "Paging State", "cql.query.flags.paging_state",
2039 FT_BOOLEAN, 8,
2040 NULL, CQL_QUERY_FLAG_PAGING_STATE,
2041 NULL, HFILL
2045 &hf_cql_query_flags_serial_consistency,
2047 "Serial Consistency", "cql.query.flags.serial_consistency",
2048 FT_BOOLEAN, 8,
2049 NULL, CQL_QUERY_FLAG_SERIAL_CONSISTENCY,
2050 NULL, HFILL
2054 &hf_cql_query_flags_reserved3,
2056 "Reserved", "cql.query_flags.reserved",
2057 FT_UINT8, BASE_HEX,
2058 NULL, CQL_QUERY_FLAG_V3_RESERVED,
2059 NULL, HFILL
2063 &hf_cql_stream,
2065 "Stream Identifier", "cql.stream",
2066 FT_INT16, BASE_DEC,
2067 NULL, 0x0,
2068 "Stream identifier this packet belongs to", HFILL
2072 &hf_cql_opcode,
2074 "Opcode", "cql.opcode",
2075 FT_UINT8, BASE_DEC,
2076 VALS(cql_opcode_names), 0x7F, /* Mask the highest-order bit because it indicates message direction, not opcode. */
2077 "CQL operation this packet describes", HFILL
2081 &hf_cql_batch_type,
2083 "Batch type", "cql.batch_type",
2084 FT_UINT8, BASE_DEC,
2085 VALS(cql_batch_type_names), 0x0,
2086 NULL, HFILL
2090 &hf_cql_batch_query_type,
2092 "Batch query type", "cql.batch_query_type",
2093 FT_UINT8, BASE_DEC,
2094 VALS(cql_batch_query_type_names), 0x00,
2095 NULL, HFILL
2099 &hf_cql_length,
2101 "Message Length", "cql.message_length",
2102 FT_UINT32, BASE_DEC,
2103 NULL, 0x0,
2104 NULL, HFILL
2108 &hf_cql_string_map_size,
2110 "String Map Size", "cql.string_map_size",
2111 FT_UINT16, BASE_DEC,
2112 NULL, 0x0,
2113 "Number of strings in the map", HFILL
2117 &hf_cql_string_list_size,
2119 "String List Size", "cql.string_list_size",
2120 FT_UINT16, BASE_DEC,
2121 NULL, 0x0,
2122 "Number of strings in the list", HFILL
2126 &hf_cql_string,
2128 "String", "cql.string",
2129 FT_STRING, BASE_NONE,
2130 NULL, 0x0,
2131 "UTF-8 string value", HFILL
2135 &hf_cql_auth_token,
2137 "Auth Token", "cql.auth_token",
2138 FT_BYTES, BASE_NONE,
2139 NULL, 0x0,
2140 "[bytes] auth token", HFILL
2144 &hf_cql_string_result_rows_global_table_spec_ksname,
2146 "Global Spec Keyspace Name", "cql.result.rows.keyspace_name",
2147 FT_STRING, BASE_NONE,
2148 NULL, 0x0,
2149 NULL, HFILL
2153 &hf_cql_string_result_rows_global_table_spec_table_name,
2155 "Global Spec Table Name", "cql.result.rows.table_name",
2156 FT_STRING, BASE_NONE,
2157 NULL, 0x0,
2158 NULL, HFILL
2162 &hf_cql_string_result_rows_table_name,
2164 "Table Name", "cql.result.rows.table_name",
2165 FT_STRING, BASE_NONE,
2166 NULL, 0x0,
2167 NULL, HFILL
2171 &hf_cql_string_result_rows_udt_name,
2173 "User Defined Type Name", "cql.result.rows.udt_name",
2174 FT_STRING, BASE_NONE,
2175 NULL, 0x0,
2176 NULL, HFILL
2180 &hf_cql_string_result_rows_udt_field_name,
2182 "User Defined Type field Name", "cql.result.rows.udt_field_name",
2183 FT_STRING, BASE_NONE,
2184 NULL, 0x0,
2185 NULL, HFILL
2189 &hf_cql_string_result_rows_udt_size,
2191 "User Defined Type Size", "cql.result.rows.udt_size",
2192 FT_UINT16, BASE_DEC,
2193 NULL, 0x0,
2194 NULL, HFILL
2198 &hf_cql_string_result_rows_list_size,
2200 "List Size", "cql.result.rows.list_size",
2201 FT_INT32, BASE_DEC,
2202 NULL, 0x0,
2203 NULL, HFILL
2207 &hf_cql_string_result_rows_map_size,
2209 "No. of key/value pairs in map", "cql.result.rows.map_size",
2210 FT_INT32, BASE_DEC,
2211 NULL, 0x0,
2212 NULL, HFILL
2216 &hf_cql_string_result_rows_set_size,
2218 "Set Size", "cql.result.rows.set_size",
2219 FT_INT32, BASE_DEC,
2220 NULL, 0x0,
2221 NULL, HFILL
2225 &hf_cql_string_result_rows_keyspace_name,
2227 "Keyspace Name", "cql.result.rows.keyspace_name",
2228 FT_STRING, BASE_NONE,
2229 NULL, 0x0,
2230 NULL, HFILL
2234 &hf_cql_bytesmap_string,
2236 "Key", "cql.bytesmap.key",
2237 FT_STRING, BASE_NONE,
2238 NULL, 0x0,
2239 NULL, HFILL
2243 &hf_cql_string_result_rows_column_name,
2245 "Column Name", "cql.result.rows.column_name",
2246 FT_STRING, BASE_NONE,
2247 NULL, 0x0,
2248 NULL, HFILL
2252 &hf_cql_string_length,
2254 "String Length", "cql.string_length",
2255 FT_UINT32, BASE_DEC,
2256 NULL, 0x0,
2257 "Length of the subsequent string value", HFILL
2261 &hf_cql_consistency,
2263 "Consistency", "cql.consistency",
2264 FT_UINT16, BASE_HEX,
2265 VALS(cql_consistency_names), 0x0,
2266 "CQL consistency level specification", HFILL
2270 &hf_cql_value_count,
2272 "Value count", "cql.value_count",
2273 FT_UINT16, BASE_DEC,
2274 NULL, 0x0,
2275 "Number of subsequent values", HFILL
2279 &hf_cql_bytes_length,
2281 "Bytes length", "cql.bytes_length.int",
2282 FT_INT32, BASE_DEC,
2283 NULL, 0x0,
2284 "Number of subsequent bytes", HFILL
2288 &hf_cql_short_bytes_length,
2290 "Bytes length", "cql.bytes_length.short",
2291 FT_UINT16, BASE_DEC,
2292 NULL, 0x0,
2293 "Number of subsequent bytes", HFILL
2295 }, {
2296 &hf_cql_bytes,
2298 "Bytes", "cql.bytes",
2299 FT_BYTES, BASE_NONE,
2300 NULL, 0x0,
2301 "Raw byte array", HFILL
2305 &hf_cql_bigint,
2307 "Bigint", "cql.bigint",
2308 FT_INT64, BASE_DEC,
2309 NULL, 0x0,
2310 NULL, HFILL
2314 &hf_cql_scale,
2316 "Scale", "cql.scale",
2317 FT_INT32, BASE_DEC,
2318 NULL, 0x0,
2319 NULL, HFILL
2323 &hf_cql_ascii,
2325 "Ascii", "cql.ascii",
2326 FT_STRING, BASE_NONE,
2327 NULL, 0x0,
2328 "An Ascii string", HFILL
2332 &hf_cql_double,
2334 "Double float", "cql.double",
2335 FT_DOUBLE, BASE_NONE,
2336 NULL, 0x0,
2337 NULL, HFILL
2341 &hf_cql_float,
2343 "Float", "cql.float",
2344 FT_FLOAT, BASE_NONE,
2345 NULL, 0x0,
2346 NULL, HFILL
2350 &hf_cql_int,
2352 "Int", "cql.int",
2353 FT_INT32, BASE_DEC,
2354 NULL, 0x0,
2355 NULL, HFILL
2359 &hf_cql_varint_count8,
2361 "Varint", "cql.varint",
2362 FT_UINT8, BASE_DEC,
2363 NULL, 0x0,
2364 NULL, HFILL
2368 &hf_cql_varint_count16,
2370 "Varint", "cql.varint",
2371 FT_UINT16, BASE_DEC,
2372 NULL, 0x0,
2373 NULL, HFILL
2377 &hf_cql_varint_count32,
2379 "Varint", "cql.varint",
2380 FT_UINT32, BASE_DEC,
2381 NULL, 0x0,
2382 NULL, HFILL
2386 &hf_cql_varint_count64,
2388 "Varint", "cql.varint64",
2389 FT_UINT64, BASE_DEC,
2390 NULL, 0x0,
2391 NULL, HFILL
2395 &hf_cql_varchar,
2397 "Varchar", "cql.varchar",
2398 FT_STRING, BASE_NONE,
2399 NULL, 0x0,
2400 NULL, HFILL
2404 &hf_cql_timeuuid,
2406 "Time Uuid", "cql.timeuuid",
2407 FT_GUID, BASE_NONE,
2408 NULL, 0x0,
2409 NULL, HFILL
2413 &hf_cql_custom,
2415 "Custom", "cql.custom",
2416 FT_STRING, BASE_NONE,
2417 NULL, 0x0,
2418 "A custom field", HFILL
2422 &hf_cql_null_value,
2424 "NULL value", "cql.null_value",
2425 FT_NONE, BASE_NONE,
2426 NULL, 0x0,
2427 "A NULL value", HFILL
2431 &hf_cql_raw_compressed_bytes,
2433 "Raw compressed bytes", "cql.raw_compressed_bytes",
2434 FT_BYTES, BASE_NONE,
2435 NULL, 0x0,
2436 "Raw byte that failed to be decompressed", HFILL
2441 &hf_cql_paging_state,
2443 "Paging State", "cql.paging_state",
2444 FT_BYTES, BASE_NONE,
2445 NULL, 0x0,
2446 "Paging state byte array", HFILL
2450 &hf_cql_page_size,
2452 "Page size", "cql.page_size",
2453 FT_INT32, BASE_DEC,
2454 NULL, 0x0,
2455 "Desired page size of result (in CQL3 rows)", HFILL
2459 &hf_cql_response_in,
2461 "Response in", "cql.response_in",
2462 FT_FRAMENUM, BASE_NONE,
2463 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
2464 "The response to this CQL request is in this frame", HFILL
2468 &hf_cql_response_to,
2470 "Request in", "cql.response_to",
2471 FT_FRAMENUM, BASE_NONE,
2472 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
2473 "This is a response to the CQL request in this fame", HFILL
2477 &hf_cql_response_time,
2479 "Response time", "cql.response_time",
2480 FT_RELATIVE_TIME, BASE_NONE,
2481 NULL, 0x0,
2482 "The time between the request and the response", HFILL
2486 &hf_cql_timestamp,
2488 "Timestamp", "cql.timestamp",
2489 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
2490 NULL, 0x0,
2491 NULL, HFILL
2495 &hf_cql_query_id,
2497 "Query ID", "cql.query_id",
2498 FT_BYTES, BASE_NONE,
2499 NULL, 0x0,
2500 "CQL query id resulting from a PREPARE statement", HFILL
2504 &hf_cql_event_type,
2506 "Event Type", "cql.event_type",
2507 FT_STRING, BASE_NONE,
2508 NULL, 0x0,
2509 "CQL Event Type", HFILL
2513 &hf_cql_event_schema_change_type,
2515 "Schema change type", "cql.schema_change_type",
2516 FT_STRING, BASE_NONE,
2517 NULL, 0x0,
2518 "CQL Schema Change Type", HFILL
2522 &hf_cql_event_schema_change_type_target,
2524 "Schema change target", "cql.schema_change_target",
2525 FT_STRING, BASE_NONE,
2526 NULL, 0x0,
2527 "CQL Schema Change target object", HFILL
2531 &hf_cql_event_schema_change_object,
2533 "Schema change event object name", "cql.schema_change_object_name",
2534 FT_STRING, BASE_NONE,
2535 NULL, 0x0,
2536 "CQL Schema Change object name", HFILL
2540 &hf_cql_event_schema_change_keyspace,
2542 "Schema change event keyspace name", "cql.schema_change_keyspace",
2543 FT_STRING, BASE_NONE,
2544 NULL, 0x0,
2545 "CQL Schema Change keyspace name", HFILL
2549 &hf_cql_batch_query_size,
2551 "Batch Query Size", "cql.batch_query_size",
2552 FT_UINT16, BASE_DEC,
2553 NULL, 0x0,
2554 "Number of statements in CQL batch", HFILL
2558 &hf_cql_error_code,
2560 "Error Code", "cql.error_code",
2561 FT_UINT32, BASE_HEX,
2562 VALS(cql_error_names), 0x0,
2563 "Error code from CQL server", HFILL
2567 &hf_cql_result_kind,
2569 "Result Kind", "cql.result.kind",
2570 FT_INT32, BASE_DEC,
2571 VALS(cql_result_kind_names), 0x0,
2572 "Kind of result from CQL server", HFILL
2576 &hf_cql_result_rows_column_count,
2578 "Column Count", "cql.result.rows.column_count",
2579 FT_INT32, BASE_DEC,
2580 NULL, 0x0,
2581 "Count of columns in a rows result from CQL server", HFILL
2585 &hf_cql_result_prepared_pk_count,
2587 "PK Count", "cql.result.prepared.pk_count",
2588 FT_INT32, BASE_DEC,
2589 NULL, 0x0,
2590 "Count of Partition Key columns in a Prepared result from CQL server", HFILL
2594 &hf_cql_result_rows_tuple_size,
2596 "Tuple Size", "cql.result.rows.tuple_size",
2597 FT_UINT16, BASE_DEC,
2598 NULL, 0x0,
2599 "Size of a tuple rows result from CQL server", HFILL
2603 &hf_cql_result_timestamp,
2605 "Timestamp (Epoch Time)", "cql.result.timestamp",
2606 FT_INT64, BASE_DEC,
2607 NULL, 0x0,
2608 "Timestamp result", HFILL
2612 &hf_cql_result_rows_data_type,
2614 "CQL Data Type", "cql.data_type",
2615 FT_UINT16, BASE_DEC,
2616 VALS(cql_result_row_type_names), 0x0,
2617 NULL, HFILL
2621 &hf_cql_result_rows_row_count,
2623 "CQL Result Rows Count", "cql.result.rows.row_count",
2624 FT_INT32, BASE_DEC,
2625 NULL, 0x0,
2626 "Number of rows returned in CQL result", HFILL
2630 &hf_cql_uuid,
2632 "UUID", "cql.uuid",
2633 FT_GUID, BASE_NONE,
2634 NULL, 0x0,
2635 NULL, HFILL
2639 &hf_cql_tracing_uuid,
2641 "Tracing UUID", "cql.tracing_uuid",
2642 FT_GUID, BASE_NONE,
2643 NULL, 0x0,
2644 NULL, HFILL
2648 &hf_cql_port,
2650 "Port", "cql.port",
2651 FT_UINT32, BASE_DEC,
2652 NULL, 0x0,
2653 NULL, HFILL
2657 &hf_cql_boolean,
2659 "Boolean", "cql.boolean",
2660 FT_BOOLEAN, BASE_NONE,
2661 NULL, 0x0,
2662 NULL, HFILL
2666 &hf_cql_ipv4,
2668 "IPV4", "cql.ipv4",
2669 FT_IPv4, BASE_NONE,
2670 NULL, 0x0,
2671 NULL, HFILL
2675 &hf_cql_ipv6,
2677 "IPV6", "cql.ipv6",
2678 FT_IPv6, BASE_NONE,
2679 NULL, 0x0,
2680 NULL, HFILL
2685 static ei_register_info ei[] = {
2686 { &ei_cql_data_not_dissected_yet,
2687 { "cql.ie_data_not_dissected_yet",
2688 PI_UNDECODED, PI_WARN, "IE data not dissected yet", EXPFILL }},
2689 { &ei_cql_unexpected_negative_value,
2690 { "cql.unexpected_negative_value",
2691 PI_UNDECODED, PI_ERROR, "Unexpected negative value", EXPFILL }},
2694 static int* ett[] = {
2695 &ett_cql_protocol,
2696 &ett_cql_version,
2697 &ett_cql_message,
2698 &ett_cql_result_columns,
2699 &ett_cql_results_no_metadata,
2700 &ett_cql_result_map,
2701 &ett_cql_result_set,
2702 &ett_cql_result_metadata,
2703 &ett_cql_result_metadata_colspec,
2704 &ett_cql_result_rows,
2705 &ett_cql_header_flags_bitmap,
2706 &ett_cql_query_flags_bitmap,
2707 &ett_cql_batch_flags_bitmap,
2708 &ett_cql_custom_payload
2711 proto_cql = proto_register_protocol("Cassandra CQL Protocol", "CQL", "cql" );
2712 register_dissector("cql", dissect_cql_tcp, proto_cql);
2714 proto_register_field_array(proto_cql, hf, array_length(hf));
2715 proto_register_subtree_array(ett, array_length(ett));
2717 expert_cql = expert_register_protocol(proto_cql);
2718 expert_register_field_array(expert_cql, ei, array_length(ei));
2722 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2724 * Local variables:
2725 * c-basic-offset: 8
2726 * tab-width: 8
2727 * indent-tabs-mode: t
2728 * End:
2730 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2731 * :indentSize=8:tabSize=8:noTabs=false: