Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-cql.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-cql.c
2
 * Routines for Apache Cassandra CQL dissection
3
 * Copyright 2015, Aaron Ten Clay <aarontc@aarontc.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
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
15
 */
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
30
31
14
#define CQL_DEFAULT_PORT 9042 /* Not IANA registered */
32
33
/* the code can reasonably attempt to decompress buffer up to 10MB */
34
#define MAX_UNCOMPRESSED_SIZE (10 * 1024 * 1024)
35
36
void proto_reg_handoff_cql(void);
37
void proto_register_cql(void);
38
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 */
56
/*
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;
62
*/
63
/* Batch flags */
64
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;
70
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;
116
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;
126
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;
134
135
static int hf_cql_result_prepared_pk_count;
136
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;
150
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;
164
165
static int hf_cql_response_in;
166
static int hf_cql_response_to;
167
static int hf_cql_response_time;
168
169
static int hf_cql_ipv4;
170
static int hf_cql_ipv6;
171
172
/* desegmentation of CQL */
173
static bool cql_desegment = true;
174
175
static expert_field ei_cql_data_not_dissected_yet;
176
static expert_field ei_cql_unexpected_negative_value;
177
178
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;
184
185
typedef struct _cql_conversation_info_type {
186
  wmem_map_t* streams;
187
} cql_conversation_type;
188
189
static const value_string cql_direction_names[] = {
190
  { 0x0, "Request" },
191
  { 0x8, "Response" },
192
  { 0x0, NULL }
193
};
194
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;
200
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;
220
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 }
239
};
240
241
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;
250
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;
261
262
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;
268
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;
282
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 }
296
};
297
298
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;
304
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 }
310
};
311
312
typedef enum {
313
  CQL_BATCH_QUERY_TYPE_QUERY = 0,
314
  CQL_BATCH_QUERY_TYPE_PREPARED = 1
315
} cql_batch_query_types;
316
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 }
321
};
322
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;
330
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 }
338
};
339
340
341
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;
369
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 }
397
};
398
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;
420
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}
441
};
442
443
static int
444
dissect_cql_query_parameters(proto_tree* cql_subtree, tvbuff_t* tvb, int offset, int execute)
445
0
{
446
0
  int32_t bytes_length = 0;
447
0
  uint32_t flags = 0;
448
0
  uint64_t i = 0;
449
0
  uint32_t string_length = 0;
450
0
  uint32_t value_count = 0;
451
452
0
  static int * const cql_query_bitmaps[] = {
453
0
    &hf_cql_query_flags_values,
454
0
    &hf_cql_query_flags_skip_metadata,
455
0
    &hf_cql_query_flags_page_size,
456
0
    &hf_cql_query_flags_paging_state,
457
0
    &hf_cql_query_flags_serial_consistency,
458
0
    &hf_cql_query_flags_default_timestamp,
459
0
    &hf_cql_query_flags_names_for_values,
460
0
    &hf_cql_query_flags_reserved3,
461
0
    NULL
462
0
  };
463
464
  /* consistency */
465
0
  proto_tree_add_item(cql_subtree, hf_cql_consistency, tvb, offset, 2, ENC_BIG_ENDIAN);
466
0
  offset += 2;
467
468
  /* flags */
469
0
  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
0
  flags = tvb_get_uint8(tvb, offset);
471
0
  offset += 1;
472
473
0
  if(flags & CQL_QUERY_FLAG_VALUES) {
474
0
    proto_tree_add_item_ret_uint(cql_subtree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &value_count);
475
0
    offset += 2;
476
0
    for (i = 0; i < value_count; ++i) {
477
0
      if (!execute && flags & CQL_QUERY_FLAG_VALUE_NAMES) {
478
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
479
0
        offset += 2;
480
0
        proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
481
0
        offset += string_length;
482
0
      }
483
0
      proto_tree_add_item_ret_int(cql_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
484
0
      offset += 4;
485
0
      if (bytes_length > 0) {
486
0
        proto_tree_add_item(cql_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
487
0
        offset += bytes_length;
488
0
      }
489
0
    }
490
0
  }
491
492
0
  if (flags & CQL_QUERY_FLAG_PAGE_SIZE) {
493
0
    proto_tree_add_item(cql_subtree, hf_cql_page_size, tvb, offset, 4, ENC_BIG_ENDIAN);
494
0
    offset += 4;
495
0
  }
496
497
0
  if (flags & CQL_QUERY_FLAG_PAGING_STATE) {
498
0
    proto_tree_add_item_ret_int(cql_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
499
0
    offset += 4;
500
0
    if (bytes_length > 0) {
501
0
      proto_tree_add_item(cql_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
502
0
      offset += bytes_length;
503
0
    }
504
0
  }
505
506
0
  if (flags & CQL_QUERY_FLAG_SERIAL_CONSISTENCY) {
507
0
    proto_tree_add_item(cql_subtree, hf_cql_consistency, tvb, offset, 2, ENC_BIG_ENDIAN);
508
0
    offset += 2;
509
0
  }
510
511
0
  if (flags & CQL_QUERY_FLAG_DEFAULT_TIMESTAMP) {
512
0
    proto_tree_add_item(cql_subtree, hf_cql_timestamp, tvb, offset, 8, ENC_TIME_USECS|ENC_BIG_ENDIAN);
513
0
    offset += 8;
514
0
  }
515
516
0
  return offset;
517
0
}
518
519
static unsigned
520
get_cql_pdu_len(packet_info* pinfo _U_, tvbuff_t* tvb, int offset, void* data _U_)
521
94
{
522
  /* CQL has 32-bit length at 5th byte in frame. */
523
94
  uint32_t length = tvb_get_ntohl(tvb, offset + 5);
524
525
  /* Include length of frame header. */
526
94
  return length + 9;
527
94
}
528
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)
534
76
{
535
76
  cql_transaction_type* trans;
536
76
  wmem_list_t* list;
537
538
76
  list = (wmem_list_t*)wmem_map_lookup(conv->streams, GINT_TO_POINTER(stream));
539
76
  if(!list) {
540
20
    list = wmem_list_new(wmem_file_scope());
541
56
  } else {
542
56
    wmem_map_remove(conv->streams, GINT_TO_POINTER(stream));
543
56
  }
544
545
76
  trans = wmem_new(wmem_file_scope(), cql_transaction_type);
546
76
  if (fake) {
547
12
    trans->req_frame = 0;
548
64
  } else {
549
64
    trans->req_frame = pinfo->fd->num;
550
64
  }
551
76
  trans->rep_frame = 0;
552
76
  trans->req_time = pinfo->abs_ts;
553
554
76
  wmem_list_append(list, (void *)trans);
555
76
  wmem_map_insert(conv->streams, GINT_TO_POINTER(stream), (void*)list);
556
557
76
  return trans;
558
76
}
559
560
static cql_transaction_type*
561
cql_enrich_transaction_with_response(cql_conversation_type* conv,
562
          packet_info* pinfo,
563
          int32_t stream)
564
30
{
565
30
  cql_transaction_type* trans;
566
30
  wmem_list_frame_t* frame;
567
30
  wmem_list_t* list;
568
569
30
  list = (wmem_list_t*)wmem_map_lookup(conv->streams, GINT_TO_POINTER(stream));
570
30
  if (!list) {
571
12
    return NULL;
572
12
  }
573
574
18
  frame = wmem_list_tail(list);
575
18
  if (!frame) {
576
0
    return NULL;
577
0
  }
578
579
18
  trans = (cql_transaction_type *)wmem_list_frame_data(frame);
580
18
  if (!trans) {
581
0
    return NULL;
582
0
  }
583
584
18
  trans->rep_frame = pinfo->fd->num;
585
586
18
  return trans;
587
18
}
588
589
static cql_transaction_type*
590
cql_transaction_lookup(cql_conversation_type* conv,
591
      packet_info* pinfo,
592
      int32_t stream)
593
0
{
594
0
  wmem_list_frame_t* frame;
595
0
  wmem_list_t* list;
596
597
0
  list = (wmem_list_t*)wmem_map_lookup(conv->streams, GINT_TO_POINTER(stream));
598
0
  if (!list) {
599
0
    return NULL;
600
0
  }
601
602
0
  frame = wmem_list_head(list);
603
0
  if (!frame) {
604
0
    return NULL;
605
0
  }
606
607
0
  do {
608
0
    cql_transaction_type* trans = NULL;
609
0
    trans = (cql_transaction_type *)wmem_list_frame_data(frame);
610
0
    if (trans->req_frame == pinfo->fd->num || trans->rep_frame == pinfo->fd->num) {
611
0
      return trans;
612
0
    }
613
0
  } while ((frame = wmem_list_frame_next(frame)));
614
615
0
  return NULL;
616
0
}
617
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;
624
625
626
// NOLINTNEXTLINE(misc-no-recursion)
627
static int parse_option(proto_tree* metadata_subtree, packet_info *pinfo, tvbuff_t* tvb, int offset)
628
0
{
629
0
  uint32_t data_type = 0;
630
0
  uint32_t string_length = 0;
631
0
  uint32_t tuple_size = 0;
632
0
  uint32_t udt_size = 0;
633
0
  uint32_t i = 0;
634
635
0
  proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_data_type, tvb, offset, 2, ENC_BIG_ENDIAN, &data_type);
636
0
  offset += 2;
637
0
  increment_dissection_depth(pinfo);
638
0
  switch (data_type) {
639
0
    case CQL_RESULT_ROW_TYPE_LIST:
640
0
      offset = parse_option(metadata_subtree, pinfo, tvb, offset);
641
0
      break;
642
0
    case CQL_RESULT_ROW_TYPE_MAP:
643
0
      offset = parse_option(metadata_subtree, pinfo, tvb, offset);
644
0
      offset = parse_option(metadata_subtree, pinfo, tvb, offset);
645
0
      break;
646
0
    case CQL_RESULT_ROW_TYPE_SET:
647
0
      offset = parse_option(metadata_subtree, pinfo, tvb, offset);
648
0
      break;
649
0
    case CQL_RESULT_ROW_TYPE_UDT:
650
      /* keyspace */
651
0
      proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
652
0
      offset += 2;
653
0
      proto_tree_add_item(metadata_subtree, hf_cql_string_result_rows_keyspace_name, tvb, offset, string_length, ENC_UTF_8);
654
0
      offset += string_length;
655
656
      /* UDT name */
657
0
      proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
658
0
      offset += 2;
659
0
      proto_tree_add_item(metadata_subtree, hf_cql_string_result_rows_udt_name, tvb, offset, string_length, ENC_UTF_8);
660
0
      offset += string_length;
661
662
      /* UDT size */
663
0
      proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_result_rows_udt_size, tvb, offset, 2, ENC_BIG_ENDIAN, &udt_size);
664
0
      offset += 2;
665
666
0
      for (i = 0; i < udt_size; i++) {
667
        /* UDT field name */
668
0
        proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
669
0
        offset += 2;
670
0
        proto_tree_add_item(metadata_subtree, hf_cql_string_result_rows_udt_field_name, tvb, offset, string_length, ENC_UTF_8);
671
0
        offset += string_length;
672
673
        /* UDT field option */
674
0
        offset = parse_option(metadata_subtree, pinfo, tvb, offset);
675
0
      }
676
0
      break;
677
0
    case CQL_RESULT_ROW_TYPE_TUPLE:
678
0
      proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_tuple_size, tvb, offset, 2, ENC_BIG_ENDIAN, &tuple_size);
679
0
      offset += 2;
680
0
      for (i = 0; i < tuple_size; i++) {
681
0
        offset = parse_option(metadata_subtree, pinfo, tvb, offset);
682
0
      }
683
0
      break;
684
0
    default:
685
0
      break;
686
0
  }
687
0
  decrement_dissection_depth(pinfo);
688
689
0
  return offset;
690
0
}
691
692
static void add_varint_item(proto_tree *tree, tvbuff_t *tvb, const int offset, int length)
693
0
{
694
0
  switch (length)
695
0
  {
696
0
  case 1:
697
0
    proto_tree_add_item(tree, hf_cql_varint_count8,  tvb, offset, 1, ENC_BIG_ENDIAN);
698
0
    break;
699
0
  case 2:
700
0
    proto_tree_add_item(tree, hf_cql_varint_count16, tvb, offset, 2, ENC_BIG_ENDIAN);
701
0
    break;
702
0
  case 3:
703
0
    proto_tree_add_item(tree, hf_cql_varint_count32, tvb, offset, 3, ENC_BIG_ENDIAN);
704
0
    break;
705
0
  case 4:
706
0
    proto_tree_add_item(tree, hf_cql_varint_count32, tvb, offset, 4, ENC_BIG_ENDIAN);
707
0
    break;
708
0
  case 5:
709
0
    proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 5, ENC_BIG_ENDIAN);
710
0
    break;
711
0
  case 6:
712
0
    proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 6, ENC_BIG_ENDIAN);
