Commit 89c50775 authored by Daniel Salzman's avatar Daniel Salzman
Browse files

libknot/dname: code cleanup

parent 31e3c38b
......@@ -100,11 +100,7 @@ static int get_zone(ctl_args_t *args, zone_t **zone)
if (dname == NULL) {
return KNOT_EINVAL;
}
int ret = knot_dname_to_lower(dname);
if (ret != KNOT_EOK) {
return ret;
}
knot_dname_to_lower(dname);
*zone = knot_zonedb_find(args->server->zone_db, dname);
if (*zone == NULL) {
......@@ -592,11 +588,7 @@ static int get_owner(uint8_t *out, size_t out_len, knot_dname_t *origin,
if (dname == NULL) {
return KNOT_EINVAL;
}
int ret = knot_dname_to_lower(dname);
if (ret != KNOT_EOK) {
return ret;
}
knot_dname_to_lower(dname);
prefix_len = knot_dname_size(out);
if (prefix_len == 0) {
......
......@@ -67,7 +67,7 @@ static int deserialize_rrset(wire_ctx_t *wire, knot_rrset_t *rrset, long *phase)
if (*phase == SERIALIZE_RRSET_INIT && wire_ctx_available(wire) > 0) {
// Read owner, rtype, rclass and RR count.
size_t size = knot_dname_size(wire->position);
knot_dname_t *owner = knot_dname_copy_part(wire->position, size, NULL);
knot_dname_t *owner = knot_dname_copy(wire->position, NULL);
if (owner == NULL || wire_ctx_available(wire) < size + 3 * sizeof(uint16_t)) {
return KNOT_EMALF;
}
......
......@@ -74,7 +74,7 @@ static int dname_cname_synth(const knot_rrset_t *dname_rr,
const knot_dname_t *dname_wire = dname_rr->owner;
const knot_dname_t *dname_tgt = knot_dname_target(&dname_rr->rrs);
size_t labels = knot_dname_labels(dname_wire, NULL);
knot_dname_t *cname = knot_dname_replace_suffix(qname, labels, dname_tgt);
knot_dname_t *cname = knot_dname_replace_suffix(qname, labels, dname_tgt, mm);
if (cname == NULL) {
knot_dname_free(&owner_copy, mm);
return KNOT_ENOMEM;
......@@ -84,7 +84,7 @@ static int dname_cname_synth(const knot_rrset_t *dname_rr,
size_t cname_size = knot_dname_size(cname);
uint8_t cname_rdata[cname_size];
memcpy(cname_rdata, cname, cname_size);
knot_dname_free(&cname, NULL);
knot_dname_free(&cname, mm);
int ret = knot_rrset_add_rdata(cname_rrset, cname_rdata, cname_size, mm);
if (ret != KNOT_EOK) {
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -320,7 +320,7 @@ static int answer_edns_put(knot_pkt_t *resp, knotd_qdata_t *qdata)
}
/*! \brief Initialize response, sizes and find zone from which we're going to answer. */
static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx)
static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, knot_layer_t *ctx)
{
knotd_qdata_t *qdata = QUERY_DATA(ctx);
server_t *server = qdata->params->server;
......@@ -343,10 +343,8 @@ static int prepare_answer(const knot_pkt_t *query, knot_pkt_t *resp, knot_layer_
* Already checked for absence of compression and length.
*/
memcpy(qdata->extra->orig_qname, qname, query->qname_size);
ret = process_query_qname_case_lower((knot_pkt_t *)query);
if (ret != KNOT_EOK) {
return ret;
}
process_query_qname_case_lower(query);
/* Find zone for QNAME. */
qdata->extra->zone = answer_zone_find(query, server->zone_db);
......@@ -735,22 +733,6 @@ fail:
return ret;
}
void process_query_qname_case_restore(knot_pkt_t *pkt, knotd_qdata_t *qdata)
{
/* If original QNAME is empty, Query is either unparsed or for root domain.
* Either way, letter case doesn't matter. */
if (qdata->extra->orig_qname[0] != '\0') {
memcpy(pkt->wire + KNOT_WIRE_HEADER_SIZE,
qdata->extra->orig_qname, qdata->query->qname_size);
}
}
int process_query_qname_case_lower(knot_pkt_t *pkt)
{
knot_dname_t *qname = (knot_dname_t *)knot_pkt_qname(pkt);
return knot_dname_to_lower(qname);
}
/*! \brief Synthesize RRSIG for given parameters, store in 'qdata' for later use */
static int put_rrsig(const knot_dname_t *sig_owner, uint16_t type,
const knot_rrset_t *rrsigs, knot_rrinfo_t *rrinfo,
......
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -97,14 +97,24 @@ int process_query_sign_response(knot_pkt_t *pkt, knotd_qdata_t *qdata);
* \param pkt Incoming message.
* \param qdata Query data.
*/
void process_query_qname_case_restore(knot_pkt_t *pkt, knotd_qdata_t *qdata);
static inline void process_query_qname_case_restore(knot_pkt_t *pkt, knotd_qdata_t *qdata)
{
// If original QNAME is empty, query is either unparsed or for root domain.
if (qdata->extra->orig_qname[0] != '\0') {
memcpy(pkt->wire + KNOT_WIRE_HEADER_SIZE,
qdata->extra->orig_qname, qdata->query->qname_size);
}
}
/*!
* \brief Convert QNAME to lowercase format for processing.
*
* \param pkt Incoming message.
*/
int process_query_qname_case_lower(knot_pkt_t *pkt);
static inline void process_query_qname_case_lower(knot_pkt_t *pkt)
{
knot_dname_to_lower(knot_pkt_qname(pkt));
}
/*!
* \brief Puts RRSet to packet, will store its RRSIG for later use.
......
......@@ -33,32 +33,59 @@ static int label_is_equal(const uint8_t *lb1, const uint8_t *lb2)
return (*lb1 == *lb2) && memcmp(lb1 + 1, lb2 + 1, *lb1) == 0;
}
/*!
* \brief Align name end-to-end and return number of common suffix labels.
*
* \param d1 Domain name1.
* \param d1_labels Number of labels in d1.
* \param d2 Domain name2.
* \param d2_labels Number of labels in d2.
*/
static int dname_align(const uint8_t **d1, uint8_t d1_labels,
const uint8_t **d2, uint8_t d2_labels)
{
assert(d1 && d2);
for (unsigned j = d1_labels; j < d2_labels; ++j) {
*d2 = knot_wire_next_label(*d2, NULL);
}
for (unsigned j = d2_labels; j < d1_labels; ++j) {
*d1 = knot_wire_next_label(*d1, NULL);
}
return (d1_labels < d2_labels) ? d1_labels : d2_labels;
}
_public_
int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp,
const uint8_t *pkt)
{
if (name == NULL || name == endp)
return KNOT_EMALF;
if (name == NULL || name == endp) {
return KNOT_EINVAL;
}
int wire_len = 0;
int name_len = 1; /* Keep \x00 terminal label in advance. */
bool is_compressed = false;
while (*name != '\0') {
/* Check bounds (must have at least 2 octets remaining). */
if (name + 2 > endp)
return KNOT_ESPACE;
if (name + 2 > endp) {
return KNOT_EMALF;
}
if (knot_wire_is_pointer(name)) {
/* Check that the pointer points backwards
* otherwise it could result in infinite loop
*/
if (pkt == NULL)
if (pkt == NULL) {
return KNOT_EINVAL;
}
uint16_t ptr = knot_wire_get_pointer(name);
if (ptr >= (name - pkt))
if (ptr >= (name - pkt)) {
return KNOT_EMALF;
}
name = pkt + ptr; /* Hop to compressed label */
if (!is_compressed) { /* Measure compressed size only */
......@@ -67,27 +94,32 @@ int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp,
}
} else {
/* Check label length. */
if (*name > KNOT_DNAME_MAXLABELLEN)
if (*name > KNOT_DNAME_MAXLABELLEN) {
return KNOT_EMALF;
}
/* Check if there's enough space. */
int lblen = *name + 1;
if (name_len + lblen > KNOT_DNAME_MAXLEN)
if (name_len + lblen > KNOT_DNAME_MAXLEN) {
return KNOT_EMALF;
}
/* Update wire size only for noncompressed part. */
name_len += lblen;
if (!is_compressed)
if (!is_compressed) {
wire_len += lblen;
}
/* Hop to next label. */
name += lblen;
}
/* Check bounds (must have at least 1 octet). */
if (name + 1 > endp)
return KNOT_ESPACE;
if (name + 1 > endp) {
return KNOT_EMALF;
}
}
if (!is_compressed) /* Terminal label. */
if (!is_compressed) { /* Terminal label. */
wire_len += 1;
}
return wire_len;
}
......@@ -96,8 +128,9 @@ _public_
knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos,
knot_mm_t *mm)
{
if (pkt == NULL || pos == NULL)
if (pkt == NULL || pos == NULL) {
return NULL;
}
const uint8_t *name = pkt + *pos;
const uint8_t *endp = pkt + maxpos;
......@@ -114,7 +147,7 @@ knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos,
/* Allocate space for the name. */
knot_dname_t *res = mm_alloc(mm, decompressed_len);
if (res) {
if (res != NULL) {
/* Unpack name (expand compression pointers). */
if (knot_dname_unpack(res, name, decompressed_len, pkt) > 0) {
*pos += parsed;
......@@ -128,26 +161,32 @@ knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos,
}
_public_
knot_dname_t *knot_dname_copy(const knot_dname_t *name, knot_mm_t *mm)
size_t knot_dname_store(knot_dname_storage_t *dst, const knot_dname_t *name)
{
if (name == NULL)
return NULL;
if (dst == NULL || name == NULL) {
return 0;
}
return knot_dname_copy_part(name, knot_dname_size(name), mm);
size_t len = knot_dname_size(name);
assert(len <= KNOT_DNAME_MAXLEN);
memcpy(dst->data, name, len);
return len;
}
_public_
knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len,
knot_mm_t *mm)
knot_dname_t *knot_dname_copy(const knot_dname_t *name, knot_mm_t *mm)
{
if (name == NULL || len == 0)
if (name == NULL) {
return NULL;
}
size_t len = knot_dname_size(name);
knot_dname_t *dst = mm_alloc(mm, len);
if (knot_dname_to_wire(dst, name, len) < 1) {
mm_free(mm, dst);
if (dst == NULL) {
return NULL;
}
memcpy(dst, name, len);
return dst;
}
......@@ -163,8 +202,8 @@ int knot_dname_to_wire(uint8_t *dst, const knot_dname_t *src, size_t maxlen)
if (len > maxlen) {
return KNOT_ESPACE;
}
memcpy(dst, src, len);
return len;
}
......@@ -172,8 +211,9 @@ _public_
int knot_dname_unpack(uint8_t *dst, const knot_dname_t *src,
size_t maxlen, const uint8_t *pkt)
{
if (dst == NULL || src == NULL)
if (dst == NULL || src == NULL) {
return KNOT_EINVAL;
}
/* Seek first real label occurrence. */
src = knot_wire_seek_label(src, pkt);
......@@ -182,16 +222,18 @@ int knot_dname_unpack(uint8_t *dst, const knot_dname_t *src,
int len = 0;
while (*src != '\0') {
uint8_t lblen = *src + 1;
if (len + lblen > maxlen)
if (len + lblen > maxlen) {
return KNOT_ESPACE;
}
memcpy(dst + len, src, lblen);
len += lblen;
src = knot_wire_next_label(src, pkt);
}
/* Terminal label */
if (len + 1 > maxlen)
if (len + 1 > maxlen) {
return KNOT_EINVAL;
}
*(dst + len) = '\0';
return len + 1;
......@@ -441,23 +483,19 @@ dname_from_str_failed:
}
_public_
int knot_dname_to_lower(knot_dname_t *name)
void knot_dname_to_lower(knot_dname_t *name)
{
if (name == NULL)
return KNOT_EINVAL;
if (name == NULL) {
return;
}
while (*name != '\0') {
uint8_t len = *name;
for (uint8_t i = 1; i <= len; ++i) {
name[i] = knot_tolower(name[i]);
}
name = (uint8_t *)knot_wire_next_label(name, NULL);
if (name == NULL) { /* Must not be used on compressed names. */
return KNOT_EMALF;
}
name += 1 + len;
}
return KNOT_EOK;
}
_public_
......@@ -519,7 +557,7 @@ bool knot_dname_is_sub(const knot_dname_t *sub, const knot_dname_t *domain)
}
/* Align end-to-end to common suffix. */
int common = knot_dname_align(&sub, sub_l, &domain, domain_l, NULL);
int common = dname_align(&sub, sub_l, &domain, domain_l);
/* Compare common suffix. */
while (common > 0) {
......@@ -532,6 +570,7 @@ bool knot_dname_is_sub(const knot_dname_t *sub, const knot_dname_t *domain)
domain = knot_wire_next_label(domain, NULL);
--common;
}
return true;
}
......@@ -541,16 +580,6 @@ bool knot_dname_in(const knot_dname_t *domain, const knot_dname_t *sub)
return knot_dname_is_equal(domain, sub) || knot_dname_is_sub(sub, domain);
}
_public_
bool knot_dname_is_wildcard(const knot_dname_t *name)
{
if (name == NULL) {
return false;
}
return name[0] == 1 && name[1] == '*';
}
_public_
size_t knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2)
{
......@@ -562,7 +591,7 @@ size_t knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2)
}
/* Align end-to-end to common suffix. */
int common = knot_dname_align(&d1, l1, &d2, l2, NULL);
int common = dname_align(&d1, l1, &d2, l2);
/* Count longest chain leading to root label. */
size_t matched = 0;
......@@ -584,7 +613,7 @@ size_t knot_dname_matched_labels(const knot_dname_t *d1, const knot_dname_t *d2)
_public_
knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned labels,
const knot_dname_t *suffix)
const knot_dname_t *suffix, knot_mm_t *mm)
{
if (name == NULL) {
return NULL;
......@@ -605,7 +634,7 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label
/* Create target name. */
size_t new_len = prefix_len + suffix_len;
knot_dname_t *out = malloc(new_len);
knot_dname_t *out = mm_alloc(mm, new_len);
if (out == NULL) {
return NULL;
}
......@@ -625,6 +654,7 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label
dst += *suffix + 1;
suffix = knot_wire_next_label(suffix, NULL);
}
*dst = '\0';
return out;
}
......@@ -632,8 +662,9 @@ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned label
_public_
void knot_dname_free(knot_dname_t **name, knot_mm_t *mm)
{
if (name == NULL || *name == NULL)
if (name == NULL || *name == NULL) {
return;
}
mm_free(mm, *name);
*name = NULL;
......@@ -717,22 +748,6 @@ bool knot_dname_label_is_equal(const uint8_t *label1, const uint8_t *label2)
return true;
}
_public_
knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2)
{
if (d1 == NULL || d2 == NULL)
return NULL;
/* This is problem equal to replacing last \x00 from d1 with d2. */
knot_dname_t *ret = knot_dname_replace_suffix(d1, 0, d2);
/* Like if we are reallocating d1. */
if (ret != NULL)
knot_dname_free(&d1, NULL);
return ret;
}
_public_
size_t knot_dname_prefixlen(const uint8_t *name, unsigned nlabels, const uint8_t *pkt)
{
......@@ -775,24 +790,8 @@ size_t knot_dname_labels(const uint8_t *name, const uint8_t *pkt)
return 0;
}
}
return count;
}
_public_
int knot_dname_align(const uint8_t **d1, uint8_t d1_labels,
const uint8_t **d2, uint8_t d2_labels,
uint8_t *wire)
{
if (d1 == NULL || d2 == NULL)
return KNOT_EINVAL;
for (unsigned j = d1_labels; j < d2_labels; ++j)
*d2 = knot_wire_next_label(*d2, wire);
for (unsigned j = d2_labels; j < d1_labels; ++j)
*d1 = knot_wire_next_label(*d1, wire);
return (d1_labels < d2_labels) ? d1_labels : d2_labels;
return count;
}
_public_
......
......@@ -45,13 +45,13 @@ typedef union {
*
* If the name passes such checks, it is safe to be used in rest of the functions.
*
* \param name Name on the wire.
* \param endp Name boundary.
* \param pkt Wire.
* \param name Name on the wire.
* \param endp Name boundary.
* \param pkt Wire.
*
* \retval (compressed) size of the domain name.
* \retval KNOT_EINVAL
* \retval KNOT_EMALF
* \retval KNOT_ESPACE
*/
_pure_ _mustcheck_
int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp,
......@@ -60,10 +60,10 @@ int knot_dname_wire_check(const uint8_t *name, const uint8_t *endp,
/*!
* \brief Parse dname from wire.
*
* \param pkt Message in wire format.
* \param pos Position of the domain name on wire.
* \param maxpos Domain name length.
* \param mm Memory context.
* \param pkt Message in wire format.
* \param pos Position of the domain name on wire.
* \param maxpos Domain name length.
* \param mm Memory context.
*
* \return parsed domain name or NULL.
*/
......@@ -72,35 +72,34 @@ knot_dname_t *knot_dname_parse(const uint8_t *pkt, size_t *pos, size_t maxpos,
knot_mm_t *mm);
/*!
* \brief Duplicates the given domain name.
* \brief Duplicates the given domain name to a local storage.
*
* \param name Domain name to be copied.
* \param mm Memory context.
* \param dst Destination storage.
* \param name Domain name to be copied.
*
* \return New domain name which is an exact copy of \a dname.
* \retval size of the domain name.
* \retval 0 if invalid argument.
*/
_mustcheck_
knot_dname_t *knot_dname_copy(const knot_dname_t *name, knot_mm_t *mm);
size_t knot_dname_store(knot_dname_storage_t *dst, const knot_dname_t *name);
/*!
* \brief Duplicates part of the given domain name.
* \brief Duplicates the given domain name.
*
* \param name Domain name to be copied.
* \param len Part length.
* \param mm Memory context.
* \param name Domain name to be copied.
* \param mm Memory context.
*
* \return New domain name which is an partial copy of \a dname.
* \return New domain name which is an exact copy of \a name.
*/
_mustcheck_
knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len,
knot_mm_t *mm);
knot_dname_t *knot_dname_copy(const knot_dname_t *name, knot_mm_t *mm);
/*!
* \brief Copy name to wire as is, no compression pointer expansion will be done.
*
* \param dst Destination wire.
* \param src Source name.
* \param maxlen Maximum wire length.
* \param dst Destination wire.
* \param src Source name.
* \param maxlen Maximum wire length.
*
* \return number of bytes written
*/
......@@ -115,10 +114,10 @@ int knot_dname_to_wire(uint8_t *dst, const knot_dname_t *src, size_t maxlen);
* And you want to use knot_dname_to_wire() if you know the name is not
* compressed or you want to copy it 1:1.
*
* \param dst Destination wire.
* \param src Source name.
* \param maxlen Maximum destination wire size.
* \param pkt Name packet wire (for compression pointers).
* \param dst Destination wire.
* \param src Source name.
* \param maxlen Maximum destination wire size.
* \param pkt Name packet wire (for compression pointers).
*
* \return number of bytes written
*/
......@@ -130,9 +129,9 @@ int knot_dname_unpack(uint8_t *dst, const knot_dname_t *src,
*
* \note Output buffer is allocated automatically if dst is NULL.
*
* \param dst Output buffer.
* \param name Domain name to be converted.
* \param maxlen Output buffer length.
* \param dst Output buffer.
* \param name Domain name to be converted.
* \param maxlen Output buffer length.
*
* \return 0-terminated string if successful, NULL if error.
*/
......@@ -177,14 +176,9 @@ static inline knot_dname_t *knot_dname_from_str_alloc(const char *name)
/*!
* \brief Convert name to lowercase.
*
* \note Name must not be compressed.
*
* \param name Domain name to be converted.
*
* \return KNOT_EOK
* \retval KNOT_EINVAL
* \param name Domain name to be converted.
*/
int knot_dname_to_lower(knot_dname_t *name);
void knot_dname_to_lower(knot_dname_t *name);
/*!
* \brief Returns size of the given domain name.
......@@ -192,7 +186,7 @@ int knot_dname_to_lower(knot_dname_t *name);
* \note If the domain name is compressed, the length of not compressed part
* is returned.
*
* \param name Domain name to get the size of.
* \param name Domain name to get the size of.
*
* \retval size of the domain name.
* \retval 0 if invalid argument.
......@@ -203,8 +197,8 @@ size_t knot_dname_size(const knot_dname_t *name);
/*!