3dd5c32ab1148c8e2ba53df98caac2ca9bb6b933
[metze/samba/wip.git] / ctdb / protocol / protocol_debug.c
1 /*
2    CTDB protocol marshalling
3
4    Copyright (C) Amitay Isaacs  2016
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/network.h"
22 #include "system/locale.h"
23
24 #include <talloc.h>
25 #include <tdb.h>
26
27 #include <protocol/protocol.h>
28 #include <protocol/protocol_api.h>
29
30 /*
31  * Utility functions
32  */
33 struct uint32_map {
34         uint32_t key;
35 #define MAP_END         0xffffffff
36         const char *name;
37 };
38
39
40 static void uint32_map_print(struct uint32_map *map, uint32_t key, FILE *fp)
41 {
42         int i = 0;
43
44         while (map[i].key != MAP_END) {
45                 if (key == map[i].key) {
46                         fprintf(fp, "%s", map[i].name);
47                         return;
48                 }
49                 i = i+1;
50         }
51
52         fprintf(fp, "UNKNOWN(%u)", key);
53 }
54
55 static void tdb_data_print(TDB_DATA d, FILE *fp)
56 {
57         unsigned char *p = (unsigned char *)d.dptr;
58         int len = d.dsize;
59         while (len--) {
60                 if (isprint(*p) && !strchr("\"\\", *p)) {
61                         fputc(*p, fp);
62                 } else {
63                         fprintf(fp, "\\%02X", *p);
64                 }
65                 p++;
66         }
67 }
68
69 /*
70  * Data types
71  */
72
73 static void ctdb_operation_print(uint32_t operation, FILE *fp)
74 {
75         struct uint32_map map[] = {
76                 { CTDB_REQ_CALL, "REQ_CALL" },
77                 { CTDB_REPLY_CALL, "REPLY_CALL" },
78                 { CTDB_REQ_DMASTER, "REQ_DMASTER" },
79                 { CTDB_REPLY_DMASTER, "REPLY_DMASTER" },
80                 { CTDB_REPLY_ERROR, "REPLY_ERROR" },
81                 { CTDB_REQ_MESSAGE, "REQ_MESSAGE" },
82                 { CTDB_REQ_CONTROL, "REQ_CONTROL", },
83                 { CTDB_REPLY_CONTROL, "REPLY_CONTROL" },
84                 { CTDB_REQ_KEEPALIVE, "REQ_KEEPALIVE" },
85                 { MAP_END, "" },
86         };
87
88         uint32_map_print(map, operation, fp);
89 }
90
91 static void ctdb_callid_print(uint32_t callid, FILE *fp)
92 {
93         struct uint32_map map[] = {
94                 { CTDB_NULL_FUNC, "NULL" },
95                 { CTDB_FETCH_FUNC, "FETCH" },
96                 { CTDB_FETCH_WITH_HEADER_FUNC, "FETCH_WITH_HEADER" },
97                 { MAP_END, "" },
98         };
99
100         uint32_map_print(map, callid, fp);
101 }
102
103 static void ctdb_opcode_print(uint32_t opcode, FILE *fp)
104 {
105         struct uint32_map map[] = {
106                 { CTDB_CONTROL_PROCESS_EXISTS, "PROCESS_EXISTS" },
107                 { CTDB_CONTROL_STATISTICS, "STATISTICS" },
108                 { CTDB_CONTROL_PING, "PING" },
109                 { CTDB_CONTROL_GETDBPATH, "GETDBPATH" },
110                 { CTDB_CONTROL_GETVNNMAP, "GETVNNMAP" },
111                 { CTDB_CONTROL_SETVNNMAP, "SETVNNMAP" },
112                 { CTDB_CONTROL_GET_DEBUG, "GET_DEBUG" },
113                 { CTDB_CONTROL_SET_DEBUG, "SET_DEBUG" },
114                 { CTDB_CONTROL_GET_DBMAP, "GET_DBMAP" },
115                 { CTDB_CONTROL_GET_NODEMAPv4, "GET_NODEMAPv4" },
116                 { CTDB_CONTROL_SET_DMASTER, "SET_DMASTER" },
117                 { CTDB_CONTROL_PULL_DB, "PULL_DB" },
118                 { CTDB_CONTROL_PUSH_DB, "PUSH_DB" },
119                 { CTDB_CONTROL_GET_RECMODE, "GET_RECMODE" },
120                 { CTDB_CONTROL_SET_RECMODE, "SET_RECMODE" },
121                 { CTDB_CONTROL_STATISTICS_RESET, "STATISTICS_RESET" },
122                 { CTDB_CONTROL_DB_ATTACH, "DB_ATTACH" },
123                 { CTDB_CONTROL_SET_CALL, "SET_CALL" },
124                 { CTDB_CONTROL_TRAVERSE_START, "TRAVERSE_START" },
125                 { CTDB_CONTROL_TRAVERSE_ALL, "TRAVERSE_ALL" },
126                 { CTDB_CONTROL_TRAVERSE_DATA, "TRAVERSE_DATA" },
127                 { CTDB_CONTROL_REGISTER_SRVID, "REGISTER_SRVID" },
128                 { CTDB_CONTROL_DEREGISTER_SRVID, "DEREGISTER_SRVID" },
129                 { CTDB_CONTROL_GET_DBNAME, "GET_DBNAME" },
130                 { CTDB_CONTROL_ENABLE_SEQNUM, "ENABLE_SEQNUM" },
131                 { CTDB_CONTROL_UPDATE_SEQNUM, "UPDATE_SEQNUM" },
132                 { CTDB_CONTROL_DUMP_MEMORY, "DUMP_MEMORY" },
133                 { CTDB_CONTROL_GET_PID, "GET_PID" },
134                 { CTDB_CONTROL_GET_RECMASTER, "GET_RECMASTER" },
135                 { CTDB_CONTROL_SET_RECMASTER, "SET_RECMASTER" },
136                 { CTDB_CONTROL_FREEZE, "FREEZE" },
137                 { CTDB_CONTROL_THAW, "THAW" },
138                 { CTDB_CONTROL_GET_PNN, "GET_PNN" },
139                 { CTDB_CONTROL_SHUTDOWN, "SHUTDOWN" },
140                 { CTDB_CONTROL_GET_MONMODE, "GET_MONMODE" },
141                 { CTDB_CONTROL_TAKEOVER_IPv4, "TAKEOVER_IPv4" },
142                 { CTDB_CONTROL_RELEASE_IPv4, "RELEASE_IPv4" },
143                 { CTDB_CONTROL_TCP_CLIENT, "TCP_CLIENT" },
144                 { CTDB_CONTROL_TCP_ADD, "TCP_ADD" },
145                 { CTDB_CONTROL_TCP_REMOVE, "TCP_REMOVE" },
146                 { CTDB_CONTROL_STARTUP, "STARTUP" },
147                 { CTDB_CONTROL_SET_TUNABLE, "SET_TUNABLE" },
148                 { CTDB_CONTROL_GET_TUNABLE, "GET_TUNABLE" },
149                 { CTDB_CONTROL_LIST_TUNABLES, "LIST_TUNABLES" },
150                 { CTDB_CONTROL_GET_PUBLIC_IPSv4, "GET_PUBLIC_IPSv4" },
151                 { CTDB_CONTROL_MODIFY_FLAGS, "MODIFY_FLAGS" },
152                 { CTDB_CONTROL_GET_ALL_TUNABLES, "GET_ALL_TUNABLES" },
153                 { CTDB_CONTROL_KILL_TCP, "KILL_TCP" },
154                 { CTDB_CONTROL_GET_TCP_TICKLE_LIST, "GET_TCP_TICKLE_LIST" },
155                 { CTDB_CONTROL_SET_TCP_TICKLE_LIST, "SET_TCP_TICKLE_LIST" },
156                 { CTDB_CONTROL_REGISTER_SERVER_ID, "REGISTER_SERVER_ID" },
157                 { CTDB_CONTROL_UNREGISTER_SERVER_ID, "UNREGISTER_SERVER_ID" },
158                 { CTDB_CONTROL_CHECK_SERVER_ID, "CHECK_SERVER_ID" },
159                 { CTDB_CONTROL_GET_SERVER_ID_LIST, "GET_SERVER_ID_LIST" },
160                 { CTDB_CONTROL_DB_ATTACH_PERSISTENT, "DB_ATTACH_PERSISTENT" },
161                 { CTDB_CONTROL_PERSISTENT_STORE, "PERSISTENT_STORE" },
162                 { CTDB_CONTROL_UPDATE_RECORD, "UPDATE_RECORD" },
163                 { CTDB_CONTROL_SEND_GRATUITOUS_ARP, "SEND_GRATUITOUS_ARP" },
164                 { CTDB_CONTROL_TRANSACTION_START, "TRANSACTION_START" },
165                 { CTDB_CONTROL_TRANSACTION_COMMIT, "TRANSACTION_COMMIT" },
166                 { CTDB_CONTROL_WIPE_DATABASE, "WIPE_DATABASE" },
167                 { CTDB_CONTROL_UPTIME, "UPTIME" },
168                 { CTDB_CONTROL_START_RECOVERY, "START_RECOVERY" },
169                 { CTDB_CONTROL_END_RECOVERY, "END_RECOVERY" },
170                 { CTDB_CONTROL_RELOAD_NODES_FILE, "RELOAD_NODES_FILE" },
171                 { CTDB_CONTROL_TRY_DELETE_RECORDS, "TRY_DELETE_RECORDS" },
172                 { CTDB_CONTROL_ENABLE_MONITOR, "ENABLE_MONITOR" },
173                 { CTDB_CONTROL_DISABLE_MONITOR, "DISABLE_MONITOR" },
174                 { CTDB_CONTROL_ADD_PUBLIC_IP, "ADD_PUBLIC_IP" },
175                 { CTDB_CONTROL_DEL_PUBLIC_IP, "DEL_PUBLIC_IP" },
176                 { CTDB_CONTROL_RUN_EVENTSCRIPTS, "RUN_EVENTSCRIPTS" },
177                 { CTDB_CONTROL_GET_CAPABILITIES, "GET_CAPABILITIES" },
178                 { CTDB_CONTROL_START_PERSISTENT_UPDATE, "START_PERSISTENT_UPDATE" },
179                 { CTDB_CONTROL_CANCEL_PERSISTENT_UPDATE, "CANCEL_PERSISTENT_UPDATE" },
180                 { CTDB_CONTROL_TRANS2_COMMIT, "TRANS2_COMMIT" },
181                 { CTDB_CONTROL_TRANS2_FINISHED, "TRANS2_FINISHED" },
182                 { CTDB_CONTROL_TRANS2_ERROR, "TRANS2_ERROR" },
183                 { CTDB_CONTROL_TRANS2_COMMIT_RETRY, "TRANS2_COMMIT_RETRY" },
184                 { CTDB_CONTROL_RECD_PING, "RECD_PING" },
185                 { CTDB_CONTROL_RELEASE_IP, "RELEASE_IP" },
186                 { CTDB_CONTROL_TAKEOVER_IP, "TAKEOVER_IP" },
187                 { CTDB_CONTROL_GET_PUBLIC_IPS, "GET_PUBLIC_IPS" },
188                 { CTDB_CONTROL_GET_NODEMAP, "GET_NODEMAP" },
189                 { CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS, "GET_EVENT_SCRIPT_STATUS" },
190                 { CTDB_CONTROL_TRAVERSE_KILL, "TRAVERSE_KILL" },
191                 { CTDB_CONTROL_RECD_RECLOCK_LATENCY, "RECD_RECLOCK_LATENCY" },
192                 { CTDB_CONTROL_GET_RECLOCK_FILE, "GET_RECLOCK_FILE" },
193                 { CTDB_CONTROL_STOP_NODE, "STOP_NODE" },
194                 { CTDB_CONTROL_CONTINUE_NODE, "CONTINUE_NODE" },
195                 { CTDB_CONTROL_SET_NATGWSTATE, "SET_NATGWSTATE" },
196                 { CTDB_CONTROL_SET_LMASTERROLE, "SET_LMASTERROLE" },
197                 { CTDB_CONTROL_SET_RECMASTERROLE, "SET_RECMASTERROLE" },
198                 { CTDB_CONTROL_ENABLE_SCRIPT, "ENABLE_SCRIPT" },
199                 { CTDB_CONTROL_DISABLE_SCRIPT, "DISABLE_SCRIPT" },
200                 { CTDB_CONTROL_SET_BAN_STATE, "SET_BAN_STATE" },
201                 { CTDB_CONTROL_GET_BAN_STATE, "GET_BAN_STATE" },
202                 { CTDB_CONTROL_SET_DB_PRIORITY, "SET_DB_PRIORITY" },
203                 { CTDB_CONTROL_GET_DB_PRIORITY, "GET_DB_PRIORITY" },
204                 { CTDB_CONTROL_TRANSACTION_CANCEL, "TRANSACTION_CANCEL" },
205                 { CTDB_CONTROL_REGISTER_NOTIFY, "REGISTER_NOTIFY" },
206                 { CTDB_CONTROL_DEREGISTER_NOTIFY, "DEREGISTER_NOTIFY" },
207                 { CTDB_CONTROL_TRANS2_ACTIVE, "TRANS2_ACTIVE" },
208                 { CTDB_CONTROL_GET_LOG, "GET_LOG" },
209                 { CTDB_CONTROL_CLEAR_LOG, "CLEAR_LOG" },
210                 { CTDB_CONTROL_TRANS3_COMMIT, "TRANS3_COMMIT" },
211                 { CTDB_CONTROL_GET_DB_SEQNUM, "GET_DB_SEQNUM" },
212                 { CTDB_CONTROL_DB_SET_HEALTHY, "DB_SET_HEALTHY" },
213                 { CTDB_CONTROL_DB_GET_HEALTH, "DB_GET_HEALTH" },
214                 { CTDB_CONTROL_GET_PUBLIC_IP_INFO, "GET_PUBLIC_IP_INFO" },
215                 { CTDB_CONTROL_GET_IFACES, "GET_IFACES" },
216                 { CTDB_CONTROL_SET_IFACE_LINK_STATE, "SET_IFACE_LINK_STATE" },
217                 { CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE, "TCP_ADD_DELAYED_UPDATE" },
218                 { CTDB_CONTROL_GET_STAT_HISTORY, "GET_STAT_HISTORY" },
219                 { CTDB_CONTROL_SCHEDULE_FOR_DELETION, "SCHEDULE_FOR_DELETION" },
220                 { CTDB_CONTROL_SET_DB_READONLY, "SET_DB_READONLY" },
221                 { CTDB_CONTROL_CHECK_SRVIDS, "CHECK_SRVIDS" },
222                 { CTDB_CONTROL_TRAVERSE_START_EXT, "TRAVERSE_START_EXT" },
223                 { CTDB_CONTROL_GET_DB_STATISTICS, "GET_DB_STATISTICS" },
224                 { CTDB_CONTROL_SET_DB_STICKY, "SET_DB_STICKY" },
225                 { CTDB_CONTROL_RELOAD_PUBLIC_IPS, "RELOAD_PUBLIC_IPS" },
226                 { CTDB_CONTROL_TRAVERSE_ALL_EXT, "TRAVERSE_ALL_EXT" },
227                 { CTDB_CONTROL_RECEIVE_RECORDS, "RECEIVE_RECORDS" },
228                 { CTDB_CONTROL_IPREALLOCATED, "IPREALLOCATED" },
229                 { CTDB_CONTROL_GET_RUNSTATE, "GET_RUNSTATE" },
230                 { CTDB_CONTROL_DB_DETACH, "DB_DETACH" },
231                 { CTDB_CONTROL_GET_NODES_FILE, "GET_NODES_FILE" },
232                 { CTDB_CONTROL_DB_FREEZE, "DB_FREEZE" },
233                 { CTDB_CONTROL_DB_THAW, "DB_THAW" },
234                 { CTDB_CONTROL_DB_TRANSACTION_START, "DB_TRANSACTION_START" },
235                 { CTDB_CONTROL_DB_TRANSACTION_COMMIT, "DB_TRANSACTION_COMMIT" },
236                 { CTDB_CONTROL_DB_TRANSACTION_CANCEL, "DB_TRANSACTION_CANCEL" },
237                 { CTDB_CONTROL_DB_PULL, "DB_PULL" },
238                 { CTDB_CONTROL_DB_PUSH_START, "DB_PUSH_START" },
239                 { CTDB_CONTROL_DB_PUSH_CONFIRM, "DB_PUSH_CONFIRM" },
240                 { CTDB_CONTROL_DB_OPEN_FLAGS, "DB_OPEN_FLAGS" },
241                 { CTDB_CONTROL_DB_ATTACH_REPLICATED, "DB_ATTACH_REPLICATED" },
242                 { CTDB_CONTROL_CHECK_PID_SRVID, "CHECK_PID_SRVID" },
243                 { CTDB_CONTROL_TUNNEL_REGISTER, "TUNNEL_REGISTER" },
244                 { CTDB_CONTROL_TUNNEL_DEREGISTER, "TUNNEL_DEREGISTER" },
245                 { MAP_END, "" },
246         };
247
248         uint32_map_print(map, opcode, fp);
249 }
250
251 static void ctdb_control_flags_print(uint32_t flags, FILE *fp)
252 {
253         if (flags & CTDB_CTRL_FLAG_NOREPLY) {
254                 fprintf(fp, "NOREPLY ");
255         }
256         if (flags & CTDB_CTRL_FLAG_OPCODE_SPECIFIC) {
257                 fprintf(fp, "OPCODE_SPECIFIC ");
258         }
259 }
260
261 static void ctdb_pnn_print(uint32_t pnn, FILE *fp)
262 {
263         if (pnn == CTDB_CURRENT_NODE) {
264                 fprintf(fp, "CURRENT");
265         } else if (pnn == CTDB_BROADCAST_ALL) {
266                 fprintf(fp, "ALL");
267         } else if (pnn == CTDB_BROADCAST_VNNMAP) {
268                 fprintf(fp, "VNNMAP");
269         } else  if (pnn == CTDB_BROADCAST_CONNECTED) {
270                 fprintf(fp, "CONNECTED");
271         } else if (pnn == CTDB_MULTICAST) {
272                 fprintf(fp, "MULTICAST");
273         } else if (pnn == CTDB_UNKNOWN_PNN) {
274                 fprintf(fp, "UNKNOWN");
275         } else {
276                 fprintf(fp, "%u", pnn);
277         }
278 }
279
280 static void ctdb_srvid_print(uint64_t srvid, FILE *fp)
281 {
282         uint64_t prefix = 0xFFFF000000000000LL;
283
284         if (srvid == CTDB_SRVID_ALL) {
285                 fprintf(fp, "ALL");
286         } else if ((srvid & prefix) == CTDB_SRVID_RECOVERY) {
287                 srvid = srvid & ~CTDB_SRVID_RECOVERY;
288                 fprintf(fp, "RECOVERY-%"PRIx64"", srvid);
289         } else if (srvid == CTDB_SRVID_BANNING) {
290                 fprintf(fp, "BANNING");
291         } else if (srvid == CTDB_SRVID_ELECTION) {
292                 fprintf(fp, "ELECTION");
293         } else if (srvid == CTDB_SRVID_RECONFIGURE) {
294                 fprintf(fp, "RECONFIGURE");
295         } else if (srvid == CTDB_SRVID_RELEASE_IP) {
296                 fprintf(fp, "RELEASE_IP");
297         } else if (srvid == CTDB_SRVID_TAKE_IP) {
298                 fprintf(fp, "TAKE_IP");
299         } else if (srvid == CTDB_SRVID_SET_NODE_FLAGS) {
300                 fprintf(fp, "SET_NODE_FLAGS");
301         } else if (srvid == CTDB_SRVID_RECD_UPDATE_IP) {
302                 fprintf(fp, "RECD_UPDATE_IP");
303         } else if (srvid == CTDB_SRVID_VACUUM_FETCH) {
304                 fprintf(fp, "VACUUM_FETCH");
305         } else if (srvid == CTDB_SRVID_DETACH_DATABASE) {
306                 fprintf(fp, "DETACH_DATABASE");
307         } else if (srvid == CTDB_SRVID_MEM_DUMP) {
308                 fprintf(fp, "MEM_DUMP");
309         } else if (srvid == CTDB_SRVID_GETLOG) {
310                 fprintf(fp, "GETLOG");
311         } else if (srvid == CTDB_SRVID_CLEARLOG) {
312                 fprintf(fp, "CLEARLOG");
313         } else if (srvid == CTDB_SRVID_PUSH_NODE_FLAGS) {
314                 fprintf(fp, "PUSH_NODE_FLAGS");
315         } else if (srvid == CTDB_SRVID_RELOAD_NODES) {
316                 fprintf(fp, "RELOAD_NODES");
317         } else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
318                 fprintf(fp, "TAKEOVER_RUN");
319         } else if (srvid == CTDB_SRVID_REBALANCE_NODE) {
320                 fprintf(fp, "REBALANCE_NODE");
321         } else if (srvid == CTDB_SRVID_DISABLE_TAKEOVER_RUNS) {
322                 fprintf(fp, "DISABLE_TAKEOVER_RUNS");
323         } else if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
324                 fprintf(fp, "DISABLE_RECOVERIES");
325         } else if (srvid == CTDB_SRVID_DISABLE_IP_CHECK) {
326                 fprintf(fp, "DISABLE_IP_CHECK");
327         } else if ((srvid & prefix) == CTDB_SRVID_SAMBA_RANGE) {
328                 if (srvid == CTDB_SRVID_SAMBA_NOTIFY) {
329                         fprintf(fp, "SAMBA_NOTIFY");
330                 } else {
331                         srvid &= ~CTDB_SRVID_SAMBA_RANGE;
332                         fprintf(fp, "samba-0x%"PRIx64"", srvid);
333                 }
334         } else if ((srvid & prefix) == CTDB_SRVID_NFSD_RANGE) {
335                 srvid &= ~CTDB_SRVID_NFSD_RANGE;
336                 fprintf(fp, "nfsd-0x%"PRIx64"", srvid);
337         } else if ((srvid & prefix) == CTDB_SRVID_ISCSID_RANGE) {
338                 srvid &= ~CTDB_SRVID_ISCSID_RANGE;
339                 fprintf(fp, "iscsi-0x%"PRIx64"", srvid);
340         } else if ((srvid & prefix) == CTDB_SRVID_TOOL_RANGE) {
341                 srvid &= ~CTDB_SRVID_TOOL_RANGE;
342                 fprintf(fp, "tool-0x%"PRIx64"", srvid);
343         } else if ((srvid & prefix) == CTDB_SRVID_TEST_RANGE) {
344                 srvid &= ~CTDB_SRVID_TEST_RANGE;
345                 fprintf(fp, "test-0x%"PRIx64"", srvid);
346         } else if ((srvid & prefix) == CTDB_SRVID_PID_RANGE) {
347                 if (srvid < UINT16_MAX) {
348                         fprintf(fp, "pid-%"PRIu64, srvid);
349                 } else {
350                         fprintf(fp, "pid-0x%"PRIx64, srvid);
351                 }
352         } else {
353                 fprintf(fp, "0x%"PRIx64, srvid);
354         }
355 }
356
357 static void ctdb_tunnel_id_print(uint64_t tunnel_id, FILE *fp)
358 {
359         fprintf(fp, "0x%"PRIx64, tunnel_id);
360 }
361
362 static void ctdb_tunnel_flags_print(uint32_t flags, FILE *fp)
363 {
364         if (flags & CTDB_TUNNEL_FLAG_REQUEST) {
365                 fprintf(fp, "REQUEST ");
366         }
367         if (flags & CTDB_TUNNEL_FLAG_REPLY) {
368                 fprintf(fp, "REPLY ");
369         }
370         if (flags & CTDB_TUNNEL_FLAG_NOREPLY) {
371                 fprintf(fp, "NOREPLY ");
372         }
373 }
374
375 /*
376  * Print routines
377  */
378
379 static void ctdb_req_header_print(struct ctdb_req_header *h, FILE *fp)
380 {
381         fprintf(fp, "Header\n");
382         fprintf(fp, "  length:%u magic:0x%"PRIx32" version:%u generation:0x%"PRIx32"\n",
383                 h->length, h->ctdb_magic, h->ctdb_version, h->generation);
384         fprintf(fp, "  ");
385         ctdb_operation_print(h->operation, fp);
386         fprintf(fp, " dst:");
387         ctdb_pnn_print(h->destnode, fp);
388         fprintf(fp, " src:");
389         ctdb_pnn_print(h->srcnode, fp);
390         fprintf(fp, " reqid:0x%"PRIx32"\n", h->reqid);
391 }
392
393 static void ctdb_req_call_print(struct ctdb_req_call *c, FILE *fp)
394 {
395         fprintf(fp, "Data\n");
396         fprintf(fp, "  db:0x%"PRIx32" ", c->db_id);
397         ctdb_callid_print(c->callid, fp);
398         fprintf(fp, "\n");
399         fprintf(fp, "  key:");
400         tdb_data_print(c->key, fp);
401         fprintf(fp, "\n");
402 }
403
404 static void ctdb_reply_call_print(struct ctdb_reply_call *c, FILE *fp)
405 {
406         fprintf(fp, "Data\n");
407         fprintf(fp, "  status:%d\n", c->status);
408         if (c->status == 0) {
409                 fprintf(fp, "  data:");
410                 tdb_data_print(c->data, fp);
411                 fprintf(fp, "\n");
412         }
413 }
414
415 static void ctdb_req_dmaster_print(struct ctdb_req_dmaster *c, FILE *fp)
416 {
417         fprintf(fp, "Data\n");
418         fprintf(fp, "  db:0x%"PRIx32" rsn:0x%"PRIx64" dmaster:%u\n",
419                 c->db_id, c->rsn, c->dmaster);
420         fprintf(fp, "  key:");
421         tdb_data_print(c->key, fp);
422         fprintf(fp, "\n");
423         fprintf(fp, "  data:");
424         tdb_data_print(c->data, fp);
425         fprintf(fp, "\n");
426 }
427
428 static void ctdb_reply_dmaster_print(struct ctdb_reply_dmaster *c, FILE *fp)
429 {
430         fprintf(fp, "Data\n");
431         fprintf(fp, "  db:0x%"PRIx32" rsn:0x%"PRIx64"\n", c->db_id, c->rsn);
432         fprintf(fp, "  key:");
433         tdb_data_print(c->key, fp);
434         fprintf(fp, "\n");
435         fprintf(fp, "  data:");
436         tdb_data_print(c->data, fp);
437         fprintf(fp, "\n");
438 }
439
440 static void ctdb_reply_error_print(struct ctdb_reply_error *c, FILE *fp)
441 {
442         fprintf(fp, "Data\n");
443         fprintf(fp, "  status:%d\n", c->status);
444         if (c->status != 0) {
445                 fprintf(fp, "  msg:");
446                 tdb_data_print(c->msg, fp);
447                 fprintf(fp, "\n");
448         }
449 }
450
451 static void ctdb_req_message_data_print(struct ctdb_req_message_data *c,
452                                         FILE *fp)
453 {
454         fprintf(fp, "Data\n");
455         fprintf(fp, "  srvid:");
456         ctdb_srvid_print(c->srvid, fp);
457         fprintf(fp, "\n");
458         fprintf(fp, "  data:");
459         tdb_data_print(c->data, fp);
460         fprintf(fp, "\n");
461 }
462
463 static void ctdb_req_control_print(struct ctdb_req_control *c, FILE *fp)
464 {
465         fprintf(fp, "Data\n");
466         fprintf(fp, "  ");
467         ctdb_opcode_print(c->opcode, fp);
468         fprintf(fp, " srvid:");
469         ctdb_srvid_print(c->srvid, fp);
470         fprintf(fp, " client_id:0x%"PRIx32" ", c->client_id);
471         ctdb_control_flags_print(c->flags, fp);
472         fprintf(fp, "\n");
473 }
474
475 static void ctdb_reply_control_print(struct ctdb_reply_control *c, FILE *fp)
476 {
477         fprintf(fp, "Data\n");
478         fprintf(fp, "  status:%d ", c->status);
479         if (c->errmsg != NULL) {
480                 fprintf(fp, "errmsg: %s", c->errmsg);
481         }
482         fprintf(fp, "\n");
483 }
484
485 static void ctdb_req_keepalive_print(struct ctdb_req_keepalive *c, FILE *fp)
486 {
487         fprintf(fp, "Data\n");
488         fprintf(fp, "  version:0x%"PRIx32, c->version);
489         fprintf(fp, "  uptime:%"PRIu32, c->uptime);
490         fprintf(fp, "\n");
491 }
492
493 static void ctdb_req_tunnel_print(struct ctdb_req_tunnel *c, FILE *fp)
494 {
495         fprintf(fp, "Data\n");
496         fprintf(fp, "  tunnel_id:");
497         ctdb_tunnel_id_print(c->tunnel_id, fp);
498         ctdb_tunnel_flags_print(c->flags, fp);
499         tdb_data_print(c->data, fp);
500         fprintf(fp, "\n");
501 }
502
503 /*
504  * Parse routines
505  */
506
507 static void ctdb_req_call_parse(uint8_t *buf, size_t buflen, FILE *fp,
508                                 TALLOC_CTX *mem_ctx)
509 {
510         struct ctdb_req_call c;
511         int ret;
512
513         ret = ctdb_req_call_pull(buf, buflen, NULL, mem_ctx, &c);
514         if (ret != 0) {
515                 fprintf(fp, "Failed to parse CTDB_REQ_CALL\n");
516                 return;
517         }
518
519         ctdb_req_call_print(&c, fp);
520 }
521
522 static void ctdb_reply_call_parse(uint8_t *buf, size_t buflen, FILE *fp,
523                                   TALLOC_CTX *mem_ctx)
524 {
525         struct ctdb_reply_call c;
526         int ret;
527
528         ret = ctdb_reply_call_pull(buf, buflen, NULL, mem_ctx, &c);
529         if (ret != 0) {
530                 fprintf(fp, "Failed to parse CTDB_REPLY_CALL\n");
531                 return;
532         }
533
534         ctdb_reply_call_print(&c, fp);
535 }
536
537 static void ctdb_req_dmaster_parse(uint8_t *buf, size_t buflen, FILE *fp,
538                                    TALLOC_CTX *mem_ctx)
539 {
540         struct ctdb_req_dmaster c;
541         int ret;
542
543         ret = ctdb_req_dmaster_pull(buf, buflen, NULL, mem_ctx, &c);
544         if (ret != 0) {
545                 fprintf(fp, "Failed to parse CTDB_REQ_DMASTER\n");
546                 return;
547         }
548
549         ctdb_req_dmaster_print(&c, fp);
550 }
551
552 static void ctdb_reply_dmaster_parse(uint8_t *buf, size_t buflen, FILE *fp,
553                                      TALLOC_CTX *mem_ctx)
554 {
555         struct ctdb_reply_dmaster c;
556         int ret;
557
558         ret = ctdb_reply_dmaster_pull(buf, buflen, NULL, mem_ctx, &c);
559         if (ret != 0) {
560                 fprintf(fp, "Failed to parse CTDB_REPLY_DMASTER\n");
561                 return;
562         }
563
564         ctdb_reply_dmaster_print(&c, fp);
565 }
566
567 static void ctdb_reply_error_parse(uint8_t *buf, size_t buflen, FILE *fp,
568                                    TALLOC_CTX *mem_ctx)
569 {
570         struct ctdb_reply_error c;
571         int ret;
572
573         ret = ctdb_reply_error_pull(buf, buflen, NULL, mem_ctx, &c);
574         if (ret != 0) {
575                 fprintf(fp, "Failed to parse CTDB_REPLY_ERROR\n");
576                 return;
577         }
578
579         ctdb_reply_error_print(&c, fp);
580 }
581
582 static void ctdb_req_message_parse(uint8_t *buf, size_t buflen, FILE *fp,
583                                    TALLOC_CTX *mem_ctx)
584 {
585         struct ctdb_req_message_data c;
586         int ret;
587
588         ret = ctdb_req_message_data_pull(buf, buflen, NULL, mem_ctx, &c);
589         if (ret != 0) {
590                 fprintf(fp, "Failed to parse CTDB_REQ_MESSAGE\n");
591                 return;
592         }
593
594         ctdb_req_message_data_print(&c, fp);
595 }
596
597 static void ctdb_req_control_parse(uint8_t *buf, size_t buflen, FILE *fp,
598                                    TALLOC_CTX *mem_ctx)
599 {
600         struct ctdb_req_control c;
601         int ret;
602
603         ret = ctdb_req_control_pull(buf, buflen, NULL, mem_ctx, &c);
604         if (ret != 0) {
605                 fprintf(fp, "Failed to parse CTDB_REQ_CONTROL\n");
606                 return;
607         }
608
609         ctdb_req_control_print(&c, fp);
610 }
611
612 static void ctdb_reply_control_parse(uint8_t *buf, size_t buflen, FILE *fp,
613                                      TALLOC_CTX *mem_ctx)
614 {
615         struct ctdb_reply_control c;
616         int ret;
617
618         ret = ctdb_reply_control_pull(buf, buflen, -1, NULL, mem_ctx, &c);
619         if (ret != 0) {
620                 fprintf(fp, "Failed to parse CTDB_REPLY_CONTROL\n");
621                 return;
622         }
623
624         ctdb_reply_control_print(&c, fp);
625 }
626
627 static void ctdb_req_keepalive_parse(uint8_t *buf, size_t buflen, FILE *fp,
628                                      TALLOC_CTX *mem_ctx)
629 {
630         struct ctdb_req_keepalive c;
631         int ret;
632
633         ret = ctdb_req_keepalive_pull(buf, buflen, NULL, mem_ctx, &c);
634         if (ret != 0) {
635                 fprintf(fp, "Failed to parse CTDB_REQ_KEEPALIVE\n");
636                 return;
637         }
638
639         ctdb_req_keepalive_print(&c, fp);
640 }
641
642 static void ctdb_req_tunnel_parse(uint8_t *buf, size_t buflen, FILE *fp,
643                                   TALLOC_CTX *mem_ctx)
644 {
645         struct ctdb_req_tunnel c;
646         int ret;
647
648         ret = ctdb_req_tunnel_pull(buf, buflen, NULL, mem_ctx, &c);
649         if (ret != 0) {
650                 fprintf(fp, "Failed to parse CTDB_REQ_TUNNEL\n");
651                 return;
652         }
653
654         ctdb_req_tunnel_print(&c, fp);
655 }
656
657 /*
658  * Packet print
659  */
660
661 void ctdb_packet_print(uint8_t *buf, size_t buflen, FILE *fp)
662 {
663         TALLOC_CTX *mem_ctx = talloc_new(NULL);
664         struct ctdb_req_header h;
665         size_t np;
666         int ret;
667
668         fprintf(fp, "Buffer len:%zu\n", buflen);
669
670         ret = ctdb_req_header_pull(buf, buflen, &h, &np);
671         if (ret != 0) {
672                 fprintf(fp, "Failed to parse ctdb packet header\n");
673                 return;
674         }
675
676         ctdb_req_header_print(&h, fp);
677
678         if (h.length > buflen) {
679                 fprintf(fp, "Packet length mismatch\n");
680         }
681
682         ret = ctdb_req_header_verify(&h, 0);
683         if (ret != 0) {
684                 fprintf(fp, "Invalid ctdb packet header\n");
685                 return;
686         }
687
688         switch (h.operation) {
689                 case CTDB_REQ_CALL:
690                         ctdb_req_call_parse(buf, buflen, fp, mem_ctx);
691                         break;
692
693                 case CTDB_REPLY_CALL:
694                         ctdb_reply_call_parse(buf, buflen, fp, mem_ctx);
695                         break;
696
697                 case CTDB_REQ_DMASTER:
698                         ctdb_req_dmaster_parse(buf, buflen, fp, mem_ctx);
699                         break;
700
701                 case CTDB_REPLY_DMASTER:
702                         ctdb_reply_dmaster_parse(buf, buflen, fp, mem_ctx);
703                         break;
704
705                 case CTDB_REPLY_ERROR:
706                         ctdb_reply_error_parse(buf, buflen, fp, mem_ctx);
707                         break;
708
709                 case CTDB_REQ_MESSAGE:
710                         ctdb_req_message_parse(buf, buflen, fp, mem_ctx);
711                         break;
712
713                 case CTDB_REQ_CONTROL:
714                         ctdb_req_control_parse(buf, buflen, fp, mem_ctx);
715                         break;
716
717                 case CTDB_REPLY_CONTROL:
718                         ctdb_reply_control_parse(buf, buflen, fp, mem_ctx);
719                         break;
720
721                 case CTDB_REQ_KEEPALIVE:
722                         ctdb_req_keepalive_parse(buf, buflen, fp, mem_ctx);
723                         break;
724
725                 case CTDB_REQ_TUNNEL:
726                         ctdb_req_tunnel_parse(buf, buflen, fp, mem_ctx);
727                         break;
728
729                 default:
730                         fprintf(fp, "Invalid ctdb operation\n");
731                         break;
732         }
733
734         talloc_free(mem_ctx);
735 }