Commit d1b90b24 authored by Jan Včelák's avatar Jan Včelák 🚀

huge events refactor

parent 55cd48a7
......@@ -292,6 +292,8 @@ src/knot/nameserver/tsig_ctx.c
src/knot/nameserver/tsig_ctx.h
src/knot/nameserver/update.c
src/knot/nameserver/update.h
src/knot/nameserver/xfr.c
src/knot/nameserver/xfr.h
src/knot/query/capture.c
src/knot/query/capture.h
src/knot/query/layer.c
......@@ -576,7 +578,6 @@ tests/libknot/test_ypscheme.c
tests/libknot/test_yptrafo.c
tests/modules/online_sign.c
tests/node.c
tests/process_answer.c
tests/process_query.c
tests/query_module.c
tests/requestor.c
......
......@@ -308,6 +308,8 @@ libknotd_la_SOURCES = \
knot/nameserver/tsig_ctx.h \
knot/nameserver/update.c \
knot/nameserver/update.h \
knot/nameserver/xfr.c \
knot/nameserver/xfr.h \
knot/query/capture.c \
knot/query/capture.h \
knot/query/layer.c \
......
......@@ -85,7 +85,7 @@ int event_dnssec(conf_t *conf, zone_t *zone)
apply_init_ctx(&a_ctx, NULL, APPLY_STRICT);
zone_contents_t *new_contents = NULL;
int ret = apply_changeset(&a_ctx, zone, &ch, &new_contents);
int ret = apply_changeset(&a_ctx, zone->contents, &ch, &new_contents);
if (ret != KNOT_EOK) {
log_zone_error(zone->name, "DNSSEC, failed to sign zone (%s)",
knot_strerror(ret));
......
......@@ -19,35 +19,149 @@
#include "knot/common/log.h"
#include "knot/conf/conf.h"
#include "knot/query/query.h"
#include "knot/query/requestor.h"
#include "knot/zone/zone.h"
#include "libknot/errcode.h"
#define NOTIFY_LOG(priority, zone, remote, msg...) \
ZONE_QUERY_LOG(priority, zone, remote, "NOTIFY, outgoing", msg);
/*!
* \brief NOTIFY message processing data.
*/
struct notify_data {
const knot_dname_t *zone;
const knot_rrset_t *soa;
const struct sockaddr_storage *remote;
uint16_t response_rcode;
};
static int notify_begin(knot_layer_t *layer, void *params)
{
layer->data = params;
return KNOT_STATE_PRODUCE;
}
static int notify_produce(knot_layer_t *layer, knot_pkt_t *pkt)
{
struct notify_data *data = layer->data;
// mandatory: NOTIFY opcode, AA flag, SOA qtype
query_init_pkt(pkt);
knot_wire_set_opcode(pkt->wire, KNOT_OPCODE_NOTIFY);
knot_wire_set_aa(pkt->wire);
knot_pkt_put_question(pkt, data->zone, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
// unsecure hint: new SOA
if (data->soa) {
knot_pkt_begin(pkt, KNOT_ANSWER);
knot_pkt_put(pkt, KNOT_COMPR_HINT_QNAME, data->soa, 0);
}
return KNOT_STATE_CONSUME;
}
static int notify_consume(knot_layer_t *layer, knot_pkt_t *pkt)
{
struct notify_data *data = layer->data;
data->response_rcode = knot_pkt_get_ext_rcode(pkt);
if (data->response_rcode != KNOT_RCODE_NOERROR) {
return KNOT_STATE_FAIL;
}
return KNOT_STATE_DONE;
}
static const knot_layer_api_t NOTIFY_API = {
.begin = notify_begin,
.produce = notify_produce,
.consume = notify_consume,
};
static int send_notify(zone_t *zone, const knot_rrset_t *soa,
const conf_remote_t *slave, int timeout, uint16_t *rcode)
{
struct notify_data data = {
.zone = zone->name,
.soa = soa,
.remote = &slave->addr,
};
struct knot_requestor requestor = { 0 };
knot_requestor_init(&requestor, &NOTIFY_API, &data, NULL);
knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
if (!pkt) {
knot_requestor_clear(&requestor);
return KNOT_ENOMEM;
}
const struct sockaddr *dst = (struct sockaddr *)&slave->addr;
const struct sockaddr *src = (struct sockaddr *)&slave->via;
struct knot_request *req = knot_request_make(NULL, dst, src, pkt, &slave->key, 0);
if (!req) {
knot_request_free(req, NULL);
knot_requestor_clear(&requestor);
return KNOT_ENOMEM;
}
int ret = knot_requestor_exec(&requestor, req, timeout);
knot_request_free(req, NULL);
knot_requestor_clear(&requestor);
*rcode = data.response_rcode;
return ret;
}
#define NOTIFY_LOG(priority, zone, remote, fmt, ...) \
ns_log(priority, zone, LOG_OPERATION_NOTIFY, LOG_DIRECTION_OUT, remote, \
fmt, ## __VA_ARGS__)
static void log_notify_result(int ret, uint16_t rcode, const knot_dname_t *zone,
const struct sockaddr_storage *_remote, uint32_t serial)
{
const struct sockaddr *remote = (struct sockaddr *)_remote;
if (ret == KNOT_EOK) {
NOTIFY_LOG(LOG_INFO, zone, remote, "serial %u", serial);
} else if (rcode == 0) {
NOTIFY_LOG(LOG_WARNING, zone, remote, "failed (%s)", knot_strerror(ret));
} else {
const knot_lookup_t *lut = knot_lookup_by_id(knot_rcode_names, rcode);
if (lut) {
NOTIFY_LOG(LOG_WARNING, zone, remote, "server responded with %s", lut->name);
} else {
NOTIFY_LOG(LOG_WARNING, zone, remote, "server responded with RCODE %u", rcode);
}
}
}
int event_notify(conf_t *conf, zone_t *zone)
{
assert(zone);
/* Check zone contents. */
if (zone_contents_is_empty(zone->contents)) {
return KNOT_EOK;
}
/* Walk through configured remotes and send messages. */
// NOTIFY content
int timeout = conf->cache.srv_tcp_reply_timeout * 1000;
knot_rrset_t soa = node_rrset(zone->contents->apex, KNOT_RRTYPE_SOA);
uint32_t serial = zone_contents_serial(zone->contents);
// send NOTIFY to each remote, use working address
conf_val_t notify = conf_zone_get(conf, C_NOTIFY, zone->name);
while (notify.code == KNOT_EOK) {
conf_val_t addr = conf_id_get(conf, C_RMT, C_ADDR, &notify);
size_t addr_count = conf_val_count(&addr);
for (int i = 0; i < addr_count; i++) {
uint16_t rcode = 0;
conf_remote_t slave = conf_remote(conf, &notify, i);
int ret = zone_query_execute(conf, zone, KNOT_QUERY_NOTIFY, &slave);
int ret = send_notify(zone, &soa, &slave, timeout, &rcode);
log_notify_result(ret, rcode, zone->name, &slave.addr, serial);
if (ret == KNOT_EOK) {
NOTIFY_LOG(LOG_INFO, zone, &slave, "serial %u", zone_contents_serial(zone->contents));
break;
} else {
NOTIFY_LOG(LOG_WARNING, zone, &slave, "failed (%s)", knot_strerror(ret));
}
}
......
This diff is collapsed.
......@@ -80,7 +80,7 @@ static int dnsproxy_fwd(int state, knot_pkt_t *pkt, struct query_data *qdata, vo
bool is_tcp = net_is_stream(qdata->param->socket);
const struct sockaddr *dst = (const struct sockaddr *)&proxy->remote.addr;
const struct sockaddr *src = (const struct sockaddr *)&proxy->remote.via;
struct knot_request *req = knot_request_make(re.mm, dst, src, qdata->query,
struct knot_request *req = knot_request_make(re.mm, dst, src, qdata->query, NULL,
is_tcp ? 0 : KNOT_RQ_UDP);
if (req == NULL) {
knot_requestor_clear(&re);
......
......@@ -17,15 +17,23 @@
#include <urcu.h>
#include "contrib/mempattern.h"
#include "contrib/print.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)
#define REMOTE(qdata) (struct sockaddr *)(qdata)->param->remote
#define AXFROUT_LOG(priority, qdata, fmt...) \
ns_log(priority, ZONE_NAME(qdata), LOG_OPERATION_AXFR, \
LOG_DIRECTION_OUT, REMOTE(qdata), fmt)
/* AXFR context. @note aliasing the generic xfr_proc */
struct axfr_proc {
struct xfr_proc proc;
......@@ -142,7 +150,7 @@ static int axfr_query_init(struct query_data *qdata)
init_list(&axfr->proc.nodes);
/* Put data to process. */
gettimeofday(&axfr->proc.tstamp, NULL);
xfr_stats_begin(&axfr->proc.stats);
ptrlist_add(&axfr->proc.nodes, zone->nodes, mm);
/* Put NSEC3 data if exists. */
if (!zone_tree_is_empty(zone->nsec3_nodes)) {
......@@ -160,53 +168,6 @@ static int axfr_query_init(struct query_data *qdata)
return KNOT_EOK;
}
int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb process_item,
struct query_data *qdata)
{
if (pkt == NULL || qdata == NULL || qdata->ext == NULL) {
return KNOT_EINVAL;
}
int ret = KNOT_EOK;
knot_mm_t *mm = qdata->mm;
struct xfr_proc *xfer = qdata->ext;
zone_contents_t *zone = qdata->zone->contents;
knot_rrset_t soa_rr = node_rrset(zone->apex, KNOT_RRTYPE_SOA);
/* Prepend SOA on first packet. */
if (xfer->npkts == 0) {
ret = knot_pkt_put(pkt, 0, &soa_rr, KNOT_PF_NOTRUNC);
if (ret != KNOT_EOK) {
return ret;
}
}
/* Process all items in the list. */
while (!EMPTY_LIST(xfer->nodes)) {
ptrnode_t *head = HEAD(xfer->nodes);
ret = process_item(pkt, head->d, xfer);
if (ret == KNOT_EOK) { /* Finished. */
/* Complete change set. */
rem_node((node_t *)head);
mm_free(mm, head);
} else { /* Packet full or other error. */
break;
}
}
/* Append SOA on last packet. */
if (ret == KNOT_EOK) {
ret = knot_pkt_put(pkt, 0, &soa_rr, KNOT_PF_NOTRUNC);
}
/* Update counters. */
xfer->npkts += 1;
xfer->nbytes += pkt->size;
return ret;
}
int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
{
if (pkt == NULL || qdata == NULL) {
......@@ -214,7 +175,6 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
}
int ret = KNOT_EOK;
struct timeval now = {0};
/* If AXFR is disabled, respond with NOTIMPL. */
if (qdata->param->proc_flags & NS_QUERY_NO_AXFR) {
......@@ -227,11 +187,11 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
ret = axfr_query_init(qdata);
if (ret != KNOT_EOK) {
AXFROUT_LOG(LOG_ERR, "failed to start (%s)",
AXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
return KNOT_STATE_FAIL;
} else {
AXFROUT_LOG(LOG_INFO, "started, serial %u",
AXFROUT_LOG(LOG_INFO, qdata, "started, serial %u",
zone_contents_serial(qdata->zone->contents));
}
}
......@@ -246,201 +206,13 @@ int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata)
case KNOT_ESPACE: /* Couldn't write more, send packet and continue. */
return KNOT_STATE_PRODUCE; /* Check for more. */
case KNOT_EOK: /* Last response. */
gettimeofday(&now, NULL);
AXFROUT_LOG(LOG_INFO,
"finished, %.02f seconds, %u messages, %u bytes",
time_diff(&axfr->proc.tstamp, &now) / 1000.0,
axfr->proc.npkts, axfr->proc.nbytes);
xfr_stats_end(&axfr->proc.stats);
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, "failed (%s)", knot_strerror(ret));
return KNOT_STATE_FAIL;
}
}
static void axfr_answer_cleanup(struct answer_data *data)
{
assert(data != NULL);
struct xfr_proc *proc = data->ext;
if (proc) {
zone_contents_deep_free(&proc->contents);
mm_free(data->mm, proc);
data->ext = NULL;
}
}
static int axfr_answer_init(struct answer_data *data)
{
assert(data);
/* Create new zone contents. */
zone_t *zone = data->param->zone;
zone_contents_t *new_contents = zone_contents_new(zone->name);
if (new_contents == NULL) {
return KNOT_ENOMEM;
}
/* Create new processing context. */
struct xfr_proc *proc = mm_alloc(data->mm, sizeof(struct xfr_proc));
if (proc == NULL) {
zone_contents_deep_free(&new_contents);
return KNOT_ENOMEM;
}
memset(proc, 0, sizeof(struct xfr_proc));
proc->contents = new_contents;
gettimeofday(&proc->tstamp, NULL);
/* Set up cleanup callback. */
data->ext = proc;
data->ext_cleanup = &axfr_answer_cleanup;
return KNOT_EOK;
}
static int axfr_answer_finalize(struct answer_data *adata)
{
struct timeval now;
gettimeofday(&now, NULL);
/*
* Adjust zone so that node count is set properly and nodes are
* marked authoritative / delegation point.
*/
struct xfr_proc *proc = adata->ext;
int rc = zone_contents_adjust_full(proc->contents);
if (rc != KNOT_EOK) {
return rc;
}
err_handler_logger_t handler;
handler._cb.cb = err_handler_logger;
rc = zone_do_sem_checks(proc->contents, false, &handler._cb);
if (rc != KNOT_EOK) {
return rc;
}
conf_val_t val = conf_zone_get(adata->param->conf, C_MAX_ZONE_SIZE,
proc->contents->apex->owner);
int64_t size_limit = conf_int(&val);
if (proc->contents->size > size_limit) {
AXFRIN_LOG(LOG_WARNING, "zone size exceeded");
AXFROUT_LOG(LOG_ERR, qdata, "failed (%s)", knot_strerror(ret));
return KNOT_STATE_FAIL;
}
/* Switch contents. */
zone_t *zone = adata->param->zone;
zone_contents_t *old_contents =
zone_switch_contents(zone, proc->contents);
zone->flags &= ~ZONE_EXPIRED;
synchronize_rcu();
if (old_contents != NULL) {
AXFRIN_LOG(LOG_INFO, "finished, "
"serial %u -> %u, %.02f seconds, %u messages, %u bytes",
zone_contents_serial(old_contents),
zone_contents_serial(proc->contents),
time_diff(&proc->tstamp, &now) / 1000.0,
proc->npkts, proc->nbytes);
} else {
AXFRIN_LOG(LOG_INFO, "finished, "
"serial %u, %.02f seconds, %u messages, %u bytes",
zone_contents_serial(proc->contents),
time_diff(&proc->tstamp, &now) / 1000.0,
proc->npkts, proc->nbytes);
}
/* Do not free new contents with cleanup. */
zone_contents_deep_free(&old_contents);
proc->contents = NULL;
return KNOT_EOK;
}
static int axfr_answer_packet(knot_pkt_t *pkt, struct answer_data *adata)
{
assert(adata != NULL);
struct xfr_proc *proc = adata->ext;
assert(pkt != NULL);
assert(proc != NULL);
/* Update counters. */
proc->npkts += 1;
proc->nbytes += pkt->size;
conf_val_t val = conf_zone_get(adata->param->conf, C_MAX_ZONE_SIZE,
proc->contents->apex->owner);
int64_t size_limit = conf_int(&val);
/* Init zone creator. */
zcreator_t zc = {.z = proc->contents, .master = false, .ret = KNOT_EOK };
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
const knot_rrset_t *answer_rr = knot_pkt_rr(answer, 0);
for (uint16_t i = 0; i < answer->count; ++i) {
if (answer_rr[i].type == KNOT_RRTYPE_SOA &&
node_rrtype_exists(zc.z->apex, KNOT_RRTYPE_SOA)) {
return KNOT_STATE_DONE;
} else {
int ret = zcreator_step(&zc, &answer_rr[i]);
if (ret != KNOT_EOK) {
return KNOT_STATE_FAIL;
}
}
proc->contents->size += knot_rrset_size(&answer_rr[i]);
if (proc->contents->size > size_limit) {
AXFRIN_LOG(LOG_WARNING, "zone size exceeded");
return KNOT_STATE_FAIL;
}
}
return KNOT_STATE_CONSUME;
}
int axfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
{
if (pkt == NULL || adata == NULL) {
return KNOT_STATE_FAIL;
}
/* Check RCODE. */
uint8_t rcode = knot_wire_get_rcode(pkt->wire);
if (rcode != KNOT_RCODE_NOERROR) {
const knot_lookup_t *lut = knot_lookup_by_id(knot_rcode_names, rcode);
if (lut != NULL) {
AXFRIN_LOG(LOG_WARNING, "server responded with %s", lut->name);
}
return KNOT_STATE_FAIL;
}
/* Initialize processing with first packet. */
if (adata->ext == NULL) {
NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
AXFRIN_LOG(LOG_INFO, "starting");
int ret = axfr_answer_init(adata);
if (ret != KNOT_EOK) {
AXFRIN_LOG(LOG_WARNING, "failed (%s)", knot_strerror(ret));
return KNOT_STATE_FAIL;
}
} else {
NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 100);
}
/* Process answer packet. */
int ret = axfr_answer_packet(pkt, adata);
if (ret == KNOT_STATE_DONE) {
NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
/* This was the last packet, finalize zone and publish it. */
int fret = axfr_answer_finalize(adata);
if (fret != KNOT_EOK) {
ret = KNOT_STATE_FAIL;
}
}
return ret;
}
......@@ -13,64 +13,11 @@
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
*
* \brief AXFR processing.
*
* \addtogroup query_processing
* @{
*/
#pragma once
#include "libknot/packet/pkt.h"
#include "knot/nameserver/log.h"
#include "knot/query/query.h"
#include "knot/nameserver/process_query.h"
#include "knot/zone/contents.h"
#include "contrib/ucw/lists.h"
/*!
* \brief Transfer-specific logging (internal, expects 'qdata' variable set).
*
* Emits a message in the following format:
* > [zone] type, outgoing, address: custom formatted message
*/
#define TRANSFER_OUT_LOG(type, priority, msg, ...) \
NS_PROC_LOG(priority, knot_pkt_qname((qdata)->query), (qdata)->param->remote, \
type ", outgoing", msg, ##__VA_ARGS__)
#define AXFROUT_LOG(args...) TRANSFER_OUT_LOG("AXFR", args)
#define IXFROUT_LOG(args...) TRANSFER_OUT_LOG("IXFR", args)
/*!
* \brief Transfer-specific logging (internal, expects 'adata' variable set).
*/
#define TRANSFER_IN_LOG(type, priority, msg, ...) \
NS_PROC_LOG(priority, (adata)->param->zone->name, (adata)->param->remote, \
type ", incoming", msg, ##__VA_ARGS__)
#define AXFRIN_LOG(args...) TRANSFER_IN_LOG("AXFR", args)
#define IXFRIN_LOG(args...) TRANSFER_IN_LOG("IXFR", args)
/*! \brief Generic transfer processing state. */
struct xfr_proc {
list_t nodes; /* Items to process (ptrnode_t). */
unsigned npkts; /* Packets processed. */
unsigned nbytes; /* Bytes processed. */
struct timeval tstamp; /* Start time. */
zone_contents_t *contents; /* Processed zone. */
};
/*! \brief Generic transfer processing (reused for IXFR).
* \return KNOT_EOK or an error
*/
typedef int (*xfr_put_cb)(knot_pkt_t *pkt, const void *item, struct xfr_proc *xfer);
/*! \brief Put all items from xfr_proc.nodes to packet using a callback function.
* \note qdata->ext points to struct xfr_proc* (this is xfer-specific context)
*/
int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb put, struct query_data *qdata);
#include "libknot/packet/pkt.h"
/*!
* \brief Process an AXFR query message.
......@@ -78,12 +25,3 @@ int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb put, struct query_data *qdata);
* \return KNOT_STATE_* processing states
*/
int axfr_process_query(knot_pkt_t *pkt, struct query_data *qdata);
/*!
* \brief Processes an AXFR response message.
*
* \return KNOT_STATE_* processing states
*/
int axfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata);
/*! @} */
......@@ -807,8 +807,6 @@ static int answer_query(struct query_plan *plan, knot_pkt_t *response, struct qu
return KNOT_STATE_DONE;
}
#undef SOLVE_STEP
int internet_process_query(knot_pkt_t *response, struct query_data *qdata)
{
if (response == NULL || qdata == NULL) {
......@@ -834,72 +832,3 @@ int internet_process_query(knot_pkt_t *response, struct query_data *qdata)
return answer_query(qdata->zone->query_plan, response, qdata);
}
#include "knot/nameserver/log.h"
#define REFRESH_LOG(priority, msg, ...) \
NS_PROC_LOG(priority, (data)->param->zone->name, (data)->param->remote, \
"refresh, outgoing", msg, ##__VA_ARGS__)
/*! \brief Process answer to SOA query. */
static int process_soa_answer(knot_pkt_t *pkt, struct answer_data *data)
{
zone_t *zone = data->param->zone;
/* Check RCODE. */
uint8_t rcode = knot_wire_get_rcode(pkt->wire);
if (rcode != KNOT_RCODE_NOERROR) {
const knot_lookup_t *lut = knot_lookup_by_id(knot_rcode_names, rcode);
if (lut != NULL) {
REFRESH_LOG(LOG_WARNING, "server responded with %s", lut->name);
}
return KNOT_STATE_FAIL;
}
/* Expect SOA in answer section. */
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
const knot_rrset_t *first_rr = knot_pkt_rr(answer, 0);
if (answer->count < 1 || first_rr->type != KNOT_RRTYPE_SOA) {
REFRESH_LOG(LOG_WARNING, "malformed message");
return KNOT_STATE_FAIL;
}
/* Our zone is expired, schedule transfer. */
if (zone_contents_is_empty(zone->contents)) {
zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW);
return KNOT_STATE_DONE;
}
/* Check if master has newer zone and schedule transfer. */
knot_rdataset_t *soa = node_rdataset(zone->contents->apex, KNOT_RRTYPE_SOA);
uint32_t our_serial = knot_soa_serial(soa);
uint32_t their_serial = knot_soa_serial(&first_rr->rrs);
if (serial_compare(our_serial, their_serial) >= 0) {
REFRESH_LOG(LOG_INFO, "zone is up-to-date");
zone_events_cancel(zone, ZONE_EVENT_EXPIRE);
zone_clear_preferred_master(zone);
return KNOT_STATE_DONE; /* Our zone is up to date. */
}
/* Our zone is outdated, schedule zone transfer. */
REFRESH_LOG(LOG_INFO, "master has newer serial %u -> %u", our_serial, their_serial);
zone_set_preferred_master(zone, data->param->remote);
zone_events_schedule(zone, ZONE_EVENT_XFER, ZONE_EVENT_NOW);
return KNOT_STATE_DONE;
}
int internet_process_answer(knot_pkt_t *pkt, struct answer_data *data)
{
if (pkt == NULL || data == NULL) {
return KNOT_STATE_FAIL;
}
NS_NEED_TSIG_SIGNED(&data->param->tsig_ctx, 0);
/* As of now, server can only issue SOA queries. */
switch(knot_pkt_qtype(pkt)) {
case KNOT_RRTYPE_SOA:
return process_soa_answer(pkt, data);
default:
return KNOT_STATE_NOOP;
}
}
......@@ -29,9 +29,6 @@
/* Query data (from query processing). */
struct query_data;
struct query_plan;
struct query_module;
struct answer_data;
/*! \brief Internet query processing states. */
enum {
......@@ -53,15 +50,6 @@ enum {
*/
int internet_process_query(knot_pkt_t *resp, struct query_data *qdata);
/*!
* \brief Process answer in an IN class zone.
*
* \retval FAIL if it encountered an error.
* \retval DONE if finished.
* \retval NOOP if not supported.
*/
int internet_process_answer(knot_pkt_t *pkt, struct answer_data *data);
/*!
* \brief Puts RRSet to packet, will store its RRSIG for later use.
*
......
This diff is collapsed.
......@@ -24,9 +24,41 @@
#pragma once
#include "libknot/packet/pkt.h"
#include "knot/query/query.h"
#include "knot/nameserver/process_query.h"
#include "knot/nameserver/xfr.h"
#include "knot/query/query.h"
#include "libknot/packet/pkt.h"
/*! \brief IXFR-in processing states. */
enum ixfr_state {
IXFR_INVALID = 0,
IXFR_START, /* IXFR-in starting, expecting final SOA. */