713
0
    break;
714
0
  case 7:
715
0
    proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 7, ENC_BIG_ENDIAN);
716
0
    break;
717
0
  case 8:
718
0
    proto_tree_add_item(tree, hf_cql_varint_count64, tvb, offset, 8, ENC_BIG_ENDIAN);
719
0
    break;
720
0
  }
721
0
}
722
723
static void add_cql_uuid(proto_tree* tree, int hf_uuid, tvbuff_t* tvb, int offset)
724
4
{
725
4
  e_guid_t guid;
726
4
  int i;
727
728
4
  guid.data1 = tvb_get_letohl(tvb, offset+12);
729
4
  guid.data2 = tvb_get_letohl(tvb, offset+10);
730
4
  guid.data3 = tvb_get_letohl(tvb, offset+8);
731
732
12
  for (i = 0; i < 8; i++)
733
8
  {
734
8
    guid.data4[i] = tvb_get_uint8(tvb, offset+(7-i));
735
8
  }
736
737
4
  proto_tree_add_guid(tree, hf_uuid, tvb, offset, 16, &guid);
738
4
}
739
740
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)
743
0
{
744
0
  uint32_t data_type = 0;
745
0
  uint32_t string_length = 0;
746
0
  int32_t bytes_length = 0;
747
0
  uint32_t tuple_size = 0;
748
0
  int32_t list_size = 0;
749
0
  int32_t map_size = 0;
750
0
  int32_t set_size = 0;
751
0
  uint32_t udt_size = 0;
752
0
  proto_item *item;
753
0
  proto_item *sub_item;
754
0
  uint32_t i = 0;
755
0
  int32_t j = 0;
756
0
  int offset_metadata_backup = 0;
757
0
  uint32_t addr4;
758
0
  ws_in6_addr addr6;
759
0
  uint32_t port_number;
760
0
  proto_tree* map_subtree;
761
0
  proto_tree* set_subtree;
762
763
0
  proto_tree_add_item_ret_int(columns_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
764
0
  offset += 4;
765
766
0
  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
0
  proto_item_set_hidden(item);
768
0
  *offset_metadata += 2;
769
770
0
  if (bytes_length == -1) { // value is NULL, but need to skip metadata offsets
771
0
    proto_tree_add_item(columns_subtree, hf_cql_null_value, tvb, offset, 0, ENC_NA);
772
0
    if (data_type == CQL_RESULT_ROW_TYPE_MAP) {
773
0
      *offset_metadata += 4; /* skip the type fields of *both* key and value in the map in the metadata */
774
0
    } else if (data_type == CQL_RESULT_ROW_TYPE_SET) {
775
0
      *offset_metadata += 2; /* skip the type field of the elements in the set in the metadata */
776
0
    }
777
0
    return offset;
778
0
  }
779
780
0
  increment_dissection_depth(pinfo);
781
0
  switch (data_type) {
782
0
    case CQL_RESULT_ROW_TYPE_CUSTOM:
783
0
      proto_tree_add_item(columns_subtree, hf_cql_custom, tvb, offset, bytes_length, ENC_UTF_8);
784
0
      offset += bytes_length;
785
0
      break;
786
0
    case CQL_RESULT_ROW_TYPE_ASCII:
787
0
      proto_tree_add_item(columns_subtree, hf_cql_ascii, tvb, offset, bytes_length, ENC_ASCII);
788
0
      offset += bytes_length;
789
0
      break;
790
0
    case CQL_RESULT_ROW_TYPE_BIGINT:
791
0
      proto_tree_add_item(columns_subtree, hf_cql_bigint, tvb, offset, 8, ENC_BIG_ENDIAN);
792
0
      offset += 8;
793
0
      break;
794
0
    case CQL_RESULT_ROW_TYPE_BLOB:
795
0
      proto_tree_add_item(columns_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
796
0
      offset += bytes_length;
797
0
      break;
798
0
    case CQL_RESULT_ROW_TYPE_BOOLEAN:
799
0
      proto_tree_add_boolean(columns_subtree, hf_cql_boolean, tvb, offset, 1, true);
800
0
      offset += 1;
801
0
      break;
802
0
    case CQL_RESULT_ROW_TYPE_COUNTER:
803
0
      break;
804
0
    case CQL_RESULT_ROW_TYPE_DECIMAL:
805
0
      proto_tree_add_item(columns_subtree, hf_cql_scale, tvb, offset, 4, ENC_BIG_ENDIAN);
806
0
      offset += 4;
807
0
      add_varint_item(columns_subtree, tvb, offset, bytes_length - 4);
808
0
      offset += bytes_length - 4;
809
0
      break;
810
0
    case CQL_RESULT_ROW_TYPE_DOUBLE:
811
0
      proto_tree_add_item(columns_subtree, hf_cql_double, tvb, offset, 8, ENC_BIG_ENDIAN);
812
0
      offset += 8;
813
0
      break;
814
0
    case CQL_RESULT_ROW_TYPE_FLOAT:
815
0
      proto_tree_add_item(columns_subtree, hf_cql_float, tvb, offset, 4, ENC_BIG_ENDIAN);
816
0
      offset += 4;
817
0
      break;
818
0
    case CQL_RESULT_ROW_TYPE_INT:
819
0
      proto_tree_add_item(columns_subtree, hf_cql_int, tvb, offset, 4, ENC_BIG_ENDIAN);
820
0
      offset += 4;
821
0
      break;
822
0
    case CQL_RESULT_ROW_TYPE_TIMESTAMP:
823
0
      proto_tree_add_item(columns_subtree, hf_cql_result_timestamp, tvb, offset, 8, ENC_BIG_ENDIAN);
824
0
      offset += 8;
825
0
      break;
826
0
    case CQL_RESULT_ROW_TYPE_UUID:
827
0
      add_cql_uuid(columns_subtree, hf_cql_uuid, tvb, offset);
828
0
      offset += 16;
829
0
      break;
830
0
    case CQL_RESULT_ROW_TYPE_VARCHAR:
831
0
      proto_tree_add_item(columns_subtree, hf_cql_varchar, tvb, offset, bytes_length, ENC_ASCII);
832
0
      offset += bytes_length;
833
0
      break;
834
0
    case CQL_RESULT_ROW_TYPE_VARINT:
835
0
      add_varint_item(columns_subtree, tvb, offset, bytes_length);
836
0
      offset += bytes_length;
837
0
      break;
838
0
    case CQL_RESULT_ROW_TYPE_TIMEUUID:
839
0
      add_cql_uuid(columns_subtree, hf_cql_timeuuid, tvb, offset);
840
0
      offset += 16;
841
0
      break;
842
0
    case CQL_RESULT_ROW_TYPE_INET:
843
0
      switch (bytes_length) {
844
0
        case 4:
845
0
        case 8:
846
0
          addr4 = tvb_get_ipv4(tvb, offset);
847
0
          proto_tree_add_ipv4_format_value(columns_subtree, hf_cql_ipv4, tvb, offset, 4, addr4, "%s", get_hostname(addr4));
848
0
          offset += 4;
849
0
        break;
850
0
        case 16:
851
0
        case 20:
852
0
          tvb_get_ipv6(tvb, offset, &addr6);
853
0
          proto_tree_add_ipv6_format_value(columns_subtree, hf_cql_ipv6, tvb, offset, 16, &addr6, "%s", get_hostname6(&addr6));
854
0
          offset += 16;
855
0
          break;
856
0
        default:
857
0
          break;
858
0
      }
859
      /* port number is optional */
860
0
      if (bytes_length == 16 || bytes_length == 20) {
861
0
        sub_item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_port, tvb, offset, 4, ENC_BIG_ENDIAN, &port_number);
862
0
        proto_item_append_text(sub_item, " (%u)", port_number);
863
0
        offset += 4;
864
0
      }
865
0
      break;
866
0
    case CQL_RESULT_ROW_TYPE_DATE:
867
0
      break;
868
0
    case CQL_RESULT_ROW_TYPE_TIME:
869
0
      break;
870
0
    case CQL_RESULT_ROW_TYPE_SMALLINT:
871
0
      break;
872
0
    case CQL_RESULT_ROW_TYPE_TINYINT:
873
0
      break;
874
0
    case CQL_RESULT_ROW_TYPE_LIST:
875
0
      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
0
      if (list_size < 0) {
877
0
        expert_add_info(pinfo, item, &ei_cql_unexpected_negative_value);
878
0
        decrement_dissection_depth(pinfo);
879
0
        return tvb_reported_length(tvb);
880
0
      }
881
0
      offset += 4;
882
0
      offset_metadata_backup = *offset_metadata;
883
0
      for (j = 0; j < list_size; j++) {
884
0
        *offset_metadata = offset_metadata_backup;
885
0
        offset = parse_value(columns_subtree, pinfo, tvb, offset_metadata, offset);
886
0
      }
887
0
      break;
888
0
    case CQL_RESULT_ROW_TYPE_MAP:
889
0
      map_subtree = proto_tree_add_subtree(columns_subtree, tvb, offset, 0, ett_cql_result_map, NULL, "Map");
890
0
      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
0
      offset += 4;
892
0
      proto_item_append_text(map_subtree, " with %" PRId32 " element(s)", map_size);
893
0
      if (map_size < 0) {
894
0
        expert_add_info(pinfo, item, &ei_cql_unexpected_negative_value);
895
0
        decrement_dissection_depth(pinfo);
896
0
        return tvb_reported_length(tvb);
897
0
      } else if (map_size == 0) {
898
0
        *offset_metadata += 4; /* skip the type fields of *both* key and value in the map in the metadata */
899
0
      } else {
900
0
        offset_metadata_backup = *offset_metadata;
901
0
        for (j = 0; j < map_size; j++) {
902
0
          *offset_metadata = offset_metadata_backup;
903
0
          offset = parse_value(map_subtree, pinfo, tvb, offset_metadata, offset);
904
0
          offset = parse_value(map_subtree, pinfo, tvb, offset_metadata, offset);
905
0
        }
906
0
      }
907
0
      break;
908
0
    case CQL_RESULT_ROW_TYPE_SET:
909
0
      set_subtree = proto_tree_add_subtree(columns_subtree, tvb, offset, 0, ett_cql_result_set, NULL, "Set");
910
0
      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
0
      offset += 4;
912
0
      if (set_size < 0) {
913
0
        expert_add_info(pinfo, item, &ei_cql_unexpected_negative_value);
914
0
        decrement_dissection_depth(pinfo);
915
0
        return tvb_reported_length(tvb);
916
0
      } else if (set_size == 0) {
917
0
        *offset_metadata += 2; /* skip the type field of the elements in the set in the metadata */
918
0
      } else {
919
0
        offset_metadata_backup = *offset_metadata;
920
0
        for (j = 0; j < set_size; j++) {
921
0
          *offset_metadata = offset_metadata_backup;
922
0
          offset = parse_value(set_subtree, pinfo, tvb, offset_metadata, offset);
923
0
        }
924
0
      }
925
0
      break;
926
0
    case CQL_RESULT_ROW_TYPE_UDT:
927
      /* keyspace */
928
0
      item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &string_length);
929
0
      proto_item_set_hidden(item);
930
0
      *offset_metadata += 2;
931
0
      item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_keyspace_name, tvb, *offset_metadata, string_length, ENC_UTF_8);
932
0
      proto_item_set_hidden(item);
933
0
      *offset_metadata += string_length;
934
935
      /* UDT name */
936
0
      item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &string_length);
