dcerpc-netlogon: maintain netlogon_auth_vars for NetrServerAuthenticateKerberos
[wireshark-sm.git] / epan / dissectors / packet-scylla.c
blobb7c50b1a3c4b03a2936d119985aa3d28055b8182
1 /* packet-scylla.c
2 * Routines for Scylla RPC dissection
3 * Copyright 2020 ScyllaDB, Piotr Sarna <sarna@scylladb.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * ScyllaDB RPC protocol is used for inter-node communication
14 * in the ScyllaDB database - reading/sending data, exchanging
15 * cluster information through gossip, updating schemas, etc.
17 * Protocol references:
18 * https://github.com/scylladb/seastar/blob/master/doc/rpc.md
19 * https://github.com/scylladb/scylla/blob/master/message/messaging_service.hh
23 #include <config.h>
25 #include <epan/expert.h>
26 #include <epan/packet.h>
27 #include <epan/prefs.h>
28 #include "packet-tcp.h"
30 void proto_reg_handoff_scylla(void);
31 void proto_register_scylla(void);
33 static dissector_handle_t scylla_handle;
35 #define SCYLLA_PORT 0 /* Not IANA registered, 7000 is the expected value */
37 #define SCYLLA_HEADER_SIZE 28
38 #define SCYLLA_HEADER_VERB_OFFSET 8
39 #define SCYLLA_HEADER_MSG_ID_OFFSET 16
40 #define SCYLLA_HEADER_LEN_OFFSET 24
42 #define SCYLLA_RESPONSE_SIZE 12
43 #define SCYLLA_RESPONSE_MSG_ID_OFFSET 0
44 #define SCYLLA_RESPONSE_LEN_OFFSET 8
46 #define SCYLLA_NEGOTIATION_SIZE 12
47 #define SCYLLA_NEGOTIATION_LEN_OFFSET 8
49 static int proto_scylla;
51 static int hf_scylla_request;
52 static int hf_scylla_request_response_frame;
53 static int hf_scylla_timeout;
54 static int hf_scylla_verb;
55 static int hf_scylla_msg_id;
56 static int hf_scylla_len;
57 static int hf_scylla_response;
58 static int hf_scylla_response_size;
59 static int hf_scylla_response_request_frame;
60 static int hf_scylla_negotiation_magic;
61 static int hf_scylla_negotiation_size;
62 static int hf_scylla_payload; // TODO: dissect everything, so that generic "payload" is not needed
64 // Mutation
65 static int hf_scylla_mut_size1;
66 static int hf_scylla_mut_size2;
67 static int hf_scylla_mut_table_id;
68 static int hf_scylla_mut_schema_id;
69 static int hf_scylla_mut_len_pkeys;
70 static int hf_scylla_mut_num_pkeys;
71 static int hf_scylla_mut_len_pkey;
72 static int hf_scylla_mut_pkey;
74 // Read data
75 static int hf_scylla_read_data_timeout;
76 static int hf_scylla_read_data_table_id;
77 static int hf_scylla_read_data_schema_version;
79 static int ett_scylla;
80 static int ett_scylla_header;
81 static int ett_scylla_response;
82 static int ett_scylla_negotiation;
83 static int ett_scylla_mut;
84 static int ett_scylla_mut_pkey;
85 static int ett_scylla_read_data;
87 static bool scylla_desegment = true;
89 static expert_field ei_scylla_response_missing;
91 enum scylla_packets {
92 CLIENT_ID = 0,
93 MUTATION = 1,
94 MUTATION_DONE = 2,
95 READ_DATA = 3,
96 READ_MUTATION_DATA = 4,
97 READ_DIGEST = 5,
98 // Used by gossip
99 GOSSIP_DIGEST_SYN = 6,
100 GOSSIP_DIGEST_ACK = 7,
101 GOSSIP_DIGEST_ACK2 = 8,
102 GOSSIP_ECHO = 9,
103 GOSSIP_SHUTDOWN = 10,
104 // end of gossip verb
105 DEFINITIONS_UPDATE = 11,
106 TRUNCATE = 12,
107 REPLICATION_FINISHED = 13,
108 MIGRATION_REQUEST = 14,
109 // Used by streaming
110 PREPARE_MESSAGE = 15,
111 PREPARE_DONE_MESSAGE = 16,
112 STREAM_MUTATION = 17,
113 STREAM_MUTATION_DONE = 18,
114 COMPLETE_MESSAGE = 19,
115 // end of streaming verbs
116 REPAIR_CHECKSUM_RANGE = 20,
117 GET_SCHEMA_VERSION = 21,
118 SCHEMA_CHECK = 22,
119 COUNTER_MUTATION = 23,
120 MUTATION_FAILED = 24,
121 STREAM_MUTATION_FRAGMENTS = 25,
122 REPAIR_ROW_LEVEL_START = 26,
123 REPAIR_ROW_LEVEL_STOP = 27,
124 REPAIR_GET_FULL_ROW_HASHES = 28,
125 REPAIR_GET_COMBINED_ROW_HASH = 29,
126 REPAIR_GET_SYNC_BOUNDARY = 30,
127 REPAIR_GET_ROW_DIFF = 31,
128 REPAIR_PUT_ROW_DIFF = 32,
129 REPAIR_GET_ESTIMATED_PARTITIONS = 33,
130 REPAIR_SET_ESTIMATED_PARTITIONS = 34,
131 REPAIR_GET_DIFF_ALGORITHMS = 35,
132 REPAIR_GET_ROW_DIFF_WITH_RPC_STREAM = 36,
133 REPAIR_PUT_ROW_DIFF_WITH_RPC_STREAM = 37,
134 REPAIR_GET_FULL_ROW_HASHES_WITH_RPC_STREAM = 38,
135 PAXOS_PREPARE = 39,
136 PAXOS_ACCEPT = 40,
137 PAXOS_LEARN = 41,
138 HINT_MUTATION = 42,
139 PAXOS_PRUNE = 43,
140 LAST = 44,
143 static const val64_string packettypenames[] = {
144 {CLIENT_ID, "CLIENT_ID"},
145 {MUTATION, "MUTATION"},
146 {MUTATION_DONE, "MUTATION_DONE"},
147 {READ_DATA, "READ_DATA"},
148 {READ_MUTATION_DATA, "READ_MUTATION_DATA"},
149 {READ_DIGEST, "READ_DIGEST"},
150 {GOSSIP_DIGEST_SYN, "GOSSIP_DIGEST_SYN"},
151 {GOSSIP_DIGEST_ACK, "GOSSIP_DIGEST_ACK"},
152 {GOSSIP_DIGEST_ACK2, "GOSSIP_DIGEST_ACK2"},
153 {GOSSIP_ECHO, "GOSSIP_ECHO"},
154 {GOSSIP_SHUTDOWN, "GOSSIP_SHUTDOWN"},
155 {DEFINITIONS_UPDATE, "DEFINITIONS_UPDATE"},
156 {TRUNCATE, "TRUNCATE"},
157 {REPLICATION_FINISHED, "REPLICATION_FINISHED"},
158 {MIGRATION_REQUEST, "MIGRATION_REQUEST"},
159 {PREPARE_MESSAGE, "PREPARE_MESSAGE"},
160 {PREPARE_DONE_MESSAGE, "PREPARE_DONE_MESSAGE"},
161 {STREAM_MUTATION, "STREAM_MUTATION"},
162 {STREAM_MUTATION_DONE, "STREAM_MUTATION_DONE"},
163 {COMPLETE_MESSAGE, "COMPLETE_MESSAGE"},
164 {REPAIR_CHECKSUM_RANGE, "REPAIR_CHECKSUM_RANGE"},
165 {GET_SCHEMA_VERSION, "GET_SCHEMA_VERSION"},
166 {SCHEMA_CHECK, "SCHEMA_CHECK"},
167 {COUNTER_MUTATION, "COUNTER_MUTATION"},
168 {MUTATION_FAILED, "MUTATION_FAILED"},
169 {STREAM_MUTATION_FRAGMENTS, "STREAM_MUTATION_FRAGMENTS"},
170 {REPAIR_ROW_LEVEL_START, "REPAIR_ROW_LEVEL_START"},
171 {REPAIR_ROW_LEVEL_STOP, "REPAIR_ROW_LEVEL_STOP"},
172 {REPAIR_GET_FULL_ROW_HASHES, "REPAIR_GET_FULL_ROW_HASHES"},
173 {REPAIR_GET_COMBINED_ROW_HASH, "REPAIR_GET_COMBINED_ROW_HASH"},
174 {REPAIR_GET_SYNC_BOUNDARY, "REPAIR_GET_SYNC_BOUNDARY"},
175 {REPAIR_GET_ROW_DIFF, "REPAIR_GET_ROW_DIFF"},
176 {REPAIR_PUT_ROW_DIFF, "REPAIR_PUT_ROW_DIFF"},
177 {REPAIR_GET_ESTIMATED_PARTITIONS, "REPAIR_GET_ESTIMATED_PARTITIONS"},
178 {REPAIR_SET_ESTIMATED_PARTITIONS, "REPAIR_SET_ESTIMATED_PARTITIONS"},
179 {REPAIR_GET_DIFF_ALGORITHMS, "REPAIR_GET_DIFF_ALGORITHMS"},
180 {REPAIR_GET_ROW_DIFF_WITH_RPC_STREAM, "REPAIR_GET_ROW_DIFF_WITH_RPC_STREAM"},
181 {REPAIR_PUT_ROW_DIFF_WITH_RPC_STREAM, "REPAIR_PUT_ROW_DIFF_WITH_RPC_STREAM"},
182 {REPAIR_GET_FULL_ROW_HASHES_WITH_RPC_STREAM, "REPAIR_GET_FULL_ROW_HASHES_WITH_RPC_STREAM"},
183 {PAXOS_PREPARE, "PAXOS_PREPARE"},
184 {PAXOS_ACCEPT, "PAXOS_ACCEPT"},
185 {PAXOS_LEARN, "PAXOS_LEARN"},
186 {HINT_MUTATION, "HINT_MUTATION"},
187 {PAXOS_PRUNE, "PAXOS_PRUNE"},
188 {0, NULL}
191 static bool
192 looks_like_rpc_negotiation(tvbuff_t *tvb, const int offset) {
193 return tvb_memeql(tvb, offset, (const uint8_t *)"SSTARRPC", 8) == 0;
196 static bool
197 looks_like_response(uint64_t verb_type, uint32_t len) {
198 return verb_type >= LAST || len > 64*1024*1024;
201 typedef struct {
202 uint64_t verb_type;
203 uint32_t request_frame_num;
204 uint32_t response_frame_num;
205 } request_response_t;
207 static unsigned
208 get_scylla_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
210 uint64_t verb_type = LAST;
211 uint32_t plen = 0;
212 if (looks_like_rpc_negotiation(tvb, offset)) {
213 return tvb_get_letohl(tvb, offset + SCYLLA_NEGOTIATION_LEN_OFFSET) + SCYLLA_NEGOTIATION_SIZE;
215 if (tvb_reported_length(tvb) >= SCYLLA_HEADER_SIZE) {
216 plen = tvb_get_letohl(tvb, offset + SCYLLA_HEADER_LEN_OFFSET);
217 verb_type = tvb_get_letoh64(tvb, offset + SCYLLA_HEADER_VERB_OFFSET);
220 if (looks_like_response(verb_type, plen)) {
221 return tvb_get_letohl(tvb, offset + SCYLLA_RESPONSE_LEN_OFFSET) + SCYLLA_RESPONSE_SIZE;
223 return plen + SCYLLA_HEADER_SIZE;
226 static int
227 dissect_scylla_negotiation_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *scylla_tree)
229 int offset = 0;
230 uint32_t len = tvb_get_letohl(tvb, offset + SCYLLA_NEGOTIATION_LEN_OFFSET) + SCYLLA_NEGOTIATION_SIZE;
232 proto_tree *scylla_negotiation_tree = proto_tree_add_subtree(scylla_tree, tvb, offset,
233 len, ett_scylla_negotiation, NULL, "Protocol negotiation");
234 proto_tree_add_item(scylla_negotiation_tree, hf_scylla_negotiation_magic, tvb, offset, 8, ENC_ASCII);
235 int negotiation_offset = 8;
236 proto_tree_add_item(scylla_negotiation_tree, hf_scylla_negotiation_size, tvb, offset + negotiation_offset, 4, ENC_LITTLE_ENDIAN);
237 negotiation_offset += 4;
238 proto_tree_add_item(scylla_negotiation_tree, hf_scylla_payload, tvb, offset + negotiation_offset, len - negotiation_offset, ENC_NA);
240 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Scylla");
241 col_set_str(pinfo->cinfo, COL_INFO, "Protocol negotiation");
242 return tvb_reported_length(tvb);
245 static int
246 dissect_scylla_response_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *scylla_tree, request_response_t *req_resp)
248 int offset = 0;
249 uint32_t len = tvb_get_letohl(tvb, offset + SCYLLA_RESPONSE_LEN_OFFSET) + SCYLLA_RESPONSE_SIZE;
251 /* Add response subtree */
252 proto_item *response_ti = proto_tree_add_string_format(scylla_tree, hf_scylla_response,
253 tvb, offset, len, "", "Response");
254 proto_tree *scylla_response_tree = proto_item_add_subtree(response_ti, ett_scylla_response);
256 int resp_offset = 0;
258 uint64_t msg_id;
259 proto_tree_add_item_ret_uint64(scylla_response_tree, hf_scylla_msg_id, tvb, offset + resp_offset, 8, ENC_LITTLE_ENDIAN, &msg_id);
260 resp_offset += 8;
261 proto_tree_add_item(scylla_response_tree, hf_scylla_response_size, tvb, offset + resp_offset, 4, ENC_LITTLE_ENDIAN);
262 resp_offset += 4;
263 proto_tree_add_item(scylla_response_tree, hf_scylla_payload, tvb, offset + resp_offset, len - resp_offset, ENC_NA);
265 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Scylla");
266 if (req_resp) {
267 /* Fill in the response frame */
268 req_resp->response_frame_num = pinfo->num;
270 proto_item *verb_item = proto_tree_add_uint64(scylla_response_tree, hf_scylla_verb, tvb, offset + len, 8, req_resp->verb_type);
271 proto_item_set_generated(verb_item);
272 proto_item *req = proto_tree_add_uint(scylla_tree, hf_scylla_response_request_frame, tvb, 0, 0, req_resp->request_frame_num);
273 proto_item_set_generated(req);
275 proto_item_append_text(response_ti, " (msg_id=%" PRIu64 ", %s)",
276 msg_id, val64_to_str(req_resp->verb_type, packettypenames, "Unknown (0x%02x)"));
278 col_clear(pinfo->cinfo, COL_INFO);
279 col_add_fstr(pinfo->cinfo, COL_INFO, "Response for %s",
280 val64_to_str(req_resp->verb_type, packettypenames, "Unknown (0x%02x)"));
281 } else {
282 col_set_str(pinfo->cinfo, COL_INFO, "Response for unknown packet");
284 return tvb_reported_length(tvb);
287 static int
288 dissect_scylla_msg_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *scylla_tree, proto_item *ti, uint64_t verb_type, uint32_t len, request_response_t *req_resp)
290 int offset = 0;
292 /* Add request subtree */
293 proto_item *request_ti = proto_tree_add_string_format(scylla_tree, hf_scylla_request,
294 tvb, offset, SCYLLA_HEADER_SIZE,
295 "", "Header for %s",
296 val64_to_str(verb_type, packettypenames, "Unknown (0x%02x)"));
297 proto_tree *scylla_header_tree = proto_item_add_subtree(request_ti, ett_scylla_response);
299 proto_tree_add_item(scylla_header_tree, hf_scylla_timeout, tvb, offset, 8, ENC_LITTLE_ENDIAN);
300 offset += 8;
301 proto_item_append_text(ti, ", Type %s", val64_to_str(verb_type, packettypenames, "Unknown (0x%02x)"));
302 proto_tree_add_item(scylla_header_tree, hf_scylla_verb, tvb, offset, 8, ENC_LITTLE_ENDIAN);
303 offset += 8;
304 uint64_t msg_id;
305 proto_tree_add_item_ret_uint64(scylla_header_tree, hf_scylla_msg_id, tvb, offset, 8, ENC_LITTLE_ENDIAN, &msg_id);
306 offset += 8;
307 proto_tree_add_item(scylla_header_tree, hf_scylla_len, tvb, offset, 4, ENC_LITTLE_ENDIAN);
308 offset += 4;
310 proto_item_append_text(request_ti, " (msg_id=%" PRIu64 ")", msg_id);
312 switch (verb_type) {
313 case MUTATION: {
314 proto_tree* scylla_mut_tree = proto_tree_add_subtree(scylla_tree, tvb, offset,
315 len, ett_scylla_mut, NULL, "Mutation");
316 int mut_offset = 0;
317 uint32_t len_keys;
318 uint32_t num_keys;
319 proto_tree_add_item(scylla_mut_tree, hf_scylla_mut_size1, tvb, offset + mut_offset, 4, ENC_LITTLE_ENDIAN);
320 mut_offset += 4;
321 proto_tree_add_item(scylla_mut_tree, hf_scylla_mut_size2, tvb, offset + mut_offset, 4, ENC_LITTLE_ENDIAN);
322 mut_offset += 4;
323 proto_tree_add_item(scylla_mut_tree, hf_scylla_mut_table_id, tvb, offset + mut_offset, 16, ENC_NA);
324 mut_offset += 16;
325 proto_tree_add_item(scylla_mut_tree, hf_scylla_mut_schema_id, tvb, offset + mut_offset, 16, ENC_NA);
326 mut_offset += 16;
327 proto_tree_add_item_ret_uint(scylla_mut_tree, hf_scylla_mut_len_pkeys, tvb, offset + mut_offset, 4, ENC_LITTLE_ENDIAN, &len_keys);
328 mut_offset += 4;
329 proto_tree* scylla_mut_pkey_tree = proto_tree_add_subtree(scylla_mut_tree, tvb, offset + mut_offset,
330 len - mut_offset, ett_scylla_mut_pkey, NULL, "Partition key");
331 proto_tree_add_item_ret_uint(scylla_mut_pkey_tree, hf_scylla_mut_num_pkeys, tvb, offset + mut_offset, 4, ENC_LITTLE_ENDIAN, &num_keys);
332 mut_offset += 4;
333 unsigned i;
334 for (i = 0; i < num_keys; ++i) {
335 uint32_t len_pkey = tvb_get_letohl(tvb, offset + mut_offset);
336 proto_tree_add_item(scylla_mut_pkey_tree, hf_scylla_mut_len_pkey, tvb, offset + mut_offset, 4, ENC_LITTLE_ENDIAN);
337 mut_offset += 4;
338 proto_tree_add_item(scylla_mut_pkey_tree, hf_scylla_mut_pkey, tvb, offset + mut_offset, len_pkey, ENC_NA);
339 mut_offset += len_pkey;
341 // TODO: dissect further
342 proto_tree_add_item(scylla_mut_tree, hf_scylla_payload, tvb, offset + mut_offset, len - mut_offset, ENC_NA);
344 break;
345 case READ_DATA: {
346 proto_tree* scylla_read_tree = proto_tree_add_subtree(scylla_tree, tvb, offset,
347 len, ett_scylla_read_data, NULL, "Read data");
348 int rd_offset = 0;
350 proto_tree_add_item(scylla_read_tree, hf_scylla_read_data_timeout, tvb, offset + rd_offset, 4, ENC_LITTLE_ENDIAN);
351 rd_offset += 4;
352 proto_tree_add_item(scylla_read_tree, hf_scylla_read_data_table_id, tvb, offset + rd_offset, 16, ENC_NA);
353 rd_offset += 16;
354 proto_tree_add_item(scylla_read_tree, hf_scylla_read_data_schema_version, tvb, offset + rd_offset, 16, ENC_NA);
355 rd_offset += 16;
356 //TODO: dissect further
357 proto_tree_add_item(scylla_read_tree, hf_scylla_payload, tvb, offset + rd_offset, len - rd_offset, ENC_NA);
359 break;
360 default:
361 // Generic payload. TODO: dissect
362 proto_tree_add_item(scylla_tree, hf_scylla_payload, tvb, offset, len, ENC_NA);
363 break;
366 /* req_resp will only be set if fd was already visited (PINFO_FD_VISITED(pinfo)) */
367 if (req_resp) {
368 if (req_resp->response_frame_num > 0) {
369 proto_item *rep = proto_tree_add_uint(scylla_tree, hf_scylla_request_response_frame, tvb, 0, 0, req_resp->response_frame_num);
370 proto_item_set_generated(rep);
371 } else {
372 expert_add_info(pinfo, request_ti, &ei_scylla_response_missing);
376 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Scylla");
377 col_clear(pinfo->cinfo, COL_INFO);
378 col_add_fstr(pinfo->cinfo, COL_INFO, "Request %s",
379 val64_to_str(verb_type, packettypenames, "Unknown (0x%02x)"));
380 return tvb_reported_length(tvb);
383 static bool
384 response_expected(uint64_t verb_type)
386 switch (verb_type) {
387 case GOSSIP_DIGEST_SYN:
388 case GOSSIP_DIGEST_ACK:
389 case GOSSIP_DIGEST_ACK2:
390 case GOSSIP_SHUTDOWN:
391 case DEFINITIONS_UPDATE:
392 case MUTATION:
393 case MUTATION_DONE:
394 case MUTATION_FAILED:
395 case HINT_MUTATION:
396 case PAXOS_LEARN:
397 case PAXOS_PRUNE:
398 return false;
399 default:
400 return true;
405 static int
406 dissect_scylla_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
408 int offset = 0;
409 conversation_t *conversation;
410 wmem_map_t *conv_map;
412 proto_item *ti = proto_tree_add_item(tree, proto_scylla, tvb, 0, -1, ENC_NA);
413 proto_tree *scylla_tree = proto_item_add_subtree(ti, ett_scylla);
415 uint64_t verb_type = LAST;
416 uint32_t len = 0;
418 if (looks_like_rpc_negotiation(tvb, offset)) {
419 return dissect_scylla_negotiation_pdu(tvb, pinfo, scylla_tree);
422 if (tvb_reported_length(tvb) >= SCYLLA_HEADER_SIZE) {
423 verb_type = tvb_get_letoh64(tvb, offset + SCYLLA_HEADER_VERB_OFFSET);
424 len = tvb_get_letohl(tvb, offset + SCYLLA_HEADER_LEN_OFFSET);
427 conversation = find_or_create_conversation(pinfo);
428 conv_map = (wmem_map_t *)conversation_get_proto_data(conversation, proto_scylla);
429 if (conv_map == NULL) {
430 conv_map = wmem_map_new(wmem_file_scope(), wmem_int64_hash, g_int64_equal);
431 conversation_add_proto_data(conversation, proto_scylla, conv_map);
434 if (looks_like_response(verb_type, len)) {
435 void *req_resp;
436 uint64_t msg_id;
437 msg_id = tvb_get_letoh64(tvb, offset + SCYLLA_RESPONSE_MSG_ID_OFFSET);
438 req_resp = wmem_map_lookup(conv_map, &msg_id);
439 return dissect_scylla_response_pdu(tvb, pinfo, scylla_tree, (request_response_t *)req_resp);
442 uint64_t msg_id = tvb_get_letoh64(tvb, offset + SCYLLA_HEADER_MSG_ID_OFFSET);
443 void *req_resp = NULL;
445 if (response_expected(verb_type)) {
446 if (!PINFO_FD_VISITED(pinfo)) {
447 uint64_t *key = wmem_new(wmem_file_scope(), uint64_t);
448 request_response_t *val = wmem_new(wmem_file_scope(), request_response_t);
449 *key = msg_id;
450 val->verb_type = verb_type;
451 val->request_frame_num = pinfo->num;
452 wmem_map_insert(conv_map, key, val);
453 } else {
454 req_resp = wmem_map_lookup(conv_map, &msg_id);
458 return dissect_scylla_msg_pdu(tvb, pinfo, scylla_tree, ti, verb_type, len, (request_response_t *)req_resp);
461 static int
462 dissect_scylla(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
464 tcp_dissect_pdus(tvb, pinfo, tree, scylla_desegment, SCYLLA_NEGOTIATION_SIZE,
465 get_scylla_pdu_len, dissect_scylla_pdu, data);
466 return tvb_reported_length(tvb);
469 void
470 proto_register_scylla(void)
472 static hf_register_info hf[] = {
473 // RPC header
474 { &hf_scylla_request, { "request", "scylla.request", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
475 { &hf_scylla_request_response_frame, { "Response frame", "scylla.request.response", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, NULL, HFILL } },
476 { &hf_scylla_timeout, { "RPC timeout", "scylla.timeout", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
477 { &hf_scylla_verb, { "verb", "scylla.verb", FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(packettypenames), 0x0, NULL, HFILL } },
478 { &hf_scylla_msg_id, { "msg id", "scylla.msg_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
479 { &hf_scylla_len, { "packet length", "scylla.len", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
480 { &hf_scylla_payload, { "payload", "scylla.payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
481 { &hf_scylla_response, { "response", "scylla.response", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
482 { &hf_scylla_response_size, { "response size", "scylla.response.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
483 { &hf_scylla_response_request_frame, { "Request frame", "scylla.response.request", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, NULL, HFILL } },
484 { &hf_scylla_negotiation_magic, { "negotiation magic sequence", "scylla.negotiation.magic", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
485 { &hf_scylla_negotiation_size, { "negotiation size", "scylla.negotiation.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
486 // mutation verb
487 { &hf_scylla_mut_size1, { "mutation size 1", "scylla.mut.size1", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
488 { &hf_scylla_mut_size2, { "mutation size 2", "scylla.mut.size2", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
489 { &hf_scylla_mut_table_id, { "mutation table id", "scylla.mut.table_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
490 { &hf_scylla_mut_schema_id, { "mutation schema id", "scylla.mut.schema_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
491 { &hf_scylla_mut_len_pkeys, { "size of partition keys payload", "scylla.mut.len_pkeys", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
492 { &hf_scylla_mut_num_pkeys, { "number of partition keys", "scylla.mut.num_pkeys", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
493 { &hf_scylla_mut_len_pkey, { "length of a partition key", "scylla.mut.len_pkey", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
494 { &hf_scylla_mut_pkey, { "partition key", "scylla.mut.pkey", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
495 // read_data verb
496 { &hf_scylla_read_data_timeout, { "timeout", "scylla.read_data.timeout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
497 { &hf_scylla_read_data_table_id, { "table ID", "scylla.read_data.table_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
498 { &hf_scylla_read_data_schema_version, { "Schema version", "scylla.read_data.schema_version", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
502 static ei_register_info ei[] = {
503 { &ei_scylla_response_missing,
504 { "scylla.ei_scylla_response_missing",
505 PI_COMMENTS_GROUP, PI_NOTE, "Response has not arrived yet", EXPFILL }},
508 /* Setup protocol subtree array */
509 static int *ett[] = {
510 &ett_scylla,
511 &ett_scylla_header,
512 &ett_scylla_response,
513 &ett_scylla_negotiation,
514 &ett_scylla_mut,
515 &ett_scylla_mut_pkey,
516 &ett_scylla_read_data,
519 expert_module_t* expert_scylla;
521 proto_scylla = proto_register_protocol("Scylla RPC protocol", "Scylla", "scylla");
522 module_t* scylla_module = prefs_register_protocol(proto_scylla, NULL);
523 prefs_register_bool_preference(scylla_module, "desegment",
524 "Desegment all Scylla messages spanning multiple TCP segments",
525 "Whether Scylla dissector should desegment all messages spanning multiple TCP segments",
526 &scylla_desegment);
528 proto_register_field_array(proto_scylla, hf, array_length(hf));
529 proto_register_subtree_array(ett, array_length(ett));
530 expert_scylla = expert_register_protocol(proto_scylla);
531 expert_register_field_array(expert_scylla, ei, array_length(ei));
533 scylla_handle = register_dissector("scylla", dissect_scylla, proto_scylla);
536 void
537 proto_reg_handoff_scylla(void)
539 dissector_add_uint_with_preference("tcp.port", SCYLLA_PORT, scylla_handle);
543 * Editor modelines - https://www.wireshark.org/tools/modelines.html
545 * Local variables:
546 * c-basic-offset: 4
547 * tab-width: 8
548 * indent-tabs-mode: nil
549 * End:
551 * vi: set shiftwidth=4 tabstop=8 expandtab:
552 * :indentSize=4:tabSize=8:noTabs=true: