ctdb-protocol: Fix marshalling for ctdb_uptime
[vlendec/samba-autobuild/.git] / ctdb / tests / src / protocol_types_compat_test.c
index 86db077c878081f67e411626212eb451b6bbf1c3..ad908d0b515ee3a077666776ff82403dad25892e 100644 (file)
@@ -242,10 +242,955 @@ static int ctdb_dbid_map_pull_old(uint8_t *buf, size_t buflen,
        return 0;
 }
 
+static size_t ctdb_pulldb_len_old(struct ctdb_pulldb *in)
+{
+       return sizeof(struct ctdb_pulldb);
+}
+
+static void ctdb_pulldb_push_old(struct ctdb_pulldb *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_pulldb));
+}
+
+static int ctdb_pulldb_pull_old(uint8_t *buf, size_t buflen,
+                               TALLOC_CTX *mem_ctx, struct ctdb_pulldb **out)
+{
+       struct ctdb_pulldb *val;
+
+       if (buflen < sizeof(struct ctdb_pulldb)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_pulldb_ext_len_old(struct ctdb_pulldb_ext *in)
+{
+       return sizeof(struct ctdb_pulldb_ext);
+}
+
+static void ctdb_pulldb_ext_push_old(struct ctdb_pulldb_ext *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_pulldb_ext));
+}
+
+static int ctdb_pulldb_ext_pull_old(uint8_t *buf, size_t buflen,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct ctdb_pulldb_ext **out)
+{
+       struct ctdb_pulldb_ext *val;
+
+       if (buflen < sizeof(struct ctdb_pulldb_ext)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_pulldb_ext));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_ltdb_header_len_old(struct ctdb_ltdb_header *in)
+{
+       return sizeof(struct ctdb_ltdb_header);
+}
+
+static void ctdb_ltdb_header_push_old(struct ctdb_ltdb_header *in,
+                                     uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_ltdb_header));
+}
+
+static int ctdb_ltdb_header_pull_old(uint8_t *buf, size_t buflen,
+                                    struct ctdb_ltdb_header *out)
+{
+       if (buflen < sizeof(struct ctdb_ltdb_header)) {
+               return EMSGSIZE;
+       }
+
+       memcpy(out, 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];
+};
+
+static size_t ctdb_rec_data_len_old(struct ctdb_rec_data *in)
+{
+       return offsetof(struct ctdb_rec_data_wire, data) +
+              in->key.dsize + in->data.dsize +
+              (in->header == NULL ? 0 : sizeof(struct ctdb_ltdb_header));
+}
+
+static void ctdb_rec_data_push_old(struct ctdb_rec_data *in, uint8_t *buf)
+{
+       struct ctdb_rec_data_wire *wire = (struct ctdb_rec_data_wire *)buf;
+       size_t offset;
+
+       wire->length = ctdb_rec_data_len(in);
+       wire->reqid = in->reqid;
+       wire->keylen = in->key.dsize;
+       wire->datalen = in->data.dsize;
+       if (in->header != NULL) {
+               wire->datalen += sizeof(struct ctdb_ltdb_header);
+       }
+
+       memcpy(wire->data, in->key.dptr, in->key.dsize);
+       offset = in->key.dsize;
+       if (in->header != NULL) {
+               memcpy(&wire->data[offset], in->header,
+                      sizeof(struct ctdb_ltdb_header));
+               offset += sizeof(struct ctdb_ltdb_header);
+       }
+       if (in->data.dsize > 0) {
+               memcpy(&wire->data[offset], in->data.dptr, in->data.dsize);
+       }
+}
+
+static int ctdb_rec_data_pull_data_old(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;
+
+       if (buflen < offsetof(struct ctdb_rec_data_wire, data)) {
+               return EMSGSIZE;
+       }
+       if (wire->keylen > buflen || wire->datalen > buflen) {
+               return EMSGSIZE;
+       }
+       if (offsetof(struct ctdb_rec_data_wire, data) + wire->keylen <
+           offsetof(struct ctdb_rec_data_wire, data)) {
+               return EMSGSIZE;
+       }
+       if (offsetof(struct ctdb_rec_data_wire, data) +
+               wire->keylen + wire->datalen <
+           offsetof(struct ctdb_rec_data_wire, data)) {
+               return EMSGSIZE;
+       }
+       if (buflen < offsetof(struct ctdb_rec_data_wire, data) +
+                       wire->keylen + wire->datalen) {
+               return EMSGSIZE;
+       }
+
+       *reqid = wire->reqid;
+
+       key->dsize = wire->keylen;
+       key->dptr = wire->data;
+       offset = wire->keylen;
+
+       /* Always set header to NULL.  If it is required, exact it using
+        * ctdb_rec_data_extract_header()
+        */
+       *header = NULL;
+
+       data->dsize = wire->datalen;
+       data->dptr = &wire->data[offset];
+
+       *reclen = offsetof(struct ctdb_rec_data_wire, data) +
+                       wire->keylen + wire->datalen;
+
+       return 0;
+}
+
+static int ctdb_rec_data_pull_elems_old(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_old(buf, buflen, &reqid, &header,
+                                         &key, &data, &reclen);
+       if (ret != 0) {
+               return ret;
+       }
+
+       out->reqid = reqid;
+       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;
+}
+
+static int ctdb_rec_data_pull_old(uint8_t *buf, size_t buflen,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct ctdb_rec_data **out)
+{
+       struct ctdb_rec_data *val;
+       int ret;
+
+       val = talloc(mem_ctx, struct ctdb_rec_data);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       ret = ctdb_rec_data_pull_elems_old(buf, buflen, val, val);
+       if (ret != 0) {
+               TALLOC_FREE(val);
+               return ret;
+       }
+
+       *out = val;
+       return ret;
+}
+
+struct ctdb_rec_buffer_wire {
+       uint32_t db_id;
+       uint32_t count;
+       uint8_t data[1];
+};
+
+static size_t ctdb_rec_buffer_len_old(struct ctdb_rec_buffer *in)
+{
+       return offsetof(struct ctdb_rec_buffer_wire, data) + in->buflen;
+}
+
+static void ctdb_rec_buffer_push_old(struct ctdb_rec_buffer *in, uint8_t *buf)
+{
+       struct ctdb_rec_buffer_wire *wire = (struct ctdb_rec_buffer_wire *)buf;
+
+       wire->db_id = in->db_id;
+       wire->count = in->count;
+       if (in->buflen > 0) {
+               memcpy(wire->data, in->buf, in->buflen);
+       }
+}
+
+static int ctdb_rec_buffer_pull_old(uint8_t *buf, size_t buflen,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct ctdb_rec_buffer **out)
+{
+       struct ctdb_rec_buffer *val;
+       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;
+       }
+
+       val = talloc(mem_ctx, struct ctdb_rec_buffer);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       val->db_id = wire->db_id;
+       val->count = wire->count;
+
+       offset = offsetof(struct ctdb_rec_buffer_wire, data);
+       val->buflen = buflen - offset;
+       val->buf = talloc_memdup(val, wire->data, val->buflen);
+       if (val->buf == NULL) {
+               talloc_free(val);
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_traverse_start_len_old(struct ctdb_traverse_start *in)
+{
+       return sizeof(struct ctdb_traverse_start);
+}
+
+static void ctdb_traverse_start_push_old(struct ctdb_traverse_start *in,
+                                        uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_traverse_start));
+}
+
+static int ctdb_traverse_start_pull_old(uint8_t *buf, size_t buflen,
+                                       TALLOC_CTX *mem_ctx,
+                                       struct ctdb_traverse_start **out)
+{
+       struct ctdb_traverse_start *val;
+
+       if (buflen < sizeof(struct ctdb_traverse_start)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_traverse_start));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_traverse_all_len_old(struct ctdb_traverse_all *in)
+{
+       return sizeof(struct ctdb_traverse_all);
+}
+
+static void ctdb_traverse_all_push_old(struct ctdb_traverse_all *in,
+                                      uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_traverse_all));
+}
+
+static int ctdb_traverse_all_pull_old(uint8_t *buf, size_t buflen,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct ctdb_traverse_all **out)
+{
+       struct ctdb_traverse_all *val;
+
+       if (buflen < sizeof(struct ctdb_traverse_all)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_traverse_all));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_traverse_start_ext_len_old(
+                       struct ctdb_traverse_start_ext *in)
+{
+       return sizeof(struct ctdb_traverse_start_ext);
+}
+
+static void ctdb_traverse_start_ext_push_old(
+                       struct ctdb_traverse_start_ext *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_traverse_start_ext));
+}
+
+static int ctdb_traverse_start_ext_pull_old(uint8_t *buf, size_t buflen,
+                                           TALLOC_CTX *mem_ctx,
+                                           struct ctdb_traverse_start_ext **out)
+{
+       struct ctdb_traverse_start_ext *val;
+
+       if (buflen < sizeof(struct ctdb_traverse_start_ext)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf,
+                           sizeof(struct ctdb_traverse_start_ext));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_traverse_all_ext_len_old(struct ctdb_traverse_all_ext *in)
+{
+       return sizeof(struct ctdb_traverse_all_ext);
+}
+
+static void ctdb_traverse_all_ext_push_old(struct ctdb_traverse_all_ext *in,
+                                          uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_traverse_all_ext));
+}
+
+static int ctdb_traverse_all_ext_pull_old(uint8_t *buf, size_t buflen,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct ctdb_traverse_all_ext **out)
+{
+       struct ctdb_traverse_all_ext *val;
+
+       if (buflen < sizeof(struct ctdb_traverse_all_ext)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf,
+                           sizeof(struct ctdb_traverse_all_ext));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_sock_addr_len_old(ctdb_sock_addr *in)
+{
+       return sizeof(ctdb_sock_addr);
+}
+
+static void ctdb_sock_addr_push_old(ctdb_sock_addr *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(ctdb_sock_addr));
+}
+
+static int ctdb_sock_addr_pull_elems_old(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;
+}
+
+static int ctdb_sock_addr_pull_old(uint8_t *buf, size_t buflen,
+                                  TALLOC_CTX *mem_ctx, ctdb_sock_addr **out)
+{
+       ctdb_sock_addr *val;
+       int ret;
+
+       val = talloc(mem_ctx, ctdb_sock_addr);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       ret = ctdb_sock_addr_pull_elems_old(buf, buflen, val, val);
+       if (ret != 0) {
+               TALLOC_FREE(val);
+               return ret;
+       }
+
+       *out = val;
+       return ret;
+}
+
+static size_t ctdb_connection_len_old(struct ctdb_connection *in)
+{
+       return sizeof(struct ctdb_connection);
+}
+
+static void ctdb_connection_push_old(struct ctdb_connection *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_connection));
+}
+
+static int ctdb_connection_pull_elems_old(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;
+}
+
+static int ctdb_connection_pull_old(uint8_t *buf, size_t buflen,
+                                   TALLOC_CTX *mem_ctx,
+                                   struct ctdb_connection **out)
+{
+       struct ctdb_connection *val;
+       int ret;
+
+       val = talloc(mem_ctx, struct ctdb_connection);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       ret = ctdb_connection_pull_elems_old(buf, buflen, val, val);
+       if (ret != 0) {
+               TALLOC_FREE(val);
+               return ret;
+       }
+
+       *out = val;
+       return ret;
+}
+
+struct ctdb_tunable_wire {
+       uint32_t value;
+       uint32_t length;
+       uint8_t name[1];
+};
+
+static size_t ctdb_tunable_len_old(struct ctdb_tunable *in)
+{
+       return offsetof(struct ctdb_tunable_wire, name) +
+              strlen(in->name) + 1;
+}
+
+static void ctdb_tunable_push_old(struct ctdb_tunable *in, uint8_t *buf)
+{
+       struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
+
+       wire->value = in->value;
+       wire->length = strlen(in->name) + 1;
+       memcpy(wire->name, in->name, wire->length);
+}
+
+static int ctdb_tunable_pull_old(uint8_t *buf, size_t buflen,
+                                TALLOC_CTX *mem_ctx,
+                                struct ctdb_tunable **out)
+{
+       struct ctdb_tunable *val;
+       struct ctdb_tunable_wire *wire = (struct ctdb_tunable_wire *)buf;
+
+       if (buflen < offsetof(struct ctdb_tunable_wire, name)) {
+               return EMSGSIZE;
+       }
+       if (wire->length > buflen) {
+               return EMSGSIZE;
+       }
+       if (offsetof(struct ctdb_tunable_wire, name) + wire->length <
+           offsetof(struct ctdb_tunable_wire, name)) {
+               return EMSGSIZE;
+       }
+       if (buflen < offsetof(struct ctdb_tunable_wire, name) + wire->length) {
+               return EMSGSIZE;
+       }
+
+       val = talloc(mem_ctx, struct ctdb_tunable);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       val->value = wire->value;
+       val->name = talloc_memdup(val, wire->name, wire->length);
+       if (val->name == NULL) {
+               talloc_free(val);
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_node_flag_change_len_old(struct ctdb_node_flag_change *in)
+{
+       return sizeof(struct ctdb_node_flag_change);
+}
+
+static void ctdb_node_flag_change_push_old(struct ctdb_node_flag_change *in,
+                                          uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_node_flag_change));
+}
+
+static int ctdb_node_flag_change_pull_old(uint8_t *buf, size_t buflen,
+                                         TALLOC_CTX *mem_ctx,
+                                         struct ctdb_node_flag_change **out)
+{
+       struct ctdb_node_flag_change *val;
+
+       if (buflen < sizeof(struct ctdb_node_flag_change)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf,
+                           sizeof(struct ctdb_node_flag_change));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+struct ctdb_var_list_wire {
+       uint32_t length;
+       char list_str[1];
+};
+
+static size_t ctdb_var_list_len_old(struct ctdb_var_list *in)
+{
+       int i;
+       size_t len = sizeof(uint32_t);
+
+       for (i=0; i<in->count; i++) {
+               len += strlen(in->var[i]) + 1;
+       }
+       return len;
+}
+
+static void ctdb_var_list_push_old(struct ctdb_var_list *in, uint8_t *buf)
+{
+       struct ctdb_var_list_wire *wire = (struct ctdb_var_list_wire *)buf;
+       int i, n;
+       size_t offset = 0;
+
+       if (in->count > 0) {
+               n = sprintf(wire->list_str, "%s", in->var[0]);
+               offset += n;
+       }
+       for (i=1; i<in->count; i++) {
+               n = sprintf(&wire->list_str[offset], ":%s", in->var[i]);
+               offset += n;
+       }
+       wire->length = offset + 1;
+}
+
+static int ctdb_var_list_pull_old(uint8_t *buf, size_t buflen,
+                                 TALLOC_CTX *mem_ctx,
+                                 struct ctdb_var_list **out)
+{
+       struct ctdb_var_list *val = 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 (wire->length > buflen) {
+               return EMSGSIZE;
+       }
+       if (sizeof(uint32_t) + wire->length < 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;
+       }
+
+       val = talloc_zero(mem_ctx, struct ctdb_var_list);
+       if (val == NULL) {
+               goto fail;
+       }
+
+       s = str;
+       while ((tok = strtok_r(s, ":", &ptr)) != NULL) {
+               s = NULL;
+               list = talloc_realloc(val, val->var, const char *,
+                                     val->count+1);
+               if (list == NULL) {
+                       goto fail;
+               }
+
+               val->var = list;
+               val->var[val->count] = talloc_strdup(val, tok);
+               if (val->var[val->count] == NULL) {
+                       goto fail;
+               }
+               val->count++;
+       }
+
+       talloc_free(str);
+       *out = val;
+       return 0;
+
+fail:
+       talloc_free(str);
+       talloc_free(val);
+       return ENOMEM;
+}
+
+static size_t ctdb_tunable_list_len_old(struct ctdb_tunable_list *in)
+{
+       return sizeof(struct ctdb_tunable_list);
+}
+
+static void ctdb_tunable_list_push_old(struct ctdb_tunable_list *in,
+                                      uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_tunable_list));
+}
+
+static int ctdb_tunable_list_pull_old(uint8_t *buf, size_t buflen,
+                                     TALLOC_CTX *mem_ctx,
+                                     struct ctdb_tunable_list **out)
+{
+       struct ctdb_tunable_list *val;
+
+       if (buflen < sizeof(struct ctdb_tunable_list)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_tunable_list));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+struct ctdb_tickle_list_wire {
+       ctdb_sock_addr addr;
+       uint32_t num;
+       struct ctdb_connection conn[1];
+};
+
+static size_t ctdb_tickle_list_len_old(struct ctdb_tickle_list *in)
+{
+       return offsetof(struct ctdb_tickle_list, conn) +
+              in->num * sizeof(struct ctdb_connection);
+}
+
+static void ctdb_tickle_list_push_old(struct ctdb_tickle_list *in,
+                                     uint8_t *buf)
+{
+       struct ctdb_tickle_list_wire *wire =
+               (struct ctdb_tickle_list_wire *)buf;
+       size_t offset;
+       int i;
+
+       memcpy(&wire->addr, &in->addr, sizeof(ctdb_sock_addr));
+       wire->num = in->num;
+
+       offset = offsetof(struct ctdb_tickle_list_wire, conn);
+       for (i=0; i<in->num; i++) {
+               ctdb_connection_push_old(&in->conn[i], &buf[offset]);
+               offset += ctdb_connection_len_old(&in->conn[i]);
+       }
+}
+
+static int ctdb_tickle_list_pull_old(uint8_t *buf, size_t buflen,
+                                    TALLOC_CTX *mem_ctx,
+                                    struct ctdb_tickle_list **out)
+{
+       struct ctdb_tickle_list *val;
+       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 (wire->num > buflen / sizeof(struct ctdb_connection)) {
+               return EMSGSIZE;
+       }
+       if (offsetof(struct ctdb_tickle_list_wire, conn) +
+           wire->num * sizeof(struct ctdb_connection) <
+           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;
+       }
+
+       val = talloc(mem_ctx, struct ctdb_tickle_list);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       offset = offsetof(struct ctdb_tickle_list, conn);
+       memcpy(val, wire, offset);
+
+       val->conn = talloc_array(val, struct ctdb_connection, wire->num);
+       if (val->conn == NULL) {
+               talloc_free(val);
+               return ENOMEM;
+       }
+
+       for (i=0; i<wire->num; i++) {
+               ret = ctdb_connection_pull_elems_old(&buf[offset],
+                                                    buflen-offset,
+                                                    val->conn,
+                                                    &val->conn[i]);
+               if (ret != 0) {
+                       talloc_free(val);
+                       return ret;
+               }
+               offset += ctdb_connection_len_old(&val->conn[i]);
+       }
+
+       *out = val;
+       return 0;
+}
+
+struct ctdb_addr_info_wire {
+       ctdb_sock_addr addr;
+       uint32_t mask;
+       uint32_t len;
+       char iface[1];
+};
+
+static size_t ctdb_addr_info_len_old(struct ctdb_addr_info *in)
+{
+       uint32_t len;
+
+       len = offsetof(struct ctdb_addr_info_wire, iface);
+       if (in->iface != NULL) {
+              len += strlen(in->iface)+1;
+       }
+
+       return len;
+}
+
+static void ctdb_addr_info_push_old(struct ctdb_addr_info *in, uint8_t *buf)
+{
+       struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
+
+       wire->addr = in->addr;
+       wire->mask = in->mask;
+       if (in->iface == NULL) {
+               wire->len = 0;
+       } else {
+               wire->len = strlen(in->iface)+1;
+               memcpy(wire->iface, in->iface, wire->len);
+       }
+}
+
+static int ctdb_addr_info_pull_old(uint8_t *buf, size_t buflen,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct ctdb_addr_info **out)
+{
+       struct ctdb_addr_info *val;
+       struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf;
+
+       if (buflen < offsetof(struct ctdb_addr_info_wire, iface)) {
+               return EMSGSIZE;
+       }
+       if (wire->len > buflen) {
+               return EMSGSIZE;
+       }
+       if (offsetof(struct ctdb_addr_info_wire, iface) + wire->len <
+           offsetof(struct ctdb_addr_info_wire, iface)) {
+               return EMSGSIZE;
+       }
+       if (buflen < offsetof(struct ctdb_addr_info_wire, iface) + wire->len) {
+               return EMSGSIZE;
+       }
+
+       val = talloc(mem_ctx, struct ctdb_addr_info);
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       val->addr = wire->addr;
+       val->mask = wire->mask;
+
+       if (wire->len == 0) {
+               val->iface = NULL;
+       } else {
+               val->iface = talloc_strndup(val, wire->iface, wire->len);
+               if (val->iface == NULL) {
+                       talloc_free(val);
+                       return ENOMEM;
+               }
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_transdb_len_old(struct ctdb_transdb *in)
+{
+       return sizeof(struct ctdb_transdb);
+}
+
+static void ctdb_transdb_push_old(struct ctdb_transdb *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_transdb));
+}
+
+static int ctdb_transdb_pull_old(uint8_t *buf, size_t buflen,
+                                TALLOC_CTX *mem_ctx,
+                                struct ctdb_transdb **out)
+{
+       struct ctdb_transdb *val;
+
+       if (buflen < sizeof(struct ctdb_transdb)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_transdb));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
+static size_t ctdb_uptime_len_old(struct ctdb_uptime *in)
+{
+       return sizeof(struct ctdb_uptime);
+}
+
+static void ctdb_uptime_push_old(struct ctdb_uptime *in, uint8_t *buf)
+{
+       memcpy(buf, in, sizeof(struct ctdb_uptime));
+}
+
+static int ctdb_uptime_pull_old(uint8_t *buf, size_t buflen,
+                               TALLOC_CTX *mem_ctx, struct ctdb_uptime **out)
+{
+       struct ctdb_uptime *val;
+
+       if (buflen < sizeof(struct ctdb_uptime)) {
+               return EMSGSIZE;
+       }
+
+       val = talloc_memdup(mem_ctx, buf, sizeof(struct ctdb_uptime));
+       if (val == NULL) {
+               return ENOMEM;
+       }
+
+       *out = val;
+       return 0;
+}
+
 
 COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics);
 COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map);
 COMPAT_TYPE3_TEST(struct ctdb_dbid_map, ctdb_dbid_map);
