2 * Routines for CTDB (Cluster TDB) dissection
3 * Copyright 2007, Ronnie Sahlberg
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
37 #include <epan/value_string.h>
38 #include <epan/emem.h>
40 /* Initialize the protocol and registered fields */
41 static int proto_ctdb = -1;
42 static int hf_ctdb_length = -1;
43 static int hf_ctdb_opcode = -1;
44 static int hf_ctdb_magic = -1;
45 static int hf_ctdb_version = -1;
46 static int hf_ctdb_dst = -1;
47 static int hf_ctdb_src = -1;
48 static int hf_ctdb_id = -1;
49 static int hf_ctdb_flags_immediate = -1;
50 static int hf_ctdb_dbid = -1;
51 static int hf_ctdb_callid = -1;
52 static int hf_ctdb_status = -1;
53 static int hf_ctdb_keylen = -1;
54 static int hf_ctdb_datalen = -1;
55 static int hf_ctdb_errorlen = -1;
56 static int hf_ctdb_key = -1;
57 static int hf_ctdb_keyhash = -1;
58 static int hf_ctdb_data = -1;
59 static int hf_ctdb_error = -1;
60 static int hf_ctdb_dmaster = -1;
61 static int hf_ctdb_request_in = -1;
62 static int hf_ctdb_response_in = -1;
63 static int hf_ctdb_time = -1;
64 static int hf_ctdb_generation = -1;
65 static int hf_ctdb_hopcount = -1;
66 static int hf_ctdb_rsn = -1;
67 static int hf_ctdb_ctrl_opcode = -1;
68 static int hf_ctdb_srvid = -1;
69 static int hf_ctdb_clientid = -1;
70 static int hf_ctdb_ctrl_flags = -1;
71 static int hf_ctdb_recmaster = -1;
72 static int hf_ctdb_recmode = -1;
73 static int hf_ctdb_num_nodes = -1;
74 static int hf_ctdb_vnn = -1;
75 static int hf_ctdb_node_flags = -1;
76 static int hf_ctdb_node_ip = -1;
77 static int hf_ctdb_pid = -1;
78 static int hf_ctdb_process_exists = -1;
80 /* Initialize the subtree pointers */
81 static gint ett_ctdb = -1;
82 static gint ett_ctdb_key = -1;
84 /* this tree keeps track of caller/reqid for ctdb transactions */
85 emem_tree_t *ctdb_transactions=NULL;
86 typedef struct _ctdb_trans_t {
93 /* this tree keeps track of CONTROL request/responses */
94 emem_tree_t *ctdb_controls=NULL;
95 typedef struct _ctdb_control_t {
102 #define CTDB_REQ_CALL 0
103 #define CTDB_REPLY_CALL 1
104 #define CTDB_REQ_DMASTER 2
105 #define CTDB_REPLY_DMASTER 3
106 #define CTDB_REPLY_ERROR 4
107 #define CTDB_REQ_MESSAGE 5
108 #define CTDB_REQ_CONTROL 7
109 #define CTDB_REPLY_CONTROL 8
110 #define CTDB_REQ_KEEPALIVE 9
111 static const value_string ctdb_opcodes[] = {
112 {CTDB_REQ_CALL, "REQ_CALL"},
113 {CTDB_REPLY_CALL, "REPLY_CALL"},
114 {CTDB_REQ_DMASTER, "REQ_DMASTER"},
115 {CTDB_REPLY_DMASTER, "REPLY_DMASTER"},
116 {CTDB_REPLY_ERROR, "REPLY_ERROR"},
117 {CTDB_REQ_MESSAGE, "REQ_MESSAGE"},
118 {CTDB_REQ_CONTROL, "REQ_CONTROL"},
119 {CTDB_REPLY_CONTROL, "REPLY_CONTROL"},
120 {CTDB_REQ_KEEPALIVE, "REQ_KEEPALIVE"},
125 #define CTDB_CONTROL_PROCESS_EXISTS 0
126 #define CTDB_CONTROL_STATISTICS 1
127 #define CTDB_CONTROL_CONFIG 2
128 #define CTDB_CONTROL_PING 3
129 #define CTDB_CONTROL_GETDBPATH 4
130 #define CTDB_CONTROL_GETVNNMAP 5
131 #define CTDB_CONTROL_SETVNNMAP 6
132 #define CTDB_CONTROL_GET_DEBUG 7
133 #define CTDB_CONTROL_SET_DEBUG 8
134 #define CTDB_CONTROL_GET_DBMAP 9
135 #define CTDB_CONTROL_GET_NODEMAP 10
136 #define CTDB_CONTROL_SET_DMASTER 11
137 #define CTDB_CONTROL_CLEAR_DB 12
138 #define CTDB_CONTROL_PULL_DB 13
139 #define CTDB_CONTROL_PUSH_DB 14
140 #define CTDB_CONTROL_GET_RECMODE 15
141 #define CTDB_CONTROL_SET_RECMODE 16
142 #define CTDB_CONTROL_STATISTICS_RESET 17
143 #define CTDB_CONTROL_DB_ATTACH 18
144 #define CTDB_CONTROL_SET_CALL 19
145 #define CTDB_CONTROL_TRAVERSE_START 20
146 #define CTDB_CONTROL_TRAVERSE_ALL 21
147 #define CTDB_CONTROL_TRAVERSE_DATA 22
148 #define CTDB_CONTROL_REGISTER_SRVID 23
149 #define CTDB_CONTROL_DEREGISTER_SRVID 24
150 #define CTDB_CONTROL_GET_DBNAME 25
151 #define CTDB_CONTROL_ENABLE_SEQNUM 26
152 #define CTDB_CONTROL_UPDATE_SEQNUM 27
153 #define CTDB_CONTROL_SET_SEQNUM_FREQUENCY 28
154 #define CTDB_CONTROL_DUMP_MEMORY 29
155 #define CTDB_CONTROL_GET_PID 30
156 #define CTDB_CONTROL_GET_RECMASTER 31
157 #define CTDB_CONTROL_SET_RECMASTER 32
158 #define CTDB_CONTROL_FREEZE 33
159 #define CTDB_CONTROL_THAW 34
160 #define CTDB_CONTROL_GET_VNN 35
161 #define CTDB_CONTROL_SHUTDOWN 36
162 #define CTDB_CONTROL_GET_MONMODE 37
163 #define CTDB_CONTROL_SET_MONMODE 38
164 #define CTDB_CONTROL_MAX_RSN 39
165 #define CTDB_CONTROL_SET_RSN_NONEMPTY 40
166 #define CTDB_CONTROL_DELETE_LOW_RSN 41
167 #define CTDB_CONTROL_TAKEOVER_IP 42
168 #define CTDB_CONTROL_RELEASE_IP 43
169 #define CTDB_CONTROL_TCP_CLIENT 44
170 #define CTDB_CONTROL_TCP_ADD 45
171 #define CTDB_CONTROL_TCP_REMOVE 46
172 #define CTDB_CONTROL_STARTUP 47
173 #define CTDB_CONTROL_SET_TUNABLE 48
174 #define CTDB_CONTROL_GET_TUNABLE 49
175 #define CTDB_CONTROL_LIST_TUNABLES 50
176 #define CTDB_CONTROL_GET_PUBLIC_IPS 51
177 #define CTDB_CONTROL_MODIFY_FLAGS 52
178 #define CTDB_CONTROL_GET_ALL_TUNABLES 53
179 #define CTDB_CONTROL_KILL_TCP 54
180 #define CTDB_CONTROL_GET_TCP_TICKLE_LIST 55
181 #define CTDB_CONTROL_SET_TCP_TICKLE_LIST 56
182 #define CTDB_CONTROL_REGISTER_SERVER_ID 57
183 #define CTDB_CONTROL_UNREGISTER_SERVER_ID 58
184 #define CTDB_CONTROL_CHECK_SERVER_ID 59
185 #define CTDB_CONTROL_GET_SERVER_ID_LIST 60
186 #define CTDB_CONTROL_DB_ATTACH_PERSISTENT 61
187 #define CTDB_CONTROL_PERSISTENT_STORE 62
188 #define CTDB_CONTROL_UPDATE_RECORD 63
190 static const value_string ctrl_opcode_vals[] = {
191 {CTDB_CONTROL_PROCESS_EXISTS, "PROCESS_EXISTS"},
192 {CTDB_CONTROL_STATISTICS, "STATISTICS"},
193 {CTDB_CONTROL_CONFIG, "CONFIG"},
194 {CTDB_CONTROL_PING, "PING"},
195 {CTDB_CONTROL_GETDBPATH, "GETDBPATH"},
196 {CTDB_CONTROL_GETVNNMAP, "GETVNNMAP"},
197 {CTDB_CONTROL_SETVNNMAP, "SETVNNMAP"},
198 {CTDB_CONTROL_GET_DEBUG, "GET_DEBUG"},
199 {CTDB_CONTROL_SET_DEBUG, "SET_DEBUG"},
200 {CTDB_CONTROL_GET_DBMAP, "GET_DBMAP"},
201 {CTDB_CONTROL_GET_NODEMAP, "GET_NODEMAP"},
202 {CTDB_CONTROL_SET_DMASTER, "SET_DMASTER"},
203 {CTDB_CONTROL_CLEAR_DB, "CLEAR_DB"},
204 {CTDB_CONTROL_PULL_DB, "PULL_DB"},
205 {CTDB_CONTROL_PUSH_DB, "PUSH_DB"},
206 {CTDB_CONTROL_GET_RECMODE, "GET_RECMODE"},
207 {CTDB_CONTROL_SET_RECMODE, "SET_RECMODE"},
208 {CTDB_CONTROL_STATISTICS_RESET, "STATISTICS_RESET"},
209 {CTDB_CONTROL_DB_ATTACH, "DB_ATTACH"},
210 {CTDB_CONTROL_SET_CALL, "SET_CALL"},
211 {CTDB_CONTROL_TRAVERSE_START, "TRAVERSE_START"},
212 {CTDB_CONTROL_TRAVERSE_ALL, "TRAVERSE_ALL"},
213 {CTDB_CONTROL_TRAVERSE_DATA, "TRAVERSE_DATA"},
214 {CTDB_CONTROL_REGISTER_SRVID, "REGISTER_SRVID"},
215 {CTDB_CONTROL_DEREGISTER_SRVID, "DEREGISTER_SRVID"},
216 {CTDB_CONTROL_GET_DBNAME, "GET_DBNAME"},
217 {CTDB_CONTROL_ENABLE_SEQNUM, "ENABLE_SEQNUM"},
218 {CTDB_CONTROL_UPDATE_SEQNUM, "UPDATE_SEQNUM"},
219 {CTDB_CONTROL_SET_SEQNUM_FREQUENCY, "SET_SEQNUM_FREQUENCY"},
220 {CTDB_CONTROL_DUMP_MEMORY, "DUMP_MEMORY"},
221 {CTDB_CONTROL_GET_PID, "GET_PID"},
222 {CTDB_CONTROL_GET_RECMASTER, "GET_RECMASTER"},
223 {CTDB_CONTROL_SET_RECMASTER, "SET_RECMASTER"},
224 {CTDB_CONTROL_FREEZE, "FREEZE"},
225 {CTDB_CONTROL_THAW, "THAW"},
226 {CTDB_CONTROL_GET_VNN, "GET_VNN"},
227 {CTDB_CONTROL_SHUTDOWN, "SHUTDOWN"},
228 {CTDB_CONTROL_GET_MONMODE, "GET_MONMODE"},
229 {CTDB_CONTROL_SET_MONMODE, "SET_MONMODE"},
230 {CTDB_CONTROL_MAX_RSN, "MAX_RSN"},
231 {CTDB_CONTROL_SET_RSN_NONEMPTY, "SET_RSN_NONEMPTY"},
232 {CTDB_CONTROL_DELETE_LOW_RSN, "DELETE_LOW_RSN"},
233 {CTDB_CONTROL_TAKEOVER_IP, "TAKEOVER_IP"},
234 {CTDB_CONTROL_RELEASE_IP, "RELEASE_IP"},
235 {CTDB_CONTROL_TCP_CLIENT, "TCP_CLIENT"},
236 {CTDB_CONTROL_TCP_ADD, "TCP_ADD"},
237 {CTDB_CONTROL_TCP_REMOVE, "TCP_REMOVE"},
238 {CTDB_CONTROL_STARTUP, "STARTUP"},
239 {CTDB_CONTROL_SET_TUNABLE, "SET_TUNABLE"},
240 {CTDB_CONTROL_GET_TUNABLE, "GET_TUNABLE"},
241 {CTDB_CONTROL_LIST_TUNABLES, "LIST_TUNABLES"},
242 {CTDB_CONTROL_GET_PUBLIC_IPS, "GET_PUBLIC_IPS"},
243 {CTDB_CONTROL_MODIFY_FLAGS, "MODIFY_FLAGS"},
244 {CTDB_CONTROL_GET_ALL_TUNABLES, "GET_ALL_TUNABLES"},
245 {CTDB_CONTROL_KILL_TCP, "KILL_TCP"},
246 {CTDB_CONTROL_GET_TCP_TICKLE_LIST, "GET_TCP_TICKLE_LIST"},
247 {CTDB_CONTROL_SET_TCP_TICKLE_LIST, "SET_TCP_TICKLE_LIST"},
248 {CTDB_CONTROL_REGISTER_SERVER_ID, "REGISTER_SERVER_ID"},
249 {CTDB_CONTROL_UNREGISTER_SERVER_ID, "UNREGISTER_SERVER_ID"},
250 {CTDB_CONTROL_CHECK_SERVER_ID, "CHECK_SERVER_ID"},
251 {CTDB_CONTROL_GET_SERVER_ID_LIST, "GET_SERVER_ID_LIST"},
252 {CTDB_CONTROL_DB_ATTACH_PERSISTENT, "DB_ATTACH_PERSISTENT"},
253 {CTDB_CONTROL_PERSISTENT_STORE, "PERSISTENT_STORE"},
254 {CTDB_CONTROL_UPDATE_RECORD, "UPDATE_RECORD"},
260 static int dissect_control_get_recmaster_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess _U_)
262 proto_tree_add_uint(tree, hf_ctdb_recmaster, tvb, 0, 0, status);
264 if(check_col(pinfo->cinfo, COL_INFO)){
265 col_append_fstr(pinfo->cinfo, COL_INFO, " RecMaster:%d", status);
271 static const value_string recmode_vals[] = {
273 {1,"RECOVERY ACTIVE"},
277 static int dissect_control_get_recmode_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess _U_)
279 proto_tree_add_uint(tree, hf_ctdb_recmode, tvb, 0, 0, status);
281 if(check_col(pinfo->cinfo, COL_INFO)){
282 col_append_fstr(pinfo->cinfo, COL_INFO, " RecMode:%s",
283 val_to_str(status, recmode_vals, "Unknown:%d"));
289 static int dissect_control_get_nodemap_reply(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status _U_, int endianess)
294 proto_tree_add_item(tree, hf_ctdb_num_nodes, tvb, offset, 4, endianess);
296 num_nodes=tvb_get_letohl(tvb, offset);
298 num_nodes=tvb_get_ntohl(tvb, offset);
304 proto_tree_add_item(tree, hf_ctdb_vnn, tvb, offset, 4, endianess);
308 proto_tree_add_item(tree, hf_ctdb_node_flags, tvb, offset, 4, endianess);
311 /* here comes a sockaddr_in but we only store ipv4 addresses in it */
312 proto_tree_add_item(tree, hf_ctdb_node_ip, tvb, offset+4, 4, FALSE);
319 static int dissect_control_process_exist_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status _U_, int endianess)
324 proto_tree_add_item(tree, hf_ctdb_pid, tvb, offset, 4, endianess);
326 pid=tvb_get_letohl(tvb, offset);
328 pid=tvb_get_ntohl(tvb, offset);
332 if(check_col(pinfo->cinfo, COL_INFO)){
333 col_append_fstr(pinfo->cinfo, COL_INFO, " pid:%d", pid);
339 static const true_false_string process_exists_tfs = {
340 "Process does NOT exist",
344 static int dissect_control_process_exist_reply(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess _U_)
346 proto_tree_add_boolean(tree, hf_ctdb_process_exists, tvb, offset, 4, status);
350 /* This defines the array of dissectors for request/reply controls */
351 typedef int (*control_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess);
353 typedef struct _control_dissector_array_t {
355 control_dissector request_dissector;
356 control_dissector reply_dissector;
357 } control_dissector_array_t;
359 static control_dissector_array_t control_dissectors[] = {
360 {CTDB_CONTROL_GET_RECMASTER,
362 dissect_control_get_recmaster_reply},
363 {CTDB_CONTROL_GET_RECMODE,
365 dissect_control_get_recmode_reply},
366 {CTDB_CONTROL_GET_NODEMAP,
368 dissect_control_get_nodemap_reply},
369 {CTDB_CONTROL_FREEZE,
375 {CTDB_CONTROL_PROCESS_EXISTS,
376 dissect_control_process_exist_request,
377 dissect_control_process_exist_reply},
379 /*CTDB_CONTROL_STATISTICS*/
380 /*CTDB_CONTROL_CONFIG*/
381 /*CTDB_CONTROL_PING*/
382 /*CTDB_CONTROL_GETDBPATH*/
383 /*CTDB_CONTROL_GETVNNMAP*/
384 /*CTDB_CONTROL_SETVNNMAP*/
385 /*CTDB_CONTROL_GET_DEBUG*/
386 /*CTDB_CONTROL_SET_DEBUG*/
387 /*CTDB_CONTROL_GET_DBMAP*/
388 /*CTDB_CONTROL_SET_DMASTER*/
389 /*CTDB_CONTROL_CLEAR_DB*/
390 /*CTDB_CONTROL_PULL_DB*/
391 /*CTDB_CONTROL_PUSH_DB*/
392 /*CTDB_CONTROL_SET_RECMODE*/
393 /*CTDB_CONTROL_STATISTICS_RESET*/
394 /*CTDB_CONTROL_DB_ATTACH*/
395 /*CTDB_CONTROL_SET_CALL*/
396 /*CTDB_CONTROL_TRAVERSE_START*/
397 /*CTDB_CONTROL_TRAVERSE_ALL*/
398 /*CTDB_CONTROL_TRAVERSE_DATA*/
399 /*CTDB_CONTROL_REGISTER_SRVID*/
400 /*CTDB_CONTROL_DEREGISTER_SRVID*/
401 /*CTDB_CONTROL_GET_DBNAME*/
402 /*CTDB_CONTROL_ENABLE_SEQNUM*/
403 /*CTDB_CONTROL_UPDATE_SEQNUM*/
404 /*CTDB_CONTROL_SET_SEQNUM_FREQUENCY*/
405 /*CTDB_CONTROL_DUMP_MEMORY*/
406 /*CTDB_CONTROL_GET_PID*/
407 /*CTDB_CONTROL_SET_RECMASTER*/
408 /*CTDB_CONTROL_GET_VNN*/
409 /*CTDB_CONTROL_SHUTDOWN*/
410 /*CTDB_CONTROL_GET_MONMODE*/
411 /*CTDB_CONTROL_SET_MONMODE*/
412 /*CTDB_CONTROL_MAX_RSN*/
413 /*CTDB_CONTROL_SET_RSN_NONEMPTY*/
414 /*CTDB_CONTROL_DELETE_LOW_RSN*/
415 /*CTDB_CONTROL_TAKEOVER_IP*/
416 /*CTDB_CONTROL_RELEASE_IP*/
417 /*CTDB_CONTROL_TCP_CLIENT*/
418 /*CTDB_CONTROL_TCP_ADD*/
419 /*CTDB_CONTROL_TCP_REMOVE*/
420 /*CTDB_CONTROL_STARTUP*/
421 /*CTDB_CONTROL_SET_TUNABLE*/
422 /*CTDB_CONTROL_GET_TUNABLE*/
423 /*CTDB_CONTROL_LIST_TUNABLES*/
424 /*CTDB_CONTROL_GET_PUBLIC_IPS*/
425 /*CTDB_CONTROL_MODIFY_FLAGS*/
426 /*CTDB_CONTROL_GET_ALL_TUNABLES*/
427 /*CTDB_CONTROL_KILL_TCP*/
428 /*CTDB_CONTROL_GET_TCP_TICKLE_LIST*/
429 /*CTDB_CONTROL_SET_TCP_TICKLE_LIST*/
433 static control_dissector find_control_dissector(guint32 opcode, gboolean is_request)
435 control_dissector_array_t *cd=control_dissectors;
438 if((!cd->opcode)&&(!cd->request_dissector)&&(!cd->reply_dissector)){
441 if(opcode==cd->opcode){
443 return cd->request_dissector;
445 return cd->reply_dissector;
453 static const value_string ctdb_dbid_vals[] = {
454 {0x435d3410, "notify.tdb"},
455 {0x42fe72c5, "locking.tdb"},
456 {0x1421fb78, "brlock.tdb"},
457 {0x17055d90, "connections.tdb"},
458 {0xc0bdde6a, "sessionid.tdb"},
463 ctdb_display_trans(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, ctdb_trans_t *ctdb_trans)
467 if(ctdb_trans->request_in!=pinfo->fd->num){
468 item=proto_tree_add_uint(tree, hf_ctdb_request_in, tvb, 0, 0, ctdb_trans->request_in);
469 PROTO_ITEM_SET_GENERATED(item);
472 if( (ctdb_trans->response_in!=0)
473 &&(ctdb_trans->response_in!=pinfo->fd->num) ){
474 item=proto_tree_add_uint(tree, hf_ctdb_response_in, tvb, 0, 0, ctdb_trans->response_in);
475 PROTO_ITEM_SET_GENERATED(item);
478 if(pinfo->fd->num==ctdb_trans->response_in){
481 nstime_delta(&ns, &pinfo->fd->abs_ts, &ctdb_trans->req_time);
482 item=proto_tree_add_time(tree, hf_ctdb_time, tvb, 0, 0, &ns);
483 PROTO_ITEM_SET_GENERATED(item);
488 ctdb_display_control(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, ctdb_control_t *ctdb_control)
492 if(ctdb_control->request_in!=pinfo->fd->num){
493 item=proto_tree_add_uint(tree, hf_ctdb_request_in, tvb, 0, 0, ctdb_control->request_in);
494 PROTO_ITEM_SET_GENERATED(item);
497 if( (ctdb_control->response_in!=0)
498 &&(ctdb_control->response_in!=pinfo->fd->num) ){
499 item=proto_tree_add_uint(tree, hf_ctdb_response_in, tvb, 0, 0, ctdb_control->response_in);
500 PROTO_ITEM_SET_GENERATED(item);
503 if(pinfo->fd->num==ctdb_control->response_in){
506 nstime_delta(&ns, &pinfo->fd->abs_ts, &ctdb_control->req_time);
507 item=proto_tree_add_time(tree, hf_ctdb_time, tvb, 0, 0, &ns);
508 PROTO_ITEM_SET_GENERATED(item);
513 ctdb_hash(tvbuff_t *tvb, int offset, guint32 len)
518 for(value=0x238F13AF*len, i=0; i < len; i++)
519 value=(value+(tvb_get_guint8(tvb, offset+i) << (i*5 % 24)));
521 return (1103515243 * value + 12345);
525 dissect_ctdb_key(proto_tree *tree, tvbuff_t *tvb, int offset, guint32 keylen, guint32 *key_hash, int endianess)
528 proto_item *key_item=NULL;
529 proto_item *key_tree=NULL;
532 key_item=proto_tree_add_item(tree, hf_ctdb_key, tvb, offset, keylen, endianess);
533 key_tree=proto_item_add_subtree(key_item, ett_ctdb_key);
537 keyhash=ctdb_hash(tvb, offset, keylen);
538 proto_item_append_text(key_item, " (Hash:0x%08x)", keyhash);
539 key_item=proto_tree_add_uint(key_tree, hf_ctdb_keyhash, tvb, 0, 0, keyhash);
540 PROTO_ITEM_SET_GENERATED(key_item);
552 dissect_ctdb_reply_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int endianess)
557 proto_tree_add_item(tree, hf_ctdb_status, tvb, offset, 4, endianess);
561 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
563 datalen=tvb_get_letohl(tvb, offset);
565 datalen=tvb_get_ntohl(tvb, offset);
570 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
578 dissect_ctdb_reply_dmaster(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, guint32 dst, int endianess)
580 guint32 datalen, keylen;
581 emem_tree_key_t tkey[3];
582 ctdb_trans_t *ctdb_trans;
585 proto_tree_add_item(tree, hf_ctdb_dbid, tvb, offset, 4, endianess);
590 offset=(offset+7)&0xfffff8; /* fixup alignment*/
591 proto_tree_add_item(tree, hf_ctdb_rsn, tvb, offset, 8, endianess);
595 proto_tree_add_item(tree, hf_ctdb_keylen, tvb, offset, 4, endianess);
597 keylen=tvb_get_letohl(tvb, offset);
599 keylen=tvb_get_ntohl(tvb, offset);
604 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
606 datalen=tvb_get_letohl(tvb, offset);
608 datalen=tvb_get_ntohl(tvb, offset);
613 offset=dissect_ctdb_key(tree, tvb, offset, keylen, NULL, endianess);
616 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
624 ctdb_trans=se_tree_lookup32_array(ctdb_transactions, &tkey[0]);
627 ctdb_trans->response_in=pinfo->fd->num;
628 ctdb_display_trans(pinfo, tree, tvb, ctdb_trans);
635 dissect_ctdb_req_dmaster(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, int endianess)
637 guint32 keylen, datalen, dmaster;
638 emem_tree_key_t tkey[3];
639 ctdb_trans_t *ctdb_trans;
642 proto_tree_add_item(tree, hf_ctdb_dbid, tvb, offset, 4, endianess);
646 offset=(offset+7)&0xfffff8; /* fixup alignment*/
647 proto_tree_add_item(tree, hf_ctdb_rsn, tvb, offset, 8, endianess);
651 proto_tree_add_item(tree, hf_ctdb_dmaster, tvb, offset, 4, endianess);
653 dmaster=tvb_get_letohl(tvb, offset);
655 dmaster=tvb_get_ntohl(tvb, offset);
660 proto_tree_add_item(tree, hf_ctdb_keylen, tvb, offset, 4, endianess);
662 keylen=tvb_get_letohl(tvb, offset);
664 keylen=tvb_get_ntohl(tvb, offset);
669 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
671 datalen=tvb_get_letohl(tvb, offset);
673 datalen=tvb_get_ntohl(tvb, offset);
678 offset=dissect_ctdb_key(tree, tvb, offset, keylen, NULL, endianess);
681 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
688 tkey[1].key=&dmaster;
690 ctdb_trans=se_tree_lookup32_array(ctdb_transactions, &tkey[0]);
693 ctdb_display_trans(pinfo, tree, tvb, ctdb_trans);
702 dissect_ctdb_req_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, guint32 src, guint32 dst, int endianess)
706 ctdb_control_t *ctdb_control;
707 control_dissector cd;
711 proto_tree_add_item(tree, hf_ctdb_ctrl_opcode, tvb, offset, 4, endianess);
713 opcode=tvb_get_letohl(tvb, offset);
715 opcode=tvb_get_ntohl(tvb, offset);
719 if(check_col(pinfo->cinfo, COL_INFO)){
720 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request %d->%d",
721 val_to_str(opcode, ctrl_opcode_vals, "Unknown:%d"),
726 offset=(offset+7)&0xfffff8; /* fixup alignment*/
727 proto_tree_add_item(tree, hf_ctdb_srvid, tvb, offset, 8, endianess);
731 proto_tree_add_item(tree, hf_ctdb_clientid, tvb, offset, 4, endianess);
735 proto_tree_add_item(tree, hf_ctdb_ctrl_flags, tvb, offset, 4, endianess);
739 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
741 datalen=tvb_get_letohl(tvb, offset);
743 datalen=tvb_get_ntohl(tvb, offset);
750 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
754 /* setup request/response matching */
755 if(!pinfo->fd->flags.visited){
756 emem_tree_key_t tkey[4];
758 ctdb_control=se_alloc(sizeof(ctdb_control_t));
759 ctdb_control->opcode=opcode;
760 ctdb_control->request_in=pinfo->fd->num;
761 ctdb_control->response_in=0;
762 ctdb_control->req_time=pinfo->fd->abs_ts;
771 se_tree_insert32_array(ctdb_controls, &tkey[0], ctdb_control);
773 emem_tree_key_t tkey[4];
782 ctdb_control=se_tree_lookup32_array(ctdb_controls, &tkey[0]);
786 cd=find_control_dissector(ctdb_control->opcode, TRUE);
788 cd(pinfo, tree, tvb, data_offset, 0, endianess);
791 ctdb_display_control(pinfo, tree, tvb, ctdb_control);
797 dissect_ctdb_reply_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, guint32 src, guint32 dst, int endianess)
799 ctdb_control_t *ctdb_control;
800 emem_tree_key_t tkey[4];
802 guint32 datalen, errorlen, status;
804 control_dissector cd;
813 ctdb_control=se_tree_lookup32_array(ctdb_controls, &tkey[0]);
819 if(!pinfo->fd->flags.visited){
820 ctdb_control->response_in = pinfo->fd->num;
824 item=proto_tree_add_uint(tree, hf_ctdb_ctrl_opcode, tvb, 0, 0, ctdb_control->opcode);
825 PROTO_ITEM_SET_GENERATED(item);
827 if(check_col(pinfo->cinfo, COL_INFO)){
828 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Reply %d->%d",
829 val_to_str(ctdb_control->opcode, ctrl_opcode_vals, "Unknown:%d"),
835 proto_tree_add_item(tree, hf_ctdb_status, tvb, offset, 4, endianess);
837 status=tvb_get_letohl(tvb, offset);
839 status=tvb_get_ntohl(tvb, offset);
844 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
846 datalen=tvb_get_letohl(tvb, offset);
848 datalen=tvb_get_ntohl(tvb, offset);
853 proto_tree_add_item(tree, hf_ctdb_errorlen, tvb, offset, 4, endianess);
855 errorlen=tvb_get_letohl(tvb, offset);
857 errorlen=tvb_get_ntohl(tvb, offset);
864 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
871 proto_tree_add_item(tree, hf_ctdb_error, tvb, offset, errorlen, endianess);
876 cd=find_control_dissector(ctdb_control->opcode, FALSE);
878 cd(pinfo, tree, tvb, data_offset, status, endianess);
881 ctdb_display_control(pinfo, tree, tvb, ctdb_control);
885 static const true_false_string flags_immediate_tfs={
886 "DMASTER for the record must IMMEDIATELY be migrated to the caller",
887 "Dmaster migration is not required"
891 dissect_ctdb_req_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint32 reqid, guint32 caller, int endianess)
893 guint32 flags, keyhash;
894 guint32 keylen, datalen;
895 ctdb_trans_t *ctdb_trans=NULL;
898 proto_tree_add_item(tree, hf_ctdb_flags_immediate, tvb, offset, 4, endianess);
900 flags=tvb_get_letohl(tvb, offset);
902 flags=tvb_get_ntohl(tvb, offset);
904 if(flags&0x00000001){
905 col_append_str(pinfo->cinfo, COL_INFO, " IMMEDIATE");
910 proto_tree_add_item(tree, hf_ctdb_dbid, tvb, offset, 4, endianess);
914 proto_tree_add_item(tree, hf_ctdb_callid, tvb, offset, 4, endianess);
918 proto_tree_add_item(tree, hf_ctdb_hopcount, tvb, offset, 4, endianess);
922 proto_tree_add_item(tree, hf_ctdb_keylen, tvb, offset, 4, endianess);
924 keylen=tvb_get_letohl(tvb, offset);
926 keylen=tvb_get_ntohl(tvb, offset);
931 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
933 datalen=tvb_get_letohl(tvb, offset);
935 datalen=tvb_get_ntohl(tvb, offset);
940 offset=dissect_ctdb_key(tree, tvb, offset, keylen, &keyhash, endianess);
943 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
946 /* setup request/response matching */
947 if(!pinfo->fd->flags.visited){
948 emem_tree_key_t tkey[3];
950 ctdb_trans=se_alloc(sizeof(ctdb_trans_t));
951 ctdb_trans->key_hash=keyhash;
952 ctdb_trans->request_in=pinfo->fd->num;
953 ctdb_trans->response_in=0;
954 ctdb_trans->req_time=pinfo->fd->abs_ts;
961 se_tree_insert32_array(ctdb_transactions, &tkey[0], ctdb_trans);
963 emem_tree_key_t tkey[3];
970 ctdb_trans=se_tree_lookup32_array(ctdb_transactions, &tkey[0]);
974 ctdb_display_trans(pinfo, tree, tvb, ctdb_trans);
981 dissect_ctdb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
983 proto_tree *tree=NULL;
984 proto_item *item=NULL;
986 guint32 opcode, src, dst, reqid;
989 /* does this look like CTDB? */
990 if(tvb_length_remaining(tvb, offset)<8){
993 switch(tvb_get_letohl(tvb, offset+4)){
1005 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CTDB");
1006 col_clear(pinfo->cinfo, COL_INFO);
1009 item=proto_tree_add_item(parent_tree, proto_ctdb, tvb, offset,
1011 tree=proto_item_add_subtree(item, ett_ctdb);
1016 proto_tree_add_item(tree, hf_ctdb_length, tvb, offset, 4, endianess);
1020 proto_tree_add_item(tree, hf_ctdb_magic, tvb, offset, 4, endianess);
1024 proto_tree_add_item(tree, hf_ctdb_version, tvb, offset, 4, endianess);
1028 proto_tree_add_item(tree, hf_ctdb_generation, tvb, offset, 4, endianess);
1032 proto_tree_add_item(tree, hf_ctdb_opcode, tvb, offset, 4, endianess);
1034 opcode=tvb_get_letohl(tvb, offset);
1036 opcode=tvb_get_ntohl(tvb, offset);
1041 proto_tree_add_item(tree, hf_ctdb_dst, tvb, offset, 4, endianess);
1043 dst=tvb_get_letohl(tvb, offset);
1045 dst=tvb_get_ntohl(tvb, offset);
1050 proto_tree_add_item(tree, hf_ctdb_src, tvb, offset, 4, endianess);
1052 src=tvb_get_letohl(tvb, offset);
1054 src=tvb_get_ntohl(tvb, offset);
1059 proto_tree_add_item(tree, hf_ctdb_id, tvb, offset, 4, endianess);
1061 reqid=tvb_get_letohl(tvb, offset);
1063 reqid=tvb_get_ntohl(tvb, offset);
1067 if(check_col(pinfo->cinfo, COL_INFO)){
1068 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %d->%d",
1069 val_to_str(opcode, ctdb_opcodes, "Unknown:%d"),
1075 offset=dissect_ctdb_req_call(tvb, offset, pinfo, tree, reqid, src, endianess);
1077 case CTDB_REPLY_CALL:
1078 offset=dissect_ctdb_reply_call(tvb, offset, pinfo, tree, endianess);
1080 case CTDB_REPLY_DMASTER:
1081 offset=dissect_ctdb_reply_dmaster(tvb, offset, pinfo, tree, reqid, dst, endianess);
1083 case CTDB_REQ_DMASTER:
1084 offset=dissect_ctdb_req_dmaster(tvb, offset, pinfo, tree, reqid, endianess);
1086 case CTDB_REPLY_ERROR:
1088 case CTDB_REQ_MESSAGE:
1090 case CTDB_REQ_CONTROL:
1091 offset=dissect_ctdb_req_control(tvb, offset, pinfo, tree, reqid, src, dst, endianess);
1093 case CTDB_REPLY_CONTROL:
1094 offset=dissect_ctdb_reply_control(tvb, offset, pinfo, tree, reqid, src, dst, endianess);
1103 * Register the protocol with Wireshark
1106 proto_register_ctdb(void)
1108 static hf_register_info hf[] = {
1109 { &hf_ctdb_length, {
1110 "Length", "ctdb.len", FT_UINT32, BASE_DEC,
1111 NULL, 0x0, "Size of CTDB PDU", HFILL }},
1113 "Destination", "ctdb.dst", FT_UINT32, BASE_DEC,
1114 NULL, 0x0, NULL, HFILL }},
1116 "Source", "ctdb.src", FT_UINT32, BASE_DEC,
1117 NULL, 0x0, NULL, HFILL }},
1119 "Id", "ctdb.id", FT_UINT32, BASE_DEC,
1120 NULL, 0x0, "Transaction ID", HFILL }},
1121 { &hf_ctdb_opcode, {
1122 "Opcode", "ctdb.opcode", FT_UINT32, BASE_DEC,
1123 VALS(ctdb_opcodes), 0x0, "CTDB command opcode", HFILL }},
1124 { &hf_ctdb_flags_immediate, {
1125 "Immediate", "ctdb.immediate", FT_BOOLEAN, 32,
1126 TFS(&flags_immediate_tfs), 0x00000001, "Force migration of DMASTER?", HFILL }},
1128 "DB Id", "ctdb.dbid", FT_UINT32, BASE_HEX,
1129 VALS(ctdb_dbid_vals), 0x0, "Database ID", HFILL }},
1130 { &hf_ctdb_callid, {
1131 "Call Id", "ctdb.callid", FT_UINT32, BASE_DEC,
1132 NULL, 0x0, "Call ID", HFILL }},
1133 { &hf_ctdb_status, {
1134 "Status", "ctdb.status", FT_UINT32, BASE_DEC,
1135 NULL, 0x0, NULL, HFILL }},
1136 { &hf_ctdb_datalen, {
1137 "Data Length", "ctdb.datalen", FT_UINT32, BASE_DEC,
1138 NULL, 0x0, NULL, HFILL }},
1139 { &hf_ctdb_errorlen, {
1140 "Error Length", "ctdb.errorlen", FT_UINT32, BASE_DEC,
1141 NULL, 0x0, NULL, HFILL }},
1142 { &hf_ctdb_keylen, {
1143 "Key Length", "ctdb.keylen", FT_UINT32, BASE_DEC,
1144 NULL, 0x0, NULL, HFILL }},
1146 "Magic", "ctdb.magic", FT_UINT32, BASE_HEX,
1147 NULL, 0x0, NULL, HFILL }},
1148 { &hf_ctdb_version, {
1149 "Version", "ctdb.version", FT_UINT32, BASE_DEC,
1150 NULL, 0x0, NULL, HFILL }},
1151 { &hf_ctdb_dmaster, {
1152 "Dmaster", "ctdb.dmaster", FT_UINT32, BASE_DEC,
1153 NULL, 0x0, NULL, HFILL }},
1154 { &hf_ctdb_generation, {
1155 "Generation", "ctdb.generation", FT_UINT32, BASE_DEC,
1156 NULL, 0x0, NULL, HFILL }},
1158 "Key", "ctdb.key", FT_BYTES, BASE_NONE,
1159 NULL, 0x0, NULL, HFILL }},
1160 { &hf_ctdb_keyhash, {
1161 "KeyHash", "ctdb.keyhash", FT_UINT32, BASE_HEX,
1162 NULL, 0x0, NULL, HFILL }},
1164 "Data", "ctdb.data", FT_BYTES, BASE_NONE,
1165 NULL, 0x0, NULL, HFILL }},
1167 "Error", "ctdb.error", FT_BYTES, BASE_NONE,
1168 NULL, 0x0, NULL, HFILL }},
1169 { &hf_ctdb_request_in, {
1170 "Request In", "ctdb.request_in", FT_FRAMENUM, BASE_NONE,
1171 NULL, 0x0, NULL, HFILL }},
1172 { &hf_ctdb_response_in, {
1173 "Response In", "ctdb.response_in", FT_FRAMENUM, BASE_NONE,
1174 NULL, 0x0, NULL, HFILL }},
1176 "Time since request", "ctdb.time", FT_RELATIVE_TIME, BASE_NONE,
1177 NULL, 0x0, NULL, HFILL }},
1178 { &hf_ctdb_hopcount, {
1179 "Hopcount", "ctdb.hopcount", FT_UINT32, BASE_DEC,
1180 NULL, 0x0, NULL, HFILL }},
1182 "RSN", "ctdb.rsn", FT_UINT64, BASE_HEX,
1183 NULL, 0x0, NULL, HFILL }},
1184 { &hf_ctdb_ctrl_opcode, {
1185 "CTRL Opcode", "ctdb.ctrl_opcode", FT_UINT32, BASE_DEC,
1186 VALS(ctrl_opcode_vals), 0x0, NULL, HFILL }},
1188 "SrvId", "ctdb.srvid", FT_UINT64, BASE_HEX,
1189 NULL, 0x0, NULL, HFILL }},
1190 { &hf_ctdb_clientid, {
1191 "ClientId", "ctdb.clientid", FT_UINT32, BASE_HEX,
1192 NULL, 0x0, NULL, HFILL }},
1193 { &hf_ctdb_ctrl_flags, {
1194 "CTRL Flags", "ctdb.ctrl_flags", FT_UINT32, BASE_HEX,
1195 NULL, 0x0, NULL, HFILL }},
1196 { &hf_ctdb_recmaster, {
1197 "Recovery Master", "ctdb.recmaster", FT_UINT32, BASE_DEC,
1198 NULL, 0x0, NULL, HFILL }},
1199 { &hf_ctdb_recmode, {
1200 "Recovery Mode", "ctdb.recmode", FT_UINT32, BASE_DEC,
1201 VALS(recmode_vals), 0x0, NULL, HFILL }},
1202 { &hf_ctdb_num_nodes, {
1203 "Num Nodes", "ctdb.num_nodes", FT_UINT32, BASE_DEC,
1204 NULL, 0x0, NULL, HFILL }},
1206 "VNN", "ctdb.vnn", FT_UINT32, BASE_DEC,
1207 NULL, 0x0, NULL, HFILL }},
1208 { &hf_ctdb_node_flags, {
1209 "Node Flags", "ctdb.node_flags", FT_UINT32, BASE_HEX,
1210 NULL, 0x0, NULL, HFILL }},
1211 { &hf_ctdb_node_ip, {
1212 "Node IP", "ctdb.node_ip", FT_IPv4, BASE_NONE,
1213 NULL, 0x0, NULL, HFILL }},
1215 "PID", "ctdb.pid", FT_UINT32, BASE_DEC,
1216 NULL, 0x0, NULL, HFILL }},
1217 { &hf_ctdb_process_exists, {
1218 "Process Exists", "ctdb.process_exists", FT_BOOLEAN, 32,
1219 TFS(&process_exists_tfs), 0x01, NULL, HFILL }},
1222 /* Setup protocol subtree array */
1223 static gint *ett[] = {
1228 /* Register the protocol name and description */
1229 proto_ctdb = proto_register_protocol("Cluster TDB", "CTDB", "ctdb");
1231 /* Required function calls to register the header fields and subtrees used */
1232 proto_register_field_array(proto_ctdb, hf, array_length(hf));
1233 proto_register_subtree_array(ett, array_length(ett));
1238 proto_reg_handoff_ctdb(void)
1240 dissector_handle_t ctdb_handle;
1242 ctdb_handle = new_create_dissector_handle(dissect_ctdb, proto_ctdb);
1243 dissector_add_handle("tcp.port", ctdb_handle);
1245 heur_dissector_add("tcp", dissect_ctdb, proto_ctdb);
1247 ctdb_transactions=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "CTDB transactions tree");
1248 ctdb_controls=se_tree_create(EMEM_TREE_TYPE_RED_BLACK, "CTDB controls tree");