937
0
      proto_item_set_hidden(item);
938
0
      *offset_metadata += 2;
939
0
      item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_udt_name, tvb, *offset_metadata, string_length, ENC_UTF_8);
940
0
      proto_item_set_hidden(item);
941
0
      *offset_metadata += string_length;
942
943
      /* UDT size */
944
0
      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
0
      proto_item_set_hidden(item);
946
0
      *offset_metadata += 2;
947
948
0
      for (i = 0; i < udt_size; i++) {
949
        /* UDT field name */
950
0
        item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, *offset_metadata, 2, ENC_BIG_ENDIAN, &string_length);
951
0
        proto_item_set_hidden(item);
952
0
        *offset_metadata += 2;
953
0
        item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_udt_field_name, tvb, *offset_metadata, string_length, ENC_UTF_8);
954
0
        proto_item_set_hidden(item);
955
0
        *offset_metadata += string_length;
956
957
        /* UDT field option */
958
0
        offset = parse_value(columns_subtree, pinfo, tvb, offset_metadata, offset);
959
0
      }
960
0
      break;
961
0
    case CQL_RESULT_ROW_TYPE_TUPLE:
962
0
      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
0
      proto_item_set_hidden(item);
964
0
      *offset_metadata += 2;
965
0
      for (i = 0; i < tuple_size; i++) {
966
0
        offset = parse_value(columns_subtree, pinfo, tvb, offset_metadata, offset);
967
0
      }
968
0
      break;
969
0
    default:
970
0
      break;
971
0
  }
972
0
  decrement_dissection_depth(pinfo);
973
974
0
  return offset;
975
0
}
976
977
static int parse_result_metadata_more_pages(proto_tree* tree, tvbuff_t* tvb, int offset, int flags)
978
0
{
979
0
  int32_t bytes_length = 0;
980
981
0
  if (flags & CQL_RESULT_ROWS_FLAG_HAS_MORE_PAGES) {
982
    /* show paging state */
983
0
    proto_tree_add_item_ret_int(tree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
984
0
    offset += 4;
985
0
    if (bytes_length > 0) {
986
0
      proto_tree_add_item(tree, hf_cql_paging_state, tvb, offset, bytes_length, ENC_NA);
987
0
      offset += bytes_length;
988
0
    }
989
0
  }
990
991
0
  return offset;
992
0
}
993
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)
996
0
{
997
0
  proto_tree* col_spec_subtree = NULL;
998
0
  uint32_t string_length = 0;
999
0
  int j;
1000
1001
0
  if (flags & CQL_RESULT_ROWS_FLAG_NO_METADATA) {
1002
    /* There will be no col_spec elements. */
1003
0
    return offset;
1004
0
  }
1005
1006
0
  if ((flags & (CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC | CQL_RESULT_ROWS_FLAG_NO_METADATA)) == CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC) {
1007
0
    proto_tree_add_item_ret_uint(tree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1008
0
    offset += 2;
1009
0
    proto_tree_add_item(tree, hf_cql_string_result_rows_global_table_spec_ksname, tvb, offset, string_length, ENC_UTF_8);
1010
0
    offset += string_length;
1011
1012
0
    proto_tree_add_item_ret_uint(tree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1013
0
    offset += 2;
1014
0
    proto_tree_add_item(tree, hf_cql_string_result_rows_global_table_spec_table_name, tvb, offset, string_length, ENC_UTF_8);
1015
0
    offset += string_length;
1016
0
  }
1017
1018
0
  for (j = 0; j < result_rows_columns_count; ++j) {
1019
0
    col_spec_subtree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_cql_result_metadata_colspec, NULL, "Column");
1020
0
    proto_item_append_text(col_spec_subtree, " # %" PRId32 " specification", j + 1);
1021
0
    if (!(flags & CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC)) {
1022
      /* ksname and tablename */
1023
0
      proto_tree_add_item_ret_uint(col_spec_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1024
0
      offset += 2;
1025
0
      proto_tree_add_item(col_spec_subtree, hf_cql_string_result_rows_keyspace_name, tvb, offset, string_length, ENC_UTF_8);
1026
0
      offset += string_length;
1027
0
      proto_tree_add_item_ret_uint(col_spec_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1028
0
      offset += 2;
1029
0
      proto_tree_add_item(col_spec_subtree, hf_cql_string_result_rows_table_name, tvb, offset, string_length, ENC_UTF_8);
1030
0
      offset += string_length;
1031
0
    }
1032
1033
    /* column name */
1034
0
    proto_tree_add_item_ret_uint(col_spec_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1035
0
    offset += 2;
1036
0
    proto_tree_add_item(col_spec_subtree, hf_cql_string_result_rows_column_name, tvb, offset, string_length, ENC_UTF_8);
1037
0
    offset += string_length;
1038
1039
    /* type "option" */
1040
0
    offset = parse_option(col_spec_subtree, pinfo, tvb, offset);
1041
0
  }
1042
1043
0
  return offset;
1044
0
}
1045
1046
1047
static int parse_result_schema_change(proto_tree* subtree, packet_info *pinfo, tvbuff_t* tvb,
1048
      int offset)
1049
0
{
1050
0
  uint32_t short_bytes_length = 0;
1051
0
  const uint8_t* string_event_type_target = NULL;
1052
1053
0
  proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1054
0
  offset += 2;
1055
0
  proto_tree_add_item(subtree, hf_cql_event_schema_change_type, tvb, offset, short_bytes_length, ENC_UTF_8);
1056
0
  offset += short_bytes_length;
1057
0
  proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1058
0
  offset += 2;
1059
0
  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
0
  offset += short_bytes_length;
1061
  /* all targets have the keyspace as the first parameter*/
1062
0
  proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1063
0
  offset += 2;
1064
0
  proto_tree_add_item(subtree, hf_cql_event_schema_change_keyspace, tvb, offset, short_bytes_length, ENC_UTF_8);
1065
0
  offset += short_bytes_length;
1066
0
  if ((strcmp(string_event_type_target, "TABLE") == 0) || (strcmp(string_event_type_target, "TYPE") == 0)) {
1067
0
    proto_tree_add_item_ret_uint(subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1068
0
    offset += 2;
1069
0
    proto_tree_add_item(subtree, hf_cql_event_schema_change_object, tvb, offset, short_bytes_length, ENC_UTF_8);
1070
0
  } 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)
1074
    */
1075
0
  }
1076
1077
0
  return offset;
1078
0
}
1079
1080
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)
1083
0
{
1084
0
  int32_t result_rows_flags = 0;
1085
0
  int string_length;
1086
0
  int shadow_offset;
1087
0
  proto_item *item;
1088
0
  int j;
1089
1090
0
  shadow_offset = offset_metadata;
1091
0
  for (j = 0; j < result_rows_columns_count; ++j) {
1092
0
    if (!(result_rows_flags & CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC)) {
1093
      /* ksname and tablename */
1094
0
      item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, shadow_offset, 2, ENC_BIG_ENDIAN, &string_length);
1095
0
      proto_item_set_hidden(item);
1096
0
      shadow_offset += 2;
1097
0
      item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_keyspace_name, tvb, shadow_offset, string_length, ENC_UTF_8);
1098
0
      proto_item_set_hidden(item);
1099
0
      shadow_offset += string_length;
1100
0
      item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, shadow_offset, 2, ENC_BIG_ENDIAN, &string_length);
1101
0
      proto_item_set_hidden(item);
1102
0
      shadow_offset += 2;
1103
0
      item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_table_name, tvb, shadow_offset, string_length, ENC_UTF_8);
1104
0
      proto_item_set_hidden(item);
1105
0
      shadow_offset += string_length;
1106
0
    }
1107
1108
    /* column name */
1109
0
    item = proto_tree_add_item_ret_uint(columns_subtree, hf_cql_string_length, tvb, shadow_offset, 2, ENC_BIG_ENDIAN, &string_length);
1110
0
    proto_item_set_hidden(item);
1111
0
    shadow_offset += 2;
1112
0
    item = proto_tree_add_item(columns_subtree, hf_cql_string_result_rows_column_name, tvb, shadow_offset, string_length, ENC_UTF_8);
1113
0
    proto_item_set_hidden(item);
1114
0
    shadow_offset += string_length;
1115
1116
0
    offset = parse_value(columns_subtree, pinfo, tvb, &shadow_offset, offset);
1117
0
  }
1118
1119
0
  return offset;
1120
0
}
1121
1122
static int
1123
dissect_cql_tcp_pdu(tvbuff_t* raw_tvb, packet_info* pinfo, proto_tree* tree, void* data _U_)
1124
94
{
1125
94
  proto_item* ti;
1126
94
  tvbuff_t* tvb = NULL;
1127
94
  proto_tree* cql_tree;
1128
94
  proto_tree* version_tree;
1129
94
  proto_tree* cql_subtree = NULL;
1130
94
  proto_tree* cust_payload_tree = NULL;
1131
94
  proto_tree* rows_subtree = NULL;
1132
94
  proto_tree* columns_subtree = NULL;
1133
94
  proto_tree* single_column_subtree = NULL;
1134
94
  proto_tree* metadata_subtree = NULL;
1135
94
  proto_tree* prepared_metadata_subtree = NULL;
1136
1137
94
  int offset = 0;
1138
94
  int offset_row_metadata = 0;
1139
94
  uint8_t flags = 0;
1140
94
  uint8_t first_byte = 0;
1141
94
  uint8_t cql_version = 0;
1142
94
  uint8_t server_to_client = 0;
1143
94
  uint8_t opcode = 0;
1144
94
  uint32_t message_length = 0;
1145
94
  uint32_t map_size = 0;
1146
94
  uint64_t i = 0;
1147
94
  uint32_t string_length = 0;
1148
94
  int32_t stream = 0;
1149
94
  uint32_t batch_size = 0;
1150
94
  uint32_t batch_query_type = 0;
1151
94
  uint32_t result_kind = 0;
1152
94
  int32_t result_rows_flags = 0;
1153
94
  int32_t result_rows_columns_count = 0;
1154
94
  int32_t result_prepared_flags = 0;
1155
94
  int32_t result_prepared_pk_count = 0;
1156
94
  int64_t j = 0;
1157
94
  int64_t k = 0;
1158
94
  uint32_t short_bytes_length = 0;
1159
94
  int32_t bytes_length = 0;
1160
94
  int32_t result_rows_row_count = 0;
1161
1162
94
  conversation_t* conversation;
1163
94
  cql_conversation_type* cql_conv;
1164
94
  cql_transaction_type* cql_trans = NULL;
1165
94
  cql_compression_level compression_level = CQL_COMPRESSION_NONE;
1166
1167
94
  static int * const cql_batch_flags_bitmaps[] = {
1168
94
    &hf_cql_batch_flag_serial_consistency,
1169
94
    &hf_cql_batch_flag_default_timestamp,
1170
94
    &hf_cql_batch_flag_with_name_for_values,
1171
94
    NULL
1172
94
  };
1173
1174
94
  static int * const cql_header_bitmaps_v3[] = {
1175
94
    &hf_cql_flag_compression,
1176
94
    &hf_cql_flag_tracing,
1177
94
    &hf_cql_flag_reserved3,
1178
94
    NULL
1179
94
  };
1180
1181
94
  static int * const cql_header_bitmaps_v4[] = {
1182
94
    &hf_cql_flag_compression,
1183
94
    &hf_cql_flag_tracing,
1184
94
    &hf_cql_flag_custom_payload,
1185
94
    &hf_cql_flag_warning,
1186
94
    &hf_cql_flag_reserved4,
1187
94
    NULL
1188
94
  };
1189
1190
94
  const uint8_t* string_event_type = NULL;
1191
1192
94
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "CQL");
1193
94
  col_clear(pinfo->cinfo, COL_INFO);
1194
1195
94
  first_byte = tvb_get_uint8(raw_tvb, 0);
1196
94
  cql_version = first_byte & (uint8_t)0x7F;
1197
94
  server_to_client = first_byte & (uint8_t)0x80;
1198
94
  opcode = tvb_get_uint8(raw_tvb, 4);
