Commit a5af9e4d authored by Jan Kadlec's avatar Jan Kadlec

zone-events: Moved IXFR-in processing from xfr-in.c to ixfr.c

parent 00145bbc
This diff is collapsed.
......@@ -35,24 +35,6 @@ struct query_data;
struct answer_data;
struct xfr_proc;
/*! \brief IXFR-in processing states. */
enum ixfrin_states {
IXFR_START = 0, /* IXFR-in starting, expecting final SOA. */
IXFR_SOA_FROM = 1, /* Expecting starting SOA. */
IXFR_SOA_TO = 2, /* Expecting ending SOA. */
IXFR_DEL = 3, /* Expecting RR to delete. */
IXFR_ADD = 4, /* Expecting RR to add. */
IXFR_DONE = 5 /* Processing done, IXFR-in complete. */
};
/*! \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.
*
......@@ -63,27 +45,11 @@ struct ixfrin_proc {
int ixfr_query(knot_pkt_t *pkt, struct query_data *qdata);
/*!
* \brief Process an IXFR query response.
*
* \param pkt Processed packet.
* \param xfr Persistent transfer-specific data.
*
* \retval KNOT_EOK If this packet was processed successfuly and another packet
* is expected. (RFC1995bis, case c)
* \retval KNOT_ENOXFR If the transfer is not taking place because server's
* SERIAL is the same as this client's SERIAL. The client
* should close the connection and do no further processing.
* (RFC1995bis case a).
* \retval KNOT_EAGAIN If the server could not fit the transfer into the packet.
* This should happen only if UDP was used. In this case
* the client should retry the request via TCP. If UDP was
* not used, it should be considered that the transfer was
* malformed and the connection should be closed.
* (RFC1995bis case b).
* \retval >0 Transfer successully finished. Changesets are created and furter
* processing is needed.
* \retval Other If any other error occured. The connection should be closed.
* \brief IXFR query response processing module.
*
* \retval MORE if more data are required.
* \retval FAIL if it encountered an error, retry over AXFR will be done.
* \retval DONE if finished.
*/
int ixfrin_process_answer(knot_pkt_t *pkt, struct answer_data *adata);
......
......@@ -114,6 +114,7 @@ int xfrin_transfer_needed(const zone_contents_t *zone,
static int xfrin_check_tsig(knot_pkt_t *packet, knot_ns_xfr_t *xfr,
int tsig_req)
{
#warning reimplement, but not inside this file
assert(packet != NULL);
assert(xfr != NULL);
......@@ -254,204 +255,6 @@ int xfrin_process_axfr_packet(knot_pkt_t *pkt, struct xfr_proc *proc)
/*----------------------------------------------------------------------------*/
/* ------------------------- IXFR-in processing ----------------------------- */
/*! \brief Stores starting SOA into changesets structure. */
static int solve_start(const knot_rrset_t *rr, knot_changesets_t *changesets, mm_ctx_t *mm)
{
assert(changesets->first_soa == NULL);
if (rr->type != KNOT_RRTYPE_SOA) {
return NS_PROC_FAIL;
}
// Store the first SOA for later use.
changesets->first_soa = knot_rrset_copy(rr, mm);
if (changesets->first_soa == NULL) {
return NS_PROC_FAIL;
}
return NS_PROC_MORE;
}
/*!
* \brief Decides what to do with a starting SOA - either ends the processing or
* creates a new changeset and stores the SOA into it.
*/
static int solve_soa_from(const knot_rrset_t *rr, knot_changesets_t *changesets,
int *state, mm_ctx_t *mm)
{
if (rr->type != KNOT_RRTYPE_SOA) {
return NS_PROC_FAIL;
}
if (knot_rrset_equal(rr, changesets->first_soa, KNOT_RRSET_COMPARE_WHOLE)) {
// Last SOA encountered, transfer done.
*state = IXFR_DONE;
return NS_PROC_DONE;
}
// Create new changeset.
knot_changeset_t *change = knot_changesets_create_changeset(changesets);
if (change == NULL) {
return NS_PROC_FAIL;
}
// Store SOA into changeset.
change->soa_from = knot_rrset_copy(rr, mm);
if (change->soa_from == NULL) {
return NS_PROC_FAIL;
}
change->serial_from = knot_soa_serial(&rr->rrs);
return NS_PROC_MORE;
}
/*! \brief Stores ending SOA into changeset. */
static int solve_soa_to(const knot_rrset_t *rr, knot_changeset_t *change, mm_ctx_t *mm)
{
if (rr->type != KNOT_RRTYPE_SOA) {
return NS_PROC_FAIL;
}
change->soa_to= knot_rrset_copy(rr, mm);
if (change->soa_to == NULL) {
return NS_PROC_FAIL;
}
change->serial_to = knot_soa_serial(&rr->rrs);
return NS_PROC_MORE;
}
/*! \brief Adds single RR into given section of changeset. */
static int add_part(const knot_rrset_t *rr, knot_changeset_t *change, int part, mm_ctx_t *mm)
{
assert(rr->type != KNOT_RRTYPE_SOA);
knot_rrset_t *copy = knot_rrset_copy(rr, mm);
if (copy) {
int ret = knot_changeset_add_rrset(change, copy, part);
if (ret != KNOT_EOK) {
return NS_PROC_FAIL;
} else {
return NS_PROC_MORE;
}
} else {
return NS_PROC_FAIL;
}
}
/*! \brief Adds single RR into REMOVE section of changeset. */
static int solve_del(const knot_rrset_t *rr, knot_changeset_t *change, mm_ctx_t *mm)
{
return add_part(rr, change, KNOT_CHANGESET_REMOVE, mm);
}
/*! \brief Adds single RR into ADD section of changeset. */
static int solve_add(const knot_rrset_t *rr, knot_changeset_t *change, mm_ctx_t *mm)
{
return add_part(rr, change, KNOT_CHANGESET_ADD, mm);
}
/*!
* \brief Processes single RR according to current IXFR-in state. The states
* correspond with IXFR-in message structure, in the order they are
* mentioned in the code.
* \param rr RR to process.
* \param changesets Output changesets.
* \param state Current IXFR-in state.
* \param next Output parameter - set to true if next RR should be fetched.
* \param mm Memory context used to create RR copies.
* \return NS_PROC_MORE, NS_PROC_DONE, NS_PROC_FAIL.
*/
static int ixfrin_step(const knot_rrset_t *rr, knot_changesets_t *changesets,
int *state, bool *next, mm_ctx_t *mm)
{
switch (*state) {
case IXFR_START:
*state = IXFR_SOA_FROM;
*next = true;
return solve_start(rr, changesets, mm);
case IXFR_SOA_FROM:
*state = IXFR_DEL;
*next = true;
return solve_soa_from(rr, changesets, state, mm);
case IXFR_DEL:
if (rr->type == KNOT_RRTYPE_SOA) {
// Encountered SOA, do not consume the RR.
*state = IXFR_SOA_TO;
*next = false;
return NS_PROC_MORE;
}
*next = true;
return solve_del(rr, knot_changesets_get_last(changesets), mm);
case IXFR_SOA_TO:
*state = IXFR_ADD;
*next = true;
return solve_soa_to(rr, knot_changesets_get_last(changesets), mm);
case IXFR_ADD:
if (rr->type == KNOT_RRTYPE_SOA) {
// Encountered SOA, do not consume the RR.
*state = IXFR_SOA_FROM;
*next = false;
return NS_PROC_MORE;
}
*next = true;
return solve_add(rr, knot_changesets_get_last(changesets), mm);
default:
return NS_PROC_FAIL;
}
}
/*! \brief Checks whether journal node limit has not been exceeded. */
static bool journal_limit_exceeded(struct ixfrin_proc *proc)
{
return proc->changesets->count > JOURNAL_NCOUNT;
}
/*! \brief Checks whether RR belongs into zone. */
static bool out_of_zone(const knot_rrset_t *rr, struct ixfrin_proc *proc)
{
return !knot_dname_is_sub(rr->owner, proc->zone->name) &&
!knot_dname_is_equal(rr->owner, proc->zone->name);
}
int xfrin_process_ixfr_packet(knot_pkt_t *pkt, struct ixfrin_proc *proc)
{
uint16_t rr_id = 0;
knot_changesets_t *changesets = proc->changesets;
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
const knot_rrset_t *rr = NULL;
xfrin_take_rr(answer, &rr, &rr_id);
int ret = NS_PROC_NOOP;
while (rr) {
if (journal_limit_exceeded(proc)) {
// Will revert to AXFR.
assert(proc->state != IXFR_DONE);
return NS_PROC_DONE;
}
if (out_of_zone(rr, proc)) {
xfrin_take_rr(answer, &rr, &rr_id);
continue;
}
// Process RR.
bool next = false;
ret = ixfrin_step(rr, changesets, &proc->state, &next, proc->mm);
if (ret == NS_PROC_FAIL || ret == NS_PROC_DONE) {
// Quit on errors and if we're done.
return ret;
}
if (next) {
xfrin_take_rr(answer, &rr, &rr_id);
}
}
#warning TODO TSIG
assert(ret == NS_PROC_MORE);
return ret;
}
/*----------------------------------------------------------------------------*/
/* Applying changesets to zone */
/*----------------------------------------------------------------------------*/
......
......@@ -79,16 +79,6 @@ int xfrin_transfer_needed(const zone_contents_t *zone,
*/
int xfrin_process_axfr_packet(knot_pkt_t *pkt, struct xfr_proc *proc);
/*!
* \brief Parses IXFR reply packet and fills in the changesets structure.
*
* \param pkt Packet containing the IXFR reply in wire format.
* \param proc Processing context.
*
* \return NS_PROC_MORE, NS_PROC_DONE, NS_PROC_FAIL
*/
int xfrin_process_ixfr_packet(knot_pkt_t *pkt, struct ixfrin_proc *proc);
/*!
* \brief Applies changesets *with* zone shallow copy.
*
......
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