From 4d70b972f2be599bcb9e8f70234b9768ac317a7c Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Tue, 4 Jul 2017 18:12:04 +1000 Subject: [PATCH] ctdb-protocol: Fix marshalling for ctdb_addr_info Signed-off-by: Amitay Isaacs Reviewed-by: Martin Schwenke --- ctdb/protocol/protocol_control.c | 12 +-- ctdb/protocol/protocol_private.h | 7 +- ctdb/protocol/protocol_types.c | 99 +++++++++------------ ctdb/tests/src/protocol_types_compat_test.c | 78 ++++++++++++++++ ctdb/tests/src/protocol_types_test.c | 2 +- 5 files changed, 133 insertions(+), 65 deletions(-) diff --git a/ctdb/protocol/protocol_control.c b/ctdb/protocol/protocol_control.c index 621290ce1a1..360665caf11 100644 --- a/ctdb/protocol/protocol_control.c +++ b/ctdb/protocol/protocol_control.c @@ -551,7 +551,7 @@ static void ctdb_req_control_data_push(struct ctdb_req_control_data *cd, break; case CTDB_CONTROL_SEND_GRATUITOUS_ARP: - ctdb_addr_info_push(cd->data.addr_info, buf); + ctdb_addr_info_push(cd->data.addr_info, buf, &np); break; case CTDB_CONTROL_WIPE_DATABASE: @@ -563,11 +563,11 @@ static void ctdb_req_control_data_push(struct ctdb_req_control_data *cd, break; case CTDB_CONTROL_ADD_PUBLIC_IP: - ctdb_addr_info_push(cd->data.addr_info, buf); + ctdb_addr_info_push(cd->data.addr_info, buf, &np); break; case CTDB_CONTROL_DEL_PUBLIC_IP: - ctdb_addr_info_push(cd->data.addr_info, buf); + ctdb_addr_info_push(cd->data.addr_info, buf, &np); break; case CTDB_CONTROL_RELEASE_IP: @@ -853,7 +853,7 @@ static int ctdb_req_control_data_pull(uint8_t *buf, size_t buflen, case CTDB_CONTROL_SEND_GRATUITOUS_ARP: ret = ctdb_addr_info_pull(buf, buflen, mem_ctx, - &cd->data.addr_info); + &cd->data.addr_info, &np); break; case CTDB_CONTROL_WIPE_DATABASE: @@ -868,12 +868,12 @@ static int ctdb_req_control_data_pull(uint8_t *buf, size_t buflen, case CTDB_CONTROL_ADD_PUBLIC_IP: ret = ctdb_addr_info_pull(buf, buflen, mem_ctx, - &cd->data.addr_info); + &cd->data.addr_info, &np); break; case CTDB_CONTROL_DEL_PUBLIC_IP: ret = ctdb_addr_info_pull(buf, buflen, mem_ctx, - &cd->data.addr_info); + &cd->data.addr_info, &np); break; case CTDB_CONTROL_RELEASE_IP: diff --git a/ctdb/protocol/protocol_private.h b/ctdb/protocol/protocol_private.h index 037819ac9e3..8b3c9bcbbeb 100644 --- a/ctdb/protocol/protocol_private.h +++ b/ctdb/protocol/protocol_private.h @@ -215,10 +215,11 @@ void ctdb_tickle_list_push(struct ctdb_tickle_list *in, 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 *npull); -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); +size_t ctdb_addr_info_len(struct ctdb_addr_info *in); +void ctdb_addr_info_push(struct ctdb_addr_info *in, uint8_t *buf, + size_t *npush); int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, - struct ctdb_addr_info **out); + struct ctdb_addr_info **out, size_t *npull); size_t ctdb_transdb_len(struct ctdb_transdb *transdb); void ctdb_transdb_push(struct ctdb_transdb *transdb, uint8_t *buf); diff --git a/ctdb/protocol/protocol_types.c b/ctdb/protocol/protocol_types.c index ec9d7d5eb81..90091ff1b4c 100644 --- a/ctdb/protocol/protocol_types.c +++ b/ctdb/protocol/protocol_types.c @@ -3194,80 +3194,69 @@ fail: return ret; } -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 *in) +{ + return ctdb_sock_addr_len(&in->addr) + + ctdb_uint32_len(&in->mask) + + ctdb_stringn_len(&in->iface); +} -size_t ctdb_addr_info_len(struct ctdb_addr_info *arp) +void ctdb_addr_info_push(struct ctdb_addr_info *in, uint8_t *buf, + size_t *npush) { - uint32_t len; + size_t offset = 0, np; - len = offsetof(struct ctdb_addr_info_wire, iface); - if (arp->iface != NULL) { - len += strlen(arp->iface)+1; - } + ctdb_sock_addr_push(&in->addr, buf+offset, &np); + offset += np; - return len; -} + ctdb_uint32_push(&in->mask, buf+offset, &np); + offset += np; -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; + ctdb_stringn_push(&in->iface, buf+offset, &np); + offset += np; - wire->addr = addr_info->addr; - wire->mask = addr_info->mask; - if (addr_info->iface == NULL) { - wire->len = 0; - } else { - wire->len = strlen(addr_info->iface)+1; - memcpy(wire->iface, addr_info->iface, wire->len); - } + *npush = offset; } int ctdb_addr_info_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, - struct ctdb_addr_info **out) + struct ctdb_addr_info **out, size_t *npull) { - struct ctdb_addr_info *addr_info; - struct ctdb_addr_info_wire *wire = (struct ctdb_addr_info_wire *)buf; + struct ctdb_addr_info *val; + size_t offset = 0, np; + int ret; - 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; } - addr_info = talloc(mem_ctx, struct ctdb_addr_info); - if (addr_info == NULL) { - return ENOMEM; + ret = ctdb_sock_addr_pull_elems(buf+offset, buflen-offset, val, + &val->addr, &np); + if (ret != 0) { + goto fail; } + offset += np; - addr_info->addr = wire->addr; - addr_info->mask = wire->mask; + ret = ctdb_uint32_pull(buf+offset, buflen-offset, &val->mask, &np); + if (ret != 0) { + goto fail; + } + offset += np; - if (wire->len == 0) { - addr_info->iface = NULL; - } else { - addr_info->iface = talloc_strndup(addr_info, wire->iface, - wire->len); - if (addr_info->iface == NULL) { - talloc_free(addr_info); - return ENOMEM; - } + ret = ctdb_stringn_pull(buf+offset, buflen-offset, val, &val->iface, + &np); + if (ret != 0) { + goto fail; } + offset += np; - *out = addr_info; + *out = val; + *npull = offset; return 0; + +fail: + talloc_free(val); + return ret; } size_t ctdb_transdb_len(struct ctdb_transdb *transdb) diff --git a/ctdb/tests/src/protocol_types_compat_test.c b/ctdb/tests/src/protocol_types_compat_test.c index cb651e37fb3..040d1a57e57 100644 --- a/ctdb/tests/src/protocol_types_compat_test.c +++ b/ctdb/tests/src/protocol_types_compat_test.c @@ -1033,6 +1033,82 @@ static int ctdb_tickle_list_pull_old(uint8_t *buf, size_t buflen, 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; +} + COMPAT_TYPE3_TEST(struct ctdb_statistics, ctdb_statistics); COMPAT_TYPE3_TEST(struct ctdb_vnn_map, ctdb_vnn_map); @@ -1055,6 +1131,7 @@ 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); int main(int argc, char *argv[]) { @@ -1082,6 +1159,7 @@ int main(int argc, char *argv[]) COMPAT_TEST_FUNC(ctdb_var_list)(); COMPAT_TEST_FUNC(ctdb_tunable_list)(); COMPAT_TEST_FUNC(ctdb_tickle_list)(); + COMPAT_TEST_FUNC(ctdb_addr_info)(); return 0; } diff --git a/ctdb/tests/src/protocol_types_test.c b/ctdb/tests/src/protocol_types_test.c index e0468408a61..3db2722fde4 100644 --- a/ctdb/tests/src/protocol_types_test.c +++ b/ctdb/tests/src/protocol_types_test.c @@ -67,7 +67,7 @@ PROTOCOL_TYPE3_TEST(struct ctdb_node_flag_change, ctdb_node_flag_change); PROTOCOL_TYPE3_TEST(struct ctdb_var_list, ctdb_var_list); PROTOCOL_TYPE3_TEST(struct ctdb_tunable_list, ctdb_tunable_list); PROTOCOL_TYPE3_TEST(struct ctdb_tickle_list, ctdb_tickle_list); -DEFINE_TEST(struct ctdb_addr_info, ctdb_addr_info); +PROTOCOL_TYPE3_TEST(struct ctdb_addr_info, ctdb_addr_info); DEFINE_TEST(struct ctdb_transdb, ctdb_transdb); DEFINE_TEST(struct ctdb_uptime, ctdb_uptime); DEFINE_TEST(struct ctdb_public_ip, ctdb_public_ip); -- 2.34.1