1199
1200
94
  col_add_fstr(pinfo->cinfo, COL_INFO, "v%d %s Type %s",
1201
94
    cql_version,
1202
94
    server_to_client == 0 ? "C->S" : "S->C",
1203
94
    val_to_str(opcode, cql_opcode_names, "Unknown (0x%02x)")
1204
94
  );
1205
1206
94
  conversation = find_or_create_conversation(pinfo);
1207
94
  cql_conv = (cql_conversation_type*) conversation_get_proto_data(conversation, proto_cql);
1208
94
  if(!cql_conv) {
1209
3
    cql_conv = wmem_new(wmem_file_scope(), cql_conversation_type);
1210
3
    cql_conv->streams = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1211
3
    conversation_add_proto_data(conversation, proto_cql, cql_conv);
1212
3
  }
1213
1214
94
  ti = proto_tree_add_item(tree, proto_cql, raw_tvb, 0, -1, ENC_NA);
1215
94
  cql_tree = proto_item_add_subtree(ti, ett_cql_protocol);
1216
1217
94
  ti = proto_tree_add_item(cql_tree, hf_cql_version, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1218
94
  version_tree = proto_item_add_subtree(ti, ett_cql_version);
1219
94
  proto_tree_add_item(version_tree, hf_cql_protocol_version, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1220
94
  proto_tree_add_item(version_tree, hf_cql_direction, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1221
94
  offset += 1;
1222
94
  switch(cql_version){
1223
12
    case 3:
1224
12
    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
12
    break;
1226
1
    case 4:
1227
1
    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
1
    break;
1229
81
    default:
1230
81
    proto_tree_add_item(cql_tree, hf_cql_flags_bitmap, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1231
81
    break;
1232
94
  }
1233
94
  flags = tvb_get_uint8(raw_tvb, offset);
1234
94
  offset += 1;
1235
94
  proto_tree_add_item_ret_int(cql_tree, hf_cql_stream, raw_tvb, offset, 2, ENC_BIG_ENDIAN, &stream);
1236
94
  offset += 2;
1237
94
  proto_tree_add_item(cql_tree, hf_cql_opcode, raw_tvb, offset, 1, ENC_BIG_ENDIAN);
1238
94
  offset += 1;
1239
94
  proto_tree_add_item_ret_uint(cql_tree, hf_cql_length, raw_tvb, offset, 4, ENC_BIG_ENDIAN, &message_length);
1240
94
  offset += 4;
1241
1242
  /* Track the request/response. */
1243
94
  if (!pinfo->fd->visited) {
1244
94
    if (server_to_client == 0) {
1245
      /* This is a request, add it to this stream tracking */
1246
64
      cql_trans = cql_transaction_add_request(cql_conv, pinfo, stream, 0);
1247
64
    } else {
1248
      /* This is a response, bind the response with the latest request */
1249
30
      cql_trans = cql_enrich_transaction_with_response(cql_conv, pinfo, stream);
1250
30
    }
1251
94
  } else {
1252
    /* Search for any packet having this packed id as request or response */
1253
0
    cql_trans = cql_transaction_lookup(cql_conv, pinfo, stream);
1254
0
  }
1255
1256
94
  if (!cql_trans) {
1257
    /* Add a fake request to this stream tracking */
1258
12
    cql_trans = cql_transaction_add_request(cql_conv, pinfo, stream, 1);
1259
12
  }
1260
1261
  /* Add state tracking to tree */
1262
94
  if (server_to_client == 0 && cql_trans->rep_frame) {
1263
    /* request */
1264
0
    ti = proto_tree_add_uint(cql_tree, hf_cql_response_in, raw_tvb, 0, 0, cql_trans->rep_frame);
1265
0
    proto_item_set_generated(ti);
1266
0
  }
1267
94
  if (server_to_client && cql_trans->req_frame) {
1268
    /* reply */
1269
7
    nstime_t ns;
1270
1271
7
    ti = proto_tree_add_uint(cql_tree, hf_cql_response_to, raw_tvb, 0, 0, cql_trans->req_frame);
1272
7
    proto_item_set_generated(ti);
1273
7
    nstime_delta(&ns, &pinfo->abs_ts, &cql_trans->req_time);
1274
7
    ti = proto_tree_add_time(cql_tree, hf_cql_response_time, raw_tvb, 0, 0, &ns);
1275
7
    proto_item_set_generated(ti);
1276
7
  }
1277
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
1281
   */
1282
94
  if (flags & CQL_HEADER_FLAG_COMPRESSION) {
1283
24
    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
1288
       */
1289
      uint32_t ret = 0, orig_size = tvb_get_ntohl(raw_tvb, offset);
1290
      unsigned char *decompressed_buffer = NULL;
1291
      offset += 4;
1292
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);
1300
      }
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;
1312
      }
1313
    }
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;
1320
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
1327
       */
1328
      if (ret == SNAPPY_OK && orig_size <= MAX_UNCOMPRESSED_SIZE) {
1329
        decompressed_buffer = (unsigned char*)wmem_alloc(pinfo->pool, orig_size);
1330
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
1338
         */
1339
        ret = SNAPPY_INVALID_INPUT;
1340
      }
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);
1349
      }
1350
    }
1351
#endif
1352
24
  }
1353
94
  if (compression_level == CQL_COMPRESSION_NONE) {
1354
    /* In case of decompression failure or uncompressed packet */
1355
70
    tvb = tvb_new_subset_remaining(raw_tvb, offset);
1356
70
  } else if (compression_level == CQL_DECOMPRESSION_ATTEMPTED) {
1357
24
    proto_tree_add_item(cql_tree, hf_cql_raw_compressed_bytes, raw_tvb, offset,
1358
24
          tvb_captured_length_remaining(raw_tvb, offset), ENC_NA);
1359
24
    return tvb_captured_length(raw_tvb);
1360
24
  }
1361
70
  offset = 0;
1362
1363
1364
  /* Dissect the operation. */
1365
70
  if (server_to_client == 0) {
1366
51
    switch (opcode) {
1367
2
      case CQL_OPCODE_STARTUP:
1368
2
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message STARTUP");
1369
2
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_map_size, tvb, offset, 2, ENC_BIG_ENDIAN, &map_size);
1370
2
        offset += 2;
1371
9
        for(i = 0; i < map_size; ++i) {
1372
7
          proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1373
7
          offset += 2;
1374
7
          proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1375
7
          offset += string_length;
1376
1377
7
          proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1378
7
          offset += 2;
1379
7
          proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1380
7
          offset += string_length;
1381
7
        }
1382
2
        break;
1383
1384
0
      case CQL_OPCODE_AUTH_RESPONSE:
1385
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTH_RESPONSE");
1386
1387
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1388
0
        offset += 4;
1389
0
        if (string_length > 0) {
1390
0
          proto_tree_add_item(cql_subtree, hf_cql_auth_token, tvb, offset, string_length, ENC_NA);
1391
0
        }
1392
0
        break;
1393
1394
2
      case CQL_OPCODE_OPTIONS:
1395
        /* body should be empty */
1396
2
        break;
1397
1398
0
      case CQL_OPCODE_QUERY:
1399
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Query");
1400
1401
        /* Query */
1402
0
        const uint8_t *query_string;
1403
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1404
0
        offset += 4;
1405
0
        proto_tree_add_item_ret_string(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8, pinfo->pool, &query_string);
1406
0
        col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", query_string);
1407
0
        offset += string_length;
1408
1409
        /* Query parameters */
1410
0
        dissect_cql_query_parameters(cql_subtree, tvb, offset, 0);
1411
1412
0
        break;
1413
1414
1415
0
      case CQL_OPCODE_PREPARE:
1416
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message PREPARE");
1417
1418
        /* TODO: Link for later use by EXECUTE? */
1419
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1420
0
        offset += 4;
1421
0
        proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1422
0
        break;
1423
1424
1425
0
      case CQL_OPCODE_EXECUTE:
1426
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message EXECUTE");
1427
1428
        /* TODO: link to original PREPARE? */
1429
1430
        /* Query ID */
1431
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1432
0
        offset += 2;
1433
0
        proto_tree_add_item(cql_subtree, hf_cql_query_id, tvb, offset, short_bytes_length, ENC_NA);
1434
0
        offset += short_bytes_length;
1435
1436
        /* Query parameters */
1437
0
        dissect_cql_query_parameters(cql_subtree, tvb, offset, 1);
1438
0
        break;
1439
1440
1441
0
      case CQL_OPCODE_BATCH:
1442
        /* TODO NOT DONE */
1443
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message BATCH");
1444
1445
0
        proto_tree_add_item(cql_subtree, hf_cql_batch_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1446
0
        offset += 1;
1447
1448
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_batch_query_size, tvb, offset, 2, ENC_BIG_ENDIAN, &batch_size);
1449
0
        offset += 2;
1450
1451
0
        for (i = 0; i < batch_size; ++i) {
1452
0
          uint32_t value_count = 0;
1453
1454
0
          proto_tree_add_item_ret_uint(cql_subtree, hf_cql_batch_query_type, tvb, offset, 1, ENC_BIG_ENDIAN, &batch_query_type);
1455
0
          batch_query_type = tvb_get_uint8(tvb, offset);
1456
0
          offset += 1;
1457
0
          if (batch_query_type == 0) {
1458
            /* Query */
1459
0
            proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1460
0
            offset += 4;
1461
0
            proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1462
0
            offset += string_length;
1463
0
          } else if (batch_query_type == 1) {
1464
0
            uint32_t query_id_bytes_length;
1465
1466
            /* Query ID */
1467
0
            proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &query_id_bytes_length);
1468
0
            offset += 2;
1469
0
            proto_tree_add_item(cql_subtree, hf_cql_query_id, tvb, offset, query_id_bytes_length, ENC_NA);
1470
0
            offset += query_id_bytes_length;
1471
0
          }
1472
1473
0
          proto_tree_add_item_ret_uint(cql_subtree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &value_count);
1474
0
          offset += 2;
1475
0
          for (k = 0; k < value_count; ++k) {
1476
0
            int32_t batch_bytes_length = 0;
1477
0
            proto_tree_add_item_ret_int(cql_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &batch_bytes_length);
1478
0
            offset += 4;
1479
0
            if (batch_bytes_length > 0) {
1480
0
              proto_tree_add_item(cql_subtree, hf_cql_bytes, tvb, offset, batch_bytes_length, ENC_NA);
1481
0
              offset += batch_bytes_length;
1482
0
            }
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. */
1487
0
          }
1488
0
        }
1489
        /* consistency */
1490
0
        proto_tree_add_item(cql_subtree, hf_cql_consistency, tvb, offset, 2, ENC_BIG_ENDIAN);
1491
0
        offset += 2;
1492
0
        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
0
        break;
1494
1495
0
      case CQL_OPCODE_REGISTER:
1496
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message REGISTER");
1497
1498
        /* string list */
1499
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_list_size, tvb, offset, 2, ENC_BIG_ENDIAN, &map_size);
1500
0
        offset += 2;
1501
0
        for(i = 0; i < map_size; ++i) {
1502
0
          proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1503
0
          offset += 2;
1504
0
          proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1505
0
          offset += string_length;
1506
0
        }
1507
1508
0
        break;
1509
1510
47
      default:
1511
47
        proto_tree_add_expert(cql_tree, pinfo, &ei_cql_data_not_dissected_yet, tvb, 0, message_length);
1512
47
        break;
1513
51
    }
1514
51
  } else {
1515
19
    if (flags & CQL_HEADER_FLAG_TRACING) {
1516
4
      add_cql_uuid(cql_tree, hf_cql_tracing_uuid, tvb, offset);
1517
4
      offset += 16;
1518
4
    }
1519
19
    switch (opcode) {
1520
11
      case CQL_OPCODE_ERROR:
1521
11
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message ERROR");
1522
11
        uint32_t error_code;
1523
11
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_error_code, tvb, offset, 4, ENC_BIG_ENDIAN, &error_code);
1524
11
        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
11
        offset += 4;
1526
1527
        /* string  */
1528
11
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1529
11
        offset += 2;
1530
11
        proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1531
11
        break;
1532
1533
1534
1
      case CQL_OPCODE_AUTHENTICATE:
1535
1
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTHENTICATE");
1536
1537
1
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1538
1
        offset += 2;
1539
1
        proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1540
1
        break;
1541
1542
1543
0
      case CQL_OPCODE_SUPPORTED:
1544
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message SUPPORTED");
1545
0
        uint32_t multimap_count, value_count;
1546
1547
        /* string multimap */
1548
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &multimap_count);
1549
0
        offset += 2;
