Commit 1761a134 authored by Lubos Slovak's avatar Lubos Slovak

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.
parent c29af675
......@@ -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);
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;
if (z == NULL || rr == NULL) {
return KNOT_EINVAL;
}
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;
}
......
/* 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;
}
/*! @} */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment