ctdb-protocol: Fix marshalling for ctdb_srvid_message
[vlendec/samba-autobuild/.git] / ctdb / protocol / protocol_call.c
index 441bf6048a2466d2277d7584465263c8414dfe1b..111cdf25de0aee348dae442d751942123ea04787 100644 (file)
@@ -74,36 +74,38 @@ struct ctdb_reply_dmaster_wire {
 size_t ctdb_req_call_len(struct ctdb_req_header *h, struct ctdb_req_call *c)
 {
        return offsetof(struct ctdb_req_call_wire, data) +
-               ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->calldata);
+               ctdb_tdb_data_len(&c->key) +
+               ctdb_tdb_data_len(&c->calldata);
 }
 
 int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c,
-                      uint8_t *buf, size_t buflen)
+                      uint8_t *buf, size_t *buflen)
 {
        struct ctdb_req_call_wire *wire =
                (struct ctdb_req_call_wire *)buf;
-       size_t length;
+       size_t length, np;
 
        if (c->key.dsize == 0) {
                return EINVAL;
        }
 
        length = ctdb_req_call_len(h, c);
-       if (buflen < length) {
+       if (*buflen < length) {
+               *buflen = length;
                return EMSGSIZE;
        }
 
-       h->length = buflen;
+       h->length = *buflen;
        ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
 
        wire->flags = c->flags;
        wire->db_id = c->db_id;
        wire->callid = c->callid;
        wire->hopcount = c->hopcount;
-       wire->keylen = ctdb_tdb_data_len(c->key);
-       wire->calldatalen = ctdb_tdb_data_len(c->calldata);
-       ctdb_tdb_data_push(c->key, wire->data);
-       ctdb_tdb_data_push(c->calldata, wire->data + wire->keylen);
+       wire->keylen = ctdb_tdb_data_len(&c->key);
+       wire->calldatalen = ctdb_tdb_data_len(&c->calldata);
+       ctdb_tdb_data_push(&c->key, wire->data, &np);
+       ctdb_tdb_data_push(&c->calldata, wire->data + wire->keylen, &np);
 
        return 0;
 }
@@ -115,13 +117,22 @@ int ctdb_req_call_pull(uint8_t *buf, size_t buflen,
 {
        struct ctdb_req_call_wire *wire =
                (struct ctdb_req_call_wire *)buf;
-       size_t length;
+       size_t length, np;
        int ret;
 
        length = offsetof(struct ctdb_req_call_wire, data);
        if (buflen < length) {
                return EMSGSIZE;
        }
+       if (wire->keylen > buflen || wire->calldatalen > buflen) {
+               return EMSGSIZE;
+       }
+       if (length + wire->keylen < length) {
+               return EMSGSIZE;
+       }
+       if (length + wire->keylen + wire->calldatalen < length) {
+               return EMSGSIZE;
+       }
        if (buflen < length + wire->keylen + wire->calldatalen) {
                return EMSGSIZE;
        }
@@ -138,13 +149,14 @@ int ctdb_req_call_pull(uint8_t *buf, size_t buflen,
        c->callid = wire->callid;
        c->hopcount = wire->hopcount;
 
-       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key);
+       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
+                                &np);
        if (ret != 0) {
                return ret;
        }
 
        ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->calldatalen,
-                                mem_ctx, &c->calldata);
+                                mem_ctx, &c->calldata, &np);
        if (ret != 0) {
                return ret;
        }
@@ -156,27 +168,28 @@ size_t ctdb_reply_call_len(struct ctdb_req_header *h,
                           struct ctdb_reply_call *c)
 {
        return offsetof(struct ctdb_reply_call_wire, data) +
-               ctdb_tdb_data_len(c->data);
+               ctdb_tdb_data_len(&c->data);
 }
 
 int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c,
