diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c index 0ac9285a2c65daf01cb8184aa802ed4a1e4c1a5b..00e93783d2716bb34fc23baaae06fe7acbc1e2b2 100644 --- a/src/knot/ctl/remote.c +++ b/src/knot/ctl/remote.c @@ -797,24 +797,26 @@ int remote_create_txt(knot_rrset_t *rr, const char *v, size_t v_len) /* Number of chunks. */ const size_t K = 255; unsigned chunks = v_len / K + 1; - uint8_t *raw = knot_rrset_create_rr(rr, v_len + chunks, 0, NULL); + uint8_t raw[v_len + chunks]; + memset(raw, 0, v_len + chunks); /* Write TXT item. */ unsigned p = 0; + size_t off = 0; if (v_len > K) { for (; p + K < v_len; p += K) { - *(raw++) = (uint8_t)K; - memcpy(raw, v+p, K); - raw += K; + raw[off++] = (uint8_t)K; + memcpy(raw + off, v + p, K); + off += K; } } unsigned r = v_len - p; if (r > 0) { - *(raw++) = (uint8_t)r; - memcpy(raw, v+p, r); + raw[off++] = (uint8_t)r; + memcpy(raw + off, v + p, r); } - return KNOT_EOK; + return knot_rrset_add_rr(rr, raw, v_len + chunks, 0, NULL); } int remote_create_ns(knot_rrset_t *rr, const char *d) diff --git a/src/knot/dnssec/nsec-chain.c b/src/knot/dnssec/nsec-chain.c index 46cdd87fc0bafd14e073558fb22c15629e50aaa7..0634abce09de5a4db1b64894f1579865a91d9bfd 100644 --- a/src/knot/dnssec/nsec-chain.c +++ b/src/knot/dnssec/nsec-chain.c @@ -64,16 +64,18 @@ static knot_rrset_t *create_nsec_rrset(const knot_node_t *from, assert(to->owner); size_t next_owner_size = knot_dname_size(to->owner); size_t rdata_size = next_owner_size + bitmap_size(&rr_types); - uint8_t *rdata = knot_rrset_create_rr(rrset, rdata_size, ttl, NULL); - if (!rdata) { - knot_rrset_free(&rrset, NULL); - return NULL; - } + uint8_t rdata[rdata_size]; // Fill RDATA memcpy(rdata, to->owner, next_owner_size); bitmap_write(&rr_types, rdata + next_owner_size); + int ret = knot_rrset_add_rr(rrset, rdata, rdata_size, ttl, NULL); + if (ret != KNOT_EOK) { + knot_rrset_free(&rrset, NULL); + return NULL; + } + return rrset; } diff --git a/src/knot/dnssec/nsec3-chain.c b/src/knot/dnssec/nsec3-chain.c index 789bf79028a077c987c28d38601f906b3433fb59..d5ea8f18b69ba81d43f3d2e462cab8aa0680dd39 100644 --- a/src/knot/dnssec/nsec3-chain.c +++ b/src/knot/dnssec/nsec3-chain.c @@ -57,7 +57,7 @@ inline static bool valid_nsec3_node(const knot_node_t *node) return false; } - if (knot_rrs_rr_count(nsec3) != 1) { + if (nsec3->rr_count != 1) { return false; } @@ -262,15 +262,10 @@ static int create_nsec3_rrset(knot_rrset_t *rrset, knot_rrset_init(rrset, owner, KNOT_RRTYPE_NSEC3, KNOT_CLASS_IN); size_t rdata_size = nsec3_rdata_size(params, rr_types); - uint8_t *rdata = knot_rrset_create_rr(rrset, rdata_size, ttl, NULL); - if (!rdata) { - knot_rrset_clear(rrset, NULL); - return KNOT_ENOMEM; - } - + uint8_t rdata[rdata_size]; nsec3_fill_rdata(rdata, params, rr_types, next_hashed, ttl); - return KNOT_EOK; + return knot_rrset_add_rr(rrset, rdata, rdata_size, ttl, NULL); } /*! diff --git a/src/knot/nameserver/chaos.c b/src/knot/nameserver/chaos.c index a550069bff38a187328be681a7bb392e3e00b908..0a3cd2b526e1025e55dfe5b760086aed4ce77cb9 100644 --- a/src/knot/nameserver/chaos.c +++ b/src/knot/nameserver/chaos.c @@ -69,16 +69,17 @@ static int create_txt_rrset(knot_rrset_t *rrset, const knot_dname_t *owner, } knot_rrset_init(rrset, rowner, KNOT_RRTYPE_TXT, KNOT_CLASS_CH); - uint8_t *rdata = knot_rrset_create_rr(rrset, response_len + 1, 0, mm); - if (!rdata) { - knot_dname_free(&rrset->owner, mm); - knot_rrs_clear(&rrset->rrs, mm); - return KNOT_ENOMEM; - } + uint8_t rdata[response_len + 1]; rdata[0] = response_len; memcpy(&rdata[1], response, response_len); + int ret = knot_rrset_add_rr(rrset, rdata, response_len + 1, 0, mm); + if (ret != KNOT_EOK) { + knot_dname_free(&rrset->owner, mm); + return ret; + } + return KNOT_EOK; } diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c index 1af5da97b79f8bb7e9a264cd96ae8d56c0ff9b21..157f7e2f4597c9f0938a73cec169180555a5ee6d 100644 --- a/src/knot/nameserver/internet.c +++ b/src/knot/nameserver/internet.c @@ -81,17 +81,12 @@ static int dname_cname_synth(const knot_rrset_t *dname_rr, /* Store DNAME into RDATA. */ int cname_size = knot_dname_size(cname); - uint8_t *cname_rdata = knot_rrset_create_rr(cname_rrset, cname_size, - knot_rrset_rr_ttl(dname_rr, 0), - mm); - if (cname_rdata == NULL) { - knot_dname_free(&cname, NULL); - return KNOT_ENOMEM; - } + uint8_t cname_rdata[cname_size]; memcpy(cname_rdata, cname, cname_size); knot_dname_free(&cname, NULL); - return KNOT_EOK; + return knot_rrset_add_rr(cname_rrset, cname_rdata, cname_size, + knot_rrset_rr_ttl(dname_rr, 0), mm); } /*! diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index 83b17264df5bdcd61a234566fcaede87f0adebff..dcf3348a006436b6cd2dc352d7915df42c27bedf 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -685,7 +685,7 @@ static int process_rem_rr(const knot_rrset_t *rr, type == KNOT_RRTYPE_NS; if (apex_ns) { const knot_rrs_t *ns_rrs = knot_node_rrs(node, KNOT_RRTYPE_NS); - if (*apex_ns_rem == knot_rrs_rr_count(ns_rrs) - 1) { + if (*apex_ns_rem == ns_rrs->rr_count - 1) { // Cannot remove last apex NS RR return KNOT_EOK; } diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c index fd669c3ac94aface78e1e76a70ce053d0b59ccdf..ca91dbcfa669076fc03c7d1b71d4f972b16e0414 100644 --- a/src/knot/zone/node.c +++ b/src/knot/zone/node.c @@ -656,7 +656,7 @@ bool knot_node_rrtype_is_signed(const knot_node_t *node, uint16_t type) return false; } - uint16_t rrsigs_rdata_count = knot_rrs_rr_count(rrsigs); + uint16_t rrsigs_rdata_count = rrsigs->rr_count; for (uint16_t i = 0; i < rrsigs_rdata_count; ++i) { const uint16_t type_covered = knot_rrs_rrsig_type_covered(rrsigs, i); diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index 79a6c847283865817e41bcf301cd7959091af2e8..7ecad72b89c2f9dbea5bdfd57a846266c19c7d2c 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -511,7 +511,7 @@ static int check_rrsig_in_rrset(err_handler_t *handler, info_str); } - for (uint16_t i = 0; i < knot_rrs_rr_count(&rrsigs); ++i) { + for (uint16_t i = 0; i < (&rrsigs)->rr_count; ++i) { int ret = check_rrsig_rdata(handler, node, &rrsigs, i, rrset, dnskey_rrset); if (ret != KNOT_EOK) { @@ -772,7 +772,7 @@ static int sem_check_node_mandatory(const knot_node_t *node, } } - if (knot_rrs_rr_count(cname_rrs) != 1) { + if (cname_rrs->rr_count != 1) { *fatal_error = true; err_handler_handle_error(handler, node, ZC_ERR_CNAME_MULTIPLE, NULL); @@ -822,7 +822,7 @@ static int sem_check_node_optional(const knot_zone_contents_t *zone, return KNOT_EOK; } - for (int i = 0; i < knot_rrs_rr_count(ns_rrs); ++i) { + for (int i = 0; i < ns_rrs->rr_count; ++i) { const knot_dname_t *ns_dname = knot_rrs_ns_name(ns_rrs, i); const knot_node_t *glue_node = @@ -982,7 +982,7 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone, } free(array); /* Test that only one record is in the NSEC RRSet */ - if (knot_rrs_rr_count(nsec_rrs) != 1) { + if (nsec_rrs->rr_count != 1) { err_handler_handle_error(handler, node, ZC_ERR_NSEC_RDATA_MULTIPLE, diff --git a/src/libknot/dnssec/rrset-sign.c b/src/libknot/dnssec/rrset-sign.c index 4163009ec27683b4523e942c179da81817885cee..8c0ecc244c1a94ceeb081059c497fec21410b583 100644 --- a/src/libknot/dnssec/rrset-sign.c +++ b/src/libknot/dnssec/rrset-sign.c @@ -100,62 +100,6 @@ int knot_rrsig_write_rdata(uint8_t *rdata, const knot_dnssec_key_t *key, return KNOT_EOK; } -/*- Creating of RRSIGs from covered RRs -------------------------------------*/ - -/*! - * \brief Create RRSIG RDATA (all fields except signature are filled). - * - * \param[in] rrsigs RR set with RRSIGS. - * \param[in] covered RR covered by the signature. - * \param[in] key Key used for signing. - * \param[in] sig_incepted Timestamp of signature inception. - * \param[in] sig_expires Timestamp of signature expiration. - * \param[out] rdata Created RDATA. - * \param[out] rdata_size Size of created RDATA. - * - * \return Error code, KNOT_EOK if succesful. - */ -static int rrsigs_create_rdata(knot_rrset_t *rrsigs, - const knot_rrset_t *covered, - const knot_dnssec_key_t *key, - uint32_t sig_incepted, uint32_t sig_expires, - uint8_t **rdata, size_t *rdata_size) -{ - assert(rrsigs); - assert(rrsigs->type == KNOT_RRTYPE_RRSIG); - assert(!knot_rrset_empty(covered)); - assert(key); - assert(rdata); - assert(rdata_size); - - size_t size = knot_rrsig_rdata_size(key); - assert(size != 0); - - uint8_t *result = knot_rrset_create_rr(rrsigs, size, - knot_rrset_rr_ttl(covered, 0), - NULL); - if (!result) { - return KNOT_ENOMEM; - } - - uint8_t owner_labels = knot_dname_labels(covered->owner, NULL); - if (knot_dname_is_wildcard(covered->owner)) { - owner_labels -= 1; - } - - int res = knot_rrsig_write_rdata(result, key, covered->type, owner_labels, - knot_rrset_rr_ttl(covered, 0), - sig_incepted, sig_expires); - - assert(res == KNOT_EOK); - UNUSED(res); - - *rdata = result; - *rdata_size = size; - - return KNOT_EOK; -} - /*- Computation of signatures ------------------------------------------------*/ /*! @@ -242,6 +186,67 @@ static int sign_ctx_add_data(knot_dnssec_sign_context_t *ctx, return sign_ctx_add_records(ctx, covered); } +/*! + * \brief Create RRSIG RDATA (all fields except signature are filled). + * + * \param[in] rrsigs RR set with RRSIGS. + * \param[in] rrsigs DNSSEC signing context. + * \param[in] covered RR covered by the signature. + * \param[in] key Key used for signing. + * \param[in] sig_incepted Timestamp of signature inception. + * \param[in] sig_expires Timestamp of signature expiration. + * + * \return Error code, KNOT_EOK if succesful. + */ +static int rrsigs_create_rdata(knot_rrset_t *rrsigs, + knot_dnssec_sign_context_t *context, + const knot_rrset_t *covered, + const knot_dnssec_key_t *key, + uint32_t sig_incepted, uint32_t sig_expires) +{ + assert(rrsigs); + assert(rrsigs->type == KNOT_RRTYPE_RRSIG); + assert(!knot_rrset_empty(covered)); + assert(key); + + size_t size = knot_rrsig_rdata_size(key); + assert(size != 0); + + uint8_t owner_labels = knot_dname_labels(covered->owner, NULL); + if (knot_dname_is_wildcard(covered->owner)) { + owner_labels -= 1; + } + + uint8_t result[size]; + int res = knot_rrsig_write_rdata(result, key, covered->type, owner_labels, + knot_rrset_rr_ttl(covered, 0), + sig_incepted, sig_expires); + assert(res == KNOT_EOK); + + res = knot_dnssec_sign_new(context); + if (res != KNOT_EOK) { + return res; + } + + res = sign_ctx_add_data(context, result, covered); + if (res != KNOT_EOK) { + return res; + } + + const size_t signature_offset = RRSIG_RDATA_SIGNER_OFFSET + knot_dname_size(key->name); + uint8_t *signature = result + signature_offset; + const size_t signature_size = size - signature_offset; + + res = knot_dnssec_sign_write(context, signature, signature_size); + if (res != KNOT_EOK) { + return res; + } + + + return knot_rrset_add_rr(rrsigs, result, size, + knot_rrset_rr_ttl(covered, 0), NULL); +} + /*! * \brief Create RRSIG RR for given RR set. */ @@ -260,30 +265,8 @@ int knot_sign_rrset(knot_rrset_t *rrsigs, const knot_rrset_t *covered, uint32_t sig_incept = policy->now; uint32_t sig_expire = sig_incept + policy->sign_lifetime; - uint8_t *rdata = NULL; - size_t rdata_size = 0; - - int result = rrsigs_create_rdata(rrsigs, covered, key, sig_incept, - sig_expire, &rdata, &rdata_size); - if (result != KNOT_EOK) { - return result; - } - - result = knot_dnssec_sign_new(sign_ctx); - if (result != KNOT_EOK) { - return result; - } - - result = sign_ctx_add_data(sign_ctx, rdata, covered); - if (result != KNOT_EOK) { - return result; - } - - size_t signature_offset = RRSIG_RDATA_SIGNER_OFFSET + knot_dname_size(key->name); - uint8_t *signature = rdata + signature_offset; - size_t signature_size = rdata_size - signature_offset; - - return knot_dnssec_sign_write(sign_ctx, signature, signature_size); + return rrsigs_create_rdata(rrsigs, sign_ctx, covered, key, sig_incept, + sig_expire); } /*- Verification of signatures -----------------------------------------------*/ diff --git a/src/libknot/dnssec/sig0.c b/src/libknot/dnssec/sig0.c index ff4de0d1dc150dfe77bda3b1479eecb60ee6514f..03b43ced8b9a511eab2730b32cf6042e63949c11 100644 --- a/src/libknot/dnssec/sig0.c +++ b/src/libknot/dnssec/sig0.c @@ -71,15 +71,14 @@ static uint8_t *sig0_create_rdata(knot_rrset_t *rrset, knot_dnssec_key_t *key) assert(key); size_t rdata_size = knot_rrsig_rdata_size(key); - uint32_t ttl = 0; - uint8_t *rdata = knot_rrset_create_rr(rrset, rdata_size, ttl, NULL); - if (!rdata) { + const uint32_t ttl = 0; + uint8_t rdata[rdata_size]; + sig0_write_rdata(rdata, key); + if (knot_rrset_add_rr(rrset, rdata, rdata_size, ttl, NULL) != KNOT_EOK) { return NULL; } - sig0_write_rdata(rdata, key); - - return rdata; + return knot_rrset_rr_rdata(rrset, 0); } /*! diff --git a/src/libknot/rr.c b/src/libknot/rr.c index aa2f7f3d1e372445e2fcbe7600f7a7a0ccdfdbfa..962e47b74c3da3bcfc84fa17c1ddcb47dcc4b122 100644 --- a/src/libknot/rr.c +++ b/src/libknot/rr.c @@ -7,38 +7,9 @@ #include "libknot/common.h" #include "common/errcode.h" +/*!< \brief RR metadata size. */ static const size_t RR_META_SIZE = sizeof(uint16_t) + sizeof(uint32_t); -uint16_t knot_rr_size(const knot_rr_t *rr) -{ - return *((uint16_t *)rr); -} - -uint32_t knot_rr_ttl(const knot_rr_t *rr) -{ - return *((uint32_t *)(rr + sizeof(uint16_t))); -} - -const uint8_t *knot_rr_rdata(const knot_rr_t *rr) -{ - return (const uint8_t *)(rr + RR_META_SIZE); -} - -uint8_t *knot_rr_get_rdata(knot_rr_t *rr) -{ - return rr + RR_META_SIZE; -} - -void knot_rr_set_size(knot_rr_t *rr, uint16_t size) -{ - *((uint16_t *)rr) = size; -} - -void knot_rr_set_ttl(knot_rr_t *rr, uint32_t ttl) -{ - *((uint32_t *)(rr + sizeof(uint16_t))) = ttl; -} - static knot_rr_t *rr_seek(knot_rr_t *d, size_t pos) { if (d == NULL) { @@ -54,25 +25,7 @@ static knot_rr_t *rr_seek(knot_rr_t *d, size_t pos) return d + offset; } -knot_rr_t *knot_rrs_get_rr(const knot_rrs_t *rrs, size_t pos) -{ - if (rrs == NULL || pos >= rrs->rr_count) { - return NULL; - } - - return rr_seek(rrs->data, pos); -} - -const knot_rr_t *knot_rrs_rr(const knot_rrs_t *rrs, size_t pos) -{ - if (rrs == NULL || pos >= rrs->rr_count) { - return NULL; - } - - return (const knot_rr_t *)rr_seek(rrs->data, pos); -} - -size_t knot_rrs_size(const knot_rrs_t *rrs) +static size_t knot_rrs_size(const knot_rrs_t *rrs) { if (rrs == NULL) { return 0; @@ -88,99 +41,13 @@ size_t knot_rrs_size(const knot_rrs_t *rrs) return total_size; } -uint16_t knot_rrs_rr_count(const knot_rrs_t *rrs) -{ - if (rrs == NULL) { - return 0; - } - - return rrs->rr_count; -} - -int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm) -{ - if (rrs == NULL || pos >= rrs->rr_count) { - return KNOT_EINVAL; - } - - knot_rr_t *old_rr = knot_rrs_get_rr(rrs, pos); - knot_rr_t *last_rr = knot_rrs_get_rr(rrs, rrs->rr_count - 1); - assert(old_rr); - assert(last_rr); - - size_t total_size = knot_rrs_size(rrs); - uint16_t old_size = knot_rr_size(old_rr); - - void *old_threshold = old_rr + old_size + RR_META_SIZE; - void *last_threshold = last_rr + knot_rr_size(last_rr) + RR_META_SIZE; - // Move RDATA - memmove(old_rr, old_threshold, - last_threshold - old_threshold); - - if (rrs->rr_count > 1) { - // Realloc RDATA - void *tmp = mm_realloc(mm, rrs->data, - total_size - (old_size + RR_META_SIZE), - total_size); - if (tmp == NULL) { - ERR_ALLOC_FAILED; - return KNOT_ENOMEM; - } else { - rrs->data = tmp; - } - } else { - // Free RDATA - mm_free(mm, rrs->data); - rrs->data = NULL; - } - rrs->rr_count--; - - return KNOT_EOK; -} - -const uint8_t *knot_rrs_rr_rdata(const knot_rrs_t *rrs, size_t pos) -{ - if (rrs == NULL || pos >= rrs->rr_count) { - return NULL; - } - - return knot_rr_rdata(knot_rrs_rr(rrs, pos)); -} - -uint8_t *knot_rrs_rr_get_rdata(const knot_rrs_t *rrs, size_t pos) -{ - return (uint8_t *)knot_rrs_rr_rdata(rrs, pos); -} - -uint16_t knot_rrs_rr_size(const knot_rrs_t *rrs, size_t pos) -{ - if (rrs == NULL || pos >= rrs->rr_count) { - return 0; - } - - return knot_rr_size(knot_rrs_rr(rrs, pos)); -} - -uint32_t knot_rrs_rr_ttl(const knot_rrs_t *rrs, size_t pos) -{ - if (rrs == NULL || pos >= rrs->rr_count) { - return 0; - } - - return knot_rr_ttl(knot_rrs_rr(rrs, pos)); -} - -uint8_t* knot_rrs_create_rr_at_pos(knot_rrs_t *rrs, - size_t pos, uint16_t size, - uint32_t ttl, mm_ctx_t *mm) +static uint8_t* knot_rrs_create_rr_at_pos(knot_rrs_t *rrs, + size_t pos, uint16_t size, + uint32_t ttl, mm_ctx_t *mm) { if (rrs == NULL || pos > rrs->rr_count) { return NULL; } - if (pos == rrs->rr_count) { - // Normal RDATA addition - return knot_rrs_create_rr(rrs, size, ttl, mm); - } size_t total_size = knot_rrs_size(rrs); @@ -195,10 +62,29 @@ uint8_t* knot_rrs_create_rr_at_pos(knot_rrs_t *rrs, return NULL; } - knot_rr_t *old_rr = knot_rrs_get_rr(rrs, pos); + // Solve corner cases: first RR + if (rrs->rr_count == 0) { + rrs->rr_count++; + assert(pos == 0); + knot_rr_t *new_rr = knot_rrs_get_rr(rrs, pos); + knot_rr_set_size(new_rr, size); + knot_rr_set_ttl(new_rr, ttl); + return knot_rr_get_rdata(new_rr); + } + knot_rr_t *last_rr = knot_rrs_get_rr(rrs, rrs->rr_count - 1); - assert(old_rr); assert(last_rr); + // Last RR + if (pos == rrs->rr_count) { + rrs->rr_count++; + knot_rr_t *new_rr = knot_rrs_get_rr(rrs, pos); + knot_rr_set_size(new_rr, size); + knot_rr_set_ttl(new_rr, ttl); + return knot_rr_get_rdata(new_rr); + } + + knot_rr_t *old_rr = knot_rrs_get_rr(rrs, pos); + assert(old_rr); // Make space for new data by moving the array memmove(old_rr + size + RR_META_SIZE, old_rr, @@ -213,8 +99,8 @@ uint8_t* knot_rrs_create_rr_at_pos(knot_rrs_t *rrs, return knot_rr_get_rdata(old_rr); } -int knot_rrs_add_rr_at_pos(knot_rrs_t *rrs, const knot_rr_t *rr, - size_t pos, mm_ctx_t *mm) +static int knot_rrs_add_rr_at_pos(knot_rrs_t *rrs, const knot_rr_t *rr, + size_t pos, mm_ctx_t *mm) { if (rrs == NULL || pos > rrs->rr_count) { return KNOT_EINVAL; @@ -232,43 +118,56 @@ int knot_rrs_add_rr_at_pos(knot_rrs_t *rrs, const knot_rr_t *rr, return KNOT_EOK; } -uint8_t* knot_rrs_create_rr(knot_rrs_t *rrs, const uint16_t size, - const uint32_t ttl, mm_ctx_t *mm) + +uint16_t knot_rr_size(const knot_rr_t *rr) { - if (rrs == NULL) { - return NULL; - } + return *((uint16_t *)rr); +} - size_t total_size = knot_rrs_size(rrs); - /* Realloc RRs. */ - void *tmp = mm_realloc(mm, rrs->data, total_size + size + RR_META_SIZE, - total_size); - if (tmp) { - rrs->data = tmp; - } else { - ERR_ALLOC_FAILED; - return NULL; - } +void knot_rr_set_size(knot_rr_t *rr, uint16_t size) +{ + *((uint16_t *)rr) = size; +} - rrs->rr_count++; - knot_rr_t *rr = knot_rrs_get_rr(rrs, rrs->rr_count - 1); - assert(rr); +uint32_t knot_rr_ttl(const knot_rr_t *rr) +{ + return *((uint32_t *)(rr + sizeof(uint16_t))); +} - knot_rr_set_size(rr, size); - knot_rr_set_ttl(rr, ttl); +void knot_rr_set_ttl(knot_rr_t *rr, uint32_t ttl) +{ + *((uint32_t *)(rr + sizeof(uint16_t))) = ttl; +} - return knot_rr_get_rdata(rr); +const uint8_t *knot_rr_rdata(const knot_rr_t *rr) +{ + return (const uint8_t *)(rr + RR_META_SIZE); } -knot_rrs_t *knot_rrs_new(mm_ctx_t *mm) +uint8_t *knot_rr_get_rdata(knot_rr_t *rr) { - knot_rrs_t *rrs = mm_alloc(mm, sizeof(knot_rrs_t)); - if (rrs == NULL) { - ERR_ALLOC_FAILED; - return NULL; + return rr + RR_META_SIZE; +} + +size_t knot_rr_array_size(uint16_t size) +{ + return size + RR_META_SIZE; +} + +int knot_rr_cmp(const knot_rr_t *rr1, const knot_rr_t *rr2) +{ + if (rr1 == NULL || rr2 == NULL) { + return -1; + } + const uint8_t *r1 = knot_rr_rdata(rr1); + const uint8_t *r2 = knot_rr_rdata(rr2); + uint16_t l1 = knot_rr_size(rr1); + uint16_t l2 = knot_rr_size(rr2); + int cmp = memcmp(r1, r2, MIN(l1, l2)); + if (cmp == 0 && l1 != l2) { + cmp = l1 < l2 ? -1 : 1; } - knot_rrs_init(rrs); - return rrs; + return cmp; } void knot_rrs_init(knot_rrs_t *rrs) @@ -306,46 +205,117 @@ int knot_rrs_copy(knot_rrs_t *dst, const knot_rrs_t *src, mm_ctx_t *mm) return KNOT_EOK; } +knot_rr_t *knot_rrs_get_rr(const knot_rrs_t *rrs, size_t pos) +{ + if (rrs == NULL || pos >= rrs->rr_count) { + return NULL; + } + + return rr_seek(rrs->data, pos); +} + +const knot_rr_t *knot_rrs_rr(const knot_rrs_t *rrs, size_t pos) +{ + if (rrs == NULL || pos >= rrs->rr_count) { + return NULL; + } + + return (const knot_rr_t *)rr_seek(rrs->data, pos); +} -int knot_rrs_synth_rrsig(uint16_t type, const knot_rrs_t *rrsig_rrs, - knot_rrs_t *out_sig, mm_ctx_t *mm) +const uint8_t *knot_rrs_rr_rdata(const knot_rrs_t *rrs, size_t pos) { - if (rrsig_rrs == NULL) { - return KNOT_ENOENT; + if (rrs == NULL || pos >= rrs->rr_count) { + return NULL; } - if (out_sig == NULL || out_sig->rr_count > 0) { - return KNOT_EINVAL; + return knot_rr_rdata(knot_rrs_rr(rrs, pos)); +} + +uint8_t *knot_rrs_rr_get_rdata(const knot_rrs_t *rrs, size_t pos) +{ + return (uint8_t *)knot_rrs_rr_rdata(rrs, pos); +} + +uint16_t knot_rrs_rr_size(const knot_rrs_t *rrs, size_t pos) +{ + if (rrs == NULL || pos >= rrs->rr_count) { + return 0; } - for (int i = 0; i < rrsig_rrs->rr_count; ++i) { - if (type == knot_rrs_rrsig_type_covered(rrsig_rrs, i)) { - const knot_rr_t *rr_to_copy = knot_rrs_rr(rrsig_rrs, i); - int ret = knot_rrs_add_rr(out_sig, rr_to_copy, mm); - if (ret != KNOT_EOK) { - knot_rrs_clear(out_sig, mm); - return ret; - } - } + return knot_rr_size(knot_rrs_rr(rrs, pos)); +} + +uint32_t knot_rrs_rr_ttl(const knot_rrs_t *rrs, size_t pos) +{ + if (rrs == NULL || pos >= rrs->rr_count) { + return 0; } - return out_sig->rr_count > 0 ? KNOT_EOK : KNOT_ENOENT; + return knot_rr_ttl(knot_rrs_rr(rrs, pos)); } -int knot_rr_cmp(const knot_rr_t *rr1, const knot_rr_t *rr2) +int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm) { - if (rr1 == NULL || rr2 == NULL) { - return -1; + if (rrs == NULL || rr == NULL) { + return KNOT_EINVAL; } - const uint8_t *r1 = knot_rr_rdata(rr1); - const uint8_t *r2 = knot_rr_rdata(rr2); - uint16_t l1 = knot_rr_size(rr1); - uint16_t l2 = knot_rr_size(rr2); - int cmp = memcmp(r1, r2, MIN(l1, l2)); - if (cmp == 0 && l1 != l2) { - cmp = l1 < l2 ? -1 : 1; + + for (uint16_t i = 0; i < rrs->rr_count; ++i) { + const knot_rr_t *rrset_rr = knot_rrs_rr(rrs, i); + int cmp = knot_rr_cmp(rrset_rr, rr); + if (cmp == 0) { + // Duplication - no need to add this RR + return KNOT_EOK; + } else if (cmp > 0) { + // Found position to insert + return knot_rrs_add_rr_at_pos(rrs, rr, i, mm); + } } - return cmp; + + // If flow gets here, it means that we should insert at the last position + return knot_rrs_add_rr_at_pos(rrs, rr, rrs->rr_count, mm); +} + +int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm) +{ + if (rrs == NULL || pos >= rrs->rr_count) { + return KNOT_EINVAL; + } + + knot_rr_t *old_rr = knot_rrs_get_rr(rrs, pos); + knot_rr_t *last_rr = knot_rrs_get_rr(rrs, rrs->rr_count - 1); + assert(old_rr); + assert(last_rr); + + size_t total_size = knot_rrs_size(rrs); + uint16_t old_size = knot_rr_size(old_rr); + + void *old_threshold = old_rr + old_size + RR_META_SIZE; + void *last_threshold = last_rr + knot_rr_size(last_rr) + RR_META_SIZE; + // Move RDATA + memmove(old_rr, old_threshold, + last_threshold - old_threshold); + + if (rrs->rr_count > 1) { + // Realloc RDATA + void *tmp = mm_realloc(mm, rrs->data, + total_size - (old_size + RR_META_SIZE), + total_size); + if (tmp == NULL) { + ERR_ALLOC_FAILED; + return KNOT_ENOMEM; + } else { + rrs->data = tmp; + } + } else { + // Free RDATA + mm_free(mm, rrs->data); + rrs->data = NULL; + } + rrs->rr_count--; + + return KNOT_EOK; } bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2) @@ -365,26 +335,29 @@ bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2) return true; } -int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm) +int knot_rrs_synth_rrsig(uint16_t type, const knot_rrs_t *rrsig_rrs, + knot_rrs_t *out_sig, mm_ctx_t *mm) { - if (rrs == NULL || rr == NULL) { + if (rrsig_rrs == NULL) { + return KNOT_ENOENT; + } + + if (out_sig == NULL || out_sig->rr_count > 0) { return KNOT_EINVAL; } - for (uint16_t i = 0; i < rrs->rr_count; ++i) { - const knot_rr_t *rrset_rr = knot_rrs_rr(rrs, i); - int cmp = knot_rr_cmp(rrset_rr, rr); - if (cmp == 0) { - // Duplication - no need to add this RR - return KNOT_EOK; - } else if (cmp > 0) { - // Found position to insert - return knot_rrs_add_rr_at_pos(rrs, rr, i, mm); + for (int i = 0; i < rrsig_rrs->rr_count; ++i) { + if (type == knot_rrs_rrsig_type_covered(rrsig_rrs, i)) { + const knot_rr_t *rr_to_copy = knot_rrs_rr(rrsig_rrs, i); + int ret = knot_rrs_add_rr(out_sig, rr_to_copy, mm); + if (ret != KNOT_EOK) { + knot_rrs_clear(out_sig, mm); + return ret; + } } } - // If flow gets here, it means that we should insert at the last position - return knot_rrs_add_rr_at_pos(rrs, rr, rrs->rr_count, mm); + return out_sig->rr_count > 0 ? KNOT_EOK : KNOT_ENOENT; } int knot_rrs_merge(knot_rrs_t *rrs1, const knot_rrs_t *rrs2, mm_ctx_t *mm) diff --git a/src/libknot/rr.h b/src/libknot/rr.h index 28a7226903048ad8f780dec24e08a9b7fa66807d..ab02754a09ba803f4b6f44744259c94f033ceab0 100644 --- a/src/libknot/rr.h +++ b/src/libknot/rr.h @@ -7,44 +7,205 @@ #include "common/mempattern.h" -typedef uint8_t knot_rr_t; +/* ---------------------------- Single RR ----------------------------------- */ -typedef struct knot_rrs { - uint16_t rr_count; - knot_rr_t *data; -} knot_rrs_t; +typedef uint8_t knot_rr_t; /*!< \brief Single RR containing size, TTL and RDATA. */ + +/* ------------------------- RR getters/setters ----------------------------- */ +/*! + * \brief Returns size of single RR. + * \param rr RR whose size we want. + * \return RR size. + */ uint16_t knot_rr_size(const knot_rr_t *rr); + +/*! + * \brief Sets size for given RR. + * \param rr RR whose size we want to set. + * \param size Size to be set. + */ +void knot_rr_set_size(knot_rr_t *rr, uint16_t size); + +/*! + * \brief Returns TTL of single RR. + * \param rr RR whose TTL we want. + * \return RR TTL. + */ uint32_t knot_rr_ttl(const knot_rr_t *rr); + +/*! + * \brief Sets TTL for given RR. + * \param rr RR whose TTL we want to set. + * \param ttl TTL to be set. + */ +void knot_rr_set_ttl(knot_rr_t *rr, uint32_t ttl); + +/*! + * \brief Returns const pointer to RR data. + * \param rr RR whose data we want. + * \return RR data const pointer. + */ const uint8_t *knot_rr_rdata(const knot_rr_t *rr); + +/*! + * \brief Returns pointer to RR data. + * \param rr RR whose data we want. + * \return RR data pointer. + */ uint8_t *knot_rr_get_rdata(knot_rr_t *rr); -void knot_rr_set_size(knot_rr_t *rr, uint16_t size); -void knot_rr_set_ttl(knot_rr_t *rr, uint32_t ttl); -int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm); -knot_rrs_t *knot_rrs_new(mm_ctx_t *mm); + +/* ----------------------------- RR misc ------------------------------------ */ + +/*! + * \brief Returns actual size of RR structure for given RDATA size. + * \param size RDATA size. + * \return Actual structure size. + */ +size_t knot_rr_array_size(uint16_t size); + +/*! + * \brief Canonical comparison of two RRs. + * \param rr1 First RR to compare. + * \param rr2 Second RR to compare. + * \retval 0 if rr1 == rr2. + * \retval < 0 if rr1 < rr2. + * \retval > 0 if rr1 > rr2. + */ +int knot_rr_cmp(const knot_rr_t *rr1, const knot_rr_t *rr2); + +/* --------------------------- Multiple RRs ----------------------------------*/ + +/*!< \brief Array of RRs */ +typedef struct knot_rrs { + uint16_t rr_count; /*!< \brief Count of RRs stored in the structure. */ + knot_rr_t *data; /*!< \brief Actual data, canonically sorted. */ +} knot_rrs_t; + +/* -------------------------- RRs init/clear ---------------------------------*/ + +/*! + * \brief Initializes RRS structure. + * \param rrs Structure to be initialized. + */ void knot_rrs_init(knot_rrs_t *rrs); -size_t knot_rrs_size(const knot_rrs_t *rrs); -uint16_t knot_rrs_rr_count(const knot_rrs_t *rrs); + +/*! + * \brief Frees data initialized by RRS structure, but not the structure itself. + * \param rrs Structure to be cleared. + * \param mm Memory context used to create allocations. + */ +void knot_rrs_clear(knot_rrs_t *rrs, mm_ctx_t *mm); + +/*! + * \brief Deep copies RRS structure. All data are duplicated. + * \param dst Copy destination. + * \param src Copy source. + * \param mm Memory context. + * \return KNOT_E* + */ +int knot_rrs_copy(knot_rrs_t *dst, const knot_rrs_t *src, mm_ctx_t *mm); + +/* ----------------------- RRs getters/setters ------------------------------ */ + +/*! + * \brief Gets RR from RRS structure, using given position. + * \param rrs RRS structure to get RR from. + * \param pos Position to use. + * \return Pointer to RR at \a pos position. + */ knot_rr_t *knot_rrs_get_rr(const knot_rrs_t *rrs, size_t pos); + +/*! + * \brief Gets RR from RRS structure, using given position. + * \param rrs RRS structure to get RR from. + * \param pos Position to use. + * \return Const pointer to RR at \a pos position. + */ const knot_rr_t *knot_rrs_rr(const knot_rrs_t *rrs, size_t pos); + +/*! + * \brief Gets RDATA from RR at \a pos position. + * \param rrs RRS to get RDATA from. + * \param pos Position to use. + * \return Pointer to RDATA of RR at \a pos position. + */ const uint8_t *knot_rrs_rr_rdata(const knot_rrs_t *rrs, size_t pos); + +/*! + * \brief Gets RDATA from RR at \a pos position. + * \param rrs RRS to get RDATA from. + * \param pos Position to use. + * \return Const pointer to RDATA of RR at \a pos position. + */ uint8_t *knot_rrs_rr_get_rdata(const knot_rrs_t *rrs, size_t pos); + +/*! + * \brief Gets size from RR at \a pos position. + * \param rrs RRS to get size from. + * \param pos Position to use. + * \return Size of RR at \a pos position. + */ uint16_t knot_rrs_rr_size(const knot_rrs_t *rrs, size_t pos); + +/*! + * \brief Gets TTL from RR at \a pos position. + * \param rrs RRS to get TTL from. + * \param pos Position to use. + * \return Size of TTL at \a pos position. + */ uint32_t knot_rrs_rr_ttl(const knot_rrs_t *rrs, size_t pos); -uint8_t* knot_rrs_create_rr(knot_rrs_t *rrs, const uint16_t size, - const uint32_t ttl, mm_ctx_t *mm); -uint8_t* knot_rrs_create_rr_at_pos(knot_rrs_t *rrs, - size_t pos, uint16_t size, - uint32_t ttl, mm_ctx_t *mm); -int knot_rrs_add_rr_at_pos(knot_rrs_t *rrs, const knot_rr_t *rr, - size_t pos, mm_ctx_t *mm); + +/* ----------------------- RRs RR manipulation ------------------------------ */ + +/*! + * \brief Adds single RR into RRS structure. All data are copied. + * \param rrs RRS structure to add RR into. + * \param rr RR to add. + * \param mm Memory context. + * \return KNOT_E* + */ +int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm); + +/*! + * \brief Removes RR at a given position from RRS structure. RR is dropped. + * \param rrs RRS structure to remove from. + * \param pos Position to use. + * \param mm Memory context. + * \return KNOT_E* + */ int knot_rrs_remove_rr_at_pos(knot_rrs_t *rrs, size_t pos, mm_ctx_t *mm); -void knot_rrs_clear(knot_rrs_t *rrs, mm_ctx_t *mm); -int knot_rr_cmp(const knot_rr_t *rr1, const knot_rr_t *rr2); + +/* ----------------------------- RRs misc ----------------------------------- */ + +/*! + * \brief RRS equality check. + * \param rrs1 First RRS to be compared. + * \param rrs2 Second RRS to be compared. + * \retval true if rrs1 == rrs2. + * \retval false if rrs1 != rrs2. + */ bool knot_rrs_eq(const knot_rrs_t *rrs1, const knot_rrs_t *rrs2); -int knot_rrs_copy(knot_rrs_t *dst, const knot_rrs_t *src, mm_ctx_t *mm); + +/*! + * \brief Creates new RRS using \a rrsig_rrs as a source. Only those RRs that + * cover given \a type are copied into \a out_sig + * \param type Covered type. + * \param rrsig_rrs Source RRS. + * \param out_sig Output RRS. + * \param mm Memory context. + * \return KNOT_E* + */ int knot_rrs_synth_rrsig(uint16_t type, const knot_rrs_t *rrsig_rrs, knot_rrs_t *out_sig, mm_ctx_t *mm); -int knot_rrs_add_rr(knot_rrs_t *rrs, const knot_rr_t *rr, mm_ctx_t *mm); + +/*! + * \brief Merges two RRS into the first one. Second RRS is left intact. + * Canonical order is preserved. + * \param rrs1 Destination RRS (merge here). + * \param rrs2 RRS to be merged (merge from). + * \param mm Memory context. + * \return KNOT_E* + */ int knot_rrs_merge(knot_rrs_t *rrs1, const knot_rrs_t *rrs2, mm_ctx_t *mm); diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c index c729e955b5ab905c0291ddccc9655824b2b0b230..d42ba6fb43b10e857a7386a4fa223bb5e64de18d 100644 --- a/src/libknot/rrset.c +++ b/src/libknot/rrset.c @@ -407,15 +407,8 @@ static int rrset_deserialize_rr(knot_rrset_t *rrset, { uint32_t ttl; memcpy(&ttl, stream, sizeof(uint32_t)); - uint8_t *rdata = knot_rrset_create_rr(rrset, - rdata_size - sizeof(uint32_t), - ttl, NULL); - if (rdata == NULL) { - return KNOT_ENOMEM; - } - - memcpy(rdata, stream + sizeof(uint32_t), rdata_size - sizeof(uint32_t)); - return KNOT_EOK; + return knot_rrset_add_rr(rrset, stream + sizeof(uint32_t), + rdata_size - sizeof(uint32_t), ttl, NULL); } void knot_rrset_init(knot_rrset_t *rrset, knot_dname_t *owner, uint16_t type, @@ -470,16 +463,13 @@ int knot_rrset_add_rr(knot_rrset_t *rrset, return KNOT_EINVAL; } - uint8_t *p = knot_rrset_create_rr(rrset, size, ttl, mm); - memcpy(p, rdata, size); - - return KNOT_EOK; -} + // Create knot_rr_t from given data + knot_rr_t rr[knot_rr_array_size(size)]; + knot_rr_set_size(rr, size); + knot_rr_set_ttl(rr, ttl); + memcpy(knot_rr_get_rdata(rr), rdata, size); -uint8_t* knot_rrset_create_rr(knot_rrset_t *rrset, const uint16_t size, - const uint32_t ttl, mm_ctx_t *mm) -{ - return knot_rrs_create_rr(&rrset->rrs, size, ttl, mm); + return knot_rrs_add_rr(&rrset->rrs, rr, mm); } uint16_t knot_rrset_rr_size(const knot_rrset_t *rrset, size_t pos) @@ -561,8 +551,13 @@ int knot_rrset_rdata_from_wire_one(knot_rrset_t *rrset, } if (rdlength == 0) { - return knot_rrset_create_rr(rrset, 0, ttl, mm) == NULL ? - KNOT_ENOMEM : KNOT_EOK; + uint8_t *empty_rdata = malloc(1); + if (empty_rdata == NULL) { + return KNOT_ENOMEM; + } + int ret = knot_rrset_add_rr(rrset, empty_rdata, 0, ttl, mm); + free(empty_rdata); + return ret; } dbg_rrset_detail("rr: parse_rdata_wire: Parsing RDATA of size=%zu," @@ -703,14 +698,7 @@ dbg_rrset_exec_detail( } } - uint8_t *rdata = knot_rrset_create_rr(rrset, offset, ttl, mm); - if (rdata == NULL) { - return KNOT_ENOMEM; - } - - memcpy(rdata, rdata_buffer, offset); - - return KNOT_EOK; + return knot_rrset_add_rr(rrset, rdata_buffer, offset, ttl, mm); } bool knot_rrset_equal(const knot_rrset_t *r1, @@ -996,20 +984,11 @@ int knot_rrset_add_rr_from_rrset(knot_rrset_t *dest, const knot_rrset_t *source, return KNOT_EINVAL; } - /* Get size and TTL of RR to be copied. */ - uint16_t size = knot_rrset_rr_size(source, rdata_pos); - uint32_t ttl = knot_rrset_rr_ttl(source, rdata_pos); - /* Reserve space in dest RRSet. */ - uint8_t *rdata = knot_rrset_create_rr(dest, size, ttl, mm); - if (rdata == NULL) { - dbg_rrset("rr: add_rr_from_rrset: Could not create RDATA.\n"); - return KNOT_ERROR; - } - - /* Copy actual data. */ - memcpy(rdata, knot_rrset_rr_rdata(source, rdata_pos), size); - - return KNOT_EOK; + /* Get RDATA, size and TTL of RR to be copied. */ + const uint8_t *rdata = knot_rrset_rr_rdata(source, rdata_pos); + const uint16_t size = knot_rrset_rr_size(source, rdata_pos); + const uint32_t ttl = knot_rrset_rr_ttl(source, rdata_pos); + return knot_rrset_add_rr(dest, rdata, size, ttl, mm); } int knot_rrset_remove_rr_using_rrset(knot_rrset_t *from, diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h index f0baa47abf631535b4a3d1feb0bfb7485c1732d8..92f356354e046ee23372c12d3da17673e20cb791 100644 --- a/src/libknot/rrset.h +++ b/src/libknot/rrset.h @@ -63,12 +63,6 @@ typedef enum { KNOT_RRSET_COMPARE_WHOLE } knot_rrset_compare_type_t; -typedef enum { - KNOT_RRSET_DUPL_MERGE, - KNOT_RRSET_DUPL_REPLACE, - KNOT_RRSET_DUPL_SKIP -} knot_rrset_dupl_handling_t; - /*----------------------------------------------------------------------------*/ /*! @@ -116,21 +110,6 @@ int knot_rrset_add_rr(knot_rrset_t *rrset, const uint8_t *rdata, const uint16_t size, const uint32_t ttl, mm_ctx_t *mm); -/*! - * \brief Creates RDATA memory and returns a pointer to it. - * If the RRSet is not empty, function will return a memory - * pointing to a beginning of a new RR. - * - * \param rrset RRSet to add the RDATA to. - * \param size Size of RR RDATA (Size in internal representation) - * \param mm Memory context. - * - * \retval Pointer to memory to be written to. - * \retval NULL if arguments are invalid / no memory. - */ -uint8_t* knot_rrset_create_rr(knot_rrset_t *rrset, const uint16_t size, - const uint32_t ttl, mm_ctx_t *mm); - /*! * \brief Returns RDATA of RR on given position. * diff --git a/src/libknot/tsig.c b/src/libknot/tsig.c index 233814ed9774dce501c23989ba1563cfdd1e999b..c527d23f940a6f8a47da4bf73bb799ac30369d4a 100644 --- a/src/libknot/tsig.c +++ b/src/libknot/tsig.c @@ -132,15 +132,20 @@ int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg, uint16_t maclen if (tsig_err != KNOT_RCODE_BADTIME) { rdlen -= TSIG_OTHER_MAXLEN; } - uint8_t *rd = knot_rrset_create_rr(rr, rdlen, 0, NULL); + uint8_t rd[rdlen]; memset(rd, 0, rdlen); /* Copy alg name. */ knot_dname_to_wire(rd, alg, rdlen); /* Set MAC variable length in advance. */ - rd += alg_len + TSIG_OFF_MACLEN; - knot_wire_write_u16(rd, maclen); + size_t offset = alg_len + TSIG_OFF_MACLEN; + knot_wire_write_u16(rd + offset, maclen); + + int ret = knot_rrset_add_rr(rr, rd, rdlen, 0, NULL); + if (ret != KNOT_EOK) { + return ret; + } /* Set error. */ tsig_rdata_set_tsig_error(rr, tsig_err);