From b5144390fe90bc651a54aac13cfb49e31dcc2066 Mon Sep 17 00:00:00 2001 From: Jan Kadlec <jan.kadlec@nic.cz> Date: Mon, 24 Feb 2014 12:32:14 +0100 Subject: [PATCH] Parse RRs with 0 length and store TTL into them. - Most changes were in ddns.c: Empty checks used rr_count == 0 --- src/knot/updates/ddns.c | 38 ++++++++++++++++---------------------- src/libknot/edns.c | 18 ++++++++---------- src/libknot/edns.h | 3 +-- src/libknot/packet/pkt.c | 14 ++++++-------- src/libknot/rrset.c | 10 ++-------- 5 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/knot/updates/ddns.c b/src/knot/updates/ddns.c index 540919317..714e55d9b 100644 --- a/src/knot/updates/ddns.c +++ b/src/knot/updates/ddns.c @@ -30,6 +30,18 @@ #include "knot/updates/xfr-in.h" #include "common/descriptor.h" +static bool rrset_empty(const knot_rrset_t *rrset) +{ + uint16_t rr_count = knot_rrset_rr_count(rrset); + if (rr_count == 0) { + return true; + } + if (rr_count == 1) { + return knot_rrset_rr_size(rrset, 0) == 0; + } + return false; +} + /*----------------------------------------------------------------------------*/ // Copied from XFR - maybe extract somewhere else static int knot_ddns_prereq_check_rrsets(knot_rrset_t ***rrsets, @@ -143,7 +155,7 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs, int ret; if (knot_rrset_class(rrset) == KNOT_CLASS_ANY) { - if (knot_rrset_rr_count(rrset)) { + if (!rrset_empty(rrset)) { dbg_ddns("ddns: add_prereq: Extra data\n"); return KNOT_EMALF; } @@ -159,7 +171,7 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs, &prereqs->exist_allocd); } } else if (knot_rrset_class(rrset) == KNOT_CLASS_NONE) { - if (knot_rrset_rr_count(rrset)) { + if (!rrset_empty(rrset)) { dbg_ddns("ddns: add_prereq: Extra data\n"); return KNOT_EMALF; } @@ -195,7 +207,6 @@ static int knot_ddns_check_exist(const knot_zone_contents_t *zone, assert(zone != NULL); assert(rrset != NULL); assert(rcode != NULL); - assert(knot_rrset_rr_count(rrset) == 0); assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY); assert(knot_rrset_class(rrset) == KNOT_CLASS_ANY); @@ -269,7 +280,6 @@ static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone, assert(zone != NULL); assert(rrset != NULL); assert(rcode != NULL); - assert(knot_rrset_rr_count(rrset) == 0); assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY); assert(knot_rrset_class(rrset) == KNOT_CLASS_NONE); @@ -505,7 +515,7 @@ static int knot_ddns_check_update(const knot_rrset_t *rrset, return KNOT_EMALF; } } else if (knot_rrset_class(rrset) == KNOT_CLASS_ANY) { - if (knot_rrset_rr_count(rrset) + if (!rrset_empty(rrset) || (knot_rrtype_is_metatype(knot_rrset_type(rrset)) && knot_rrset_type(rrset) != KNOT_RRTYPE_ANY)) { *rcode = KNOT_RCODE_FORMERR; @@ -607,7 +617,7 @@ dbg_ddns_exec_detail( ); if (knot_dname_is_equal(knot_rrset_owner(rrset), owner)) { // Removing one or all RRSets - if ((knot_rrset_rr_count(rr) == 0) + if (rrset_empty(rr) && (knot_rrset_type(rr) == knot_rrset_type(rrset) || knot_rrset_type(rr) == KNOT_RRTYPE_ANY)) { dbg_ddns_detail("Removing one or all RRSets\n"); @@ -719,21 +729,6 @@ static int knot_ddns_process_add_cname(knot_node_t *node, return ret; } - /* TODO: signing will take care of this. If signing is off, then, oh well. */ -// if (knot_node_rrtype_is_signed(node, removed->type)) { -// assert(0); -// ret = knot_changes_add_rrset(changes, -// removed->rrsigs, -// KNOT_CHANGES_OLD); -// if (ret != KNOT_EOK) { -// dbg_ddns("Failed to add removed RRSIGs to " -// "'changes': %s\n", knot_strerror(ret)); -// return ret; -// } -// /* Disconnect RRsigs from rrset. */ -// knot_rrset_set_rrsigs(removed, NULL); -// } - /* c) And remove it from the node. */ UNUSED(knot_node_remove_rrset(node, KNOT_RRTYPE_CNAME)); @@ -1633,7 +1628,6 @@ static int knot_ddns_process_rr(const knot_rrset_t *rr, changes); } } else { - assert(0); return KNOT_ERROR; } } diff --git a/src/libknot/edns.c b/src/libknot/edns.c index 5a82f9ab2..2df9efa0e 100644 --- a/src/libknot/edns.c +++ b/src/libknot/edns.c @@ -52,11 +52,11 @@ knot_opt_rr_t *knot_edns_new() /*----------------------------------------------------------------------------*/ -int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset, - uint32_t rr_ttl) +int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset) { if (opt_rr == NULL || rrset == NULL - || knot_rrset_type(rrset) != KNOT_RRTYPE_OPT) { + || knot_rrset_type(rrset) != KNOT_RRTYPE_OPT || + knot_rrset_rr_count(rrset) == 0) { return KNOT_EINVAL; } @@ -68,10 +68,10 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset, opt_rr->payload = EDNS_MIN_UDP_PAYLOAD; } - // the TTL has switched bytes + // TTL has switched bytes uint32_t ttl; - dbg_edns_detail("TTL: %u\n", rr_ttl); - knot_wire_write_u32((uint8_t *)&ttl, rr_ttl); + dbg_edns_detail("TTL: %u\n", knot_rrset_rr_ttl(rrset, 0)); + knot_wire_write_u32((uint8_t *)&ttl, knot_rrset_rr_ttl(rrset, 0)); // first byte of TTL is extended RCODE dbg_edns_detail("TTL: %u\n", ttl); memcpy(&opt_rr->ext_rcode, &ttl, 1); @@ -87,12 +87,10 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset, int rc = 0; dbg_edns_verb("Parsing options.\n"); - uint8_t *raw = knot_rrset_rr_rdata(rrset, 0); uint16_t size = knot_rrset_rr_size(rrset, 0); - - if (raw != NULL) { + if (size > 0) { + uint8_t *raw = knot_rrset_rr_rdata(rrset, 0); size_t pos = 0; - assert(size > 0); while (pos < size) { // ensure there is enough data to parse the OPTION CODE // and OPTION LENGTH diff --git a/src/libknot/edns.h b/src/libknot/edns.h index cc7cfc943..1518080b5 100644 --- a/src/libknot/edns.h +++ b/src/libknot/edns.h @@ -110,8 +110,7 @@ knot_opt_rr_t *knot_edns_new(); * \retval KNOT_EINVAL * \retval KNOT_EMALF */ -int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset, - uint32_t rr_ttl); +int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr, const knot_rrset_t *rrset); /*! * \brief Returns the UDP payload stored in the OPT RR. diff --git a/src/libknot/packet/pkt.c b/src/libknot/packet/pkt.c index d10512e9a..bbcd5dba1 100644 --- a/src/libknot/packet/pkt.c +++ b/src/libknot/packet/pkt.c @@ -670,8 +670,7 @@ static int knot_pkt_merge_rr(knot_pkt_t *pkt, knot_rrset_t *rr, unsigned flags) * should be copied if they are supposed to be stored in zone permanently. */ static knot_rrset_t *knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos, - size_t size, uint32_t *ttl, - mm_ctx_t *mm) + size_t size, mm_ctx_t *mm) { dbg_packet("%s(%p, %zu, %zu)\n", __func__, wire, *pos, size); assert(wire); @@ -691,7 +690,7 @@ static knot_rrset_t *knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos, uint16_t type = knot_wire_read_u16(wire + *pos); uint16_t rclass = knot_wire_read_u16(wire + *pos + sizeof(uint16_t)); - *ttl = knot_wire_read_u32(wire + *pos + 2 * sizeof(uint16_t)); + uint32_t ttl = knot_wire_read_u32(wire + *pos + 2 * sizeof(uint16_t)); uint16_t rdlength = knot_wire_read_u16(wire + *pos + 4 * sizeof(uint16_t)); knot_rrset_t *rrset = knot_rrset_new(owner, type, rclass, mm); @@ -702,7 +701,7 @@ static knot_rrset_t *knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos, *pos += KNOT_RR_HEADER_SIZE; dbg_packet_verb("%s: read type %u, class %u, ttl %u, rdlength %u\n", - __func__, rrset->type, rrset->rclass, *ttl, rdlength); + __func__, rrset->type, rrset->rclass, ttl, rdlength); if (size - *pos < rdlength) { dbg_packet("%s: not enough data to parse RDATA\n", __func__); @@ -713,7 +712,7 @@ static knot_rrset_t *knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos, // parse RDATA /*! \todo Merge with add_rdata_to_rr in zcompile, should be a rrset func * probably. */ - int ret = knot_rrset_rdata_from_wire_one(rrset, wire, pos, size, *ttl, + int ret = knot_rrset_rdata_from_wire_one(rrset, wire, pos, size, ttl, rdlength, mm); if (ret != KNOT_EOK) { dbg_packet("%s: couldn't parse RDATA (%d)\n", __func__, ret); @@ -745,9 +744,8 @@ int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags) /* Parse wire format. */ size_t rr_size = pkt->parsed; knot_rrset_t *rr = NULL; - uint32_t rr_ttl = 0; rr = knot_pkt_rr_from_wire(pkt->wire, &pkt->parsed, pkt->max_size, - &rr_ttl, &pkt->mm); + &pkt->mm); if (rr == NULL) { dbg_packet("%s: failed to parse RR\n", __func__); return KNOT_EMALF; @@ -790,7 +788,7 @@ int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags) pkt->tsig_rr = rr; break; case KNOT_RRTYPE_OPT: - ret = knot_edns_new_from_rr(&pkt->opt_rr, rr, rr_ttl); + ret = knot_edns_new_from_rr(&pkt->opt_rr, rr); if (ret != KNOT_EOK) { dbg_packet("%s: couldn't parse OPT RR = %d\n", __func__, ret); diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c index cfb2be7a8..15f1385e7 100644 --- a/src/libknot/rrset.c +++ b/src/libknot/rrset.c @@ -852,14 +852,8 @@ int knot_rrset_rdata_from_wire_one(knot_rrset_t *rrset, } if (rdlength == 0) { - /* Nothing to parse, APLs can have 0 RDLENGTH, but only APLs. */ - if (rrset->type == KNOT_RRTYPE_APL) { - // Add empty RDATA - return knot_rrset_create_rr(rrset, 0, ttl, mm) == NULL ? - KNOT_ENOMEM : KNOT_EOK; - } else { - return KNOT_EOK; - } + return knot_rrset_create_rr(rrset, 0, ttl, mm) == NULL ? + KNOT_ENOMEM : KNOT_EOK; } dbg_rrset_detail("rr: parse_rdata_wire: Parsing RDATA of size=%zu," -- GitLab