summaryrefslogtreecommitdiff
path: root/ctdb/protocol
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2015-04-14 17:20:05 +1000
committerAmitay Isaacs <amitay@samba.org>2015-10-07 14:53:29 +0200
commit34a6c99776cd50dfa4f6c2e02a6439d6d59b045e (patch)
tree511b7cbc5eb91c3b71724924644abc251ec066c3 /ctdb/protocol
parent8b45badfdaa8d9b618d551fcbbe8a2f7d680c4f9 (diff)
downloadsamba-34a6c99776cd50dfa4f6c2e02a6439d6d59b045e.tar.gz
ctdb-protocol: Add ctdb protocol serialization routines
Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
Diffstat (limited to 'ctdb/protocol')
-rw-r--r--ctdb/protocol/protocol.h1002
-rw-r--r--ctdb/protocol/protocol_api.h643
-rw-r--r--ctdb/protocol/protocol_call.c446
-rw-r--r--ctdb/protocol/protocol_client.c2370
-rw-r--r--ctdb/protocol/protocol_control.c2007
-rw-r--r--ctdb/protocol/protocol_header.c73
-rw-r--r--ctdb/protocol/protocol_message.c383
-rw-r--r--ctdb/protocol/protocol_packet.c44
-rw-r--r--ctdb/protocol/protocol_private.h274
-rw-r--r--ctdb/protocol/protocol_types.c2519
-rw-r--r--ctdb/protocol/protocol_util.c114
11 files changed, 9875 insertions, 0 deletions
diff --git a/ctdb/protocol/protocol.h b/ctdb/protocol/protocol.h
new file mode 100644
index 00000000000..805fdd161b2
--- /dev/null
+++ b/ctdb/protocol/protocol.h
@@ -0,0 +1,1002 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CTDB_PROTOCOL_H__
+#define __CTDB_PROTOCOL_H__
+
+#define CTDB_MAGIC 0x43544442 /* CTDB */
+#define CTDB_PROTOCOL 1
+
+enum ctdb_operation {
+ CTDB_REQ_CALL = 0,
+ CTDB_REPLY_CALL = 1,
+ CTDB_REQ_DMASTER = 2,
+ CTDB_REPLY_DMASTER = 3,
+ CTDB_REPLY_ERROR = 4,
+ CTDB_REQ_MESSAGE = 5,
+ /* #6 removed */
+ CTDB_REQ_CONTROL = 7,
+ CTDB_REPLY_CONTROL = 8,
+ CTDB_REQ_KEEPALIVE = 9,
+};
+
+/* used on the domain socket, send a pdu to the local daemon */
+#define CTDB_CURRENT_NODE 0xF0000001
+/* send a broadcast to all nodes in the cluster, active or not */
+#define CTDB_BROADCAST_ALL 0xF0000002
+/* send a broadcast to all nodes in the current vnn map */
+#define CTDB_BROADCAST_VNNMAP 0xF0000003
+/* send a broadcast to all connected nodes */
+#define CTDB_BROADCAST_CONNECTED 0xF0000004
+/* send a broadcast to selected connected nodes */
+#define CTDB_MULTICAST 0xF0000005
+
+#define CTDB_UNKNOWN_PNN 0xFFFFFFFF
+
+/* the key used to store persistent db sequence number */
+#define CTDB_DB_SEQNUM_KEY "__db_sequence_number__"
+
+struct ctdb_req_header {
+ uint32_t length;
+ uint32_t ctdb_magic;
+ uint32_t ctdb_version;
+ uint32_t generation;
+ uint32_t operation;
+ uint32_t destnode;
+ uint32_t srcnode;
+ uint32_t reqid;
+};
+
+struct ctdb_req_call {
+ uint32_t flags;
+ uint32_t db_id;
+ uint32_t callid;
+ uint32_t hopcount;
+ TDB_DATA key;
+ TDB_DATA calldata;
+};
+
+struct ctdb_reply_call {
+ int32_t status;
+ TDB_DATA data;
+};
+
+struct ctdb_reply_error {
+ int32_t status;
+ TDB_DATA msg;
+};
+
+struct ctdb_req_dmaster {
+ uint32_t db_id;
+ uint64_t rsn;
+ uint32_t dmaster;
+ TDB_DATA key;
+ TDB_DATA data;
+};
+
+struct ctdb_reply_dmaster {
+ uint32_t db_id;
+ uint64_t rsn;
+ TDB_DATA key;
+ TDB_DATA data;
+};
+
+#define CTDB_NULL_FUNC 0xFF000001
+#define CTDB_FETCH_FUNC 0xFF000002
+#define CTDB_FETCH_WITH_HEADER_FUNC 0xFF000003
+
+struct ctdb_call {
+ int call_id;
+ TDB_DATA key;
+ TDB_DATA call_data;
+ TDB_DATA reply_data;
+ uint32_t status;
+#define CTDB_IMMEDIATE_MIGRATION 0x00000001
+#define CTDB_CALL_FLAG_VACUUM_MIGRATION 0x00000002
+#define CTDB_WANT_READONLY 0x00000004
+ uint32_t flags;
+};
+
+/* SRVID to catch all messages */
+#define CTDB_SRVID_ALL (~(uint64_t)0)
+
+/* SRVID prefix used by CTDB */
+#define CTDB_SRVID_PREFIX 0xF000000000000000LL
+
+/* SRVID to inform of election data */
+#define CTDB_SRVID_ELECTION 0xF100000000000000LL
+
+/* SRVID to inform clients that the cluster has been reconfigured */
+#define CTDB_SRVID_RECONFIGURE 0xF200000000000000LL
+
+/* SRVID to inform clients an IP address has been released */
+#define CTDB_SRVID_RELEASE_IP 0xF300000000000000LL
+
+/* SRVID to inform clients that an IP address has been taken over */
+#define CTDB_SRVID_TAKE_IP 0xF301000000000000LL
+
+/* SRVID to inform recovery daemon of the node flags */
+#define CTDB_SRVID_SET_NODE_FLAGS 0xF400000000000000LL
+
+/* SRVID to inform recovery daemon to update public ip assignment */
+#define CTDB_SRVID_RECD_UPDATE_IP 0xF500000000000000LL
+
+/* SRVID to inform recovery daemon to migrate a set of records */
+#define CTDB_SRVID_VACUUM_FETCH 0xF700000000000000LL
+
+/* SRVID to inform recovery daemon to detach a database */
+#define CTDB_SRVID_DETACH_DATABASE 0xF701000000000000LL
+
+/* SRVID to inform recovery daemon to dump talloc memdump to the log */
+#define CTDB_SRVID_MEM_DUMP 0xF800000000000000LL
+
+/* SRVID to inform recovery daemon to send logs */
+#define CTDB_SRVID_GETLOG 0xF801000000000000LL
+
+/* SRVID to inform recovery daemon to clear logs */
+#define CTDB_SRVID_CLEARLOG 0xF802000000000000LL
+
+/* SRVID to inform recovery daemon to push the node flags to other nodes */
+#define CTDB_SRVID_PUSH_NODE_FLAGS 0xF900000000000000LL
+
+/* SRVID to inform recovery daemon to reload the nodes file */
+#define CTDB_SRVID_RELOAD_NODES 0xFA00000000000000LL
+
+/* SRVID to inform recovery daemon to perform a takeover run */
+#define CTDB_SRVID_TAKEOVER_RUN 0xFB00000000000000LL
+
+/* SRVID to inform recovery daemon to rebalance ips for a node. */
+#define CTDB_SRVID_REBALANCE_NODE 0xFB01000000000000LL
+
+/* SRVID to inform recovery daemon to stop takeover runs from occurring */
+#define CTDB_SRVID_DISABLE_TAKEOVER_RUNS 0xFB03000000000000LL
+
+/* SRVID to inform recovery daemon to stop recoveries from occurring */
+#define CTDB_SRVID_DISABLE_RECOVERIES 0xFB04000000000000LL
+
+/* SRVID to inform recovery daemon to disable the public ip checks */
+#define CTDB_SRVID_DISABLE_IP_CHECK 0xFC00000000000000LL
+
+/* SRVID to inform recovery daemon of ipreallocate resposnes from ctdbd */
+#define CTDB_SRVID_TAKEOVER_RUN_RESPONSE 0xFD00000000000000LL
+
+/* A range of ports reserved for registering a PID (top 8 bits)
+ * All ports matching the 8 top bits are reserved for exclusive use by
+ * registering a SRVID that matches the process-id of the requesting process
+ */
+#define CTDB_SRVID_PID_RANGE 0x0000000000000000LL
+
+/* A range of ports reserved for samba (top 8 bits)
+ * All ports matching the 8 top bits are reserved for exclusive use by
+ * CIFS server
+ */
+#define CTDB_SRVID_SAMBA_NOTIFY 0xFE00000000000000LL
+#define CTDB_SRVID_SAMBA_RANGE 0xFE00000000000000LL
+
+/* A range of ports reserved for a CTDB NFS server (top 8 bits)
+ * All ports matching the 8 top bits are reserved for exclusive use by
+ * NFS server
+ */
+#define CTDB_SRVID_NFSD_RANGE 0xEE00000000000000LL
+
+/* A range of ports reserved for a CTDB ISCSI server (top 8 bits)
+ * All ports matching the 8 top bits are reserved for exclusive use by
+ * ISCSI server
+ */
+#define CTDB_SRVID_ISCSID_RANGE 0xDE00000000000000LL
+
+/* A range of ports reserved for testing (top 8 bits)
+ * All ports matching the 8 top bits are reserved for exclusive use by
+ * test applications
+ */
+#define CTDB_SRVID_TEST_RANGE 0xCE00000000000000LL
+
+/* Range of ports reserved for traversals */
+#define CTDB_SRVID_TRAVERSE_RANGE 0xBE00000000000000LL
+
+
+enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
+ CTDB_CONTROL_STATISTICS = 1,
+ /* #2 removed */
+ CTDB_CONTROL_PING = 3,
+ CTDB_CONTROL_GETDBPATH = 4,
+ CTDB_CONTROL_GETVNNMAP = 5,
+ CTDB_CONTROL_SETVNNMAP = 6,
+ CTDB_CONTROL_GET_DEBUG = 7,
+ CTDB_CONTROL_SET_DEBUG = 8,
+ CTDB_CONTROL_GET_DBMAP = 9,
+ CTDB_CONTROL_GET_NODEMAPv4 = 10, /* obsolete */
+ CTDB_CONTROL_SET_DMASTER = 11, /* obsolete */
+ /* #12 removed */
+ CTDB_CONTROL_PULL_DB = 13,
+ CTDB_CONTROL_PUSH_DB = 14,
+ CTDB_CONTROL_GET_RECMODE = 15,
+ CTDB_CONTROL_SET_RECMODE = 16,
+ CTDB_CONTROL_STATISTICS_RESET = 17,
+ CTDB_CONTROL_DB_ATTACH = 18,
+ CTDB_CONTROL_SET_CALL = 19, /* obsolete */
+ CTDB_CONTROL_TRAVERSE_START = 20,
+ CTDB_CONTROL_TRAVERSE_ALL = 21,
+ CTDB_CONTROL_TRAVERSE_DATA = 22,
+ CTDB_CONTROL_REGISTER_SRVID = 23,
+ CTDB_CONTROL_DEREGISTER_SRVID = 24,
+ CTDB_CONTROL_GET_DBNAME = 25,
+ CTDB_CONTROL_ENABLE_SEQNUM = 26,
+ CTDB_CONTROL_UPDATE_SEQNUM = 27,
+ /* #28 removed */
+ CTDB_CONTROL_DUMP_MEMORY = 29,
+ CTDB_CONTROL_GET_PID = 30,
+ CTDB_CONTROL_GET_RECMASTER = 31,
+ CTDB_CONTROL_SET_RECMASTER = 32,
+ CTDB_CONTROL_FREEZE = 33,
+ CTDB_CONTROL_THAW = 34,
+ CTDB_CONTROL_GET_PNN = 35,
+ CTDB_CONTROL_SHUTDOWN = 36,
+ CTDB_CONTROL_GET_MONMODE = 37,
+ /* #38 removed */
+ /* #39 removed */
+ /* #40 removed */
+ /* #41 removed */
+ CTDB_CONTROL_TAKEOVER_IPv4 = 42, /* obsolete */
+ CTDB_CONTROL_RELEASE_IPv4 = 43, /* obsolete */
+ CTDB_CONTROL_TCP_CLIENT = 44,
+ CTDB_CONTROL_TCP_ADD = 45,
+ CTDB_CONTROL_TCP_REMOVE = 46,
+ CTDB_CONTROL_STARTUP = 47,
+ CTDB_CONTROL_SET_TUNABLE = 48,
+ CTDB_CONTROL_GET_TUNABLE = 49,
+ CTDB_CONTROL_LIST_TUNABLES = 50,
+ CTDB_CONTROL_GET_PUBLIC_IPSv4 = 51, /* obsolete */
+ CTDB_CONTROL_MODIFY_FLAGS = 52,
+ CTDB_CONTROL_GET_ALL_TUNABLES = 53,
+ CTDB_CONTROL_KILL_TCP = 54,
+ CTDB_CONTROL_GET_TCP_TICKLE_LIST = 55,
+ CTDB_CONTROL_SET_TCP_TICKLE_LIST = 56,
+ CTDB_CONTROL_REGISTER_SERVER_ID = 57,
+ CTDB_CONTROL_UNREGISTER_SERVER_ID = 58,
+ CTDB_CONTROL_CHECK_SERVER_ID = 59,
+ CTDB_CONTROL_GET_SERVER_ID_LIST = 60,
+ CTDB_CONTROL_DB_ATTACH_PERSISTENT = 61,
+ CTDB_CONTROL_PERSISTENT_STORE = 62, /* obsolete */
+ CTDB_CONTROL_UPDATE_RECORD = 63,
+ CTDB_CONTROL_SEND_GRATUITOUS_ARP = 64,
+ CTDB_CONTROL_TRANSACTION_START = 65,
+ CTDB_CONTROL_TRANSACTION_COMMIT = 66,
+ CTDB_CONTROL_WIPE_DATABASE = 67,
+ /* #68 removed */
+ CTDB_CONTROL_UPTIME = 69,
+ CTDB_CONTROL_START_RECOVERY = 70,
+ CTDB_CONTROL_END_RECOVERY = 71,
+ CTDB_CONTROL_RELOAD_NODES_FILE = 72,
+ /* #73 removed */
+ CTDB_CONTROL_TRY_DELETE_RECORDS = 74,
+ CTDB_CONTROL_ENABLE_MONITOR = 75,
+ CTDB_CONTROL_DISABLE_MONITOR = 76,
+ CTDB_CONTROL_ADD_PUBLIC_IP = 77,
+ CTDB_CONTROL_DEL_PUBLIC_IP = 78,
+ CTDB_CONTROL_RUN_EVENTSCRIPTS = 79,
+ CTDB_CONTROL_GET_CAPABILITIES = 80,
+ CTDB_CONTROL_START_PERSISTENT_UPDATE = 81, /* obsolete */
+ CTDB_CONTROL_CANCEL_PERSISTENT_UPDATE= 82, /* obsolete */
+ CTDB_CONTROL_TRANS2_COMMIT = 83, /* obsolete */
+ CTDB_CONTROL_TRANS2_FINISHED = 84, /* obsolete */
+ CTDB_CONTROL_TRANS2_ERROR = 85, /* obsolete */
+ CTDB_CONTROL_TRANS2_COMMIT_RETRY = 86, /* obsolete */
+ CTDB_CONTROL_RECD_PING = 87,
+ CTDB_CONTROL_RELEASE_IP = 88,
+ CTDB_CONTROL_TAKEOVER_IP = 89,
+ CTDB_CONTROL_GET_PUBLIC_IPS = 90,
+ CTDB_CONTROL_GET_NODEMAP = 91,
+ /* missing */
+ CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS = 96,
+ CTDB_CONTROL_TRAVERSE_KILL = 97,
+ CTDB_CONTROL_RECD_RECLOCK_LATENCY = 98,
+ CTDB_CONTROL_GET_RECLOCK_FILE = 99,
+ CTDB_CONTROL_SET_RECLOCK_FILE = 100,
+ CTDB_CONTROL_STOP_NODE = 101,
+ CTDB_CONTROL_CONTINUE_NODE = 102,
+ CTDB_CONTROL_SET_NATGWSTATE = 103,
+ CTDB_CONTROL_SET_LMASTERROLE = 104,
+ CTDB_CONTROL_SET_RECMASTERROLE = 105,
+ CTDB_CONTROL_ENABLE_SCRIPT = 107,
+ CTDB_CONTROL_DISABLE_SCRIPT = 108,
+ CTDB_CONTROL_SET_BAN_STATE = 109,
+ CTDB_CONTROL_GET_BAN_STATE = 110,
+ CTDB_CONTROL_SET_DB_PRIORITY = 111,
+ CTDB_CONTROL_GET_DB_PRIORITY = 112,
+ CTDB_CONTROL_TRANSACTION_CANCEL = 113,
+ CTDB_CONTROL_REGISTER_NOTIFY = 114,
+ CTDB_CONTROL_DEREGISTER_NOTIFY = 115,
+ CTDB_CONTROL_TRANS2_ACTIVE = 116, /* obsolete */
+ CTDB_CONTROL_GET_LOG = 117, /* obsolete */
+ CTDB_CONTROL_CLEAR_LOG = 118, /* obsolete */
+ CTDB_CONTROL_TRANS3_COMMIT = 119,
+ CTDB_CONTROL_GET_DB_SEQNUM = 120,
+ CTDB_CONTROL_DB_SET_HEALTHY = 121,
+ CTDB_CONTROL_DB_GET_HEALTH = 122,
+ CTDB_CONTROL_GET_PUBLIC_IP_INFO = 123,
+ CTDB_CONTROL_GET_IFACES = 124,
+ CTDB_CONTROL_SET_IFACE_LINK_STATE = 125,
+ CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE = 126,
+ CTDB_CONTROL_GET_STAT_HISTORY = 127,
+ CTDB_CONTROL_SCHEDULE_FOR_DELETION = 128,
+ CTDB_CONTROL_SET_DB_READONLY = 129,
+ CTDB_CONTROL_CHECK_SRVIDS = 130,
+ CTDB_CONTROL_TRAVERSE_START_EXT = 131,
+ CTDB_CONTROL_GET_DB_STATISTICS = 132,
+ CTDB_CONTROL_SET_DB_STICKY = 133,
+ CTDB_CONTROL_RELOAD_PUBLIC_IPS = 134,
+ CTDB_CONTROL_TRAVERSE_ALL_EXT = 135,
+ CTDB_CONTROL_RECEIVE_RECORDS = 136,
+ CTDB_CONTROL_IPREALLOCATED = 137,
+ CTDB_CONTROL_GET_RUNSTATE = 138,
+ CTDB_CONTROL_DB_DETACH = 139,
+ CTDB_CONTROL_GET_NODES_FILE = 140,
+};
+
+#define CTDB_MONITORING_ACTIVE 0
+#define CTDB_MONITORING_DISABLED 1
+
+#define MAX_COUNT_BUCKETS 16
+#define MAX_HOT_KEYS 10
+
+struct ctdb_latency_counter {
+ int num;
+ double min;
+ double max;
+ double total;
+};
+
+struct ctdb_statistics {
+ uint32_t num_clients;
+ uint32_t frozen;
+ uint32_t recovering;
+ uint32_t client_packets_sent;
+ uint32_t client_packets_recv;
+ uint32_t node_packets_sent;
+ uint32_t node_packets_recv;
+ uint32_t keepalive_packets_sent;
+ uint32_t keepalive_packets_recv;
+ struct {
+ uint32_t req_call;
+ uint32_t reply_call;
+ uint32_t req_dmaster;
+ uint32_t reply_dmaster;
+ uint32_t reply_error;
+ uint32_t req_message;
+ uint32_t req_control;
+ uint32_t reply_control;
+ } node;
+ struct {
+ uint32_t req_call;
+ uint32_t req_message;
+ uint32_t req_control;
+ } client;
+ struct {
+ uint32_t call;
+ uint32_t control;
+ uint32_t traverse;
+ } timeouts;
+ struct {
+ struct ctdb_latency_counter ctdbd;
+ struct ctdb_latency_counter recd;
+ } reclock;
+ struct {
+ uint32_t num_calls;
+ uint32_t num_current;
+ uint32_t num_pending;
+ uint32_t num_failed;
+ struct ctdb_latency_counter latency;
+ uint32_t buckets[MAX_COUNT_BUCKETS];
+ } locks;
+ uint32_t total_calls;
+ uint32_t pending_calls;
+ uint32_t childwrite_calls;
+ uint32_t pending_childwrite_calls;
+ uint32_t memory_used;
+ uint32_t __last_counter; /* hack */
+ uint32_t max_hop_count;
+ uint32_t hop_count_bucket[MAX_COUNT_BUCKETS];
+ struct ctdb_latency_counter call_latency;
+ struct ctdb_latency_counter childwrite_latency;
+ uint32_t num_recoveries;
+ struct timeval statistics_start_time;
+ struct timeval statistics_current_time;
+ uint32_t total_ro_delegations;
+ uint32_t total_ro_revokes;
+};
+
+#define INVALID_GENERATION 1
+/* table that contains the mapping between a hash value and lmaster
+ */
+struct ctdb_vnn_map {
+ uint32_t generation;
+ uint32_t size;
+ uint32_t *map;
+};
+
+struct ctdb_dbid {
+ uint32_t db_id;
+#define CTDB_DB_FLAGS_PERSISTENT 0x01
+#define CTDB_DB_FLAGS_READONLY 0x02
+#define CTDB_DB_FLAGS_STICKY 0x04
+ uint8_t flags;
+};
+
+struct ctdb_dbid_map {
+ uint32_t num;
+ struct ctdb_dbid *dbs;
+};
+
+struct ctdb_pulldb {
+ uint32_t db_id;
+#define CTDB_LMASTER_ANY 0xffffffff
+ uint32_t lmaster;
+};
+
+#define CTDB_RECOVERY_NORMAL 0
+#define CTDB_RECOVERY_ACTIVE 1
+
+#define CTDB_NUM_DB_PRIORITIES 3
+
+/*
+ the extended header for records in the ltdb
+*/
+struct ctdb_ltdb_header {
+ uint64_t rsn;
+ uint32_t dmaster;
+ uint32_t reserved1;
+#define CTDB_REC_FLAG_DEFAULT 0x00000000
+#define CTDB_REC_FLAG_MIGRATED_WITH_DATA 0x00010000
+#define CTDB_REC_FLAG_VACUUM_MIGRATED 0x00020000
+#define CTDB_REC_FLAG_AUTOMATIC 0x00040000
+#define CTDB_REC_RO_HAVE_DELEGATIONS 0x01000000
+#define CTDB_REC_RO_HAVE_READONLY 0x02000000
+#define CTDB_REC_RO_REVOKING_READONLY 0x04000000
+#define CTDB_REC_RO_REVOKE_COMPLETE 0x08000000
+#define CTDB_REC_RO_FLAGS (CTDB_REC_RO_HAVE_DELEGATIONS|\
+ CTDB_REC_RO_HAVE_READONLY|\
+ CTDB_REC_RO_REVOKING_READONLY|\
+ CTDB_REC_RO_REVOKE_COMPLETE)
+ uint32_t flags;
+};
+
+struct ctdb_rec_data {
+ uint32_t reqid;
+ struct ctdb_ltdb_header *header;
+ TDB_DATA key, data;
+};
+
+struct ctdb_rec_buffer {
+ uint32_t db_id;
+ uint32_t count;
+ uint8_t *buf;
+ size_t buflen;
+};
+
+typedef int (*ctdb_rec_parser_func_t)(uint32_t reqid,
+ struct ctdb_ltdb_header *header,
+ TDB_DATA key, TDB_DATA data,
+ void *private_data);
+
+struct ctdb_traverse_start {
+ uint32_t db_id;
+ uint32_t reqid;
+ uint64_t srvid;
+};
+
+struct ctdb_traverse_all {
+ uint32_t db_id;
+ uint32_t reqid;
+ uint32_t pnn;
+ uint32_t client_reqid;
+ uint64_t srvid;
+};
+
+struct ctdb_traverse_start_ext {
+ uint32_t db_id;
+ uint32_t reqid;
+ uint64_t srvid;
+ bool withemptyrecords;
+};
+
+struct ctdb_traverse_all_ext {
+ uint32_t db_id;
+ uint32_t reqid;
+ uint32_t pnn;
+ uint32_t client_reqid;
+ uint64_t srvid;
+ bool withemptyrecords;
+};
+
+typedef union {
+ struct sockaddr sa;
+ struct sockaddr_in ip;
+ struct sockaddr_in6 ip6;
+} ctdb_sock_addr;
+
+struct ctdb_connection {
+ ctdb_sock_addr src;
+ ctdb_sock_addr dst;
+};
+
+struct ctdb_tunable {
+ const char *name;
+ uint32_t value;
+};
+
+struct ctdb_var_list {
+ int count;
+ const char **var;
+};
+
+struct ctdb_node_flag_change {
+ uint32_t pnn;
+ uint32_t new_flags;
+ uint32_t old_flags;
+};
+
+/* all tunable variables go in here */
+struct ctdb_tunable_list {
+ uint32_t max_redirect_count;
+ uint32_t seqnum_interval; /* unit is ms */
+ uint32_t control_timeout;
+ uint32_t traverse_timeout;
+ uint32_t keepalive_interval;
+ uint32_t keepalive_limit;
+ uint32_t recover_timeout;
+ uint32_t recover_interval;
+ uint32_t election_timeout;
+ uint32_t takeover_timeout;
+ uint32_t monitor_interval;
+ uint32_t tickle_update_interval;
+ uint32_t script_timeout;
+ uint32_t script_timeout_count; /* allow dodgy scripts to hang this many times in a row before we mark the node unhealthy */
+ uint32_t script_unhealthy_on_timeout; /* obsolete */
+ uint32_t recovery_grace_period;
+ uint32_t recovery_ban_period;
+ uint32_t database_hash_size;
+ uint32_t database_max_dead;
+ uint32_t rerecovery_timeout;
+ uint32_t enable_bans;
+ uint32_t deterministic_public_ips;
+ uint32_t reclock_ping_period;
+ uint32_t no_ip_failback;
+ uint32_t disable_ip_failover;
+ uint32_t verbose_memory_names;
+ uint32_t recd_ping_timeout;
+ uint32_t recd_ping_failcount;
+ uint32_t log_latency_ms;
+ uint32_t reclock_latency_ms;
+ uint32_t recovery_drop_all_ips;
+ uint32_t verify_recovery_lock;
+ uint32_t vacuum_interval;
+ uint32_t vacuum_max_run_time;
+ uint32_t repack_limit;
+ uint32_t vacuum_limit;
+ uint32_t max_queue_depth_drop_msg;
+ uint32_t allow_unhealthy_db_read;
+ uint32_t stat_history_interval;
+ uint32_t deferred_attach_timeout;
+ uint32_t vacuum_fast_path_count;
+ uint32_t lcp2_public_ip_assignment;
+ uint32_t allow_client_db_attach;
+ uint32_t recover_pdb_by_seqnum;
+ uint32_t deferred_rebalance_on_node_add;
+ uint32_t fetch_collapse;
+ uint32_t hopcount_make_sticky;
+ uint32_t sticky_duration;
+ uint32_t sticky_pindown;
+ uint32_t no_ip_takeover;
+ uint32_t db_record_count_warn;
+ uint32_t db_record_size_warn;
+ uint32_t db_size_warn;
+ uint32_t pulldb_preallocation_size;
+ uint32_t no_ip_host_on_all_disabled;
+ uint32_t samba3_hack;
+ uint32_t mutex_enabled;
+ uint32_t lock_processes_per_db;
+};
+
+struct ctdb_tickle_list {
+ ctdb_sock_addr addr;
+ uint32_t num;
+ struct ctdb_connection *conn;
+};
+
+enum ctdb_client_type {
+ SERVER_TYPE_CTDB = 0,
+ SERVER_TYPE_SAMBA = 1,
+ SERVER_TYPE_NFSD = 2,
+ SERVER_TYPE_ISCSID = 3
+};
+
+struct ctdb_client_id {
+ enum ctdb_client_type type;
+ uint32_t pnn;
+ uint32_t server_id;
+};
+
+struct ctdb_client_id_list {
+ uint32_t num;
+ struct ctdb_client_id *cid;
+};
+
+struct ctdb_client_id_map {
+ int count;
+ struct ctdb_client_id_list *list;
+};
+
+struct ctdb_addr_info {
+ ctdb_sock_addr addr;
+ uint32_t mask;
+ const char *iface;
+};
+
+struct ctdb_transdb {
+ uint32_t db_id;
+ uint32_t tid;
+};
+
+struct ctdb_uptime {
+ struct timeval current_time;
+ struct timeval ctdbd_start_time;
+ struct timeval last_recovery_started;
+ struct timeval last_recovery_finished;
+};
+
+struct ctdb_public_ip {
+ uint32_t pnn;
+ ctdb_sock_addr addr;
+};
+
+struct ctdb_public_ip_list {
+ uint32_t num;
+ struct ctdb_public_ip *ip;
+};
+
+/*
+ * Node flags
+ */
+#define NODE_FLAGS_DISCONNECTED 0x00000001 /* node isn't connected */
+#define NODE_FLAGS_UNHEALTHY 0x00000002 /* monitoring says node is unhealthy */
+#define NODE_FLAGS_PERMANENTLY_DISABLED 0x00000004 /* administrator has disabled node */
+#define NODE_FLAGS_BANNED 0x00000008 /* recovery daemon has banned the node */
+#define NODE_FLAGS_DELETED 0x00000010 /* this node has been deleted */
+#define NODE_FLAGS_STOPPED 0x00000020 /* this node has been stopped */
+#define NODE_FLAGS_DISABLED (NODE_FLAGS_UNHEALTHY|NODE_FLAGS_PERMANENTLY_DISABLED)
+#define NODE_FLAGS_INACTIVE (NODE_FLAGS_DELETED|NODE_FLAGS_DISCONNECTED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)
+
+/*
+ * Node capabilities
+ */
+#define CTDB_CAP_RECMASTER 0x00000001
+#define CTDB_CAP_LMASTER 0x00000002
+/* This capability is set if CTDB_LVS_PUBLIC_IP is set */
+#define CTDB_CAP_LVS 0x00000004
+/* This capability is set if NATGW is enabled */
+#define CTDB_CAP_NATGW 0x00000008
+
+struct ctdb_node_and_flags {
+ uint32_t pnn;
+ uint32_t flags;
+ ctdb_sock_addr addr;
+};
+
+struct ctdb_node_map {
+ uint32_t num;
+ struct ctdb_node_and_flags *node;
+};
+
+enum ctdb_event {
+ CTDB_EVENT_INIT, /* CTDB starting up: no args */
+ CTDB_EVENT_SETUP, /* CTDB starting up after transport is readdy: no args. */
+ CTDB_EVENT_STARTUP, /* CTDB starting up after initial recovery: no args. */
+ CTDB_EVENT_START_RECOVERY, /* CTDB recovery starting: no args. */
+ CTDB_EVENT_RECOVERED, /* CTDB recovery finished: no args. */
+ CTDB_EVENT_TAKE_IP, /* IP taken: interface, IP address, netmask bits. */
+ CTDB_EVENT_RELEASE_IP, /* IP released: interface, IP address, netmask bits. */
+ CTDB_EVENT_STOPPED, /* Deprecated, do not use. */
+ CTDB_EVENT_MONITOR, /* Please check if service is healthy: no args. */
+ CTDB_EVENT_STATUS, /* Deprecated, do not use. */
+ CTDB_EVENT_SHUTDOWN, /* CTDB shutting down: no args. */
+ CTDB_EVENT_RELOAD, /* Deprecated, do not use */
+ CTDB_EVENT_UPDATE_IP, /* IP updating: old interface, new interface, IP address, netmask bits. */
+ CTDB_EVENT_IPREALLOCATED, /* when a takeover_run() completes */
+ CTDB_EVENT_MAX
+};
+
+#define MAX_SCRIPT_NAME 31
+#define MAX_SCRIPT_OUTPUT 511
+
+struct ctdb_script {
+ char name[MAX_SCRIPT_NAME+1];
+ struct timeval start;
+ struct timeval finished;
+ int32_t status;
+ char output[MAX_SCRIPT_OUTPUT+1];
+};
+
+struct ctdb_script_list {
+ uint32_t num_scripts;
+ struct ctdb_script *script;
+};
+
+struct ctdb_ban_state {
+ uint32_t pnn;
+ uint32_t time;
+};
+
+struct ctdb_db_priority {
+ uint32_t db_id;
+ uint32_t priority;
+};
+
+struct ctdb_notify_data {
+ uint64_t srvid;
+ TDB_DATA data;
+};
+
+#ifdef IFNAMSIZ
+#define CTDB_IFACE_SIZE IFNAMSIZ
+#else
+#define CTDB_IFACE_SIZE 16
+#endif
+
+struct ctdb_iface {
+ char name[CTDB_IFACE_SIZE+2];
+ uint16_t link_state;
+ uint32_t references;
+};
+
+struct ctdb_iface_list {
+ uint32_t num;
+ struct ctdb_iface *iface;
+};
+
+struct ctdb_public_ip_info {
+ struct ctdb_public_ip ip;
+ uint32_t active_idx;
+ struct ctdb_iface_list *ifaces;
+};
+
+struct ctdb_statistics_list {
+ int num;
+ struct ctdb_statistics *stats;
+};
+
+struct ctdb_key_data {
+ uint32_t db_id;
+ struct ctdb_ltdb_header header;
+ TDB_DATA key;
+};
+
+struct ctdb_uint8_array {
+ int num;
+ uint8_t *val;
+};
+
+struct ctdb_uint64_array {
+ int num;
+ uint64_t *val;
+};
+
+struct ctdb_db_statistics {
+ struct {
+ uint32_t num_calls;
+ uint32_t num_current;
+ uint32_t num_pending;
+ uint32_t num_failed;
+ struct ctdb_latency_counter latency;
+ uint32_t buckets[MAX_COUNT_BUCKETS];
+ } locks;
+ struct {
+ struct ctdb_latency_counter latency;
+ } vacuum;
+ uint32_t db_ro_delegations;
+ uint32_t db_ro_revokes;
+ uint32_t hop_count_bucket[MAX_COUNT_BUCKETS];
+ uint32_t num_hot_keys;
+ struct {
+ uint32_t count;
+ TDB_DATA key;
+ } hot_keys[MAX_HOT_KEYS];
+};
+
+enum ctdb_runstate {
+ CTDB_RUNSTATE_UNKNOWN,
+ CTDB_RUNSTATE_INIT,
+ CTDB_RUNSTATE_SETUP,
+ CTDB_RUNSTATE_FIRST_RECOVERY,
+ CTDB_RUNSTATE_STARTUP,
+ CTDB_RUNSTATE_RUNNING,
+ CTDB_RUNSTATE_SHUTDOWN,
+};
+
+struct ctdb_req_control_data {
+ uint32_t opcode;
+ union {
+ pid_t pid;
+ uint32_t db_id;
+ struct ctdb_vnn_map *vnnmap;
+ uint32_t loglevel;
+ struct ctdb_pulldb *pulldb;
+ struct ctdb_rec_buffer *recbuf;
+ uint32_t recmode;
+ const char *db_name;
+ struct ctdb_traverse_start *traverse_start;
+ struct ctdb_traverse_all *traverse_all;
+ struct ctdb_rec_data *rec_data;
+ uint32_t recmaster;
+ struct ctdb_connection *conn;
+ struct ctdb_tunable *tunable;
+ const char *tun_var;
+ struct ctdb_node_flag_change *flag_change;
+ ctdb_sock_addr *addr;
+ struct ctdb_tickle_list *tickles;
+ struct ctdb_client_id *cid;
+ struct ctdb_addr_info *addr_info;
+ uint32_t tid;
+ struct ctdb_transdb *transdb;
+ const char *event_str;
+ struct ctdb_public_ip *pubip;
+ enum ctdb_event event;
+ double reclock_latency;
+ const char *reclock_file;
+ uint32_t role;
+ const char *script;
+ struct ctdb_ban_state *ban_state;
+ struct ctdb_db_priority *db_prio;
+ struct ctdb_notify_data *notify;
+ uint64_t srvid;
+ struct ctdb_iface *iface;
+ struct ctdb_key_data *key;
+ struct ctdb_uint64_array *u64_array;
+ struct ctdb_traverse_start_ext *traverse_start_ext;
+ struct ctdb_traverse_all_ext *traverse_all_ext;
+ } data;
+};
+
+struct ctdb_reply_control_data {
+ uint32_t opcode;
+ union {
+ struct ctdb_statistics *stats;
+ const char *db_path;
+ struct ctdb_vnn_map *vnnmap;
+ uint32_t loglevel;
+ struct ctdb_dbid_map *dbmap;
+ struct ctdb_rec_buffer *recbuf;
+ uint32_t db_id;
+ const char *db_name;
+ const char *mem_str;
+ uint32_t tun_value;
+ struct ctdb_var_list *tun_var_list;
+ struct ctdb_tunable_list *tun_list;
+ struct ctdb_tickle_list *tickles;
+ struct ctdb_client_id_map *cid_map;
+ struct ctdb_uptime *uptime;
+ uint32_t caps;
+ struct ctdb_public_ip_list *pubip_list;
+ struct ctdb_node_map *nodemap;
+ struct ctdb_script_list *script_list;
+ const char *reclock_file;
+ struct ctdb_ban_state *ban_state;
+ uint64_t seqnum;
+ const char *reason;
+ struct ctdb_public_ip_info *ipinfo;
+ struct ctdb_iface_list *iface_list;
+ struct ctdb_statistics_list *stats_list;
+ struct ctdb_uint8_array *u8_array;
+ struct ctdb_db_statistics *dbstats;
+ enum ctdb_runstate runstate;
+ } data;
+};
+
+struct ctdb_req_control {
+ uint32_t opcode;
+ uint32_t pad;
+ uint64_t srvid;
+ uint32_t client_id;
+#define CTDB_CTRL_FLAG_NOREPLY 1
+#define CTDB_CTRL_FLAG_OPCODE_SPECIFIC 0xFFFF0000
+ uint32_t flags;
+ struct ctdb_req_control_data rdata;
+};
+
+struct ctdb_reply_control {
+ int32_t status;
+ const char *errmsg;
+ struct ctdb_reply_control_data rdata;
+};
+
+struct ctdb_election_message {
+ uint32_t num_connected;
+ struct timeval priority_time;
+ uint32_t pnn;
+ uint32_t node_flags;
+};
+
+struct ctdb_srvid_message {
+ uint32_t pnn;
+ uint64_t srvid;
+};
+
+struct ctdb_disable_message {
+ uint32_t pnn;
+ uint64_t srvid;
+ uint32_t timeout;
+};
+
+union ctdb_message_data {
+ /* SRVID_ELECTION */
+ struct ctdb_election_message *election;
+ /* SRVID_RELEASE_IP, SRVID_TAKE_IP */
+ const char *ipaddr;
+ /* SRVID_SET_NODE_FLAGS, SERVID_PUSH_NODE_FLAGS */
+ struct ctdb_node_flag_change *flag_change;
+ /* SRVID_RECD_UPDATE_IP */
+ struct ctdb_public_ip *pubip;
+ /* SRVID_VACUUM_FETCH */
+ struct ctdb_rec_buffer *recbuf;
+ /* SRVID_DETACH_DATABASE */
+ uint32_t db_id;
+ /* SRVID_MEM_DUMP, SRVID_TAKEOVER_RUN */
+ struct ctdb_srvid_message *msg;
+ /* SRVID_REBALANCE_NODE */
+ uint32_t pnn;
+ /* SRVID_DISABLE_TAKEOVER_RUNS, SRVID_DISABLE_RECOVERIES */
+ struct ctdb_disable_message *disable;
+ /* SRVID_DISABLE_IP_CHECK */
+ uint32_t timeout;
+};
+
+struct ctdb_req_message {
+ uint64_t srvid;
+ union ctdb_message_data data;
+};
+
+struct ctdb_req_message_data {
+ uint64_t srvid;
+ TDB_DATA data;
+};
+
+/* This is equivalent to server_id */
+struct ctdb_server_id {
+ uint64_t pid;
+ uint32_t task_id;
+ uint32_t vnn;
+ uint64_t unique_id;
+};
+
+enum ctdb_g_lock_type {
+ G_LOCK_READ = 0,
+ G_LOCK_WRITE = 1,
+};
+
+struct ctdb_g_lock {
+ enum ctdb_g_lock_type type;
+ struct ctdb_server_id sid;
+};
+
+struct ctdb_g_lock_list {
+ unsigned int num;
+ struct ctdb_g_lock *lock;
+};
+
+#endif /* __CTDB_PROTOCOL_H__ */
diff --git a/ctdb/protocol/protocol_api.h b/ctdb/protocol/protocol_api.h
new file mode 100644
index 00000000000..3628c3e73f4
--- /dev/null
+++ b/ctdb/protocol/protocol_api.h
@@ -0,0 +1,643 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CTDB_PROTOCOL_API_H__
+#define __CTDB_PROTOCOL_API_H__
+
+#include "protocol/protocol.h"
+
+/* From protocol/protocol_types.c */
+
+size_t ctdb_ltdb_header_len(struct ctdb_ltdb_header *header);
+void ctdb_ltdb_header_push(struct ctdb_ltdb_header *header, uint8_t *buf);
+int ctdb_ltdb_header_pull(uint8_t *buf, size_t buflen,
+ struct ctdb_ltdb_header *header);
+
+size_t ctdb_rec_data_len(struct ctdb_rec_data *rec);
+void ctdb_rec_data_push(struct ctdb_rec_data *rec, uint8_t *buf);
+int ctdb_rec_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_data **out);
+
+size_t ctdb_rec_buffer_len(struct ctdb_rec_buffer *recbuf);
+void ctdb_rec_buffer_push(struct ctdb_rec_buffer *recbuf, uint8_t *buf);
+int ctdb_rec_buffer_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **out);
+
+struct ctdb_rec_buffer *ctdb_rec_buffer_init(TALLOC_CTX *mem_ctx,
+ uint32_t db_id);
+int ctdb_rec_buffer_add(TALLOC_CTX *mem_ctx, struct ctdb_rec_buffer *recbuf,
+ uint32_t reqid, struct ctdb_ltdb_header *header,
+ TDB_DATA key, TDB_DATA data);
+int ctdb_rec_buffer_traverse(struct ctdb_rec_buffer *recbuf,
+ ctdb_rec_parser_func_t func,
+ void *private_data);
+
+size_t ctdb_server_id_len(struct ctdb_server_id *sid);
+void ctdb_server_id_push(struct ctdb_server_id *sid, uint8_t *buf);
+int ctdb_server_id_pull(uint8_t *buf, size_t buflen,
+ struct ctdb_server_id *sid);
+
+size_t ctdb_g_lock_len(struct ctdb_g_lock *lock);
+void ctdb_g_lock_push(struct ctdb_g_lock *lock, uint8_t *buf);
+int ctdb_g_lock_pull(uint8_t *buf, size_t buflen, struct ctdb_g_lock *lock);
+
+size_t ctdb_g_lock_list_len(struct ctdb_g_lock_list *lock_list);
+void ctdb_g_lock_list_push(struct ctdb_g_lock_list *lock_list, uint8_t *buf);
+int ctdb_g_lock_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_g_lock_list **out);
+
+/* From protocol/protocol_header.c */
+
+void ctdb_req_header_fill(struct ctdb_req_header *h, uint32_t generation,
+ uint32_t operation, uint32_t destnode,
+ uint32_t srcnode, uint32_t reqid);
+
+int ctdb_req_header_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h);
+
+int ctdb_req_header_verify(struct ctdb_req_header *h, uint32_t operation);
+
+/* From protocol/protocol_call.c */
+
+int ctdb_req_call_push(struct ctdb_req_header *h,
+ struct ctdb_req_call *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_req_call_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_call *c);
+
+int ctdb_reply_call_push(struct ctdb_req_header *h,
+ struct ctdb_reply_call *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_reply_call_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_call *c);
+
+int ctdb_reply_error_push(struct ctdb_req_header *h,
+ struct ctdb_reply_error *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_reply_error_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_error *c);
+
+int ctdb_req_dmaster_push(struct ctdb_req_header *h,
+ struct ctdb_req_dmaster *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_req_dmaster_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_dmaster *c);
+
+int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
+ struct ctdb_reply_dmaster *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_reply_dmaster_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_dmaster *c);
+
+/* From protocol/protocol_control.c */
+
+int ctdb_req_control_push(struct ctdb_req_header *h,
+ struct ctdb_req_control *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_req_control_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_control *c);
+
+int ctdb_reply_control_push(struct ctdb_req_header *h,
+ struct ctdb_reply_control *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_reply_control_pull(uint8_t *pkt, size_t pkt_len, uint32_t opcode,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_control *c);
+
+/* From protocol/protocol_client.c */
+
+void ctdb_req_control_process_exists(struct ctdb_req_control *request,
+ pid_t pid);
+int ctdb_reply_control_process_exists(struct ctdb_reply_control *reply,
+ int *status);
+
+void ctdb_req_control_statistics(struct ctdb_req_control *request);
+
+int ctdb_reply_control_statistics(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics **stats);
+
+void ctdb_req_control_ping(struct ctdb_req_control *request);
+int ctdb_reply_control_ping(struct ctdb_reply_control *reply,
+ int *num_clients);
+
+void ctdb_req_control_getdbpath(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_getdbpath(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **db_path);
+
+void ctdb_req_control_getvnnmap(struct ctdb_req_control *request);
+int ctdb_reply_control_getvnnmap(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_vnn_map **vnnmap);
+
+void ctdb_req_control_setvnnmap(struct ctdb_req_control *request,
+ struct ctdb_vnn_map *vnnmap);
+int ctdb_reply_control_setvnnmap(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_debug(struct ctdb_req_control *request);
+int ctdb_reply_control_get_debug(struct ctdb_reply_control *reply,
+ uint32_t *debug_level);
+
+void ctdb_req_control_set_debug(struct ctdb_req_control *request,
+ uint32_t debug_level);
+int ctdb_reply_control_set_debug(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_dbmap(struct ctdb_req_control *request);
+int ctdb_reply_control_get_dbmap(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_dbid_map **dbmap);
+
+void ctdb_req_control_pull_db(struct ctdb_req_control *request,
+ struct ctdb_pulldb *pulldb);
+int ctdb_reply_control_pull_db(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **recbuf);
+
+void ctdb_req_control_push_db(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf);
+int ctdb_reply_control_push_db(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_recmode(struct ctdb_req_control *request);
+int ctdb_reply_control_get_recmode(struct ctdb_reply_control *reply,
+ int *recmode);
+
+void ctdb_req_control_set_recmode(struct ctdb_req_control *request,
+ int recmode);
+int ctdb_reply_control_set_recmode(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_statistics_reset(struct ctdb_req_control *request);
+int ctdb_reply_control_statistics_reset(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_db_attach(struct ctdb_req_control *request,
+ const char *db_name, uint32_t tdb_flags);
+int ctdb_reply_control_db_attach(struct ctdb_reply_control *reply,
+ uint32_t *db_id);
+
+void ctdb_req_control_traverse_start(struct ctdb_req_control *request,
+ struct ctdb_traverse_start *traverse);
+int ctdb_reply_control_traverse_start(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_register_srvid(struct ctdb_req_control *request,
+ uint64_t srvid);
+int ctdb_reply_control_register_srvid(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_deregister_srvid(struct ctdb_req_control *request,
+ uint64_t srvid);
+int ctdb_reply_control_deregister_srvid(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_dbname(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_get_dbname(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **db_name);
+
+void ctdb_req_control_enable_seqnum(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_enable_seqnum(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_update_seqnum(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_update_seqnum(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_dump_memory(struct ctdb_req_control *request);
+int ctdb_reply_control_dump_memory(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **mem_str);
+
+void ctdb_req_control_get_pid(struct ctdb_req_control *request);
+int ctdb_reply_control_get_pid(struct ctdb_reply_control *reply,
+ pid_t *pid);
+
+void ctdb_req_control_get_recmaster(struct ctdb_req_control *request);
+int ctdb_reply_control_get_recmaster(struct ctdb_reply_control *reply,
+ uint32_t *recmaster);
+
+void ctdb_req_control_set_recmaster(struct ctdb_req_control *request,
+ int recmaster);
+int ctdb_reply_control_set_recmaster(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_freeze(struct ctdb_req_control *request,
+ uint32_t priority);
+int ctdb_reply_control_freeze(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_thaw(struct ctdb_req_control *request,
+ uint32_t priority);
+int ctdb_reply_control_thaw(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_pnn(struct ctdb_req_control *request);
+int ctdb_reply_control_get_pnn(struct ctdb_reply_control *reply,
+ uint32_t *pnn);
+
+void ctdb_req_control_shutdown(struct ctdb_req_control *request);
+int ctdb_reply_control_shutdown(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_monmode(struct ctdb_req_control *request);
+int ctdb_reply_control_get_monmode(struct ctdb_reply_control *reply,
+ int *mon_mode);
+
+void ctdb_req_control_tcp_client(struct ctdb_req_control *request,
+ struct ctdb_connection *conn);
+int ctdb_reply_control_tcp_client(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_tcp_add(struct ctdb_req_control *request,
+ struct ctdb_connection *conn);
+int ctdb_reply_control_tcp_add(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_tcp_remove(struct ctdb_req_control *request,
+ struct ctdb_connection *conn);
+int ctdb_reply_control_tcp_remove(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_startup(struct ctdb_req_control *request);
+int ctdb_reply_control_startup(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_set_tunable(struct ctdb_req_control *request,
+ struct ctdb_tunable *tunable);
+int ctdb_reply_control_set_tunable(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_tunable(struct ctdb_req_control *request,
+ const char *name);
+int ctdb_reply_control_get_tunable(struct ctdb_reply_control *reply,
+ uint32_t *value);
+
+void ctdb_req_control_list_tunables(struct ctdb_req_control *request);
+int ctdb_reply_control_list_tunables(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_var_list **tun_var_list);
+
+void ctdb_req_control_modify_flags(struct ctdb_req_control *request,
+ struct ctdb_node_flag_change *flag_change);
+int ctdb_reply_control_modify_flags(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_all_tunables(struct ctdb_req_control *request);
+int ctdb_reply_control_get_all_tunables(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_tunable_list **tun_list);
+
+void ctdb_req_control_kill_tcp(struct ctdb_req_control *request,
+ struct ctdb_connection *conn);
+int ctdb_reply_control_kill_tcp(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_tcp_tickle_list(struct ctdb_req_control *request,
+ ctdb_sock_addr *addr);
+int ctdb_reply_control_get_tcp_tickle_list(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_tickle_list **tickles);
+
+void ctdb_req_control_set_tcp_tickle_list(struct ctdb_req_control *request,
+ struct ctdb_tickle_list *tickles);
+int ctdb_reply_control_set_tcp_tickle_list(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_register_server_id(struct ctdb_req_control *request,
+ struct ctdb_client_id *sid);
+int ctdb_reply_control_register_server_id(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_unregister_server_id(struct ctdb_req_control *request,
+ struct ctdb_client_id *sid);
+int ctdb_reply_control_unregister_server_id(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_check_server_id(struct ctdb_req_control *request,
+ struct ctdb_client_id *sid);
+int ctdb_reply_control_check_server_id(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_server_id_list(struct ctdb_req_control *request);
+int ctdb_reply_control_get_server_id_list(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_map **cid_map);
+
+void ctdb_req_control_db_attach_persistent(struct ctdb_req_control *request,
+ const char *name,
+ uint32_t tdb_flags);
+int ctdb_reply_control_db_attach_persistent(struct ctdb_reply_control *reply,
+ uint32_t *db_id);
+
+void ctdb_req_control_update_record(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf);
+int ctdb_reply_control_update_record(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_send_gratuitous_arp(struct ctdb_req_control *request,
+ struct ctdb_addr_info *addr_info);
+int ctdb_reply_control_send_gratuitous_arp(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_transaction_start(struct ctdb_req_control *request,
+ uint32_t tid);
+int ctdb_reply_control_transaction_start(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_transaction_commit(struct ctdb_req_control *request,
+ uint32_t tid);
+int ctdb_reply_control_transaction_commit(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_wipe_database(struct ctdb_req_control *request,
+ struct ctdb_transdb *transdb);
+int ctdb_reply_control_wipe_database(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_uptime(struct ctdb_req_control *request);
+int ctdb_reply_control_uptime(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_uptime **uptime);
+
+void ctdb_req_control_start_recovery(struct ctdb_req_control *request);
+int ctdb_reply_control_start_recovery(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_end_recovery(struct ctdb_req_control *request);
+int ctdb_reply_control_end_recovery(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_reload_nodes_file(struct ctdb_req_control *request);
+int ctdb_reply_control_reload_nodes_file(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_try_delete_records(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf);
+int ctdb_reply_control_try_delete_records(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **recbuf);
+
+void ctdb_req_control_enable_monitor(struct ctdb_req_control *request);
+int ctdb_reply_control_enable_monitor(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_disable_monitor(struct ctdb_req_control *request);
+int ctdb_reply_control_disable_monitor(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_add_public_ip(struct ctdb_req_control *request,
+ struct ctdb_addr_info *addr_info);
+int ctdb_reply_control_add_public_ip(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_del_public_ip(struct ctdb_req_control *request,
+ struct ctdb_addr_info *addr_info);
+int ctdb_reply_control_del_public_ip(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_run_eventscripts(struct ctdb_req_control *request,
+ const char *event_str);
+int ctdb_reply_control_run_eventscripts(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_capabilities(struct ctdb_req_control *request);
+int ctdb_reply_control_get_capabilities(struct ctdb_reply_control *reply,
+ uint32_t *caps);
+
+void ctdb_req_control_recd_ping(struct ctdb_req_control *request);
+int ctdb_reply_control_recd_ping(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_release_ip(struct ctdb_req_control *request,
+ struct ctdb_public_ip *pubip);
+int ctdb_reply_control_release_ip(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_takeover_ip(struct ctdb_req_control *request,
+ struct ctdb_public_ip *pubip);
+int ctdb_reply_control_takeover_ip(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_public_ips(struct ctdb_req_control *request);
+int ctdb_reply_control_get_public_ips(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_list **pubip_list);
+
+void ctdb_req_control_get_nodemap(struct ctdb_req_control *request);
+int ctdb_reply_control_get_nodemap(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map **nodemap);
+
+void ctdb_req_control_get_event_script_status(struct ctdb_req_control *request,
+ uint32_t event);
+int ctdb_reply_control_get_event_script_status(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_script_list **script_list);
+
+void ctdb_req_control_traverse_kill(struct ctdb_req_control *request,
+ struct ctdb_traverse_start *traverse);
+int ctdb_reply_control_traverse_kill(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_recd_reclock_latency(struct ctdb_req_control *request,
+ double reclock_latency);
+int ctdb_reply_control_recd_reclock_latency(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_reclock_file(struct ctdb_req_control *request);
+int ctdb_reply_control_get_reclock_file(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ const char **reclock_file);
+
+void ctdb_req_control_set_reclock_file(struct ctdb_req_control *request,
+ const char *reclock_file);
+int ctdb_reply_control_set_reclock_file(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_stop_node(struct ctdb_req_control *request);
+int ctdb_reply_control_stop_node(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_continue_node(struct ctdb_req_control *request);
+int ctdb_reply_control_continue_node(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_set_natgwstate(struct ctdb_req_control *request,
+ uint32_t natgw_role);
+int ctdb_reply_control_set_natgwstate(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_set_lmasterrole(struct ctdb_req_control *request,
+ uint32_t lmaster_role);
+int ctdb_reply_control_set_lmasterrole(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_set_recmasterrole(struct ctdb_req_control *request,
+ uint32_t recmaster_role);
+int ctdb_reply_control_set_recmasterrole(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_enable_script(struct ctdb_req_control *request,
+ const char *script);
+int ctdb_reply_control_enable_script(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_disable_script(struct ctdb_req_control *request,
+ const char *script);
+int ctdb_reply_control_disable_script(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_set_ban_state(struct ctdb_req_control *request,
+ struct ctdb_ban_state *ban_state);
+int ctdb_reply_control_set_ban_state(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_ban_state(struct ctdb_req_control *request);
+int ctdb_reply_control_get_ban_state(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_ban_state **ban_state);
+
+void ctdb_req_control_set_db_priority(struct ctdb_req_control *request,
+ struct ctdb_db_priority *db_prio);
+int ctdb_reply_control_set_db_priority(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_db_priority(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_get_db_priority(struct ctdb_reply_control *reply,
+ uint32_t *priority);
+
+void ctdb_req_control_transaction_cancel(struct ctdb_req_control *request,
+ uint32_t tid);
+int ctdb_reply_control_transaction_cancel(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_register_notify(struct ctdb_req_control *request,
+ struct ctdb_notify_data *notify);
+int ctdb_reply_control_register_notify(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_deregister_notify(struct ctdb_req_control *request,
+ uint64_t srvid);
+int ctdb_reply_control_deregister_notify(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_trans3_commit(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf);
+int ctdb_reply_control_trans3_commit(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_db_seqnum(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_get_db_seqnum(struct ctdb_reply_control *reply,
+ uint64_t *seqnum);
+
+void ctdb_req_control_db_set_healthy(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_db_set_healthy(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_db_get_health(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_db_get_health(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ const char **reason);
+
+void ctdb_req_control_get_public_ip_info(struct ctdb_req_control *request,
+ ctdb_sock_addr *addr);
+int ctdb_reply_control_get_public_ip_info(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_info **ipinfo);
+
+void ctdb_req_control_get_ifaces(struct ctdb_req_control *request);
+int ctdb_reply_control_get_ifaces(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_iface_list **iface_list);
+
+void ctdb_req_control_set_iface_link_state(struct ctdb_req_control *request,
+ struct ctdb_iface *iface);
+int ctdb_reply_control_set_iface_link_state(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_tcp_add_delayed_update(struct ctdb_req_control *request,
+ struct ctdb_connection *conn);
+int ctdb_reply_control_tcp_add_delayed_update(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_stat_history(struct ctdb_req_control *request);
+int ctdb_reply_control_get_stat_history(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics_list **stats_list);
+
+void ctdb_req_control_schedule_for_deletion(struct ctdb_req_control *request,
+ struct ctdb_key_data *key);
+int ctdb_reply_control_schedule_for_deletion(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_set_db_readonly(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_set_db_readonly(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_check_srvids(struct ctdb_req_control *request,
+ struct ctdb_uint64_array *u64_array);
+int ctdb_reply_control_check_srvids(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_uint8_array **u8_array);
+
+void ctdb_req_control_traverse_start_ext(struct ctdb_req_control *request,
+ struct ctdb_traverse_start_ext *traverse);
+int ctdb_reply_control_traverse_start_ext(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_db_statistics(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_get_db_statistics(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_db_statistics **dbstats);
+
+void ctdb_req_control_set_db_sticky(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_set_db_sticky(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_reload_public_ips(struct ctdb_req_control *request);
+int ctdb_reply_control_reload_public_ips(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_receive_records(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf);
+int ctdb_reply_control_receive_records(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **recbuf);
+
+void ctdb_req_control_ipreallocated(struct ctdb_req_control *request);
+int ctdb_reply_control_ipreallocated(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_runstate(struct ctdb_req_control *request);
+int ctdb_reply_control_get_runstate(struct ctdb_reply_control *reply,
+ enum ctdb_runstate *runstate);
+
+void ctdb_req_control_db_detach(struct ctdb_req_control *request,
+ uint32_t db_id);
+int ctdb_reply_control_db_detach(struct ctdb_reply_control *reply);
+
+void ctdb_req_control_get_nodes_file(struct ctdb_req_control *request);
+int ctdb_reply_control_get_nodes_file(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map **nodemap);
+
+/* From protocol/protocol_message.c */
+
+int ctdb_req_message_push(struct ctdb_req_header *h,
+ struct ctdb_req_message *c,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_req_message_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_message *c);
+
+int ctdb_req_message_data_push(struct ctdb_req_header *h,
+ struct ctdb_req_message_data *message,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len);
+
+int ctdb_req_message_data_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_message_data *message);
+
+/* From protocol/protocol_util.c */
+
+const char *ctdb_runstate_to_string(enum ctdb_runstate runstate);
+enum ctdb_runstate ctdb_runstate_from_string(const char *runstate_str);
+
+const char *ctdb_event_to_string(enum ctdb_event event);
+enum ctdb_event ctdb_event_from_string(const char *event_str);
+
+#endif /* __CTDB_PROTOCOL_API_H__ */
diff --git a/ctdb/protocol/protocol_call.c b/ctdb/protocol/protocol_call.c
new file mode 100644
index 00000000000..e0f38d97e08
--- /dev/null
+++ b/ctdb/protocol/protocol_call.c
@@ -0,0 +1,446 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_api.h"
+#include "protocol_private.h"
+
+struct ctdb_req_call_wire {
+ struct ctdb_req_header hdr;
+ uint32_t flags;
+ uint32_t db_id;
+ uint32_t callid;
+ uint32_t hopcount;
+ uint32_t keylen;
+ uint32_t calldatalen;
+ uint8_t data[1]; /* key[] followed by calldata[] */
+};
+
+struct ctdb_reply_call_wire {
+ struct ctdb_req_header hdr;
+ uint32_t status;
+ uint32_t datalen;
+ uint8_t data[1];
+};
+
+struct ctdb_reply_error_wire {
+ struct ctdb_req_header hdr;
+ uint32_t status;
+ uint32_t msglen;
+ uint8_t msg[1];
+};
+
+struct ctdb_req_dmaster_wire {
+ struct ctdb_req_header hdr;
+ uint32_t db_id;
+ uint64_t rsn;
+ uint32_t dmaster;
+ uint32_t keylen;
+ uint32_t datalen;
+ uint8_t data[1];
+};
+
+struct ctdb_reply_dmaster_wire {
+ struct ctdb_req_header hdr;
+ uint32_t db_id;
+ uint64_t rsn;
+ uint32_t keylen;
+ uint32_t datalen;
+ uint8_t data[1];
+};
+
+int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c,
+ TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_req_call_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen;
+ int ret;
+
+ if (c->key.dsize == 0) {
+ return EINVAL;
+ }
+
+ length = offsetof(struct ctdb_req_call_wire, data) +
+ c->key.dsize + c->calldata.dsize;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_req_call_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->flags = c->flags;
+ wire->db_id = c->db_id;
+ wire->callid = c->callid;
+ wire->hopcount = c->hopcount;
+ wire->keylen = c->key.dsize;
+ wire->calldatalen = c->calldata.dsize;
+ memcpy(wire->data, c->key.dptr, c->key.dsize);
+ if (c->calldata.dsize > 0) {
+ memcpy(wire->data + c->key.dsize, c->calldata.dptr,
+ c->calldata.dsize);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_req_call_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_call *c)
+{
+ struct ctdb_req_call_wire *wire;
+ size_t length;
+
+ length = offsetof(struct ctdb_req_call_wire, data);
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+
+ wire = (struct ctdb_req_call_wire *)pkt;
+
+ if (pkt_len < length + wire->keylen + wire->calldatalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ c->flags = wire->flags;
+ c->db_id = wire->db_id;
+ c->callid = wire->callid;
+ c->hopcount = wire->hopcount;
+ c->key.dsize = wire->keylen;
+ c->key.dptr = talloc_memdup(mem_ctx, wire->data, wire->keylen);
+ if (c->key.dptr == NULL) {
+ return ENOMEM;
+ }
+ c->calldata.dsize = wire->calldatalen;
+ if (wire->calldatalen > 0) {
+ c->calldata.dptr = talloc_memdup(mem_ctx,
+ wire->data + wire->keylen,
+ wire->calldatalen);
+ if (c->calldata.dptr == NULL) {
+ talloc_free(c->key.dptr);
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c,
+ TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_reply_call_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen;
+ int ret;
+
+ length = offsetof(struct ctdb_reply_call_wire, data) + c->data.dsize;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_reply_call_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->status = c->status;
+ wire->datalen = c->data.dsize;
+ if (c->data.dsize > 0) {
+ memcpy(wire->data, c->data.dptr, c->data.dsize);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_reply_call_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_call *c)
+{
+ struct ctdb_reply_call_wire *wire;
+ size_t length;
+
+ length = offsetof(struct ctdb_reply_call_wire, data);
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+
+ wire = (struct ctdb_reply_call_wire *)pkt;
+
+ if (pkt_len < length + wire->datalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ c->status = wire->status;
+ c->data.dsize = wire->datalen;
+ if (wire->datalen > 0) {
+ c->data.dptr = talloc_memdup(mem_ctx, wire->data,
+ wire->datalen);
+ if (c->data.dptr == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c,
+ TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_reply_error_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen;
+ int ret;
+
+ length = offsetof(struct ctdb_reply_error_wire, msg) + c->msg.dsize;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_reply_error_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->status = c->status;
+ wire->msglen = c->msg.dsize;
+ if (c->msg.dsize > 0) {
+ memcpy(wire->msg, c->msg.dptr, c->msg.dsize);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_reply_error_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_error *c)
+{
+ struct ctdb_reply_error_wire *wire;
+ size_t length;
+
+ length = offsetof(struct ctdb_reply_error_wire, msg);
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+
+ wire = (struct ctdb_reply_error_wire *)pkt;
+
+ if (pkt_len < length + wire->msglen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ c->status = wire->status;
+ c->msg.dsize = wire->msglen;
+ if (wire->msglen > 0) {
+ c->msg.dptr = talloc_memdup(mem_ctx, wire->msg, wire->msglen);
+ if (c->msg.dptr == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c,
+ TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_req_dmaster_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen;
+ int ret;
+
+ length = offsetof(struct ctdb_req_dmaster_wire, data) +
+ c->key.dsize + c->data.dsize;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_req_dmaster_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->db_id = c->db_id;
+ wire->rsn = c->rsn;
+ wire->dmaster = c->dmaster;
+ wire->keylen = c->key.dsize;
+ if (c->key.dsize > 0) {
+ memcpy(wire->data, c->key.dptr, c->key.dsize);
+ }
+ wire->datalen = c->data.dsize;
+ if (c->data.dsize > 0) {
+ memcpy(wire->data + c->key.dsize, c->data.dptr, c->data.dsize);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_req_dmaster_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_dmaster *c)
+{
+ struct ctdb_req_dmaster_wire *wire;
+ size_t length;
+
+ length = offsetof(struct ctdb_req_dmaster_wire, data);
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+
+ wire = (struct ctdb_req_dmaster_wire *)pkt;
+
+ if (pkt_len < length + wire->keylen + wire->datalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ c->db_id = wire->db_id;
+ c->rsn = wire->rsn;
+ c->dmaster = wire->dmaster;
+ c->key.dsize = wire->keylen;
+ c->key.dptr = talloc_memdup(mem_ctx, wire->data, wire->keylen);
+ if (c->key.dptr == NULL) {
+ return ENOMEM;
+ }
+ c->data.dsize = wire->datalen;
+ if (wire->datalen > 0) {
+ c->data.dptr = talloc_memdup(mem_ctx, wire->data + wire->keylen,
+ wire->datalen);
+ if (c->data.dptr == NULL) {
+ talloc_free(c->key.dptr);
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
+ struct ctdb_reply_dmaster *c,
+ TALLOC_CTX *mem_ctx, uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_reply_dmaster_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen;
+ int ret;
+
+ length = offsetof(struct ctdb_reply_dmaster_wire, data) +
+ c->key.dsize + c->data.dsize;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_reply_dmaster_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->db_id = c->db_id;
+ wire->rsn = c->rsn;
+ wire->keylen = c->key.dsize;
+ if (c->key.dsize > 0) {
+ memcpy(wire->data, c->key.dptr, c->key.dsize);
+ }
+ wire->datalen = c->data.dsize;
+ if (c->data.dsize > 0) {
+ memcpy(wire->data + c->key.dsize, c->data.dptr, c->data.dsize);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_reply_dmaster_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_dmaster *c)
+{
+ struct ctdb_reply_dmaster_wire *wire;
+ size_t length;
+
+ length = offsetof(struct ctdb_reply_dmaster_wire, data);
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+
+ wire = (struct ctdb_reply_dmaster_wire *)pkt;
+
+ if (pkt_len < length + wire->keylen + wire->datalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ c->db_id = wire->db_id;
+ c->rsn = wire->rsn;
+ c->key.dsize = wire->keylen;
+ c->key.dptr = talloc_memdup(mem_ctx, wire->data, wire->keylen);
+ if (c->key.dptr == NULL) {
+ return ENOMEM;
+ }
+ c->data.dsize = wire->datalen;
+ if (wire->datalen > 0) {
+ c->data.dptr = talloc_memdup(mem_ctx, wire->data + wire->keylen,
+ wire->datalen);
+ if (c->data.dptr == NULL) {
+ talloc_free(c->key.dptr);
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
diff --git a/ctdb/protocol/protocol_client.c b/ctdb/protocol/protocol_client.c
new file mode 100644
index 00000000000..f4bfe193990
--- /dev/null
+++ b/ctdb/protocol/protocol_client.c
@@ -0,0 +1,2370 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_api.h"
+#include "protocol_private.h"
+
+/*
+void ctdb_req_call_fill(struct ctdb_req_call *c,
+ uint32_t db_id, uint32_t flags,
+ uint32_t call_id, TDB_DATA key)
+{
+ request->flags = flags;
+ c->db_id = db_id;
+ c->call_id = call_id;
+ c->key = key;
+ c->calldata = tdb_null;
+}
+*/
+
+static int ctdb_reply_control_generic(struct ctdb_reply_control *reply)
+{
+ return reply->status;
+}
+
+/* CTDB_CONTROL_PROCESS_EXISTS */
+
+void ctdb_req_control_process_exists(struct ctdb_req_control *request,
+ pid_t pid)
+{
+ request->opcode = CTDB_CONTROL_PROCESS_EXISTS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_PROCESS_EXISTS;
+ request->rdata.data.pid = pid;
+
+}
+
+int ctdb_reply_control_process_exists(struct ctdb_reply_control *reply,
+ int *status)
+{
+ if (reply->rdata.opcode == CTDB_CONTROL_PROCESS_EXISTS) {
+ *status = reply->status;
+ reply->status = 0;
+
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_STATISTICS */
+
+void ctdb_req_control_statistics(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_STATISTICS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_STATISTICS;
+}
+
+int ctdb_reply_control_statistics(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics **stats)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_STATISTICS) {
+ *stats = talloc_steal(mem_ctx, reply->rdata.data.stats);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_PING */
+
+void ctdb_req_control_ping(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_PING;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_PING;
+}
+
+int ctdb_reply_control_ping(struct ctdb_reply_control *reply,
+ int *num_clients)
+{
+ if (reply->status >= 0) {
+ *num_clients = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GETDBPATH */
+
+void ctdb_req_control_getdbpath(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_GETDBPATH;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GETDBPATH;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_getdbpath(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **db_path)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GETDBPATH) {
+ *db_path = talloc_steal(mem_ctx, reply->rdata.data.db_path);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GETVNNMAP */
+
+void ctdb_req_control_getvnnmap(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GETVNNMAP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GETVNNMAP;
+}
+
+int ctdb_reply_control_getvnnmap(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_vnn_map **vnnmap)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GETVNNMAP) {
+ *vnnmap = talloc_steal(mem_ctx, reply->rdata.data.vnnmap);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SETVNNMAP */
+
+void ctdb_req_control_setvnnmap(struct ctdb_req_control *request,
+ struct ctdb_vnn_map *vnnmap)
+{
+ request->opcode = CTDB_CONTROL_SETVNNMAP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SETVNNMAP;
+ request->rdata.data.vnnmap = vnnmap;
+}
+
+int ctdb_reply_control_setvnnmap(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_DEBUG */
+
+void ctdb_req_control_get_debug(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_DEBUG;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_DEBUG;
+}
+
+int ctdb_reply_control_get_debug(struct ctdb_reply_control *reply,
+ uint32_t *loglevel)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_DEBUG) {
+ *loglevel = reply->rdata.data.loglevel;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_DEBUG */
+
+void ctdb_req_control_set_debug(struct ctdb_req_control *request,
+ uint32_t loglevel)
+{
+ request->opcode = CTDB_CONTROL_SET_DEBUG;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_DEBUG;
+ request->rdata.data.loglevel = loglevel;
+}
+
+int ctdb_reply_control_set_debug(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_DBMAP */
+
+void ctdb_req_control_get_dbmap(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_DBMAP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_DBMAP;
+}
+
+int ctdb_reply_control_get_dbmap(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_dbid_map **dbmap)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_DBMAP) {
+ *dbmap = talloc_steal(mem_ctx, reply->rdata.data.dbmap);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_PULL_DB */
+
+void ctdb_req_control_pull_db(struct ctdb_req_control *request,
+ struct ctdb_pulldb *pulldb)
+{
+ request->opcode = CTDB_CONTROL_PULL_DB;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_PULL_DB;
+ request->rdata.data.pulldb = pulldb;
+}
+
+int ctdb_reply_control_pull_db(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **recbuf)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_PULL_DB) {
+ *recbuf = talloc_steal(mem_ctx, reply->rdata.data.recbuf);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_PUSH_DB */
+
+void ctdb_req_control_push_db(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf)
+{
+ request->opcode = CTDB_CONTROL_PUSH_DB;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_PUSH_DB;
+ request->rdata.data.recbuf = recbuf;
+}
+
+int ctdb_reply_control_push_db(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_RECMODE */
+
+void ctdb_req_control_get_recmode(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_RECMODE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_RECMODE;
+}
+
+int ctdb_reply_control_get_recmode(struct ctdb_reply_control *reply,
+ int *recmode)
+{
+ if (reply->status >= 0) {
+ *recmode = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_RECMODE */
+
+void ctdb_req_control_set_recmode(struct ctdb_req_control *request,
+ int recmode)
+{
+ request->opcode = CTDB_CONTROL_SET_RECMODE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_RECMODE;
+ request->rdata.data.recmode = recmode;
+}
+
+int ctdb_reply_control_set_recmode(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_STATISTICS_RESET */
+
+void ctdb_req_control_statistics_reset(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_STATISTICS_RESET;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_STATISTICS_RESET;
+}
+
+int ctdb_reply_control_statistics_reset(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DB_ATTACH */
+
+void ctdb_req_control_db_attach(struct ctdb_req_control *request,
+ const char *db_name, uint32_t tdb_flags)
+{
+ request->opcode = CTDB_CONTROL_DB_ATTACH;
+ request->pad = 0;
+ request->srvid = tdb_flags;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DB_ATTACH;
+ request->rdata.data.db_name = db_name;
+}
+
+int ctdb_reply_control_db_attach(struct ctdb_reply_control *reply,
+ uint32_t *db_id)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_DB_ATTACH) {
+ *db_id = reply->rdata.data.db_id;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_CALL */
+
+/* CTDB_CONTROL_TRAVERSE_START */
+
+void ctdb_req_control_traverse_start(struct ctdb_req_control *request,
+ struct ctdb_traverse_start *traverse)
+{
+ request->opcode = CTDB_CONTROL_TRAVERSE_START;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRAVERSE_START;
+ request->rdata.data.traverse_start = traverse;
+}
+
+int ctdb_reply_control_traverse_start(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TRAVERSE_ALL */
+/* CTDB_CONTROL_TRAVERSE_DATA */
+
+/* CTDB_CONTROL_REGISTER_SRVID */
+
+void ctdb_req_control_register_srvid(struct ctdb_req_control *request,
+ uint64_t srvid)
+{
+ request->opcode = CTDB_CONTROL_REGISTER_SRVID;
+ request->pad = 0;
+ request->srvid = srvid;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_REGISTER_SRVID;
+}
+
+int ctdb_reply_control_register_srvid(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DEREGISTER_SRVID */
+
+void ctdb_req_control_deregister_srvid(struct ctdb_req_control *request,
+ uint64_t srvid)
+{
+ request->opcode = CTDB_CONTROL_DEREGISTER_SRVID;
+ request->pad = 0;
+ request->srvid = srvid;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DEREGISTER_SRVID;
+}
+
+int ctdb_reply_control_deregister_srvid(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_DBNAME */
+
+void ctdb_req_control_get_dbname(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_GET_DBNAME;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_DBNAME;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_get_dbname(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **db_name)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_DBNAME) {
+ *db_name = talloc_steal(mem_ctx, reply->rdata.data.db_name);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_ENABLE_SEQNUM */
+
+void ctdb_req_control_enable_seqnum(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_ENABLE_SEQNUM;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_ENABLE_SEQNUM;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_enable_seqnum(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_UPDATE_SEQNUM */
+
+void ctdb_req_control_update_seqnum(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_UPDATE_SEQNUM;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_UPDATE_SEQNUM;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_update_seqnum(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DUMP_MEMORY */
+
+void ctdb_req_control_dump_memory(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_DUMP_MEMORY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DUMP_MEMORY;
+}
+
+int ctdb_reply_control_dump_memory(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **mem_str)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_DUMP_MEMORY) {
+ *mem_str = talloc_steal(mem_ctx, reply->rdata.data.mem_str);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_PID */
+
+void ctdb_req_control_get_pid(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_PID;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_PID;
+}
+
+int ctdb_reply_control_get_pid(struct ctdb_reply_control *reply,
+ pid_t *pid)
+{
+ if (reply->rdata.opcode == CTDB_CONTROL_GET_PID) {
+ *pid = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_RECMASTER */
+
+void ctdb_req_control_get_recmaster(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_RECMASTER;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_RECMASTER;
+}
+
+int ctdb_reply_control_get_recmaster(struct ctdb_reply_control *reply,
+ uint32_t *recmaster)
+{
+ if (reply->rdata.opcode == CTDB_CONTROL_GET_RECMASTER) {
+ *recmaster = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_RECMASTER */
+
+void ctdb_req_control_set_recmaster(struct ctdb_req_control *request,
+ int recmaster)
+{
+ request->opcode = CTDB_CONTROL_SET_RECMASTER;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_RECMASTER;
+ request->rdata.data.recmaster = recmaster;
+}
+
+int ctdb_reply_control_set_recmaster(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_FREEZE */
+
+void ctdb_req_control_freeze(struct ctdb_req_control *request,
+ uint32_t priority)
+{
+ request->opcode = CTDB_CONTROL_FREEZE;
+ request->pad = 0;
+ request->srvid = priority;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_FREEZE;
+}
+
+int ctdb_reply_control_freeze(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_THAW */
+
+void ctdb_req_control_thaw(struct ctdb_req_control *request,
+ uint32_t priority)
+{
+ request->opcode = CTDB_CONTROL_THAW;
+ request->pad = 0;
+ request->srvid = priority;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_THAW;
+}
+
+int ctdb_reply_control_thaw(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_PNN */
+
+void ctdb_req_control_get_pnn(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_PNN;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_PNN;
+}
+
+int ctdb_reply_control_get_pnn(struct ctdb_reply_control *reply,
+ uint32_t *pnn)
+{
+ if (reply->status >= 0) {
+ *pnn = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SHUTDOWN */
+
+void ctdb_req_control_shutdown(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_SHUTDOWN;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SHUTDOWN;
+}
+
+int ctdb_reply_control_shutdown(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_MONMODE */
+
+void ctdb_req_control_get_monmode(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_MONMODE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_MONMODE;
+}
+
+int ctdb_reply_control_get_monmode(struct ctdb_reply_control *reply,
+ int *mon_mode)
+{
+ if (reply->status >= 0) {
+ *mon_mode = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_TCP_CLIENT */
+
+void ctdb_req_control_tcp_client(struct ctdb_req_control *request,
+ struct ctdb_connection *conn)
+{
+ request->opcode = CTDB_CONTROL_TCP_CLIENT;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TCP_CLIENT;
+ request->rdata.data.conn = conn;
+}
+
+int ctdb_reply_control_tcp_client(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TCP_ADD */
+
+void ctdb_req_control_tcp_add(struct ctdb_req_control *request,
+ struct ctdb_connection *conn)
+{
+ request->opcode = CTDB_CONTROL_TCP_ADD;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TCP_ADD;
+ request->rdata.data.conn = conn;
+}
+
+int ctdb_reply_control_tcp_add(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TCP_REMOVE */
+
+void ctdb_req_control_tcp_remove(struct ctdb_req_control *request,
+ struct ctdb_connection *conn)
+{
+ request->opcode = CTDB_CONTROL_TCP_REMOVE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TCP_REMOVE;
+ request->rdata.data.conn = conn;
+}
+
+int ctdb_reply_control_tcp_remove(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_STARTUP */
+
+void ctdb_req_control_startup(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_STARTUP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_STARTUP;
+}
+
+int ctdb_reply_control_startup(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SET_TUNABLE */
+
+void ctdb_req_control_set_tunable(struct ctdb_req_control *request,
+ struct ctdb_tunable *tunable)
+{
+ request->opcode = CTDB_CONTROL_SET_TUNABLE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_TUNABLE;
+ request->rdata.data.tunable = tunable;
+}
+
+int ctdb_reply_control_set_tunable(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_TUNABLE */
+
+void ctdb_req_control_get_tunable(struct ctdb_req_control *request,
+ const char *name)
+{
+ request->opcode = CTDB_CONTROL_GET_TUNABLE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_TUNABLE;
+ request->rdata.data.tun_var = discard_const(name);
+}
+
+int ctdb_reply_control_get_tunable(struct ctdb_reply_control *reply,
+ uint32_t *value)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_TUNABLE) {
+ *value = reply->rdata.data.tun_value;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_LIST_TUNABLES */
+
+void ctdb_req_control_list_tunables(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_LIST_TUNABLES;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_LIST_TUNABLES;
+}
+
+int ctdb_reply_control_list_tunables(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_var_list **tun_var_list)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_LIST_TUNABLES) {
+ *tun_var_list = talloc_steal(mem_ctx,
+ reply->rdata.data.tun_var_list);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_MODIFY_FLAGS */
+
+void ctdb_req_control_modify_flags(struct ctdb_req_control *request,
+ struct ctdb_node_flag_change *flag_change)
+{
+ request->opcode = CTDB_CONTROL_MODIFY_FLAGS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_MODIFY_FLAGS;
+ request->rdata.data.flag_change = flag_change;
+}
+
+int ctdb_reply_control_modify_flags(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_ALL_TUNABLES */
+
+void ctdb_req_control_get_all_tunables(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_ALL_TUNABLES;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_ALL_TUNABLES;
+}
+
+int ctdb_reply_control_get_all_tunables(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_tunable_list **tun_list)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_ALL_TUNABLES) {
+ *tun_list = talloc_steal(mem_ctx, reply->rdata.data.tun_list);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_KILL_TCP */
+
+void ctdb_req_control_kill_tcp(struct ctdb_req_control *request,
+ struct ctdb_connection *conn)
+{
+ request->opcode = CTDB_CONTROL_KILL_TCP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_KILL_TCP;
+ request->rdata.data.conn = conn;
+}
+
+int ctdb_reply_control_kill_tcp(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_TCP_TICKLE_LIST */
+
+void ctdb_req_control_get_tcp_tickle_list(struct ctdb_req_control *request,
+ ctdb_sock_addr *addr)
+{
+ request->opcode = CTDB_CONTROL_GET_TCP_TICKLE_LIST;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_TCP_TICKLE_LIST;
+ request->rdata.data.addr = addr;
+}
+
+int ctdb_reply_control_get_tcp_tickle_list(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_tickle_list **tickles)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_TCP_TICKLE_LIST) {
+ *tickles = talloc_steal(mem_ctx, reply->rdata.data.tickles);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_TCP_TICKLE_LIST */
+
+void ctdb_req_control_set_tcp_tickle_list(struct ctdb_req_control *request,
+ struct ctdb_tickle_list *tickles)
+{
+ request->opcode = CTDB_CONTROL_SET_TCP_TICKLE_LIST;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_TCP_TICKLE_LIST;
+ request->rdata.data.tickles = tickles;
+}
+
+int ctdb_reply_control_set_tcp_tickle_list(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_REGISTER_SERVER_ID */
+
+void ctdb_req_control_register_server_id(struct ctdb_req_control *request,
+ struct ctdb_client_id *cid)
+{
+ request->opcode = CTDB_CONTROL_REGISTER_SERVER_ID;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_REGISTER_SERVER_ID;
+ request->rdata.data.cid = cid;
+}
+
+int ctdb_reply_control_register_server_id(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_UNREGISTER_SERVER_ID */
+
+void ctdb_req_control_unregister_server_id(struct ctdb_req_control *request,
+ struct ctdb_client_id *cid)
+{
+ request->opcode = CTDB_CONTROL_UNREGISTER_SERVER_ID;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_UNREGISTER_SERVER_ID;
+ request->rdata.data.cid = cid;
+}
+
+int ctdb_reply_control_unregister_server_id(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_CHECK_SERVER_ID */
+
+void ctdb_req_control_check_server_id(struct ctdb_req_control *request,
+ struct ctdb_client_id *cid)
+{
+ request->opcode = CTDB_CONTROL_CHECK_SERVER_ID;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_CHECK_SERVER_ID;
+ request->rdata.data.cid = cid;
+}
+
+int ctdb_reply_control_check_server_id(struct ctdb_reply_control *reply)
+{
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_SERVER_ID_LIST */
+
+void ctdb_req_control_get_server_id_list(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_SERVER_ID_LIST;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_SERVER_ID_LIST;
+}
+
+int ctdb_reply_control_get_server_id_list(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_map **cid_map)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_SERVER_ID_LIST) {
+ *cid_map = talloc_steal(mem_ctx, reply->rdata.data.cid_map);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_DB_ATTACH_PERSISTENT */
+
+void ctdb_req_control_db_attach_persistent(struct ctdb_req_control *request,
+ const char *db_name,
+ uint32_t tdb_flags)
+{
+ request->opcode = CTDB_CONTROL_DB_ATTACH_PERSISTENT;
+ request->pad = 0;
+ request->srvid = tdb_flags;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DB_ATTACH_PERSISTENT;
+ request->rdata.data.db_name = db_name;
+}
+
+int ctdb_reply_control_db_attach_persistent(struct ctdb_reply_control *reply,
+ uint32_t *db_id)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_DB_ATTACH_PERSISTENT) {
+ *db_id = reply->rdata.data.db_id;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_UPDATE_RECORD */
+
+void ctdb_req_control_update_record(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf)
+{
+ request->opcode = CTDB_CONTROL_UPDATE_RECORD;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_UPDATE_RECORD;
+ request->rdata.data.recbuf = recbuf;
+}
+
+int ctdb_reply_control_update_record(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SEND_GRATUITOUS_ARP */
+
+void ctdb_req_control_send_gratuitous_arp(struct ctdb_req_control *request,
+ struct ctdb_addr_info *addr_info)
+{
+ request->opcode = CTDB_CONTROL_SEND_GRATUITOUS_ARP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SEND_GRATUITOUS_ARP;
+ request->rdata.data.addr_info = addr_info;
+}
+
+int ctdb_reply_control_send_gratuitous_arp(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TRANSACTION_START */
+
+void ctdb_req_control_transaction_start(struct ctdb_req_control *request,
+ uint32_t tid)
+{
+ request->opcode = CTDB_CONTROL_TRANSACTION_START;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRANSACTION_START;
+ request->rdata.data.tid = tid;
+}
+
+int ctdb_reply_control_transaction_start(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TRANSACTION_COMMIT */
+
+void ctdb_req_control_transaction_commit(struct ctdb_req_control *request,
+ uint32_t tid)
+{
+ request->opcode = CTDB_CONTROL_TRANSACTION_COMMIT;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRANSACTION_COMMIT;
+ request->rdata.data.tid = tid;
+}
+
+int ctdb_reply_control_transaction_commit(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_WIPE_DATABASE */
+
+void ctdb_req_control_wipe_database(struct ctdb_req_control *request,
+ struct ctdb_transdb *transdb)
+{
+ request->opcode = CTDB_CONTROL_WIPE_DATABASE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_WIPE_DATABASE;
+ request->rdata.data.transdb = transdb;
+}
+
+int ctdb_reply_control_wipe_database(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_UPTIME */
+
+void ctdb_req_control_uptime(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_UPTIME;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_UPTIME;
+}
+
+int ctdb_reply_control_uptime(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, struct ctdb_uptime **uptime)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_UPTIME) {
+ *uptime = talloc_steal(mem_ctx, reply->rdata.data.uptime);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_START_RECOVERY */
+
+void ctdb_req_control_start_recovery(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_START_RECOVERY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_START_RECOVERY;
+}
+
+int ctdb_reply_control_start_recovery(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_END_RECOVERY */
+
+void ctdb_req_control_end_recovery(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_END_RECOVERY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_END_RECOVERY;
+}
+
+int ctdb_reply_control_end_recovery(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_RELOAD_NODES_FILE */
+
+void ctdb_req_control_reload_nodes_file(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_RELOAD_NODES_FILE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RELOAD_NODES_FILE;
+}
+
+int ctdb_reply_control_reload_nodes_file(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TRY_DELETE_RECORDS */
+
+void ctdb_req_control_try_delete_records(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf)
+{
+ request->opcode = CTDB_CONTROL_TRY_DELETE_RECORDS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRY_DELETE_RECORDS;
+ request->rdata.data.recbuf = recbuf;
+}
+
+int ctdb_reply_control_try_delete_records(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **recbuf)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_TRY_DELETE_RECORDS) {
+ *recbuf = talloc_steal(mem_ctx, reply->rdata.data.recbuf);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_ENABLE_MONITOR */
+
+void ctdb_req_control_enable_monitor(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_ENABLE_MONITOR;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_ENABLE_MONITOR;
+}
+
+int ctdb_reply_control_enable_monitor(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DISABLE_MONITOR */
+
+void ctdb_req_control_disable_monitor(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_DISABLE_MONITOR;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DISABLE_MONITOR;
+}
+
+int ctdb_reply_control_disable_monitor(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_ADD_PUBLIC_IP */
+
+void ctdb_req_control_add_public_ip(struct ctdb_req_control *request,
+ struct ctdb_addr_info *addr_info)
+{
+ request->opcode = CTDB_CONTROL_ADD_PUBLIC_IP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_ADD_PUBLIC_IP;
+ request->rdata.data.addr_info = addr_info;
+}
+
+int ctdb_reply_control_add_public_ip(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DEL_PUBLIC_IP */
+
+void ctdb_req_control_del_public_ip(struct ctdb_req_control *request,
+ struct ctdb_addr_info *addr_info)
+{
+ request->opcode = CTDB_CONTROL_DEL_PUBLIC_IP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DEL_PUBLIC_IP;
+ request->rdata.data.addr_info = addr_info;
+}
+
+int ctdb_reply_control_del_public_ip(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_RUN_EVENTSCRIPTS */
+
+void ctdb_req_control_run_eventscripts(struct ctdb_req_control *request,
+ const char *event_str)
+{
+ request->opcode = CTDB_CONTROL_RUN_EVENTSCRIPTS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RUN_EVENTSCRIPTS;
+ request->rdata.data.event_str = event_str;
+}
+
+int ctdb_reply_control_run_eventscripts(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_CAPABILITIES */
+
+void ctdb_req_control_get_capabilities(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_CAPABILITIES;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_CAPABILITIES;
+}
+
+int ctdb_reply_control_get_capabilities(struct ctdb_reply_control *reply,
+ uint32_t *caps)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_CAPABILITIES) {
+ *caps = reply->rdata.data.caps;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_RECD_PING */
+
+void ctdb_req_control_recd_ping(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_RECD_PING;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RECD_PING;
+}
+
+int ctdb_reply_control_recd_ping(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_RELEASE_IP */
+
+void ctdb_req_control_release_ip(struct ctdb_req_control *request,
+ struct ctdb_public_ip *pubip)
+{
+ request->opcode = CTDB_CONTROL_RELEASE_IP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RELEASE_IP;
+ request->rdata.data.pubip = pubip;
+}
+
+int ctdb_reply_control_release_ip(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TAKEOVER_IP */
+
+void ctdb_req_control_takeover_ip(struct ctdb_req_control *request,
+ struct ctdb_public_ip *pubip)
+{
+ request->opcode = CTDB_CONTROL_TAKEOVER_IP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TAKEOVER_IP;
+ request->rdata.data.pubip = pubip;
+}
+
+int ctdb_reply_control_takeover_ip(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_PUBLIC_IPS */
+
+void ctdb_req_control_get_public_ips(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_PUBLIC_IPS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_PUBLIC_IPS;
+}
+
+int ctdb_reply_control_get_public_ips(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_list **pubip_list)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_PUBLIC_IPS) {
+ *pubip_list = talloc_steal(mem_ctx, reply->rdata.data.pubip_list);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_NODEMAP */
+
+void ctdb_req_control_get_nodemap(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_NODEMAP;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_NODEMAP;
+}
+
+int ctdb_reply_control_get_nodemap(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map **nodemap)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_NODEMAP) {
+ *nodemap = talloc_steal(mem_ctx, reply->rdata.data.nodemap);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS */
+
+void ctdb_req_control_get_event_script_status(struct ctdb_req_control *request,
+ uint32_t event)
+{
+ request->opcode = CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS;
+ request->rdata.data.event = event;
+}
+
+int ctdb_reply_control_get_event_script_status(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_script_list **slist)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS) {
+ *slist = talloc_steal(mem_ctx, reply->rdata.data.script_list);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_TRAVERSE_KILL */
+
+void ctdb_req_control_traverse_kill(struct ctdb_req_control *request,
+ struct ctdb_traverse_start *traverse)
+{
+ request->opcode = CTDB_CONTROL_TRAVERSE_KILL;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRAVERSE_KILL;
+ request->rdata.data.traverse_start = traverse;
+}
+
+int ctdb_reply_control_traverse_kill(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_RECD_RECLOCK_LATENCY */
+
+void ctdb_req_control_recd_reclock_latency(struct ctdb_req_control *request,
+ double reclock_latency)
+{
+ request->opcode = CTDB_CONTROL_RECD_RECLOCK_LATENCY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RECD_RECLOCK_LATENCY;
+ request->rdata.data.reclock_latency = reclock_latency;
+}
+
+int ctdb_reply_control_recd_reclock_latency(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_RECLOCK_FILE */
+
+void ctdb_req_control_get_reclock_file(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_RECLOCK_FILE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_RECLOCK_FILE;
+}
+
+int ctdb_reply_control_get_reclock_file(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ const char **reclock_file)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_RECLOCK_FILE) {
+ *reclock_file = talloc_steal(mem_ctx,
+ reply->rdata.data.reclock_file);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_RECLOCK_FILE */
+
+void ctdb_req_control_set_reclock_file(struct ctdb_req_control *request,
+ const char *reclock_file)
+{
+ request->opcode = CTDB_CONTROL_SET_RECLOCK_FILE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_RECLOCK_FILE;
+ request->rdata.data.reclock_file = reclock_file;
+}
+
+int ctdb_reply_control_set_reclock_file(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+
+/* CTDB_CONTROL_STOP_NODE */
+
+void ctdb_req_control_stop_node(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_STOP_NODE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_STOP_NODE;
+}
+
+int ctdb_reply_control_stop_node(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_CONTINUE_NODE */
+
+void ctdb_req_control_continue_node(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_CONTINUE_NODE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_CONTINUE_NODE;
+}
+
+int ctdb_reply_control_continue_node(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SET_NATGWSTATE */
+
+void ctdb_req_control_set_natgwstate(struct ctdb_req_control *request,
+ uint32_t natgw_role)
+{
+ request->opcode = CTDB_CONTROL_SET_NATGWSTATE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_NATGWSTATE;
+ request->rdata.data.role = natgw_role;
+}
+
+int ctdb_reply_control_set_natgwstate(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SET_LMASTERROLE */
+
+void ctdb_req_control_set_lmasterrole(struct ctdb_req_control *request,
+ uint32_t lmaster_role)
+{
+ request->opcode = CTDB_CONTROL_SET_LMASTERROLE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_LMASTERROLE;
+ request->rdata.data.role = lmaster_role;
+}
+
+int ctdb_reply_control_set_lmasterrole(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SET_RECMASTERROLE */
+
+void ctdb_req_control_set_recmasterrole(struct ctdb_req_control *request,
+ uint32_t recmaster_role)
+{
+ request->opcode = CTDB_CONTROL_SET_RECMASTERROLE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_RECMASTERROLE;
+ request->rdata.data.role = recmaster_role;
+}
+
+int ctdb_reply_control_set_recmasterrole(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_ENABLE_SCRIPT */
+
+void ctdb_req_control_enable_script(struct ctdb_req_control *request,
+ const char *script)
+{
+ request->opcode = CTDB_CONTROL_ENABLE_SCRIPT;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_ENABLE_SCRIPT;
+ request->rdata.data.script = script;
+}
+
+int ctdb_reply_control_enable_script(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DISABLE_SCRIPT */
+
+void ctdb_req_control_disable_script(struct ctdb_req_control *request,
+ const char *script)
+{
+ request->opcode = CTDB_CONTROL_DISABLE_SCRIPT;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DISABLE_SCRIPT;
+ request->rdata.data.script = script;
+}
+
+int ctdb_reply_control_disable_script(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SET_BAN_STATE */
+
+void ctdb_req_control_set_ban_state(struct ctdb_req_control *request,
+ struct ctdb_ban_state *ban_state)
+{
+ request->opcode = CTDB_CONTROL_SET_BAN_STATE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_BAN_STATE;
+ request->rdata.data.ban_state = ban_state;
+}
+
+int ctdb_reply_control_set_ban_state(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_BAN_STATE */
+
+void ctdb_req_control_get_ban_state(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_BAN_STATE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_BAN_STATE;
+}
+
+int ctdb_reply_control_get_ban_state(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_ban_state **ban_state)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_BAN_STATE) {
+ *ban_state = talloc_steal(mem_ctx,
+ reply->rdata.data.ban_state);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_DB_PRIORITY */
+
+void ctdb_req_control_set_db_priority(struct ctdb_req_control *request,
+ struct ctdb_db_priority *db_prio)
+{
+ request->opcode = CTDB_CONTROL_SET_DB_PRIORITY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_DB_PRIORITY;
+ request->rdata.data.db_prio = db_prio;
+}
+
+int ctdb_reply_control_set_db_priority(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_DB_PRIORITY */
+
+void ctdb_req_control_get_db_priority(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_GET_DB_PRIORITY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_DB_PRIORITY;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_get_db_priority(struct ctdb_reply_control *reply,
+ uint32_t *priority)
+{
+ if (reply->rdata.opcode == CTDB_CONTROL_GET_DB_PRIORITY) {
+ *priority = reply->status;
+ reply->status = 0;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_TRANSACTION_CANCEL */
+
+void ctdb_req_control_transaction_cancel(struct ctdb_req_control *request,
+ uint32_t tid)
+{
+ request->opcode = CTDB_CONTROL_TRANSACTION_CANCEL;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRANSACTION_CANCEL;
+ request->rdata.data.tid = tid;
+}
+
+int ctdb_reply_control_transaction_cancel(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_REGISTER_NOTIFY */
+
+void ctdb_req_control_register_notify(struct ctdb_req_control *request,
+ struct ctdb_notify_data *notify)
+{
+ request->opcode = CTDB_CONTROL_REGISTER_NOTIFY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_REGISTER_NOTIFY;
+ request->rdata.data.notify = notify;
+}
+
+int ctdb_reply_control_register_notify(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DEREGISTER_NOTIFY */
+
+void ctdb_req_control_deregister_notify(struct ctdb_req_control *request,
+ uint64_t srvid)
+{
+ request->opcode = CTDB_CONTROL_DEREGISTER_NOTIFY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DEREGISTER_NOTIFY;
+ request->rdata.data.srvid = srvid;
+}
+
+int ctdb_reply_control_deregister_notify(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TRANS3_COMMIT */
+
+void ctdb_req_control_trans3_commit(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf)
+{
+ request->opcode = CTDB_CONTROL_TRANS3_COMMIT;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRANS3_COMMIT;
+ request->rdata.data.recbuf = recbuf;
+}
+
+int ctdb_reply_control_trans3_commit(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_DB_SEQNUM */
+
+void ctdb_req_control_get_db_seqnum(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_GET_DB_SEQNUM;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_DB_SEQNUM;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_get_db_seqnum(struct ctdb_reply_control *reply,
+ uint64_t *seqnum)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_DB_SEQNUM) {
+ *seqnum = reply->rdata.data.seqnum;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_DB_SET_HEALTHY */
+
+void ctdb_req_control_db_set_healthy(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_DB_SET_HEALTHY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DB_SET_HEALTHY;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_db_set_healthy(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_DB_GET_HEALTH */
+
+void ctdb_req_control_db_get_health(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_DB_GET_HEALTH;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DB_GET_HEALTH;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_db_get_health(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx, const char **reason)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_DB_GET_HEALTH) {
+ *reason = talloc_steal(mem_ctx, reply->rdata.data.reason);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_PUBLIC_IP_INFO */
+
+void ctdb_req_control_get_public_ip_info(struct ctdb_req_control *request,
+ ctdb_sock_addr *addr)
+{
+ request->opcode = CTDB_CONTROL_GET_PUBLIC_IP_INFO;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_PUBLIC_IP_INFO;
+ request->rdata.data.addr = addr;
+}
+
+int ctdb_reply_control_get_public_ip_info(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_info **ipinfo)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_PUBLIC_IP_INFO) {
+ *ipinfo = talloc_steal(mem_ctx, reply->rdata.data.ipinfo);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_GET_IFACES */
+
+void ctdb_req_control_get_ifaces(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_IFACES;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_IFACES;
+}
+
+int ctdb_reply_control_get_ifaces(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_iface_list **iface_list)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_IFACES) {
+ *iface_list = talloc_steal(mem_ctx,
+ reply->rdata.data.iface_list);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_IFACE_LINK_STATE */
+
+void ctdb_req_control_set_iface_link_state(struct ctdb_req_control *request,
+ struct ctdb_iface *iface)
+{
+ request->opcode = CTDB_CONTROL_SET_IFACE_LINK_STATE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_IFACE_LINK_STATE;
+ request->rdata.data.iface = iface;
+}
+
+int ctdb_reply_control_set_iface_link_state(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE */
+
+void ctdb_req_control_tcp_add_delayed_update(struct ctdb_req_control *request,
+ struct ctdb_connection *conn)
+{
+ request->opcode = CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE;
+ request->rdata.data.conn = conn;
+}
+
+int ctdb_reply_control_tcp_add_delayed_update(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_STAT_HISTORY */
+
+void ctdb_req_control_get_stat_history(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_STAT_HISTORY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_STAT_HISTORY;
+}
+
+int ctdb_reply_control_get_stat_history(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics_list **stats_list)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_STAT_HISTORY) {
+ *stats_list = talloc_steal(mem_ctx,
+ reply->rdata.data.stats_list);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SCHEDULE_FOR_DELETION */
+
+void ctdb_req_control_schedule_for_deletion(struct ctdb_req_control *request,
+ struct ctdb_key_data *key)
+{
+ request->opcode = CTDB_CONTROL_SCHEDULE_FOR_DELETION;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SCHEDULE_FOR_DELETION;
+ request->rdata.data.key = key;
+}
+
+int ctdb_reply_control_schedule_for_deletion(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_SET_DB_READONLY */
+
+void ctdb_req_control_set_db_readonly(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_SET_DB_READONLY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_DB_READONLY;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_set_db_readonly(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_CHECK_SRVIDS */
+
+void ctdb_req_control_check_srvids(struct ctdb_req_control *request,
+ struct ctdb_uint64_array *u64_array)
+{
+ request->opcode = CTDB_CONTROL_CHECK_SRVIDS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_CHECK_SRVIDS;
+ request->rdata.data.u64_array = u64_array;
+}
+
+int ctdb_reply_control_check_srvids(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_uint8_array **u8_array)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_CHECK_SRVIDS) {
+ *u8_array = talloc_steal(mem_ctx, reply->rdata.data.u8_array);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_TRAVERSE_START_EXT */
+
+void ctdb_req_control_traverse_start_ext(struct ctdb_req_control *request,
+ struct ctdb_traverse_start_ext *traverse)
+{
+ request->opcode = CTDB_CONTROL_TRAVERSE_START_EXT;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_TRAVERSE_START_EXT;
+ request->rdata.data.traverse_start_ext = traverse;
+}
+
+int ctdb_reply_control_traverse_start_ext(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_DB_STATISTICS */
+
+void ctdb_req_control_get_db_statistics(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_GET_DB_STATISTICS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_DB_STATISTICS;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_get_db_statistics(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_db_statistics **dbstats)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_DB_STATISTICS) {
+ *dbstats = talloc_steal(mem_ctx, reply->rdata.data.dbstats);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_SET_DB_STICKY */
+
+void ctdb_req_control_set_db_sticky(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_SET_DB_STICKY;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_SET_DB_STICKY;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_set_db_sticky(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_RELOAD_PUBLIC_IPS */
+
+void ctdb_req_control_reload_public_ips(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_RELOAD_PUBLIC_IPS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RELOAD_PUBLIC_IPS;
+}
+
+int ctdb_reply_control_reload_public_ips(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_TRAVERSE_ALL_EXT */
+
+/* CTDB_CONTROL_RECEIVE_RECORDS */
+
+void ctdb_req_control_receive_records(struct ctdb_req_control *request,
+ struct ctdb_rec_buffer *recbuf)
+{
+ request->opcode = CTDB_CONTROL_RECEIVE_RECORDS;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_RECEIVE_RECORDS;
+ request->rdata.data.recbuf = recbuf;
+}
+
+int ctdb_reply_control_receive_records(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **recbuf)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_RECEIVE_RECORDS) {
+ *recbuf = talloc_steal(mem_ctx, reply->rdata.data.recbuf);
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_IPREALLOCATED */
+
+void ctdb_req_control_ipreallocated(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_IPREALLOCATED;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_IPREALLOCATED;
+}
+
+int ctdb_reply_control_ipreallocated(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_RUNSTATE */
+
+void ctdb_req_control_get_runstate(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_RUNSTATE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_RUNSTATE;
+}
+
+int ctdb_reply_control_get_runstate(struct ctdb_reply_control *reply,
+ enum ctdb_runstate *runstate)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_RUNSTATE) {
+ *runstate = reply->rdata.data.runstate;
+ }
+ return reply->status;
+}
+
+/* CTDB_CONTROL_DB_DETACH */
+
+void ctdb_req_control_db_detach(struct ctdb_req_control *request,
+ uint32_t db_id)
+{
+ request->opcode = CTDB_CONTROL_DB_DETACH;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_DB_DETACH;
+ request->rdata.data.db_id = db_id;
+}
+
+int ctdb_reply_control_db_detach(struct ctdb_reply_control *reply)
+{
+ return ctdb_reply_control_generic(reply);
+}
+
+/* CTDB_CONTROL_GET_NODES_FILE */
+
+void ctdb_req_control_get_nodes_file(struct ctdb_req_control *request)
+{
+ request->opcode = CTDB_CONTROL_GET_NODES_FILE;
+ request->pad = 0;
+ request->srvid = 0;
+ request->client_id = 0;
+ request->flags = 0;
+
+ request->rdata.opcode = CTDB_CONTROL_GET_NODES_FILE;
+}
+
+int ctdb_reply_control_get_nodes_file(struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map **nodemap)
+{
+ if (reply->status == 0 &&
+ reply->rdata.opcode == CTDB_CONTROL_GET_NODES_FILE) {
+ *nodemap = talloc_steal(mem_ctx, reply->rdata.data.nodemap);
+ }
+ return reply->status;
+}
diff --git a/ctdb/protocol/protocol_control.c b/ctdb/protocol/protocol_control.c
new file mode 100644
index 00000000000..da873510887
--- /dev/null
+++ b/ctdb/protocol/protocol_control.c
@@ -0,0 +1,2007 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_api.h"
+#include "protocol_private.h"
+
+struct ctdb_req_control_wire {
+ struct ctdb_req_header hdr;
+ uint32_t opcode;
+ uint32_t pad;
+ uint64_t srvid;
+ uint32_t client_id;
+ uint32_t flags;
+ uint32_t datalen;
+ uint8_t data[1];
+};
+
+struct ctdb_reply_control_wire {
+ struct ctdb_req_header hdr;
+ int32_t status;
+ uint32_t datalen;
+ uint32_t errorlen;
+ uint8_t data[1];
+};
+
+static size_t ctdb_req_control_data_len(struct ctdb_req_control_data *cd)
+{
+ size_t len = 0;
+ uint64_t u64;
+
+ if (cd == NULL) {
+ return 0;
+ }
+
+ switch (cd->opcode) {
+ case CTDB_CONTROL_PROCESS_EXISTS:
+ len = ctdb_pid_len(cd->data.pid);
+ break;
+
+ case CTDB_CONTROL_STATISTICS:
+ break;
+
+ case CTDB_CONTROL_PING:
+ break;
+
+ case CTDB_CONTROL_GETDBPATH:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_GETVNNMAP:
+ break;
+
+ case CTDB_CONTROL_SETVNNMAP:
+ len = ctdb_vnn_map_len(cd->data.vnnmap);
+ break;
+
+ case CTDB_CONTROL_GET_DEBUG:
+ break;
+
+ case CTDB_CONTROL_SET_DEBUG:
+ len = ctdb_uint32_len(cd->data.loglevel);
+ break;
+
+ case CTDB_CONTROL_GET_DBMAP:
+ break;
+
+ case CTDB_CONTROL_PULL_DB:
+ len = ctdb_pulldb_len(cd->data.pulldb);
+ break;
+
+ case CTDB_CONTROL_PUSH_DB:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_GET_RECMODE:
+ break;
+
+ case CTDB_CONTROL_SET_RECMODE:
+ len = ctdb_uint32_len(cd->data.recmode);
+ break;
+
+ case CTDB_CONTROL_STATISTICS_RESET:
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH:
+ len = ctdb_string_len(cd->data.db_name);
+ break;
+
+ case CTDB_CONTROL_SET_CALL:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START:
+ len = ctdb_traverse_start_len(cd->data.traverse_start);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL:
+ len = ctdb_traverse_all_len(cd->data.traverse_all);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_DATA:
+ len = ctdb_rec_data_len(cd->data.rec_data);
+ break;
+
+ case CTDB_CONTROL_REGISTER_SRVID:
+ break;
+
+ case CTDB_CONTROL_DEREGISTER_SRVID:
+ break;
+
+ case CTDB_CONTROL_GET_DBNAME:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SEQNUM:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_UPDATE_SEQNUM:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_DUMP_MEMORY:
+ break;
+
+ case CTDB_CONTROL_GET_PID:
+ break;
+
+ case CTDB_CONTROL_GET_RECMASTER:
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTER:
+ len = ctdb_uint32_len(cd->data.recmaster);
+ break;
+
+ case CTDB_CONTROL_FREEZE:
+ break;
+
+ case CTDB_CONTROL_THAW:
+ break;
+
+ case CTDB_CONTROL_GET_PNN:
+ break;
+
+ case CTDB_CONTROL_SHUTDOWN:
+ break;
+
+ case CTDB_CONTROL_GET_MONMODE:
+ break;
+
+ case CTDB_CONTROL_TCP_CLIENT:
+ len = ctdb_connection_len(cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_TCP_ADD:
+ len = ctdb_connection_len(cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_TCP_REMOVE:
+ len = ctdb_connection_len(cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_STARTUP:
+ break;
+
+ case CTDB_CONTROL_SET_TUNABLE:
+ len = ctdb_tunable_len(cd->data.tunable);
+ break;
+
+ case CTDB_CONTROL_GET_TUNABLE:
+ len = ctdb_stringn_len(cd->data.tun_var);
+ break;
+
+ case CTDB_CONTROL_LIST_TUNABLES:
+ break;
+
+ case CTDB_CONTROL_MODIFY_FLAGS:
+ len = ctdb_node_flag_change_len(cd->data.flag_change);
+ break;
+
+ case CTDB_CONTROL_GET_ALL_TUNABLES:
+ break;
+
+ case CTDB_CONTROL_KILL_TCP:
+ len = ctdb_connection_len(cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_GET_TCP_TICKLE_LIST:
+ len = ctdb_sock_addr_len(cd->data.addr);
+ break;
+
+ case CTDB_CONTROL_SET_TCP_TICKLE_LIST:
+ len = ctdb_tickle_list_len(cd->data.tickles);
+ break;
+
+ case CTDB_CONTROL_REGISTER_SERVER_ID:
+ len = ctdb_client_id_len(cd->data.cid);
+ break;
+
+ case CTDB_CONTROL_UNREGISTER_SERVER_ID:
+ len = ctdb_client_id_len(cd->data.cid);
+ break;
+
+ case CTDB_CONTROL_CHECK_SERVER_ID:
+ len = ctdb_client_id_len(cd->data.cid);
+ break;
+
+ case CTDB_CONTROL_GET_SERVER_ID_LIST:
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
+ len = ctdb_string_len(cd->data.db_name);
+ break;
+
+ case CTDB_CONTROL_UPDATE_RECORD:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_SEND_GRATUITOUS_ARP:
+ len = ctdb_addr_info_len(cd->data.addr_info);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_START:
+ len = ctdb_uint32_len(cd->data.tid);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_COMMIT:
+ len = ctdb_uint32_len(cd->data.tid);
+ break;
+
+ case CTDB_CONTROL_WIPE_DATABASE:
+ len = ctdb_transdb_len(cd->data.transdb);
+ break;
+
+ case CTDB_CONTROL_UPTIME:
+ break;
+
+ case CTDB_CONTROL_START_RECOVERY:
+ break;
+
+ case CTDB_CONTROL_END_RECOVERY:
+ break;
+
+ case CTDB_CONTROL_RELOAD_NODES_FILE:
+ break;
+
+ case CTDB_CONTROL_TRY_DELETE_RECORDS:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_ENABLE_MONITOR:
+ break;
+
+ case CTDB_CONTROL_DISABLE_MONITOR:
+ break;
+
+ case CTDB_CONTROL_ADD_PUBLIC_IP:
+ len = ctdb_addr_info_len(cd->data.addr_info);
+ break;
+
+ case CTDB_CONTROL_DEL_PUBLIC_IP:
+ len = ctdb_addr_info_len(cd->data.addr_info);
+ break;
+
+ case CTDB_CONTROL_RUN_EVENTSCRIPTS:
+ len = ctdb_string_len(cd->data.event_str);
+ break;
+
+ case CTDB_CONTROL_GET_CAPABILITIES:
+ break;
+
+ case CTDB_CONTROL_RECD_PING:
+ break;
+
+ case CTDB_CONTROL_RELEASE_IP:
+ len = ctdb_public_ip_len(cd->data.pubip);
+ break;
+
+ case CTDB_CONTROL_TAKEOVER_IP:
+ len = ctdb_public_ip_len(cd->data.pubip);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IPS:
+ break;
+
+ case CTDB_CONTROL_GET_NODEMAP:
+ break;
+
+ case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+ len = ctdb_uint32_len(cd->data.event);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_KILL:
+ len = ctdb_traverse_start_len(cd->data.traverse_start);
+ break;
+
+ case CTDB_CONTROL_RECD_RECLOCK_LATENCY:
+ len = ctdb_double_len(cd->data.reclock_latency);
+ break;
+
+ case CTDB_CONTROL_GET_RECLOCK_FILE:
+ break;
+
+ case CTDB_CONTROL_SET_RECLOCK_FILE:
+ len = ctdb_string_len(cd->data.reclock_file);
+ break;
+
+ case CTDB_CONTROL_STOP_NODE:
+ break;
+
+ case CTDB_CONTROL_CONTINUE_NODE:
+ break;
+
+ case CTDB_CONTROL_SET_NATGWSTATE:
+ len = ctdb_uint32_len(cd->data.role);
+ break;
+
+ case CTDB_CONTROL_SET_LMASTERROLE:
+ len = ctdb_uint32_len(cd->data.role);
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTERROLE:
+ len = ctdb_uint32_len(cd->data.role);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SCRIPT:
+ len = ctdb_string_len(cd->data.script);
+ break;
+
+ case CTDB_CONTROL_DISABLE_SCRIPT:
+ len = ctdb_string_len(cd->data.script);
+ break;
+
+ case CTDB_CONTROL_SET_BAN_STATE:
+ len = ctdb_ban_state_len(cd->data.ban_state);
+ break;
+
+ case CTDB_CONTROL_GET_BAN_STATE:
+ break;
+
+ case CTDB_CONTROL_SET_DB_PRIORITY:
+ len = ctdb_db_priority_len(cd->data.db_prio);
+ break;
+
+ case CTDB_CONTROL_GET_DB_PRIORITY:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_CANCEL:
+ break;
+
+ case CTDB_CONTROL_REGISTER_NOTIFY:
+ len = ctdb_notify_data_len(cd->data.notify);
+ break;
+
+ case CTDB_CONTROL_DEREGISTER_NOTIFY:
+ len = ctdb_uint64_len(cd->data.srvid);
+ break;
+
+ case CTDB_CONTROL_TRANS3_COMMIT:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_SEQNUM:
+ u64 = cd->data.db_id;
+ len = ctdb_uint64_len(u64);
+ break;
+
+ case CTDB_CONTROL_DB_SET_HEALTHY:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_DB_GET_HEALTH:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+ len = ctdb_sock_addr_len(cd->data.addr);
+ break;
+
+ case CTDB_CONTROL_GET_IFACES:
+ break;
+
+ case CTDB_CONTROL_SET_IFACE_LINK_STATE:
+ len = ctdb_iface_len(cd->data.iface);
+ break;
+
+ case CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE:
+ len = ctdb_connection_len(cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_GET_STAT_HISTORY:
+ break;
+
+ case CTDB_CONTROL_SCHEDULE_FOR_DELETION:
+ len = ctdb_key_data_len(cd->data.key);
+ break;
+
+ case CTDB_CONTROL_SET_DB_READONLY:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_CHECK_SRVIDS:
+ len = ctdb_uint64_array_len(cd->data.u64_array);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START_EXT:
+ len = ctdb_traverse_start_ext_len(cd->data.traverse_start_ext);
+ break;
+
+ case CTDB_CONTROL_GET_DB_STATISTICS:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_SET_DB_STICKY:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_RELOAD_PUBLIC_IPS:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL_EXT:
+ len = ctdb_traverse_all_ext_len(cd->data.traverse_all_ext);
+ break;
+
+ case CTDB_CONTROL_RECEIVE_RECORDS:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_IPREALLOCATED:
+ break;
+
+ case CTDB_CONTROL_GET_RUNSTATE:
+ break;
+
+ case CTDB_CONTROL_DB_DETACH:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_GET_NODES_FILE:
+ break;
+ }
+
+ return len;
+}
+
+static void ctdb_req_control_data_push(struct ctdb_req_control_data *cd,
+ uint8_t *buf)
+{
+ uint64_t u64;
+
+ switch (cd->opcode) {
+ case CTDB_CONTROL_PROCESS_EXISTS:
+ ctdb_pid_push(cd->data.pid, buf);
+ break;
+
+ case CTDB_CONTROL_GETDBPATH:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_SETVNNMAP:
+ ctdb_vnn_map_push(cd->data.vnnmap, buf);
+ break;
+
+ case CTDB_CONTROL_SET_DEBUG:
+ ctdb_uint32_push(cd->data.loglevel, buf);
+ break;
+
+ case CTDB_CONTROL_PULL_DB:
+ ctdb_pulldb_push(cd->data.pulldb, buf);
+ break;
+
+ case CTDB_CONTROL_PUSH_DB:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_SET_RECMODE:
+ ctdb_uint32_push(cd->data.recmode, buf);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH:
+ ctdb_string_push(cd->data.db_name, buf);
+ break;
+
+ case CTDB_CONTROL_SET_CALL:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START:
+ ctdb_traverse_start_push(cd->data.traverse_start, buf);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL:
+ ctdb_traverse_all_push(cd->data.traverse_all, buf);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_DATA:
+ ctdb_rec_data_push(cd->data.rec_data, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DBNAME:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SEQNUM:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_UPDATE_SEQNUM:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTER:
+ ctdb_uint32_push(cd->data.recmaster, buf);
+ break;
+
+ case CTDB_CONTROL_TCP_CLIENT:
+ ctdb_connection_push(cd->data.conn, buf);
+ break;
+
+ case CTDB_CONTROL_TCP_ADD:
+ ctdb_connection_push(cd->data.conn, buf);
+ break;
+
+ case CTDB_CONTROL_TCP_REMOVE:
+ ctdb_connection_push(cd->data.conn, buf);
+ break;
+
+ case CTDB_CONTROL_SET_TUNABLE:
+ ctdb_tunable_push(cd->data.tunable, buf);
+ break;
+
+ case CTDB_CONTROL_GET_TUNABLE:
+ ctdb_stringn_push(cd->data.tun_var, buf);
+ break;
+
+ case CTDB_CONTROL_MODIFY_FLAGS:
+ ctdb_node_flag_change_push(cd->data.flag_change, buf);
+ break;
+
+ case CTDB_CONTROL_KILL_TCP:
+ ctdb_connection_push(cd->data.conn, buf);
+ break;
+
+ case CTDB_CONTROL_GET_TCP_TICKLE_LIST:
+ ctdb_sock_addr_push(cd->data.addr, buf);
+ break;
+
+ case CTDB_CONTROL_SET_TCP_TICKLE_LIST:
+ ctdb_tickle_list_push(cd->data.tickles, buf);
+ break;
+
+ case CTDB_CONTROL_REGISTER_SERVER_ID:
+ ctdb_client_id_push(cd->data.cid, buf);
+ break;
+
+ case CTDB_CONTROL_UNREGISTER_SERVER_ID:
+ ctdb_client_id_push(cd->data.cid, buf);
+ break;
+
+ case CTDB_CONTROL_CHECK_SERVER_ID:
+ ctdb_client_id_push(cd->data.cid, buf);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
+ ctdb_string_push(cd->data.db_name, buf);
+ break;
+
+ case CTDB_CONTROL_UPDATE_RECORD:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_SEND_GRATUITOUS_ARP:
+ ctdb_addr_info_push(cd->data.addr_info, buf);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_START:
+ ctdb_uint32_push(cd->data.tid, buf);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_COMMIT:
+ ctdb_uint32_push(cd->data.tid, buf);
+ break;
+
+ case CTDB_CONTROL_WIPE_DATABASE:
+ ctdb_transdb_push(cd->data.transdb, buf);
+ break;
+
+ case CTDB_CONTROL_TRY_DELETE_RECORDS:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_ADD_PUBLIC_IP:
+ ctdb_addr_info_push(cd->data.addr_info, buf);
+ break;
+
+ case CTDB_CONTROL_DEL_PUBLIC_IP:
+ ctdb_addr_info_push(cd->data.addr_info, buf);
+ break;
+
+ case CTDB_CONTROL_RUN_EVENTSCRIPTS:
+ ctdb_string_push(cd->data.event_str, buf);
+ break;
+
+ case CTDB_CONTROL_RELEASE_IP:
+ ctdb_public_ip_push(cd->data.pubip, buf);
+ break;
+
+ case CTDB_CONTROL_TAKEOVER_IP:
+ ctdb_public_ip_push(cd->data.pubip, buf);
+ break;
+
+ case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+ ctdb_uint32_push(cd->data.event, buf);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_KILL:
+ ctdb_traverse_start_push(cd->data.traverse_start, buf);
+ break;
+
+ case CTDB_CONTROL_RECD_RECLOCK_LATENCY:
+ ctdb_double_push(cd->data.reclock_latency, buf);
+ break;
+
+ case CTDB_CONTROL_SET_RECLOCK_FILE:
+ ctdb_string_push(cd->data.reclock_file, buf);
+ break;
+
+ case CTDB_CONTROL_SET_NATGWSTATE:
+ ctdb_uint32_push(cd->data.role, buf);
+ break;
+
+ case CTDB_CONTROL_SET_LMASTERROLE:
+ ctdb_uint32_push(cd->data.role, buf);
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTERROLE:
+ ctdb_uint32_push(cd->data.role, buf);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SCRIPT:
+ ctdb_string_push(cd->data.script, buf);
+ break;
+
+ case CTDB_CONTROL_DISABLE_SCRIPT:
+ ctdb_string_push(cd->data.script, buf);
+ break;
+
+ case CTDB_CONTROL_SET_BAN_STATE:
+ ctdb_ban_state_push(cd->data.ban_state, buf);
+ break;
+
+ case CTDB_CONTROL_SET_DB_PRIORITY:
+ ctdb_db_priority_push(cd->data.db_prio, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_PRIORITY:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_REGISTER_NOTIFY:
+ ctdb_notify_data_push(cd->data.notify, buf);
+ break;
+
+ case CTDB_CONTROL_DEREGISTER_NOTIFY:
+ ctdb_uint64_push(cd->data.srvid, buf);
+ break;
+
+ case CTDB_CONTROL_TRANS3_COMMIT:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_SEQNUM:
+ u64 = cd->data.db_id;
+ ctdb_uint32_push(u64, buf);
+ break;
+
+ case CTDB_CONTROL_DB_SET_HEALTHY:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_DB_GET_HEALTH:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+ ctdb_sock_addr_push(cd->data.addr, buf);
+ break;
+
+ case CTDB_CONTROL_SET_IFACE_LINK_STATE:
+ ctdb_iface_push(cd->data.iface, buf);
+ break;
+
+ case CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE:
+ ctdb_connection_push(cd->data.conn, buf);
+ break;
+
+ case CTDB_CONTROL_SCHEDULE_FOR_DELETION:
+ ctdb_key_data_push(cd->data.key, buf);
+ break;
+
+ case CTDB_CONTROL_SET_DB_READONLY:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_CHECK_SRVIDS:
+ ctdb_uint64_array_push(cd->data.u64_array, buf);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START_EXT:
+ ctdb_traverse_start_ext_push(cd->data.traverse_start_ext, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_STATISTICS:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_SET_DB_STICKY:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL_EXT:
+ ctdb_traverse_all_ext_push(cd->data.traverse_all_ext, buf);
+ break;
+
+ case CTDB_CONTROL_RECEIVE_RECORDS:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_DB_DETACH:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+ }
+}
+
+static int ctdb_req_control_data_pull(uint8_t *buf, size_t buflen,
+ uint32_t opcode,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_control_data *cd)
+{
+ int ret = 0;
+ uint64_t u64;
+
+ cd->opcode = opcode;
+
+ switch (opcode) {
+ case CTDB_CONTROL_PROCESS_EXISTS:
+ ret = ctdb_pid_pull(buf, buflen, mem_ctx,
+ &cd->data.pid);
+ break;
+
+ case CTDB_CONTROL_GETDBPATH:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_SETVNNMAP:
+ ret = ctdb_vnn_map_pull(buf, buflen, mem_ctx,
+ &cd->data.vnnmap);
+ break;
+
+ case CTDB_CONTROL_SET_DEBUG:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.loglevel);
+ break;
+
+ case CTDB_CONTROL_PULL_DB:
+ ret = ctdb_pulldb_pull(buf, buflen, mem_ctx,
+ &cd->data.pulldb);
+ break;
+
+ case CTDB_CONTROL_PUSH_DB:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_SET_RECMODE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.recmode);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.db_name);
+ break;
+
+ case CTDB_CONTROL_SET_CALL:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START:
+ ret = ctdb_traverse_start_pull(buf, buflen, mem_ctx,
+ &cd->data.traverse_start);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL:
+ ret = ctdb_traverse_all_pull(buf, buflen, mem_ctx,
+ &cd->data.traverse_all);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_DATA:
+ ret = ctdb_rec_data_pull(buf, buflen, mem_ctx,
+ &cd->data.rec_data);
+ break;
+
+ case CTDB_CONTROL_GET_DBNAME:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SEQNUM:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_UPDATE_SEQNUM:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTER:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.recmaster);
+ break;
+
+ case CTDB_CONTROL_TCP_CLIENT:
+ ret = ctdb_connection_pull(buf, buflen, mem_ctx,
+ &cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_TCP_ADD:
+ ret = ctdb_connection_pull(buf, buflen, mem_ctx,
+ &cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_TCP_REMOVE:
+ ret = ctdb_connection_pull(buf, buflen, mem_ctx,
+ &cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_SET_TUNABLE:
+ ret = ctdb_tunable_pull(buf, buflen, mem_ctx,
+ &cd->data.tunable);
+ break;
+
+ case CTDB_CONTROL_GET_TUNABLE:
+ ret = ctdb_stringn_pull(buf, buflen, mem_ctx,
+ &cd->data.tun_var);
+ break;
+
+ case CTDB_CONTROL_MODIFY_FLAGS:
+ ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
+ &cd->data.flag_change);
+ break;
+
+ case CTDB_CONTROL_KILL_TCP:
+ ret = ctdb_connection_pull(buf, buflen, mem_ctx,
+ &cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_GET_TCP_TICKLE_LIST:
+ ret = ctdb_sock_addr_pull(buf, buflen, mem_ctx,
+ &cd->data.addr);
+ break;
+
+ case CTDB_CONTROL_SET_TCP_TICKLE_LIST:
+ ret = ctdb_tickle_list_pull(buf, buflen, mem_ctx,
+ &cd->data.tickles);
+ break;
+
+ case CTDB_CONTROL_REGISTER_SERVER_ID:
+ ret = ctdb_client_id_pull(buf, buflen, mem_ctx,
+ &cd->data.cid);
+ break;
+
+ case CTDB_CONTROL_UNREGISTER_SERVER_ID:
+ ret = ctdb_client_id_pull(buf, buflen, mem_ctx,
+ &cd->data.cid);
+ break;
+
+ case CTDB_CONTROL_CHECK_SERVER_ID:
+ ret = ctdb_client_id_pull(buf, buflen, mem_ctx,
+ &cd->data.cid);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.db_name);
+ break;
+
+ case CTDB_CONTROL_UPDATE_RECORD:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_SEND_GRATUITOUS_ARP:
+ ret = ctdb_addr_info_pull(buf, buflen, mem_ctx,
+ &cd->data.addr_info);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_START:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.tid);
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_COMMIT:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.tid);
+ break;
+
+ case CTDB_CONTROL_WIPE_DATABASE:
+ ret = ctdb_transdb_pull(buf, buflen, mem_ctx,
+ &cd->data.transdb);
+ break;
+
+ case CTDB_CONTROL_TRY_DELETE_RECORDS:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_ADD_PUBLIC_IP:
+ ret = ctdb_addr_info_pull(buf, buflen, mem_ctx,
+ &cd->data.addr_info);
+ break;
+
+ case CTDB_CONTROL_DEL_PUBLIC_IP:
+ ret = ctdb_addr_info_pull(buf, buflen, mem_ctx,
+ &cd->data.addr_info);
+ break;
+
+ case CTDB_CONTROL_RUN_EVENTSCRIPTS:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.event_str);
+ break;
+
+ case CTDB_CONTROL_RELEASE_IP:
+ ret = ctdb_public_ip_pull(buf, buflen, mem_ctx,
+ &cd->data.pubip);
+ break;
+
+ case CTDB_CONTROL_TAKEOVER_IP:
+ ret = ctdb_public_ip_pull(buf, buflen, mem_ctx,
+ &cd->data.pubip);
+ break;
+
+ case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.event);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_KILL:
+ ret = ctdb_traverse_start_pull(buf, buflen, mem_ctx,
+ &cd->data.traverse_start);
+ break;
+
+ case CTDB_CONTROL_RECD_RECLOCK_LATENCY:
+ ret = ctdb_double_pull(buf, buflen, mem_ctx,
+ &cd->data.reclock_latency);
+ break;
+
+ case CTDB_CONTROL_SET_RECLOCK_FILE:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.reclock_file);
+ break;
+
+ case CTDB_CONTROL_SET_NATGWSTATE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.role);
+ break;
+
+ case CTDB_CONTROL_SET_LMASTERROLE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.role);
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTERROLE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.role);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SCRIPT:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.script);
+ break;
+
+ case CTDB_CONTROL_DISABLE_SCRIPT:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.script);
+ break;
+
+ case CTDB_CONTROL_SET_BAN_STATE:
+ ret = ctdb_ban_state_pull(buf, buflen, mem_ctx,
+ &cd->data.ban_state);
+ break;
+
+ case CTDB_CONTROL_SET_DB_PRIORITY:
+ ret = ctdb_db_priority_pull(buf, buflen, mem_ctx,
+ &cd->data.db_prio);
+ break;
+
+ case CTDB_CONTROL_GET_DB_PRIORITY:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_REGISTER_NOTIFY:
+ ret = ctdb_notify_data_pull(buf, buflen, mem_ctx,
+ &cd->data.notify);
+ break;
+
+ case CTDB_CONTROL_DEREGISTER_NOTIFY:
+ ctdb_uint64_pull(buf, buflen, mem_ctx,
+ &cd->data.srvid);
+ break;
+
+ case CTDB_CONTROL_TRANS3_COMMIT:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_SEQNUM:
+ ret = ctdb_uint64_pull(buf, buflen, mem_ctx, &u64);
+ cd->data.db_id = (uint32_t)u64;
+ break;
+
+ case CTDB_CONTROL_DB_SET_HEALTHY:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_DB_GET_HEALTH:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+ ret = ctdb_sock_addr_pull(buf, buflen, mem_ctx,
+ &cd->data.addr);
+ break;
+
+ case CTDB_CONTROL_SET_IFACE_LINK_STATE:
+ ret = ctdb_iface_pull(buf, buflen, mem_ctx,
+ &cd->data.iface);
+ break;
+
+ case CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE:
+ ret = ctdb_connection_pull(buf, buflen, mem_ctx,
+ &cd->data.conn);
+ break;
+
+ case CTDB_CONTROL_SCHEDULE_FOR_DELETION:
+ ret = ctdb_key_data_pull(buf, buflen, mem_ctx,
+ &cd->data.key);
+ break;
+
+ case CTDB_CONTROL_SET_DB_READONLY:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_CHECK_SRVIDS:
+ ret = ctdb_uint64_array_pull(buf, buflen, mem_ctx,
+ &cd->data.u64_array);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START_EXT:
+ ret = ctdb_traverse_start_ext_pull(buf, buflen, mem_ctx,
+ &cd->data.traverse_start_ext);
+ break;
+
+ case CTDB_CONTROL_GET_DB_STATISTICS:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_SET_DB_STICKY:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL_EXT:
+ ret = ctdb_traverse_all_ext_pull(buf, buflen, mem_ctx,
+ &cd->data.traverse_all_ext);
+ break;
+
+ case CTDB_CONTROL_RECEIVE_RECORDS:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_DB_DETACH:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+ }
+
+ return ret;
+}
+
+static size_t ctdb_reply_control_data_len(struct ctdb_reply_control_data *cd)
+{
+ size_t len = 0;
+
+ if (cd == NULL) {
+ return 0;
+ }
+
+ switch (cd->opcode) {
+ case CTDB_CONTROL_PROCESS_EXISTS:
+ break;
+
+ case CTDB_CONTROL_STATISTICS:
+ len = ctdb_statistics_len(cd->data.stats);
+ break;
+
+ case CTDB_CONTROL_PING:
+ break;
+
+ case CTDB_CONTROL_GETDBPATH:
+ len = ctdb_string_len(cd->data.db_path);
+ break;
+
+ case CTDB_CONTROL_GETVNNMAP:
+ len = ctdb_vnn_map_len(cd->data.vnnmap);
+ break;
+
+ case CTDB_CONTROL_SETVNNMAP:
+ break;
+
+ case CTDB_CONTROL_GET_DEBUG:
+ len = ctdb_uint32_len(cd->data.loglevel);
+ break;
+
+ case CTDB_CONTROL_SET_DEBUG:
+ break;
+
+ case CTDB_CONTROL_GET_DBMAP:
+ len = ctdb_dbid_map_len(cd->data.dbmap);
+ break;
+
+ case CTDB_CONTROL_PULL_DB:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_PUSH_DB:
+ break;
+
+ case CTDB_CONTROL_GET_RECMODE:
+ break;
+
+ case CTDB_CONTROL_SET_RECMODE:
+ break;
+
+ case CTDB_CONTROL_STATISTICS_RESET:
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_SET_CALL:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_DATA:
+ break;
+
+ case CTDB_CONTROL_REGISTER_SRVID:
+ break;
+
+ case CTDB_CONTROL_DEREGISTER_SRVID:
+ break;
+
+ case CTDB_CONTROL_GET_DBNAME:
+ len = ctdb_string_len(cd->data.db_name);
+ break;
+
+ case CTDB_CONTROL_ENABLE_SEQNUM:
+ break;
+
+ case CTDB_CONTROL_UPDATE_SEQNUM:
+ break;
+
+ case CTDB_CONTROL_DUMP_MEMORY:
+ len = ctdb_string_len(cd->data.mem_str);
+ break;
+
+ case CTDB_CONTROL_GET_PID:
+ break;
+
+ case CTDB_CONTROL_GET_RECMASTER:
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTER:
+ break;
+
+ case CTDB_CONTROL_FREEZE:
+ break;
+
+ case CTDB_CONTROL_THAW:
+ break;
+
+ case CTDB_CONTROL_GET_PNN:
+ break;
+
+ case CTDB_CONTROL_SHUTDOWN:
+ break;
+
+ case CTDB_CONTROL_GET_MONMODE:
+ break;
+
+ case CTDB_CONTROL_TCP_CLIENT:
+ break;
+
+ case CTDB_CONTROL_TCP_ADD:
+ break;
+
+ case CTDB_CONTROL_TCP_REMOVE:
+ break;
+
+ case CTDB_CONTROL_STARTUP:
+ break;
+
+ case CTDB_CONTROL_SET_TUNABLE:
+ break;
+
+ case CTDB_CONTROL_GET_TUNABLE:
+ len = ctdb_uint32_len(cd->data.tun_value);
+ break;
+
+ case CTDB_CONTROL_LIST_TUNABLES:
+ len = ctdb_var_list_len(cd->data.tun_var_list);
+ break;
+
+ case CTDB_CONTROL_MODIFY_FLAGS:
+ break;
+
+ case CTDB_CONTROL_GET_ALL_TUNABLES:
+ len = ctdb_tunable_list_len(cd->data.tun_list);
+ break;
+
+ case CTDB_CONTROL_KILL_TCP:
+ break;
+
+ case CTDB_CONTROL_GET_TCP_TICKLE_LIST:
+ len = ctdb_tickle_list_len(cd->data.tickles);
+ break;
+
+ case CTDB_CONTROL_SET_TCP_TICKLE_LIST:
+ break;
+
+ case CTDB_CONTROL_REGISTER_SERVER_ID:
+ break;
+
+ case CTDB_CONTROL_UNREGISTER_SERVER_ID:
+ break;
+
+ case CTDB_CONTROL_CHECK_SERVER_ID:
+ break;
+
+ case CTDB_CONTROL_GET_SERVER_ID_LIST:
+ len = ctdb_client_id_map_len(cd->data.cid_map);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
+ len = ctdb_uint32_len(cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_UPDATE_RECORD:
+ break;
+
+ case CTDB_CONTROL_SEND_GRATUITOUS_ARP:
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_START:
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_COMMIT:
+ break;
+
+ case CTDB_CONTROL_WIPE_DATABASE:
+ break;
+
+ case CTDB_CONTROL_UPTIME:
+ len = ctdb_uptime_len(cd->data.uptime);
+ break;
+
+ case CTDB_CONTROL_START_RECOVERY:
+ break;
+
+ case CTDB_CONTROL_END_RECOVERY:
+ break;
+
+ case CTDB_CONTROL_RELOAD_NODES_FILE:
+ break;
+
+ case CTDB_CONTROL_TRY_DELETE_RECORDS:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_ENABLE_MONITOR:
+ break;
+
+ case CTDB_CONTROL_DISABLE_MONITOR:
+ break;
+
+ case CTDB_CONTROL_ADD_PUBLIC_IP:
+ break;
+
+ case CTDB_CONTROL_DEL_PUBLIC_IP:
+ break;
+
+ case CTDB_CONTROL_RUN_EVENTSCRIPTS:
+ break;
+
+ case CTDB_CONTROL_GET_CAPABILITIES:
+ len = ctdb_uint32_len(cd->data.caps);
+ break;
+
+ case CTDB_CONTROL_RECD_PING:
+ break;
+
+ case CTDB_CONTROL_RELEASE_IP:
+ break;
+
+ case CTDB_CONTROL_TAKEOVER_IP:
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IPS:
+ len = ctdb_public_ip_list_len(cd->data.pubip_list);
+ break;
+
+ case CTDB_CONTROL_GET_NODEMAP:
+ len = ctdb_node_map_len(cd->data.nodemap);
+ break;
+
+ case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+ len = ctdb_script_list_len(cd->data.script_list);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_KILL:
+ break;
+
+ case CTDB_CONTROL_RECD_RECLOCK_LATENCY:
+ break;
+
+ case CTDB_CONTROL_GET_RECLOCK_FILE:
+ len = ctdb_string_len(cd->data.reclock_file);
+ break;
+
+ case CTDB_CONTROL_SET_RECLOCK_FILE:
+ break;
+
+ case CTDB_CONTROL_STOP_NODE:
+ break;
+
+ case CTDB_CONTROL_CONTINUE_NODE:
+ break;
+
+ case CTDB_CONTROL_SET_NATGWSTATE:
+ break;
+
+ case CTDB_CONTROL_SET_LMASTERROLE:
+ break;
+
+ case CTDB_CONTROL_SET_RECMASTERROLE:
+ break;
+
+ case CTDB_CONTROL_ENABLE_SCRIPT:
+ break;
+
+ case CTDB_CONTROL_DISABLE_SCRIPT:
+ break;
+
+ case CTDB_CONTROL_SET_BAN_STATE:
+ break;
+
+ case CTDB_CONTROL_GET_BAN_STATE:
+ len = ctdb_ban_state_len(cd->data.ban_state);
+ break;
+
+ case CTDB_CONTROL_SET_DB_PRIORITY:
+ break;
+
+ case CTDB_CONTROL_GET_DB_PRIORITY:
+ break;
+
+ case CTDB_CONTROL_TRANSACTION_CANCEL:
+ break;
+
+ case CTDB_CONTROL_REGISTER_NOTIFY:
+ break;
+
+ case CTDB_CONTROL_DEREGISTER_NOTIFY:
+ break;
+
+ case CTDB_CONTROL_TRANS3_COMMIT:
+ break;
+
+ case CTDB_CONTROL_GET_DB_SEQNUM:
+ len = ctdb_uint64_len(cd->data.seqnum);
+ break;
+
+ case CTDB_CONTROL_DB_SET_HEALTHY:
+ break;
+
+ case CTDB_CONTROL_DB_GET_HEALTH:
+ len = ctdb_string_len(cd->data.reason);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+ len = ctdb_public_ip_info_len(cd->data.ipinfo);
+ break;
+
+ case CTDB_CONTROL_GET_IFACES:
+ len = ctdb_iface_list_len(cd->data.iface_list);
+ break;
+
+ case CTDB_CONTROL_SET_IFACE_LINK_STATE:
+ break;
+
+ case CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE:
+ break;
+
+ case CTDB_CONTROL_GET_STAT_HISTORY:
+ len = ctdb_statistics_list_len(cd->data.stats_list);
+ break;
+
+ case CTDB_CONTROL_SCHEDULE_FOR_DELETION:
+ break;
+
+ case CTDB_CONTROL_SET_DB_READONLY:
+ break;
+
+ case CTDB_CONTROL_CHECK_SRVIDS:
+ len = ctdb_uint8_array_len(cd->data.u8_array);
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_START_EXT:
+ break;
+
+ case CTDB_CONTROL_GET_DB_STATISTICS:
+ len = ctdb_db_statistics_len(cd->data.dbstats);
+ break;
+
+ case CTDB_CONTROL_SET_DB_STICKY:
+ break;
+
+ case CTDB_CONTROL_RELOAD_PUBLIC_IPS:
+ break;
+
+ case CTDB_CONTROL_TRAVERSE_ALL_EXT:
+ break;
+
+ case CTDB_CONTROL_RECEIVE_RECORDS:
+ len = ctdb_rec_buffer_len(cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_IPREALLOCATED:
+ break;
+
+ case CTDB_CONTROL_GET_RUNSTATE:
+ len = ctdb_uint32_len(cd->data.runstate);
+ break;
+
+ case CTDB_CONTROL_DB_DETACH:
+ break;
+
+ case CTDB_CONTROL_GET_NODES_FILE:
+ len = ctdb_node_map_len(cd->data.nodemap);
+ break;
+ }
+
+ return len;
+}
+
+static void ctdb_reply_control_data_push(struct ctdb_reply_control_data *cd,
+ uint8_t *buf)
+{
+ switch (cd->opcode) {
+ case CTDB_CONTROL_STATISTICS:
+ ctdb_statistics_push(cd->data.stats, buf);
+ break;
+
+ case CTDB_CONTROL_GETDBPATH:
+ ctdb_string_push(cd->data.db_path, buf);
+ break;
+
+ case CTDB_CONTROL_GETVNNMAP:
+ ctdb_vnn_map_push(cd->data.vnnmap, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DEBUG:
+ ctdb_uint32_push(cd->data.loglevel, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DBMAP:
+ ctdb_dbid_map_push(cd->data.dbmap, buf);
+ break;
+
+ case CTDB_CONTROL_PULL_DB:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_PUSH_DB:
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DBNAME:
+ ctdb_string_push(cd->data.db_name, buf);
+ break;
+
+ case CTDB_CONTROL_DUMP_MEMORY:
+ ctdb_string_push(cd->data.mem_str, buf);
+ break;
+
+ case CTDB_CONTROL_GET_PID:
+ break;
+
+ case CTDB_CONTROL_GET_RECMASTER:
+ break;
+
+ case CTDB_CONTROL_GET_TUNABLE:
+ ctdb_uint32_push(cd->data.tun_value, buf);
+ break;
+
+ case CTDB_CONTROL_LIST_TUNABLES:
+ ctdb_var_list_push(cd->data.tun_var_list, buf);
+ break;
+
+ case CTDB_CONTROL_GET_ALL_TUNABLES:
+ ctdb_tunable_list_push(cd->data.tun_list, buf);
+ break;
+
+ case CTDB_CONTROL_GET_TCP_TICKLE_LIST:
+ ctdb_tickle_list_push(cd->data.tickles, buf);
+ break;
+
+ case CTDB_CONTROL_GET_SERVER_ID_LIST:
+ ctdb_client_id_map_push(cd->data.cid_map, buf);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
+ ctdb_uint32_push(cd->data.db_id, buf);
+ break;
+
+ case CTDB_CONTROL_UPTIME:
+ ctdb_uptime_push(cd->data.uptime, buf);
+ break;
+
+ case CTDB_CONTROL_TRY_DELETE_RECORDS:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_GET_CAPABILITIES:
+ ctdb_uint32_push(cd->data.caps, buf);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IPS:
+ ctdb_public_ip_list_push(cd->data.pubip_list, buf);
+ break;
+
+ case CTDB_CONTROL_GET_NODEMAP:
+ ctdb_node_map_push(cd->data.nodemap, buf);
+ break;
+
+ case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+ ctdb_script_list_push(cd->data.script_list, buf);
+ break;
+
+ case CTDB_CONTROL_GET_RECLOCK_FILE:
+ ctdb_string_push(cd->data.reclock_file, buf);
+ break;
+
+ case CTDB_CONTROL_GET_BAN_STATE:
+ ctdb_ban_state_push(cd->data.ban_state, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_PRIORITY:
+ break;
+
+ case CTDB_CONTROL_GET_DB_SEQNUM:
+ ctdb_uint64_push(cd->data.seqnum, buf);
+ break;
+
+ case CTDB_CONTROL_DB_GET_HEALTH:
+ ctdb_string_push(cd->data.reason, buf);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+ ctdb_public_ip_info_push(cd->data.ipinfo, buf);
+ break;
+
+ case CTDB_CONTROL_GET_IFACES:
+ ctdb_iface_list_push(cd->data.iface_list, buf);
+ break;
+
+ case CTDB_CONTROL_GET_STAT_HISTORY:
+ ctdb_statistics_list_push(cd->data.stats_list, buf);
+ break;
+
+ case CTDB_CONTROL_CHECK_SRVIDS:
+ ctdb_uint8_array_push(cd->data.u8_array, buf);
+ break;
+
+ case CTDB_CONTROL_GET_DB_STATISTICS:
+ ctdb_db_statistics_push(cd->data.dbstats, buf);
+ break;
+
+ case CTDB_CONTROL_RECEIVE_RECORDS:
+ ctdb_rec_buffer_push(cd->data.recbuf, buf);
+ break;
+
+ case CTDB_CONTROL_GET_RUNSTATE:
+ ctdb_uint32_push(cd->data.runstate, buf);
+ break;
+
+ case CTDB_CONTROL_GET_NODES_FILE:
+ ctdb_node_map_push(cd->data.nodemap, buf);
+ break;
+ }
+}
+
+static int ctdb_reply_control_data_pull(uint8_t *buf, size_t buflen,
+ uint32_t opcode, TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_control_data *cd)
+{
+ int ret = 0;
+ cd->opcode = opcode;
+
+ switch (opcode) {
+ case CTDB_CONTROL_STATISTICS:
+ ret = ctdb_statistics_pull(buf, buflen, mem_ctx,
+ &cd->data.stats);
+ break;
+
+ case CTDB_CONTROL_GETDBPATH:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.db_path);
+ break;
+
+ case CTDB_CONTROL_GETVNNMAP:
+ ret = ctdb_vnn_map_pull(buf, buflen, mem_ctx,
+ &cd->data.vnnmap);
+ break;
+
+ case CTDB_CONTROL_GET_DEBUG:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.loglevel);
+ break;
+
+ case CTDB_CONTROL_GET_DBMAP:
+ ret = ctdb_dbid_map_pull(buf, buflen, mem_ctx,
+ &cd->data.dbmap);
+ break;
+
+ case CTDB_CONTROL_PULL_DB:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_PUSH_DB:
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_GET_DBNAME:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.db_name);
+ break;
+
+ case CTDB_CONTROL_DUMP_MEMORY:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.mem_str);
+ break;
+
+ case CTDB_CONTROL_GET_PID:
+ break;
+
+ case CTDB_CONTROL_GET_RECMASTER:
+ break;
+
+ case CTDB_CONTROL_GET_TUNABLE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.tun_value);
+ break;
+
+ case CTDB_CONTROL_LIST_TUNABLES:
+ ret = ctdb_var_list_pull(buf, buflen, mem_ctx,
+ &cd->data.tun_var_list);
+ break;
+
+ case CTDB_CONTROL_GET_ALL_TUNABLES:
+ ret = ctdb_tunable_list_pull(buf, buflen, mem_ctx,
+ &cd->data.tun_list);
+ break;
+
+ case CTDB_CONTROL_GET_TCP_TICKLE_LIST:
+ ret = ctdb_tickle_list_pull(buf, buflen, mem_ctx,
+ &cd->data.tickles);
+ break;
+
+ case CTDB_CONTROL_GET_SERVER_ID_LIST:
+ ret = ctdb_client_id_map_pull(buf, buflen, mem_ctx,
+ &cd->data.cid_map);
+ break;
+
+ case CTDB_CONTROL_DB_ATTACH_PERSISTENT:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.db_id);
+ break;
+
+ case CTDB_CONTROL_UPTIME:
+ ret = ctdb_uptime_pull(buf, buflen, mem_ctx,
+ &cd->data.uptime);
+ break;
+
+ case CTDB_CONTROL_TRY_DELETE_RECORDS:
+ ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_GET_CAPABILITIES:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.caps);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IPS:
+ ret = ctdb_public_ip_list_pull(buf, buflen, mem_ctx,
+ &cd->data.pubip_list);
+ break;
+
+ case CTDB_CONTROL_GET_NODEMAP:
+ ret = ctdb_node_map_pull(buf, buflen, mem_ctx,
+ &cd->data.nodemap);
+ break;
+
+ case CTDB_CONTROL_GET_EVENT_SCRIPT_STATUS:
+ ret = ctdb_script_list_pull(buf, buflen, mem_ctx,
+ &cd->data.script_list);
+ break;
+
+ case CTDB_CONTROL_GET_RECLOCK_FILE:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.reclock_file);
+ break;
+
+ case CTDB_CONTROL_GET_BAN_STATE:
+ ret = ctdb_ban_state_pull(buf, buflen, mem_ctx,
+ &cd->data.ban_state);
+ break;
+
+ case CTDB_CONTROL_GET_DB_PRIORITY:
+ break;
+
+ case CTDB_CONTROL_GET_DB_SEQNUM:
+ ret = ctdb_uint64_pull(buf, buflen, mem_ctx,
+ &cd->data.seqnum);
+ break;
+
+ case CTDB_CONTROL_DB_GET_HEALTH:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx,
+ &cd->data.reason);
+ break;
+
+ case CTDB_CONTROL_GET_PUBLIC_IP_INFO:
+ ret = ctdb_public_ip_info_pull(buf, buflen, mem_ctx,
+ &cd->data.ipinfo);
+ break;
+
+ case CTDB_CONTROL_GET_IFACES:
+ ret = ctdb_iface_list_pull(buf, buflen, mem_ctx,
+ &cd->data.iface_list);
+ break;
+
+ case CTDB_CONTROL_GET_STAT_HISTORY:
+ ret = ctdb_statistics_list_pull(buf, buflen, mem_ctx,
+ &cd->data.stats_list);
+ break;
+
+ case CTDB_CONTROL_CHECK_SRVIDS:
+ ret = ctdb_uint8_array_pull(buf, buflen, mem_ctx,
+ &cd->data.u8_array);
+ break;
+
+ case CTDB_CONTROL_GET_DB_STATISTICS:
+ ret = ctdb_db_statistics_pull(buf, buflen, mem_ctx,
+ &cd->data.dbstats);
+ break;
+
+ case CTDB_CONTROL_RECEIVE_RECORDS:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &cd->data.recbuf);
+ break;
+
+ case CTDB_CONTROL_GET_RUNSTATE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx,
+ &cd->data.runstate);
+ break;
+
+ case CTDB_CONTROL_GET_NODES_FILE:
+ ret = ctdb_node_map_pull(buf, buflen, mem_ctx,
+ &cd->data.nodemap);
+ break;
+ }
+
+ return ret;
+}
+
+int ctdb_req_control_push(struct ctdb_req_header *h,
+ struct ctdb_req_control *request,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_req_control_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen, datalen;
+ int ret;
+
+ datalen = ctdb_req_control_data_len(&request->rdata);
+ length = offsetof(struct ctdb_req_control_wire, data) + datalen;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_req_control_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->opcode = request->opcode;
+ wire->pad = request->pad;
+ wire->srvid = request->srvid;
+ wire->client_id = request->client_id;
+ wire->flags = request->flags;
+
+ wire->datalen = datalen;
+ ctdb_req_control_data_push(&request->rdata, wire->data);
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_req_control_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_control *request)
+{
+ struct ctdb_req_control_wire *wire =
+ (struct ctdb_req_control_wire *)pkt;
+ size_t length;
+ int ret;
+
+ length = offsetof(struct ctdb_req_control_wire, data);
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+ if (pkt_len < length + wire->datalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ request->opcode = wire->opcode;
+ request->pad = wire->pad;
+ request->srvid = wire->srvid;
+ request->client_id = wire->client_id;
+ request->flags = wire->flags;
+
+ ret = ctdb_req_control_data_pull(wire->data, wire->datalen,
+ request->opcode, mem_ctx,
+ &request->rdata);
+ if (ret != 0) {
+ return ret;
+ }
+
+ return 0;
+}
+
+int ctdb_reply_control_push(struct ctdb_req_header *h,
+ struct ctdb_reply_control *reply,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_reply_control_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen, datalen, errlen;
+ int ret;
+
+ if (reply->status == 0) {
+ datalen = ctdb_reply_control_data_len(&reply->rdata);
+ } else {
+ datalen = 0;
+ }
+
+ if (reply->errmsg == NULL) {
+ errlen = 0;
+ } else {
+ errlen = strlen(reply->errmsg) + 1;
+ }
+
+ length = offsetof(struct ctdb_reply_control_wire, data) +
+ datalen + errlen;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_reply_control_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->status = reply->status;
+
+ wire->datalen = datalen;
+ if (reply->status == 0) {
+ ctdb_reply_control_data_push(&reply->rdata, wire->data);
+ }
+
+ wire->errorlen = errlen;
+ if (errlen > 0) {
+ memcpy(wire->data + datalen, reply->errmsg, wire->errorlen);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_reply_control_pull(uint8_t *pkt, size_t pkt_len, uint32_t opcode,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_reply_control *reply)
+{
+ struct ctdb_reply_control_wire *wire =
+ (struct ctdb_reply_control_wire *)pkt;
+ size_t length;
+ int ret;
+
+ length = offsetof(struct ctdb_reply_control_wire, data);
+
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+ if (pkt_len < length + wire->datalen + wire->errorlen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ reply->status = wire->status;
+
+ if (reply->status != -1) {
+ ret = ctdb_reply_control_data_pull(wire->data, wire->datalen,
+ opcode, mem_ctx,
+ &reply->rdata);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ if (wire->errorlen > 0) {
+ reply->errmsg = talloc_memdup(mem_ctx,
+ wire->data + wire->datalen,
+ wire->errorlen);
+ } else {
+ reply->errmsg = NULL;
+ }
+
+ return 0;
+}
diff --git a/ctdb/protocol/protocol_header.c b/ctdb/protocol/protocol_header.c
new file mode 100644
index 00000000000..b802d082dcd
--- /dev/null
+++ b/ctdb/protocol/protocol_header.c
@@ -0,0 +1,73 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_api.h"
+
+int ctdb_req_header_verify(struct ctdb_req_header *h, uint32_t operation)
+{
+ if (h->length < sizeof(struct ctdb_req_header)) {
+ return EMSGSIZE;
+ }
+
+ if (h->ctdb_magic != CTDB_MAGIC) {
+ return EPROTO;
+ }
+
+ if (h->ctdb_version != CTDB_PROTOCOL) {
+ return EPROTO;
+ }
+
+ if (operation != 0 && h->operation != operation) {
+ return EPROTO;
+ }
+
+ return 0;
+}
+
+void ctdb_req_header_fill(struct ctdb_req_header *h, uint32_t generation,
+ uint32_t operation, uint32_t destnode,
+ uint32_t srcnode, uint32_t reqid)
+{
+ h->length = sizeof(struct ctdb_req_header);
+ h->ctdb_magic = CTDB_MAGIC;
+ h->ctdb_version = CTDB_PROTOCOL;
+ h->generation = generation;
+ h->operation = operation;
+ h->destnode = destnode;
+ h->srcnode = srcnode;
+ h->reqid = reqid;
+}
+
+int ctdb_req_header_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h)
+{
+ if (pkt_len < sizeof(struct ctdb_req_header)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, pkt, sizeof(struct ctdb_req_header));
+ return 0;
+}
diff --git a/ctdb/protocol/protocol_message.c b/ctdb/protocol/protocol_message.c
new file mode 100644
index 00000000000..07d2dbb0ae0
--- /dev/null
+++ b/ctdb/protocol/protocol_message.c
@@ -0,0 +1,383 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_api.h"
+#include "protocol_private.h"
+
+struct ctdb_req_message_wire {
+ struct ctdb_req_header hdr;
+ uint64_t srvid;
+ uint32_t datalen;
+ uint8_t data[1];
+};
+
+static size_t ctdb_message_data_len(union ctdb_message_data *mdata,
+ uint64_t srvid)
+{
+ size_t len = 0;
+
+ switch (srvid) {
+ case CTDB_SRVID_ELECTION:
+ len = ctdb_election_message_len(mdata->election);
+ break;
+
+ case CTDB_SRVID_RECONFIGURE:
+ break;
+
+ case CTDB_SRVID_RELEASE_IP:
+ len = ctdb_string_len(mdata->ipaddr);
+ break;
+
+ case CTDB_SRVID_TAKE_IP:
+ len = ctdb_string_len(mdata->ipaddr);
+ break;
+
+ case CTDB_SRVID_SET_NODE_FLAGS:
+ len = ctdb_node_flag_change_len(mdata->flag_change);
+ break;
+
+ case CTDB_SRVID_RECD_UPDATE_IP:
+ len = ctdb_public_ip_len(mdata->pubip);
+ break;
+
+ case CTDB_SRVID_VACUUM_FETCH:
+ len = ctdb_rec_buffer_len(mdata->recbuf);
+ break;
+
+ case CTDB_SRVID_DETACH_DATABASE:
+ len = ctdb_uint32_len(mdata->db_id);
+ break;
+
+ case CTDB_SRVID_MEM_DUMP:
+ len = ctdb_srvid_message_len(mdata->msg);
+ break;
+
+ case CTDB_SRVID_PUSH_NODE_FLAGS:
+ len = ctdb_node_flag_change_len(mdata->flag_change);
+ break;
+
+ case CTDB_SRVID_RELOAD_NODES:
+ break;
+
+ case CTDB_SRVID_TAKEOVER_RUN:
+ len = ctdb_srvid_message_len(mdata->msg);
+ break;
+
+ case CTDB_SRVID_REBALANCE_NODE:
+ len = ctdb_uint32_len(mdata->pnn);
+ break;
+
+ case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
+ len = ctdb_disable_message_len(mdata->disable);
+ break;
+
+ case CTDB_SRVID_DISABLE_RECOVERIES:
+ len = ctdb_disable_message_len(mdata->disable);
+ break;
+
+ case CTDB_SRVID_DISABLE_IP_CHECK:
+ len = ctdb_uint32_len(mdata->timeout);
+ break;
+ }
+
+ return len;
+}
+
+static void ctdb_message_data_push(union ctdb_message_data *mdata,
+ uint64_t srvid, uint8_t *buf)
+{
+ switch (srvid) {
+ case CTDB_SRVID_ELECTION:
+ ctdb_election_message_push(mdata->election, buf);
+ break;
+
+ case CTDB_SRVID_RECONFIGURE:
+ break;
+
+ case CTDB_SRVID_RELEASE_IP:
+ ctdb_string_push(mdata->ipaddr, buf);
+ break;
+
+ case CTDB_SRVID_TAKE_IP:
+ ctdb_string_push(mdata->ipaddr, buf);
+ break;
+
+ case CTDB_SRVID_SET_NODE_FLAGS:
+ ctdb_node_flag_change_push(mdata->flag_change, buf);
+ break;
+
+ case CTDB_SRVID_RECD_UPDATE_IP:
+ ctdb_public_ip_push(mdata->pubip, buf);
+ break;
+
+ case CTDB_SRVID_VACUUM_FETCH:
+ ctdb_rec_buffer_push(mdata->recbuf, buf);
+ break;
+
+ case CTDB_SRVID_DETACH_DATABASE:
+ ctdb_uint32_push(mdata->db_id, buf);
+ break;
+
+ case CTDB_SRVID_MEM_DUMP:
+ ctdb_srvid_message_push(mdata->msg, buf);
+ break;
+
+ case CTDB_SRVID_PUSH_NODE_FLAGS:
+ ctdb_node_flag_change_push(mdata->flag_change, buf);
+ break;
+
+ case CTDB_SRVID_RELOAD_NODES:
+ break;
+
+ case CTDB_SRVID_TAKEOVER_RUN:
+ ctdb_srvid_message_push(mdata->msg, buf);
+ break;
+
+ case CTDB_SRVID_REBALANCE_NODE:
+ ctdb_uint32_push(mdata->pnn, buf);
+ break;
+
+ case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
+ ctdb_disable_message_push(mdata->disable, buf);
+ break;
+
+ case CTDB_SRVID_DISABLE_RECOVERIES:
+ ctdb_disable_message_push(mdata->disable, buf);
+ break;
+
+ case CTDB_SRVID_DISABLE_IP_CHECK:
+ ctdb_uint32_push(mdata->timeout, buf);
+ break;
+ }
+}
+
+static int ctdb_message_data_pull(uint8_t *buf, size_t buflen,
+ uint64_t srvid, TALLOC_CTX *mem_ctx,
+ union ctdb_message_data *mdata)
+{
+ int ret = 0;
+
+ switch (srvid) {
+ case CTDB_SRVID_ELECTION:
+ ret = ctdb_election_message_pull(buf, buflen, mem_ctx,
+ &mdata->election);
+ break;
+
+ case CTDB_SRVID_RECONFIGURE:
+ break;
+
+ case CTDB_SRVID_RELEASE_IP:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr);
+ break;
+
+ case CTDB_SRVID_TAKE_IP:
+ ret = ctdb_string_pull(buf, buflen, mem_ctx, &mdata->ipaddr);
+ break;
+
+ case CTDB_SRVID_SET_NODE_FLAGS:
+ ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
+ &mdata->flag_change);
+ break;
+
+ case CTDB_SRVID_RECD_UPDATE_IP:
+ ret = ctdb_public_ip_pull(buf, buflen, mem_ctx,
+ &mdata->pubip);
+ break;
+
+ case CTDB_SRVID_VACUUM_FETCH:
+ ret = ctdb_rec_buffer_pull(buf, buflen, mem_ctx,
+ &mdata->recbuf);
+ break;
+
+ case CTDB_SRVID_DETACH_DATABASE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->db_id);
+ break;
+
+ case CTDB_SRVID_MEM_DUMP:
+ ret = ctdb_srvid_message_pull(buf, buflen, mem_ctx,
+ &mdata->msg);
+ break;
+
+ case CTDB_SRVID_PUSH_NODE_FLAGS:
+ ret = ctdb_node_flag_change_pull(buf, buflen, mem_ctx,
+ &mdata->flag_change);
+ break;
+
+ case CTDB_SRVID_RELOAD_NODES:
+ break;
+
+ case CTDB_SRVID_TAKEOVER_RUN:
+ ret = ctdb_srvid_message_pull(buf, buflen, mem_ctx,
+ &mdata->msg);
+ break;
+
+ case CTDB_SRVID_REBALANCE_NODE:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->pnn);
+ break;
+
+ case CTDB_SRVID_DISABLE_TAKEOVER_RUNS:
+ ret = ctdb_disable_message_pull(buf, buflen, mem_ctx,
+ &mdata->disable);
+ break;
+
+ case CTDB_SRVID_DISABLE_RECOVERIES:
+ ret = ctdb_disable_message_pull(buf, buflen, mem_ctx,
+ &mdata->disable);
+ break;
+
+ case CTDB_SRVID_DISABLE_IP_CHECK:
+ ret = ctdb_uint32_pull(buf, buflen, mem_ctx, &mdata->timeout);
+ break;
+ }
+
+ return ret;
+}
+
+int ctdb_req_message_push(struct ctdb_req_header *h,
+ struct ctdb_req_message *message,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_req_message_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen, datalen;
+ int ret;
+
+ datalen = ctdb_message_data_len(&message->data, message->srvid);
+ length = offsetof(struct ctdb_req_message_wire, data) + datalen;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_req_message_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->srvid = message->srvid;
+ wire->datalen = datalen;
+ ctdb_message_data_push(&message->data, message->srvid, wire->data);
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_req_message_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_message *message)
+{
+ struct ctdb_req_message_wire *wire =
+ (struct ctdb_req_message_wire *)pkt;
+ size_t length;
+ int ret;
+
+ length = offsetof(struct ctdb_req_message_wire, data);
+
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+ if (pkt_len < length + wire->datalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ message->srvid = wire->srvid;
+ ret = ctdb_message_data_pull(wire->data, wire->datalen, wire->srvid,
+ mem_ctx, &message->data);
+ return ret;
+}
+
+int ctdb_req_message_data_push(struct ctdb_req_header *h,
+ struct ctdb_req_message_data *message,
+ TALLOC_CTX *mem_ctx,
+ uint8_t **pkt, size_t *pkt_len)
+{
+ struct ctdb_req_message_wire *wire;
+ uint8_t *buf;
+ size_t length, buflen;
+ int ret;
+
+ length = offsetof(struct ctdb_req_message_wire, data) +
+ message->data.dsize;
+
+ ret = allocate_pkt(mem_ctx, length, &buf, &buflen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ wire = (struct ctdb_req_message_wire *)buf;
+
+ h->length = buflen;
+ memcpy(&wire->hdr, h, sizeof(struct ctdb_req_header));
+
+ wire->srvid = message->srvid;
+ wire->datalen = message->data.dsize;
+ if (message->data.dsize > 0) {
+ memcpy(wire->data, message->data.dptr, message->data.dsize);
+ }
+
+ *pkt = buf;
+ *pkt_len = buflen;
+ return 0;
+}
+
+int ctdb_req_message_data_pull(uint8_t *pkt, size_t pkt_len,
+ struct ctdb_req_header *h,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_req_message_data *message)
+{
+ struct ctdb_req_message_wire *wire =
+ (struct ctdb_req_message_wire *)pkt;
+ size_t length;
+
+ length = offsetof(struct ctdb_req_message_wire, data);
+
+ if (pkt_len < length) {
+ return EMSGSIZE;
+ }
+ if (pkt_len < length + wire->datalen) {
+ return EMSGSIZE;
+ }
+
+ memcpy(h, &wire->hdr, sizeof(struct ctdb_req_header));
+
+ message->srvid = wire->srvid;
+ message->data.dsize = wire->datalen;
+ if (wire->datalen > 0) {
+ message->data.dptr = talloc_memdup(mem_ctx, wire->data,
+ wire->datalen);
+ if (message->data.dptr == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
diff --git a/ctdb/protocol/protocol_packet.c b/ctdb/protocol/protocol_packet.c
new file mode 100644
index 00000000000..0e1a61cd1ba
--- /dev/null
+++ b/ctdb/protocol/protocol_packet.c
@@ -0,0 +1,44 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol_private.h"
+
+#define CTDB_DS_ALIGNMENT 8
+
+int allocate_pkt(TALLOC_CTX *mem_ctx, size_t length,
+ uint8_t **buf, size_t *buflen)
+{
+ size_t new_length;
+
+ new_length = (length + CTDB_DS_ALIGNMENT-1) & ~(CTDB_DS_ALIGNMENT-1);
+
+ *buflen = new_length;
+ *buf = talloc_zero_size(mem_ctx, new_length);
+ if (*buf == NULL) {
+ return ENOMEM;
+ }
+
+ return 0;
+}
diff --git a/ctdb/protocol/protocol_private.h b/ctdb/protocol/protocol_private.h
new file mode 100644
index 00000000000..ffe3fb2017e
--- /dev/null
+++ b/ctdb/protocol/protocol_private.h
@@ -0,0 +1,274 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __PROTOCOL_PRIVATE_H__
+#define __PROTOCOL_PRIVATE_H__
+
+#include "protocol.h"
+
+int allocate_pkt(TALLOC_CTX *mem_ctx, size_t length,
+ uint8_t **buf, size_t *buflen);
+
+size_t ctdb_uint32_len(uint32_t val);
+void ctdb_uint32_push(uint32_t val, uint8_t *buf);
+int ctdb_uint32_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ uint32_t *out);
+
+size_t ctdb_uint64_len(uint64_t val);
+void ctdb_uint64_push(uint64_t val, uint8_t *buf);
+int ctdb_uint64_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ uint64_t *out);
+
+size_t ctdb_double_len(double val);
+void ctdb_double_push(double val, uint8_t *buf);
+int ctdb_double_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ double *out);
+
+size_t ctdb_uint8_array_len(struct ctdb_uint8_array *array);
+void ctdb_uint8_array_push(struct ctdb_uint8_array *array, uint8_t *buf);
+int ctdb_uint8_array_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_uint8_array **out);
+
+size_t ctdb_uint64_array_len(struct ctdb_uint64_array *array);
+void ctdb_uint64_array_push(struct ctdb_uint64_array *array, uint8_t *buf);
+int ctdb_uint64_array_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_uint64_array **out);
+
+size_t ctdb_pid_len(pid_t pid);
+void ctdb_pid_push(pid_t pid, uint8_t *buf);
+int ctdb_pid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ pid_t *out);
+
+size_t ctdb_string_len(const char *str);
+void ctdb_string_push(const char *str, uint8_t *buf);
+int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ const char **out);
+
+size_t ctdb_stringn_len(const char *str);
+void ctdb_stringn_push(const char *str, uint8_t *buf);
+int ctdb_stringn_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ const char **out);
+
+size_t ctdb_statistics_len(struct ctdb_statistics *stats);
+void ctdb_statistics_push(struct ctdb_statistics *stats, uint8_t *buf);
+int ctdb_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics **out);
+
+size_t ctdb_statistics_list_len(struct ctdb_statistics_list *stats_list);
+void ctdb_statistics_list_push(struct ctdb_statistics_list *stats_list,
+ uint8_t *buf);
+int ctdb_statistics_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics_list **out);
+
+size_t ctdb_vnn_map_len(struct ctdb_vnn_map *vnnmap);
+void ctdb_vnn_map_push(struct ctdb_vnn_map *vnnmap, uint8_t *buf);
+int ctdb_vnn_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_vnn_map **out);
+
+size_t ctdb_dbid_map_len(struct ctdb_dbid_map *dbmap);
+void ctdb_dbid_map_push(struct ctdb_dbid_map *dbmap, uint8_t *buf);
+int ctdb_dbid_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_dbid_map **out);
+
+size_t ctdb_pulldb_len(struct ctdb_pulldb *pulldb);
+void ctdb_pulldb_push(struct ctdb_pulldb *pulldb, uint8_t *buf);
+int ctdb_pulldb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_pulldb **out);
+
+size_t ctdb_traverse_start_len(struct ctdb_traverse_start *traverse);
+void ctdb_traverse_start_push(struct ctdb_traverse_start *traverse,
+ uint8_t *buf);
+int ctdb_traverse_start_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_start **out);
+
+size_t ctdb_traverse_all_len(struct ctdb_traverse_all *traverse);
+void ctdb_traverse_all_push(struct ctdb_traverse_all *traverse, uint8_t *buf);
+int ctdb_traverse_all_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_all **out);
+
+size_t ctdb_traverse_start_ext_len(struct ctdb_traverse_start_ext *traverse);
+void ctdb_traverse_start_ext_push(struct ctdb_traverse_start_ext *traverse,
+ uint8_t *buf);
+int ctdb_traverse_start_ext_pull(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_start_ext **out);
+
+size_t ctdb_traverse_all_ext_len(struct ctdb_traverse_all_ext *traverse);
+void ctdb_traverse_all_ext_push(struct ctdb_traverse_all_ext *traverse,
+ uint8_t *buf);
+int ctdb_traverse_all_ext_pull(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_all_ext **out);
+
+size_t ctdb_sock_addr_len(ctdb_sock_addr *addr);
+void ctdb_sock_addr_push(ctdb_sock_addr *addr, uint8_t *buf);
+int ctdb_sock_addr_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ ctdb_sock_addr **out);
+
+size_t ctdb_connection_len(struct ctdb_connection *conn);
+void ctdb_connection_push(struct ctdb_connection *conn, uint8_t *buf);
+int ctdb_connection_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_connection **out);
+
+size_t ctdb_tunable_len(struct ctdb_tunable *tunable);
+void ctdb_tunable_push(struct ctdb_tunable *tunable, uint8_t *buf);
+int ctdb_tunable_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_tunable **out);
+
+size_t ctdb_node_flag_change_len(struct ctdb_node_flag_change *flag_change);
+void ctdb_node_flag_change_push(struct ctdb_node_flag_change *flag_change,
+ uint8_t *buf);
+int ctdb_node_flag_change_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_node_flag_change **out);
+
+size_t ctdb_var_list_len(struct ctdb_var_list *var_list);
+void ctdb_var_list_push(struct ctdb_var_list *var_list, uint8_t *buf);
+int ctdb_var_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_var_list **out);
+
+size_t ctdb_tunable_list_len(struct ctdb_tunable_list *tun_list);
+void ctdb_tunable_list_push(struct ctdb_tunable_list *tun_list, uint8_t *buf);
+int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_tunable_list **out);
+
+size_t ctdb_tickle_list_len(struct ctdb_tickle_list *tickles);
+void ctdb_tickle_list_push(struct ctdb_tickle_list *tickles, uint8_t *buf);
+int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_tickle_list **out);
+
+size_t ctdb_client_id_len(struct ctdb_client_id *cid);
+void ctdb_client_id_push(struct ctdb_client_id *cid, uint8_t *buf);
+int ctdb_client_id_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id **out);
+
+size_t ctdb_client_id_list_len(struct ctdb_client_id_list *cid_list);
+void ctdb_client_id_list_push(struct ctdb_client_id_list *cid_list,
+ uint8_t *buf);
+int ctdb_client_id_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_list **out);
+
+size_t ctdb_client_id_map_len(struct ctdb_client_id_map *cid_map);
+void ctdb_client_id_map_push(struct ctdb_client_id_map *cid_map, uint8_t *buf);
+int ctdb_client_id_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_map **out);
+
+size_t ctdb_addr_info_len(struct ctdb_addr_info *addr_info);
+void ctdb_addr_info_push(struct ctdb_addr_info *addr_info, uint8_t *buf);
+int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_addr_info **out);
+
+size_t ctdb_transdb_len(struct ctdb_transdb *transdb);
+void ctdb_transdb_push(struct ctdb_transdb *transdb, uint8_t *buf);
+int ctdb_transdb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_transdb **out);
+
+size_t ctdb_uptime_len(struct ctdb_uptime *uptime);
+void ctdb_uptime_push(struct ctdb_uptime *uptime, uint8_t *buf);
+int ctdb_uptime_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_uptime **out);
+
+size_t ctdb_public_ip_len(struct ctdb_public_ip *public_ip);
+void ctdb_public_ip_push(struct ctdb_public_ip *public_ip, uint8_t *buf);
+int ctdb_public_ip_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip **out);
+
+size_t ctdb_public_ip_list_len(struct ctdb_public_ip_list *pubip_list);
+void ctdb_public_ip_list_push(struct ctdb_public_ip_list *pubip_list,
+ uint8_t *buf);
+int ctdb_public_ip_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_list **out);
+
+size_t ctdb_node_and_flags_len(struct ctdb_node_and_flags *node);
+void ctdb_node_and_flags_push(struct ctdb_node_and_flags *node, uint8_t *buf);
+int ctdb_node_and_flags_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_node_and_flags **out);
+
+size_t ctdb_node_map_len(struct ctdb_node_map *nodemap);
+void ctdb_node_map_push(struct ctdb_node_map *nodemap, uint8_t *buf);
+int ctdb_node_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map **out);
+
+size_t ctdb_script_len(struct ctdb_script *script);
+void ctdb_script_push(struct ctdb_script *script, uint8_t *buf);
+int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_script **out);
+
+size_t ctdb_script_list_len(struct ctdb_script_list *script_list);
+void ctdb_script_list_push(struct ctdb_script_list *script_list, uint8_t *buf);
+int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_script_list **out);
+
+size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state);
+void ctdb_ban_state_push(struct ctdb_ban_state *ban_state, uint8_t *buf);
+int ctdb_ban_state_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_ban_state **out);
+
+size_t ctdb_db_priority_len(struct ctdb_db_priority *db_prio);
+void ctdb_db_priority_push(struct ctdb_db_priority *db_prio, uint8_t *buf);
+int ctdb_db_priority_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_db_priority **out);
+
+size_t ctdb_notify_data_len(struct ctdb_notify_data *notify);
+void ctdb_notify_data_push(struct ctdb_notify_data *notify, uint8_t *buf);
+int ctdb_notify_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_notify_data **out);
+
+size_t ctdb_iface_len(struct ctdb_iface *iface);
+void ctdb_iface_push(struct ctdb_iface *iface, uint8_t *buf);
+int ctdb_iface_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_iface **out);
+
+size_t ctdb_iface_list_len(struct ctdb_iface_list *iface_list);
+void ctdb_iface_list_push(struct ctdb_iface_list *iface_list, uint8_t *buf);
+int ctdb_iface_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_iface_list **out);
+
+size_t ctdb_public_ip_info_len(struct ctdb_public_ip_info *ipinfo);
+void ctdb_public_ip_info_push(struct ctdb_public_ip_info *ipinfo, uint8_t *buf);
+int ctdb_public_ip_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_info **out);
+
+size_t ctdb_key_data_len(struct ctdb_key_data *key);
+void ctdb_key_data_push(struct ctdb_key_data *key, uint8_t *buf);
+int ctdb_key_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_key_data **out);
+
+size_t ctdb_db_statistics_len(struct ctdb_db_statistics *dbstats);
+void ctdb_db_statistics_push(struct ctdb_db_statistics *dbstats, void *buf);
+int ctdb_db_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_db_statistics **out);
+
+size_t ctdb_election_message_len(struct ctdb_election_message *election);
+void ctdb_election_message_push(struct ctdb_election_message *election,
+ uint8_t *buf);
+int ctdb_election_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_election_message **out);
+
+size_t ctdb_srvid_message_len(struct ctdb_srvid_message *msg);
+void ctdb_srvid_message_push(struct ctdb_srvid_message *msg, uint8_t *buf);
+int ctdb_srvid_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_srvid_message **out);
+
+size_t ctdb_disable_message_len(struct ctdb_disable_message *disable);
+void ctdb_disable_message_push(struct ctdb_disable_message *disable,
+ uint8_t *buf);
+int ctdb_disable_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_disable_message **out);
+
+#endif /* __PROTOCOL_PRIVATE_H__ */
diff --git a/ctdb/protocol/protocol_types.c b/ctdb/protocol/protocol_types.c
new file mode 100644
index 00000000000..f868d767d07
--- /dev/null
+++ b/ctdb/protocol/protocol_types.c
@@ -0,0 +1,2519 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_private.h"
+#include "protocol_api.h"
+
+size_t ctdb_uint32_len(uint32_t val)
+{
+ return sizeof(uint32_t);
+}
+
+void ctdb_uint32_push(uint32_t val, uint8_t *buf)
+{
+ memcpy(buf, &val, sizeof(uint32_t));
+}
+
+int ctdb_uint32_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ uint32_t *out)
+{
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+
+ *out = *(uint32_t *)buf;
+ return 0;
+}
+
+size_t ctdb_uint64_len(uint64_t val)
+{
+ return sizeof(uint64_t);
+}
+
+void ctdb_uint64_push(uint64_t val, uint8_t *buf)
+{
+ memcpy(buf, &val, sizeof(uint64_t));
+}
+
+int ctdb_uint64_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ uint64_t *out)
+{
+ if (buflen < sizeof(uint64_t)) {
+ return EMSGSIZE;
+ }
+
+ *out = *(uint64_t *)buf;
+ return 0;
+}
+
+size_t ctdb_double_len(double val)
+{
+ return sizeof(double);
+}
+
+void ctdb_double_push(double val, uint8_t *buf)
+{
+ memcpy(buf, &val, sizeof(double));
+}
+
+int ctdb_double_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ double *out)
+{
+ if (buflen < sizeof(double)) {
+ return EMSGSIZE;
+ }
+
+ *out = *(double *)buf;
+ return 0;
+}
+
+size_t ctdb_uint8_array_len(struct ctdb_uint8_array *array)
+{
+ return array->num * sizeof(uint8_t);
+}
+
+void ctdb_uint8_array_push(struct ctdb_uint8_array *array, uint8_t *buf)
+{
+ memcpy(buf, array->val, array->num * sizeof(uint8_t));
+}
+
+int ctdb_uint8_array_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_uint8_array **out)
+{
+ struct ctdb_uint8_array *array;
+
+ array = talloc(mem_ctx, struct ctdb_uint8_array);
+ if (array == NULL) {
+ return ENOMEM;
+ }
+
+ array->num = buflen / sizeof(uint8_t);
+
+ array->val = talloc_array(array, uint8_t, array->num);
+ if (array->val == NULL) {
+ talloc_free(array);
+ return ENOMEM;
+ }
+ memcpy(array->val, buf, buflen);
+
+ *out = array;
+ return 0;
+}
+
+size_t ctdb_uint64_array_len(struct ctdb_uint64_array *array)
+{
+ return array->num * sizeof(uint64_t);
+}
+
+void ctdb_uint64_array_push(struct ctdb_uint64_array *array, uint8_t *buf)
+{
+ memcpy(buf, array->val, array->num * sizeof(uint64_t));
+}
+
+int ctdb_uint64_array_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_uint64_array **out)
+{
+ struct ctdb_uint64_array *array;
+
+ array = talloc(mem_ctx, struct ctdb_uint64_array);
+ if (array == NULL) {
+ return ENOMEM;
+ }
+
+ array->num = buflen / sizeof(uint64_t);
+
+ array->val = talloc_array(array, uint64_t, array->num);
+ if (array->val == NULL) {
+ talloc_free(array);
+ return ENOMEM;
+ }
+ memcpy(array->val, buf, buflen);
+
+ *out = array;
+ return 0;
+}
+
+size_t ctdb_pid_len(pid_t pid)
+{
+ return sizeof(pid_t);
+}
+
+void ctdb_pid_push(pid_t pid, uint8_t *buf)
+{
+ memcpy(buf, &pid, sizeof(pid_t));
+}
+
+int ctdb_pid_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ pid_t *out)
+{
+ if (buflen < sizeof(pid_t)) {
+ return EMSGSIZE;
+ }
+
+ *out = *(pid_t *)buf;
+ return 0;
+}
+
+size_t ctdb_string_len(const char *str)
+{
+ if (str == NULL) {
+ return 0;
+ }
+ return strlen(str) + 1;
+}
+
+void ctdb_string_push(const char *str, uint8_t *buf)
+{
+ if (str == NULL) {
+ return;
+ }
+ memcpy(buf, str, strlen(str)+1);
+}
+
+int ctdb_string_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ const char **out)
+{
+ char *str;
+
+ if (buflen == 0) {
+ return 0;
+ }
+
+ str = talloc_strndup(mem_ctx, (char *)buf, buflen);
+ if (str == NULL) {
+ return ENOMEM;
+ }
+
+ *out = str;
+ return 0;
+}
+
+struct stringn_wire {
+ uint32_t length;
+ uint8_t str[1];
+};
+
+size_t ctdb_stringn_len(const char *str)
+{
+ return sizeof(uint32_t) + strlen(str) + 1;
+}
+
+void ctdb_stringn_push(const char *str, uint8_t *buf)
+{
+ struct stringn_wire *wire = (struct stringn_wire *)buf;
+
+ if (str == NULL) {
+ wire->length = 0;
+ } else {
+ wire->length = strlen(str) + 1;
+ memcpy(wire->str, str, wire->length);
+ }
+}
+
+int ctdb_stringn_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ const char **out)
+{
+ char *str;
+ struct stringn_wire *wire = (struct stringn_wire *)buf;
+
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+
+ if (buflen < sizeof(uint32_t) + wire->length) {
+ return EMSGSIZE;
+ }
+
+ str = talloc_strndup(mem_ctx, (char *)wire->str, wire->length);
+ if (str == NULL) {
+ return ENOMEM;
+ }
+
+ *out = str;
+ return 0;
+}
+
+size_t ctdb_statistics_len(struct ctdb_statistics *stats)
+{
+ return sizeof(struct ctdb_statistics);
+}
+
+void ctdb_statistics_push(struct ctdb_statistics *stats, uint8_t *buf)
+{
+ memcpy(buf, stats, sizeof(struct ctdb_statistics));
+}
+
+int ctdb_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics **out)
+{
+ struct ctdb_statistics *stats;
+ struct ctdb_statistics *wire = (struct ctdb_statistics *)buf;
+
+ if (buflen < sizeof(struct ctdb_statistics)) {
+ return EMSGSIZE;
+ }
+
+ stats = talloc(mem_ctx, struct ctdb_statistics);
+ if (stats == NULL) {
+ return ENOMEM;
+ }
+ memcpy(stats, wire, sizeof(struct ctdb_statistics));
+
+ *out = stats;
+ return 0;
+}
+
+struct ctdb_statistics_list_wire {
+ uint32_t num;
+ struct ctdb_statistics stats[1];
+};
+
+size_t ctdb_statistics_list_len(struct ctdb_statistics_list *stats_list)
+{
+ return offsetof(struct ctdb_statistics_list_wire, stats) +
+ stats_list->num * sizeof(struct ctdb_statistics);
+}
+
+void ctdb_statistics_list_push(struct ctdb_statistics_list *stats_list,
+ uint8_t *buf)
+{
+ struct ctdb_statistics_list_wire *wire =
+ (struct ctdb_statistics_list_wire *)buf;
+
+ wire->num = stats_list->num;
+ memcpy(wire->stats, stats_list->stats,
+ stats_list->num * sizeof(struct ctdb_statistics));
+}
+
+int ctdb_statistics_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_statistics_list **out)
+{
+ struct ctdb_statistics_list *stats_list;
+ struct ctdb_statistics_list_wire *wire =
+ (struct ctdb_statistics_list_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_statistics_list_wire, stats)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_statistics_list_wire, stats) +
+ wire->num * sizeof(struct ctdb_statistics)) {
+ return EMSGSIZE;
+ }
+
+ stats_list = talloc(mem_ctx, struct ctdb_statistics_list);
+ if (stats_list == NULL) {
+ return ENOMEM;
+ }
+
+ stats_list->num = wire->num;
+
+ stats_list->stats = talloc_array(stats_list, struct ctdb_statistics,
+ wire->num);
+ if (stats_list->stats == NULL) {
+ talloc_free(stats_list);
+ return ENOMEM;
+ }
+
+ memcpy(stats_list->stats, wire->stats,
+ wire->num * sizeof(struct ctdb_statistics));
+
+ *out = stats_list;
+ return 0;
+}
+
+struct ctdb_vnn_map_wire {
+ uint32_t generation;
+ uint32_t size;
+ uint32_t map[1];
+};
+
+size_t ctdb_vnn_map_len(struct ctdb_vnn_map *vnnmap)
+{
+ return offsetof(struct ctdb_vnn_map, map) +
+ vnnmap->size * sizeof(uint32_t);
+}
+
+void ctdb_vnn_map_push(struct ctdb_vnn_map *vnnmap, uint8_t *buf)
+{
+ struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
+
+ memcpy(wire, vnnmap, offsetof(struct ctdb_vnn_map, map));
+ memcpy(wire->map, vnnmap->map, vnnmap->size * sizeof(uint32_t));
+}
+
+int ctdb_vnn_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_vnn_map **out)
+{
+ struct ctdb_vnn_map *vnnmap;
+ struct ctdb_vnn_map_wire *wire = (struct ctdb_vnn_map_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_vnn_map_wire, map)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_vnn_map_wire, map) +
+ wire->size * sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+
+ vnnmap = talloc(mem_ctx, struct ctdb_vnn_map);
+ if (vnnmap == NULL) {
+ return ENOMEM;
+ }
+
+ memcpy(vnnmap, wire, offsetof(struct ctdb_vnn_map, map));
+
+ vnnmap->map = talloc_memdup(vnnmap, wire->map,
+ wire->size * sizeof(uint32_t));
+ if (vnnmap->map == NULL) {
+ talloc_free(vnnmap);
+ return ENOMEM;
+ }
+
+ *out = vnnmap;
+ return 0;
+}
+
+struct ctdb_dbid_map_wire {
+ uint32_t num;
+ struct ctdb_dbid dbs[1];
+};
+
+size_t ctdb_dbid_map_len(struct ctdb_dbid_map *dbmap)
+{
+ return sizeof(uint32_t) + dbmap->num * sizeof(struct ctdb_dbid);
+}
+
+void ctdb_dbid_map_push(struct ctdb_dbid_map *dbmap, uint8_t *buf)
+{
+ struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
+
+ wire->num = dbmap->num;
+ memcpy(wire->dbs, dbmap->dbs, dbmap->num * sizeof(struct ctdb_dbid));
+}
+
+int ctdb_dbid_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_dbid_map **out)
+{
+ struct ctdb_dbid_map *dbmap;
+ struct ctdb_dbid_map_wire *wire = (struct ctdb_dbid_map_wire *)buf;
+
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+ if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_dbid)) {
+ return EMSGSIZE;
+ }
+
+ dbmap = talloc(mem_ctx, struct ctdb_dbid_map);
+ if (dbmap == NULL) {
+ return ENOMEM;
+ }
+
+ dbmap->num = wire->num;
+
+ dbmap->dbs = talloc_memdup(dbmap, wire->dbs,
+ wire->num * sizeof(struct ctdb_dbid));
+ if (dbmap->dbs == NULL) {
+ talloc_free(dbmap);
+ return ENOMEM;
+ }
+
+ *out = dbmap;
+ return 0;
+}
+
+size_t ctdb_pulldb_len(struct ctdb_pulldb *pulldb)
+{
+ return sizeof(struct ctdb_pulldb);
+}
+
+void ctdb_pulldb_push(struct ctdb_pulldb *pulldb, uint8_t *buf)
+{
+ memcpy(buf, pulldb, sizeof(struct ctdb_pulldb));
+}
+
+int ctdb_pulldb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_pulldb **out)
+{
+ struct ctdb_pulldb *pulldb;
+
+ if (buflen < sizeof(struct ctdb_pulldb)) {
+ return EMSGSIZE;
+ }
+
+ pulldb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb));
+ if (pulldb == NULL) {
+ return ENOMEM;
+ }
+
+ *out = pulldb;
+ return 0;
+}
+
+size_t ctdb_ltdb_header_len(struct ctdb_ltdb_header *header)
+{
+ return sizeof(struct ctdb_ltdb_header);
+}
+
+void ctdb_ltdb_header_push(struct ctdb_ltdb_header *header, uint8_t *buf)
+{
+ memcpy(buf, header, sizeof(struct ctdb_ltdb_header));
+}
+
+int ctdb_ltdb_header_pull(uint8_t *buf, size_t buflen,
+ struct ctdb_ltdb_header *header)
+{
+ if (buflen < sizeof(struct ctdb_ltdb_header)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(header, buf, sizeof(struct ctdb_ltdb_header));
+ return 0;
+}
+
+struct ctdb_rec_data_wire {
+ uint32_t length;
+ uint32_t reqid;
+ uint32_t keylen;
+ uint32_t datalen;
+ uint8_t data[1];
+};
+
+size_t ctdb_rec_data_len(struct ctdb_rec_data *rec)
+{
+ return offsetof(struct ctdb_rec_data_wire, data) +
+ rec->key.dsize + rec->data.dsize +
+ (rec->header == NULL ? 0 : sizeof(struct ctdb_ltdb_header));
+}
+
+void ctdb_rec_data_push(struct ctdb_rec_data *rec, uint8_t *buf)
+{
+ struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
+ size_t offset;
+
+ wire->length = ctdb_rec_data_len(rec);
+ wire->reqid = rec->reqid;
+ wire->keylen = rec->key.dsize;
+ wire->datalen = rec->data.dsize;
+
+ memcpy(wire->data, rec->key.dptr, rec->key.dsize);
+ offset = rec->key.dsize;
+ if (rec->header != NULL) {
+ memcpy(&wire->data[offset], rec->header,
+ sizeof(struct ctdb_ltdb_header));
+ offset += sizeof(struct ctdb_ltdb_header);
+ }
+ if (rec->data.dsize > 0) {
+ memcpy(&wire->data[offset], rec->data.dptr, rec->data.dsize);
+ }
+}
+
+static int ctdb_rec_data_pull_data(uint8_t *buf, size_t buflen,
+ uint32_t *reqid,
+ struct ctdb_ltdb_header **header,
+ TDB_DATA *key, TDB_DATA *data,
+ size_t *reclen)
+{
+ struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
+ size_t offset, n;
+
+ if (buflen < offsetof(struct ctdb_rec_data_wire, data)) {
+ return EMSGSIZE;
+ }
+ n = offsetof(struct ctdb_rec_data_wire, data) +
+ wire->keylen + wire->datalen;
+ if (buflen < n) {
+ return EMSGSIZE;
+ }
+
+ *reqid = wire->reqid;
+
+ key->dsize = wire->keylen;
+ key->dptr = wire->data;
+ offset = wire->keylen;
+
+ if (wire->length - n == sizeof(struct ctdb_ltdb_header)) {
+ *header = (struct ctdb_ltdb_header *)&wire->data[offset];
+ offset += sizeof(struct ctdb_ltdb_header);
+ } else {
+ *header = NULL;
+ }
+
+ data->dsize = wire->datalen;
+ data->dptr = &wire->data[offset];
+
+ *reclen = n;
+
+ return 0;
+}
+
+static int ctdb_rec_data_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_data *out)
+{
+ uint32_t reqid;
+ struct ctdb_ltdb_header *header;
+ TDB_DATA key, data;
+ size_t reclen;
+ int ret;
+
+ ret = ctdb_rec_data_pull_data(buf, buflen, &reqid, &header,
+ &key, &data, &reclen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ out->reqid = reqid;
+
+ if (header != NULL) {
+ out->header = talloc_memdup(mem_ctx, header,
+ sizeof(struct ctdb_ltdb_header));
+ if (out->header == NULL) {
+ return ENOMEM;
+ }
+ } else {
+ out->header = NULL;
+ }
+
+ out->key.dsize = key.dsize;
+ if (key.dsize > 0) {
+ out->key.dptr = talloc_memdup(mem_ctx, key.dptr, key.dsize);
+ if (out->key.dptr == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ out->data.dsize = data.dsize;
+ if (data.dsize > 0) {
+ out->data.dptr = talloc_memdup(mem_ctx, data.dptr, data.dsize);
+ if (out->data.dptr == NULL) {
+ return ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
+int ctdb_rec_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_data **out)
+{
+ struct ctdb_rec_data *rec;
+ int ret;
+
+ rec = talloc(mem_ctx, struct ctdb_rec_data);
+ if (rec == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_rec_data_pull_elems(buf, buflen, rec, rec);
+ if (ret != 0) {
+ TALLOC_FREE(rec);
+ }
+
+ *out = rec;
+ return ret;
+}
+
+struct ctdb_rec_buffer_wire {
+ uint32_t db_id;
+ uint32_t count;
+ uint8_t data[1];
+};
+
+size_t ctdb_rec_buffer_len(struct ctdb_rec_buffer *recbuf)
+{
+ return offsetof(struct ctdb_rec_buffer_wire, data) + recbuf->buflen;
+}
+
+void ctdb_rec_buffer_push(struct ctdb_rec_buffer *recbuf, uint8_t *buf)
+{
+ struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
+
+ wire->db_id = recbuf->db_id;
+ wire->count = recbuf->count;
+ if (recbuf->buflen > 0) {
+ memcpy(wire->data, recbuf->buf, recbuf->buflen);
+ }
+}
+
+int ctdb_rec_buffer_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_rec_buffer **out)
+{
+ struct ctdb_rec_buffer *recbuf;
+ struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
+ size_t offset;
+
+ if (buflen < offsetof(struct ctdb_rec_buffer_wire, data)) {
+ return EMSGSIZE;
+ }
+
+ recbuf = talloc(mem_ctx, struct ctdb_rec_buffer);
+ if (recbuf == NULL) {
+ return ENOMEM;
+ }
+
+ recbuf->db_id = wire->db_id;
+ recbuf->count = wire->count;
+
+ offset = offsetof(struct ctdb_rec_buffer_wire, data);
+ recbuf->buflen = buflen - offset;
+ recbuf->buf = talloc_memdup(recbuf, wire->data, recbuf->buflen);
+ if (recbuf->buf == NULL) {
+ talloc_free(recbuf);
+ return ENOMEM;
+ }
+
+ *out = recbuf;
+ return 0;
+}
+
+struct ctdb_rec_buffer *ctdb_rec_buffer_init(TALLOC_CTX *mem_ctx,
+ uint32_t db_id)
+{
+ struct ctdb_rec_buffer *recbuf;
+
+ recbuf = talloc_zero(mem_ctx, struct ctdb_rec_buffer);
+ if (recbuf == NULL) {
+ return recbuf;
+ }
+
+ recbuf->db_id = db_id;
+
+ return recbuf;
+}
+
+int ctdb_rec_buffer_add(TALLOC_CTX *mem_ctx, struct ctdb_rec_buffer *recbuf,
+ uint32_t reqid, struct ctdb_ltdb_header *header,
+ TDB_DATA key, TDB_DATA data)
+{
+ struct ctdb_rec_data recdata;
+ size_t len;
+ uint8_t *ptr;
+
+ recdata.reqid = reqid;
+ recdata.header = header;
+ recdata.key = key;
+ recdata.data = data;
+
+ len = ctdb_rec_data_len(&recdata);
+
+ ptr = talloc_realloc(mem_ctx, recbuf->buf, uint8_t,
+ recbuf->buflen + len);
+ if (ptr == NULL) {
+ return ENOMEM;
+ }
+
+ ctdb_rec_data_push(&recdata, &ptr[recbuf->buflen]);
+
+ recbuf->count++;
+ recbuf->buf = ptr;
+ recbuf->buflen += len;
+ return 0;
+}
+
+int ctdb_rec_buffer_traverse(struct ctdb_rec_buffer *recbuf,
+ ctdb_rec_parser_func_t func,
+ void *private_data)
+{
+ struct ctdb_ltdb_header *header;
+ TDB_DATA key, data;
+ uint32_t reqid;
+ size_t offset, reclen;
+ int ret = 0, i;
+
+ offset = 0;
+ for (i=0; i<recbuf->count; i++) {
+ ret = ctdb_rec_data_pull_data(&recbuf->buf[offset],
+ recbuf->buflen - offset,
+ &reqid, &header,
+ &key, &data, &reclen);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = func(reqid, header, key, data, private_data);
+ if (ret != 0) {
+ break;
+ }
+
+ offset += reclen;
+ }
+
+ return ret;
+}
+
+size_t ctdb_traverse_start_len(struct ctdb_traverse_start *traverse)
+{
+ return sizeof(struct ctdb_traverse_start);
+}
+
+void ctdb_traverse_start_push(struct ctdb_traverse_start *traverse,
+ uint8_t *buf)
+{
+ memcpy(buf, traverse, sizeof(struct ctdb_traverse_start));
+}
+
+int ctdb_traverse_start_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_start **out)
+{
+ struct ctdb_traverse_start *traverse;
+
+ if (buflen < sizeof(struct ctdb_traverse_start)) {
+ return EMSGSIZE;
+ }
+
+ traverse = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_traverse_start));
+ if (traverse == NULL) {
+ return ENOMEM;
+ }
+
+ *out = traverse;
+ return 0;
+}
+
+size_t ctdb_traverse_all_len(struct ctdb_traverse_all *traverse)
+{
+ return sizeof(struct ctdb_traverse_all);
+}
+
+void ctdb_traverse_all_push(struct ctdb_traverse_all *traverse, uint8_t *buf)
+{
+ memcpy(buf, traverse, sizeof(struct ctdb_traverse_all));
+}
+
+int ctdb_traverse_all_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_all **out)
+{
+ struct ctdb_traverse_all *traverse;
+
+ if (buflen < sizeof(struct ctdb_traverse_all)) {
+ return EMSGSIZE;
+ }
+
+ traverse = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_traverse_all));
+ if (traverse == NULL) {
+ return ENOMEM;
+ }
+
+ *out = traverse;
+ return 0;
+}
+
+size_t ctdb_traverse_start_ext_len(struct ctdb_traverse_start_ext *traverse)
+{
+ return sizeof(struct ctdb_traverse_start_ext);
+}
+
+void ctdb_traverse_start_ext_push(struct ctdb_traverse_start_ext *traverse,
+ uint8_t *buf)
+{
+ memcpy(buf, traverse, sizeof(struct ctdb_traverse_start_ext));
+}
+
+int ctdb_traverse_start_ext_pull(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_start_ext **out)
+{
+ struct ctdb_traverse_start_ext *traverse;
+
+ if (buflen < sizeof(struct ctdb_traverse_start_ext)) {
+ return EMSGSIZE;
+ }
+
+ traverse = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_traverse_start_ext));
+ if (traverse == NULL) {
+ return ENOMEM;
+ }
+
+ *out = traverse;
+ return 0;
+}
+
+size_t ctdb_traverse_all_ext_len(struct ctdb_traverse_all_ext *traverse)
+{
+ return sizeof(struct ctdb_traverse_all_ext);
+}
+
+void ctdb_traverse_all_ext_push(struct ctdb_traverse_all_ext *traverse,
+ uint8_t *buf)
+{
+ memcpy(buf, traverse, sizeof(struct ctdb_traverse_all_ext));
+}
+
+int ctdb_traverse_all_ext_pull(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_traverse_all_ext **out)
+{
+ struct ctdb_traverse_all_ext *traverse;
+
+ if (buflen < sizeof(struct ctdb_traverse_all_ext)) {
+ return EMSGSIZE;
+ }
+
+ traverse = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_traverse_all_ext));
+ if (traverse == NULL) {
+ return ENOMEM;
+ }
+
+ *out = traverse;
+ return 0;
+}
+
+size_t ctdb_sock_addr_len(ctdb_sock_addr *addr)
+{
+ return sizeof(ctdb_sock_addr);
+}
+
+void ctdb_sock_addr_push(ctdb_sock_addr *addr, uint8_t *buf)
+{
+ memcpy(buf, addr, sizeof(ctdb_sock_addr));
+}
+
+static int ctdb_sock_addr_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx, ctdb_sock_addr *out)
+{
+ if (buflen < sizeof(ctdb_sock_addr)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(ctdb_sock_addr));
+
+ return 0;
+}
+
+int ctdb_sock_addr_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ ctdb_sock_addr **out)
+{
+ ctdb_sock_addr *addr;
+ int ret;
+
+ addr = talloc(mem_ctx, ctdb_sock_addr);
+ if (addr == NULL) {
+ return false;
+ }
+
+ ret = ctdb_sock_addr_pull_elems(buf, buflen, addr, addr);
+ if (ret != 0) {
+ TALLOC_FREE(addr);
+ }
+
+ *out = addr;
+ return ret;
+}
+
+size_t ctdb_connection_len(struct ctdb_connection *conn)
+{
+ return sizeof(struct ctdb_connection);
+}
+
+void ctdb_connection_push(struct ctdb_connection *conn, uint8_t *buf)
+{
+ memcpy(buf, conn, sizeof(struct ctdb_connection));
+}
+
+static int ctdb_connection_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_connection *out)
+{
+ if (buflen < sizeof(struct ctdb_connection)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(struct ctdb_connection));
+
+ return 0;
+}
+
+int ctdb_connection_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_connection **out)
+{
+ struct ctdb_connection *conn;
+ int ret;
+
+ conn = talloc(mem_ctx, struct ctdb_connection);
+ if (conn == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_connection_pull_elems(buf, buflen, conn, conn);
+ if (ret != 0) {
+ TALLOC_FREE(conn);
+ }
+
+ *out = conn;
+ return ret;
+}
+
+struct ctdb_tunable_wire {
+ uint32_t value;
+ uint32_t length;
+ uint8_t name[1];
+};
+
+size_t ctdb_tunable_len(struct ctdb_tunable *tunable)
+{
+ return offsetof(struct ctdb_tunable_wire, name) +
+ strlen(tunable->name) + 1;
+}
+
+void ctdb_tunable_push(struct ctdb_tunable *tunable, uint8_t *buf)
+{
+ struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
+
+ wire->value = tunable->value;
+ wire->length = strlen(tunable->name) + 1;
+ memcpy(wire->name, tunable->name, wire->length);
+}
+
+int ctdb_tunable_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_tunable **out)
+{
+ struct ctdb_tunable *tunable;
+ struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_tunable_wire, name)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_tunable_wire, name) + wire->length) {
+ return EMSGSIZE;
+ }
+
+ tunable = talloc(mem_ctx, struct ctdb_tunable);
+ if (tunable == NULL) {
+ return ENOMEM;
+ }
+
+ tunable->value = wire->value;
+ tunable->name = talloc_memdup(tunable, wire->name, wire->length);
+ if (tunable->name == NULL) {
+ talloc_free(tunable);
+ return ENOMEM;
+ }
+
+ *out = tunable;
+ return 0;
+}
+
+size_t ctdb_node_flag_change_len(struct ctdb_node_flag_change *flag_change)
+{
+ return sizeof(struct ctdb_node_flag_change);
+}
+
+void ctdb_node_flag_change_push(struct ctdb_node_flag_change *flag_change,
+ uint8_t *buf)
+{
+ memcpy(buf, flag_change, sizeof(struct ctdb_node_flag_change));
+}
+
+int ctdb_node_flag_change_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_node_flag_change **out)
+{
+ struct ctdb_node_flag_change *flag_change;
+
+ if (buflen < sizeof(struct ctdb_node_flag_change)) {
+ return EMSGSIZE;
+ }
+
+ flag_change = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_node_flag_change));
+ if (flag_change == NULL) {
+ return ENOMEM;
+ }
+
+ *out = flag_change;
+ return 0;
+}
+
+struct ctdb_var_list_wire {
+ uint32_t length;
+ char list_str[1];
+};
+
+size_t ctdb_var_list_len(struct ctdb_var_list *var_list)
+{
+ int i;
+ size_t len = sizeof(uint32_t);
+
+ for (i=0; i<var_list->count; i++) {
+ len += strlen(var_list->var[i]) + 1;
+ }
+ return len;
+}
+
+void ctdb_var_list_push(struct ctdb_var_list *var_list, uint8_t *buf)
+{
+ struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
+ int i, n;
+ size_t offset = 0;
+
+ if (var_list->count > 0) {
+ n = sprintf(wire->list_str, "%s", var_list->var[0]);
+ offset += n;
+ }
+ for (i=1; i<var_list->count; i++) {
+ n = sprintf(&wire->list_str[offset], ":%s", var_list->var[i]);
+ offset += n;
+ }
+ wire->length = offset + 1;
+}
+
+int ctdb_var_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_var_list **out)
+{
+ struct ctdb_var_list *var_list = NULL;
+ struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
+ char *str, *s, *tok, *ptr;
+ const char **list;
+
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+ if (buflen < sizeof(uint32_t) + wire->length) {
+ return EMSGSIZE;
+ }
+
+ str = talloc_strndup(mem_ctx, (char *)wire->list_str, wire->length);
+ if (str == NULL) {
+ return ENOMEM;
+ }
+
+ var_list = talloc_zero(mem_ctx, struct ctdb_var_list);
+ if (var_list == NULL) {
+ goto fail;
+ }
+
+ s = str;
+ while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
+ s = NULL;
+ list = talloc_realloc(var_list, var_list->var, const char *,
+ var_list->count+1);
+ if (list == NULL) {
+ goto fail;
+ }
+
+ var_list->var = list;
+ var_list->var[var_list->count] = talloc_strdup(var_list, tok);
+ if (var_list->var[var_list->count] == NULL) {
+ goto fail;
+ }
+ var_list->count++;
+ }
+
+ talloc_free(str);
+ *out = var_list;
+ return 0;
+
+fail:
+ talloc_free(str);
+ talloc_free(var_list);
+ return ENOMEM;
+}
+
+size_t ctdb_tunable_list_len(struct ctdb_tunable_list *tun_list)
+{
+ return sizeof(struct ctdb_tunable_list);
+}
+
+void ctdb_tunable_list_push(struct ctdb_tunable_list *tun_list, uint8_t *buf)
+{
+ memcpy(buf, tun_list, sizeof(struct ctdb_tunable_list));
+}
+
+int ctdb_tunable_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_tunable_list **out)
+{
+ struct ctdb_tunable_list *tun_list;
+
+ if (buflen < sizeof(struct ctdb_tunable_list)) {
+ return EMSGSIZE;
+ }
+
+ tun_list = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_tunable_list));
+ if (tun_list == NULL) {
+ return ENOMEM;
+ }
+
+ *out = tun_list;
+ return 0;
+}
+
+struct ctdb_tickle_list_wire {
+ ctdb_sock_addr addr;
+ uint32_t num;
+ struct ctdb_connection conn[1];
+};
+
+size_t ctdb_tickle_list_len(struct ctdb_tickle_list *tickles)
+{
+ return offsetof(struct ctdb_tickle_list, conn) +
+ tickles->num * sizeof(struct ctdb_connection);
+}
+
+void ctdb_tickle_list_push(struct ctdb_tickle_list *tickles, uint8_t *buf)
+{
+ struct ctdb_tickle_list_wire *wire =
+ (struct ctdb_tickle_list_wire *)buf;
+ size_t offset;
+ int i;
+
+ memcpy(&wire->addr, &tickles->addr, sizeof(ctdb_sock_addr));
+ wire->num = tickles->num;
+
+ offset = offsetof(struct ctdb_tickle_list_wire, conn);
+ for (i=0; i<tickles->num; i++) {
+ ctdb_connection_push(&tickles->conn[i], &buf[offset]);
+ offset += ctdb_connection_len(&tickles->conn[i]);
+ }
+}
+
+int ctdb_tickle_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_tickle_list **out)
+{
+ struct ctdb_tickle_list *tickles;
+ struct ctdb_tickle_list_wire *wire =
+ (struct ctdb_tickle_list_wire *)buf;
+ size_t offset;
+ int i, ret;
+
+ if (buflen < offsetof(struct ctdb_tickle_list_wire, conn)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_tickle_list_wire, conn) +
+ wire->num * sizeof(struct ctdb_connection)) {
+ return EMSGSIZE;
+ }
+
+ tickles = talloc(mem_ctx, struct ctdb_tickle_list);
+ if (tickles == NULL) {
+ return ENOMEM;
+ }
+
+ offset = offsetof(struct ctdb_tickle_list, conn);
+ memcpy(tickles, wire, offset);
+
+ tickles->conn = talloc_array(tickles, struct ctdb_connection,
+ wire->num);
+ if (tickles->conn == NULL) {
+ talloc_free(tickles);
+ return ENOMEM;
+ }
+
+ for (i=0; i<wire->num; i++) {
+ ret = ctdb_connection_pull_elems(&buf[offset], buflen-offset,
+ tickles->conn,
+ &tickles->conn[i]);
+ if (ret != 0) {
+ talloc_free(tickles);
+ return ret;
+ }
+ offset += ctdb_connection_len(&tickles->conn[i]);
+ }
+
+ *out = tickles;
+ return 0;
+}
+
+size_t ctdb_client_id_len(struct ctdb_client_id *cid)
+{
+ return sizeof(struct ctdb_client_id);
+}
+
+void ctdb_client_id_push(struct ctdb_client_id *cid, uint8_t *buf)
+{
+ memcpy(buf, cid, sizeof(struct ctdb_client_id));
+}
+
+static int ctdb_client_id_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id *out)
+{
+ if (buflen < sizeof(struct ctdb_client_id)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(struct ctdb_client_id));
+
+ return 0;
+}
+
+int ctdb_client_id_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id **out)
+{
+ struct ctdb_client_id *cid;
+ int ret;
+
+ cid = talloc(mem_ctx, struct ctdb_client_id);
+ if (cid == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_client_id_pull_elems(buf, buflen, cid, cid);
+ if (ret != 0) {
+ TALLOC_FREE(cid);
+ }
+
+ *out = cid;
+ return ret;
+}
+
+struct ctdb_client_id_list_wire {
+ uint32_t num;
+ struct ctdb_client_id cid[1];
+};
+
+size_t ctdb_client_id_list_len(struct ctdb_client_id_list *cid_list)
+{
+ return sizeof(uint32_t) +
+ cid_list->num * sizeof(struct ctdb_client_id);
+}
+
+void ctdb_client_id_list_push(struct ctdb_client_id_list *cid_list,
+ uint8_t *buf)
+{
+ struct ctdb_client_id_list_wire *wire =
+ (struct ctdb_client_id_list_wire *)buf;
+ size_t offset;
+ int i;
+
+ wire->num = cid_list->num;
+
+ offset = offsetof(struct ctdb_client_id_list_wire, cid);
+ for (i=0; i<cid_list->num; i++) {
+ ctdb_client_id_push(&cid_list->cid[i], &buf[offset]);
+ offset += ctdb_client_id_len(&cid_list->cid[i]);
+ }
+}
+
+static int ctdb_client_id_list_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_list *out)
+{
+ struct ctdb_client_id_list_wire *wire =
+ (struct ctdb_client_id_list_wire *)buf;
+ size_t offset;
+ int i;
+
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+ if (buflen < sizeof(uint32_t) +
+ wire->num * sizeof(struct ctdb_client_id)) {
+ return EMSGSIZE;
+ }
+
+ out->num = wire->num;
+ out->cid = talloc_array(mem_ctx, struct ctdb_client_id,
+ wire->num);
+ if (out->cid == NULL) {
+ return ENOMEM;
+ }
+
+ offset = offsetof(struct ctdb_client_id_list_wire, cid);
+ for (i=0; i<wire->num; i++) {
+ bool ret;
+ ret = ctdb_client_id_pull_elems(&buf[offset], buflen-offset,
+ out->cid, &out->cid[i]);
+ if (ret != 0) {
+ return ret;
+ }
+ offset += ctdb_client_id_len(&out->cid[i]);
+ }
+
+ return 0;
+}
+
+int ctdb_client_id_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_list **out)
+{
+ struct ctdb_client_id_list *cid_list;
+ int ret;
+
+ cid_list = talloc(mem_ctx, struct ctdb_client_id_list);
+ if (cid_list == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_client_id_list_pull_elems(buf, buflen, cid_list, cid_list);
+ if (ret != 0) {
+ TALLOC_FREE(cid_list);
+ }
+
+ *out = cid_list;
+ return ret;
+}
+
+struct ctdb_client_id_map_wire {
+ int count;
+ struct ctdb_client_id_list list[1];
+};
+
+size_t ctdb_client_id_map_len(struct ctdb_client_id_map *cid_map)
+{
+ int i;
+ size_t len;
+
+ len = sizeof(int);
+ for (i=0; i<cid_map->count; i++) {
+ len += ctdb_client_id_list_len(&cid_map->list[i]);
+ }
+ return len;
+}
+
+void ctdb_client_id_map_push(struct ctdb_client_id_map *cid_map, uint8_t *buf)
+{
+ struct ctdb_client_id_map_wire *wire =
+ (struct ctdb_client_id_map_wire *)buf;
+ size_t offset;
+ int i;
+
+ wire->count = cid_map->count;
+
+ offset = sizeof(int);
+ for (i=0; i<cid_map->count; i++) {
+ ctdb_client_id_list_push(&cid_map->list[i], &buf[offset]);
+ offset += ctdb_client_id_list_len(&cid_map->list[i]);
+ }
+}
+
+int ctdb_client_id_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_client_id_map **out)
+{
+ struct ctdb_client_id_map *cid_map;
+ struct ctdb_client_id_map_wire *wire =
+ (struct ctdb_client_id_map_wire *)buf;
+ size_t offset;
+ int i;
+ bool ret;
+
+ if (buflen < sizeof(int)) {
+ return EMSGSIZE;
+ }
+ if (buflen < sizeof(int) +
+ wire->count * sizeof(struct ctdb_client_id_list)) {
+ return EMSGSIZE;
+ }
+
+ cid_map = talloc(mem_ctx, struct ctdb_client_id_map);
+ if (cid_map == NULL) {
+ return ENOMEM;
+ }
+
+ cid_map->count = wire->count;
+ cid_map->list = talloc_array(cid_map, struct ctdb_client_id_list,
+ wire->count);
+ if (cid_map->list == NULL) {
+ return ENOMEM;
+ }
+
+ offset = sizeof(int);
+ for (i=0; i<wire->count; i++) {
+ ret = ctdb_client_id_list_pull_elems(&buf[offset],
+ buflen-offset,
+ cid_map->list,
+ &cid_map->list[i]);
+ if (ret != 0) {
+ talloc_free(cid_map);
+ return ret;
+ }
+ offset += ctdb_client_id_list_len(&cid_map->list[i]);
+ }
+
+ *out = cid_map;
+ return 0;
+}
+
+struct ctdb_addr_info_wire {
+ ctdb_sock_addr addr;
+ uint32_t mask;
+ uint32_t len;
+ char iface[1];
+};
+
+size_t ctdb_addr_info_len(struct ctdb_addr_info *arp)
+{
+ return offsetof(struct ctdb_addr_info_wire, iface) +
+ strlen(arp->iface)+1;
+}
+
+void ctdb_addr_info_push(struct ctdb_addr_info *addr_info, uint8_t *buf)
+{
+ struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
+
+ wire->addr = addr_info->addr;
+ wire->mask = addr_info->mask;
+ wire->len = strlen(addr_info->iface)+1;
+ memcpy(wire->iface, addr_info->iface, wire->len);
+}
+
+int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_addr_info **out)
+{
+ struct ctdb_addr_info *addr_info;
+ struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_addr_info_wire, iface)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_addr_info_wire, iface) + wire->len) {
+ return EMSGSIZE;
+ }
+
+ addr_info = talloc(mem_ctx, struct ctdb_addr_info);
+ if (addr_info == NULL) {
+ return ENOMEM;
+ }
+
+ addr_info->addr = wire->addr;
+ addr_info->mask = wire->mask;
+
+ addr_info->iface = talloc_strndup(addr_info, wire->iface, wire->len);
+ if (addr_info->iface == NULL) {
+ talloc_free(addr_info);
+ return ENOMEM;
+ }
+
+ *out = addr_info;
+ return 0;
+}
+
+size_t ctdb_transdb_len(struct ctdb_transdb *transdb)
+{
+ return sizeof(struct ctdb_transdb);
+}
+
+void ctdb_transdb_push(struct ctdb_transdb *transdb, uint8_t *buf)
+{
+ memcpy(buf, transdb, sizeof(struct ctdb_transdb));
+}
+
+int ctdb_transdb_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_transdb **out)
+{
+ struct ctdb_transdb *transdb;
+
+ if (buflen < sizeof(struct ctdb_transdb)) {
+ return EMSGSIZE;
+ }
+
+ transdb = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_transdb));
+ if (transdb == NULL) {
+ return ENOMEM;
+ }
+
+ *out = transdb;
+ return 0;
+}
+
+size_t ctdb_uptime_len(struct ctdb_uptime *uptime)
+{
+ return sizeof(struct ctdb_uptime);
+}
+
+void ctdb_uptime_push(struct ctdb_uptime *uptime, uint8_t *buf)
+{
+ memcpy(buf, uptime, sizeof(struct ctdb_uptime));
+}
+
+int ctdb_uptime_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_uptime **out)
+{
+ struct ctdb_uptime *uptime;
+
+ if (buflen < sizeof(struct ctdb_uptime)) {
+ return EMSGSIZE;
+ }
+
+ uptime = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_uptime));
+ if (uptime == NULL) {
+ return ENOMEM;
+ }
+
+ *out = uptime;
+ return 0;
+}
+
+size_t ctdb_public_ip_len(struct ctdb_public_ip *pubip)
+{
+ return sizeof(struct ctdb_public_ip);
+}
+
+void ctdb_public_ip_push(struct ctdb_public_ip *pubip, uint8_t *buf)
+{
+ memcpy(buf, pubip, sizeof(struct ctdb_public_ip));
+}
+
+static int ctdb_public_ip_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip *out)
+{
+ if (buflen < sizeof(struct ctdb_public_ip)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(struct ctdb_public_ip));
+
+ return 0;
+}
+
+int ctdb_public_ip_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip **out)
+{
+ struct ctdb_public_ip *pubip;
+ int ret;
+
+ pubip = talloc(mem_ctx, struct ctdb_public_ip);
+ if (pubip == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_public_ip_pull_elems(buf, buflen, pubip, pubip);
+ if (ret != 0) {
+ TALLOC_FREE(pubip);
+ }
+
+ *out = pubip;
+ return ret;
+}
+
+struct ctdb_public_ip_list_wire {
+ uint32_t num;
+ struct ctdb_public_ip ip[1];
+};
+
+size_t ctdb_public_ip_list_len(struct ctdb_public_ip_list *pubip_list)
+{
+ int i;
+ size_t len;
+
+ len = sizeof(uint32_t);
+ for (i=0; i<pubip_list->num; i++) {
+ len += ctdb_public_ip_len(&pubip_list->ip[i]);
+ }
+ return len;
+}
+
+void ctdb_public_ip_list_push(struct ctdb_public_ip_list *pubip_list,
+ uint8_t *buf)
+{
+ struct ctdb_public_ip_list_wire *wire =
+ (struct ctdb_public_ip_list_wire *)buf;
+ size_t offset;
+ int i;
+
+ wire->num = pubip_list->num;
+
+ offset = offsetof(struct ctdb_public_ip_list_wire, ip);
+ for (i=0; i<pubip_list->num; i++) {
+ ctdb_public_ip_push(&pubip_list->ip[i], &buf[offset]);
+ offset += ctdb_public_ip_len(&pubip_list->ip[i]);
+ }
+}
+
+int ctdb_public_ip_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_list **out)
+{
+ struct ctdb_public_ip_list *pubip_list;
+ struct ctdb_public_ip_list_wire *wire =
+ (struct ctdb_public_ip_list_wire *)buf;
+ size_t offset;
+ int i;
+ bool ret;
+
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+ if (buflen < sizeof(uint32_t) +
+ wire->num * sizeof(struct ctdb_public_ip)) {
+ return EMSGSIZE;
+ }
+
+ pubip_list = talloc(mem_ctx, struct ctdb_public_ip_list);
+ if (pubip_list == NULL) {
+ return ENOMEM;
+ }
+
+ pubip_list->num = wire->num;
+ pubip_list->ip = talloc_array(pubip_list, struct ctdb_public_ip,
+ wire->num);
+ if (pubip_list->ip == NULL) {
+ talloc_free(pubip_list);
+ return ENOMEM;
+ }
+
+ offset = offsetof(struct ctdb_public_ip_list_wire, ip);
+ for (i=0; i<wire->num; i++) {
+ ret = ctdb_public_ip_pull_elems(&buf[offset], buflen-offset,
+ pubip_list->ip,
+ &pubip_list->ip[i]);
+ if (ret != 0) {
+ talloc_free(pubip_list);
+ return ret;
+ }
+ offset += ctdb_public_ip_len(&pubip_list->ip[i]);
+ }
+
+ *out = pubip_list;
+ return 0;
+}
+
+size_t ctdb_node_and_flags_len(struct ctdb_node_and_flags *node)
+{
+ return sizeof(struct ctdb_node_and_flags);
+}
+
+void ctdb_node_and_flags_push(struct ctdb_node_and_flags *node, uint8_t *buf)
+{
+ memcpy(buf, node, sizeof(struct ctdb_node_and_flags));
+}
+
+static int ctdb_node_and_flags_pull_elems(TALLOC_CTX *mem_ctx,
+ uint8_t *buf, size_t buflen,
+ struct ctdb_node_and_flags *out)
+{
+ if (buflen < sizeof(struct ctdb_node_and_flags)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(struct ctdb_node_and_flags));
+
+ return 0;
+}
+
+int ctdb_node_and_flags_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_node_and_flags **out)
+{
+ struct ctdb_node_and_flags *node;
+ int ret;
+
+ node = talloc(mem_ctx, struct ctdb_node_and_flags);
+ if (node == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_node_and_flags_pull_elems(node, buf, buflen, node);
+ if (ret != 0) {
+ TALLOC_FREE(node);
+ }
+
+ *out = node;
+ return ret;
+}
+
+struct ctdb_node_map_wire {
+ uint32_t num;
+ struct ctdb_node_and_flags node[1];
+};
+
+size_t ctdb_node_map_len(struct ctdb_node_map *nodemap)
+{
+ return sizeof(uint32_t) +
+ nodemap->num * sizeof(struct ctdb_node_and_flags);
+}
+
+void ctdb_node_map_push(struct ctdb_node_map *nodemap, uint8_t *buf)
+{
+ struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
+ size_t offset;
+ int i;
+
+ wire->num = nodemap->num;
+
+ offset = offsetof(struct ctdb_node_map_wire, node);
+ for (i=0; i<nodemap->num; i++) {
+ ctdb_node_and_flags_push(&nodemap->node[i], &buf[offset]);
+ offset += ctdb_node_and_flags_len(&nodemap->node[i]);
+ }
+}
+
+int ctdb_node_map_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_node_map **out)
+{
+ struct ctdb_node_map *nodemap;
+ struct ctdb_node_map_wire *wire = (struct ctdb_node_map_wire *)buf;
+ size_t offset;
+ int i;
+ bool ret;
+
+ nodemap = talloc(mem_ctx, struct ctdb_node_map);
+ if (nodemap == NULL) {
+ return ENOMEM;
+ }
+
+ nodemap->num = wire->num;
+ nodemap->node = talloc_array(nodemap, struct ctdb_node_and_flags,
+ wire->num);
+ if (nodemap->node == NULL) {
+ talloc_free(nodemap);
+ return ENOMEM;
+ }
+
+ offset = offsetof(struct ctdb_node_map_wire, node);
+ for (i=0; i<wire->num; i++) {
+ ret = ctdb_node_and_flags_pull_elems(nodemap->node,
+ &buf[offset],
+ buflen-offset,
+ &nodemap->node[i]);
+ if (ret != 0) {
+ talloc_free(nodemap);
+ return ret;
+ }
+ offset += ctdb_node_and_flags_len(&nodemap->node[i]);
+ }
+
+ *out = nodemap;
+ return 0;
+}
+
+size_t ctdb_script_len(struct ctdb_script *script)
+{
+ return sizeof(struct ctdb_script);
+}
+
+void ctdb_script_push(struct ctdb_script *script, uint8_t *buf)
+{
+ memcpy(buf, script, sizeof(struct ctdb_script));
+}
+
+static int ctdb_script_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_script *out)
+{
+ if (buflen < sizeof(struct ctdb_script)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(struct ctdb_script));
+
+ return 0;
+}
+
+int ctdb_script_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_script **out)
+{
+ struct ctdb_script *script;
+ int ret;
+
+ script = talloc(mem_ctx, struct ctdb_script);
+ if (script == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_script_pull_elems(buf, buflen, script, script);
+ if (ret != 0) {
+ TALLOC_FREE(script);
+ }
+
+ *out = script;
+ return ret;
+}
+
+struct ctdb_script_list_wire {
+ uint32_t num_scripts;
+ struct ctdb_script script[1];
+};
+
+size_t ctdb_script_list_len(struct ctdb_script_list *script_list)
+{
+ int i;
+ size_t len;
+
+ if (script_list == NULL) {
+ return 0;
+ }
+
+ len = offsetof(struct ctdb_script_list_wire, script);
+ for (i=0; i<script_list->num_scripts; i++) {
+ len += ctdb_script_len(&script_list->script[i]);
+ }
+ return len;
+}
+
+void ctdb_script_list_push(struct ctdb_script_list *script_list, uint8_t *buf)
+{
+ struct ctdb_script_list_wire *wire =
+ (struct ctdb_script_list_wire *)buf;
+ size_t offset;
+ int i;
+
+ if (script_list == NULL) {
+ return;
+ }
+
+ wire->num_scripts = script_list->num_scripts;
+
+ offset = offsetof(struct ctdb_script_list_wire, script);
+ for (i=0; i<script_list->num_scripts; i++) {
+ ctdb_script_push(&script_list->script[i], &buf[offset]);
+ offset += ctdb_script_len(&script_list->script[i]);
+ }
+}
+
+int ctdb_script_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_script_list **out)
+{
+ struct ctdb_script_list *script_list;
+ struct ctdb_script_list_wire *wire =
+ (struct ctdb_script_list_wire *)buf;
+ size_t offset;
+ int i;
+ bool ret;
+
+ /* If event scripts have never been run, the result will be NULL */
+ if (buflen == 0) {
+ *out = NULL;
+ return 0;
+ }
+
+ offset = offsetof(struct ctdb_script_list_wire, script);
+
+ if (buflen < offset) {
+ return EMSGSIZE;
+ }
+ if (buflen < offset + wire->num_scripts * sizeof(struct ctdb_script)) {
+ return EMSGSIZE;
+ }
+
+ script_list = talloc(mem_ctx, struct ctdb_script_list);
+ if (script_list == NULL) {
+ return ENOMEM;
+
+ }
+
+ script_list->num_scripts = wire->num_scripts;
+ script_list->script = talloc_array(script_list, struct ctdb_script,
+ wire->num_scripts);
+ if (script_list->script == NULL) {
+ talloc_free(script_list);
+ return ENOMEM;
+ }
+
+ for (i=0; i<wire->num_scripts; i++) {
+ ret = ctdb_script_pull_elems(&buf[offset], buflen-offset,
+ script_list->script,
+ &script_list->script[i]);
+ if (ret != 0) {
+ talloc_free(script_list);
+ return ret;
+ }
+ offset += ctdb_script_len(&script_list->script[i]);
+ }
+
+ *out = script_list;
+ return 0;
+}
+
+size_t ctdb_ban_state_len(struct ctdb_ban_state *ban_state)
+{
+ return sizeof(struct ctdb_ban_state);
+}
+
+void ctdb_ban_state_push(struct ctdb_ban_state *ban_state, uint8_t *buf)
+{
+ memcpy(buf, ban_state, sizeof(struct ctdb_ban_state));
+}
+
+int ctdb_ban_state_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_ban_state **out)
+{
+ struct ctdb_ban_state *ban_state;
+
+ if (buflen < sizeof(struct ctdb_ban_state)) {
+ return EMSGSIZE;
+ }
+
+ ban_state = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_ban_state));
+ if (ban_state == NULL) {
+ return ENOMEM;
+ }
+
+ *out = ban_state;
+ return 0;
+}
+
+size_t ctdb_db_priority_len(struct ctdb_db_priority *db_prio)
+{
+ return sizeof(struct ctdb_db_priority);
+}
+
+void ctdb_db_priority_push(struct ctdb_db_priority *db_prio, uint8_t *buf)
+{
+ memcpy(buf, db_prio, sizeof(struct ctdb_db_priority));
+}
+
+int ctdb_db_priority_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_db_priority **out)
+{
+ struct ctdb_db_priority *db_prio;
+
+ if (buflen < sizeof(struct ctdb_db_priority)) {
+ return EMSGSIZE;
+ }
+
+ db_prio = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_db_priority));
+ if (db_prio == NULL) {
+ return ENOMEM;
+ }
+
+ *out = db_prio;
+ return 0;
+}
+
+struct ctdb_notify_data_wire {
+ uint64_t srvid;
+ uint32_t len;
+ uint8_t data[1];
+};
+
+size_t ctdb_notify_data_len(struct ctdb_notify_data *notify)
+{
+ return offsetof(struct ctdb_notify_data_wire, data) +
+ notify->data.dsize;
+}
+
+void ctdb_notify_data_push(struct ctdb_notify_data *notify, uint8_t *buf)
+{
+ struct ctdb_notify_data_wire *wire =
+ (struct ctdb_notify_data_wire *)buf;
+
+ wire->srvid = notify->srvid;
+ wire->len = notify->data.dsize;
+ memcpy(wire->data, notify->data.dptr, notify->data.dsize);
+}
+
+int ctdb_notify_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_notify_data **out)
+{
+ struct ctdb_notify_data *notify;
+ struct ctdb_notify_data_wire *wire =
+ (struct ctdb_notify_data_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_notify_data_wire, data)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_notify_data_wire, data) + wire->len) {
+ return EMSGSIZE;
+ }
+
+ notify = talloc(mem_ctx, struct ctdb_notify_data);
+ if (notify == NULL) {
+ return ENOMEM;
+ }
+
+ notify->srvid = wire->srvid;
+ notify->data.dsize = wire->len;
+ notify->data.dptr = talloc_memdup(notify, wire->data, wire->len);
+ if (notify->data.dptr == NULL) {
+ talloc_free(notify);
+ return ENOMEM;
+ }
+
+ *out = notify;
+ return 0;
+}
+
+size_t ctdb_iface_len(struct ctdb_iface *iface)
+{
+ return sizeof(struct ctdb_iface);
+}
+
+void ctdb_iface_push(struct ctdb_iface *iface, uint8_t *buf)
+{
+ memcpy(buf, iface, sizeof(struct ctdb_iface));
+}
+
+static int ctdb_iface_pull_elems(uint8_t *buf, size_t buflen,
+ TALLOC_CTX *mem_ctx,
+ struct ctdb_iface *out)
+{
+ if (buflen < sizeof(struct ctdb_iface)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(out, buf, sizeof(struct ctdb_iface));
+
+ return 0;
+}
+
+int ctdb_iface_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_iface **out)
+{
+ struct ctdb_iface *iface;
+ int ret;
+
+ iface = talloc(mem_ctx, struct ctdb_iface);
+ if (iface == NULL) {
+ return ENOMEM;
+ }
+
+ ret = ctdb_iface_pull_elems(buf, buflen, iface, iface);
+ if (ret != 0) {
+ TALLOC_FREE(iface);
+ }
+
+ *out = iface;
+ return ret;
+}
+
+struct ctdb_iface_list_wire {
+ uint32_t num;
+ struct ctdb_iface iface[1];
+};
+
+size_t ctdb_iface_list_len(struct ctdb_iface_list *iface_list)
+{
+ return sizeof(uint32_t) +
+ iface_list->num * sizeof(struct ctdb_iface);
+}
+
+void ctdb_iface_list_push(struct ctdb_iface_list *iface_list, uint8_t *buf)
+{
+ struct ctdb_iface_list_wire *wire =
+ (struct ctdb_iface_list_wire *)buf;
+
+ wire->num = iface_list->num;
+ memcpy(wire->iface, iface_list->iface,
+ iface_list->num * sizeof(struct ctdb_iface));
+}
+
+int ctdb_iface_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_iface_list **out)
+{
+ struct ctdb_iface_list *iface_list;
+ struct ctdb_iface_list_wire *wire =
+ (struct ctdb_iface_list_wire *)buf;
+
+ if (buflen < sizeof(uint32_t)) {
+ return EMSGSIZE;
+ }
+ if (buflen < sizeof(uint32_t) + wire->num * sizeof(struct ctdb_iface)) {
+ return EMSGSIZE;
+ }
+
+ iface_list = talloc(mem_ctx, struct ctdb_iface_list);
+ if (iface_list == NULL) {
+ return ENOMEM;
+ }
+
+ iface_list->num = wire->num;
+ iface_list->iface = talloc_array(iface_list, struct ctdb_iface,
+ wire->num);
+ if (iface_list->iface == NULL) {
+ talloc_free(iface_list);
+ return ENOMEM;
+ }
+
+ memcpy(iface_list->iface, wire->iface,
+ wire->num * sizeof(struct ctdb_iface));
+
+ *out = iface_list;
+ return 0;
+}
+
+struct ctdb_public_ip_info_wire {
+ struct ctdb_public_ip ip;
+ uint32_t active_idx;
+ uint32_t num;
+ struct ctdb_iface ifaces[1];
+};
+
+size_t ctdb_public_ip_info_len(struct ctdb_public_ip_info *ipinfo)
+{
+ return offsetof(struct ctdb_public_ip_info_wire, num) +
+ ctdb_iface_list_len(ipinfo->ifaces);
+}
+
+void ctdb_public_ip_info_push(struct ctdb_public_ip_info *ipinfo, uint8_t *buf)
+{
+ struct ctdb_public_ip_info_wire *wire =
+ (struct ctdb_public_ip_info_wire *)buf;
+ size_t offset;
+
+ offset = offsetof(struct ctdb_public_ip_info_wire, num);
+ memcpy(wire, ipinfo, offset);
+ wire->num = ipinfo->ifaces->num;
+ memcpy(wire->ifaces, ipinfo->ifaces->iface,
+ ipinfo->ifaces->num * sizeof(struct ctdb_iface));
+}
+
+int ctdb_public_ip_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_public_ip_info **out)
+{
+ struct ctdb_public_ip_info *ipinfo;
+ struct ctdb_public_ip_info_wire *wire =
+ (struct ctdb_public_ip_info_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_public_ip_info_wire, ifaces)) {
+ return EMSGSIZE;
+ }
+
+ ipinfo = talloc(mem_ctx, struct ctdb_public_ip_info);
+ if (ipinfo == NULL) {
+ return ENOMEM;
+ }
+
+ memcpy(ipinfo, wire, offsetof(struct ctdb_public_ip_info_wire, num));
+
+ ipinfo->ifaces = talloc(ipinfo, struct ctdb_iface_list);
+ if (ipinfo->ifaces == NULL) {
+ talloc_free(ipinfo);
+ return ENOMEM;
+ }
+
+ ipinfo->ifaces->num = wire->num;
+ ipinfo->ifaces->iface = talloc_array(ipinfo->ifaces, struct ctdb_iface,
+ wire->num);
+ if (ipinfo->ifaces->iface == NULL) {
+ talloc_free(ipinfo);
+ return ENOMEM;
+ }
+
+ memcpy(ipinfo->ifaces->iface, wire->ifaces,
+ wire->num * sizeof(struct ctdb_iface));
+
+ *out = ipinfo;
+ return 0;
+}
+
+struct ctdb_key_data_wire {
+ uint32_t db_id;
+ struct ctdb_ltdb_header header;
+ uint32_t keylen;
+ uint8_t key[1];
+};
+
+size_t ctdb_key_data_len(struct ctdb_key_data *key)
+{
+ return offsetof(struct ctdb_key_data_wire, key) + key->key.dsize;
+}
+
+void ctdb_key_data_push(struct ctdb_key_data *key, uint8_t *buf)
+{
+ struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
+
+ memcpy(wire, key, offsetof(struct ctdb_key_data, key));
+ wire->keylen = key->key.dsize;
+ memcpy(wire->key, key->key.dptr, key->key.dsize);
+}
+
+int ctdb_key_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_key_data **out)
+{
+ struct ctdb_key_data *key_data;
+ struct ctdb_key_data_wire *wire = (struct ctdb_key_data_wire *)buf;
+
+ if (buflen < offsetof(struct ctdb_key_data_wire, key)) {
+ return EMSGSIZE;
+ }
+ if (buflen < offsetof(struct ctdb_key_data_wire, key) + wire->keylen) {
+ return EMSGSIZE;
+ }
+
+ key_data = talloc(mem_ctx, struct ctdb_key_data);
+ if (key_data == NULL) {
+ return ENOMEM;
+ }
+
+ memcpy(key_data, wire, offsetof(struct ctdb_key_data, key));
+
+ key_data->key.dsize = wire->keylen;
+ key_data->key.dptr = talloc_memdup(key_data, wire->key, wire->keylen);
+ if (key_data->key.dptr == NULL) {
+ talloc_free(key_data);
+ return ENOMEM;
+ }
+
+ *out = key_data;
+ return 0;
+}
+
+struct ctdb_db_statistics_wire {
+ struct ctdb_db_statistics dbstats;
+ char hot_keys_wire[1];
+};
+
+size_t ctdb_db_statistics_len(struct ctdb_db_statistics *dbstats)
+{
+ size_t len;
+ int i;
+
+ len = sizeof(struct ctdb_db_statistics);
+ for (i=0; i<MAX_HOT_KEYS; i++) {
+ len += dbstats->hot_keys[i].key.dsize;
+ }
+ return len;
+}
+
+void ctdb_db_statistics_push(struct ctdb_db_statistics *dbstats, void *buf)
+{
+ struct ctdb_db_statistics_wire *wire =
+ (struct ctdb_db_statistics_wire *)buf;
+ size_t offset;
+ int i;
+
+ dbstats->num_hot_keys = MAX_HOT_KEYS;
+ memcpy(wire, dbstats, sizeof(struct ctdb_db_statistics));
+
+ offset = 0;
+ for (i=0; i<MAX_HOT_KEYS; i++) {
+ memcpy(&wire->hot_keys_wire[offset],
+ dbstats->hot_keys[i].key.dptr,
+ dbstats->hot_keys[i].key.dsize);
+ offset += dbstats->hot_keys[i].key.dsize;
+ }
+}
+
+int ctdb_db_statistics_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_db_statistics **out)
+{
+ struct ctdb_db_statistics *dbstats;
+ struct ctdb_db_statistics_wire *wire =
+ (struct ctdb_db_statistics_wire *)buf;
+ size_t offset;
+ int i;
+
+ if (buflen < sizeof(struct ctdb_db_statistics)) {
+ return EMSGSIZE;
+ }
+ offset = 0;
+ for (i=0; i<wire->dbstats.num_hot_keys; i++) {
+ offset += wire->dbstats.hot_keys[i].key.dsize;
+ }
+ if (buflen < sizeof(struct ctdb_db_statistics) + offset) {
+ return EMSGSIZE;
+ }
+
+ dbstats = talloc(mem_ctx, struct ctdb_db_statistics);
+ if (dbstats == NULL) {
+ return ENOMEM;
+ }
+
+ memcpy(dbstats, wire, sizeof(struct ctdb_db_statistics));
+
+ offset = 0;
+ for (i=0; i<wire->dbstats.num_hot_keys; i++) {
+ uint8_t *ptr;
+ size_t key_size;
+
+ key_size = dbstats->hot_keys[i].key.dsize;
+ ptr = talloc_memdup(mem_ctx, &wire->hot_keys_wire[offset],
+ key_size);
+ if (ptr == NULL) {
+ talloc_free(dbstats);
+ return ENOMEM;
+ }
+ dbstats->hot_keys[i].key.dptr = ptr;
+ offset += key_size;
+ }
+
+ *out = dbstats;
+ return 0;
+}
+
+size_t ctdb_election_message_len(struct ctdb_election_message *election)
+{
+ return sizeof(struct ctdb_election_message);
+}
+
+void ctdb_election_message_push(struct ctdb_election_message *election,
+ uint8_t *buf)
+{
+ memcpy(buf, election, sizeof(struct ctdb_election_message));
+}
+
+int ctdb_election_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_election_message **out)
+{
+ struct ctdb_election_message *election;
+
+ if (buflen < sizeof(struct ctdb_election_message)) {
+ return EMSGSIZE;
+ }
+
+ election = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_election_message));
+ if (election == NULL) {
+ return ENOMEM;
+ }
+
+ *out = election;
+ return 0;
+}
+
+size_t ctdb_srvid_message_len(struct ctdb_srvid_message *msg)
+{
+ return sizeof(struct ctdb_srvid_message);
+}
+
+void ctdb_srvid_message_push(struct ctdb_srvid_message *msg, uint8_t *buf)
+{
+ memcpy(buf, msg, sizeof(struct ctdb_srvid_message));
+}
+
+int ctdb_srvid_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_srvid_message **out)
+{
+ struct ctdb_srvid_message *msg;
+
+ if (buflen < sizeof(struct ctdb_srvid_message)) {
+ return EMSGSIZE;
+ }
+
+ msg = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_srvid_message));
+ if (msg == NULL) {
+ return ENOMEM;
+ }
+
+ *out = msg;
+ return 0;
+}
+
+size_t ctdb_disable_message_len(struct ctdb_disable_message *disable)
+{
+ return sizeof(struct ctdb_disable_message);
+}
+
+void ctdb_disable_message_push(struct ctdb_disable_message *disable,
+ uint8_t *buf)
+{
+ memcpy(buf, disable, sizeof(struct ctdb_disable_message));
+}
+
+int ctdb_disable_message_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_disable_message **out)
+{
+ struct ctdb_disable_message *disable;
+
+ if (buflen < sizeof(struct ctdb_disable_message)) {
+ return EMSGSIZE;
+ }
+
+ disable = talloc_memdup(mem_ctx, buf,
+ sizeof(struct ctdb_disable_message));
+ if (disable == NULL) {
+ return ENOMEM;
+ }
+
+ *out = disable;
+ return 0;
+}
+
+size_t ctdb_server_id_len(struct ctdb_server_id *sid)
+{
+ return sizeof(struct ctdb_server_id);
+}
+
+void ctdb_server_id_push(struct ctdb_server_id *sid, uint8_t *buf)
+{
+ memcpy(buf, sid, sizeof(struct ctdb_server_id));
+}
+
+int ctdb_server_id_pull(uint8_t *buf, size_t buflen,
+ struct ctdb_server_id *sid)
+{
+ if (buflen < sizeof(struct ctdb_server_id)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(sid, buf, sizeof(struct ctdb_server_id));
+ return 0;
+}
+
+size_t ctdb_g_lock_len(struct ctdb_g_lock *lock)
+{
+ return sizeof(struct ctdb_g_lock);
+}
+
+void ctdb_g_lock_push(struct ctdb_g_lock *lock, uint8_t *buf)
+{
+ memcpy(buf, lock, sizeof(struct ctdb_g_lock));
+}
+
+int ctdb_g_lock_pull(uint8_t *buf, size_t buflen, struct ctdb_g_lock *lock)
+{
+ if (buflen < sizeof(struct ctdb_g_lock)) {
+ return EMSGSIZE;
+ }
+
+ memcpy(lock, buf, sizeof(struct ctdb_g_lock));
+ return 0;
+}
+
+size_t ctdb_g_lock_list_len(struct ctdb_g_lock_list *lock_list)
+{
+ return lock_list->num * sizeof(struct ctdb_g_lock);
+}
+
+void ctdb_g_lock_list_push(struct ctdb_g_lock_list *lock_list, uint8_t *buf)
+{
+ size_t offset = 0;
+ int i;
+
+ for (i=0; i<lock_list->num; i++) {
+ ctdb_g_lock_push(&lock_list->lock[i], &buf[offset]);
+ offset += sizeof(struct ctdb_g_lock);
+ }
+}
+
+int ctdb_g_lock_list_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx,
+ struct ctdb_g_lock_list **out)
+{
+ struct ctdb_g_lock_list *lock_list;
+ unsigned count;
+ size_t offset;
+ int ret, i;
+
+ lock_list = talloc_zero(mem_ctx, struct ctdb_g_lock_list);
+ if (lock_list == NULL) {
+ return ENOMEM;
+ }
+
+ count = buflen / sizeof(struct ctdb_g_lock);
+ lock_list->lock = talloc_array(lock_list, struct ctdb_g_lock, count);
+ if (lock_list->lock == NULL) {
+ talloc_free(lock_list);
+ return ENOMEM;
+ }
+
+ offset = 0;
+ for (i=0; i<count; i++) {
+ ret = ctdb_g_lock_pull(&buf[offset], buflen-offset,
+ &lock_list->lock[i]);
+ if (ret != 0) {
+ talloc_free(lock_list);
+ return ret;
+ }
+ offset += sizeof(struct ctdb_g_lock);
+ }
+
+ lock_list->num = count;
+
+ *out = lock_list;
+ return 0;
+}
diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c
new file mode 100644
index 00000000000..1082b0b2e8f
--- /dev/null
+++ b/ctdb/protocol/protocol_util.c
@@ -0,0 +1,114 @@
+/*
+ CTDB protocol marshalling
+
+ Copyright (C) Amitay Isaacs 2015
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/network.h"
+
+#include <talloc.h>
+#include <tdb.h>
+
+#include "protocol.h"
+#include "protocol_private.h"
+#include "protocol_api.h"
+
+static struct {
+ enum ctdb_runstate runstate;
+ const char * label;
+} runstate_map[] = {
+ { CTDB_RUNSTATE_UNKNOWN, "UNKNOWN" },
+ { CTDB_RUNSTATE_INIT, "INIT" },
+ { CTDB_RUNSTATE_SETUP, "SETUP" },
+ { CTDB_RUNSTATE_FIRST_RECOVERY, "FIRST_RECOVERY" },
+ { CTDB_RUNSTATE_STARTUP, "STARTUP" },
+ { CTDB_RUNSTATE_RUNNING, "RUNNING" },
+ { CTDB_RUNSTATE_SHUTDOWN, "SHUTDOWN" },
+ { -1, NULL },
+};
+
+const char *ctdb_runstate_to_string(enum ctdb_runstate runstate)
+{
+ int i;
+
+ for (i=0; runstate_map[i].label != NULL; i++) {
+ if (runstate_map[i].runstate == runstate) {
+ return runstate_map[i].label;
+ }
+ }
+
+ return runstate_map[0].label;
+}
+
+enum ctdb_runstate ctdb_runstate_from_string(const char *runstate_str)
+{
+ int i;
+
+ for (i=0; runstate_map[i].label != NULL; i++) {
+ if (strcasecmp(runstate_map[i].label,
+ runstate_str) == 0) {
+ return runstate_map[i].runstate;
+ }
+ }
+
+ return CTDB_RUNSTATE_UNKNOWN;
+}
+
+static struct {
+ enum ctdb_event event;
+ const char *label;
+} event_map[] = {
+ { CTDB_EVENT_INIT, "init" },
+ { CTDB_EVENT_SETUP, "setup" },
+ { CTDB_EVENT_STARTUP, "startup" },
+ { CTDB_EVENT_START_RECOVERY, "startrecovery" },
+ { CTDB_EVENT_RECOVERED, "recovered" },
+ { CTDB_EVENT_TAKE_IP, "takeip" },
+ { CTDB_EVENT_RELEASE_IP, "releaseip" },
+ { CTDB_EVENT_MONITOR, "monitor" },
+ { CTDB_EVENT_SHUTDOWN, "shutdown" },
+ { CTDB_EVENT_UPDATE_IP, "updateip" },
+ { CTDB_EVENT_IPREALLOCATED, "ipreallocated" },
+ { CTDB_EVENT_MAX, "all" },
+ { -1, NULL },
+};
+
+const char *ctdb_event_to_string(enum ctdb_event event)
+{
+ int i;
+
+ for (i=0; event_map[i].label != NULL; i++) {
+ if (event_map[i].event == event) {
+ return event_map[i].label;
+ }
+ }
+
+ return "unknown";
+}
+
+enum ctdb_event ctdb_event_from_string(const char *event_str)
+{
+ int i;
+
+ for (i=0; event_map[i].label != NULL; i++) {
+ if (strcmp(event_map[i].label, event_str) == 0) {
+ return event_map[i].event;
+ }
+ }
+
+ return CTDB_EVENT_MAX;
+}