Commit 147c21f0 authored by Daniel Salzman's avatar Daniel Salzman

nameserver: unify query check for XFR and NOTIFY

parent 444472d7
......@@ -107,10 +107,8 @@ static void axfr_query_cleanup(knotd_qdata_t *qdata)
static int axfr_query_check(knotd_qdata_t *qdata)
{
/* Check valid zone, transaction security and contents. */
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_TRANSFER);
/* Check expiration. */
NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL);
return KNOT_STATE_DONE;
......@@ -174,16 +172,20 @@ int axfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
if (axfr == NULL) {
int ret = axfr_query_init(qdata);
axfr = qdata->extra->ext;
if (ret != KNOT_EOK) {
if (qdata->rcode != KNOT_RCODE_FORMERR &&
qdata->rcode != KNOT_RCODE_NOTAUTH) {
AXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
}
return KNOT_STATE_FAIL;
} else {
switch (ret) {
case KNOT_EOK: /* OK */
AXFROUT_LOG(LOG_INFO, qdata, "started, serial %u",
zone_contents_serial(qdata->extra->zone->contents));
zone_contents_serial(qdata->extra->zone->contents));
break;
case KNOT_EDENIED: /* Not authorized, already logged. */
return KNOT_STATE_FAIL;
case KNOT_EMALF: /* Malformed query. */
AXFROUT_LOG(LOG_DEBUG, qdata, "malformed query");
return KNOT_STATE_FAIL;
default:
AXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
return KNOT_STATE_FAIL;
}
}
......
......@@ -158,11 +158,10 @@ static int ixfr_load_chsets(list_t *chgsets, zone_t *zone,
static int ixfr_query_check(knotd_qdata_t *qdata)
{
/* Check if zone exists. */
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_TRANSFER);
NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL);
/* Need IXFR query type. */
NS_NEED_QTYPE(qdata, KNOT_RRTYPE_IXFR, KNOT_RCODE_FORMERR);
/* Need SOA authority record. */
const knot_pktsection_t *authority = knot_pkt_section(qdata->query, KNOT_AUTHORITY);
const knot_rrset_t *their_soa = knot_pkt_rr(authority, 0);
......@@ -173,10 +172,6 @@ static int ixfr_query_check(knotd_qdata_t *qdata)
/* SOA needs to match QNAME. */
NS_NEED_QNAME(qdata, their_soa->owner, KNOT_RCODE_FORMERR);
/* Check transcation security and zone contents. */
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_TRANSFER);
NS_NEED_ZONE_CONTENTS(qdata, KNOT_RCODE_SERVFAIL); /* Check expiration. */
return KNOT_STATE_DONE;
}
......@@ -302,7 +297,7 @@ int ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
int ret = ixfr_answer_init(qdata);
ixfr = qdata->extra->ext;
switch (ret) {
case KNOT_EOK: /* OK */
case KNOT_EOK: /* OK */
IXFROUT_LOG(LOG_INFO, qdata, "started, serial %u -> %u",
knot_soa_serial(&ixfr->soa_from->rrs),
knot_soa_serial(&ixfr->soa_to->rrs));
......@@ -310,17 +305,19 @@ int ixfr_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
case KNOT_EUPTODATE: /* Our zone is same age/older, send SOA. */
IXFROUT_LOG(LOG_INFO, qdata, "zone is up-to-date");
return ixfr_answer_soa(pkt, qdata);
case KNOT_ERANGE: /* No history -> AXFR. */
case KNOT_ERANGE: /* No history -> AXFR. */
case KNOT_ENOENT:
IXFROUT_LOG(LOG_INFO, qdata, "incomplete history, fallback to AXFR");
qdata->type = KNOTD_QUERY_TYPE_AXFR; /* Solve as AXFR. */
return axfr_process_query(pkt, qdata);
default: /* Server errors. */
if (qdata->rcode != KNOT_RCODE_FORMERR &&
qdata->rcode != KNOT_RCODE_NOTAUTH) {
IXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
}
case KNOT_EDENIED: /* Not authorized, already logged. */
return KNOT_STATE_FAIL;
case KNOT_EMALF: /* Malformed query. */
IXFROUT_LOG(LOG_DEBUG, qdata, "malformed query");
return KNOT_STATE_FAIL;
default: /* Server errors. */
IXFROUT_LOG(LOG_ERR, qdata, "failed to start (%s)",
knot_strerror(ret));
return KNOT_STATE_FAIL;
}
}
......
......@@ -25,20 +25,17 @@
#include "dnssec/random.h"
#include "libknot/libknot.h"
#define NOTIFY_IN_LOG(priority, qdata, fmt...) \
#define NOTIFY_LOG(priority, qdata, fmt...) \
ns_log(priority, knot_pkt_qname(qdata->query), LOG_OPERATION_NOTIFY, \
LOG_DIRECTION_IN, (struct sockaddr *)qdata->params->remote, fmt)
static int notify_check_query(knotd_qdata_t *qdata)
{
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, qdata->extra->zone->name, ACL_ACTION_NOTIFY);
/* RFC1996 requires SOA question. */
NS_NEED_QTYPE(qdata, KNOT_RRTYPE_SOA, KNOT_RCODE_FORMERR);
/* Check valid zone, transaction security. */
zone_t *zone = (zone_t *)qdata->extra->zone;
NS_NEED_ZONE(qdata, KNOT_RCODE_NOTAUTH);
NS_NEED_AUTH(qdata, zone->name, ACL_ACTION_NOTIFY);
return KNOT_STATE_DONE;
}
......@@ -52,9 +49,10 @@ int notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
int state = notify_check_query(qdata);
if (state == KNOT_STATE_FAIL) {
switch (qdata->rcode) {
case KNOT_RCODE_NOTAUTH: /* Not authoritative or ACL check failed. */
case KNOT_RCODE_FORMERR: /* Silently ignore bad queries. */
default:
case KNOT_RCODE_NOTAUTH: /* Not authorized, already logged. */
break;
default: /* Other errors. */
NOTIFY_LOG(LOG_DEBUG, qdata, "invalid query");
break;
}
return state;
......@@ -71,16 +69,16 @@ int notify_process_query(knot_pkt_t *pkt, knotd_qdata_t *qdata)
if (soa->type == KNOT_RRTYPE_SOA) {
uint32_t serial = knot_soa_serial(&soa->rrs);
uint32_t zone_serial = zone_contents_serial(zone->contents);
NOTIFY_IN_LOG(LOG_INFO, qdata, "received, serial %u", serial);
NOTIFY_LOG(LOG_INFO, qdata, "received, serial %u", serial);
if (serial_compare(serial, zone_serial) == 0) {
// NOTIFY serial == zone serial => ignore, keep timers
return KNOT_STATE_DONE;
}
} else { /* Complain, but accept N/A record. */
NOTIFY_IN_LOG(LOG_NOTICE, qdata, "received, bad record in answer section");
NOTIFY_LOG(LOG_NOTICE, qdata, "received, bad record in answer section");
}
} else {
NOTIFY_IN_LOG(LOG_INFO, qdata, "received, serial none");
NOTIFY_LOG(LOG_INFO, qdata, "received, serial none");
}
/* Incoming NOTIFY expires REFRESH timer and renews EXPIRE timer. */
......
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