1550
0
        for (k = 0; k < multimap_count; ++k) {
1551
            /* key - string */
1552
0
            proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1553
0
            offset += 2;
1554
0
            proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1555
0
            offset += string_length;
1556
1557
            /* value - string list */
1558
0
            proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_list_size, tvb, offset, 2, ENC_BIG_ENDIAN, &value_count);
1559
0
            offset += 2;
1560
0
            for(i = 0; i < value_count; ++i) {
1561
0
                proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1562
0
                offset += 2;
1563
0
                proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1564
0
                offset += string_length;
1565
0
            }
1566
0
        }
1567
0
        break;
1568
1569
1570
0
      case CQL_OPCODE_RESULT:
1571
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message RESULT");
1572
1573
0
        if (flags & CQL_HEADER_FLAG_CUSTOM_PAYLOAD) {
1574
0
          uint32_t bytesmap_count;
1575
0
          cust_payload_tree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_custom_payload, NULL, "Custom Payload");
1576
0
          proto_tree_add_item_ret_uint(cust_payload_tree, hf_cql_value_count, tvb, offset, 2, ENC_BIG_ENDIAN, &bytesmap_count);
1577
0
          offset += 2;
1578
0
          for(k = 0; k < bytesmap_count; ++k) {
1579
0
            proto_tree_add_item_ret_uint(cust_payload_tree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1580
0
            offset += 2;
1581
0
            proto_tree_add_item(cust_payload_tree, hf_cql_bytesmap_string, tvb, offset, string_length, ENC_UTF_8);
1582
0
            offset += string_length;
1583
0
            if (bytes_length > 0) {
1584
0
              proto_tree_add_item(cust_payload_tree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
1585
0
              offset += bytes_length;
1586
0
            }
1587
0
          }
1588
0
          return offset;
1589
0
        }
1590
1591
0
        proto_tree_add_item_ret_int(cql_subtree, hf_cql_result_kind, tvb, offset, 4, ENC_BIG_ENDIAN, &result_kind);
1592
0
        col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(result_kind, cql_result_kind_names, "Unknown kind"));
1593
0
        offset += 4;
1594
1595
0
        switch (result_kind) {
1596
0
          case CQL_RESULT_KIND_VOID:
1597
            /* Nothing */
1598
0
            break;
1599
1600
0
          case CQL_RESULT_KIND_ROWS:
1601
0
            metadata_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_metadata, &ti, "Rows Result Metadata");
1602
0
            proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_flags_values, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_flags);
1603
0
            proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_global_tables_spec, tvb, offset, 4, ENC_BIG_ENDIAN);
1604
0
            proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_has_more_pages, tvb, offset, 4, ENC_BIG_ENDIAN);
1605
0
            proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_no_metadata, tvb, offset, 4, ENC_BIG_ENDIAN);
1606
0
            offset += 4;
1607
1608
0
            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
0
            if (result_rows_columns_count < 0) {
1610
0
              expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1611
0
              return tvb_reported_length(tvb);
1612
0
            }
1613
0
            offset += 4;
1614
1615
0
            offset = parse_result_metadata_more_pages(metadata_subtree, tvb, offset, result_rows_flags);
1616
1617
0
            offset_row_metadata = offset;
1618
0
            offset = parse_result_metadata(metadata_subtree, pinfo, tvb, offset, result_rows_flags, result_rows_columns_count);
1619
0
            if (offset == offset_row_metadata) {
1620
              /* there was no col spec, no row metadata available */
1621
0
              offset_row_metadata = 0;
1622
0
            }
1623
1624
0
            rows_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_rows, &ti, "Rows");
1625
0
            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
0
            if (result_rows_row_count < 0) {
1627
0
              expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1628
0
              return tvb_reported_length(tvb);
1629
0
            }
1630
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%d rows)", result_rows_row_count);
1631
0
            offset += 4;
1632
1633
0
            if (result_rows_columns_count) {
1634
0
              for (j = 0; j < result_rows_row_count; ++j) {
1635
0
                columns_subtree = proto_tree_add_subtree(rows_subtree, tvb, offset, 0, ett_cql_result_columns, &ti, "Data (columns)");
1636
0
                proto_item_append_text(columns_subtree, " for row # %" PRId64, j + 1);
1637
1638
0
                if (offset_row_metadata) {
1639
0
                  offset = parse_row(columns_subtree, pinfo, tvb, offset_row_metadata, offset, result_rows_columns_count);
1640
0
                } else {
1641
0
                  for (k = 0; k < result_rows_columns_count; ++k) {
1642
0
                    proto_tree_add_item_ret_int(columns_subtree, hf_cql_bytes_length, tvb, offset, 4, ENC_BIG_ENDIAN, &bytes_length);
1643
0
                    offset += 4;
1644
0
                    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
0
                    if (bytes_length > 0) {
1646
0
                      proto_item_append_text(single_column_subtree, " for column # %" PRId64, k + 1);
1647
0
                      proto_tree_add_item(single_column_subtree, hf_cql_bytes, tvb, offset, bytes_length, ENC_NA);
1648
0
                      offset += bytes_length;
1649
0
                    } else if (bytes_length == -1) {
1650
0
                      proto_item_append_text(single_column_subtree, " is NULL for column # %" PRId64, k + 1);
1651
0
                    } else if (bytes_length == -2) {
1652
0
                      proto_item_append_text(single_column_subtree, " is not set for column # %" PRId64, k + 1);
1653
0
                    } else {
1654
0
                      expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1655
0
                      return tvb_reported_length(tvb);
1656
0
                    }
1657
0
                  }
1658
0
                }
1659
0
              }
1660
0
            }
1661
1662
0
            break;
1663
1664
0
          case CQL_RESULT_KIND_SET_KEYSPACE:
1665
0
            proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 2, ENC_BIG_ENDIAN, &string_length);
1666
0
            offset += 2;
1667
0
            proto_tree_add_item(cql_subtree, hf_cql_string, tvb, offset, string_length, ENC_UTF_8);
1668
0
            break;
1669
1670
1671
0
          case CQL_RESULT_KIND_PREPARED:
1672
            /* <id><metadata><result_metadata> */
1673
1674
            /* Query ID */
1675
0
            proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1676
0
            offset += 2;
1677
0
            proto_tree_add_item(cql_subtree, hf_cql_query_id, tvb, offset, short_bytes_length, ENC_NA);
1678
0
            offset += short_bytes_length;
1679
1680
            /* metadata: <flags><columns_count><pk_count>[<pk_index_1>...<pk_index_n>][<global_table_spec>?<col_spec_1>...<col_spec_n>] */
1681
0
            prepared_metadata_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_metadata, &ti, "Prepared Metadata");
1682
0
            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
0
            proto_tree_add_item(prepared_metadata_subtree, hf_cql_result_rows_flag_global_tables_spec, tvb, offset, 4, ENC_BIG_ENDIAN);
1684
0
            offset += 4;
1685
0
            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
0
            if (result_rows_columns_count < 0) {
1687
0
              expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1688
0
              return tvb_reported_length(tvb);
1689
0
            }
1690
0
            offset += 4;
1691
1692
0
            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
0
            if (result_prepared_pk_count < 0) {
1694
0
              expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1695
0
              return tvb_reported_length(tvb);
1696
0
            }
1697
0
            offset += 4;
1698
1699
            /* TODO: skipping all pk_index elements for now*/
1700
0
            offset += (2 * result_prepared_pk_count);
1701
1702
0
            offset = parse_result_metadata(prepared_metadata_subtree, pinfo, tvb, offset, result_prepared_flags, result_rows_columns_count);
1703
1704
            /* <result_metadata> is identical to rows result metadata */
1705
0
            metadata_subtree = proto_tree_add_subtree(cql_subtree, tvb, offset, 0, ett_cql_result_metadata, &ti, "Prepared Result Metadata");
1706
0
            proto_tree_add_item_ret_uint(metadata_subtree, hf_cql_result_rows_flags_values, tvb, offset, 4, ENC_BIG_ENDIAN, &result_rows_flags);
1707
0
            proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_global_tables_spec, tvb, offset, 4, ENC_BIG_ENDIAN);
1708
0
            proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_has_more_pages, tvb, offset, 4, ENC_BIG_ENDIAN);
1709
0
            proto_tree_add_item(metadata_subtree, hf_cql_result_rows_flag_no_metadata, tvb, offset, 4, ENC_BIG_ENDIAN);
1710
0
            offset += 4;
1711
1712
0
            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
0
            if (result_rows_columns_count < 0) {
1714
0
              expert_add_info(pinfo, ti, &ei_cql_unexpected_negative_value);
1715
0
              return tvb_reported_length(tvb);
1716
0
            }
1717
0
            offset += 4;
1718
1719
0
            offset = parse_result_metadata_more_pages(metadata_subtree, tvb, offset, result_rows_flags);
1720
1721
0
            parse_result_metadata(metadata_subtree, pinfo, tvb, offset, result_rows_flags, result_rows_columns_count);
1722
1723
0
            break;
1724
0
          case CQL_RESULT_KIND_SCHEMA_CHANGE:
1725
0
            /*offset = */parse_result_schema_change(cql_subtree, pinfo, tvb, offset);
1726
0
            break;
1727
1728
0
          default:
1729
0
            proto_tree_add_expert(cql_subtree, pinfo, &ei_cql_data_not_dissected_yet, tvb, 0, message_length);
1730
0
            break;
1731
0
        }
1732
1733
0
        break;
1734
1735
1736
1
      case CQL_OPCODE_EVENT:
1737
1
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message EVENT");
1738
1739
1
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_short_bytes_length, tvb, offset, 2, ENC_BIG_ENDIAN, &short_bytes_length);
1740
1
        offset += 2;
1741
1742
1
        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
1
        offset += short_bytes_length;
1744
1
        proto_item_append_text(cql_subtree, " (type: %s)", string_event_type);
1745
1746
1
        if (strcmp(string_event_type, "SCHEMA_CHANGE") == 0) {
1747
0
          /*offset = */parse_result_schema_change(cql_subtree, pinfo, tvb, offset);
1748
1
        } else {
1749
          /* TODO: handle "TOPOLOGY_CHANGE" and "STATUS_CHANGE" event types as well*/
1750
1
        }
1751
1
        break;
1752
1753
1754
0
      case CQL_OPCODE_AUTH_CHALLENGE:
1755
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTH_CHALLENGE");
1756
1757
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1758
0
        offset += 4;
1759
0
        proto_tree_add_item(cql_subtree, hf_cql_auth_token, tvb, offset, string_length, ENC_NA);
1760
0
        break;
1761
1762
1763
0
      case CQL_OPCODE_AUTH_SUCCESS:
1764
0
        cql_subtree = proto_tree_add_subtree(cql_tree, tvb, offset, message_length, ett_cql_message, &ti, "Message AUTH_SUCCESS");
1765
1766
0
        proto_tree_add_item_ret_uint(cql_subtree, hf_cql_string_length, tvb, offset, 4, ENC_BIG_ENDIAN, &string_length);
1767
0
        offset += 4;
1768
0
        if (string_length > 0) {
1769
0
          proto_tree_add_item(cql_subtree, hf_cql_auth_token, tvb, offset, string_length, ENC_NA);
1770
0
        }
1771
0
        break;
1772
1773
3
      default:
1774
3
        proto_tree_add_expert(cql_subtree, pinfo, &ei_cql_data_not_dissected_yet, tvb, 0, message_length);
1775
3
        break;
1776
19
    }
1777
19
  }
1778
1779
51
  return tvb_reported_length(tvb);