-                        uint8_t *buf, size_t buflen)
+                        uint8_t *buf, size_t *buflen)
 {
        struct ctdb_reply_call_wire *wire =
                (struct ctdb_reply_call_wire *)buf;
-       size_t length;
+       size_t length, np;
 
        length = ctdb_reply_call_len(h, c);
-       if (buflen < length) {
+       if (*buflen < length) {
+               *buflen = length;
                return EMSGSIZE;
        }
 
-       h->length = buflen;
+       h->length = *buflen;
        ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
 
        wire->status = c->status;
-       wire->datalen = ctdb_tdb_data_len(c->data);
-       ctdb_tdb_data_push(c->data, wire->data);
+       wire->datalen = ctdb_tdb_data_len(&c->data);
+       ctdb_tdb_data_push(&c->data, wire->data, &np);
 
        return 0;
 }
@@ -188,13 +201,19 @@ int ctdb_reply_call_pull(uint8_t *buf, size_t buflen,
 {
        struct ctdb_reply_call_wire *wire =
                (struct ctdb_reply_call_wire *)buf;
-       size_t length;
+       size_t length, np;
        int ret;
 
        length = offsetof(struct ctdb_reply_call_wire, data);
        if (buflen < length) {
                return EMSGSIZE;
        }
+       if (wire->datalen > buflen) {
+               return EMSGSIZE;
+       }
+       if (length + wire->datalen < length) {
+               return EMSGSIZE;
+       }
        if (buflen < length + wire->datalen) {
                return EMSGSIZE;
        }
@@ -208,7 +227,8 @@ int ctdb_reply_call_pull(uint8_t *buf, size_t buflen,
 
        c->status = wire->status;
 
-       ret = ctdb_tdb_data_pull(wire->data, wire->datalen, mem_ctx, &c->data);
+       ret = ctdb_tdb_data_pull(wire->data, wire->datalen, mem_ctx, &c->data,
+                                &np);
        if (ret != 0) {
                return ret;
        }
@@ -220,27 +240,28 @@ size_t ctdb_reply_error_len(struct ctdb_req_header *h,
                            struct ctdb_reply_error *c)
 {
        return offsetof(struct ctdb_reply_error_wire, msg) +
-               ctdb_tdb_data_len(c->msg);
+               ctdb_tdb_data_len(&c->msg);
 }
 
 int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c,
-                         uint8_t *buf, size_t buflen)
+                         uint8_t *buf, size_t *buflen)
 {
        struct ctdb_reply_error_wire *wire =
                (struct ctdb_reply_error_wire *)buf;
-       size_t length;
+       size_t length, np;
 
        length = ctdb_reply_error_len(h, c);
-       if (buflen < length) {
+       if (*buflen < length) {
+               *buflen = length;
                return EMSGSIZE;
        }
 
-       h->length = buflen;
+       h->length = *buflen;
        ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
 
        wire->status = c->status;
-       wire->msglen = ctdb_tdb_data_len(c->msg);
-       ctdb_tdb_data_push(c->msg, wire->msg);
+       wire->msglen = ctdb_tdb_data_len(&c->msg);
+       ctdb_tdb_data_push(&c->msg, wire->msg, &np);
 
        return 0;
 }
@@ -252,13 +273,19 @@ int ctdb_reply_error_pull(uint8_t *buf, size_t buflen,
 {
        struct ctdb_reply_error_wire *wire =
                (struct ctdb_reply_error_wire *)buf;
-       size_t length;
+       size_t length, np;
        int ret;
 
        length = offsetof(struct ctdb_reply_error_wire, msg);
        if (buflen < length) {
                return EMSGSIZE;
        }
+       if (wire->msglen > buflen) {
+               return EMSGSIZE;
+       }
+       if (length + wire->msglen < length) {
+               return EMSGSIZE;
+       }
        if (buflen < length + wire->msglen) {
                return EMSGSIZE;
        }
@@ -272,7 +299,8 @@ int ctdb_reply_error_pull(uint8_t *buf, size_t buflen,
 
        c->status = wire->status;
 
-       ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg);
+       ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg,
+                                &np);
        if (ret != 0) {
                return ret;
        }
@@ -284,31 +312,33 @@ size_t ctdb_req_dmaster_len(struct ctdb_req_header *h,
                            struct ctdb_req_dmaster *c)
 {
        return offsetof(struct ctdb_req_dmaster_wire, data) +
-               ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->data);
+               ctdb_tdb_data_len(&c->key) +
+               ctdb_tdb_data_len(&c->data);
 }
 
 int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c,
-                         uint8_t *buf, size_t buflen)
+                         uint8_t *buf, size_t *buflen)
 {
        struct ctdb_req_dmaster_wire *wire =
                (struct ctdb_req_dmaster_wire *)buf;
-       size_t length;
+       size_t length, np;
 
        length = ctdb_req_dmaster_len(h, c);
-       if (buflen < length) {
+       if (*buflen < length) {
+               *buflen = length;
                return EMSGSIZE;
        }
 
-       h->length = buflen;
+       h->length = *buflen;
        ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
 
        wire->db_id = c->db_id;
        wire->rsn = c->rsn;
        wire->dmaster = c->dmaster;
-       wire->keylen = ctdb_tdb_data_len(c->key);
-       wire->datalen = ctdb_tdb_data_len(c->data);
-       ctdb_tdb_data_push(c->key, wire->data);
-       ctdb_tdb_data_push(c->data, wire->data + wire->keylen);
+       wire->keylen = ctdb_tdb_data_len(&c->key);
+       wire->datalen = ctdb_tdb_data_len(&c->data);
+       ctdb_tdb_data_push(&c->key, wire->data, &np);
+       ctdb_tdb_data_push(&c->data, wire->data + wire->keylen, &np);
 
        return 0;
 }
@@ -320,13 +350,22 @@ int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen,
 {
        struct ctdb_req_dmaster_wire *wire =
                (struct ctdb_req_dmaster_wire *)buf;
-       size_t length;
+       size_t length, np;
        int ret;
 
        length = offsetof(struct ctdb_req_dmaster_wire, data);
        if (buflen < length) {
                return EMSGSIZE;
        }
+       if (wire->keylen > buflen || wire->datalen > buflen) {
+               return EMSGSIZE;
+       }
+       if (length + wire->keylen < length) {
+               return EMSGSIZE;
+       }
+       if (length + wire->keylen + wire->datalen < length) {
+               return EMSGSIZE;
+       }
        if (buflen < length + wire->keylen + wire->datalen) {
                return EMSGSIZE;
        }
@@ -342,13 +381,14 @@ int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen,
        c->rsn = wire->rsn;
        c->dmaster = wire->dmaster;
 
-       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key);
+       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
+                                &np);
        if (ret != 0) {
                return ret;
        }
 
        ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
-                                mem_ctx, &c->data);
+                                mem_ctx, &c->data, &np);
        if (ret != 0) {
                return ret;
        }
