X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Futils%2Fproto.c;h=13d91293d20a7c91da012c10e978c3295d8b4129;hb=05f5ac1f08dfe0d8f7216390a103ec58788c8ef9;hp=bf0d9dd0e8ba629cf01ac5aa1f4c26335063fc8a;hpb=9c130e1fb599c2e7fb3c6ba2cafbacaf3644effc;p=sysdb.git diff --git a/src/utils/proto.c b/src/utils/proto.c index bf0d9dd..13d9129 100644 --- a/src/utils/proto.c +++ b/src/utils/proto.c @@ -66,6 +66,16 @@ endian_swap64(uint64_t v) | (((v & 0x00000000000000ffLL) << 56) & 0xff00000000000000LL); } /* endian_swap64 */ +static unsigned char * +memdup(const unsigned char *d, size_t length) +{ + unsigned char *v = malloc(length); + if (! v) + return NULL; + memcpy(v, d, length); + return v; +} /* memdup */ + /* In case there's not enough buffer space, the marshal functions have to * return the number of bytes that would have been written if enough space had * been available. */ @@ -93,9 +103,9 @@ marshal_int64(char *buf, size_t buf_len, int64_t v) } /* marshal_int64 */ static ssize_t -unmarshal_int64(const char *buf, size_t buf_len, int64_t *v) +unmarshal_int64(const char *buf, size_t len, int64_t *v) { - if (buf_len < sizeof(*v)) + if (len < sizeof(*v)) return -1; if (v) { memcpy(v, buf, sizeof(*v)); @@ -163,7 +173,8 @@ marshal_binary(char *buf, size_t buf_len, size_t len, const unsigned char *v) } /* marshal_binary */ static ssize_t -unmarshal_binary(const char *buf, size_t len, size_t *v_len, unsigned char **v) +unmarshal_binary(const char *buf, size_t len, + size_t *v_len, const unsigned char **v) { uint32_t l; ssize_t n; @@ -176,12 +187,8 @@ unmarshal_binary(const char *buf, size_t len, size_t *v_len, unsigned char **v) if (v_len) *v_len = (size_t)l; - if (v && (l > 0)) { - *v = malloc((size_t)l); - if (! *v) - return -1; - memcpy(*v, buf, (size_t)l); - } + if (v && (l > 0)) + *v = (const unsigned char *)buf; else if (v) *v = NULL; return sizeof(l) + (ssize_t)l; @@ -198,21 +205,17 @@ marshal_string(char *buf, size_t buf_len, const char *v) } /* marshal_string */ static ssize_t -unmarshal_string(const char *buf, size_t len, char **v) +unmarshal_string(const char *buf, size_t len, const char **v) { size_t l = 0; for (l = 0; l < len; ++l) if (buf[l] == '\0') break; - if ((! len) || (buf[l] != '\0')) + if (l == len) return -1; - if (v) { - *v = malloc(l + 1); - if (! *v) - return -1; - memcpy(*v, buf, l + 1); - } + if (v) + *v = buf; return l + 1; } /* unmarshal_string */ @@ -232,6 +235,22 @@ marshal_obj_header(char *buf, size_t buf_len, return OBJ_HEADER_LEN; } /* marshal_obj_header */ +static ssize_t +unmarshal_obj_header(const char *buf, size_t len, + int *type, sdb_time_t *last_update) +{ + ssize_t n; + + if (len < OBJ_HEADER_LEN) + return -1; + + n = sdb_proto_unmarshal_int32(buf, len, (uint32_t *)type); + buf += n; len -= n; + if (unmarshal_datetime(buf, len, last_update) < 0) + return -1; + return OBJ_HEADER_LEN; +} /* unmarshal_obj_header */ + /* * public API */ @@ -443,14 +462,14 @@ sdb_proto_marshal_attribute(char *buf, size_t buf_len, size_t len; ssize_t n; - if ((! attr) || (! attr->parent) || (! attr->key) || (! attr->value) + if ((! attr) || (! attr->parent) || (! attr->key) || ((attr->parent_type != SDB_HOST) && (! attr->hostname)) || ((attr->parent_type != SDB_HOST) && (attr->parent_type != SDB_SERVICE) && (attr->parent_type != SDB_METRIC))) return -1; - n = sdb_proto_marshal_data(NULL, 0, attr->value); + n = sdb_proto_marshal_data(NULL, 0, &attr->value); if (n < 0) return -1; @@ -472,7 +491,7 @@ sdb_proto_marshal_attribute(char *buf, size_t buf_len, buf += n; buf_len -= n; n = marshal_string(buf, buf_len, attr->key); buf += n; buf_len -= n; - sdb_proto_marshal_data(buf, buf_len, attr->value); + sdb_proto_marshal_data(buf, buf_len, &attr->value); return len; } /* sdb_proto_marshal_attribute */ @@ -532,19 +551,28 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) n = unmarshal_int64(buf, len, D(integer)); else if (d.type == SDB_TYPE_DECIMAL) n = unmarshal_double(buf, len, D(decimal)); - else if (d.type == SDB_TYPE_STRING) - n = unmarshal_string(buf, len, D(string)); + else if (d.type == SDB_TYPE_STRING) { + const char *str = NULL; + n = unmarshal_string(buf, len, &str); + if ((n > 0) && datum) + if (! (d.data.string = strdup(str))) + n = -1; + } else if (d.type == SDB_TYPE_DATETIME) n = unmarshal_datetime(buf, len, D(datetime)); - else if (d.type == SDB_TYPE_BINARY) - n = unmarshal_binary(buf, len, D(binary.length), D(binary.datum)); + else if (d.type == SDB_TYPE_BINARY) { + const unsigned char *data = NULL; + n = unmarshal_binary(buf, len, D(binary.length), &data); + if ((n > 0) && datum) + if (! (d.data.binary.datum = memdup(data, d.data.binary.length))) + n = -1; + } else if (d.type == SDB_TYPE_REGEX) { if (datum) { - char *str = NULL; + const char *str = NULL; n = unmarshal_string(buf, len, &str); if (sdb_data_parse(str, SDB_TYPE_REGEX, &d)) n = -1; - free(str); } else n = unmarshal_string(buf, len, NULL); @@ -587,7 +615,11 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) } else if ((d.type & 0xff) == SDB_TYPE_STRING) { char **v = d.data.array.values; - n = unmarshal_string(buf, len, V()); + const char *str = NULL; + n = unmarshal_string(buf, len, &str); + if ((n > 0) && datum) + if (! (v[i] = strdup(str))) + n = -1; } else if ((d.type & 0xff) == SDB_TYPE_DATETIME) { sdb_time_t *v = d.data.array.values; @@ -598,7 +630,12 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) size_t length; unsigned char *datum; } *v = d.data.array.values; - n = unmarshal_binary(buf, len, V(.length), V(.datum)); + const unsigned char *data = NULL; + + n = unmarshal_binary(buf, len, V(.length), &data); + if ((n > 0) && datum) + if (! (v[i].datum = memdup(data, v[i].length))) + n = -1; } else if ((d.type & 0xff) == SDB_TYPE_REGEX) { struct { @@ -607,7 +644,7 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) } *v = d.data.array.values; if (datum) { sdb_data_t t = SDB_DATA_INIT; - char *str = NULL; + const char *str = NULL; n = unmarshal_string(buf, len, &str); if (! sdb_data_parse(str, SDB_TYPE_REGEX, &t)) { v[i].raw = t.data.re.raw; @@ -615,7 +652,6 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) } else n = -1; - free(str); } else n = unmarshal_string(buf, len, NULL); @@ -632,13 +668,7 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) sdb_data_free_datum(&d); return -1; } - if (len >= (size_t)n) { - buf += n; - len -= n; - l += n; - } - else - return -1; + buf += n; len -= n; l += n; } #undef V @@ -647,5 +677,120 @@ sdb_proto_unmarshal_data(const char *buf, size_t len, sdb_data_t *datum) return l; } /* sdb_proto_unmarshal_data */ +ssize_t +sdb_proto_unmarshal_host(const char *buf, size_t len, + sdb_proto_host_t *host) +{ + int type = 0; + ssize_t l = 0, n; + + if ((n = unmarshal_obj_header(buf, len, + &type, host ? &host->last_update : NULL)) < 0) + return n; + if (type != SDB_HOST) + return -1; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, host ? &host->name : NULL)) < 0) + return n; + return l + n; +} /* sdb_proto_unmarshal_host */ + +ssize_t +sdb_proto_unmarshal_service(const char *buf, size_t len, + sdb_proto_service_t *svc) +{ + int type = 0; + ssize_t l = 0, n; + + if ((n = unmarshal_obj_header(buf, len, + &type, svc ? &svc->last_update : NULL)) < 0) + return n; + if (type != SDB_SERVICE) + return -1; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, svc ? &svc->hostname : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, svc ? &svc->name : NULL)) < 0) + return n; + return l + n; +} /* sdb_proto_unmarshal_service */ + +ssize_t +sdb_proto_unmarshal_metric(const char *buf, size_t len, + sdb_proto_metric_t *metric) +{ + int type = 0; + ssize_t l = 0, n; + + if ((n = unmarshal_obj_header(buf, len, + &type, metric ? &metric->last_update : NULL)) < 0) + return n; + if (type != SDB_METRIC) + return -1; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, + metric ? &metric->hostname : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, metric ? &metric->name : NULL)) < 0) + return n; + if (len > (size_t)n) { + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, + metric ? &metric->store_type : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, + metric ? &metric->store_id : NULL)) < 0) + return n; + } + else if (metric) { + metric->store_type = NULL; + metric->store_id = NULL; + } + return l + n; +} /* sdb_proto_unmarshal_metric */ + +ssize_t +sdb_proto_unmarshal_attribute(const char *buf, size_t len, + sdb_proto_attribute_t *attr) +{ + int parent_type, type = 0; + ssize_t l = 0, n; + + if ((n = unmarshal_obj_header(buf, len, + &type, attr ? &attr->last_update : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + parent_type = type & 0xf; + if (type != (parent_type | SDB_ATTRIBUTE)) + return -1; + if ((parent_type != SDB_HOST) && (parent_type != SDB_SERVICE) + && (parent_type != SDB_METRIC)) + return -1; + if (attr) + attr->parent_type = parent_type; + + if (parent_type != SDB_HOST) { + if ((n = unmarshal_string(buf, len, + attr ? &attr->hostname : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + } + else if (attr) + attr->hostname = NULL; + if ((n = unmarshal_string(buf, len, attr ? &attr->parent : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + if ((n = unmarshal_string(buf, len, attr ? &attr->key : NULL)) < 0) + return n; + buf += n; len -= n; l += n; + if ((n = sdb_proto_unmarshal_data(buf, len, + attr ? &attr->value : NULL)) < 0) + return n; + return l + n; +} /* sdb_proto_unmarshal_attribute */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */