Commit 77dda7b9 authored by Marek Vavruša's avatar Marek Vavruša

lib: zone cut api supports multi-rdata RR sets

parent 2137068f
......@@ -12,8 +12,6 @@ libkresolve_static_la_SOURCES = \
layer/stats.h \
layer/stats.c \
layer.h \
utils.h \
utils.c \
context.h \
context.c \
resolve.h \
......
......@@ -24,7 +24,7 @@
#include "lib/layer/iterate.h"
#include "lib/resolve.h"
#include "lib/rplan.h"
#include "lib/utils.h"
#include "lib/defines.h"
#ifndef NDEBUG
#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[qiter] " fmt, ## __VA_ARGS__)
......@@ -33,7 +33,7 @@
#endif
/* Iterator often walks through packet section, this is an abstraction. */
typedef int (*rr_callback_t)(const knot_rrset_t *, struct kr_layer_param *);
typedef int (*rr_callback_t)(const knot_rrset_t *, unsigned, struct kr_layer_param *);
/*! \brief Return minimized QNAME/QTYPE for current zone cut. */
static const knot_dname_t *minimized_qname(struct kr_query *query, uint16_t *qtype)
......@@ -86,7 +86,7 @@ static void follow_cname_chain(const knot_dname_t **cname, const knot_rrset_t *r
}
}
static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query)
static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query, uint16_t index)
{
if (rr == NULL || query == NULL) {
return KNOT_NS_PROC_MORE; /* Ignore */
......@@ -94,7 +94,7 @@ static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query)
if (rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA) {
if (knot_dname_is_equal(query->zone_cut.ns, rr->owner)) {
int ret = kr_rrset_to_addr(&query->zone_cut.addr, rr);
int ret = kr_set_zone_cut_addr(&query->zone_cut, rr, index);
if (ret == KNOT_EOK) {
return KNOT_NS_PROC_DONE;
}
......@@ -104,44 +104,39 @@ static int update_nsaddr(const knot_rrset_t *rr, struct kr_query *query)
return KNOT_NS_PROC_MORE;
}
static int update_glue(const knot_rrset_t *rr, struct kr_layer_param *param)
static int update_glue(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
{
return update_nsaddr(rr, kr_rplan_current(param->rplan));
return update_nsaddr(rr, kr_rplan_current(param->rplan), hint);
}
int rr_update_parent(const knot_rrset_t *rr, struct kr_layer_param *param)
int rr_update_parent(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
{
struct kr_query *query = kr_rplan_current(param->rplan);
return update_nsaddr(rr, query->parent);
return update_nsaddr(rr, query->parent, hint);
}
int rr_update_answer(const knot_rrset_t *rr, struct kr_layer_param *param)
int rr_update_answer(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
{
knot_pkt_t *answer = param->answer;
knot_rrset_t *rr_copy = knot_rrset_copy(rr, &answer->mm);
if (rr_copy == NULL) {
return KNOT_NS_PROC_FAIL;
}
/* Write copied RR to the result packet. */
int ret = knot_pkt_put(answer, KNOT_COMPR_HINT_NONE, rr_copy, KNOT_PF_FREE);
int ret = knot_pkt_put(answer, KNOT_COMPR_HINT_NONE, rr, hint);
if (ret != KNOT_EOK) {
knot_rrset_free(&rr_copy, &answer->mm);
if (hint & KNOT_PF_FREE) {
knot_rrset_clear((knot_rrset_t *)rr, &answer->mm);
}
knot_wire_set_tc(answer->wire);
return KNOT_NS_PROC_DONE;
}
/* Free just the allocated container. */
mm_free(&answer->mm, rr_copy);
/* Update parent query as well. */
return rr_update_parent(rr, param);
return rr_update_parent(rr, hint, param);
}
int rr_update_nameserver(const knot_rrset_t *rr, struct kr_layer_param *param)
int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param)
{
struct kr_query *query = kr_rplan_current(param->rplan);
const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, 0);
const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, hint);
/* Authority MUST be at/below the authority of the nameserver, otherwise
* possible cache injection attempt. */
......@@ -177,7 +172,7 @@ static int process_authority(knot_pkt_t *pkt, struct kr_layer_param *param)
continue;
}
state = rr_update_nameserver(rr, param);
state = rr_update_nameserver(rr, 0, param);
if (state != KNOT_NS_PROC_MORE) {
break;
}
......@@ -194,7 +189,7 @@ static int process_additional(knot_pkt_t *pkt, struct kr_layer_param *param)
const knot_pktsection_t *ar = knot_pkt_section(pkt, KNOT_ADDITIONAL);
for (unsigned i = 0; i < ar->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(ar, i);
int state = update_glue(rr, param);
int state = update_glue(rr, 0, param);
if (state != KNOT_NS_PROC_MORE) {
return state;
}
......@@ -235,7 +230,7 @@ static int process_answer(knot_pkt_t *pkt, struct kr_layer_param *param)
const knot_pktsection_t *an = knot_pkt_section(pkt, KNOT_ANSWER);
for (unsigned i = 0; i < an->count; ++i) {
const knot_rrset_t *rr = knot_pkt_rr(an, i);
int state = callback(rr, param);
int state = callback(rr, 0, param);
if (state == KNOT_NS_PROC_FAIL) {
return state;
}
......
......@@ -22,11 +22,20 @@
const knot_layer_api_t *layer_iterate_module(void);
#define LAYER_ITERATE layer_iterate_module()
/*! \brief Result updates the query parent. */
int rr_update_parent(const knot_rrset_t *rr, struct kr_layer_param *param);
/*!
* \brief Result updates the query parent.
* \note Hint is an index of chosen RR in the set.
*/
int rr_update_parent(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param);
/*! \brief Result updates the original query response. */
int rr_update_answer(const knot_rrset_t *rr, struct kr_layer_param *param);
/*!
* \brief Result updates the original query response.
* \note When \a hint is KNOT_PF_FREE, RR is treated as a copy and answer takes its ownership.
*/
int rr_update_answer(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param);
/*! \brief Result updates current nameserver. */
int rr_update_nameserver(const knot_rrset_t *rr, struct kr_layer_param *param);
/*!
* \brief Result updates current nameserver.
* \note Hint is an index of chosen RR in the set.
*/
int rr_update_nameserver(const knot_rrset_t *rr, unsigned hint, struct kr_layer_param *param);
......@@ -22,7 +22,6 @@
#include "lib/layer/static.h"
#include "lib/layer/iterate.h"
#include "lib/utils.h"
#ifndef NDEBUG
#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[cache] " fmt, ## __VA_ARGS__)
......@@ -34,7 +33,16 @@ typedef int (*rr_callback_t)(const knot_rrset_t *, unsigned, struct kr_layer_par
static int update_parent(const knot_rrset_t *rr, unsigned drift, struct kr_layer_param *param)
{
return rr_update_parent(rr, param);
/* Find a first non-expired record. */
uint16_t i = 0;
for (; i < rr->rrs.rr_count; ++i) {
knot_rdata_t *rd = knot_rdataset_at(&rr->rrs, i);
if (knot_rdata_ttl(rd) > drift) {
break;
}
}
return rr_update_parent(rr, i, param);
}
static int update_answer(const knot_rrset_t *rr, unsigned drift, struct kr_layer_param *param)
......
......@@ -23,7 +23,6 @@
#include "lib/resolve.h"
#include "lib/defines.h"
#include "lib/utils.h"
#include "lib/layer/itercache.h"
#include "lib/layer/iterate.h"
#include "lib/layer/static.h"
......
......@@ -23,7 +23,7 @@
#include "lib/rplan.h"
#include "lib/context.h"
#include "lib/cache.h"
#include "lib/utils.h"
#include "lib/defines.h"
#ifndef NDEBUG
#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[rplan] " fmt, ## __VA_ARGS__)
......
#include <libknot/descriptor.h>
#include <libknot/rrtype/aaaa.h>
#include <assert.h>
#include "lib/utils.h"
int kr_rrset_to_addr(struct sockaddr_storage *ss, const knot_rrset_t *rr)
{
int ret = KNOT_EOK;
/* Retrieve an address from glue record. */
switch(rr->type) {
case KNOT_RRTYPE_A:
ret = knot_a_addr(&rr->rrs, 0, (struct sockaddr_in *)ss);
break;
case KNOT_RRTYPE_AAAA:
ret = knot_aaaa_addr(&rr->rrs, 0, (struct sockaddr_in6 *)ss);
break;
default:
return KNOT_EINVAL;
}
sockaddr_port_set(ss, KR_DNS_PORT);
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/>.
*/
#pragma once
#include <libknot/rrset.h>
#include <libknot/internal/sockaddr.h>
#include "lib/defines.h"
/*!
* \brief Convert A/AAAA RRs to address with DNS port.
* \param ss address storage
* \param rr resource record
* \return KNOT_E*
*/
int kr_rrset_to_addr(struct sockaddr_storage *ss, const knot_rrset_t *rr);
......@@ -18,10 +18,12 @@
#include <libknot/descriptor.h>
#include <libknot/rrtype/rdname.h>
#include <libknot/packet/wire.h>
#include <libknot/descriptor.h>
#include <libknot/rrtype/aaaa.h>
#include "lib/zonecut.h"
#include "lib/utils.h"
#include "lib/rplan.h"
#include "lib/defines.h"
#ifndef NDEBUG
#define DEBUG_MSG(fmt, ...) fprintf(stderr, "[z-cut] " fmt, ## __VA_ARGS__)
......@@ -118,6 +120,25 @@ int kr_set_zone_cut(struct kr_zonecut *cut, const knot_dname_t *name, const knot
return KNOT_EOK;
}
int kr_set_zone_cut_addr(struct kr_zonecut *cut, const knot_rrset_t *rr, uint16_t i)
{
int ret = KNOT_EOK;
switch(rr->type) {
case KNOT_RRTYPE_A:
ret = knot_a_addr(&rr->rrs, i, (struct sockaddr_in *)&cut->addr);
break;
case KNOT_RRTYPE_AAAA:
ret = knot_aaaa_addr(&rr->rrs, i, (struct sockaddr_in6 *)&cut->addr);
break;
default:
return KNOT_EINVAL;
}
sockaddr_port_set(&cut->addr, KR_DNS_PORT);
return ret;
}
int kr_find_zone_cut(struct kr_zonecut *cut, const knot_dname_t *name, namedb_txn_t *txn, uint32_t timestamp)
{
if (cut == NULL || name == NULL) {
......
......@@ -32,6 +32,13 @@ struct kr_zonecut {
struct sockaddr_storage addr; /*!< Authoritative NS address. */
};
/*!
* \brief Initialize zone cut with SBELT.
* \param cut zone cut to be set
* \return KNOT_E*
*/
int kr_init_zone_cut(struct kr_zonecut *cut);
/*!
* \brief Set zone cut to given name and name server.
* \note Name server address is blanked.
......@@ -42,6 +49,15 @@ struct kr_zonecut {
*/
int kr_set_zone_cut(struct kr_zonecut *cut, const knot_dname_t *name, const knot_dname_t *ns);
/*!
* \brief Convert A/AAAA RRs to address with DNS port.
* \param cut zone cut to be set
* \param rr resource record
* \param i index of the set address in the rr
* \return KNOT_E*
*/
int kr_set_zone_cut_addr(struct kr_zonecut *cut, const knot_rrset_t *rr, uint16_t i);
/*!
* \brief Find the closest enclosing zone cut/nameserver from the cache.
* \param cut zone cut to be set
......@@ -51,3 +67,4 @@ int kr_set_zone_cut(struct kr_zonecut *cut, const knot_dname_t *name, const knot
* \return KNOT_E*
*/
int kr_find_zone_cut(struct kr_zonecut *cut, const knot_dname_t *name, namedb_txn_t *txn, uint32_t timestamp);
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