Commit 4a259c01 authored by Marek Vavrusa's avatar Marek Vavrusa

Partially ported server to dname reference counting.

No leaks so far with server execution.

* Newly created dnames have refcount=1, caller is responsible for releasing them.
* Copied dnames have also refcount=1 (as they are new).

To do:
* Carefully implement more uses of dname not protected by refcounting.
* Consider renaming dnslib_dname_copy() do _duplicate() as it creates duplicate.
* Consider shallow copying of dname, as it's possible with refcounting.
* Test and review.

Commit refs #993.
parent 5198980f
......@@ -49,7 +49,7 @@ static int compare_dname_table_nodes(struct dname_table_node *n1,
static void delete_dname_table_node(struct dname_table_node *node, void *data)
{
if (data) {
dnslib_dname_free(&node->dname);
dnslib_dname_release(node->dname);
}
/*!< \todo it would be nice to set pointers to NULL. */
......@@ -160,6 +160,9 @@ int dnslib_dname_table_add_dname(dnslib_dname_table_t *table,
// printf("Inserted dname got id %d\n", node->dname->id);
assert(node->dname->id != 0);
/* Increase reference counter. */
dnslib_dname_retain(dname);
TREE_INSERT(table->tree, dname_table_node, avl, node);
return DNSLIB_EOK;
}
......@@ -189,7 +192,9 @@ int dnslib_dname_table_add_dname2(dnslib_dname_table_t *table,
// name = dnslib_dname_to_str(found_dname);
// printf("Already there: %s (%p)\n", name, found_dname);
// free(name);
dnslib_dname_free(dname);
/*! \todo Release or free? We didn't retain it, so why release? */
dnslib_dname_release(*dname);
*dname = found_dname;
return 1;
}
......
......@@ -14,6 +14,10 @@
#include "dnslib/utils.h"
#include "dnslib/wire.h"
/*! \todo dnames allocated from TLS cache will be discarded after thread
* termination. This shouldn't happpen.
*/
#if 0
/*
* Memory cache.
*/
......@@ -46,6 +50,7 @@ static void dnslib_dname_cache_init()
(void) pthread_key_create(&dname_ckey, dnslib_dname_cache_free);
atexit(dnslib_dname_cache_main_free); // Main thread cleanup
}
#endif
/*!
* \brief Allocate item from thread cache.
......@@ -56,6 +61,10 @@ static dnslib_dname_t* dnslib_dname_alloc()
{
return malloc(sizeof(dnslib_dname_t));
/*! \todo dnames allocated from TLS cache will be discarded after thread
* termination. This shouldn't happpen.
*/
#if 0
/* Initialize dname cache TLS key. */
(void)pthread_once(&dname_once, dnslib_dname_cache_init);
......@@ -73,6 +82,7 @@ static dnslib_dname_t* dnslib_dname_alloc()
}
return slab_cache_alloc(cache);
#endif
}
/*----------------------------------------------------------------------------*/
......@@ -326,6 +336,13 @@ DEBUG_DNSLIB_DNAME(
return 0;
}
/*! \brief Destructor for reference counter. */
static void dnslib_dname_dtor(struct ref_t *p)
{
dnslib_dname_t *dname = (dnslib_dname_t *)p;
dnslib_dname_free(&dname);
}
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
......@@ -340,6 +357,12 @@ dnslib_dname_t *dnslib_dname_new()
dname->label_count = -1;
dname->id = 0;
/* Initialize reference counting. */
ref_init(&dname->ref, dnslib_dname_dtor);
/* Set reference counter to 1, caller should release it after use. */
dnslib_dname_retain(dname);
return dname;
}
......@@ -411,7 +434,7 @@ dnslib_dname_t *dnslib_dname_new_from_wire(const uint8_t *name, uint size,
return NULL;
}
dnslib_dname_t *dname = dnslib_dname_alloc();
dnslib_dname_t *dname = dnslib_dname_new();
if (dname == NULL) {
ERR_ALLOC_FAILED;
......@@ -490,7 +513,7 @@ dnslib_dname_t *dnslib_dname_parse_from_wire(const uint8_t *wire,
*pos += 1;
}
dnslib_dname_t *dname = dnslib_dname_alloc();
dnslib_dname_t *dname = dnslib_dname_new();
if (dname == NULL) {
ERR_ALLOC_FAILED;
......
......@@ -14,6 +14,7 @@
#include <stdint.h>
#include <string.h>
#include "common/ref.h"
struct dnslib_node;
......@@ -26,6 +27,7 @@ struct dnslib_node;
* \todo Consider restricting to FQDN only (see dnslib_dname_new_from_str()).
*/
struct dnslib_dname {
ref_t ref; /*!< Reference counting. */
uint8_t *name; /*!< Wire format of the domain name. */
/*!
* \brief Size of the domain name in octets.
......@@ -45,6 +47,9 @@ typedef struct dnslib_dname dnslib_dname_t;
/*!
* \brief Creates empty dname structure (no name, no owner node).
*
* \note Newly created dname is referenced, caller is responsible for releasing
* it after use.
*
* \return Newly allocated and initialized dname structure.
*
* \todo Possibly useless.
......@@ -58,6 +63,9 @@ dnslib_dname_t *dnslib_dname_new();
* The resulting domain name is stored in wire format, but it may not end with
* root label (0).
*
* \note Newly created dname is referenced, caller is responsible for releasing
* it after use.
*
* \param name Domain name in presentation format (labels separated by dots).
* \param size Size of the domain name (count of characters with all dots).
* \param node Zone node the domain name belongs to. Set to NULL if not
......@@ -74,6 +82,8 @@ dnslib_dname_t *dnslib_dname_new_from_str(const char *name, unsigned int size,
*
* \note The name is copied into the structure.
* \note If the given name is not a FQDN, the result will be neither.
* \note Newly created dname is referenced, caller is responsible for releasing
* it after use.
*
* \param name Domain name in wire format.
* \param size Size of the domain name in octets.
......@@ -126,9 +136,14 @@ int dnslib_dname_from_wire(const uint8_t *name, unsigned int size,
/*!
* \brief Copies the given domain name.
*
* \note Copied dname referense count is reset to 1, caller is responsible
* for releasing it after use.
*
* \param dname Domain name to be copied.
*
* \return New domain name which is an exact copy of \a dname.
*
* \todo Deep/shallow copying.
*/
dnslib_dname_t *dnslib_dname_copy(const dnslib_dname_t *dname);
......@@ -204,6 +219,9 @@ int dnslib_dname_is_fqdn(const dnslib_dname_t *dname);
/*!
* \brief Creates new domain name by removing leftmost label from \a dname.
*
* \note Newly created dname reference count is set to 1, caller is responsible
* for releasing it after use.
*
* \param dname Domain name to remove the first label from.
*
* \return New domain name with the same labels as \a dname, except for the
......@@ -342,6 +360,30 @@ void dnslib_dname_set_id(dnslib_dname_t *dname, unsigned int id);
unsigned int dnslib_dname_get_id(const dnslib_dname_t *dname);
/*!
* \brief Increment reference counter for dname.
*
* Function makes shallow copy (reference).
*
* \param dname Referenced dname.
*/
static inline void dnslib_dname_retain(dnslib_dname_t *dname) {
if (dname) {
ref_retain(&dname->ref);
}
}
/*!
* \brief Decrement reference counter for dname.
*
* \param dname Referenced dname.
*/
static inline void dnslib_dname_release(dnslib_dname_t *dname) {
if (dname) {
ref_release(&dname->ref);
}
}
#endif /* _KNOT_DNSLIB_DNAME_H_ */
/*! @} */
......@@ -699,7 +699,7 @@ void dnslib_node_free(dnslib_node_t **node, int free_owner, int fix_refs)
}
if (free_owner) {
debug_dnslib_node("Freeing owner.\n");
dnslib_dname_free(&(*node)->owner);
dnslib_dname_release((*node)->owner);
}
// check nodes referencing this node and fix the references
......
......@@ -388,7 +388,7 @@ DEBUG_DNSLIB_PACKET(
if (size - *pos < 10) {
debug_dnslib_packet("Malformed RR: Not enough data to parse RR"
" header.\n");
dnslib_dname_free(&owner);
dnslib_dname_release(owner);
return NULL;
}
......@@ -400,7 +400,7 @@ DEBUG_DNSLIB_PACKET(
dnslib_rrset_t *rrset = dnslib_rrset_new(owner, type, rclass, ttl);
if (rrset == NULL) {
dnslib_dname_free(&owner);
dnslib_dname_release(owner);
return NULL;
}
......@@ -596,7 +596,7 @@ static void dnslib_packet_free_allocated_space(dnslib_packet_t *pkt)
debug_dnslib_packet("Freeing additional space in packet.\n");
if (pkt->prealloc_type == DNSLIB_PACKET_PREALLOC_NONE) {
debug_dnslib_packet("Freeing QNAME.\n");
dnslib_dname_free(&pkt->question.qname);
dnslib_dname_release(pkt->question.qname);
}
if (pkt->max_an_rrsets > DEFAULT_RRSET_COUNT(ANCOUNT, pkt)) {
......
......@@ -442,7 +442,7 @@ void dnslib_rdata_deep_free(dnslib_rdata_t **rdata, uint type,
|| desc->wireformat[i] == DNSLIB_RDATA_WF_LITERAL_DNAME ) {
if (((*rdata)->items[i].dname != NULL) &&
free_all_dnames) {
dnslib_dname_free(&(*rdata)->items[i].dname);
dnslib_dname_release((*rdata)->items[i].dname);
}
} else {
free((*rdata)->items[i].raw_data);
......
......@@ -345,7 +345,7 @@ void dnslib_rrset_deep_free(dnslib_rrset_t **rrset, int free_owner,
}
if (free_owner) {
dnslib_dname_free(&(*rrset)->owner);
dnslib_dname_release((*rrset)->owner);
}
free(*rrset);
......
......@@ -507,6 +507,7 @@ DEBUG_DNSLIB_ZONE(
debug_dnslib_zone("Base32-encoded hash: %s\n", name_b32);
/* Will be returned to caller, make sure it is released after use. */
*nsec3_name = dnslib_dname_new_from_str(name_b32, size, NULL);
free(name_b32);
......@@ -523,7 +524,7 @@ DEBUG_DNSLIB_ZONE(
if (ret == NULL) {
debug_dnslib_zone("Error while creating NSEC3 domain name for "
"hashed name.\n");
dnslib_dname_free(nsec3_name);
dnslib_dname_release(*nsec3_name);
return DNSLIB_ERROR;
}
......@@ -939,6 +940,7 @@ DEBUG_DNSLIB_ZONE(
debug_dnslib_zone("Creating new node.\n");
next_node = dnslib_node_new(chopped, NULL, flags);
if (next_node == NULL) {
/* Directly discard. */
dnslib_dname_free(&chopped);
return DNSLIB_ENOMEM;
}
......@@ -970,6 +972,7 @@ DEBUG_DNSLIB_ZONE(
debug_dnslib_zone("Failed to insert new node "
"to zone tree.\n");
/*! \todo Delete the node?? */
/* Directly discard. */
dnslib_dname_free(&chopped);
return ret;
}
......@@ -992,6 +995,7 @@ DEBUG_DNSLIB_ZONE(
debug_dnslib_zone("Error inserting node into "
"hash table!\n");
/*! \todo Delete the node?? */
/* Directly discard. */
dnslib_dname_free(&chopped);
return DNSLIB_EHASH;
}
......@@ -1019,6 +1023,8 @@ DEBUG_DNSLIB_ZONE(
debug_dnslib_zone("Created all parents.\n");
}
/* Directly discard. */
dnslib_dname_free(&chopped);
return DNSLIB_EOK;
......@@ -1085,7 +1091,7 @@ int dnslib_zone_contents_add_rrset(dnslib_zone_contents_t *zone,
// table)
/*! \todo Do even if domain table is not used?? */
if (ret == DNSLIB_EOK && rrset->owner != (*node)->owner) {
dnslib_dname_free(&rrset->owner);
dnslib_dname_release(rrset->owner);
rrset->owner = (*node)->owner;
}
......@@ -1192,7 +1198,7 @@ int dnslib_zone_contents_add_rrsigs(dnslib_zone_contents_t *zone,
// replace RRSet's owner with the node's owner (that is already in the
// table)
if ((*rrset)->owner != (*rrset)->rrsigs->owner) {
dnslib_dname_free(&rrsigs->owner);
dnslib_dname_release(rrsigs->owner);
(*rrset)->rrsigs->owner = (*rrset)->owner;
}
......@@ -1305,7 +1311,7 @@ int dnslib_zone_contents_add_nsec3_rrset(dnslib_zone_contents_t *zone,
// table)
/*! \todo Do even if domain table is not used? */
if (rrset->owner != (*node)->owner) {
dnslib_dname_free(&rrset->owner);
dnslib_dname_release(rrset->owner);
rrset->owner = (*node)->owner;
}
......@@ -1671,6 +1677,7 @@ DEBUG_DNSLIB_ZONE(
// chop leftmost labels until some node is found
// copy the name for chopping
/* Local allocation, will be discarded. */
dnslib_dname_t *name_copy = dnslib_dname_copy(name);
DEBUG_DNSLIB_ZONE(
char *n = dnslib_dname_to_str(name_copy);
......@@ -1695,6 +1702,7 @@ DEBUG_DNSLIB_ZONE(
name_copy->size);
}
/* Directly discard. */
dnslib_dname_free(&name_copy);
assert(item != NULL);
......@@ -1743,7 +1751,7 @@ DEBUG_DNSLIB_ZONE(
zone->nsec3_nodes, nsec3_name, &found, &prev);
assert(exact_match >= 0);
dnslib_dname_free(&nsec3_name);
dnslib_dname_release(nsec3_name);
DEBUG_DNSLIB_ZONE(
if (found) {
......
......@@ -909,6 +909,7 @@ static int check_nsec3_node_in_zone(dnslib_zone_contents_t *zone, dnslib_node_t
memmove(next_dname_decoded + 1, next_dname_decoded, real_size);
next_dname_decoded[0] = real_size;
/* Local allocation, will be discarded. */
dnslib_dname_t *next_dname =
dnslib_dname_new_from_wire(next_dname_decoded,
real_size + 1, NULL);
......@@ -927,6 +928,8 @@ static int check_nsec3_node_in_zone(dnslib_zone_contents_t *zone, dnslib_node_t
err_handler_handle_error(handler, node,
ZC_ERR_NSEC3_RDATA_CHAIN);
}
/* Directly discard. */
dnslib_dname_free(&next_dname);
/* This is probably not sufficient, but again, it is covered in
......@@ -1713,6 +1716,7 @@ static void log_cyclic_errors_in_zone(err_handler_t *handler,
memmove(next_dname_decoded + 1, next_dname_decoded, real_size);
next_dname_decoded[0] = real_size;
/* Local allocation, will be discarded. */
dnslib_dname_t *next_dname =
dnslib_dname_new_from_wire(next_dname_decoded,
real_size + 1, NULL);
......@@ -1725,6 +1729,7 @@ static void log_cyclic_errors_in_zone(err_handler_t *handler,
free(next_dname_decoded);
/*! \todo Free result and dname! */
if (dnslib_dname_cat(next_dname,
dnslib_node_owner(dnslib_zone_contents_apex(zone))) ==
NULL) {
......@@ -1747,6 +1752,7 @@ static void log_cyclic_errors_in_zone(err_handler_t *handler,
ZC_ERR_NSEC3_RDATA_CHAIN);
}
/* Directly discard. */
dnslib_dname_free(&next_dname);
} else if (do_checks == 2 ) {
......
......@@ -130,7 +130,7 @@ static dnslib_dname_t *read_dname_with_id(FILE *f)
/* Read ID. */
uint32_t dname_id = 0;
if (!fread_wrapper(&dname_id, sizeof(dname_id), 1, f)) {
dnslib_dname_free(&ret);
dnslib_dname_release(ret);
return NULL;
}
......@@ -139,7 +139,7 @@ static dnslib_dname_t *read_dname_with_id(FILE *f)
/* Read size of dname. */
uint32_t dname_size = 0;
if (!fread_wrapper(&dname_size, sizeof(dname_size), 1, f)) {
dnslib_dname_free(&ret);
dnslib_dname_release(ret);
return NULL;
}
ret->size = dname_size;
......@@ -150,19 +150,19 @@ static dnslib_dname_t *read_dname_with_id(FILE *f)
ret->name = malloc(sizeof(uint8_t) * ret->size);
if (ret->name == NULL) {
ERR_ALLOC_FAILED;
dnslib_dname_free(&ret);
dnslib_dname_release(ret);
return NULL;
}
if (!fread_wrapper(ret->name, sizeof(uint8_t), ret->size, f)) {
dnslib_dname_free(&ret);
dnslib_dname_release(ret);
return NULL;
}
/* Read labels. */
uint16_t label_count = 0;
if (!fread_wrapper(&label_count, sizeof(label_count), 1, f)) {
dnslib_dname_free(&ret);
dnslib_dname_release(ret);
return NULL;
}
......@@ -171,7 +171,7 @@ static dnslib_dname_t *read_dname_with_id(FILE *f)
ret->labels = malloc(sizeof(uint8_t) * ret->label_count);
if (ret->labels == NULL) {
ERR_ALLOC_FAILED;
dnslib_dname_free(&ret);
dnslib_dname_release(ret);
return NULL;
}
......@@ -538,6 +538,7 @@ static void find_and_set_wildcard_child(dnslib_zone_contents_t *zone,
dnslib_zone_contents_get_nsec3_node(zone, chopped);
}
/* Directly discard. */
dnslib_dname_free(&chopped);
assert(wildcard_parent); /* it *has* to be there */
......@@ -744,7 +745,7 @@ static void cleanup_id_array(dnslib_dname_t **id_array,
const uint from, const uint to)
{
for (uint i = from; i < to; i++) {
dnslib_dname_free(&(id_array[i]));
dnslib_dname_release(id_array[i]);
}
free(id_array);
......@@ -831,11 +832,14 @@ static dnslib_dname_t **create_dname_array(FILE *f, uint max_id)
cleanup_id_array(array, 0, i);
return NULL;
}
if (read_dname->id < max_id) {
read_dname->node = dnslib_node_new(read_dname, NULL, 0);
if (read_dname->node == NULL) {
ERR_ALLOC_FAILED;
cleanup_id_array(array, 0, i);
/* Directly discard. */
dnslib_dname_free(&read_dname);
return NULL;
}
......@@ -844,6 +848,7 @@ static dnslib_dname_t **create_dname_array(FILE *f, uint max_id)
cleanup_id_array(array, 0, i);
return NULL;
}
// assert(array[i]->id == i);
}
......@@ -1027,6 +1032,10 @@ dnslib_zone_t *dnslib_zload_load(zloader_t *loader)
}
/* ID array is now useless */
for (uint i = 1; i < total_dnames; i++) {
/* Added to table, may discard now. */
dnslib_dname_release(id_array[i]);
}
free(id_array);
......
......@@ -51,7 +51,7 @@ dnslib_zone_t *dnslib_zone_new(dnslib_node_t *apex, uint node_count,
zone->contents = dnslib_zone_contents_new(apex, node_count,
use_domain_table, zone);
if (zone->contents == NULL) {
dnslib_dname_free(&zone->name);
dnslib_dname_release(zone->name);
free(zone);
return NULL;
}
......@@ -331,7 +331,7 @@ void dnslib_zone_free(dnslib_zone_t **zone)
"update.\n");
}
dnslib_dname_free(&(*zone)->name);
dnslib_dname_release((*zone)->name);
/* Call zone data destructor if exists. */
if ((*zone)->dtor) {
......@@ -365,7 +365,7 @@ DEBUG_DNSLIB_ZONE(
free(name);
);
dnslib_dname_free(&(*zone)->name);
dnslib_dname_release((*zone)->name);
/* Call zone data destructor if exists. */
if ((*zone)->dtor) {
......
......@@ -264,7 +264,7 @@ zone_start: TEXT {
strcat(this_zone->name, ".");
}
// Check domain name
/* Check domain name. */
dnslib_dname_t *dn = dnslib_dname_new_from_str(this_zone->name,
nlen + 1,
0);
......@@ -273,6 +273,7 @@ zone_start: TEXT {
free(this_zone);
cf_error("invalid zone origin");
} else {
/* Directly discard dname, won't be needed. */
dnslib_dname_free(&dn);
add_tail(&new_config->zones, &this_zone->n);
++new_config->zones_count;
......
......@@ -82,12 +82,10 @@ static const dnslib_zone_t *ns_get_zone_for_qname(dnslib_zonedb_t *zdb,
* records are only present in a parent zone.
*/
if (qtype == DNSLIB_RRTYPE_DS) {
/*
* TODO: optimize!!!
* 1) do not copy the name!
*/
/*! \todo Optimize, do not deep copy dname. */
dnslib_dname_t *name = dnslib_dname_left_chop(qname);
zone = dnslib_zonedb_find_zone_for_name(zdb, name);
/* Directly discard. */
dnslib_dname_free(&name);
} else {
zone = dnslib_zonedb_find_zone_for_name(zdb, qname);
......@@ -123,7 +121,7 @@ static dnslib_rrset_t *ns_synth_from_wildcard(
dnslib_rrset_ttl(wildcard_rrset));
if (synth_rrset == NULL) {
dnslib_dname_free(&owner);
dnslib_dname_release(owner);
return NULL;
}
......@@ -812,7 +810,7 @@ DEBUG_NS(
ret = ns_put_covering_nsec3(zone, next_closer, resp);
// the cast is ugly, but no better way around it
dnslib_dname_free((dnslib_dname_t **)&next_closer);
dnslib_dname_release((dnslib_dname_t *)next_closer);
} else {
ret = ns_put_covering_nsec3(zone, next_closer, resp);
}
......@@ -838,6 +836,7 @@ static dnslib_dname_t *ns_wildcard_child_name(const dnslib_dname_t *name)
}
if (dnslib_dname_cat(wildcard, name) == NULL) {
/* Directly discard dname. */
dnslib_dname_free(&wildcard);
return NULL;
}
......@@ -879,6 +878,8 @@ static int ns_put_nsec3_no_wildcard_child(const dnslib_zone_contents_t *zone,
ret = NS_ERR_SERVFAIL;
} else {
ret = ns_put_covering_nsec3(zone, wildcard, resp);
/* Directly discard wildcard. */
dnslib_dname_free(&wildcard);
}
......@@ -991,6 +992,7 @@ static int ns_put_nsec_nxdomain(const dnslib_dname_t *qname,
debug_ns("Previous node: %s\n",
dnslib_dname_to_str(dnslib_node_owner(prev_new)));
/* Directly discard dname. */
dnslib_dname_free(&wildcard);
if (prev_new != previous) {
......@@ -1123,8 +1125,9 @@ DEBUG_NS(
);
int ret = ns_put_covering_nsec3(zone, next_closer, resp);
// the cast is ugly, but no better way around it
dnslib_dname_free(&next_closer);
/* Duplicate from ns_next_close(), safe to discard. */
dnslib_dname_release(next_closer);
return ret;
}
......@@ -1423,7 +1426,7 @@ static dnslib_rrset_t *ns_cname_from_dname(const dnslib_rrset_t *dname_rrset,
owner, DNSLIB_RRTYPE_CNAME, DNSLIB_CLASS_IN, SYNTH_CNAME_TTL);
if (cname_rrset == NULL) {
dnslib_dname_free(&owner);
dnslib_dname_release(owner);
return NULL;
}
......@@ -3059,7 +3062,8 @@ int ns_process_response(ns_nameserver_t *nameserver, sockaddr_t *from,
evsched_cancel(sched, refresh_ev);
}
// get zone contents
/* Get zone contents. */
rcu_read_lock();
const dnslib_zone_contents_t *contents =
dnslib_zone_contents(zone);
......@@ -3083,20 +3087,23 @@ int ns_process_response(ns_nameserver_t *nameserver, sockaddr_t *from,
ref_tmr);
evsched_schedule(sched, refresh_ev, ref_tmr);
rcu_read_unlock();
return KNOT_EOK;
}
/* Prepare XFR client transfer. */
ns_xfr_t xfr_req;
memset(&xfr_req, 0, sizeof(ns_xfr_t));
memcpy(&xfr_req.addr, from, sizeof(sockaddr_t));
xfr_req.data = (void *)contents;
xfr_req.data = (void *)zone;
xfr_req.send = ns_send_cb;
/* Select transfer method. */
xfr_req.type = ns_transfer_to_use(nameserver, contents);
/* Unlock zone contents. */
rcu_read_unlock();
/* Enqueue XFR request. */
return xfr_request(nameserver->server->xfr_h, &xfr_req);
}
......@@ -3181,6 +3188,8 @@ static int ns_find_zone_for_xfr(ns_xfr_t *xfr, const char **zonefile,
int r = dnslib_dname_compare(zone_name, dnslib_node_owner(
dnslib_zone_contents_apex(xfr->zone)));
/* Directly discard dname, won't be needed. */
dnslib_dname_free(&zone_name);
if (r == 0) {
......@@ -3340,7 +3349,7 @@ int ns_process_axfrin(ns_nameserver_t *nameserver, ns_xfr_t *xfr)
debug_ns("ns_process_axfrin: incoming packet\n");
int ret = xfrin_process_axfr_packet(xfr->wire, xfr->wire_size,
(dnslib_zone_contents_t **)(&xfr->data));
(dnslib_zone_contents_t **)(&xfr->data));
if (ret > 0) { // transfer finished
debug_ns("ns_process_axfrin: AXFR finished, zone created.\n");
......
......@@ -10,6 +10,8 @@
#include <stdlib.h>
#include <errno.h>
#include <urcu.h>
#include "knot/common.h"
#include "knot/server/xfr-handler.h"
#include "knot/server/name-server.h"
......@@ -133,12 +135,10 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents)
}
/* Fetch associated zone. */
dnslib_zone_contents_t *zone = (dnslib_zone_contents_t *)req->data;
dnslib_zone_t *zone = (dnslib_zone_t *)req->data;
if (!zone) {
return;
}
const dnslib_node_t *apex = dnslib_zone_contents_apex(zone);
const dnslib_dname_t *dname = dnslib_node_owner(apex);
/* Connect to remote. */
if (req->session <= 0) {
......@@ -158,21 +158,28 @@ static inline void xfr_bridge_ev(struct ev_loop *loop, ev_io *w, int revents)
req->session = dup(req->session);
}
/* Fetch zone contents. */
rcu_read_lock();
const dnslib_zone_contents_t *contents = dnslib_zone_contents(zone);
/* Create XFR query. */
ret = KNOT_ERROR;
size_t bufsize = req->wire_size;
switch(req->type) {
case NS_XFR_TYPE_AIN:
ret = xfrin_create_axfr_query(dname, req->wire, &bufsize);
ret = xfrin_create_axfr_query(contents, req->wire, &bufsize);
break;
case NS_XFR_TYPE_IIN:
ret = xfrin_create_ixfr_query(dname, req->wire, &bufsize);
ret = xfrin_create_ixfr_query(contents, req->wire, &bufsize);
break;
default:
ret = KNOT_EINVAL;
break;
}
/* Unlock zone contents. */
rcu_read_unlock();
/* Handle errors. */
if (ret != KNOT_EOK) {
debug_xfr("xfr_in: failed to create XFR query type %d\n",
......@@ -403,7 +410,7 @@ int xfr_master(dthread_t *thread)
}
// Stop whole unit
/* Stop whole unit. */
debug_xfr("xfr_master: finished.\n");
return KNOT_EOK;
}
......
......@@ -28,7 +28,7 @@ static const size_t XFRIN_CHANGESET_BINARY_STEP = 100;
/* Non-API functions */
/*----------------------------------------------------------------------------*/
static int xfrin_create_query(const dnslib_dname_t *qname, uint16_t qtype,
static int xfrin_create_query(const dnslib_zone_contents_t *zone, uint16_t qtype,
uint16_t qclass, uint8_t *buffer, size_t *size)
{
dnslib_packet_t *pkt = dnslib_packet_new(DNSLIB_PACKET_PREALLOC_QUERY);
......@@ -49,6 +49,12 @@ static int xfrin_create_query(const dnslib_dname_t *qname, uint16_t qtype,
dnslib_question_t question;
const dnslib_node_t *apex = dnslib_zone_contents_apex(zone);
dnslib_dname_t *qname = dnslib_node_get_owner(apex);
/*! \todo What happens if apex is freed before we lock? */
dnslib_dname_retain(qname);
// this is ugly!!
question.qname = (dnslib_dname_t *)qname;
question.qtype = qtype;
......@@ -87,6 +93,9 @@ static int xfrin_create_query(const dnslib_dname_t *qname, uint16_t qtype,
dnslib_packet_free(&pkt);
/* Release qname. */
dnslib_dname_release(qname);
return KNOT_EOK;
}