HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-ctdb.c
blob5133fdeb8530cb99eebd71d5f5ad2ed089b4734f
1 /* packet-ctdb.c
2 * Routines for CTDB (Cluster TDB) dissection
3 * Copyright 2007, Ronnie Sahlberg
5 * $Id$
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "config.h"
28 #include <glib.h>
30 #include <epan/packet.h>
31 #include <epan/exceptions.h>
32 #include <epan/expert.h>
33 #include <epan/wmem/wmem.h>
35 void proto_register_ctdb(void);
36 void proto_reg_handoff_ctdb(void);
38 /* Initialize the protocol and registered fields */
39 static int proto_ctdb = -1;
40 static int hf_ctdb_length = -1;
41 static int hf_ctdb_opcode = -1;
42 static int hf_ctdb_magic = -1;
43 static int hf_ctdb_version = -1;
44 static int hf_ctdb_dst = -1;
45 static int hf_ctdb_src = -1;
46 static int hf_ctdb_id = -1;
47 static int hf_ctdb_flags_immediate = -1;
48 static int hf_ctdb_dbid = -1;
49 static int hf_ctdb_callid = -1;
50 static int hf_ctdb_status = -1;
51 static int hf_ctdb_keylen = -1;
52 static int hf_ctdb_datalen = -1;
53 static int hf_ctdb_errorlen = -1;
54 static int hf_ctdb_key = -1;
55 static int hf_ctdb_keyhash = -1;
56 static int hf_ctdb_data = -1;
57 static int hf_ctdb_error = -1;
58 static int hf_ctdb_dmaster = -1;
59 static int hf_ctdb_request_in = -1;
60 static int hf_ctdb_response_in = -1;
61 static int hf_ctdb_time = -1;
62 static int hf_ctdb_generation = -1;
63 static int hf_ctdb_hopcount = -1;
64 static int hf_ctdb_rsn = -1;
65 static int hf_ctdb_ctrl_opcode = -1;
66 static int hf_ctdb_srvid = -1;
67 static int hf_ctdb_clientid = -1;
68 static int hf_ctdb_ctrl_flags = -1;
69 static int hf_ctdb_recmaster = -1;
70 static int hf_ctdb_recmode = -1;
71 static int hf_ctdb_num_nodes = -1;
72 static int hf_ctdb_vnn = -1;
73 static int hf_ctdb_node_flags = -1;
74 static int hf_ctdb_node_ip = -1;
75 static int hf_ctdb_pid = -1;
76 static int hf_ctdb_process_exists = -1;
78 /* Initialize the subtree pointers */
79 static gint ett_ctdb = -1;
80 static gint ett_ctdb_key = -1;
82 static expert_field ei_ctdb_too_many_nodes = EI_INIT;
84 /* this tree keeps track of caller/reqid for ctdb transactions */
85 static wmem_tree_t *ctdb_transactions=NULL;
86 typedef struct _ctdb_trans_t {
87 guint32 key_hash;
88 guint32 request_in;
89 guint32 response_in;
90 nstime_t req_time;
91 } ctdb_trans_t;
93 /* this tree keeps track of CONTROL request/responses */
94 static wmem_tree_t *ctdb_controls=NULL;
95 typedef struct _ctdb_control_t {
96 guint32 opcode;
97 guint32 request_in;
98 guint32 response_in;
99 nstime_t req_time;
100 } 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"},
121 {0,NULL}
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"},
255 {0, NULL}
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 col_append_fstr(pinfo->cinfo, COL_INFO, " RecMaster:%d", status);
266 return offset;
269 static const value_string recmode_vals[] = {
270 {0,"NORMAL"},
271 {1,"RECOVERY ACTIVE"},
272 {0,NULL}
275 static int dissect_control_get_recmode_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess _U_)
277 proto_tree_add_uint(tree, hf_ctdb_recmode, tvb, 0, 0, status);
279 col_append_fstr(pinfo->cinfo, COL_INFO, " RecMode:%s",
280 val_to_str(status, recmode_vals, "Unknown:%d"));
282 return offset;
285 #define CTDB_MAX_NODES 500 /* Arbitrary. */
286 static int dissect_control_get_nodemap_reply(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status _U_, int endianess)
288 guint32 num_nodes;
289 proto_item *item;
291 /* num nodes */
292 item = proto_tree_add_item(tree, hf_ctdb_num_nodes, tvb, offset, 4, endianess);
293 if(endianess){
294 num_nodes=tvb_get_letohl(tvb, offset);
295 } else {
296 num_nodes=tvb_get_ntohl(tvb, offset);
298 offset+=4;
300 if (num_nodes > CTDB_MAX_NODES) {
301 expert_add_info_format(pinfo, item, &ei_ctdb_too_many_nodes, "Too many nodes (%u). Stopping dissection.", num_nodes);
302 THROW(ReportedBoundsError);
305 while(num_nodes--){
306 /* vnn */
307 proto_tree_add_item(tree, hf_ctdb_vnn, tvb, offset, 4, endianess);
308 offset+=4;
310 /* node flags */
311 proto_tree_add_item(tree, hf_ctdb_node_flags, tvb, offset, 4, endianess);
312 offset+=4;
314 /* here comes a sockaddr_in but we only store ipv4 addresses in it */
315 proto_tree_add_item(tree, hf_ctdb_node_ip, tvb, offset+4, 4, ENC_BIG_ENDIAN);
316 offset+=16;
319 return offset;
322 static int dissect_control_process_exist_request(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status _U_, int endianess)
324 guint32 pid;
326 /* pid */
327 proto_tree_add_item(tree, hf_ctdb_pid, tvb, offset, 4, endianess);
328 if(endianess){
329 pid=tvb_get_letohl(tvb, offset);
330 } else {
331 pid=tvb_get_ntohl(tvb, offset);
333 offset+=4;
335 col_append_fstr(pinfo->cinfo, COL_INFO, " pid:%d", pid);
337 return offset;
340 static const true_false_string process_exists_tfs = {
341 "Process does NOT exist",
342 "Process Exists"
345 static int dissect_control_process_exist_reply(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess _U_)
347 proto_tree_add_boolean(tree, hf_ctdb_process_exists, tvb, offset, 4, status);
348 return offset;
351 /* This defines the array of dissectors for request/reply controls */
352 typedef int (*control_dissector)(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, guint32 status, int endianess);
354 typedef struct _control_dissector_array_t {
355 guint32 opcode;
356 control_dissector request_dissector;
357 control_dissector reply_dissector;
358 } control_dissector_array_t;
360 static control_dissector_array_t control_dissectors[] = {
361 {CTDB_CONTROL_GET_RECMASTER,
362 NULL,
363 dissect_control_get_recmaster_reply},
364 {CTDB_CONTROL_GET_RECMODE,
365 NULL,
366 dissect_control_get_recmode_reply},
367 {CTDB_CONTROL_GET_NODEMAP,
368 NULL,
369 dissect_control_get_nodemap_reply},
370 {CTDB_CONTROL_FREEZE,
371 NULL,
372 NULL},
373 {CTDB_CONTROL_THAW,
374 NULL,
375 NULL},
376 {CTDB_CONTROL_PROCESS_EXISTS,
377 dissect_control_process_exist_request,
378 dissect_control_process_exist_reply},
380 /*CTDB_CONTROL_STATISTICS*/
381 /*CTDB_CONTROL_CONFIG*/
382 /*CTDB_CONTROL_PING*/
383 /*CTDB_CONTROL_GETDBPATH*/
384 /*CTDB_CONTROL_GETVNNMAP*/
385 /*CTDB_CONTROL_SETVNNMAP*/
386 /*CTDB_CONTROL_GET_DEBUG*/
387 /*CTDB_CONTROL_SET_DEBUG*/
388 /*CTDB_CONTROL_GET_DBMAP*/
389 /*CTDB_CONTROL_SET_DMASTER*/
390 /*CTDB_CONTROL_CLEAR_DB*/
391 /*CTDB_CONTROL_PULL_DB*/
392 /*CTDB_CONTROL_PUSH_DB*/
393 /*CTDB_CONTROL_SET_RECMODE*/
394 /*CTDB_CONTROL_STATISTICS_RESET*/
395 /*CTDB_CONTROL_DB_ATTACH*/
396 /*CTDB_CONTROL_SET_CALL*/
397 /*CTDB_CONTROL_TRAVERSE_START*/
398 /*CTDB_CONTROL_TRAVERSE_ALL*/
399 /*CTDB_CONTROL_TRAVERSE_DATA*/
400 /*CTDB_CONTROL_REGISTER_SRVID*/
401 /*CTDB_CONTROL_DEREGISTER_SRVID*/
402 /*CTDB_CONTROL_GET_DBNAME*/
403 /*CTDB_CONTROL_ENABLE_SEQNUM*/
404 /*CTDB_CONTROL_UPDATE_SEQNUM*/
405 /*CTDB_CONTROL_SET_SEQNUM_FREQUENCY*/
406 /*CTDB_CONTROL_DUMP_MEMORY*/
407 /*CTDB_CONTROL_GET_PID*/
408 /*CTDB_CONTROL_SET_RECMASTER*/
409 /*CTDB_CONTROL_GET_VNN*/
410 /*CTDB_CONTROL_SHUTDOWN*/
411 /*CTDB_CONTROL_GET_MONMODE*/
412 /*CTDB_CONTROL_SET_MONMODE*/
413 /*CTDB_CONTROL_MAX_RSN*/
414 /*CTDB_CONTROL_SET_RSN_NONEMPTY*/
415 /*CTDB_CONTROL_DELETE_LOW_RSN*/
416 /*CTDB_CONTROL_TAKEOVER_IP*/
417 /*CTDB_CONTROL_RELEASE_IP*/
418 /*CTDB_CONTROL_TCP_CLIENT*/
419 /*CTDB_CONTROL_TCP_ADD*/
420 /*CTDB_CONTROL_TCP_REMOVE*/
421 /*CTDB_CONTROL_STARTUP*/
422 /*CTDB_CONTROL_SET_TUNABLE*/
423 /*CTDB_CONTROL_GET_TUNABLE*/
424 /*CTDB_CONTROL_LIST_TUNABLES*/
425 /*CTDB_CONTROL_GET_PUBLIC_IPS*/
426 /*CTDB_CONTROL_MODIFY_FLAGS*/
427 /*CTDB_CONTROL_GET_ALL_TUNABLES*/
428 /*CTDB_CONTROL_KILL_TCP*/
429 /*CTDB_CONTROL_GET_TCP_TICKLE_LIST*/
430 /*CTDB_CONTROL_SET_TCP_TICKLE_LIST*/
431 {0, NULL, NULL}
434 static control_dissector find_control_dissector(guint32 opcode, gboolean is_request)
436 control_dissector_array_t *cd=control_dissectors;
438 while(cd){
439 if((!cd->opcode)&&(!cd->request_dissector)&&(!cd->reply_dissector)){
440 break;
442 if(opcode==cd->opcode){
443 if(is_request){
444 return cd->request_dissector;
445 } else {
446 return cd->reply_dissector;
449 cd++;
451 return NULL;
454 static const value_string ctdb_dbid_vals[] = {
455 {0x435d3410, "notify.tdb"},
456 {0x42fe72c5, "locking.tdb"},
457 {0x1421fb78, "brlock.tdb"},
458 {0x17055d90, "connections.tdb"},
459 {0xc0bdde6a, "sessionid.tdb"},
460 {0, NULL}
463 static void
464 ctdb_display_trans(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, ctdb_trans_t *ctdb_trans)
466 proto_item *item;
468 if(ctdb_trans->request_in!=pinfo->fd->num){
469 item=proto_tree_add_uint(tree, hf_ctdb_request_in, tvb, 0, 0, ctdb_trans->request_in);
470 PROTO_ITEM_SET_GENERATED(item);
473 if( (ctdb_trans->response_in!=0)
474 &&(ctdb_trans->response_in!=pinfo->fd->num) ){
475 item=proto_tree_add_uint(tree, hf_ctdb_response_in, tvb, 0, 0, ctdb_trans->response_in);
476 PROTO_ITEM_SET_GENERATED(item);
479 if(pinfo->fd->num==ctdb_trans->response_in){
480 nstime_t ns;
482 nstime_delta(&ns, &pinfo->fd->abs_ts, &ctdb_trans->req_time);
483 item=proto_tree_add_time(tree, hf_ctdb_time, tvb, 0, 0, &ns);
484 PROTO_ITEM_SET_GENERATED(item);
488 static void
489 ctdb_display_control(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, ctdb_control_t *ctdb_control)
491 proto_item *item;
493 if(ctdb_control->request_in!=pinfo->fd->num){
494 item=proto_tree_add_uint(tree, hf_ctdb_request_in, tvb, 0, 0, ctdb_control->request_in);
495 PROTO_ITEM_SET_GENERATED(item);
498 if( (ctdb_control->response_in!=0)
499 &&(ctdb_control->response_in!=pinfo->fd->num) ){
500 item=proto_tree_add_uint(tree, hf_ctdb_response_in, tvb, 0, 0, ctdb_control->response_in);
501 PROTO_ITEM_SET_GENERATED(item);
504 if(pinfo->fd->num==ctdb_control->response_in){
505 nstime_t ns;
507 nstime_delta(&ns, &pinfo->fd->abs_ts, &ctdb_control->req_time);
508 item=proto_tree_add_time(tree, hf_ctdb_time, tvb, 0, 0, &ns);
509 PROTO_ITEM_SET_GENERATED(item);
513 static guint32
514 ctdb_hash(tvbuff_t *tvb, int offset, guint32 len)
516 guint32 value;
517 guint32 i;
519 for(value=0x238F13AF*len, i=0; i < len; i++)
520 value=(value+(tvb_get_guint8(tvb, offset+i) << (i*5 % 24)));
522 return (1103515243 * value + 12345);
525 static int
526 dissect_ctdb_key(proto_tree *tree, tvbuff_t *tvb, int offset, guint32 keylen, guint32 *key_hash, int endianess)
528 guint32 keyhash;
529 proto_item *key_item=NULL;
530 proto_item *key_tree=NULL;
532 if(tree){
533 key_item=proto_tree_add_item(tree, hf_ctdb_key, tvb, offset, keylen, endianess);
534 key_tree=proto_item_add_subtree(key_item, ett_ctdb_key);
538 keyhash=ctdb_hash(tvb, offset, keylen);
539 proto_item_append_text(key_item, " (Hash:0x%08x)", keyhash);
540 key_item=proto_tree_add_uint(key_tree, hf_ctdb_keyhash, tvb, 0, 0, keyhash);
541 PROTO_ITEM_SET_GENERATED(key_item);
543 offset+=keylen;
545 if(key_hash){
546 *key_hash=keyhash;
549 return offset;
552 static int
553 dissect_ctdb_reply_call(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, int endianess)
555 guint32 datalen;
557 /* status */
558 proto_tree_add_item(tree, hf_ctdb_status, tvb, offset, 4, endianess);
559 offset+=4;
561 /* datalen */
562 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
563 if(endianess){
564 datalen=tvb_get_letohl(tvb, offset);
565 } else {
566 datalen=tvb_get_ntohl(tvb, offset);
568 offset+=4;
570 /* data */
571 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
572 offset+=datalen;
575 return offset;
578 static int
579 dissect_ctdb_reply_dmaster(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, guint32 dst, int endianess)
581 guint32 datalen, keylen;
582 wmem_tree_key_t tkey[3];
583 ctdb_trans_t *ctdb_trans;
585 /* dbid */
586 proto_tree_add_item(tree, hf_ctdb_dbid, tvb, offset, 4, endianess);
587 offset+=4;
590 /* rsn */
591 offset=(offset+7)&0xfffff8; /* fixup alignment*/
592 proto_tree_add_item(tree, hf_ctdb_rsn, tvb, offset, 8, endianess);
593 offset+=8;
595 /* keylen */
596 proto_tree_add_item(tree, hf_ctdb_keylen, tvb, offset, 4, endianess);
597 if(endianess){
598 keylen=tvb_get_letohl(tvb, offset);
599 } else {
600 keylen=tvb_get_ntohl(tvb, offset);
602 offset+=4;
604 /* datalen */
605 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
606 if(endianess){
607 datalen=tvb_get_letohl(tvb, offset);
608 } else {
609 datalen=tvb_get_ntohl(tvb, offset);
611 offset+=4;
613 /* key */
614 offset=dissect_ctdb_key(tree, tvb, offset, keylen, NULL, endianess);
616 /* data */
617 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
618 offset+=datalen;
620 tkey[0].length=1;
621 tkey[0].key=&reqid;
622 tkey[1].length=1;
623 tkey[1].key=&dst;
624 tkey[2].length=0;
625 ctdb_trans=(ctdb_trans_t *)wmem_tree_lookup32_array(ctdb_transactions, &tkey[0]);
627 if(ctdb_trans){
628 ctdb_trans->response_in=pinfo->fd->num;
629 ctdb_display_trans(pinfo, tree, tvb, ctdb_trans);
632 return offset;
635 static int
636 dissect_ctdb_req_dmaster(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, int endianess)
638 guint32 keylen, datalen, dmaster;
639 wmem_tree_key_t tkey[3];
640 ctdb_trans_t *ctdb_trans;
642 /* dbid */
643 proto_tree_add_item(tree, hf_ctdb_dbid, tvb, offset, 4, endianess);
644 offset+=4;
646 /* rsn */
647 offset=(offset+7)&0xfffff8; /* fixup alignment*/
648 proto_tree_add_item(tree, hf_ctdb_rsn, tvb, offset, 8, endianess);
649 offset+=8;
651 /* dmaster */
652 proto_tree_add_item(tree, hf_ctdb_dmaster, tvb, offset, 4, endianess);
653 if(endianess){
654 dmaster=tvb_get_letohl(tvb, offset);
655 } else {
656 dmaster=tvb_get_ntohl(tvb, offset);
658 offset += 4;
660 /* keylen */
661 proto_tree_add_item(tree, hf_ctdb_keylen, tvb, offset, 4, endianess);
662 if(endianess){
663 keylen=tvb_get_letohl(tvb, offset);
664 } else {
665 keylen=tvb_get_ntohl(tvb, offset);
667 offset+=4;
669 /* datalen */
670 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
671 if(endianess){
672 datalen=tvb_get_letohl(tvb, offset);
673 } else {
674 datalen=tvb_get_ntohl(tvb, offset);
676 offset+=4;
678 /* key */
679 offset=dissect_ctdb_key(tree, tvb, offset, keylen, NULL, endianess);
681 /* data */
682 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
683 offset+=datalen;
686 tkey[0].length=1;
687 tkey[0].key=&reqid;
688 tkey[1].length=1;
689 tkey[1].key=&dmaster;
690 tkey[2].length=0;
691 ctdb_trans=(ctdb_trans_t *)wmem_tree_lookup32_array(ctdb_transactions, &tkey[0]);
693 if(ctdb_trans){
694 ctdb_display_trans(pinfo, tree, tvb, ctdb_trans);
697 return offset;
702 static int
703 dissect_ctdb_req_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, guint32 src, guint32 dst, int endianess)
705 guint32 datalen;
706 guint32 opcode;
707 ctdb_control_t *ctdb_control;
708 control_dissector cd;
709 int data_offset;
711 /* ctrl opcode */
712 proto_tree_add_item(tree, hf_ctdb_ctrl_opcode, tvb, offset, 4, endianess);
713 if(endianess){
714 opcode=tvb_get_letohl(tvb, offset);
715 } else {
716 opcode=tvb_get_ntohl(tvb, offset);
718 offset+=4;
720 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Request %d->%d",
721 val_to_str(opcode, ctrl_opcode_vals, "Unknown:%d"),
722 src, dst);
724 /* srvid */
725 offset=(offset+7)&0xfffff8; /* fixup alignment*/
726 proto_tree_add_item(tree, hf_ctdb_srvid, tvb, offset, 8, endianess);
727 offset+=8;
729 /* client id */
730 proto_tree_add_item(tree, hf_ctdb_clientid, tvb, offset, 4, endianess);
731 offset+=4;
733 /* ctrl flags */
734 proto_tree_add_item(tree, hf_ctdb_ctrl_flags, tvb, offset, 4, endianess);
735 offset+=4;
737 /* datalen */
738 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
739 if(endianess){
740 datalen=tvb_get_letohl(tvb, offset);
741 } else {
742 datalen=tvb_get_ntohl(tvb, offset);
744 offset+=4;
746 /* data */
747 data_offset=offset;
748 if (datalen) {
749 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
750 offset+=datalen;
753 /* setup request/response matching */
754 if(!pinfo->fd->flags.visited){
755 wmem_tree_key_t tkey[4];
757 ctdb_control=wmem_new(wmem_file_scope(), ctdb_control_t);
758 ctdb_control->opcode=opcode;
759 ctdb_control->request_in=pinfo->fd->num;
760 ctdb_control->response_in=0;
761 ctdb_control->req_time=pinfo->fd->abs_ts;
762 tkey[0].length=1;
763 tkey[0].key=&reqid;
764 tkey[1].length=1;
765 tkey[1].key=&src;
766 tkey[2].length=1;
767 tkey[2].key=&dst;
768 tkey[3].length=0;
770 wmem_tree_insert32_array(ctdb_controls, &tkey[0], ctdb_control);
771 } else {
772 wmem_tree_key_t tkey[4];
774 tkey[0].length=1;
775 tkey[0].key=&reqid;
776 tkey[1].length=1;
777 tkey[1].key=&src;
778 tkey[2].length=1;
779 tkey[2].key=&dst;
780 tkey[3].length=0;
781 ctdb_control=(ctdb_control_t *)wmem_tree_lookup32_array(ctdb_controls, &tkey[0]);
785 cd=find_control_dissector(ctdb_control->opcode, TRUE);
786 if (cd) {
787 cd(pinfo, tree, tvb, data_offset, 0, endianess);
790 ctdb_display_control(pinfo, tree, tvb, ctdb_control);
792 return offset;
795 static int
796 dissect_ctdb_reply_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, guint32 reqid, guint32 src, guint32 dst, int endianess)
798 ctdb_control_t *ctdb_control;
799 wmem_tree_key_t tkey[4];
800 proto_item *item;
801 guint32 datalen, errorlen, status;
802 int data_offset;
803 control_dissector cd;
805 tkey[0].length=1;
806 tkey[0].key=&reqid;
807 tkey[1].length=1;
808 tkey[1].key=&dst;
809 tkey[2].length=1;
810 tkey[2].key=&src;
811 tkey[3].length=0;
812 ctdb_control=(ctdb_control_t *)wmem_tree_lookup32_array(ctdb_controls, &tkey[0]);
814 if(!ctdb_control){
815 return offset;
818 if(!pinfo->fd->flags.visited){
819 ctdb_control->response_in = pinfo->fd->num;
822 /* ctrl opcode */
823 item=proto_tree_add_uint(tree, hf_ctdb_ctrl_opcode, tvb, 0, 0, ctdb_control->opcode);
824 PROTO_ITEM_SET_GENERATED(item);
826 col_add_fstr(pinfo->cinfo, COL_INFO, "%s Reply %d->%d",
827 val_to_str(ctdb_control->opcode, ctrl_opcode_vals, "Unknown:%d"),
828 src, dst);
831 /* status */
832 proto_tree_add_item(tree, hf_ctdb_status, tvb, offset, 4, endianess);
833 if(endianess){
834 status=tvb_get_letohl(tvb, offset);
835 } else {
836 status=tvb_get_ntohl(tvb, offset);
838 offset+=4;
840 /* datalen */
841 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
842 if(endianess){
843 datalen=tvb_get_letohl(tvb, offset);
844 } else {
845 datalen=tvb_get_ntohl(tvb, offset);
847 offset+=4;
849 /* errorlen */
850 proto_tree_add_item(tree, hf_ctdb_errorlen, tvb, offset, 4, endianess);
851 if(endianess){
852 errorlen=tvb_get_letohl(tvb, offset);
853 } else {
854 errorlen=tvb_get_ntohl(tvb, offset);
856 offset+=4;
858 /* data */
859 data_offset=offset;
860 if (datalen) {
861 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
862 offset+=datalen;
866 /* error */
867 if (errorlen) {
868 proto_tree_add_item(tree, hf_ctdb_error, tvb, offset, errorlen, endianess);
869 offset+=datalen;
873 cd=find_control_dissector(ctdb_control->opcode, FALSE);
874 if (cd) {
875 cd(pinfo, tree, tvb, data_offset, status, endianess);
878 ctdb_display_control(pinfo, tree, tvb, ctdb_control);
879 return offset;
882 static const true_false_string flags_immediate_tfs={
883 "DMASTER for the record must IMMEDIATELY be migrated to the caller",
884 "Dmaster migration is not required"
887 static int
888 dissect_ctdb_req_call(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint32 reqid, guint32 caller, int endianess)
890 guint32 flags, keyhash;
891 guint32 keylen, datalen;
892 ctdb_trans_t *ctdb_trans=NULL;
894 /* flags */
895 proto_tree_add_item(tree, hf_ctdb_flags_immediate, tvb, offset, 4, endianess);
896 if(endianess){
897 flags=tvb_get_letohl(tvb, offset);
898 } else {
899 flags=tvb_get_ntohl(tvb, offset);
901 if(flags&0x00000001){
902 col_append_str(pinfo->cinfo, COL_INFO, " IMMEDIATE");
904 offset+=4;
906 /* dbid */
907 proto_tree_add_item(tree, hf_ctdb_dbid, tvb, offset, 4, endianess);
908 offset+=4;
910 /* callid */
911 proto_tree_add_item(tree, hf_ctdb_callid, tvb, offset, 4, endianess);
912 offset+=4;
914 /* hopcount */
915 proto_tree_add_item(tree, hf_ctdb_hopcount, tvb, offset, 4, endianess);
916 offset+=4;
918 /* keylen */
919 proto_tree_add_item(tree, hf_ctdb_keylen, tvb, offset, 4, endianess);
920 if(endianess){
921 keylen=tvb_get_letohl(tvb, offset);
922 } else {
923 keylen=tvb_get_ntohl(tvb, offset);
925 offset+=4;
927 /* datalen */
928 proto_tree_add_item(tree, hf_ctdb_datalen, tvb, offset, 4, endianess);
929 if(endianess){
930 datalen=tvb_get_letohl(tvb, offset);
931 } else {
932 datalen=tvb_get_ntohl(tvb, offset);
934 offset+=4;
936 /* key */
937 offset=dissect_ctdb_key(tree, tvb, offset, keylen, &keyhash, endianess);
939 /* data */
940 proto_tree_add_item(tree, hf_ctdb_data, tvb, offset, datalen, endianess);
941 offset+=datalen;
943 /* setup request/response matching */
944 if(!pinfo->fd->flags.visited){
945 wmem_tree_key_t tkey[3];
947 ctdb_trans=wmem_new(wmem_file_scope(), ctdb_trans_t);
948 ctdb_trans->key_hash=keyhash;
949 ctdb_trans->request_in=pinfo->fd->num;
950 ctdb_trans->response_in=0;
951 ctdb_trans->req_time=pinfo->fd->abs_ts;
952 tkey[0].length=1;
953 tkey[0].key=&reqid;
954 tkey[1].length=1;
955 tkey[1].key=&caller;
956 tkey[2].length=0;
958 wmem_tree_insert32_array(ctdb_transactions, &tkey[0], ctdb_trans);
959 } else {
960 wmem_tree_key_t tkey[3];
962 tkey[0].length=1;
963 tkey[0].key=&reqid;
964 tkey[1].length=1;
965 tkey[1].key=&caller;
966 tkey[2].length=0;
967 ctdb_trans=(ctdb_trans_t *)wmem_tree_lookup32_array(ctdb_transactions, &tkey[0]);
970 if(ctdb_trans){
971 ctdb_display_trans(pinfo, tree, tvb, ctdb_trans);
974 return offset;
977 static gboolean
978 dissect_ctdb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
980 proto_tree *tree=NULL;
981 proto_item *item=NULL;
982 int offset=0;
983 guint32 opcode, src, dst, reqid;
984 int endianess;
986 /* does this look like CTDB? */
987 if(tvb_length_remaining(tvb, offset)<8){
988 return FALSE;
990 switch(tvb_get_letohl(tvb, offset+4)){
991 case 0x42445443:
992 endianess=FALSE;
993 break;
994 case 0x43544442:
995 endianess=TRUE;
996 break;
997 default:
998 return FALSE;
1002 col_set_str(pinfo->cinfo, COL_PROTOCOL, "CTDB");
1003 col_clear(pinfo->cinfo, COL_INFO);
1005 if(parent_tree){
1006 item=proto_tree_add_item(parent_tree, proto_ctdb, tvb, offset,
1007 -1, endianess);
1008 tree=proto_item_add_subtree(item, ett_ctdb);
1011 /* header*/
1012 /* length */
1013 proto_tree_add_item(tree, hf_ctdb_length, tvb, offset, 4, endianess);
1014 offset+=4;
1016 /* magic */
1017 proto_tree_add_item(tree, hf_ctdb_magic, tvb, offset, 4, endianess);
1018 offset+=4;
1020 /* version */
1021 proto_tree_add_item(tree, hf_ctdb_version, tvb, offset, 4, endianess);
1022 offset+=4;
1024 /* generation */
1025 proto_tree_add_item(tree, hf_ctdb_generation, tvb, offset, 4, endianess);
1026 offset+=4;
1028 /* opcode */
1029 proto_tree_add_item(tree, hf_ctdb_opcode, tvb, offset, 4, endianess);
1030 if(endianess){
1031 opcode=tvb_get_letohl(tvb, offset);
1032 } else {
1033 opcode=tvb_get_ntohl(tvb, offset);
1035 offset+=4;
1037 /* dst */
1038 proto_tree_add_item(tree, hf_ctdb_dst, tvb, offset, 4, endianess);
1039 if(endianess){
1040 dst=tvb_get_letohl(tvb, offset);
1041 } else {
1042 dst=tvb_get_ntohl(tvb, offset);
1044 offset+=4;
1046 /* src */
1047 proto_tree_add_item(tree, hf_ctdb_src, tvb, offset, 4, endianess);
1048 if(endianess){
1049 src=tvb_get_letohl(tvb, offset);
1050 } else {
1051 src=tvb_get_ntohl(tvb, offset);
1053 offset+=4;
1055 /* id */
1056 proto_tree_add_item(tree, hf_ctdb_id, tvb, offset, 4, endianess);
1057 if(endianess){
1058 reqid=tvb_get_letohl(tvb, offset);
1059 } else {
1060 reqid=tvb_get_ntohl(tvb, offset);
1062 offset+=4;
1064 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %d->%d",
1065 val_to_str(opcode, ctdb_opcodes, "Unknown:%d"),
1066 src, dst);
1068 switch(opcode){
1069 case CTDB_REQ_CALL:
1070 dissect_ctdb_req_call(tvb, offset, pinfo, tree, reqid, src, endianess);
1071 break;
1072 case CTDB_REPLY_CALL:
1073 dissect_ctdb_reply_call(tvb, offset, pinfo, tree, endianess);
1074 break;
1075 case CTDB_REPLY_DMASTER:
1076 dissect_ctdb_reply_dmaster(tvb, offset, pinfo, tree, reqid, dst, endianess);
1077 break;
1078 case CTDB_REQ_DMASTER:
1079 dissect_ctdb_req_dmaster(tvb, offset, pinfo, tree, reqid, endianess);
1080 break;
1081 case CTDB_REPLY_ERROR:
1082 break;
1083 case CTDB_REQ_MESSAGE:
1084 break;
1085 case CTDB_REQ_CONTROL:
1086 dissect_ctdb_req_control(tvb, offset, pinfo, tree, reqid, src, dst, endianess);
1087 break;
1088 case CTDB_REPLY_CONTROL:
1089 dissect_ctdb_reply_control(tvb, offset, pinfo, tree, reqid, src, dst, endianess);
1090 break;
1093 return TRUE;
1098 * Register the protocol with Wireshark
1100 void
1101 proto_register_ctdb(void)
1103 static hf_register_info hf[] = {
1104 { &hf_ctdb_length, {
1105 "Length", "ctdb.len", FT_UINT32, BASE_DEC,
1106 NULL, 0x0, "Size of CTDB PDU", HFILL }},
1107 { &hf_ctdb_dst, {
1108 "Destination", "ctdb.dst", FT_UINT32, BASE_DEC,
1109 NULL, 0x0, NULL, HFILL }},
1110 { &hf_ctdb_src, {
1111 "Source", "ctdb.src", FT_UINT32, BASE_DEC,
1112 NULL, 0x0, NULL, HFILL }},
1113 { &hf_ctdb_id, {
1114 "Id", "ctdb.id", FT_UINT32, BASE_DEC,
1115 NULL, 0x0, "Transaction ID", HFILL }},
1116 { &hf_ctdb_opcode, {
1117 "Opcode", "ctdb.opcode", FT_UINT32, BASE_DEC,
1118 VALS(ctdb_opcodes), 0x0, "CTDB command opcode", HFILL }},
1119 { &hf_ctdb_flags_immediate, {
1120 "Immediate", "ctdb.immediate", FT_BOOLEAN, 32,
1121 TFS(&flags_immediate_tfs), 0x00000001, "Force migration of DMASTER?", HFILL }},
1122 { &hf_ctdb_dbid, {
1123 "DB Id", "ctdb.dbid", FT_UINT32, BASE_HEX,
1124 VALS(ctdb_dbid_vals), 0x0, "Database ID", HFILL }},
1125 { &hf_ctdb_callid, {
1126 "Call Id", "ctdb.callid", FT_UINT32, BASE_DEC,
1127 NULL, 0x0, NULL, HFILL }},
1128 { &hf_ctdb_status, {
1129 "Status", "ctdb.status", FT_UINT32, BASE_DEC,
1130 NULL, 0x0, NULL, HFILL }},
1131 { &hf_ctdb_datalen, {
1132 "Data Length", "ctdb.datalen", FT_UINT32, BASE_DEC,
1133 NULL, 0x0, NULL, HFILL }},
1134 { &hf_ctdb_errorlen, {
1135 "Error Length", "ctdb.errorlen", FT_UINT32, BASE_DEC,
1136 NULL, 0x0, NULL, HFILL }},
1137 { &hf_ctdb_keylen, {
1138 "Key Length", "ctdb.keylen", FT_UINT32, BASE_DEC,
1139 NULL, 0x0, NULL, HFILL }},
1140 { &hf_ctdb_magic, {
1141 "Magic", "ctdb.magic", FT_UINT32, BASE_HEX,
1142 NULL, 0x0, NULL, HFILL }},
1143 { &hf_ctdb_version, {
1144 "Version", "ctdb.version", FT_UINT32, BASE_DEC,
1145 NULL, 0x0, NULL, HFILL }},
1146 { &hf_ctdb_dmaster, {
1147 "Dmaster", "ctdb.dmaster", FT_UINT32, BASE_DEC,
1148 NULL, 0x0, NULL, HFILL }},
1149 { &hf_ctdb_generation, {
1150 "Generation", "ctdb.generation", FT_UINT32, BASE_DEC,
1151 NULL, 0x0, NULL, HFILL }},
1152 { &hf_ctdb_key, {
1153 "Key", "ctdb.key", FT_BYTES, BASE_NONE,
1154 NULL, 0x0, NULL, HFILL }},
1155 { &hf_ctdb_keyhash, {
1156 "KeyHash", "ctdb.keyhash", FT_UINT32, BASE_HEX,
1157 NULL, 0x0, NULL, HFILL }},
1158 { &hf_ctdb_data, {
1159 "Data", "ctdb.data", FT_BYTES, BASE_NONE,
1160 NULL, 0x0, NULL, HFILL }},
1161 { &hf_ctdb_error, {
1162 "Error", "ctdb.error", FT_BYTES, BASE_NONE,
1163 NULL, 0x0, NULL, HFILL }},
1164 { &hf_ctdb_request_in, {
1165 "Request In", "ctdb.request_in", FT_FRAMENUM, BASE_NONE,
1166 NULL, 0x0, NULL, HFILL }},
1167 { &hf_ctdb_response_in, {
1168 "Response In", "ctdb.response_in", FT_FRAMENUM, BASE_NONE,
1169 NULL, 0x0, NULL, HFILL }},
1170 { &hf_ctdb_time, {
1171 "Time since request", "ctdb.time", FT_RELATIVE_TIME, BASE_NONE,
1172 NULL, 0x0, NULL, HFILL }},
1173 { &hf_ctdb_hopcount, {
1174 "Hopcount", "ctdb.hopcount", FT_UINT32, BASE_DEC,
1175 NULL, 0x0, NULL, HFILL }},
1176 { &hf_ctdb_rsn, {
1177 "RSN", "ctdb.rsn", FT_UINT64, BASE_HEX,
1178 NULL, 0x0, NULL, HFILL }},
1179 { &hf_ctdb_ctrl_opcode, {
1180 "CTRL Opcode", "ctdb.ctrl_opcode", FT_UINT32, BASE_DEC,
1181 VALS(ctrl_opcode_vals), 0x0, NULL, HFILL }},
1182 { &hf_ctdb_srvid, {
1183 "SrvId", "ctdb.srvid", FT_UINT64, BASE_HEX,
1184 NULL, 0x0, NULL, HFILL }},
1185 { &hf_ctdb_clientid, {
1186 "ClientId", "ctdb.clientid", FT_UINT32, BASE_HEX,
1187 NULL, 0x0, NULL, HFILL }},
1188 { &hf_ctdb_ctrl_flags, {
1189 "CTRL Flags", "ctdb.ctrl_flags", FT_UINT32, BASE_HEX,
1190 NULL, 0x0, NULL, HFILL }},
1191 { &hf_ctdb_recmaster, {
1192 "Recovery Master", "ctdb.recmaster", FT_UINT32, BASE_DEC,
1193 NULL, 0x0, NULL, HFILL }},
1194 { &hf_ctdb_recmode, {
1195 "Recovery Mode", "ctdb.recmode", FT_UINT32, BASE_DEC,
1196 VALS(recmode_vals), 0x0, NULL, HFILL }},
1197 { &hf_ctdb_num_nodes, {
1198 "Num Nodes", "ctdb.num_nodes", FT_UINT32, BASE_DEC,
1199 NULL, 0x0, NULL, HFILL }},
1200 { &hf_ctdb_vnn, {
1201 "VNN", "ctdb.vnn", FT_UINT32, BASE_DEC,
1202 NULL, 0x0, NULL, HFILL }},
1203 { &hf_ctdb_node_flags, {
1204 "Node Flags", "ctdb.node_flags", FT_UINT32, BASE_HEX,
1205 NULL, 0x0, NULL, HFILL }},
1206 { &hf_ctdb_node_ip, {
1207 "Node IP", "ctdb.node_ip", FT_IPv4, BASE_NONE,
1208 NULL, 0x0, NULL, HFILL }},
1209 { &hf_ctdb_pid, {
1210 "PID", "ctdb.pid", FT_UINT32, BASE_DEC,
1211 NULL, 0x0, NULL, HFILL }},
1212 { &hf_ctdb_process_exists, {
1213 "Process Exists", "ctdb.process_exists", FT_BOOLEAN, 32,
1214 TFS(&process_exists_tfs), 0x01, NULL, HFILL }},
1217 /* Setup protocol subtree array */
1218 static gint *ett[] = {
1219 &ett_ctdb,
1220 &ett_ctdb_key,
1223 static ei_register_info ei[] = {
1224 { &ei_ctdb_too_many_nodes, { "ctdb.too_many_nodes", PI_UNDECODED, PI_WARN, "Too many nodes", EXPFILL }},
1227 expert_module_t* expert_ctdb;
1230 /* Register the protocol name and description */
1231 proto_ctdb = proto_register_protocol("Cluster TDB", "CTDB", "ctdb");
1233 /* Required function calls to register the header fields and subtrees used */
1234 proto_register_field_array(proto_ctdb, hf, array_length(hf));
1235 proto_register_subtree_array(ett, array_length(ett));
1236 expert_ctdb = expert_register_protocol(proto_ctdb);
1237 expert_register_field_array(expert_ctdb, ei, array_length(ei));
1239 ctdb_transactions = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1240 ctdb_controls = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1244 void
1245 proto_reg_handoff_ctdb(void)
1247 dissector_handle_t ctdb_handle;
1249 ctdb_handle = new_create_dissector_handle(dissect_ctdb, proto_ctdb);
1250 dissector_add_handle("tcp.port", ctdb_handle);
1252 heur_dissector_add("tcp", dissect_ctdb, proto_ctdb);