@@ -360,31 +400,33 @@ size_t ctdb_reply_dmaster_len(struct ctdb_req_header *h,
                              struct ctdb_reply_dmaster *c)
 {
        return offsetof(struct ctdb_reply_dmaster_wire, data) +
-               ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->data);
+               ctdb_tdb_data_len(&c->key) +
+               ctdb_tdb_data_len(&c->data);
 }
 
 int ctdb_reply_dmaster_push(struct ctdb_req_header *h,
                            struct ctdb_reply_dmaster *c,
-                           uint8_t *buf, size_t buflen)
+                           uint8_t *buf, size_t *buflen)
 {
        struct ctdb_reply_dmaster_wire *wire =
                (struct ctdb_reply_dmaster_wire *)buf;
-       size_t length;
+       size_t length, np;
 
        length = ctdb_reply_dmaster_len(h, c);
-       if (buflen < length) {
+       if (*buflen < length) {
+               *buflen = length;
                return EMSGSIZE;
        }
 
-       h->length = buflen;
+       h->length = *buflen;
        ctdb_req_header_push(h, (uint8_t *)&wire->hdr);
 
        wire->db_id = c->db_id;
        wire->rsn = c->rsn;
-       wire->keylen = ctdb_tdb_data_len(c->key);
-       wire->datalen = ctdb_tdb_data_len(c->data);
-       ctdb_tdb_data_push(c->key, wire->data);
-       ctdb_tdb_data_push(c->data, wire->data + wire->keylen);
+       wire->keylen = ctdb_tdb_data_len(&c->key);
+       wire->datalen = ctdb_tdb_data_len(&c->data);
+       ctdb_tdb_data_push(&c->key, wire->data, &np);
+       ctdb_tdb_data_push(&c->data, wire->data + wire->keylen, &np);
 
        return 0;
 }
@@ -396,13 +438,22 @@ int ctdb_reply_dmaster_pull(uint8_t *buf, size_t buflen,
 {
        struct ctdb_reply_dmaster_wire *wire =
                (struct ctdb_reply_dmaster_wire *)buf;
-       size_t length;
+       size_t length, np;
        int ret;
 
        length = offsetof(struct ctdb_reply_dmaster_wire, data);
        if (buflen < length) {
                return EMSGSIZE;
        }
+       if (wire->keylen > buflen || wire->datalen > buflen) {
+               return EMSGSIZE;
+       }
+       if (length + wire->keylen < length) {
+               return EMSGSIZE;
+       }
+       if (length + wire->keylen + wire->datalen < length) {
+               return EMSGSIZE;
+       }
        if (buflen < length + wire->keylen + wire->datalen) {
                return EMSGSIZE;
        }
@@ -417,13 +468,14 @@ int ctdb_reply_dmaster_pull(uint8_t *buf, size_t buflen,
        c->db_id = wire->db_id;
        c->rsn = wire->rsn;
 
-       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key);
+       ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key,
+                                &np);
        if (ret != 0) {
                return ret;
        }
 
        ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen,
-                                mem_ctx, &c->data);
+                                mem_ctx, &c->data, &np);
        if (ret != 0) {
                return ret;
        }