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 
uint32_map_print(struct uint32_map * map,uint32_t key,FILE * fp)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 
tdb_data_print(TDB_DATA d,FILE * fp)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 
ctdb_operation_print(uint32_t operation,FILE * fp)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 
ctdb_callid_print(uint32_t callid,FILE * fp)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 
ctdb_opcode_print(uint32_t opcode,FILE * fp)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 		{ CTDB_CONTROL_VACUUM_FETCH, "VACUUM_FETCH" },
246 		{ CTDB_CONTROL_DB_VACUUM, "DB_VACUUM" },
247 		{ MAP_END, "" },
248 	};
249 
250 	uint32_map_print(map, opcode, fp);
251 }
252 
ctdb_control_flags_print(uint32_t flags,FILE * fp)253 static void ctdb_control_flags_print(uint32_t flags, FILE *fp)
254 {
255 	if (flags & CTDB_CTRL_FLAG_NOREPLY) {
256 		fprintf(fp, "NOREPLY ");
257 	}
258 	if (flags & CTDB_CTRL_FLAG_OPCODE_SPECIFIC) {
259 		fprintf(fp, "OPCODE_SPECIFIC ");
260 	}
261 }
262 
ctdb_pnn_print(uint32_t pnn,FILE * fp)263 static void ctdb_pnn_print(uint32_t pnn, FILE *fp)
264 {
265 	if (pnn == CTDB_CURRENT_NODE) {
266 		fprintf(fp, "CURRENT");
267 	} else if (pnn == CTDB_BROADCAST_ALL) {
268 		fprintf(fp, "ALL");
269 	} else if (pnn == CTDB_BROADCAST_ACTIVE) {
270 		fprintf(fp, "ACTIVE");
271 	} else  if (pnn == CTDB_BROADCAST_CONNECTED) {
272 		fprintf(fp, "CONNECTED");
273 	} else if (pnn == CTDB_MULTICAST) {
274 		fprintf(fp, "MULTICAST");
275 	} else if (pnn == CTDB_UNKNOWN_PNN) {
276 		fprintf(fp, "UNKNOWN");
277 	} else {
278 		fprintf(fp, "%u", pnn);
279 	}
280 }
281 
ctdb_srvid_print(uint64_t srvid,FILE * fp)282 static void ctdb_srvid_print(uint64_t srvid, FILE *fp)
283 {
284 	uint64_t prefix = 0xFFFF000000000000LL;
285 
286 	if (srvid == CTDB_SRVID_ALL) {
287 		fprintf(fp, "ALL");
288 	} else if ((srvid & prefix) == CTDB_SRVID_RECOVERY) {
289 		srvid = srvid & ~CTDB_SRVID_RECOVERY;
290 		fprintf(fp, "RECOVERY-%"PRIx64"", srvid);
291 	} else if (srvid == CTDB_SRVID_BANNING) {
292 		fprintf(fp, "BANNING");
293 	} else if (srvid == CTDB_SRVID_ELECTION) {
294 		fprintf(fp, "ELECTION");
295 	} else if (srvid == CTDB_SRVID_RECONFIGURE) {
296 		fprintf(fp, "RECONFIGURE");
297 	} else if (srvid == CTDB_SRVID_RELEASE_IP) {
298 		fprintf(fp, "RELEASE_IP");
299 	} else if (srvid == CTDB_SRVID_TAKE_IP) {
300 		fprintf(fp, "TAKE_IP");
301 	} else if (srvid == CTDB_SRVID_SET_NODE_FLAGS) {
302 		fprintf(fp, "SET_NODE_FLAGS");
303 	} else if (srvid == CTDB_SRVID_RECD_UPDATE_IP) {
304 		fprintf(fp, "RECD_UPDATE_IP");
305 	} else if (srvid == CTDB_SRVID_VACUUM_FETCH) {
306 		fprintf(fp, "VACUUM_FETCH");
307 	} else if (srvid == CTDB_SRVID_DETACH_DATABASE) {
308 		fprintf(fp, "DETACH_DATABASE");
309 	} else if (srvid == CTDB_SRVID_MEM_DUMP) {
310 		fprintf(fp, "MEM_DUMP");
311 	} else if (srvid == CTDB_SRVID_GETLOG) {
312 		fprintf(fp, "GETLOG");
313 	} else if (srvid == CTDB_SRVID_CLEARLOG) {
314 		fprintf(fp, "CLEARLOG");
315 	} else if (srvid == CTDB_SRVID_PUSH_NODE_FLAGS) {
316 		fprintf(fp, "PUSH_NODE_FLAGS");
317 	} else if (srvid == CTDB_SRVID_RELOAD_NODES) {
318 		fprintf(fp, "RELOAD_NODES");
319 	} else if (srvid == CTDB_SRVID_TAKEOVER_RUN) {
320 		fprintf(fp, "TAKEOVER_RUN");
321 	} else if (srvid == CTDB_SRVID_REBALANCE_NODE) {
322 		fprintf(fp, "REBALANCE_NODE");
323 	} else if (srvid == CTDB_SRVID_DISABLE_TAKEOVER_RUNS) {
324 		fprintf(fp, "DISABLE_TAKEOVER_RUNS");
325 	} else if (srvid == CTDB_SRVID_DISABLE_RECOVERIES) {
326 		fprintf(fp, "DISABLE_RECOVERIES");
327 	} else if (srvid == CTDB_SRVID_DISABLE_IP_CHECK) {
328 		fprintf(fp, "DISABLE_IP_CHECK");
329 	} else if ((srvid & prefix) == CTDB_SRVID_SAMBA_RANGE) {
330 		if (srvid == CTDB_SRVID_SAMBA_NOTIFY) {
331 			fprintf(fp, "SAMBA_NOTIFY");
332 		} else {
333 			srvid &= ~CTDB_SRVID_SAMBA_RANGE;
334 			fprintf(fp, "samba-0x%"PRIx64"", srvid);
335 		}
336 	} else if ((srvid & prefix) == CTDB_SRVID_NFSD_RANGE) {
337 		srvid &= ~CTDB_SRVID_NFSD_RANGE;
338 		fprintf(fp, "nfsd-0x%"PRIx64"", srvid);
339 	} else if ((srvid & prefix) == CTDB_SRVID_ISCSID_RANGE) {
340 		srvid &= ~CTDB_SRVID_ISCSID_RANGE;
341 		fprintf(fp, "iscsi-0x%"PRIx64"", srvid);
342 	} else if ((srvid & prefix) == CTDB_SRVID_TOOL_RANGE) {
343 		srvid &= ~CTDB_SRVID_TOOL_RANGE;
344 		fprintf(fp, "tool-0x%"PRIx64"", srvid);
345 	} else if ((srvid & prefix) == CTDB_SRVID_TEST_RANGE) {
346 		srvid &= ~CTDB_SRVID_TEST_RANGE;
347 		fprintf(fp, "test-0x%"PRIx64"", srvid);
348 	} else if ((srvid & prefix) == CTDB_SRVID_PID_RANGE) {
349 		if (srvid < UINT16_MAX) {
350 			fprintf(fp, "pid-%"PRIu64, srvid);
351 		} else {
352 			fprintf(fp, "pid-0x%"PRIx64, srvid);
353 		}
354 	} else {
355 		fprintf(fp, "0x%"PRIx64, srvid);
356 	}
357 }
358 
ctdb_tunnel_id_print(uint64_t tunnel_id,FILE * fp)359 static void ctdb_tunnel_id_print(uint64_t tunnel_id, FILE *fp)
360 {
361 	if ((tunnel_id & CTDB_TUNNEL_TEST) == CTDB_TUNNEL_TEST) {
362 		fprintf(fp, "TEST-%"PRIx64, tunnel_id);
363 	} else {
364 		fprintf(fp, "0x%"PRIx64, tunnel_id);
365 	}
366 }
367 
ctdb_tunnel_flags_print(uint32_t flags,FILE * fp)368 static void ctdb_tunnel_flags_print(uint32_t flags, FILE *fp)
369 {
370 	if (flags & CTDB_TUNNEL_FLAG_REQUEST) {
371 		fprintf(fp, "REQUEST ");
372 	}
373 	if (flags & CTDB_TUNNEL_FLAG_REPLY) {
374 		fprintf(fp, "REPLY ");
375 	}
376 	if (flags & CTDB_TUNNEL_FLAG_NOREPLY) {
377 		fprintf(fp, "NOREPLY ");
378 	}
379 }
380 
381 /*
382  * Print routines
383  */
384 
ctdb_req_header_print(struct ctdb_req_header * h,FILE * fp)385 static void ctdb_req_header_print(struct ctdb_req_header *h, FILE *fp)
386 {
387 	fprintf(fp, "Header\n");
388 	fprintf(fp, "  length:%u magic:0x%"PRIx32" version:%u generation:0x%"PRIx32"\n",
389 		h->length, h->ctdb_magic, h->ctdb_version, h->generation);
390 	fprintf(fp, "  ");
391 	ctdb_operation_print(h->operation, fp);
392 	fprintf(fp, " dst:");
393 	ctdb_pnn_print(h->destnode, fp);
394 	fprintf(fp, " src:");
395 	ctdb_pnn_print(h->srcnode, fp);
396 	fprintf(fp, " reqid:0x%"PRIx32"\n", h->reqid);
397 }
398 
ctdb_req_call_print(struct ctdb_req_call * c,FILE * fp)399 static void ctdb_req_call_print(struct ctdb_req_call *c, FILE *fp)
400 {
401 	fprintf(fp, "Data\n");
402 	fprintf(fp, "  db:0x%"PRIx32" ", c->db_id);
403 	ctdb_callid_print(c->callid, fp);
404 	fprintf(fp, "\n");
405 	fprintf(fp, "  key:");
406 	tdb_data_print(c->key, fp);
407 	fprintf(fp, "\n");
408 }
409 
ctdb_reply_call_print(struct ctdb_reply_call * c,FILE * fp)410 static void ctdb_reply_call_print(struct ctdb_reply_call *c, FILE *fp)
411 {
412 	fprintf(fp, "Data\n");
413 	fprintf(fp, "  status:%d\n", c->status);
414 	if (c->status == 0) {
415 		fprintf(fp, "  data:");
416 		tdb_data_print(c->data, fp);
417 		fprintf(fp, "\n");
418 	}
419 }
420 
ctdb_req_dmaster_print(struct ctdb_req_dmaster * c,FILE * fp)421 static void ctdb_req_dmaster_print(struct ctdb_req_dmaster *c, FILE *fp)
422 {
423 	fprintf(fp, "Data\n");
424 	fprintf(fp, "  db:0x%"PRIx32" rsn:0x%"PRIx64" dmaster:%u\n",
425 		c->db_id, c->rsn, c->dmaster);
426 	fprintf(fp, "  key:");
427 	tdb_data_print(c->key, fp);
428 	fprintf(fp, "\n");
429 	fprintf(fp, "  data:");
430 	tdb_data_print(c->data, fp);
431 	fprintf(fp, "\n");
432 }
433 
ctdb_reply_dmaster_print(struct ctdb_reply_dmaster * c,FILE * fp)434 static void ctdb_reply_dmaster_print(struct ctdb_reply_dmaster *c, FILE *fp)
435 {
436 	fprintf(fp, "Data\n");
437 	fprintf(fp, "  db:0x%"PRIx32" rsn:0x%"PRIx64"\n", c->db_id, c->rsn);
438 	fprintf(fp, "  key:");
439 	tdb_data_print(c->key, fp);
440 	fprintf(fp, "\n");
441 	fprintf(fp, "  data:");
442 	tdb_data_print(c->data, fp);
443 	fprintf(fp, "\n");
444 }
445 
ctdb_reply_error_print(struct ctdb_reply_error * c,FILE * fp)446 static void ctdb_reply_error_print(struct ctdb_reply_error *c, FILE *fp)
447 {
448 	fprintf(fp, "Data\n");
449 	fprintf(fp, "  status:%d\n", c->status);
450 	if (c->status != 0) {
451 		fprintf(fp, "  msg:");
452 		tdb_data_print(c->msg, fp);
453 		fprintf(fp, "\n");
454 	}
455 }
456 
ctdb_req_message_data_print(struct ctdb_req_message_data * c,FILE * fp)457 static void ctdb_req_message_data_print(struct ctdb_req_message_data *c,
458 					FILE *fp)
459 {
460 	fprintf(fp, "Data\n");
461 	fprintf(fp, "  srvid:");
462 	ctdb_srvid_print(c->srvid, fp);
463 	fprintf(fp, "\n");
464 	fprintf(fp, "  data:");
465 	tdb_data_print(c->data, fp);
466 	fprintf(fp, "\n");
467 }
468 
ctdb_req_control_print(struct ctdb_req_control * c,FILE * fp)469 static void ctdb_req_control_print(struct ctdb_req_control *c, FILE *fp)
470 {
471 	fprintf(fp, "Data\n");
472 	fprintf(fp, "  ");
473 	ctdb_opcode_print(c->opcode, fp);
474 	fprintf(fp, " srvid:");
475 	ctdb_srvid_print(c->srvid, fp);
476 	fprintf(fp, " client_id:0x%"PRIx32" ", c->client_id);
477 	ctdb_control_flags_print(c->flags, fp);
478 	fprintf(fp, "\n");
479 }
480 
ctdb_reply_control_print(struct ctdb_reply_control * c,FILE * fp)481 static void ctdb_reply_control_print(struct ctdb_reply_control *c, FILE *fp)
482 {
483 	fprintf(fp, "Data\n");
484 	fprintf(fp, "  status:%d ", c->status);
485 	if (c->errmsg != NULL) {
486 		fprintf(fp, "errmsg: %s", c->errmsg);
487 	}
488 	fprintf(fp, "\n");
489 }
490 
ctdb_req_keepalive_print(struct ctdb_req_keepalive * c,FILE * fp)491 static void ctdb_req_keepalive_print(struct ctdb_req_keepalive *c, FILE *fp)
492 {
493 	fprintf(fp, "Data\n");
494 	fprintf(fp, "  version:0x%"PRIx32, c->version);
495 	fprintf(fp, "  uptime:%"PRIu32, c->uptime);
496 	fprintf(fp, "\n");
497 }
498 
ctdb_req_tunnel_print(struct ctdb_req_tunnel * c,FILE * fp)499 static void ctdb_req_tunnel_print(struct ctdb_req_tunnel *c, FILE *fp)
500 {
501 	fprintf(fp, "Data\n");
502 	fprintf(fp, "  tunnel_id:");
503 	ctdb_tunnel_id_print(c->tunnel_id, fp);
504 	ctdb_tunnel_flags_print(c->flags, fp);
505 	tdb_data_print(c->data, fp);
506 	fprintf(fp, "\n");
507 }
508 
509 /*
510  * Parse routines
511  */
512 
ctdb_req_call_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)513 static void ctdb_req_call_parse(uint8_t *buf, size_t buflen, FILE *fp,
514 				TALLOC_CTX *mem_ctx)
515 {
516 	struct ctdb_req_call c;
517 	int ret;
518 
519 	ret = ctdb_req_call_pull(buf, buflen, NULL, mem_ctx, &c);
520 	if (ret != 0) {
521 		fprintf(fp, "Failed to parse CTDB_REQ_CALL\n");
522 		return;
523 	}
524 
525 	ctdb_req_call_print(&c, fp);
526 }
527 
ctdb_reply_call_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)528 static void ctdb_reply_call_parse(uint8_t *buf, size_t buflen, FILE *fp,
529 				  TALLOC_CTX *mem_ctx)
530 {
531 	struct ctdb_reply_call c;
532 	int ret;
533 
534 	ret = ctdb_reply_call_pull(buf, buflen, NULL, mem_ctx, &c);
535 	if (ret != 0) {
536 		fprintf(fp, "Failed to parse CTDB_REPLY_CALL\n");
537 		return;
538 	}
539 
540 	ctdb_reply_call_print(&c, fp);
541 }
542 
ctdb_req_dmaster_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)543 static void ctdb_req_dmaster_parse(uint8_t *buf, size_t buflen, FILE *fp,
544 				   TALLOC_CTX *mem_ctx)
545 {
546 	struct ctdb_req_dmaster c;
547 	int ret;
548 
549 	ret = ctdb_req_dmaster_pull(buf, buflen, NULL, mem_ctx, &c);
550 	if (ret != 0) {
551 		fprintf(fp, "Failed to parse CTDB_REQ_DMASTER\n");
552 		return;
553 	}
554 
555 	ctdb_req_dmaster_print(&c, fp);
556 }
557 
ctdb_reply_dmaster_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)558 static void ctdb_reply_dmaster_parse(uint8_t *buf, size_t buflen, FILE *fp,
559 				     TALLOC_CTX *mem_ctx)
560 {
561 	struct ctdb_reply_dmaster c;
562 	int ret;
563 
564 	ret = ctdb_reply_dmaster_pull(buf, buflen, NULL, mem_ctx, &c);
565 	if (ret != 0) {
566 		fprintf(fp, "Failed to parse CTDB_REPLY_DMASTER\n");
567 		return;
568 	}
569 
570 	ctdb_reply_dmaster_print(&c, fp);
571 }
572 
ctdb_reply_error_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)573 static void ctdb_reply_error_parse(uint8_t *buf, size_t buflen, FILE *fp,
574 				   TALLOC_CTX *mem_ctx)
575 {
576 	struct ctdb_reply_error c;
577 	int ret;
578 
579 	ret = ctdb_reply_error_pull(buf, buflen, NULL, mem_ctx, &c);
580 	if (ret != 0) {
581 		fprintf(fp, "Failed to parse CTDB_REPLY_ERROR\n");
582 		return;
583 	}
584 
585 	ctdb_reply_error_print(&c, fp);
586 }
587 
ctdb_req_message_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)588 static void ctdb_req_message_parse(uint8_t *buf, size_t buflen, FILE *fp,
589 				   TALLOC_CTX *mem_ctx)
590 {
591 	struct ctdb_req_message_data c;
592 	int ret;
593 
594 	ret = ctdb_req_message_data_pull(buf, buflen, NULL, mem_ctx, &c);
595 	if (ret != 0) {
596 		fprintf(fp, "Failed to parse CTDB_REQ_MESSAGE\n");
597 		return;
598 	}
599 
600 	ctdb_req_message_data_print(&c, fp);
601 }
602 
ctdb_req_control_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)603 static void ctdb_req_control_parse(uint8_t *buf, size_t buflen, FILE *fp,
604 				   TALLOC_CTX *mem_ctx)
605 {
606 	struct ctdb_req_control c;
607 	int ret;
608 
609 	ret = ctdb_req_control_pull(buf, buflen, NULL, mem_ctx, &c);
610 	if (ret != 0) {
611 		fprintf(fp, "Failed to parse CTDB_REQ_CONTROL\n");
612 		return;
613 	}
614 
615 	ctdb_req_control_print(&c, fp);
616 }
617 
ctdb_reply_control_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)618 static void ctdb_reply_control_parse(uint8_t *buf, size_t buflen, FILE *fp,
619 				     TALLOC_CTX *mem_ctx)
620 {
621 	struct ctdb_reply_control c;
622 	int ret;
623 
624 	ret = ctdb_reply_control_pull(buf, buflen, -1, NULL, mem_ctx, &c);
625 	if (ret != 0) {
626 		fprintf(fp, "Failed to parse CTDB_REPLY_CONTROL\n");
627 		return;
628 	}
629 
630 	ctdb_reply_control_print(&c, fp);
631 }
632 
ctdb_req_keepalive_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)633 static void ctdb_req_keepalive_parse(uint8_t *buf, size_t buflen, FILE *fp,
634 				     TALLOC_CTX *mem_ctx)
635 {
636 	struct ctdb_req_keepalive c;
637 	int ret;
638 
639 	ret = ctdb_req_keepalive_pull(buf, buflen, NULL, mem_ctx, &c);
640 	if (ret != 0) {
641 		fprintf(fp, "Failed to parse CTDB_REQ_KEEPALIVE\n");
642 		return;
643 	}
644 
645 	ctdb_req_keepalive_print(&c, fp);
646 }
647 
ctdb_req_tunnel_parse(uint8_t * buf,size_t buflen,FILE * fp,TALLOC_CTX * mem_ctx)648 static void ctdb_req_tunnel_parse(uint8_t *buf, size_t buflen, FILE *fp,
649 				  TALLOC_CTX *mem_ctx)
650 {
651 	struct ctdb_req_tunnel c;
652 	int ret;
653 
654 	ret = ctdb_req_tunnel_pull(buf, buflen, NULL, mem_ctx, &c);
655 	if (ret != 0) {
656 		fprintf(fp, "Failed to parse CTDB_REQ_TUNNEL\n");
657 		return;
658 	}
659 
660 	ctdb_req_tunnel_print(&c, fp);
661 }
662 
663 /*
664  * Packet print
665  */
666 
ctdb_packet_print(uint8_t * buf,size_t buflen,FILE * fp)667 void ctdb_packet_print(uint8_t *buf, size_t buflen, FILE *fp)
668 {
669 	TALLOC_CTX *mem_ctx = talloc_new(NULL);
670 	struct ctdb_req_header h;
671 	size_t np;
672 	int ret;
673 
674 	fprintf(fp, "Buffer len:%zu\n", buflen);
675 
676 	ret = ctdb_req_header_pull(buf, buflen, &h, &np);
677 	if (ret != 0) {
678 		fprintf(fp, "Failed to parse ctdb packet header\n");
679 		return;
680 	}
681 
682 	ctdb_req_header_print(&h, fp);
683 
684 	if (h.length > buflen) {
685 		fprintf(fp, "Packet length mismatch\n");
686 	}
687 
688 	ret = ctdb_req_header_verify(&h, 0);
689 	if (ret != 0) {
690 		fprintf(fp, "Invalid ctdb packet header\n");
691 		return;
692 	}
693 
694 	switch (h.operation) {
695 		case CTDB_REQ_CALL:
696 			ctdb_req_call_parse(buf, buflen, fp, mem_ctx);
697 			break;
698 
699 		case CTDB_REPLY_CALL:
700 			ctdb_reply_call_parse(buf, buflen, fp, mem_ctx);
701 			break;
702 
703 		case CTDB_REQ_DMASTER:
704 			ctdb_req_dmaster_parse(buf, buflen, fp, mem_ctx);
705 			break;
706 
707 		case CTDB_REPLY_DMASTER:
708 			ctdb_reply_dmaster_parse(buf, buflen, fp, mem_ctx);
709 			break;
710 
711 		case CTDB_REPLY_ERROR:
712 			ctdb_reply_error_parse(buf, buflen, fp, mem_ctx);
713 			break;
714 
715 		case CTDB_REQ_MESSAGE:
716 			ctdb_req_message_parse(buf, buflen, fp, mem_ctx);
717 			break;
718 
719 		case CTDB_REQ_CONTROL:
720 			ctdb_req_control_parse(buf, buflen, fp, mem_ctx);
721 			break;
722 
723 		case CTDB_REPLY_CONTROL:
724 			ctdb_reply_control_parse(buf, buflen, fp, mem_ctx);
725 			break;
726 
727 		case CTDB_REQ_KEEPALIVE:
728 			ctdb_req_keepalive_parse(buf, buflen, fp, mem_ctx);
729 			break;
730 
731 		case CTDB_REQ_TUNNEL:
732 			ctdb_req_tunnel_parse(buf, buflen, fp, mem_ctx);
733 			break;
734 
735 		default:
736 			fprintf(fp, "Invalid ctdb operation\n");
737 			break;
738 	}
739 
740 	talloc_free(mem_ctx);
741 }
742