+COMPAT_TYPE3_TEST(struct ctdb_pulldb, ctdb_pulldb);
+COMPAT_TYPE3_TEST(struct ctdb_pulldb_ext, ctdb_pulldb_ext);
+
+COMPAT_TYPE1_TEST(struct ctdb_ltdb_header, ctdb_ltdb_header);
+
+COMPAT_TYPE3_TEST(struct ctdb_rec_data, ctdb_rec_data);
+COMPAT_TYPE3_TEST(struct ctdb_rec_buffer, ctdb_rec_buffer);
+COMPAT_TYPE3_TEST(struct ctdb_traverse_start, ctdb_traverse_start);
+COMPAT_TYPE3_TEST(struct ctdb_traverse_all, ctdb_traverse_all);
+COMPAT_TYPE3_TEST(struct ctdb_traverse_start_ext, ctdb_traverse_start_ext);
+COMPAT_TYPE3_TEST(struct ctdb_traverse_all_ext, ctdb_traverse_all_ext);
+COMPAT_TYPE3_TEST(ctdb_sock_addr, ctdb_sock_addr);
+COMPAT_TYPE3_TEST(struct ctdb_connection, ctdb_connection);
+COMPAT_TYPE3_TEST(struct ctdb_tunable, ctdb_tunable);
+COMPAT_TYPE3_TEST(struct ctdb_node_flag_change, ctdb_node_flag_change);
+COMPAT_TYPE3_TEST(struct ctdb_var_list, ctdb_var_list);
+COMPAT_TYPE3_TEST(struct ctdb_tunable_list, ctdb_tunable_list);
+COMPAT_TYPE3_TEST(struct ctdb_tickle_list, ctdb_tickle_list);
+COMPAT_TYPE3_TEST(struct ctdb_addr_info, ctdb_addr_info);
+COMPAT_TYPE3_TEST(struct ctdb_transdb, ctdb_transdb);
+COMPAT_TYPE3_TEST(struct ctdb_uptime, ctdb_uptime);
 
 int main(int argc, char *argv[])
 {
@@ -257,6 +1202,25 @@ int main(int argc, char *argv[])
        COMPAT_TEST_FUNC(ctdb_statistics)();
        COMPAT_TEST_FUNC(ctdb_vnn_map)();
        COMPAT_TEST_FUNC(ctdb_dbid_map)();
+       COMPAT_TEST_FUNC(ctdb_pulldb)();
+       COMPAT_TEST_FUNC(ctdb_pulldb_ext)();
+       COMPAT_TEST_FUNC(ctdb_ltdb_header)();
+       COMPAT_TEST_FUNC(ctdb_rec_data)();
+       COMPAT_TEST_FUNC(ctdb_rec_buffer)();
+       COMPAT_TEST_FUNC(ctdb_traverse_start)();
+       COMPAT_TEST_FUNC(ctdb_traverse_all)();
+       COMPAT_TEST_FUNC(ctdb_traverse_start_ext)();
+       COMPAT_TEST_FUNC(ctdb_traverse_all_ext)();
+       COMPAT_TEST_FUNC(ctdb_sock_addr)();
+       COMPAT_TEST_FUNC(ctdb_connection)();
+       COMPAT_TEST_FUNC(ctdb_tunable)();
+       COMPAT_TEST_FUNC(ctdb_node_flag_change)();
+       COMPAT_TEST_FUNC(ctdb_var_list)();
+       COMPAT_TEST_FUNC(ctdb_tunable_list)();
+       COMPAT_TEST_FUNC(ctdb_tickle_list)();
+       COMPAT_TEST_FUNC(ctdb_addr_info)();
+       COMPAT_TEST_FUNC(ctdb_transdb)();
+       COMPAT_TEST_FUNC(ctdb_uptime)();
 
        return 0;
 }