Commit 4baf7353 authored by Jan Kadlec's avatar Jan Kadlec

zone-events: Initial DDNS reimplementation.

 - Simpler DDNS signing, simpler changeset merging (todo: fix leaks)
 - Removed some needles helper functions and zone adjusting
parent 0fafc364
......@@ -179,11 +179,7 @@ int knot_dnssec_sign_changeset(const zone_contents_t *zone,
knot_changeset_t *out_ch,
uint32_t *refresh_at)
{
if (!refresh_at) {
return KNOT_EINVAL;
}
if (zone == NULL || in_ch == NULL || out_ch == NULL) {
if (!refresh_at || zone == NULL || in_ch == NULL || out_ch == NULL) {
return KNOT_EINVAL;
}
......
......@@ -477,7 +477,12 @@ static const zone_t *answer_zone_find(const knot_pkt_t *query, knot_zonedb_t *zo
*/
}
if (zone == NULL) {
zone = knot_zonedb_find_suffix(zonedb, qname);
if (knot_pkt_type(query) != KNOT_QUERY_UPDATE) {
zone = knot_zonedb_find_suffix(zonedb, qname);
} else {
// Direct matches only for DDNS.
zone = knot_zonedb_find(zonedb, qname);
}
}
return zone;
......
This diff is collapsed.
......@@ -42,7 +42,17 @@ int update_answer(knot_pkt_t *pkt, struct query_data *qdata);
/*! \brief Process already authenticated packet. */
int zones_process_update_auth(zone_t *zone, const knot_pkt_t *query);
/*!
* \brief Processes serialized packet with DDNS. Function expects that the
* query is already authenticated and TSIG signature is verified.
*
* \param zone Zone to be updated.
* \param query Packet containing DDNS.
* \param rcode Output response code.
*
* \return KNOT_E*
*/
int process_ddns_pkt(zone_t *zone, const knot_pkt_t *query, uint16_t *rcode);
#endif /* _KNOT_UPDATE_H_ */
......
......@@ -299,45 +299,3 @@ int knot_changesets_clear(knot_changesets_t *changesets)
return knot_changesets_init(changesets);
}
void knot_changesets_free_merged(knot_changesets_t *diff_chs,
knot_changesets_t *sec_chs)
{
/*!
* Merged changesets freeing can be quite complicated, since there
* are several cases to handle. (NULL and empty changesets)
*/
if (diff_chs == NULL && sec_chs == NULL) {
return;
} else if (diff_chs == NULL && sec_chs != NULL) {
knot_changesets_free(&sec_chs);
} else if (sec_chs == NULL && diff_chs != NULL) {
knot_changesets_free(&diff_chs);
} else {
/*!
* Merged changesets, deep free 'diff_chs',
* shallow free 'sec_chs', unless one of them is empty.
*/
if (knot_changesets_empty(sec_chs) || knot_changesets_empty(diff_chs)) {
if (knot_changesets_get_last(diff_chs)->soa_to) {
knot_changesets_get_last(diff_chs)->soa_to = NULL;
}
knot_changesets_free(&sec_chs);
knot_changesets_free(&diff_chs);
} else {
assert(knot_changesets_get_last(diff_chs)->serial_to ==
knot_changesets_get_last(sec_chs)->serial_to);
knot_changesets_free(&diff_chs);
/*!
* From SOAs from the second changeset was not used,
* it must be freed.
*/
knot_rrset_free(&(knot_changesets_get_last(sec_chs)->soa_from),
NULL);
// Reset sec_chs' chngeset list, else we'd double free.
init_list(&sec_chs->sets);
knot_changesets_free(&sec_chs);
}
}
}
\ No newline at end of file
......@@ -223,10 +223,6 @@ void knot_changesets_free(knot_changesets_t **changesets);
*/
int knot_changeset_merge(knot_changeset_t *ch1, knot_changeset_t *ch2);
/*! \note @mvavrusa Moved from zones.c, this should be gone soon. */
void knot_changesets_free_merged(knot_changesets_t *diff_chs,
knot_changesets_t *sec_chs);
#endif /* _KNOT_CHANGESETS_H_ */
/*! @} */
......@@ -934,8 +934,8 @@ static uint16_t ret_to_rcode(int ret)
/* ---------------------------------- API ----------------------------------- */
int knot_ddns_process_prereqs(const knot_pkt_t *query, const zone_contents_t *zone,
uint16_t *rcode)
int ddns_process_prereqs(const knot_pkt_t *query, const zone_contents_t *zone,
uint16_t *rcode)
{
if (query == NULL || rcode == NULL || zone == NULL) {
return KNOT_EINVAL;
......@@ -962,10 +962,8 @@ int knot_ddns_process_prereqs(const knot_pkt_t *query, const zone_contents_t *zo
return ret;
}
int knot_ddns_process_update(const zone_t *zone,
const knot_pkt_t *query,
knot_changeset_t *changeset,
uint16_t *rcode)
int ddns_process_update(const zone_t *zone, const knot_pkt_t *query,
knot_changeset_t *changeset, uint16_t *rcode)
{
if (zone == NULL || query == NULL || changeset == NULL || rcode == NULL) {
return KNOT_EINVAL;
......@@ -983,7 +981,6 @@ int knot_ddns_process_update(const zone_t *zone,
/* Process all RRs the Authority (Update) section. */
dbg_ddns("Processing UPDATE section.\n");
int apex_ns_rem = 0;
const knot_pktsection_t *authority = knot_pkt_section(query, KNOT_AUTHORITY);
for (uint16_t i = 0; i < authority->count; ++i) {
......
......@@ -42,9 +42,8 @@
*
* \return KNOT_E*
*/
int knot_ddns_process_prereqs(const knot_pkt_t *query,
const zone_contents_t *zone,
uint16_t *rcode);
int ddns_process_prereqs(const knot_pkt_t *query, const zone_contents_t *zone,
uint16_t *rcode);
/*!
* \brief Processes DNS update and creates a changeset out of it. Zone is left
......@@ -57,10 +56,8 @@ int knot_ddns_process_prereqs(const knot_pkt_t *query,
*
* \return KNOT_E*
*/
int knot_ddns_process_update(const zone_t *zone,
const knot_pkt_t *query,
knot_changeset_t *changeset,
uint16_t *rcode);
int ddns_process_update(const zone_t *zone, const knot_pkt_t *query,
knot_changeset_t *changeset, uint16_t *rcode);
#endif /* _KNOT_DDNS_H_ */
......
......@@ -1116,31 +1116,6 @@ int xfrin_apply_changesets_directly(zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
/* Post-DDNS application, no need to shallow copy. */
int xfrin_apply_changesets_dnssec_ddns(zone_contents_t *z_new,
knot_changesets_t *sec_chsets,
knot_changesets_t *chsets)
{
if (z_new == NULL || sec_chsets == NULL || chsets == NULL) {
return KNOT_EINVAL;
}
/* Set generation to old. Zone should be long locked at this point. */
zone_contents_set_gen_old(z_new);
/* Apply changes. */
int ret = xfrin_apply_changesets_directly(z_new, sec_chsets);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to apply changesets to zone: "
"%s\n", knot_strerror(ret));
return ret;
}
return ret;
}
/*----------------------------------------------------------------------------*/
int xfrin_apply_changesets(zone_t *zone,
knot_changesets_t *chsets,
zone_contents_t **new_contents)
......
......@@ -114,22 +114,6 @@ int xfrin_apply_changesets(zone_t *zone,
knot_changesets_t *chsets,
zone_contents_t **new_contents);
/*!
* \brief Applies DNSSEC changesets after DDNS.
*
* \param z_new Post DDNS/reload zone.
* \param sec_chsets Changes with RRSIGs/NSEC(3)s.
* \param chsets DDNS/reload changes, for rollback.
* \return KNOT_E*
*
* This function does not do shallow copy of the zone, as it is already created
* by the UPDATE-processing function. It uses new and old zones from this
* operation.
*/
int xfrin_apply_changesets_dnssec_ddns(zone_contents_t *z_new,
knot_changesets_t *sec_chsets,
knot_changesets_t *chsets);
/*!
* \brief Applies changesets directly to the zone, without copying it.
*
......
......@@ -1165,18 +1165,6 @@ int zone_contents_adjust_pointers(zone_contents_t *contents)
/*----------------------------------------------------------------------------*/
int zone_contents_adjust_nsec3_pointers(zone_contents_t *contents)
{
// adjusting parameters
zone_adjust_arg_t adjust_arg = { .first_node = NULL,
.previous_node = NULL,
.zone = contents };
return zone_contents_adjust_nodes(contents->nodes, &adjust_arg,
adjust_nsec3_pointers);
}
/*----------------------------------------------------------------------------*/
int zone_contents_adjust_full(zone_contents_t *zone,
zone_node_t **first_nsec3_node,
zone_node_t **last_nsec3_node)
......
......@@ -193,11 +193,6 @@ const zone_node_t *zone_contents_find_wildcard_child(const zone_contents_t *cont
*/
int zone_contents_adjust_pointers(zone_contents_t *contents);
/*!
* \brief Sets NSEC3 nodes for normal nodes. (costly operation, calculates hash)
*/
int zone_contents_adjust_nsec3_pointers(zone_contents_t *);
/*!
* \brief Sets parent and previous pointers, sets node flags and NSEC3 links.
* This has to be called before the zone can be served.
......
......@@ -309,24 +309,57 @@ static int event_xfer(zone_t *zone)
return ret;
}
static knot_pkt_t *create_ddns_resp(const knot_pkt_t *query, uint16_t rcode)
{
knot_pkt_t *resp = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
if (resp == KNOT_EOK) {
return NULL;
}
int ret = knot_pkt_init_response(resp, query);
if (ret != KNOT_EOK) {
knot_pkt_free(&resp);
}
knot_wire_set_rcode(resp->wire, rcode);
return resp;
}
static int event_update(zone_t *zone)
{
assert(zone);
fprintf(stderr, "UPDATE of '%s'\n", zone->conf->name);
fprintf(stderr, "UPDATE of '%s' started.\n", zone->conf->name);
struct request_data *update = zone_update_dequeue(zone);
if (update == NULL) {
return KNOT_EOK; /* No scheduled data. */
assert(update);
uint16_t rcode = KNOT_RCODE_NOERROR;
const uint32_t old_serial = zone_contents_serial(zone->contents);
int ret = process_ddns_pkt(zone, update->query, &rcode);
const uint32_t new_serial = zone_contents_serial(zone->contents);
if (old_serial != new_serial) {
fprintf(stderr, "UPDATE of '%s': finished: %s\n.",
zone->conf->name, knot_strerror(ret));
} else {
fprintf(stderr, "UPDATE of '%s': No change to zone made.\n",
zone->conf->name);
}
knot_pkt_t *resp = create_ddns_resp(update->query, rcode);
if (resp == NULL) {
knot_pkt_free(&resp);
knot_pkt_free(&update->query);
return KNOT_ENOMEM;
}
int ret = zones_process_update_auth(zone, update->query);
#warning TODO: prepare response based on the result
// Send response to knsupdate.
sendto(update->fd, resp->wire, resp->size, 0,
(struct sockaddr *)update->remote, sockaddr_len(update->remote));
#warning TODO: prettier cleanup
knot_pkt_free(&resp);
knot_pkt_free(&update->query);
free(update);
#warning TODO: reschedule or loop until the queue is empty
return ret;
}
......
......@@ -66,6 +66,17 @@ static int set_acl(acl_t **acl, list_t* acl_list)
return KNOT_EOK;
}
static void free_ddns_q(zone_t *z)
{
struct request_data *n = NULL;
node_t *nxt = NULL;
WALK_LIST_DELSAFE(n, nxt, z->ddns_queue) {
knot_pkt_free(&n->query);
rem_node((node_t *)n);
free(n);
}
}
zone_t* zone_new(conf_zone_t *conf)
{
if (!conf) {
......@@ -121,6 +132,7 @@ void zone_free(zone_t **zone_ptr)
acl_delete(&zone->xfr_out);
acl_delete(&zone->notify_in);
acl_delete(&zone->update_in);
free_ddns_q(zone);
pthread_mutex_destroy(&zone->ddns_lock);
/* Free assigned config. */
......@@ -298,6 +310,8 @@ int zone_flush_journal(zone_t *zone)
int zone_update_enqueue(zone_t *zone, knot_pkt_t *pkt, struct process_query_param *param)
{
/* Create serialized request. */
struct request_data *req = malloc(sizeof(struct request_data));
if (req == NULL) {
return KNOT_ENOMEM;
......@@ -305,7 +319,7 @@ int zone_update_enqueue(zone_t *zone, knot_pkt_t *pkt, struct process_query_para
memset(req, 0, sizeof(struct request_data));
req->fd = param->socket;
req->origin = param->remote;
req->remote = param->remote;
req->query = knot_pkt_copy(pkt, NULL);
if (req->query == NULL) {
free(req);
......@@ -313,15 +327,15 @@ int zone_update_enqueue(zone_t *zone, knot_pkt_t *pkt, struct process_query_para
}
pthread_mutex_lock(&zone->ddns_lock);
/* Schedule UPDATE event if this is a first item in the list. */
if (EMPTY_LIST(zone->ddns_queue)) {
zone_events_schedule(zone, ZONE_EVENT_UPDATE, ZONE_EVENT_NOW);
}
/* Enqueue created request. */
#warning TODO: scan the queue if the same source/msgid is not already enqueued
add_tail(&zone->ddns_queue, (node_t *)req);
pthread_mutex_unlock(&zone->ddns_lock);
/* Schedule UPDATE event. If already scheduled, older event will stay. */
zone_events_schedule(zone, ZONE_EVENT_UPDATE, ZONE_EVENT_NOW);
return KNOT_EOK;
}
......@@ -331,13 +345,10 @@ struct request_data *zone_update_dequeue(zone_t *zone)
return NULL;
}
struct request_data *ret = NULL;
pthread_mutex_lock(&zone->ddns_lock);
if (!EMPTY_LIST(zone->ddns_queue)) {
ret = HEAD(zone->ddns_queue);
rem_node((node_t *)ret);
}
assert(!EMPTY_LIST(zone->ddns_queue));
struct request_data *ret = HEAD(zone->ddns_queue);
rem_node((node_t *)ret);
pthread_mutex_unlock(&zone->ddns_lock);
return ret;
......
......@@ -228,7 +228,10 @@ knot_pkt_t *knot_pkt_copy(const knot_pkt_t *pkt, mm_ctx_t *mm)
}
/* @note This could be done more effectively if needed. */
knot_pkt_parse(copy, 0);
int ret = knot_pkt_parse(copy, 0);
if (ret != KNOT_EOK) {
knot_pkt_free(&copy);
}
return 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