mirror of
https://gitlab.nic.cz/knot/knot-dns.git
synced 2026-05-28 04:02:31 -04:00
RDATA lowercase: Converting in packet parsing + zone load.
Converting to lowercase when saving to zone proved insufficient, because case-insensitive comparison of RDATA would be needed in some scenarios - e.g. in IXFR (SOA replacement) and DDNS processing. Moved the conversion to packet parsing - all dnames in RDATA are converted to lowercase when parsed from wire. RDATA parsed from zone file are converted there (in scanner_process()). Later the conversion may be moved to a lower level of parsing (and with some option to turn it on/off). QNAME is unaffected by this change.
This commit is contained in:
parent
c29af675ab
commit
1761a1343d
5 changed files with 115 additions and 96 deletions
|
|
@ -347,3 +347,4 @@ tests/zone_events.c
|
|||
tests/zone_update.c
|
||||
tests/zonedb.c
|
||||
tests/ztree.c
|
||||
src/libknot/rrtype/naptr.h
|
||||
|
|
|
|||
|
|
@ -733,87 +733,14 @@ static bool rrset_is_nsec3rel(const knot_rrset_t *rr)
|
|||
== KNOT_RRTYPE_NSEC3));
|
||||
}
|
||||
|
||||
static size_t naptr_header_size(uint8_t *naptr, uint8_t *maxp)
|
||||
{
|
||||
/*! \todo Copy-pasted from rrset.c. Unify. */
|
||||
|
||||
size_t size = 0;
|
||||
|
||||
/* Fixed fields size (order, preference) */
|
||||
size += 2 * sizeof(uint16_t);
|
||||
|
||||
/* Variable fields size (flags, services, regexp) */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
uint8_t *len_ptr = naptr + size;
|
||||
assert(len_ptr < maxp);
|
||||
size += 1 + *len_ptr;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void convert_to_lowercase(knot_rrset_t *rrset)
|
||||
{
|
||||
int ret = knot_dname_to_lower(rrset->owner);
|
||||
assert(ret == KNOT_EOK);
|
||||
|
||||
const rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset->type);
|
||||
|
||||
for (int j = 0; j < rrset->rrs.rr_count; ++j) {
|
||||
knot_rdata_t *rdata = knot_rdataset_at(&rrset->rrs, j);
|
||||
|
||||
uint16_t rdlen = knot_rdata_rdlen(rdata);
|
||||
uint8_t *pos = knot_rdata_data(rdata);
|
||||
|
||||
for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; ++i) {
|
||||
int type = desc->block_types[i];
|
||||
switch (type) {
|
||||
case KNOT_RDATA_WF_COMPRESSIBLE_DNAME:
|
||||
case KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME:
|
||||
case KNOT_RDATA_WF_FIXED_DNAME:
|
||||
ret = knot_dname_to_lower(pos);
|
||||
assert(ret == KNOT_EOK);
|
||||
pos += knot_dname_size(pos);
|
||||
break;
|
||||
case KNOT_RDATA_WF_NAPTR_HEADER:
|
||||
pos += naptr_header_size(pos, rdata + rdlen);
|
||||
break;
|
||||
case KNOT_RDATA_WF_REMAINDER:
|
||||
break;
|
||||
default:
|
||||
/* Fixed size block */
|
||||
assert(type > 0);
|
||||
pos += type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static knot_rrset_t *rrset_to_lowercase(const knot_rrset_t *rrset)
|
||||
{
|
||||
knot_rrset_t *rr_l = knot_rrset_copy(rrset, NULL);
|
||||
if (rr_l != NULL) {
|
||||
convert_to_lowercase(rr_l);
|
||||
}
|
||||
|
||||
return rr_l;
|
||||
}
|
||||
|
||||
int zone_contents_add_rr(zone_contents_t *z, const knot_rrset_t *rr,
|
||||
zone_node_t **n)
|
||||
{
|
||||
/* Convert all dnames in RRSet to lowercase. */
|
||||
knot_rrset_t *rr_lc = rrset_to_lowercase(rr);
|
||||
if (z == NULL || rr == NULL) {
|
||||
return KNOT_EINVAL;
|
||||
}
|
||||
|
||||
int ret;
|
||||
if (rr_lc != NULL) {
|
||||
ret = insert_rr(z, rr_lc, n, rrset_is_nsec3rel(rr));
|
||||
knot_rrset_free(&rr_lc, NULL);
|
||||
} else {
|
||||
ret = KNOT_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return insert_rr(z, rr, n, rrset_is_nsec3rel(rr));
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "knot/zone/zonefile.h"
|
||||
#include "libknot/rdata.h"
|
||||
#include "knot/zone/zone-dump.h"
|
||||
#include "libknot/rrtype/naptr.h"
|
||||
|
||||
#define ERROR(zone, fmt...) log_zone_error(zone, "zone loader, " fmt)
|
||||
#define WARNING(zone, fmt...) log_zone_warning(zone, "zone loader, " fmt)
|
||||
|
|
@ -144,6 +145,43 @@ int zcreator_step(zcreator_t *zc, const knot_rrset_t *rr)
|
|||
return sem_fatal_error ? KNOT_ESEMCHECK : KNOT_EOK;
|
||||
}
|
||||
|
||||
static void convert_to_lowercase(knot_rrset_t *rrset)
|
||||
{
|
||||
int ret = knot_dname_to_lower(rrset->owner);
|
||||
assert(ret == KNOT_EOK);
|
||||
|
||||
const rdata_descriptor_t *desc = knot_get_rdata_descriptor(rrset->type);
|
||||
|
||||
for (int j = 0; j < rrset->rrs.rr_count; ++j) {
|
||||
knot_rdata_t *rdata = knot_rdataset_at(&rrset->rrs, j);
|
||||
|
||||
uint16_t rdlen = knot_rdata_rdlen(rdata);
|
||||
uint8_t *pos = knot_rdata_data(rdata);
|
||||
|
||||
for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; ++i) {
|
||||
int type = desc->block_types[i];
|
||||
switch (type) {
|
||||
case KNOT_RDATA_WF_COMPRESSIBLE_DNAME:
|
||||
case KNOT_RDATA_WF_DECOMPRESSIBLE_DNAME:
|
||||
case KNOT_RDATA_WF_FIXED_DNAME:
|
||||
ret = knot_dname_to_lower(pos);
|
||||
assert(ret == KNOT_EOK);
|
||||
pos += knot_dname_size(pos);
|
||||
break;
|
||||
case KNOT_RDATA_WF_NAPTR_HEADER:
|
||||
pos += naptr_header_size(pos, rdata + rdlen);
|
||||
break;
|
||||
case KNOT_RDATA_WF_REMAINDER:
|
||||
break;
|
||||
default:
|
||||
/* Fixed size block */
|
||||
assert(type > 0);
|
||||
pos += type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Creates RR from parser input, passes it to handling function. */
|
||||
static void scanner_process(zs_scanner_t *scanner)
|
||||
{
|
||||
|
|
@ -158,7 +196,6 @@ static void scanner_process(zs_scanner_t *scanner)
|
|||
zc->ret = KNOT_ENOMEM;
|
||||
return;
|
||||
}
|
||||
knot_dname_to_lower(owner);
|
||||
|
||||
knot_rrset_t rr;
|
||||
knot_rrset_init(&rr, owner, scanner->r_type, scanner->r_class);
|
||||
|
|
@ -174,6 +211,9 @@ static void scanner_process(zs_scanner_t *scanner)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Convert RDATA dnames to lowercase before adding to zone. */
|
||||
convert_to_lowercase(&rr);
|
||||
|
||||
zc->ret = zcreator_step(zc, &rr);
|
||||
knot_dname_free(&owner, NULL);
|
||||
knot_rdataset_clear(&rr.rrs, NULL);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "libknot/packet/rrset-wire.h"
|
||||
#include "libknot/packet/wire.h"
|
||||
#include "libknot/rrset.h"
|
||||
#include "libknot/rrtype/naptr.h"
|
||||
|
||||
/*!
|
||||
* \brief Get maximal size of a domain name in a wire with given capacity.
|
||||
|
|
@ -114,26 +115,14 @@ static int write_rdata_naptr_header(const uint8_t **src, size_t *src_avail,
|
|||
assert(dst && *dst);
|
||||
assert(dst_avail);
|
||||
|
||||
size_t size = 0;
|
||||
int ret = naptr_header_size(*src, *src + *src_avail);
|
||||
|
||||
/* Fixed fields size (order, preference) */
|
||||
|
||||
size += 2 * sizeof(uint16_t);
|
||||
|
||||
/* Variable fields size (flags, services, regexp) */
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const uint8_t *len_ptr = *src + size;
|
||||
if (len_ptr >= *src + *src_avail) {
|
||||
return KNOT_EMALF;
|
||||
}
|
||||
|
||||
size += 1 + *len_ptr;
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Copy the data */
|
||||
|
||||
return write_rdata_fixed(src, src_avail, dst, dst_avail, size);
|
||||
return write_rdata_fixed(src, src_avail, dst, dst_avail, ret);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -522,7 +511,7 @@ static int decompress_rdata_dname(const uint8_t **src, size_t *src_avail,
|
|||
assert(dst && *dst);
|
||||
assert(dst_avail);
|
||||
assert(dname_cfg);
|
||||
UNUSED(flags);
|
||||
UNUSED(dname_type);
|
||||
|
||||
int compr_size = knot_dname_wire_check(*src, *src + *src_avail, dname_cfg->pkt_wire);
|
||||
if (compr_size <= 0) {
|
||||
|
|
@ -533,6 +522,12 @@ static int decompress_rdata_dname(const uint8_t **src, size_t *src_avail,
|
|||
if (decompr_size <= 0) {
|
||||
return decompr_size;
|
||||
}
|
||||
|
||||
/* Convert to lowercase. */
|
||||
if (flags & KNOT_RRSET_WIRE_CANONICAL) {
|
||||
int ret = knot_dname_to_lower(*dst);
|
||||
assert(ret == KNOT_EOK);
|
||||
}
|
||||
|
||||
/* Update buffers */
|
||||
*dst += decompr_size;
|
||||
|
|
@ -597,7 +592,7 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
|
|||
};
|
||||
|
||||
int ret = rdata_traverse(&src, &src_avail, &dst, &dst_avail,
|
||||
desc, &dname_cfg, KNOT_RRSET_WIRE_NONE);
|
||||
desc, &dname_cfg, KNOT_RRSET_WIRE_CANONICAL);
|
||||
if (ret != KNOT_EOK) {
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
56
src/libknot/rrtype/naptr.h
Normal file
56
src/libknot/rrtype/naptr.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/* Copyright (C) 2014 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
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/*!
|
||||
* \file naptr.h
|
||||
*
|
||||
* \author Lubos Slovak <lubos.slovak@nic.cz>
|
||||
*
|
||||
* \brief Functions for manipulation of NAPTR RDATA.
|
||||
*
|
||||
* \addtogroup libknot
|
||||
* @{
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libknot/errcode.h"
|
||||
|
||||
static inline int naptr_header_size(const uint8_t *naptr, const uint8_t *maxp)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
/* Fixed fields size (order, preference) */
|
||||
size += 2 * sizeof(uint16_t);
|
||||
|
||||
/* Variable fields size (flags, services, regexp) */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
uint8_t *len_ptr = naptr + size;
|
||||
printf("Checking len_ptr = %p, maxp = %p\n",
|
||||
len_ptr, maxp);
|
||||
if (len_ptr >= maxp) {
|
||||
return KNOT_EMALF;
|
||||
}
|
||||
size += 1 + *len_ptr;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
Loading…
Reference in a new issue