Commit 97b04676 authored by Daniel Salzman's avatar Daniel Salzman

nameserver: unify axfr and ixfr source files

parent bab62de8
......@@ -18,13 +18,10 @@
#include "contrib/mempattern.h"
#include "contrib/sockaddr.h"
#include "knot/common/log.h"
#include "knot/conf/conf.h"
#include "knot/nameserver/axfr.h"
#include "knot/nameserver/internet.h"
#include "knot/nameserver/log.h"
#include "knot/nameserver/xfr.h"
#include "knot/zone/zonefile.h"
#include "libknot/libknot.h"
#define ZONE_NAME(qdata) knot_pkt_qname((qdata)->query)
......@@ -32,7 +29,7 @@
#define AXFROUT_LOG(priority, qdata, fmt...) \
ns_log(priority, ZONE_NAME(qdata), LOG_OPERATION_AXFR, \
LOG_DIRECTION_OUT, REMOTE(qdata), fmt)
LOG_DIRECTION_OUT, REMOTE(qdata), fmt)
/* AXFR context. @note aliasing the generic xfr_proc */
struct axfr_proc {
......@@ -46,28 +43,24 @@ static int axfr_put_rrsets(knot_pkt_t *pkt, zone_node_t *node,
{
assert(node != NULL);
int ret = KNOT_EOK;
int i = state->cur_rrset;
uint16_t rrset_count = node->rrset_count;
unsigned flags = KNOT_PF_NOTRUNC;
/* Append all RRs. */
for (;i < rrset_count; ++i) {
for (unsigned i = state->cur_rrset; i < node->rrset_count; ++i) {
knot_rrset_t rrset = node_rrset_at(node, i);
if (rrset.type == KNOT_RRTYPE_SOA) {
continue;
}
ret = knot_pkt_put(pkt, 0, &rrset, flags);
/* If something failed, remember the current RR for later. */
int ret = knot_pkt_put(pkt, 0, &rrset, KNOT_PF_NOTRUNC);
if (ret != KNOT_EOK) {
/* If something failed, remember the current RR for later. */
state->cur_rrset = i;
return ret;
}
}
state->cur_rrset = 0;
return ret;
return KNOT_EOK;
}
static int axfr_process_node_tree(knot_pkt_t *pkt, const void *item,
......@@ -83,9 +76,8 @@ static int axfr_process_node_tree(knot_pkt_t *pkt, const void *item,
/* Put responses. */
int ret = KNOT_EOK;
zone_node_t *node = NULL;
while (!trie_it_finished(axfr->i)) {
node = (zone_node_t *)*trie_it_val(axfr->i);
zone_node_t *node = (zone_node_t *)*trie_it_val(axfr->i);
ret = axfr_put_rrsets(pkt, node, axfr);
if (ret != KNOT_EOK) {
break;
......@@ -129,8 +121,7 @@ static int axfr_query_init(struct query_data *qdata)
assert(qdata);
/* Check AXFR query validity. */
int state = axfr_query_check(qdata);
if (state == KNOT_STATE_FAIL) {
if (axfr_query_check(qdata) == KNOT_STATE_FAIL) {
if (qdata->rcode == KNOT_RCODE_FORMERR) {
return KNOT_EMALF;
} else {
......@@ -140,8 +131,6 @@ static int axfr_query_init(struct query_data *qdata)
/* Create transfer processing context. */
knot_mm_t *mm = qdata->mm;
zone_contents_t *zone = qdata->zone->contents;
struct axfr_proc *axfr = mm_alloc(mm, sizeof(struct axfr_proc));
if (axfr == NULL) {
return KNOT_ENOMEM;
......@@ -151,6 +140,7 @@ static int axfr_query_init(struct query_data *qdata)
/* Put data to process. */
xfr_stats_begin(&axfr->proc.stats);
zone_contents_t *zone = qdata->zone->contents;
ptrlist_add(&axfr->proc.nodes, zone->nodes, mm);
/* Put NSEC3 data if exists. */
if (!zone_tree_is_empty(zone->nsec3_nodes)) {
......@@ -161,8 +151,7 @@ static int axfr_query_init(struct query_data *qdata)
qdata->ext = axfr;
qdata->ext_cleanup = &axfr_query_cleanup;
/* No zone changes during multipacket answer
(unlocked in axfr_answer_cleanup) */
/* No zone changes during multipacket answer (unlocked in axfr_answer_cleanup) */
rcu_read_lock();
return KNOT_EOK;
......@@ -174,8 +163,6 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
return KNOT_STATE_FAIL;
}
int ret = KNOT_EOK;
/* If AXFR is disabled, respond with NOTIMPL. */
if (qdata->param->proc_flags & NS_QUERY_NO_AXFR) {
qdata->rcode = KNOT_RCODE_NOTIMPL;
......@@ -183,9 +170,10 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
}
/* Initialize on first call. */
if (qdata->ext == NULL) {
ret = axfr_query_init(qdata);
struct axfr_proc *axfr = qdata->ext;
if (axfr == NULL) {
int ret = axfr_query_init(qdata);
axfr = qdata->ext;
if (ret != KNOT_EOK) {
AXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
......@@ -200,9 +188,8 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
knot_pkt_reserve(pkt, knot_tsig_wire_size(&qdata->sign.tsig_key));
/* Answer current packet (or continue). */
struct axfr_proc *axfr = (struct axfr_proc *)qdata->ext;
ret = xfr_process_list(pkt, &axfr_process_node_tree, qdata);
switch(ret) {
int ret = xfr_process_list(pkt, &axfr_process_node_tree, qdata);
switch (ret) {
case KNOT_ESPACE: /* Couldn't write more, send packet and continue. */
return KNOT_STATE_PRODUCE; /* Check for more. */
case KNOT_EOK: /* Last response. */
......@@ -210,7 +197,6 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
xfr_log_finished(ZONE_NAME(qdata), LOG_OPERATION_AXFR, LOG_DIRECTION_OUT,
REMOTE(qdata), &axfr->proc.stats);
return KNOT_STATE_DONE;
break;
default: /* Generic error. */
AXFROUT_LOG(LOG_ERR, qdata, "failed (%s)", knot_strerror(ret));
return KNOT_STATE_FAIL;
......
......@@ -16,16 +16,15 @@
#include <urcu.h>
#include "knot/nameserver/internet.h"
#include "contrib/mempattern.h"
#include "contrib/sockaddr.h"
#include "knot/nameserver/axfr.h"
#include "knot/nameserver/internet.h"
#include "knot/nameserver/ixfr.h"
#include "knot/nameserver/log.h"
#include "knot/nameserver/xfr.h"
#include "knot/zone/serial.h"
#include "knot/zone/zonefile.h"
#include "libknot/libknot.h"
#include "contrib/mempattern.h"
#include "contrib/sockaddr.h"
#define ZONE_NAME(qdata) knot_pkt_qname((qdata)->query)
#define REMOTE(qdata) (struct sockaddr *)(qdata)->param->remote
......@@ -36,7 +35,7 @@
/*! \brief Helper macro for putting RRs into packet. */
#define IXFR_SAFE_PUT(pkt, rr) \
ret = knot_pkt_put((pkt), 0, (rr), KNOT_PF_NOTRUNC); \
int ret = knot_pkt_put((pkt), 0, (rr), KNOT_PF_NOTRUNC); \
if (ret != KNOT_EOK) { \
return ret; \
}
......@@ -53,13 +52,12 @@ static int ixfr_put_chg_part(knot_pkt_t *pkt, struct ixfr_proc *ixfr,
ixfr->cur_rr = changeset_iter_next(itt);
}
int ret = KNOT_EOK; // Declaration for IXFR_SAFE_PUT macro
while (!knot_rrset_empty(&ixfr->cur_rr)) {
IXFR_SAFE_PUT(pkt, &ixfr->cur_rr);
ixfr->cur_rr = changeset_iter_next(itt);
}
return ret;
return KNOT_EOK;
}
/*! \brief Tests if iteration has started. */
......@@ -136,7 +134,6 @@ static int ixfr_process_changeset(knot_pkt_t *pkt, const void *item,
#undef IXFR_SAFE_PUT
/*! \brief Loads IXFRs from journal. */
static int ixfr_load_chsets(list_t *chgsets, zone_t *zone,
const knot_rrset_t *their_soa)
{
......@@ -159,7 +156,6 @@ static int ixfr_load_chsets(list_t *chgsets, zone_t *zone,
return ret;
}
/*! \brief Check IXFR query validity. */
static int ixfr_query_check(struct query_data *qdata)
{
/* Check if zone exists. */
......@@ -184,7 +180,6 @@ static int ixfr_query_check(struct query_data *qdata)
return KNOT_STATE_DONE;
}
/*! \brief Cleans up ixfr processing context. */
static void ixfr_answer_cleanup(struct query_data *qdata)
{
struct ixfr_proc *ixfr = (struct ixfr_proc *)qdata->ext;
......@@ -199,12 +194,12 @@ static void ixfr_answer_cleanup(struct query_data *qdata)
rcu_read_unlock();
}
/*! \brief Inits ixfr processing context. */
static int ixfr_answer_init(struct query_data *qdata)
{
assert(qdata);
/* Check IXFR query validity. */
int state = ixfr_query_check(qdata);
if (state == KNOT_STATE_FAIL) {
if (ixfr_query_check(qdata) == KNOT_STATE_FAIL) {
if (qdata->rcode == KNOT_RCODE_FORMERR) {
return KNOT_EMALF;
} else {
......@@ -255,18 +250,16 @@ static int ixfr_answer_init(struct query_data *qdata)
qdata->ext = xfer;
qdata->ext_cleanup = &ixfr_answer_cleanup;
/* No zone changes during multipacket answer (unlocked in axfr_answer_cleanup) */
/* No zone changes during multipacket answer (unlocked in ixfr_answer_cleanup) */
rcu_read_lock();
return KNOT_EOK;
}
/*! \brief Sends response to SOA query. */
static int ixfr_answer_soa(knot_pkt_t *pkt, struct query_data *qdata)
{
if (pkt == NULL || qdata == NULL) {
return KNOT_STATE_FAIL;
}
assert(pkt);
assert(qdata);
/* Check query. */
int state = ixfr_query_check(qdata);
......@@ -298,20 +291,18 @@ int ixfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
return KNOT_STATE_FAIL;
}
int ret = KNOT_EOK;
struct ixfr_proc *ixfr = (struct ixfr_proc *)qdata->ext;
/* If IXFR is disabled, respond with SOA. */
if (qdata->param->proc_flags & NS_QUERY_NO_IXFR) {
return ixfr_answer_soa(pkt, qdata);
}
/* Initialize on first call. */
if (qdata->ext == NULL) {
ret = ixfr_answer_init(qdata);
struct ixfr_proc *ixfr = qdata->ext;
if (ixfr == NULL) {
int ret = ixfr_answer_init(qdata);
ixfr = qdata->ext;
switch (ret) {
case KNOT_EOK: /* OK */
ixfr = (struct ixfr_proc *)qdata->ext;
IXFROUT_LOG(LOG_INFO, qdata, "started, serial %u -> %u",
knot_soa_serial(&ixfr->soa_from->rrs),
knot_soa_serial(&ixfr->soa_to->rrs));
......@@ -325,7 +316,8 @@ int ixfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
qdata->packet_type = KNOT_QUERY_AXFR; /* Solve as AXFR. */
return axfr_process_query(pkt, qdata);
default: /* Server errors. */
IXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)", knot_strerror(ret));
IXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
return KNOT_STATE_FAIL;
}
}
......@@ -334,7 +326,7 @@ int ixfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
knot_pkt_reserve(pkt, knot_tsig_wire_size(&qdata->sign.tsig_key));
/* Answer current packet (or continue). */
ret = xfr_process_list(pkt, &ixfr_process_changeset, qdata);
int ret = xfr_process_list(pkt, &ixfr_process_changeset, qdata);
switch (ret) {
case KNOT_ESPACE: /* Couldn't write more, send packet and continue. */
return KNOT_STATE_PRODUCE; /* Check for more. */
......@@ -342,13 +334,9 @@ int ixfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
xfr_stats_end(&ixfr->proc.stats);
xfr_log_finished(ZONE_NAME(qdata), LOG_OPERATION_IXFR, LOG_DIRECTION_OUT,
REMOTE(qdata), &ixfr->proc.stats);
ret = KNOT_STATE_DONE;
break;
return KNOT_STATE_DONE;
default: /* Generic error. */
IXFROUT_LOG(LOG_ERR, qdata, "failed (%s)", knot_strerror(ret));
ret = KNOT_STATE_FAIL;
break;
return KNOT_STATE_FAIL;
}
return ret;
}
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