diff --git a/src/common/log.c b/src/common/log.c index a5c8b1c8554cd81c65831618649f2fccbea19fd0..7eb73ccff6e96aa8fc6a38a148762d90d456438a 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -403,7 +403,7 @@ int log_msg_zone(int priority, const knot_dname_t *zone, const char *fmt, ...) { va_list args; va_start(args, fmt); - char *zone_str = knot_dname_to_str(zone); + char *zone_str = knot_dname_to_str_alloc(zone); int result = log_msg_text(priority, zone_str ? zone_str : LOG_NULL_ZONE_STRING, fmt, args); diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c index fda72b0e3e677a932ed9f3293ed7dd39a90a3fa0..ea54d54764fb8f68c57ebe1ae3887ebbb2a0bb0a 100644 --- a/src/knot/ctl/remote.c +++ b/src/knot/ctl/remote.c @@ -561,7 +561,7 @@ static void log_command(const char *cmd, const remote_cmdargs_t* args) uint16_t rr_count = rr->rrs.rr_count; for (uint16_t j = 0; j < rr_count; j++) { const knot_dname_t *dn = knot_ns_name(&rr->rrs, j); - char *name = knot_dname_to_str(dn); + char *name = knot_dname_to_str_alloc(dn); int ret = snprintf(params, rest, " %s", name); free(name); diff --git a/src/knot/dnssec/nsec3-chain.c b/src/knot/dnssec/nsec3-chain.c index c486a1508c32a89901c7e175baaed21241c6ca77..685ee2998a7150e3e9446674b46793a6414ce264 100644 --- a/src/knot/dnssec/nsec3-chain.c +++ b/src/knot/dnssec/nsec3-chain.c @@ -287,7 +287,7 @@ static zone_node_t *create_nsec3_node(knot_dname_t *owner, if (!new_node) { return NULL; } - + node_set_parent(new_node, apex_node); knot_rrset_t nsec3_rrset; @@ -385,7 +385,7 @@ static int connect_nsec3_nodes(zone_node_t *a, zone_node_t *b, assert(raw_length == knot_nsec3_hash_length(algorithm)); knot_dname_to_lower(b->owner); - uint8_t *b32_hash = (uint8_t *)knot_dname_to_str(b->owner); + uint8_t *b32_hash = (uint8_t *)knot_dname_to_str_alloc(b->owner); size_t b32_length = knot_nsec3_hash_b32_length(algorithm); if (!b32_hash) { return KNOT_ENOMEM; diff --git a/src/knot/nameserver/chaos.c b/src/knot/nameserver/chaos.c index 41822136355eede084f8557e4ed8e47cd2763114..086ca8e7aff258df824dfdfd1f3091f0c1ce0d5e 100644 --- a/src/knot/nameserver/chaos.c +++ b/src/knot/nameserver/chaos.c @@ -26,7 +26,7 @@ */ static const char *get_txt_response_string(const knot_dname_t *qname) { - char *qname_str = knot_dname_to_str(qname); + char *qname_str = knot_dname_to_str_alloc(qname); const char *response = NULL; /* id.server and hostname.bind should have similar meaning */ diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index 9a4158ade629db75a427d4be0928f39e36b77930..494d00bbf6c61be155d381c6928b1e7f7f2f9fe7 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -436,7 +436,7 @@ static bool singleton_replaced(changeset_t *changeset, if (!should_replace(rr)) { return false; } - + zone_node_t *n = zone_contents_find_node_for_rr(changeset->add, rr); if (n == NULL) { return false; @@ -446,12 +446,12 @@ static bool singleton_replaced(changeset_t *changeset, if (rrs == NULL) { return false; } - + // Replace singleton RR. knot_rdataset_clear(rrs, NULL); node_remove_rdataset(n, rr->type); node_add_rrset(n, rr, NULL); - + return true; } @@ -544,7 +544,7 @@ static int process_add_nsec3param(const zone_node_t *node, { if (node == NULL || !node_rrtype_exists(node, KNOT_RRTYPE_SOA)) { // Ignore non-apex additions - char *owner = knot_dname_to_str(rr->owner); + char *owner = knot_dname_to_str_alloc(rr->owner); log_warning("DDNS, refusing to add NSEC3PARAM to non-apex " "node '%s'", owner); free(owner); @@ -555,7 +555,7 @@ static int process_add_nsec3param(const zone_node_t *node, return add_rr_to_chgset(rr, changeset, NULL); } - char *owner = knot_dname_to_str(rr->owner); + char *owner = knot_dname_to_str_alloc(rr->owner); log_warning("DDNS, refusing to add second NSEC3PARAM to node '%s'", owner); free(owner); @@ -918,7 +918,7 @@ int ddns_process_update(const zone_t *zone, const knot_pkt_t *query, } return KNOT_EINVAL; } - + changeset_t *changeset = update->change; if (changeset->soa_from == NULL) { diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c index be0821ae1f3537ae6ba25f257305837d6cc59396..cc06004a502893fba42d7ee6615ac62c80f6802b 100644 --- a/src/knot/zone/semantic-check.c +++ b/src/knot/zone/semantic-check.c @@ -181,7 +181,7 @@ static void log_error_from_node(err_handler_t *handler, handler->error_count++; - char *name = knot_dname_to_str(node->owner); + char *name = knot_dname_to_str_alloc(node->owner); const char *errmsg = error_messages[-error]; log_zone_warning(zone_name, "semantic check, node '%s' (%s%s%s)", diff --git a/src/knot/zone/zonefile.c b/src/knot/zone/zonefile.c index 70ee8e988f08e280c1c17c3a0c723ef887553bd6..9c26863ad5a70c389d9b72c3eb1e2d0d4e8fc880 100644 --- a/src/knot/zone/zonefile.c +++ b/src/knot/zone/zonefile.c @@ -63,7 +63,7 @@ static bool handle_err(zcreator_t *zc, const zone_node_t *node, const knot_rrset_t *rr, int ret, bool master) { const knot_dname_t *zname = zc->z->apex->owner; - char *rrname = rr ? knot_dname_to_str(rr->owner) : NULL; + char *rrname = rr ? knot_dname_to_str_alloc(rr->owner) : NULL; if (ret == KNOT_EOUTOFZONE) { WARNING(zname, "ignoring out-of-zone data, owner '%s'", rrname ? rrname : "unknown"); @@ -164,7 +164,7 @@ static void scanner_process(zs_scanner_t *scanner) knot_rrset_init(&rr, owner, scanner->r_type, scanner->r_class); int ret = add_rdata_to_rr(&rr, scanner); if (ret != KNOT_EOK) { - char *rr_name = knot_dname_to_str(rr.owner); + char *rr_name = knot_dname_to_str_alloc(rr.owner); const knot_dname_t *zname = zc->z->apex->owner; ERROR(zname, "failed to add RDATA, file '%s', line %"PRIu64", owner '%s'", scanner->file.name, scanner->line_counter, rr_name); diff --git a/src/libknot/dname.c b/src/libknot/dname.c index e5ad1b8494e5eb17b9880f55fcfe18ab9578b196..2df6c5ce32e2673e2cc4dd94efc2e2c2061155e2 100644 --- a/src/libknot/dname.c +++ b/src/libknot/dname.c @@ -211,17 +211,24 @@ int knot_dname_unpack(uint8_t* dst, const knot_dname_t *src, /*----------------------------------------------------------------------------*/ -char *knot_dname_to_str(const knot_dname_t *name) +char *knot_dname_to_str(char *dst, const knot_dname_t *name, size_t maxlen) { - if (name == NULL) + if (name == NULL) { return NULL; + } - /*! \todo Supply packet. */ - /*! \todo Write to static buffer? */ - // Allocate space for dname string + 1 char termination. int dname_size = knot_dname_size(name); - size_t alloc_size = dname_size + 1; - char *res = malloc(alloc_size); + if (dname_size <= 0) { + return NULL; + } + + // Check the size for len(dname) + 1 char termination. + size_t alloc_size = (dst == NULL) ? dname_size + 1 : maxlen; + if (alloc_size < dname_size + 1) { + return NULL; + } + + char *res = (dst == NULL) ? malloc(alloc_size) : dst; if (res == NULL) { return NULL; } @@ -253,33 +260,47 @@ char *knot_dname_to_str(const knot_dname_t *name) * encoded in \ddd notation. */ - // Increase output size for \x format. - alloc_size += 1; - char *extended = realloc(res, alloc_size); - if (extended == NULL) { - free(res); - return NULL; + if (dst != NULL) { + if (maxlen <= str_len + 2) { + return NULL; + } + } else { + // Extend output buffer for \x format. + alloc_size += 1; + char *extended = realloc(res, alloc_size); + if (extended == NULL) { + free(res); + return NULL; + } + res = extended; } - res = extended; // Write encoded character. res[str_len++] = '\\'; res[str_len++] = c; } else { - // Increase output size for \DDD format. - alloc_size += 3; - char *extended = realloc(res, alloc_size); - if (extended == NULL) { - free(res); - return NULL; + if (dst != NULL) { + if (maxlen <= str_len + 4) { + return NULL; + } + } else { + // Extend output buffer for \DDD format. + alloc_size += 3; + char *extended = realloc(res, alloc_size); + if (extended == NULL) { + free(res); + return NULL; + } + res = extended; } - res = extended; // Write encoded character. int ret = snprintf(res + str_len, alloc_size - str_len, "\\%03u", c); if (ret <= 0 || ret >= alloc_size - str_len) { - free(res); + if (dst == NULL) { + free(res); + } return NULL; } diff --git a/src/libknot/dname.h b/src/libknot/dname.h index 58bfc174e03d347572c1a54cee3d480ed833a746..bafe66847db749d9e19c43f547ed5ccf45c63c56 100644 --- a/src/libknot/dname.h +++ b/src/libknot/dname.h @@ -118,18 +118,26 @@ int knot_dname_unpack(uint8_t *dst, const knot_dname_t *src, size_t maxlen, const uint8_t *pkt); /*! - * \brief Converts the given domain name to string representation. + * \brief Converts the given domain name to its string representation. * - * \note Allocates new memory, remember to free it. + * \note Output buffer is allocated automatically if dst is NULL. * - * \todo The function doesn't process escaped characters like \DDD or \X. + * \param dst Output buffer. + * \param name Domain name to be converted. + * \param maxlen Output buffer length. * - * \param name Domain name to be converted. - * - * \return 0-terminated string representing the given domain name in - * presentation format. + * \return 0-terminated string if successful, NULL if error. + */ +char *knot_dname_to_str(char *dst, const knot_dname_t *name, size_t maxlen); + +/*! + * \brief This function is a shortcut for \ref knot_dname_to_str with + * no output buffer parameters. */ -char *knot_dname_to_str(const knot_dname_t *name); +static inline char *knot_dname_to_str_alloc(const knot_dname_t *name) +{ + return knot_dname_to_str(NULL, name, 0); +} /*! * \brief Creates a dname structure from domain name given in presentation diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c index 75f3590e2031d8aa0e6b6f12ca577fa29b4089b2..647ea6b95752cad3054b70abcdb23ce300e7ed0d 100644 --- a/src/libknot/rrset-dump.c +++ b/src/libknot/rrset-dump.c @@ -804,16 +804,23 @@ static void wire_dname_to_str(rrset_dump_params_t *p) } // Write dname string. - char *dname_str = knot_dname_to_str(p->in); - if (p->style->ascii_to_idn != NULL) { + if (p->style->ascii_to_idn == NULL) { + char *dname_str = knot_dname_to_str(p->out, p->in, p->out_max); + if (dname_str == NULL) { + return; + } + out_len = strlen(dname_str); + } else { + char *dname_str = knot_dname_to_str_alloc(p->in); p->style->ascii_to_idn(&dname_str); + + int ret = snprintf(p->out, p->out_max, "%s", dname_str); + free(dname_str); + if (ret < 0 || (size_t)ret >= p->out_max) { + return; + } + out_len = ret; } - int ret = snprintf(p->out, p->out_max, "%s", dname_str); - free(dname_str); - if (ret < 0 || (size_t)ret >= p->out_max) { - return; - } - out_len = ret; // Fill in output. p->in += in_len; @@ -1831,7 +1838,7 @@ int knot_rrset_txt_dump_header(const knot_rrset_t *rrset, int ret; // Dump rrset owner. - char *name = knot_dname_to_str(rrset->owner); + char *name = knot_dname_to_str_alloc(rrset->owner); if (style->ascii_to_idn != NULL) { style->ascii_to_idn(&name); } diff --git a/src/libknot/rrtype/tsig.c b/src/libknot/rrtype/tsig.c index 814883d48d452289453ec93d0846e4cb7951d4da..7722d3a1d47de58d42800ec65542936cee350190 100644 --- a/src/libknot/rrtype/tsig.c +++ b/src/libknot/rrtype/tsig.c @@ -241,7 +241,7 @@ knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig) } /* Convert alg name to string. */ - char *name = knot_dname_to_str(alg_name); + char *name = knot_dname_to_str_alloc(alg_name); if (!name) { dbg_tsig("TSIG: rdata: cannot convert alg name.\n"); return KNOT_TSIG_ALG_NULL; @@ -336,7 +336,7 @@ int tsig_alg_from_name(const knot_dname_t *alg_name) return 0; } - char *name = knot_dname_to_str(alg_name); + char *name = knot_dname_to_str_alloc(alg_name); if (!name) { return 0; } diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c index 43c6b6c009139dac48714c15aca865ddedbfa589..2d91e2db75eccfccbaf61c6754bb04f1766ac322 100644 --- a/src/libknot/tsig-op.c +++ b/src/libknot/tsig-op.c @@ -69,7 +69,7 @@ static int knot_tsig_check_key(const knot_rrset_t *tsig_rr, return KNOT_EMALF; } - char *name = knot_dname_to_str(tsig_name); + char *name = knot_dname_to_str_alloc(tsig_name); if (!name) { return KNOT_EMALF; } diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c index b4ff5fa5fe6a92469bddd9772d4dd6a0f70032ca..d516518aff7e90fb24b17504ebdb98e44e2a4908 100644 --- a/src/utils/common/exec.c +++ b/src/utils/common/exec.c @@ -376,7 +376,7 @@ static void print_section_host(const knot_rrset_t *rrsets, char type[32] = "NULL"; char *owner; - owner = knot_dname_to_str(rrset->owner); + owner = knot_dname_to_str_alloc(rrset->owner); if (style->style.ascii_to_idn != NULL) { style->style.ascii_to_idn(&owner); } @@ -432,7 +432,7 @@ static void print_error_host(const uint8_t code, knot_lookup_table_t *rcode; - owner = knot_dname_to_str(knot_pkt_qname(packet)); + owner = knot_dname_to_str_alloc(knot_pkt_qname(packet)); if (style->style.ascii_to_idn != NULL) { style->style.ascii_to_idn(&owner); } @@ -486,7 +486,7 @@ void print_header_xfr(const knot_pkt_t *packet, const style_t *style) } if (style->show_header) { - char *owner = knot_dname_to_str(knot_pkt_qname(packet)); + char *owner = knot_dname_to_str_alloc(knot_pkt_qname(packet)); if (style->style.ascii_to_idn != NULL) { style->style.ascii_to_idn(&owner); } diff --git a/tests/ztree.c b/tests/ztree.c index 4d24d9cd5c2848d2f310240490923f26d9a807bc..09523665e323ad9b987da764978ff7bd21822f50 100644 --- a/tests/ztree.c +++ b/tests/ztree.c @@ -55,8 +55,8 @@ static int ztree_iter_data(zone_node_t **node, void *data) int result = KNOT_EOK; if (owner != ORDER[*i]) { result = KNOT_ERROR; - char *exp_s = knot_dname_to_str(ORDER[*i]); - char *owner_s = knot_dname_to_str(owner); + char *exp_s = knot_dname_to_str_alloc(ORDER[*i]); + char *owner_s = knot_dname_to_str_alloc(owner); diag("ztree: at index: %u expected '%s' got '%s'\n", *i, exp_s, owner_s); free(exp_s); free(owner_s);