Commit 380672f3 authored by Jan Kadlec's avatar Jan Kadlec

zone-events: Initial IXFR-in implementation.

parent 8d008539
This diff is collapsed.
...@@ -28,9 +28,30 @@ ...@@ -28,9 +28,30 @@
#define _KNOT_IXFR_H_ #define _KNOT_IXFR_H_
#include "libknot/packet/pkt.h" #include "libknot/packet/pkt.h"
#include "knot/updates/changesets.h"
#include "knot/zone/zone.h"
struct query_data; struct query_data;
struct answer_data; struct answer_data;
struct xfr_proc;
/*! \brief IXFR-in processing states. */
enum ixfrin_states {
IXFR_START = 0,
IXFR_SOA_FROM = 1,
IXFR_SOA_TO = 2,
IXFR_DEL = 3,
IXFR_ADD = 4,
IXFR_DONE = 5
};
/*! \brief Extended structure for IXFR-in processing. */
struct ixfrin_proc {
int state;
knot_changesets_t *changesets;
zone_t *zone;
mm_ctx_t *mm;
};
/*! /*!
* \brief IXFR query processing module. * \brief IXFR query processing module.
...@@ -39,7 +60,7 @@ struct answer_data; ...@@ -39,7 +60,7 @@ struct answer_data;
* \retval FAIL if it encountered an error. * \retval FAIL if it encountered an error.
* \retval DONE if finished. * \retval DONE if finished.
*/ */
int ixfr_answer(knot_pkt_t *pkt, struct query_data *qdata); int ixfr_query(knot_pkt_t *pkt, struct query_data *qdata);
/*! /*!
* \brief Process an IXFR query response. * \brief Process an IXFR query response.
...@@ -64,7 +85,7 @@ int ixfr_answer(knot_pkt_t *pkt, struct query_data *qdata); ...@@ -64,7 +85,7 @@ int ixfr_answer(knot_pkt_t *pkt, struct query_data *qdata);
* \retval Other If any other error occured. The connection should be closed. * \retval Other If any other error occured. The connection should be closed.
* *
*/ */
int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *data); int ixfrin_process_answer(knot_pkt_t *pkt, struct answer_data *adata);
#endif /* _KNOT_IXFR_H_ */ #endif /* _KNOT_IXFR_H_ */
......
...@@ -125,7 +125,7 @@ int process_answer(knot_pkt_t *pkt, knot_process_t *ctx) ...@@ -125,7 +125,7 @@ int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
next_state = axfr_process_answer(pkt, data); next_state = axfr_process_answer(pkt, data);
break; break;
case KNOT_RESPONSE_IXFR: case KNOT_RESPONSE_IXFR:
next_state = ixfr_process_answer(pkt, data); next_state = ixfrin_process_answer(pkt, data);
break; break;
case KNOT_RESPONSE_NOTIFY: case KNOT_RESPONSE_NOTIFY:
next_state = notify_process_answer(pkt, data); next_state = notify_process_answer(pkt, data);
...@@ -139,4 +139,4 @@ int process_answer(knot_pkt_t *pkt, knot_process_t *ctx) ...@@ -139,4 +139,4 @@ int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
return next_state; return next_state;
} }
#undef ANSWER_REQUIRES #undef ANSWER_REQUIRES
\ No newline at end of file
...@@ -372,7 +372,7 @@ static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx) ...@@ -372,7 +372,7 @@ static int query_internet(knot_pkt_t *pkt, knot_process_t *ctx)
next_state = axfr_query(pkt, data); next_state = axfr_query(pkt, data);
break; break;
case KNOT_QUERY_IXFR: case KNOT_QUERY_IXFR:
next_state = ixfr_answer(pkt, data); next_state = ixfr_query(pkt, data);
break; break;
case KNOT_QUERY_UPDATE: case KNOT_QUERY_UPDATE:
next_state = update_answer(pkt, data); next_state = update_answer(pkt, data);
......
...@@ -162,7 +162,7 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents, ...@@ -162,7 +162,7 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents,
&refresh_at); &refresh_at);
} }
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
knot_changesets_free(&sec_chs); knot_changesets_free(&sec_chs, NULL);
return ret; return ret;
} }
...@@ -170,14 +170,14 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents, ...@@ -170,14 +170,14 @@ static int sign_update(zone_t *zone, const zone_contents_t *old_contents,
zone_contents_set_gen_old(new_contents); zone_contents_set_gen_old(new_contents);
ret = xfrin_apply_changesets_directly(new_contents, sec_chs); ret = xfrin_apply_changesets_directly(new_contents, sec_chs);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
knot_changesets_free(&sec_chs); knot_changesets_free(&sec_chs, NULL);
return ret; return ret;
} }
// Merge changesets // Merge changesets
ret = knot_changeset_merge(ddns_ch, sec_ch); ret = knot_changeset_merge(ddns_ch, sec_ch);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
knot_changesets_free(&sec_chs); knot_changesets_free(&sec_chs, NULL);
return ret; return ret;
} }
...@@ -211,7 +211,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata) ...@@ -211,7 +211,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata)
knot_changeset_t *ddns_ch = knot_changesets_get_last(ddns_chs); knot_changeset_t *ddns_ch = knot_changesets_get_last(ddns_chs);
ret = ddns_process_update(zone, query, ddns_ch, rcode); ret = ddns_process_update(zone, query, ddns_ch, rcode);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
knot_changesets_free(&ddns_chs); knot_changesets_free(&ddns_chs, NULL);
return ret; return ret;
} }
...@@ -225,11 +225,11 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata) ...@@ -225,11 +225,11 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata)
} else { } else {
*rcode = KNOT_RCODE_SERVFAIL; *rcode = KNOT_RCODE_SERVFAIL;
} }
knot_changesets_free(&ddns_chs); knot_changesets_free(&ddns_chs, NULL);
return ret; return ret;
} }
} else { } else {
knot_changesets_free(&ddns_chs); knot_changesets_free(&ddns_chs, NULL);
*rcode = KNOT_RCODE_NOERROR; *rcode = KNOT_RCODE_NOERROR;
return KNOT_EOK; return KNOT_EOK;
} }
...@@ -239,7 +239,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata) ...@@ -239,7 +239,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata)
ret = sign_update(zone, zone->contents, new_contents, ddns_ch); ret = sign_update(zone, zone->contents, new_contents, ddns_ch);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
xfrin_rollback_update(ddns_chs, &new_contents); xfrin_rollback_update(ddns_chs, &new_contents);
knot_changesets_free(&ddns_chs); knot_changesets_free(&ddns_chs, NULL);
*rcode = KNOT_RCODE_SERVFAIL; *rcode = KNOT_RCODE_SERVFAIL;
return ret; return ret;
} }
...@@ -249,7 +249,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata) ...@@ -249,7 +249,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata)
ret = zone_change_store(zone, ddns_chs); ret = zone_change_store(zone, ddns_chs);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
xfrin_rollback_update(ddns_chs, &new_contents); xfrin_rollback_update(ddns_chs, &new_contents);
knot_changesets_free(&ddns_chs); knot_changesets_free(&ddns_chs, NULL);
*rcode = KNOT_RCODE_SERVFAIL; *rcode = KNOT_RCODE_SERVFAIL;
return ret; return ret;
} }
...@@ -261,7 +261,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata) ...@@ -261,7 +261,7 @@ static int process_authenticated(uint16_t *rcode, struct query_data *qdata)
xfrin_zone_contents_free(&old_contents); xfrin_zone_contents_free(&old_contents);
xfrin_cleanup_successful_update(ddns_chs); xfrin_cleanup_successful_update(ddns_chs);
knot_changesets_free(&ddns_chs); knot_changesets_free(&ddns_chs, NULL);
/* Trim extra heap. */ /* Trim extra heap. */
mem_trim(); mem_trim();
......
...@@ -862,7 +862,7 @@ static int xfr_task_xfer(xfrhandler_t *xfr, knot_ns_xfr_t *rq, knot_pkt_t *pkt) ...@@ -862,7 +862,7 @@ static int xfr_task_xfer(xfrhandler_t *xfr, knot_ns_xfr_t *rq, knot_pkt_t *pkt)
ret = axfr_process_answer(pkt, rq); ret = axfr_process_answer(pkt, rq);
break; break;
case XFR_TYPE_IIN: case XFR_TYPE_IIN:
ret = ixfr_process_answer(pkt, rq); ret = ixfrin_process_answer(pkt, rq);
break; break;
default: default:
ret = KNOT_EINVAL; ret = KNOT_EINVAL;
......
...@@ -65,7 +65,7 @@ knot_changesets_t *knot_changesets_create(unsigned count) ...@@ -65,7 +65,7 @@ knot_changesets_t *knot_changesets_create(unsigned count)
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
knot_changeset_t *change = knot_changesets_create_changeset(ch); knot_changeset_t *change = knot_changesets_create_changeset(ch);
if (change == NULL) { if (change == NULL) {
knot_changesets_free(&ch); knot_changesets_free(&ch, NULL);
return NULL; return NULL;
} }
} }
...@@ -260,7 +260,7 @@ static void knot_free_changeset(knot_changeset_t *changeset) ...@@ -260,7 +260,7 @@ static void knot_free_changeset(knot_changeset_t *changeset)
free(changeset->data); free(changeset->data);
} }
static void knot_changesets_deinit(knot_changesets_t *changesets) static void knot_changesets_deinit(knot_changesets_t *changesets, mm_ctx_t *rr_mm)
{ {
if (!EMPTY_LIST(changesets->sets)) { if (!EMPTY_LIST(changesets->sets)) {
knot_changeset_t *chg = NULL; knot_changeset_t *chg = NULL;
...@@ -274,28 +274,28 @@ static void knot_changesets_deinit(knot_changesets_t *changesets) ...@@ -274,28 +274,28 @@ static void knot_changesets_deinit(knot_changesets_t *changesets)
// Free pool with RRs in sets / changes // Free pool with RRs in sets / changes
mp_delete(changesets->mmc_rr.ctx); mp_delete(changesets->mmc_rr.ctx);
knot_rrset_free(&changesets->first_soa, NULL); knot_rrset_free(&changesets->first_soa, rr_mm);
} }
void knot_changesets_free(knot_changesets_t **changesets) void knot_changesets_free(knot_changesets_t **changesets, mm_ctx_t *rr_mm)
{ {
if (changesets == NULL || *changesets == NULL) { if (changesets == NULL || *changesets == NULL) {
return; return;
} }
knot_changesets_deinit(*changesets); knot_changesets_deinit(*changesets, rr_mm);
free(*changesets); free(*changesets);
*changesets = NULL; *changesets = NULL;
} }
int knot_changesets_clear(knot_changesets_t *changesets) int knot_changesets_clear(knot_changesets_t *changesets, mm_ctx_t *rr_mm)
{ {
if (changesets == NULL) { if (changesets == NULL) {
return KNOT_EINVAL; return KNOT_EINVAL;
} }
knot_changesets_deinit(changesets); knot_changesets_deinit(changesets, rr_mm);
return knot_changesets_init(changesets); return knot_changesets_init(changesets);
} }
...@@ -101,15 +101,8 @@ typedef enum { ...@@ -101,15 +101,8 @@ typedef enum {
*/ */
knot_changesets_t *knot_changesets_create(unsigned count); knot_changesets_t *knot_changesets_create(unsigned count);
/*!
* \brief Frees the 'changesets' structure, including all its internal data.
*
* \param changesets Double pointer to changesets structure to be freed.
*/
void knot_changesets_free(knot_changesets_t **changesets);
/*! \brief Reinitialize changesets structure. */ /*! \brief Reinitialize changesets structure. */
int knot_changesets_clear(knot_changesets_t *changesets); int knot_changesets_clear(knot_changesets_t *changesets, mm_ctx_t *rr_mm);
/*! /*!
* \brief Creates new changeset structure and returns it to caller. * \brief Creates new changeset structure and returns it to caller.
...@@ -204,9 +197,10 @@ int knot_changeset_apply(knot_changeset_t *changeset, ...@@ -204,9 +197,10 @@ int knot_changeset_apply(knot_changeset_t *changeset,
/*! /*!
* \brief Frees the 'changesets' structure, including all its internal data. * \brief Frees the 'changesets' structure, including all its internal data.
* *
* \param changesets Double pointer to changesets structure to be freed. * \param changesets Double pointer to changesets structure to be freed.
* \param mm Memory context used to allocate RRSets.
*/ */
void knot_changesets_free(knot_changesets_t **changesets); void knot_changesets_free(knot_changesets_t **changesets, mm_ctx_t *rr_mm);
/*! /*!
* \brief Merges two changesets together, second changeset's lists are kept. * \brief Merges two changesets together, second changeset's lists are kept.
......
This diff is collapsed.
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "knot/updates/changesets.h" #include "knot/updates/changesets.h"
struct xfr_proc; struct xfr_proc;
struct ixfrin_proc;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
...@@ -100,7 +101,7 @@ void xfrin_free_changesets(knot_changesets_t **changesets); ...@@ -100,7 +101,7 @@ void xfrin_free_changesets(knot_changesets_t **changesets);
* \retval KNOT_EMALF * \retval KNOT_EMALF
* \retval KNOT_ENOMEM * \retval KNOT_ENOMEM
*/ */
int xfrin_process_ixfr_packet(knot_pkt_t *pkt, knot_ns_xfr_t *xfr); int xfrin_process_ixfr_packet(knot_pkt_t *pkt, struct ixfrin_proc *proc);
/*! /*!
* \brief Applies changesets *with* zone shallow copy. * \brief Applies changesets *with* zone shallow copy.
......
...@@ -441,8 +441,7 @@ static int event_dnssec(zone_t *zone) ...@@ -441,8 +441,7 @@ static int event_dnssec(zone_t *zone)
} }
if (!knot_changesets_empty(chs)) { if (!knot_changesets_empty(chs)) {
zone_contents_t *new_c = NULL; ret = zone_change_apply_and_store(chs, zone, "DNSSEC", NULL);
ret = zone_change_apply_and_store(chs, zone, &new_c, "DNSSEC");
chs = NULL; // freed by zone_change_apply_and_store() chs = NULL; // freed by zone_change_apply_and_store()
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
log_zone_error("%s Could not sign zone (%s).\n", log_zone_error("%s Could not sign zone (%s).\n",
...@@ -461,7 +460,7 @@ static int event_dnssec(zone_t *zone) ...@@ -461,7 +460,7 @@ static int event_dnssec(zone_t *zone)
} }
done: done:
knot_changesets_free(&chs); knot_changesets_free(&chs, NULL);
free(msgpref); free(msgpref);
return ret; return ret;
} }
......
...@@ -99,7 +99,7 @@ int zone_load_journal(zone_contents_t *contents, conf_zone_t *conf) ...@@ -99,7 +99,7 @@ int zone_load_journal(zone_contents_t *contents, conf_zone_t *conf)
/*! \todo Check what should be the upper bound. */ /*! \todo Check what should be the upper bound. */
int ret = journal_load_changesets(conf->ixfr_db, chsets, serial, serial - 1); int ret = journal_load_changesets(conf->ixfr_db, chsets, serial, serial - 1);
if ((ret != KNOT_EOK && ret != KNOT_ERANGE) || EMPTY_LIST(chsets->sets)) { if ((ret != KNOT_EOK && ret != KNOT_ERANGE) || EMPTY_LIST(chsets->sets)) {
knot_changesets_free(&chsets); knot_changesets_free(&chsets, NULL);
/* Absence of records is not an error. */ /* Absence of records is not an error. */
if (ret == KNOT_ENOENT) { if (ret == KNOT_ENOENT) {
return KNOT_EOK; return KNOT_EOK;
...@@ -115,7 +115,7 @@ int zone_load_journal(zone_contents_t *contents, conf_zone_t *conf) ...@@ -115,7 +115,7 @@ int zone_load_journal(zone_contents_t *contents, conf_zone_t *conf)
serial, zone_contents_serial(contents), serial, zone_contents_serial(contents),
knot_strerror(ret)); knot_strerror(ret));
knot_changesets_free(&chsets); knot_changesets_free(&chsets, NULL);
return ret; return ret;
} }
...@@ -137,7 +137,7 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone) ...@@ -137,7 +137,7 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone)
if (conf->dnssec_enable) { if (conf->dnssec_enable) {
change = zone_change_prepare(chset); change = zone_change_prepare(chset);
if (change == NULL) { if (change == NULL) {
knot_changesets_free(&chset); knot_changesets_free(&chset, NULL);
return KNOT_ENOMEM; return KNOT_ENOMEM;
} }
...@@ -153,13 +153,13 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone) ...@@ -153,13 +153,13 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone)
/* Commit existing zone change and prepare new. */ /* Commit existing zone change and prepare new. */
int ret = zone_change_commit(new_contents, chset); int ret = zone_change_commit(new_contents, chset);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
knot_changesets_free(&chset); knot_changesets_free(&chset, NULL);
return ret; return ret;
} else { } else {
knot_changesets_clear(chset); knot_changesets_clear(chset, NULL);
change = zone_change_prepare(chset); change = zone_change_prepare(chset);
if (change == NULL) { if (change == NULL) {
knot_changesets_free(&chset); knot_changesets_free(&chset, NULL);
return KNOT_ENOMEM; return KNOT_ENOMEM;
} }
} }
...@@ -182,7 +182,7 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone) ...@@ -182,7 +182,7 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone)
if (ret == KNOT_EOK) { if (ret == KNOT_EOK) {
ret = zone_change_commit(new_contents, chset); ret = zone_change_commit(new_contents, chset);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
knot_changesets_free(&chset); knot_changesets_free(&chset, NULL);
return ret; return ret;
} }
...@@ -191,7 +191,7 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone) ...@@ -191,7 +191,7 @@ int zone_load_post(zone_contents_t *new_contents, zone_t *zone)
} }
/* Free changesets and return. */ /* Free changesets and return. */
knot_changesets_free(&chset); knot_changesets_free(&chset, NULL);
return ret; return ret;
} }
......
...@@ -188,17 +188,18 @@ int zone_change_store(zone_t *zone, knot_changesets_t *chset) ...@@ -188,17 +188,18 @@ int zone_change_store(zone_t *zone, knot_changesets_t *chset)
/*! \note @mvavrusa Moved from zones.c, this needs a common API. */ /*! \note @mvavrusa Moved from zones.c, this needs a common API. */
int zone_change_apply_and_store(knot_changesets_t *chs, int zone_change_apply_and_store(knot_changesets_t *chs,
zone_t *zone, zone_t *zone,
zone_contents_t **new_contents, const char *msgpref,
const char *msgpref) mm_ctx_t *rr_mm)
{ {
int ret = KNOT_EOK; int ret = KNOT_EOK;
/* Now, try to apply the changesets to the zone. */ /* Now, try to apply the changesets to the zone. */
ret = xfrin_apply_changesets(zone, chs, new_contents); zone_contents_t *new_contents;
ret = xfrin_apply_changesets(zone, chs, &new_contents);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
log_zone_error("%s Failed to apply changesets.\n", msgpref); log_zone_error("%s Failed to apply changesets.\n", msgpref);
/* Free changesets, but not the data. */ /* Free changesets, but not the data. */
knot_changesets_free(&chs); knot_changesets_free(&chs, rr_mm);
return ret; // propagate the error above return ret; // propagate the error above
} }
...@@ -206,19 +207,19 @@ int zone_change_apply_and_store(knot_changesets_t *chs, ...@@ -206,19 +207,19 @@ int zone_change_apply_and_store(knot_changesets_t *chs,
ret = zone_change_store(zone, chs); ret = zone_change_store(zone, chs);
if (ret != KNOT_EOK) { if (ret != KNOT_EOK) {
log_zone_error("%s Failed to store changesets.\n", msgpref); log_zone_error("%s Failed to store changesets.\n", msgpref);
xfrin_rollback_update(chs, new_contents); xfrin_rollback_update(chs, &new_contents);
/* Free changesets, but not the data. */ /* Free changesets, but not the data. */
knot_changesets_free(&chs); knot_changesets_free(&chs, rr_mm);
return ret; // propagate the error above return ret; // propagate the error above
} }
/* Switch zone contents. */ /* Switch zone contents. */
zone_contents_t *old_contents = xfrin_switch_zone(zone, *new_contents); zone_contents_t *old_contents = xfrin_switch_zone(zone, new_contents);
xfrin_zone_contents_free(&old_contents); xfrin_zone_contents_free(&old_contents);
/* Free changesets, but not the data. */ /* Free changesets, but not the data. */
xfrin_cleanup_successful_update(chs); xfrin_cleanup_successful_update(chs);
knot_changesets_free(&chs); knot_changesets_free(&chs, rr_mm);
assert(ret == KNOT_EOK); assert(ret == KNOT_EOK);
return KNOT_EOK; return KNOT_EOK;
} }
......
...@@ -118,8 +118,8 @@ int zone_change_store(zone_t *zone, knot_changesets_t *chset); ...@@ -118,8 +118,8 @@ int zone_change_store(zone_t *zone, knot_changesets_t *chset);
/*! \note @mvavrusa Moved from zones.c, this needs a common API. */ /*! \note @mvavrusa Moved from zones.c, this needs a common API. */
int zone_change_apply_and_store(knot_changesets_t *chs, int zone_change_apply_and_store(knot_changesets_t *chs,
zone_t *zone, zone_t *zone,
zone_contents_t **new_contents, const char *msgpref,
const char *msgpref); mm_ctx_t *rr_mm);
/*! /*!
* \brief Atomically switch the content of the zone. * \brief Atomically switch the content of the zone.
*/ */
......
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