Commit a08abecc authored by Lubos Slovak's avatar Lubos Slovak

Merge branch 'dnslib_sep' into libknot

- Moved changesets into separate dnslib module, but API is not
  renamed yet.
- A lot of stuff moved from xfr-in to zones.

Conflicts:
	src/knot/server/name-server.c
	src/knot/server/xfr-in.c
parents 371a64ce bb0e65b3
......@@ -80,6 +80,8 @@ src/dnslib/tolower.h
src/dnslib/tolower.c
src/dnslib/nsec3.h
src/dnslib/nsec3.c
src/dnslib/changesets.h
src/dnslib/changesets.c
src/dnslib/zone-dump.c
src/dnslib/zone-dump.h
src/dnslib/zone-load.c
......
......@@ -40,9 +40,9 @@ LDFLAGS="$LDFLAGS -L/usr/local/lib"
AC_SEARCH_LIBS([pow], [m])
AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR([pthreads not found])])
AC_SEARCH_LIBS([rcu_read_lock], [urcu], [], [AC_MSG_ERROR([liburcu not found])])
AC_SEARCH_LIBS([clock_gettime], [rt], [], [AC_MSG_ERROR([librt not found])])
#AC_SEARCH_LIBS([clock_gettime], [rt], [], [AC_MSG_ERROR([librt not found])])
AC_SEARCH_LIBS([OpenSSL_add_all_digests], [crypto],[], [AC_MSG_ERROR([libcrypto not found])])
AC_SEARCH_LIBS([ev_loop], [ev],[], [AC_MSG_ERROR([libev not found])])
AC_SEARCH_LIBS([ev_loop_new], [ev],[], [AC_MSG_ERROR([libev not found])])
#AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
......
......@@ -19,12 +19,12 @@ header="${1%.*}_rc"
header=`basename ${header}`
# Get file size and dump content
size=`stat --format "%s" ${1} 2>/dev/null`
size=`wc -c ${1} | awk '{print $1}' 2>/dev/null`
dump=`${hd} "${fmt}" ${1} 2>/dev/null`
# Format file size variable
echo "static const unsigned ${header}_size = ${size};"
# Format file content dump
echo -n "static const char ${header}[] = { "
echo "static const char ${header}[] = { "
echo "${dump}0x00 };"
......@@ -253,6 +253,8 @@ libknot_la_SOURCES = \
dnslib/wire.h \
dnslib/debug.h \
dnslib/nsec3.h \
dnslib/changesets.h \
dnslib/changesets.c \
dnslib/dname-table.h
......
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "dnslib/changesets.h"
#include "dnslib/rrset.h"
#include "dnslib/error.h"
static const size_t XFRIN_CHANGESET_COUNT = 5;
static const size_t XFRIN_CHANGESET_STEP = 5;
static const size_t XFRIN_CHANGESET_RRSET_COUNT = 5;
static const size_t XFRIN_CHANGESET_RRSET_STEP = 5;
/*----------------------------------------------------------------------------*/
static int xfrin_changeset_check_count(dnslib_rrset_t ***rrsets, size_t count,
size_t *allocated)
{
// this should also do for the initial case (*rrsets == NULL)
if (count == *allocated) {
dnslib_rrset_t **rrsets_new = (dnslib_rrset_t **)calloc(
*allocated + XFRIN_CHANGESET_RRSET_STEP,
sizeof(dnslib_rrset_t *));
if (rrsets_new == NULL) {
return DNSLIB_ENOMEM;
}
memcpy(rrsets_new, *rrsets, count);
dnslib_rrset_t **rrsets_old = *rrsets;
*rrsets = rrsets_new;
*allocated += XFRIN_CHANGESET_RRSET_STEP;
free(rrsets_old);
}
return DNSLIB_EOK;
}
/*----------------------------------------------------------------------------*/
static int xfrin_changeset_rrsets_match(const dnslib_rrset_t *rrset1,
const dnslib_rrset_t *rrset2)
{
return dnslib_rrset_compare(rrset1, rrset2, DNSLIB_RRSET_COMPARE_HEADER)
&& (dnslib_rrset_type(rrset1) != DNSLIB_RRTYPE_RRSIG
|| dnslib_rdata_rrsig_type_covered(
dnslib_rrset_rdata(rrset1))
== dnslib_rdata_rrsig_type_covered(
dnslib_rrset_rdata(rrset2)));
}
/*----------------------------------------------------------------------------*/
int xfrin_allocate_changesets(dnslib_changesets_t **changesets)
{
// create new changesets
*changesets = (dnslib_changesets_t *)(
calloc(1, sizeof(dnslib_changesets_t)));
if (*changesets == NULL) {
return DNSLIB_ENOMEM;
}
assert((*changesets)->allocated == 0);
assert((*changesets)->count == 0);
assert((*changesets)->sets = NULL);
return xfrin_changesets_check_size(*changesets);
}
/*----------------------------------------------------------------------------*/
int xfrin_changeset_add_rrset(dnslib_rrset_t ***rrsets,
size_t *count, size_t *allocated,
dnslib_rrset_t *rrset)
{
int ret = xfrin_changeset_check_count(rrsets, *count, allocated);
if (ret != DNSLIB_EOK) {
return ret;
}
(*rrsets)[(*count)++] = rrset;
return DNSLIB_EOK;
}
/*----------------------------------------------------------------------------*/
int xfrin_changeset_add_rr(dnslib_rrset_t ***rrsets, size_t *count,
size_t *allocated, dnslib_rrset_t *rr)
{
// try to find the RRSet in the list of RRSets
int i = 0;
while (i < *count && !xfrin_changeset_rrsets_match((*rrsets)[i], rr)) {
++i;
}
if (i < *count) {
// found RRSet to merge the new one into
if (dnslib_rrset_merge((void **)&(*rrsets)[i],
(void **)&rr) != DNSLIB_EOK) {
return DNSLIB_ERROR;
}
// remove the RR
dnslib_rrset_deep_free(&rr, 1, 1, 1);
return DNSLIB_EOK;
} else {
return xfrin_changeset_add_rrset(rrsets, count, allocated, rr);
}
}
/*----------------------------------------------------------------------------*/
int xfrin_changeset_add_new_rr(dnslib_changeset_t *changeset,
dnslib_rrset_t *rrset,
xfrin_changeset_part_t part)
{
dnslib_rrset_t ***rrsets = NULL;
size_t *count = NULL;
size_t *allocated = NULL;
switch (part) {
case XFRIN_CHANGESET_ADD:
rrsets = &changeset->add;
count = &changeset->add_count;
allocated = &changeset->add_allocated;
break;
case XFRIN_CHANGESET_REMOVE:
rrsets = &changeset->remove;
count = &changeset->remove_count;
allocated = &changeset->remove_allocated;
break;
default:
assert(0);
}
assert(rrsets != NULL);
assert(count != NULL);
assert(allocated != NULL);
int ret = xfrin_changeset_add_rr(rrsets, count, allocated, rrset);
if (ret != DNSLIB_EOK) {
return ret;
}
return ret;
}
/*----------------------------------------------------------------------------*/
void xfrin_changeset_store_soa(dnslib_rrset_t **chg_soa,
uint32_t *chg_serial, dnslib_rrset_t *soa)
{
*chg_soa = soa;
*chg_serial = dnslib_rdata_soa_serial(dnslib_rrset_rdata(soa));
}
/*----------------------------------------------------------------------------*/
int xfrin_changeset_add_soa(dnslib_changeset_t *changeset, dnslib_rrset_t *soa,
xfrin_changeset_part_t part)
{
switch (part) {
case XFRIN_CHANGESET_ADD:
xfrin_changeset_store_soa(&changeset->soa_to,
&changeset->serial_to, soa);
break;
case XFRIN_CHANGESET_REMOVE:
xfrin_changeset_store_soa(&changeset->soa_from,
&changeset->serial_from, soa);
break;
default:
assert(0);
}
/*! \todo Remove return value? */
return DNSLIB_EOK;
}
/*---------------------------------------------------------------------------*/
int xfrin_changesets_check_size(dnslib_changesets_t *changesets)
{
if (changesets->allocated == changesets->count) {
dnslib_changeset_t *sets = (dnslib_changeset_t *)calloc(
changesets->allocated + XFRIN_CHANGESET_STEP,
sizeof(dnslib_changeset_t));
if (sets == NULL) {
return DNSLIB_ENOMEM;
}
/*! \todo realloc() may be more effective. */
memcpy(sets, changesets->sets, changesets->count);
dnslib_changeset_t *old_sets = changesets->sets;
changesets->sets = sets;
changesets->count += XFRIN_CHANGESET_STEP;
free(old_sets);
}
return DNSLIB_EOK;
}
/*----------------------------------------------------------------------------*/
void xfrin_free_changesets(dnslib_changesets_t **changesets)
{
if (changesets == NULL || *changesets == NULL) {
return;
}
assert((*changesets)->allocated >= (*changesets)->count);
for (int i = 0; i < (*changesets)->count; ++i) {
dnslib_changeset_t *ch = &(*changesets)->sets[i];
assert(ch->add_allocated >= ch->add_count);
assert(ch->remove_allocated >= ch->remove_count);
assert(ch->allocated >= ch->size);
int j;
for (j = 0; i < ch->add_count; ++j) {
dnslib_rrset_deep_free(&ch->add[j], 1, 1, 1);
}
free(ch->add);
for (j = 0; i < ch->remove_count; ++j) {
dnslib_rrset_deep_free(&ch->add[j], 1, 1, 1);
}
free(ch->remove);
dnslib_rrset_deep_free(&ch->soa_from, 1, 1, 1);
dnslib_rrset_deep_free(&ch->soa_to, 1, 1, 1);
free(ch->data);
}
free((*changesets)->sets);
free(*changesets);
*changesets = NULL;
}
/*---------------------------------------------------------------------------*/
/*!
* \file changesets.h
*
* \author Lubos Slovak <lubos.slovak@nic.cz>
*
* \brief Structure for representing IXFR/DDNS changeset and its API.
*
* \addtogroup dnslib
* @{
*/
#ifndef _KNOT_DNSLIB_CHANGESETS_H_
#define _KNOT_DNSLIB_CHANGESETS_H_
#include "dnslib/rrset.h"
/*! \todo Changeset must be serializable/deserializable, so
* all data and pointers have to be changeset-exclusive,
* or more advanced structure serialization scheme has to be
* implemented.
*
* \todo Preallocation of space for changeset.
*/
typedef struct {
dnslib_rrset_t *soa_from;
dnslib_rrset_t **remove;
size_t remove_count;
size_t remove_allocated;
dnslib_rrset_t *soa_to;
dnslib_rrset_t **add;
size_t add_count;
size_t add_allocated;
uint8_t *data;
size_t size;
size_t allocated;
uint32_t serial_from;
uint32_t serial_to;
} dnslib_changeset_t;
/*----------------------------------------------------------------------------*/
typedef struct {
dnslib_changeset_t *sets;
size_t count;
size_t allocated;
} dnslib_changesets_t;
/*----------------------------------------------------------------------------*/
typedef enum {
XFRIN_CHANGESET_ADD,
XFRIN_CHANGESET_REMOVE
} xfrin_changeset_part_t;
/*----------------------------------------------------------------------------*/
int xfrin_allocate_changesets(dnslib_changesets_t **changesets);
int xfrin_changeset_add_rrset(dnslib_rrset_t ***rrsets,
size_t *count, size_t *allocated,
dnslib_rrset_t *rrset);
int xfrin_changeset_add_rr(dnslib_rrset_t ***rrsets, size_t *count,
size_t *allocated, dnslib_rrset_t *rr);
int xfrin_changeset_add_new_rr(dnslib_changeset_t *changeset,
dnslib_rrset_t *rrset,
xfrin_changeset_part_t part);
void xfrin_changeset_store_soa(dnslib_rrset_t **chg_soa,
uint32_t *chg_serial, dnslib_rrset_t *soa);
int xfrin_changeset_add_soa(dnslib_changeset_t *changeset, dnslib_rrset_t *soa,
xfrin_changeset_part_t part);
void xfrin_free_changesets(dnslib_changesets_t **changesets);
int xfrin_changesets_check_size(dnslib_changesets_t *changesets);
#endif /* _KNOT_DNSLIB_CHANGESETS_H_ */
/*! @} */
......@@ -203,6 +203,16 @@ void dnslib_zone_contents_dump(dnslib_zone_contents_t *zone, char loaded_zone);
#define debug_ck_rehash(msg...)
#endif
#ifdef DNSLIB_XFR_DEBUG
#define debug_dnslib_xfr(msg...) fprintf(stderr, msg)
#define debug_dnslib_xfr_hex(data, len) hex_print((data), (len))
#define DEBUG_DNSLIB_XFR(cmds) do { cmds } while (0)
#else
#define debug_dnslib_xfr(msg...)
#define debug_dnslib_xfr_hex(data, len)
#define DEBUG_DNSLIB_XFR(cmds)
#endif
#endif
/*! @} */
......@@ -384,7 +384,6 @@ dnslib_dname_t *dnslib_dname_new_from_str(const char *name, uint size,
}
dnslib_dname_str_to_wire(name, size, dname);
assert(dname->label_count >= 0);
debug_dnslib_dname("Created dname with size: %d\n", dname->size);
debug_dnslib_dname("Label offsets: ");
for (int i = 0; i < dname->label_count; ++i) {
......@@ -455,7 +454,6 @@ dnslib_dname_t *dnslib_dname_new_from_wire(const uint8_t *name, uint size,
dnslib_dname_free(&dname);
return NULL;
}
assert(dname->label_count >= 0);
dname->node = node;
dname->id = 0;
......@@ -720,7 +718,6 @@ dnslib_dname_t *dnslib_dname_left_chop(const dnslib_dname_t *dname)
parent->labels[i] = dname->labels[i + 1] - first_label_length;
}
parent->label_count = dname->label_count - 1;
assert(dname->label_count >= 0);
return parent;
}
......@@ -742,7 +739,6 @@ void dnslib_dname_left_chop_no_copy(dnslib_dname_t *dname)
}
dname->label_count = dname->label_count - 1;
dname->size -= first_label_length;
assert(dname->label_count >= 0);
} else {
dname->name[0] = '\0';
dname->size = 1;
......@@ -843,7 +839,6 @@ int dnslib_dname_matched_labels(const dnslib_dname_t *dname1,
int dnslib_dname_label_count(const dnslib_dname_t *dname)
{
assert(dname->label_count >= 0);
return dname->label_count;
}
......@@ -908,8 +903,6 @@ DEBUG_DNSLIB_DNAME(
dnslib_dname_find_labels(res, 1);
assert(res->label_count >= 0);
return res;
}
......@@ -999,8 +992,6 @@ dnslib_dname_t *dnslib_dname_cat(dnslib_dname_t *d1, const dnslib_dname_t *d2)
d1->size += d2->size;
assert(d1->label_count >= 0);
return d1;
}
......
......@@ -19,6 +19,9 @@ enum dnslib_error {
DNSLIB_EOK = 0, /*!< OK */
DNSLIB_ERROR = -10000, /*!< General dnslib error. */
DNSLIB_ENOMEM, /*!< Not enough memory. */
DNSLIB_ENOTSUP, /*!< Operation not supported. */
DNSLIB_EAGAIN, /*!< OS lacked necessary resources. */
DNSLIB_ERANGE, /*!< Value is out of range. */
DNSLIB_EBADARG, /*!< Wrong argument supported. */
DNSLIB_EFEWDATA, /*!< Not enough data to parse. */
DNSLIB_ESPACE, /*!< Not enough space provided. */
......
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "common/libtap/tap.h"
#include "dnslib/tests/realdata/dnslib_tests_loader_realdata.h"
#include "dnslib/descriptor.h"
......
......@@ -33,7 +33,7 @@ struct dt_unit_t;
/*!
* \brief Thread state enumeration.
*/
enum {
typedef enum {
ThreadJoined = 1 << 0, /*!< Thread is finished and joined. */
ThreadJoinable = 1 << 1, /*!< Thread is waiting to be reclaimed. */
ThreadCancelled = 1 << 2, /*!< Thread is cancelled, finishing task. */
......
......@@ -17,6 +17,7 @@
#include "dnslib/consts.h"
#include "dnslib/zone-dump-text.h"
#include "dnslib/zone-dump.h"
#include "dnslib/changesets.h"
/*----------------------------------------------------------------------------*/
......@@ -2087,7 +2088,7 @@ static int ns_ixfr_put_rrset(dnslib_ns_xfr_t *xfr, const dnslib_rrset_t *rrset)
/*----------------------------------------------------------------------------*/
static int ns_ixfr_put_changeset(dnslib_ns_xfr_t *xfr, const xfrin_changeset_t *chgset)
static int ns_ixfr_put_changeset(dnslib_ns_xfr_t *xfr, const dnslib_changeset_t *chgset)
{
// 1) put origin SOA
int res = ns_ixfr_put_rrset(xfr, chgset->soa_from);
......@@ -2129,36 +2130,47 @@ static int ns_ixfr_from_zone(dnslib_ns_xfr_t *xfr)
assert(xfr->query != NULL);
assert(xfr->response != NULL);
assert(dnslib_packet_additional_rrset_count(xfr->query) > 0);
assert(xfr->data != NULL);
/*! \todo REMOVE start */
// const dnslib_rrset_t *zone_soa =
// dnslib_node_rrset(dnslib_zone_contents_apex(
// dnslib_zone_contents(xfr->zone)),
// DNSLIB_RRTYPE_SOA);
// // retrieve origin (xfr) serial and target (zone) serial
// uint32_t zone_serial = dnslib_rdata_soa_serial(
// dnslib_rrset_rdata(zone_soa));
// uint32_t xfr_serial = dnslib_rdata_soa_serial(dnslib_rrset_rdata(
// dnslib_packet_authority_rrset(xfr->query, 0)));
// // 3) load changesets from journal
// dnslib_changesets_t *chgsets = (dnslib_changesets_t *)
// calloc(1, sizeof(dnslib_changesets_t));
// int res = xfr_load_changesets(xfr->zone, chgsets, xfr_serial,
// zone_serial);
// if (res != DNSLIB_EOK) {
// debug_dnslib_ns("IXFR query cannot be answered: %s.\n",
// dnslib_strerror(res));
// /*! \todo Probably send back AXFR instead. */
// dnslib_response2_set_rcode(xfr->response, DNSLIB_RCODE_SERVFAIL);
// /*! \todo Probably rename the function. */
// ns_axfr_send_and_clear(xfr);
// //socket_close(xfr->session); /*! \todo Remove for UDP. */
// return 1;
// }
/*! \todo REMOVE end */
dnslib_changesets_t *chgsets = (dnslib_changesets_t *)xfr->data;
const dnslib_rrset_t *zone_soa =
dnslib_node_rrset(dnslib_zone_contents_apex(
dnslib_zone_contents(xfr->zone)),
DNSLIB_RRTYPE_SOA);
// retrieve origin (xfr) serial and target (zone) serial
uint32_t zone_serial = dnslib_rdata_soa_serial(
dnslib_rrset_rdata(zone_soa));
uint32_t xfr_serial = dnslib_rdata_soa_serial(dnslib_rrset_rdata(
dnslib_packet_authority_rrset(xfr->query, 0)));
// 3) load changesets from journal
xfrin_changesets_t *chgsets = (xfrin_changesets_t *)
calloc(1, sizeof(xfrin_changesets_t));
int res = xfr_load_changesets(xfr->zone, chgsets, xfr_serial,
zone_serial);
if (res != DNSLIB_EOK) {
debug_dnslib_ns("IXFR query cannot be answered: %s.\n",
dnslib_strerror(res));
/*! \todo Probably send back AXFR instead. */
dnslib_response2_set_rcode(xfr->response, DNSLIB_RCODE_SERVFAIL);
/*! \todo Probably rename the function. */
ns_axfr_send_and_clear(xfr);
//socket_close(xfr->session); /*! \todo Remove for UDP. */
return 1;
}
// 4) put the zone SOA as the first Answer RR
res = dnslib_response2_add_rrset_answer(xfr->response, zone_soa, 0, 0,
0);
int res = dnslib_response2_add_rrset_answer(xfr->response, zone_soa, 0,
0, 0);
if (res != DNSLIB_EOK) {
debug_dnslib_ns("IXFR query cannot be answered: %s.\n",
dnslib_strerror(res));
......@@ -2830,7 +2842,7 @@ DEBUG_DNSLIB_NS(
/*----------------------------------------------------------------------------*/
int dnslib_ns_apply_ixfr_changes(dnslib_zone_t *zone, xfrin_changesets_t *chgsets)
int dnslib_ns_apply_ixfr_changes(dnslib_zone_t *zone, dnslib_changesets_t *chgsets)
{
/*! \todo Apply changes to the zone when they are parsed. */
return DNSLIB_EOK;
......@@ -2838,7 +2850,8 @@ int dnslib_ns_apply_ixfr_changes(dnslib_zone_t *zone, xfrin_changesets_t *chgset
/*----------------------------------------------------------------------------*/
int dnslib_ns_process_ixfrin(dnslib_nameserver_t *nameserver, dnslib_ns_xfr_t *xfr)
int dnslib_ns_process_ixfrin(dnslib_nameserver_t *nameserver,
dnslib_ns_xfr_t *xfr)
{
/*! \todo Implement me.
* - xfr contains partially-built IXFR journal entry or NULL
......@@ -2850,12 +2863,14 @@ int dnslib_ns_process_ixfrin(dnslib_nameserver_t *nameserver, dnslib_ns_xfr_t *x
debug_dnslib_ns("ns_process_ixfrin: incoming packet\n");
int ret = xfrin_process_ixfr_packet(xfr->wire, xfr->wire_size,
(xfrin_changesets_t **)(&xfr->data));
(dnslib_changesets_t **)(&xfr->data));
/*! \todo Save zone into the XFR structure. */
if (ret > 0) { // transfer finished
debug_dnslib_ns("ns_process_ixfrin: IXFR finished\n");
xfrin_changesets_t *chgsets = (xfrin_changesets_t *)xfr->data;
dnslib_changesets_t *chgsets = (dnslib_changesets_t *)xfr->data;
if (chgsets == NULL || chgsets->count == 0) {
// nothing to be done??
return DNSLIB_EOK;
......@@ -2868,32 +2883,29 @@ int dnslib_ns_process_ixfrin(dnslib_nameserver_t *nameserver, dnslib_ns_xfr_t *x
if (zone == NULL) {
debug_dnslib_ns("No zone found for incoming IXFR!\n");
xfrin_free_changesets(
(xfrin_changesets_t **)(&xfr->data));
(dnslib_changesets_t **)(&xfr->data));
return DNSLIB_ENOZONE; /*! \todo Other error code? */
}
ret = xfrin_store_changesets(zone, chgsets);
if (ret != DNSLIB_EOK) {
debug_dnslib_ns("Failed to save changesets to journal.\n");
xfrin_free_changesets(
(xfrin_changesets_t **)(&xfr->data));
return ret;
}
ret = dnslib_ns_apply_ixfr_changes(zone, chgsets);
if (ret != DNSLIB_EOK) {
debug_dnslib_ns("Failed to apply changes to the zone.");
// left the changes to be applied later..?
// they are already stored
}
// ret = xfrin_store_changesets(zone, chgsets);
// if (ret != DNSLIB_EOK) {
// debug_dnslib_ns("Failed to save changesets to journal.\n");
// xfrin_free_changesets(
// (dnslib_changesets_t **)(&xfr->data));
// return ret;
// }
// we may free the changesets, they are stored and maybe applied
xfrin_free_changesets((xfrin_changesets_t **)(&xfr->data));
// ret = dnslib_ns_apply_ixfr_changes(zone, chgsets);
// if (ret != DNSLIB_EOK) {
// debug_dnslib_ns("Failed to apply changes to the zone.");
// // left the changes to be applied later..?
// // they are already stored
// }
return ret;
} else {
return ret;