1780
70
}
1781
1782
static int
1783
dissect_cql_tcp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data)
1784
14
{
1785
14
  uint8_t version;
1786
  /* This dissector version only understands CQL protocol v3 and v4. */
1787
14
  if (tvb_reported_length(tvb) < 1)
1788
0
    return 0;
1789
1790
14
  version = tvb_get_uint8(tvb, 0) & 0x7F;
1791
14
  if ((version != 3 && version != 4))
1792
1
    return 0;
1793
1794
13
  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
13
  return tvb_reported_length(tvb);
1796
14
}
1797
1798
void
1799
proto_reg_handoff_cql(void)
1800
14
{
1801
14
  dissector_add_uint_with_preference("tcp.port", CQL_DEFAULT_PORT, find_dissector("cql"));
1802
14
}
1803
1804
1805
void
1806
proto_register_cql(void)
1807
14
{
1808
14
  expert_module_t* expert_cql;
1809
14
  static hf_register_info hf[] = {
1810
14
    {
1811
14
      &hf_cql_batch_flag_serial_consistency,
1812
14
      {
1813
14
        "Serial Consistency", "cql.batch.flags.serial_consistency",
1814
14
        FT_BOOLEAN, 8,
1815
14
        NULL, CQL_BATCH_FLAG_SERIAL_CONSISTENCY,
1816
14
        NULL, HFILL
1817
14
      }
1818
14
    },
1819
14
    {
1820
14
      &hf_cql_batch_flag_default_timestamp,
1821
14
      {
1822
14
        "Default Timestamp", "cql.batch.flags.default_timestamp",
1823
14
        FT_BOOLEAN, 8,
1824
14
        NULL, CQL_BATCH_FLAG_DEFAULT_TIMESTAMP,
1825
14
        NULL, HFILL
1826
14
      }
1827
14
    },
1828
14
    {
1829
14
      &hf_cql_batch_flag_with_name_for_values,
1830
14
      {
1831
14
        "With Name For Value", "cql.batch.flags.with_name_for_values",
1832
14
        FT_BOOLEAN, 8,
1833
14
        NULL, CQL_BATCH_FLAG_WITH_NAME_FOR_VALUES,
1834
14
        NULL, HFILL
1835
14
      }
1836
14
    },
1837
14
    {
1838
14
      &hf_cql_batch_flags_bitmap,
1839
14
      {
1840
14
        "Flags", "cql.batch.flags",
1841
14
        FT_UINT8, BASE_HEX,
1842
14
        NULL, 0x0,
1843
14
        NULL, HFILL
1844
14
      }
1845
14
    },
1846
14
    {
1847
14
      &hf_cql_version,
1848
14
      {
1849
14
        "Version", "cql.version",
1850
14
        FT_UINT8, BASE_HEX,
1851
14
        NULL, 0x0,
1852
14
        "CQL protocol version (not language version)", HFILL
1853
14
      }
1854
14
    },
1855
14
    {
1856
14
      &hf_cql_protocol_version,
1857
14
      {
1858
14
        "Protocol version", "cql.protocol_version",
1859
14
        FT_UINT8, BASE_DEC,
1860
14
        NULL, 0x0F,
1861
14
        NULL, HFILL
1862
14
      }
1863
14
    },
1864
14
    {
1865
14
      &hf_cql_direction,
1866
14
      {
1867
14
        "Direction", "cql.direction",
1868
14
        FT_UINT8, BASE_HEX,
1869
14
        VALS(cql_direction_names), 0xF0,
1870
14
        NULL, HFILL
1871
14
      }
1872
14
    },
1873
14
    {
1874
14
      &hf_cql_flags_bitmap,
1875
14
      {
1876
14
        "Flags", "cql.flags",
1877
14
        FT_UINT8, BASE_HEX,
1878
14
        NULL, 0x0,
1879
14
        NULL, HFILL
1880
14
      }
1881
14
    },
1882
14
    {
1883
14
      &hf_cql_result_rows_flags_values,
1884
14
      {
1885
14
        "Rows Result Flags", "cql.result.rows.flags",
1886
14
        FT_UINT32, BASE_DEC,
1887
14
        NULL, 0x0,
1888
14
        NULL, HFILL
1889
14
      }
1890
14
    },
1891
14
    {
1892
14
      &hf_cql_result_prepared_flags_values,
1893
14
      {
1894
14
        "Prepared Result Flags", "cql.result.prepared.flags",
1895
14
        FT_UINT32, BASE_DEC,
1896
14
        NULL, 0x0,
1897
14
        NULL, HFILL
1898
14
      }
1899
14
    },
1900
14
    {
1901
14
      &hf_cql_result_rows_flag_global_tables_spec,
1902
14
      {
1903
14
        "Global tables spec.", "cql.result.rows.flags.global_tables",
1904
14
        FT_BOOLEAN, 32,
1905
14
        NULL, CQL_RESULT_ROWS_FLAG_GLOBAL_TABLES_SPEC,
1906
14
        NULL, HFILL
1907
14
      }
1908
14
    },
1909
14
    {
1910
14
      &hf_cql_result_rows_flag_has_more_pages,
1911
14
      {
1912
14
        "Has More Pages", "cql.result.rows.flags.has_more_pages",
1913
14
        FT_BOOLEAN, 32,
1914
14
        NULL, CQL_RESULT_ROWS_FLAG_HAS_MORE_PAGES,
1915
14
        NULL, HFILL
1916
14
      }
1917
14
    },
1918
14
    {
1919
14
      &hf_cql_result_rows_flag_no_metadata,
1920
14
      {
1921
14
        "No Metadata", "cql.result.rows.flags.no_metadata",
1922
14
        FT_BOOLEAN, 32,
1923
14
        NULL, CQL_RESULT_ROWS_FLAG_NO_METADATA,
1924
14
        NULL, HFILL
1925
14
      }
1926
14
    },
1927
14
    {
1928
14
      &hf_cql_flag_compression,
1929
14
      {
1930
14
        "Compression", "cql.flags.compression",
1931
14
        FT_BOOLEAN, 8,
1932
14
        NULL, CQL_HEADER_FLAG_COMPRESSION,
1933
14
        NULL, HFILL
1934
14
      }
1935
14
    },
1936
14
    {
1937
14
      &hf_cql_flag_tracing,
1938
14
      {
1939
14
        "Tracing", "cql.flags.tracing",
1940
14
        FT_BOOLEAN, 8,
1941
14
        NULL, CQL_HEADER_FLAG_TRACING,
1942
14
        NULL, HFILL
1943
14
      }
1944
14
    },
1945
14
    {
1946
14
      &hf_cql_flag_custom_payload,
1947
14
      {
1948
14
        "Custom Payload", "cql.flags.custom_payload",
1949
14
        FT_BOOLEAN, 8,
1950
14
        NULL, CQL_HEADER_FLAG_CUSTOM_PAYLOAD,
1951
14
        NULL, HFILL
1952
14
      }
1953
14
    },
1954
14
    {
1955
14
      &hf_cql_flag_warning,
1956
14
      {
1957
14
        "Warning", "cql.flags.warning",
1958
14
        FT_BOOLEAN, 8,
1959
14
        NULL, CQL_HEADER_FLAG_WARNING,
1960
14
        NULL, HFILL
1961
14
      }
1962
14
    },
1963
14
    {
1964
14
      &hf_cql_flag_reserved3,
1965
14
      {
1966
14
        "Reserved", "cql.flags.reserved",
1967
14
        FT_UINT8, BASE_HEX,
1968
14
        NULL, CQL_HEADER_FLAG_V3_RESERVED,
1969
14
        NULL, HFILL
1970
14
      }
1971
14
    },
1972
14
    {
1973
14
      &hf_cql_flag_reserved4,
1974
14
      {
1975
14
        "Reserved", "cql.flags.reserved",
1976
14
        FT_UINT8, BASE_HEX,
1977
14
        NULL, CQL_HEADER_FLAG_V4_RESERVED,
1978
14
        NULL, HFILL
1979
14
      }
1980
14
    },
1981
14
    {
1982
14
      &hf_cql_query_flags_bitmap,
1983
14
      {
1984
14
        "Flags", "cql.query.flags",
1985
14
        FT_UINT8, BASE_HEX,
1986
14
        NULL, 0x0,
1987
14
        NULL, HFILL
1988
14
      }
1989
14
    },
1990
14
    {
1991
14
      &hf_cql_query_flags_page_size,
1992
14
      {
1993
14
        "Page Size", "cql.query.flags.page_size",
1994
14
        FT_BOOLEAN, 8,
1995
14
        NULL, CQL_QUERY_FLAG_PAGE_SIZE,
1996
14
        NULL, HFILL
1997
14
      }
1998
14
    },
1999
14
    {
2000
14
      &hf_cql_query_flags_skip_metadata,
2001
14
      {
2002
14
        "Skip Metadata", "cql.query.flags.skip_metadata",
2003
14
        FT_BOOLEAN, 8,
2004
14
        NULL, CQL_QUERY_FLAG_SKIP_METADATA,
2005
14
        NULL, HFILL
2006
14
      }
2007
14
    },
2008
14
    {
2009
14
      &hf_cql_query_flags_values,
2010
14
      {
2011
14
        "Values", "cql.query.flags.values",
2012
14
        FT_BOOLEAN, 8,
2013
14
        NULL, CQL_QUERY_FLAG_VALUES,
2014
14
        NULL, HFILL
2015
14
      }
2016
14
    },
2017
14
    {
2018
14
      &hf_cql_query_flags_default_timestamp,
2019
14
      {
2020
14
        "Default Timestamp", "cql.query.flags.default_timestamp",
2021
14
        FT_BOOLEAN, 8,
2022
14
        NULL, CQL_QUERY_FLAG_DEFAULT_TIMESTAMP,
2023
14
        NULL, HFILL
2024
14
      }
2025
14
    },
2026
14
    {
2027
14
      &hf_cql_query_flags_names_for_values,
2028
14
      {
2029
14
        "Names for Values", "cql.query.flags.value_names",
2030
14
        FT_BOOLEAN, 8,
2031
14
        NULL, CQL_QUERY_FLAG_VALUE_NAMES,
2032
14
        NULL, HFILL
2033
14
      }
2034
14
    },
2035
14
    {
2036
14
      &hf_cql_query_flags_paging_state,
2037
14
      {
2038
14
        "Paging State", "cql.query.flags.paging_state",
2039
14
        FT_BOOLEAN, 8,
2040
14
        NULL, CQL_QUERY_FLAG_PAGING_STATE,
2041
14
        NULL, HFILL
2042
14
      }
2043
14
    },
2044
14
    {
2045
14
      &hf_cql_query_flags_serial_consistency,
2046
14
      {
2047
14
        "Serial Consistency", "cql.query.flags.serial_consistency",
2048
14
        FT_BOOLEAN, 8,
2049
14
        NULL, CQL_QUERY_FLAG_SERIAL_CONSISTENCY,
2050
14
        NULL, HFILL
2051
14
      }
2052
14
    },
2053
14
    {
2054
14
      &hf_cql_query_flags_reserved3,
2055
14
      {
2056
14
        "Reserved", "cql.query_flags.reserved",
2057
14
        FT_UINT8, BASE_HEX,
2058
14
        NULL, CQL_QUERY_FLAG_V3_RESERVED,
2059
14
        NULL, HFILL
2060
14
      }
2061
14
    },
2062
14
    {
2063
14
      &hf_cql_stream,
2064
14
      {
2065
14
        "Stream Identifier", "cql.stream",
2066
14
        FT_INT16, BASE_DEC,
2067
14
        NULL, 0x0,
2068
14
        "Stream identifier this packet belongs to", HFILL
2069
14
      }
2070
14
    },
2071
14
    {
2072
14
      &hf_cql_opcode,
2073
14
      {
2074
14
        "Opcode", "cql.opcode",
2075
14
        FT_UINT8, BASE_DEC,
2076
14
        VALS(cql_opcode_names), 0x7F, /* Mask the highest-order bit because it indicates message direction, not opcode. */
2077
14
        "CQL operation this packet describes", HFILL
2078
14
      }
2079
14
    },
2080
14
    {
2081
14
      &hf_cql_batch_type,
2082
14
      {
2083
14
        "Batch type", "cql.batch_type",
2084
14
        FT_UINT8, BASE_DEC,
2085
14
        VALS(cql_batch_type_names), 0x0,
2086
14
        NULL, HFILL
2087
14
      }
2088
14
    },
2089
14
    {
2090
14
      &hf_cql_batch_query_type,
2091
14
      {
2092
14
        "Batch query type", "cql.batch_query_type",
2093
14
        FT_UINT8, BASE_DEC,
2094
14
        VALS(cql_batch_query_type_names), 0x00,
2095
14
        NULL, HFILL
2096
14
      }
2097
14
    },
2098
14
    {
2099
14
      &hf_cql_length,
2100
14
      {
2101
14
        "Message Length", "cql.message_length",
2102
14
        FT_UINT32, BASE_DEC,
2103
14
        NULL, 0x0,
2104
14
        NULL, HFILL
2105
14
      }
2106
14
    },
2107
14
    {
2108
14
      &hf_cql_string_map_size,
2109
14
      {
2110
14
        "String Map Size", "cql.string_map_size",
2111
14
        FT_UINT16, BASE_DEC,
2112
14
        NULL, 0x0,
2113
14
        "Number of strings in the map", HFILL
2114
14
      }
2115
14
    },
2116
14
    {
2117
14
      &hf_cql_string_list_size,
2118
14
      {
2119
14
        "String List Size", "cql.string_list_size",
2120
14
        FT_UINT16, BASE_DEC,
2121
14
        NULL, 0x0,
2122
14
        "Number of strings in the list", HFILL
2123
14
      }
2124
14
    },
2125
14
    {
2126
14
      &hf_cql_string,
2127
14
      {
2128
14
        "String", "cql.string",
2129
14
        FT_STRING, BASE_NONE,
2130
14
        NULL, 0x0,
2131
14
        "UTF-8 string value", HFILL
2132
14
      }
2133
14
    },
2134
14
    {
2135
      /* TODO: should this be an FT_STRING field? */
2136
14
      &hf_cql_auth_token,
2137
14
      {
2138
14
        "Auth Token", "cql.auth_token",
2139
14
        FT_BYTES, BASE_NONE,
2140
14
        NULL, 0x0,
2141
14
        "[bytes] auth token", HFILL
2142
14
      }
2143
14
    },
2144
14
    {
2145
14
      &hf_cql_string_result_rows_global_table_spec_ksname,
2146
14
      {
2147
14
        "Global Spec Keyspace Name", "cql.result.rows.keyspace_name",
2148
14
        FT_STRING, BASE_NONE,
2149
14
        NULL, 0x0,
2150
14
        NULL, HFILL
2151
14
      }
2152
14
    },
2153
14
    {
2154
14
      &hf_cql_string_result_rows_global_table_spec_table_name,
2155
14
      {
2156
14
        "Global Spec Table Name", "cql.result.rows.table_name",
2157
14
        FT_STRING, BASE_NONE,
2158
14
        NULL, 0x0,
2159
14
        NULL, HFILL
2160
14
      }
2161
14
    },
2162
14
    {
2163
14
      &hf_cql_string_result_rows_table_name,
2164
14
      {
2165
14
        "Table Name", "cql.result.rows.table_name",
2166
14
        FT_STRING, BASE_NONE,
2167
14
        NULL, 0x0,
2168
14
        NULL, HFILL
2169
14
      }
2170
14
    },
2171
14
    {
2172
14
      &hf_cql_string_result_rows_udt_name,
2173
14
      {
2174
14
        "User Defined Type Name", "cql.result.rows.udt_name",
2175
14
        FT_STRING, BASE_NONE,
2176
14
        NULL, 0x0,
2177
14
        NULL, HFILL
2178
14
      }
2179
14
    },
2180
14
    {
2181
14
      &hf_cql_string_result_rows_udt_field_name,
2182
14
      {
2183
14
        "User Defined Type field Name", "cql.result.rows.udt_field_name",
2184
14
        FT_STRING, BASE_NONE,
2185
14
        NULL, 0x0,
2186
14
        NULL, HFILL
2187
14
      }
2188
14
    },
2189
14
    {
2190
14
      &hf_cql_string_result_rows_udt_size,
2191
14
      {
2192
14
        "User Defined Type Size", "cql.result.rows.udt_size",
2193
14
        FT_UINT16, BASE_DEC,
2194
14
        NULL, 0x0,
2195
14
        NULL, HFILL
2196
14
      }
2197
14
    },
2198
14
    {
2199
14
      &hf_cql_string_result_rows_list_size,
2200
14
      {
2201
14
        "List Size", "cql.result.rows.list_size",
2202
14
        FT_INT32, BASE_DEC,
2203
14
        NULL, 0x0,
2204
14
        NULL, HFILL
2205
14
      }
2206
14
    },
2207
14
    {
2208
14
      &hf_cql_string_result_rows_map_size,
2209
14
      {
2210
14
        "No. of key/value pairs in map", "cql.result.rows.map_size",
2211
14
        FT_INT32, BASE_DEC,
2212
14
        NULL, 0x0,
2213
14
        NULL, HFILL
2214
14
      }
2215
14
    },
2216
14
    {
2217
14
      &hf_cql_string_result_rows_set_size,
2218
14
      {
2219
14
        "Set Size", "cql.result.rows.set_size",
2220
14
        FT_INT32, BASE_DEC,
2221
14
        NULL, 0x0,
2222
14
        NULL, HFILL
2223
14
      }
2224
14
    },
2225
14
    {
2226
14
      &hf_cql_string_result_rows_keyspace_name,
2227
14
      {
2228
14
        "Keyspace Name", "cql.result.rows.keyspace_name",
2229
14
        FT_STRING, BASE_NONE,
2230
14
        NULL, 0x0,
2231
14
        NULL, HFILL
2232
14
      }
2233
14
    },
2234
14
    {
2235
14
      &hf_cql_bytesmap_string,
2236
14
      {
2237
14
        "Key", "cql.bytesmap.key",
2238
14
        FT_STRING, BASE_NONE,
2239
14
        NULL, 0x0,
2240
14
        NULL, HFILL
2241
14
      }
2242
14
    },
2243
14
    {
2244
14
      &hf_cql_string_result_rows_column_name,
2245
14
      {
2246
14
        "Column Name", "cql.result.rows.column_name",
2247
14
        FT_STRING, BASE_NONE,
2248
14
        NULL, 0x0,
2249
14
        NULL, HFILL
2250
14
      }
2251
14
    },
2252
14
    {
2253
14
      &hf_cql_string_length,
2254
14
      {
2255
14
        "String Length", "cql.string_length",
2256
14
        FT_UINT32, BASE_DEC,
2257
14
        NULL, 0x0,
2258
14
        "Length of the subsequent string value", HFILL
2259
14
      }
2260
14
    },
2261
14
    {
2262
14
      &hf_cql_consistency,
2263
14
      {
2264
14
        "Consistency", "cql.consistency",
2265
14
        FT_UINT16, BASE_HEX,
2266
14
        VALS(cql_consistency_names), 0x0,
2267
14
        "CQL consistency level specification", HFILL
2268
14
      }
2269
14
    },
2270
14
    {
2271
14
      &hf_cql_value_count,
2272
14
      {
2273
14
        "Value count", "cql.value_count",
2274
14
        FT_UINT16, BASE_DEC,
2275
14
        NULL, 0x0,
2276
14
        "Number of subsequent values", HFILL
2277
14
      }
2278
14
    },
2279
14
    {
2280
14
      &hf_cql_bytes_length,
2281
14
      {
2282
14
        "Bytes length", "cql.bytes_length.int",
2283
14
        FT_INT32, BASE_DEC,
2284
14
        NULL, 0x0,
2285
14
        "Number of subsequent bytes", HFILL
2286
14
      }
2287
14
    },
2288
14
    {
2289
14
      &hf_cql_short_bytes_length,
2290
14
      {
2291
14
        "Bytes length", "cql.bytes_length.short",
2292
14
        FT_UINT16, BASE_DEC,
2293
14
        NULL, 0x0,
2294
14
        "Number of subsequent bytes", HFILL
2295
14
      }
2296
14
    },    {
2297
14
      &hf_cql_bytes,
2298
14
      {
2299
14
        "Bytes", "cql.bytes",
2300
14
        FT_BYTES, BASE_NONE,
2301
14
        NULL, 0x0,
2302
14
        "Raw byte array", HFILL
2303
14
      }
2304
14
    },
2305
14
    {
2306
14
      &hf_cql_bigint,
2307
14
      {
2308
14
        "Bigint", "cql.bigint",
2309
14
        FT_INT64, BASE_DEC,
2310
14
        NULL, 0x0,
2311
14
        NULL, HFILL
2312
14
      }
2313
14
    },
2314
14
    {
2315
14
      &hf_cql_scale,
2316
14
      {
2317
14
        "Scale", "cql.scale",
2318
14
        FT_INT32, BASE_DEC,
2319
14
        NULL, 0x0,
2320
14
        NULL, HFILL
2321
14
      }
2322
14
    },
2323
14
    {
2324
14
      &hf_cql_ascii,
2325
14
      {
2326
14
        "Ascii", "cql.ascii",
2327
14
        FT_STRING, BASE_NONE,
2328
14
        NULL, 0x0,
2329
14
        "An Ascii string", HFILL
2330
14
      }
2331
14
    },
2332
14
    {
2333
14
      &hf_cql_double,
2334
14
      {
2335
14
        "Double float", "cql.double",
2336
14
        FT_DOUBLE, BASE_NONE,
2337
14
        NULL, 0x0,
2338
14
        NULL, HFILL
2339
14
      }
2340
14
    },
2341
14
    {
2342
14
      &hf_cql_float,
2343
14
      {
2344
14
        "Float", "cql.float",
2345
14
        FT_FLOAT, BASE_NONE,
2346
14
        NULL, 0x0,
2347
14
        NULL, HFILL
2348
14
      }
2349
14
    },
2350
14
    {
2351
14
      &hf_cql_int,
2352
14
      {
2353
14
        "Int", "cql.int",
2354
14
        FT_INT32, BASE_DEC,
2355
14
        NULL, 0x0,
2356
14
        NULL, HFILL
2357
14
      }
2358
14
    },
2359
14
    {
2360
14
      &hf_cql_varint_count8,
2361
14
      {
2362
14
        "Varint", "cql.varint",
2363
14
        FT_UINT8, BASE_DEC,
2364
14
        NULL, 0x0,
2365
14
        NULL, HFILL
2366
14
      },
2367
14
    },
2368
14
    {
2369
14
      &hf_cql_varint_count16,
2370
14
      {
2371
14
        "Varint", "cql.varint",
2372
14
        FT_UINT16, BASE_DEC,
2373
14
        NULL, 0x0,
2374
14
        NULL, HFILL
2375
14
      },
2376
14
    },
2377
14
    {
2378
14
      &hf_cql_varint_count32,
2379
14
      {
2380
14
        "Varint", "cql.varint",
2381
14
        FT_UINT32, BASE_DEC,
2382
14
        NULL, 0x0,
2383
14
        NULL, HFILL
2384
14
      },
2385
14
    },
2386
14
    {
2387
14
      &hf_cql_varint_count64,
2388
14
      {
2389
14
        "Varint", "cql.varint64",
2390
14
        FT_UINT64, BASE_DEC,
2391
14
        NULL, 0x0,
2392
14
        NULL, HFILL
2393
14
      },
2394
14
    },
2395
14
    {
2396
14
      &hf_cql_varchar,
2397
14
      {
2398
14
        "Varchar", "cql.varchar",
2399
14
        FT_STRING, BASE_NONE,
2400
14
        NULL, 0x0,
2401
14
        NULL, HFILL
2402
14
      }
2403
14
    },
2404
14
    {
2405
14
      &hf_cql_timeuuid,
2406
14
      {
2407
14
        "Time Uuid", "cql.timeuuid",
2408
14
        FT_GUID, BASE_NONE,
2409
14
        NULL, 0x0,
2410
14
        NULL, HFILL
2411
14
      }
2412
14
    },
2413
14
    {
2414
14
      &hf_cql_custom,
2415
14
      {
2416
14
        "Custom", "cql.custom",
2417
14
        FT_STRING, BASE_NONE,
2418
14
        NULL, 0x0,
2419
14
        "A custom field", HFILL
2420
14
      }
2421
14
    },
2422
14
    {
2423
14
      &hf_cql_null_value,
2424
14
      {
2425
14
        "NULL value", "cql.null_value",
2426
14
        FT_NONE, BASE_NONE,
2427
14
        NULL, 0x0,
2428
14
        "A NULL value", HFILL
2429
14
      }
2430
14
    },
2431
14
    {
2432
14
      &hf_cql_raw_compressed_bytes,
2433
14
      {
2434
14
        "Raw compressed bytes", "cql.raw_compressed_bytes",
2435
14
        FT_BYTES, BASE_NONE,
2436
14
        NULL, 0x0,
2437
14
        "Raw byte that failed to be decompressed", HFILL
2438
14
      }
2439
14
    },
2440
2441
14
    {
2442
14
      &hf_cql_paging_state,
2443
14
      {
2444
14
        "Paging State", "cql.paging_state",
2445
14
        FT_BYTES, BASE_NONE,
2446
14
        NULL, 0x0,
2447
14
        "Paging state byte array", HFILL
2448
14
      }
2449
14
    },
2450
14
    {
2451
14
      &hf_cql_page_size,
2452
14
      {
2453
14
        "Page size", "cql.page_size",
2454
14
        FT_INT32, BASE_DEC,
2455
14
        NULL, 0x0,
2456
14
        "Desired page size of result (in CQL3 rows)", HFILL
2457
14
      }
2458
14
    },
2459
14
    {
2460
14
      &hf_cql_response_in,
2461
14
      {
2462
14
        "Response in", "cql.response_in",
2463
14
        FT_FRAMENUM, BASE_NONE,
2464
14
        FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
2465
14
        "The response to this CQL request is in this frame", HFILL
2466
14
      }
2467
14
    },
2468
14
    {
2469
14
      &hf_cql_response_to,
2470
14
      {
2471
14
        "Request in", "cql.response_to",
2472
14
        FT_FRAMENUM, BASE_NONE,
2473
14
        FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
2474
14
        "This is a response to the CQL request in this fame", HFILL
2475
14
      }
2476
14
    },
2477
14
    {
2478
14
      &hf_cql_response_time,
2479
14
      {
2480
14
        "Response time", "cql.response_time",
2481
14
        FT_RELATIVE_TIME, BASE_NONE,
2482
14
        NULL, 0x0,
2483
14
        "The time between the request and the response", HFILL
2484
14
      }
2485
14
    },
2486
14
    {
2487
14
      &hf_cql_timestamp,
2488
14
      {
2489
14
        "Timestamp", "cql.timestamp",
2490
14
        FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
2491
14
        NULL, 0x0,
2492
14
        NULL, HFILL
2493
14
      }
2494
14
    },
2495
14
    {
2496
14
      &hf_cql_query_id,
2497
14
      {
2498
14
        "Query ID", "cql.query_id",
2499
14
        FT_BYTES, BASE_NONE,
2500
14
        NULL, 0x0,
2501
14
        "CQL query id resulting from a PREPARE statement", HFILL
2502
14
      }
2503
14
    },
2504
14
    {
2505
14
      &hf_cql_event_type,
2506
14
      {
2507
14
        "Event Type", "cql.event_type",
2508
14
        FT_STRING, BASE_NONE,
2509
14
        NULL, 0x0,
2510
14
        "CQL Event Type", HFILL
2511
14
      }
2512
14
    },
2513
14
    {
2514
14
      &hf_cql_event_schema_change_type,
2515
14
      {
2516
14
        "Schema change type", "cql.schema_change_type",
2517
14
        FT_STRING, BASE_NONE,
2518
14
        NULL, 0x0,
2519
14
        "CQL Schema Change Type", HFILL
2520
14
      }
2521
14
    },
2522
14
    {
2523
14
      &hf_cql_event_schema_change_type_target,
2524
14
      {
2525
14
        "Schema change target", "cql.schema_change_target",
2526
14
        FT_STRING, BASE_NONE,
2527
14
        NULL, 0x0,
2528
14
        "CQL Schema Change target object", HFILL
2529
14
      }
2530
14
    },
2531
14
    {
2532
14
      &hf_cql_event_schema_change_object,
2533
14
      {
2534
14
        "Schema change event object name", "cql.schema_change_object_name",
2535
14
        FT_STRING, BASE_NONE,
2536
14
        NULL, 0x0,
2537
14
        "CQL Schema Change object name", HFILL
2538
14
      }
2539
14
    },
2540
14
    {
2541
14
      &hf_cql_event_schema_change_keyspace,
2542
14
      {
2543
14
        "Schema change event keyspace name", "cql.schema_change_keyspace",
2544
14
        FT_STRING, BASE_NONE,
2545
14
        NULL, 0x0,
2546
14
        "CQL Schema Change keyspace name", HFILL
2547
14
      }
2548
14
    },
2549
14
    {
2550
14
      &hf_cql_batch_query_size,
2551
14
      {
2552
14
        "Batch Query Size", "cql.batch_query_size",
2553
14
        FT_UINT16, BASE_DEC,
2554
14
        NULL, 0x0,
2555
14
        "Number of statements in CQL batch", HFILL
2556
14
      }
2557
14
    },
2558
14
    {
2559
14
      &hf_cql_error_code,
2560
14
      {
2561
14
        "Error Code", "cql.error_code",
2562
14
        FT_UINT32, BASE_HEX,
2563
14
        VALS(cql_error_names), 0x0,
2564
14
        "Error code from CQL server", HFILL
2565
14
      }
2566
14
    },
2567
14
    {
2568
14
      &hf_cql_result_kind,
2569
14
      {
2570
14
        "Result Kind", "cql.result.kind",
2571
14
        FT_INT32, BASE_DEC,
2572
14
        VALS(cql_result_kind_names), 0x0,
2573
14
        "Kind of result from CQL server", HFILL
2574
14
      }
2575
14
    },
2576
14
    {
2577
14
      &hf_cql_result_rows_column_count,
2578
14
      {
2579
14
        "Column Count", "cql.result.rows.column_count",
2580
14
        FT_INT32, BASE_DEC,
2581
14
        NULL, 0x0,
2582
14
        "Count of columns in a rows result from CQL server", HFILL
2583
14
      }
2584
14
    },
2585
14
    {
2586
14
      &hf_cql_result_prepared_pk_count,
2587
14
      {
2588
14
        "PK Count", "cql.result.prepared.pk_count",
2589
14
        FT_INT32, BASE_DEC,
2590
14
        NULL, 0x0,
2591
14
        "Count of Partition Key columns in a Prepared result from CQL server", HFILL
2592
14
      }
2593
14
    },
2594
14
    {
2595
14
      &hf_cql_result_rows_tuple_size,
2596
14
      {
2597
14
        "Tuple Size", "cql.result.rows.tuple_size",
2598
14
        FT_UINT16, BASE_DEC,
2599
14
        NULL, 0x0,
2600
14
        "Size of a tuple rows result from CQL server", HFILL
2601
14
      }
2602
14
    },
2603
14
    {
2604
14
      &hf_cql_result_timestamp,
2605
14
      {
2606
14
        "Timestamp (Epoch Time)", "cql.result.timestamp",
2607
14
        FT_INT64, BASE_DEC,
2608
14
        NULL, 0x0,
2609
14
        "Timestamp result", HFILL
2610
14
      }
2611
14
    },
2612
14
    {
2613
14
      &hf_cql_result_rows_data_type,
2614
14
      {
2615
14
        "CQL Data Type", "cql.data_type",
2616
14
        FT_UINT16, BASE_DEC,
2617
14
        VALS(cql_result_row_type_names), 0x0,
2618
14
        NULL, HFILL
2619
14
      }
2620
14
    },
2621
14
    {
2622
14
      &hf_cql_result_rows_row_count,
2623
14
      {
2624
14
        "CQL Result Rows Count", "cql.result.rows.row_count",
2625
14
        FT_INT32, BASE_DEC,
2626
14
        NULL, 0x0,
2627
14
        "Number of rows returned in CQL result", HFILL
2628
14
      }
2629
14
    },
2630
14
    {
2631
14
      &hf_cql_uuid,
2632
14
      {
2633
14
        "UUID", "cql.uuid",
2634
14
        FT_GUID, BASE_NONE,
2635
14
        NULL, 0x0,
2636
14
        NULL, HFILL
2637
14
      }
2638
14
    },
2639
14
    {
2640
14
      &hf_cql_tracing_uuid,
2641
14
      {
2642
14
        "Tracing UUID", "cql.tracing_uuid",
2643
14
        FT_GUID, BASE_NONE,
2644
14
        NULL, 0x0,
2645
14
        NULL, HFILL
2646
14
      }
2647
14
    },
2648
14
    {
2649
14
      &hf_cql_port,
2650
14
      {
2651
14
        "Port", "cql.port",
2652
14
        FT_UINT32, BASE_DEC,
2653
14
        NULL, 0x0,
2654
14
        NULL, HFILL
2655
14
      }
2656
14
    },
2657
14
    {
2658
14
      &hf_cql_boolean,
2659
14
      {
2660
14
        "Boolean", "cql.boolean",
2661
14
        FT_BOOLEAN, BASE_NONE,
2662
14
        NULL, 0x0,
2663
14
        NULL, HFILL
2664
14
      }
2665
14
    },
2666
14
    {
2667
14
      &hf_cql_ipv4,
2668
14
      {
2669
14
        "IPV4", "cql.ipv4",
2670
14
        FT_IPv4, BASE_NONE,
2671
14
        NULL, 0x0,
2672
14
        NULL, HFILL
2673
14
      }
2674
14
    },
2675
14
    {
2676
14
      &hf_cql_ipv6,
2677
14
      {
2678
14
        "IPV6", "cql.ipv6",
2679
14
        FT_IPv6, BASE_NONE,
2680
14
        NULL, 0x0,
2681
14
        NULL, HFILL
2682
14
      }
2683
14
    },
2684
14
  };
2685
2686
14
  static ei_register_info ei[] = {
2687
14
    { &ei_cql_data_not_dissected_yet,
2688
14
      { "cql.ie_data_not_dissected_yet",
2689
14
       PI_UNDECODED, PI_WARN, "IE data not dissected yet", EXPFILL }},
2690
14
    { &ei_cql_unexpected_negative_value,
2691
14
      { "cql.unexpected_negative_value",
2692
14
       PI_UNDECODED, PI_ERROR, "Unexpected negative value", EXPFILL }},
2693
14
  };
2694
2695
14
  static int* ett[] = {
2696
14
    &ett_cql_protocol,
2697
14
    &ett_cql_version,
2698
14
    &ett_cql_message,
2699
14
    &ett_cql_result_columns,
2700
14
    &ett_cql_results_no_metadata,
2701
14
    &ett_cql_result_map,
2702
14
    &ett_cql_result_set,
2703
14
    &ett_cql_result_metadata,
2704
14
    &ett_cql_result_metadata_colspec,
2705
14
    &ett_cql_result_rows,
2706
14
    &ett_cql_header_flags_bitmap,
2707
14
    &ett_cql_query_flags_bitmap,
2708
14
    &ett_cql_batch_flags_bitmap,
2709
14
    &ett_cql_custom_payload
2710
14
  };
2711
2712
14
  proto_cql = proto_register_protocol("Cassandra CQL Protocol", "CQL", "cql" );
2713
14
  register_dissector("cql", dissect_cql_tcp, proto_cql);
2714
2715
14
  proto_register_field_array(proto_cql, hf, array_length(hf));
2716
14
  proto_register_subtree_array(ett, array_length(ett));
2717
2718
14
  expert_cql = expert_register_protocol(proto_cql);
2719
14
  expert_register_field_array(expert_cql, ei, array_length(ei));
2720
14
}
2721
2722
/*
2723
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2724
 *
2725
 * Local variables:
2726
 * c-basic-offset: 8
2727
 * tab-width: 8
2728
 * indent-tabs-mode: t
2729
 * End:
2730
 *
2731
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2732
 * :indentSize=8:tabSize=8:noTabs=false:
2733
 */