Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (33)
Showing
with 432 additions and 214 deletions
......@@ -137,6 +137,7 @@ deploy:documentation:
<<: *debian_stretch
stage: deploy
before_script:
- apt-get update
- apt-get -y install curl
only:
- tags
......
Knot DNS 2.4.2 (2017-03-23)
===========================
Features:
---------
- Zscanner can store record comments placed on the same line
- Knotc status extension with version, configure, and workers parameters
Improvements:
-------------
- Significant incoming XFR speed-up in the case of many zones
Bugfixes:
---------
- Double OPT RR insertion when a global module returns KNOT_STATE_FAIL
- User-driven zscanner parsing logic inconsistency
- Lower serial at master doesn't trigger any errors
- Queries with too long DNAME substitution do not return YXDOMAIN response
- Incorrect elapsed time in the DDNS log
- Failed to process forwarded DDNS request with TSIG
Knot DNS 2.4.1 (2017-02-10)
===========================
Improvements:
-------------
- Speed-up of rdata addition into a huge rrset
- Introduce check of minumum timeout for next refresh
- Dnsproxy module can forward all queries without local resolving
Bugfixes:
--------
- Transfer of a huge rrset goes into an infinite loop
- Huge response over TCP contains useless TC bit instead of SERVFAIL
- Failed to build utilities with disabled daemon
- Memory leaks during keys removal
- Rough TSIG packet reservation causes early truncation
- Minor out-of-bounds string termination write in rrset dump
- Server crash during stop if failed to open timers DB
- Failed to compile on OS X older than Sierra
- Poor minimum UDP-max-size configuration check
- Failed to receive one-record-per-message IXFR-style AXFR
- Kdig timeouts when receiving RCODE != NOERROR on subsequent transfer message
Knot DNS 2.4.0 (2017-01-18)
===========================
......
......@@ -4,11 +4,12 @@ AC_PREREQ([2.60])
m4_define([knot_VERSION_MAJOR],2)dnl
m4_define([knot_VERSION_MINOR],4)dnl
m4_define([knot_VERSION_PATCH],0)dnl
m4_define([knot_VERSION_PATCH],2)dnl
m4_define([knot_VERSION_EXTRA],)dnl
m4_define([knot_PKG_VERSION],[knot_VERSION_MAJOR.knot_VERSION_MINOR.knot_VERSION_PATCH]knot_VERSION_EXTRA)dnl
AC_INIT([knot], knot_PKG_VERSION, [knot-dns@labs.nic.cz])
configure_params="$*"
AM_INIT_AUTOMAKE([gnits subdir-objects no-dist-gzip dist-xz -Wall -Werror])
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR([src/knot])
......@@ -26,6 +27,10 @@ AC_CONFIG_FILES([src/libknot/version.h
src/zscanner/version.h
src/dnssec/lib/dnssec/version.h])
# Store ./configure parameters into macro
AC_DEFINE_UNQUOTED([CONFIGURE_PARAMS],["$configure_params"],[Params passed to configure])
AC_DEFINE_UNQUOTED([CONFIGURE_CFLAGS],["$CFLAGS"],[Passed CFLAGS from environment])
# Updating version info
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST([libknot_VERSION_INFO],["-version-info 5:0:0"])
......@@ -486,6 +491,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread_np.h>]], [[cpuset_t set; CPU
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sched.h>]], [[cpuset_t* set = cpuset_create(); cpuset_destroy(set);]])],
[AC_DEFINE(HAVE_CPUSET_NETBSD, 1, [Define if cpuset_t and cpuset(3) exists.])])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <stdint.h>]],
[[uint64_t val = 0; __atomic_add_fetch(&val, 1, __ATOMIC_RELAXED);]])],
[AC_DEFINE(HAVE_ATOMIC, 1, [Define to 1 if you have '__atomic' functions.])]
)
# Prepare CFLAG_VISIBILITY to be used where needed
gl_VISIBILITY()
......@@ -525,24 +536,7 @@ AM_CONDITIONAL([HAVE_SPHINXBUILD], test "$SPHINXBUILD" != "false")
AM_CONDITIONAL([HAVE_PDFLATEX], test "$PDFLATEX" != "false")
AM_CONDITIONAL([HAVE_MAKEINFO], test "$MAKEINFO" != "false")
AC_CONFIG_FILES([Makefile
doc/Makefile
libtap/Makefile
tests/Makefile
tests-fuzz/Makefile
samples/Makefile
python/Makefile
src/Makefile
src/contrib/dnstap/Makefile
src/dnssec/Makefile
src/dnssec/tests/Makefile
src/zscanner/Makefile
])
AC_OUTPUT
AC_MSG_RESULT([
$PACKAGE $VERSION
result_msg_base=" $PACKAGE $VERSION
Target: $host_os $host_cpu
Compiler: ${CC}
......@@ -578,7 +572,31 @@ AC_MSG_RESULT([
Dnstap support: ${opt_dnstap}
Code coverage: ${enable_code_coverage}
Bash completions: ${bash_completions_output}
PKCS #11 support: ${enable_pkcs11}
PKCS #11 support: ${enable_pkcs11}"
result_msg_esc=$(echo -n "$result_msg_base" | sed '$!s/$/\\n/' | tr -d '\n')
result_msg_add="
$result_msg_base
Continue with 'make' command
])
"
AC_DEFINE_UNQUOTED([CONFIGURE_SUMMARY],["$result_msg_esc"],[Configure summary])
AC_CONFIG_FILES([Makefile
doc/Makefile
libtap/Makefile
tests/Makefile
tests-fuzz/Makefile
samples/Makefile
python/Makefile
src/Makefile
src/contrib/dnstap/Makefile
src/dnssec/Makefile
src/dnssec/tests/Makefile
src/zscanner/Makefile
])
AC_OUTPUT
AC_MSG_RESULT([$result_msg_add])
......@@ -68,8 +68,10 @@ Print the program version.
.SS Actions
.INDENT 0.0
.TP
\fBstatus\fP
\fBstatus\fP [\fIdetail\fP]
Check if the server is running.
Moreover display either the running knotd version, numbers of worker threads,
or Knot DNS buid (configure) summary, if the parameter is specified.
.TP
\fBstop\fP
Stop the server if running.
......@@ -194,6 +196,8 @@ Use \fB@\fP \fIowner\fP to denote the zone name.
.sp
Type \fIitem\fP parameter in the form of \fIsection\fP[\fB[\fP\fIid\fP\fB]\fP][\fB\&.\fP\fIname\fP].
.sp
The \fIdetail\fP option for \fBstatus\fP can be one of words: version, workers, configure.
.sp
(*) indicates a local operation which requires a configuration.
.SS Interactive mode
.sp
......
......@@ -45,8 +45,10 @@ Parameters
Actions
.......
**status**
**status** [*detail*]
Check if the server is running.
Moreover display either the running knotd version, numbers of worker threads,
or Knot DNS buid (configure) summary, if the parameter is specified.
**stop**
Stop the server if running.
......@@ -172,6 +174,8 @@ Use **@** *owner* to denote the zone name.
Type *item* parameter in the form of *section*\ [**[**\ *id*\ **]**\ ][**.**\ *name*].
The *detail* option for **status** can be one of words: version, workers, configure.
(*) indicates a local operation which requires a configuration.
Interactive mode
......
......@@ -330,7 +330,7 @@ class KnotCtl(object):
section = reply[KnotCtlDataIdx.SECTION]
item = reply[KnotCtlDataIdx.ITEM]
idx = reply[KnotCtlDataIdx.ID]
data = reply[KnotCtlDataIdx.DATA]
data = int(reply[KnotCtlDataIdx.DATA])
# Add the zone if not exists.
if zone:
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -32,6 +32,13 @@ struct {
server_t *server;
} stats = { 0 };
typedef struct {
FILE *fd;
const list_t *query_modules;
const knot_dname_t *zone;
bool zone_emitted;
} dump_ctx_t;
#define DUMP_STR(fd, level, name, ...) do { \
fprintf(fd, "%-.*s"name": %s\n", level, " ", ##__VA_ARGS__); \
} while (0)
......@@ -69,36 +76,36 @@ static void dump_counters(FILE *fd, int level, mod_ctr_t *ctr)
}
}
static void dump_modules(FILE *fd, list_t *query_modules, const knot_dname_t *zone)
static void dump_modules(dump_ctx_t *ctx)
{
static int level = 0;
int level = 0;
struct query_module *mod = NULL;
WALK_LIST(mod, *query_modules) {
WALK_LIST(mod, *ctx->query_modules) {
// Skip modules without statistics.
if (mod->stats_count == 0) {
continue;
}
// Dump zone name.
if (zone != NULL) {
if (ctx->zone != NULL) {
// Prevent from zone section override.
if (level == 0) {
DUMP_STR(fd, level++, "zone", "");
} else {
level = 1;
if (!ctx->zone_emitted) {
DUMP_STR(ctx->fd, 0, "zone", "");
ctx->zone_emitted = true;
}
level = 1;
char name[KNOT_DNAME_TXT_MAXLEN + 1];
if (knot_dname_to_str(name, zone, sizeof(name)) == NULL) {
if (knot_dname_to_str(name, ctx->zone, sizeof(name)) == NULL) {
return;
}
DUMP_STR(fd, level++, "\"%s\"", name, "");
DUMP_STR(ctx->fd, level++, "\"%s\"", name, "");
} else {
level = 0;
}
// Dump module counters.
DUMP_STR(fd, level, "%s", mod->id->name + 1, "");
DUMP_STR(ctx->fd, level, "%s", mod->id->name + 1, "");
for (int i = 0; i < mod->stats_count; i++) {
mod_ctr_t *ctr = mod->stats + i;
if (ctr->name == NULL) {
......@@ -107,23 +114,26 @@ static void dump_modules(FILE *fd, list_t *query_modules, const knot_dname_t *zo
}
if (ctr->count == 1) {
// Simple counter.
DUMP_CTR(fd, level + 1, "%s", ctr->name, ctr->counter);
DUMP_CTR(ctx->fd, level + 1, "%s", ctr->name, ctr->counter);
} else {
// Array of counters.
DUMP_STR(fd, level + 1, "%s", ctr->name, "");
dump_counters(fd, level + 2, ctr);
DUMP_STR(ctx->fd, level + 1, "%s", ctr->name, "");
dump_counters(ctx->fd, level + 2, ctr);
}
}
}
}
static void zone_stats_dump(zone_t *zone, FILE *fd)
static void zone_stats_dump(zone_t *zone, dump_ctx_t *ctx)
{
if (EMPTY_LIST(zone->query_modules)) {
return;
}
dump_modules(fd, &zone->query_modules, zone->name);
ctx->query_modules = &zone->query_modules;
ctx->zone = zone->name;
dump_modules(ctx);
}
static void dump_to_file(FILE *fd, server_t *server)
......@@ -139,7 +149,7 @@ static void dump_to_file(FILE *fd, server_t *server)
// Get the server identity.
conf_val_t val = conf_get(conf(), C_SRV, C_IDENT);
const char *ident = conf_str(&val);
if (val.code != KNOT_EOK || ident[0] == '\0') {
if (ident == NULL || ident[0] == '\0') {
ident = conf()->hostname;
}
......@@ -156,11 +166,16 @@ static void dump_to_file(FILE *fd, server_t *server)
DUMP_CTR(fd, 1, "%s", item->name, item->val(server));
}
dump_ctx_t ctx = {
.fd = fd,
.query_modules = &conf()->query_modules,
};
// Dump global statistics.
dump_modules(fd, &conf()->query_modules, NULL);
dump_modules(&ctx);
// Dump zone statistics.
knot_zonedb_foreach(server->zone_db, zone_stats_dump, fd);
knot_zonedb_foreach(server->zone_db, zone_stats_dump, &ctx);
}
static void dump_stats(server_t *server)
......
......@@ -948,7 +948,7 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat
if (ctr->count == 1) {
int ret = snprintf(value, sizeof(value), "%"PRIu64, ctr->counter);
if (ret <= 0 || ret >= sizeof(value)) {
return ret;
return KNOT_ESPACE;
}
(*data)[KNOT_CTL_IDX_ID] = NULL;
......@@ -980,13 +980,13 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat
ret = snprintf(index, sizeof(index), "%u", i);
}
if (ret <= 0 || ret >= sizeof(index)) {
return ret;
return KNOT_ESPACE;
}
ret = snprintf(value, sizeof(value), "%"PRIu64,
ret = snprintf(value, sizeof(value), "%"PRIu64,
ctr->counters[i]);
if (ret <= 0 || ret >= sizeof(value)) {
return ret;
return KNOT_ESPACE;
}
(*data)[KNOT_CTL_IDX_ID] = index;
......@@ -1125,13 +1125,47 @@ static int ctl_zone(ctl_args_t *args, ctl_cmd_t cmd)
}
}
static int server_status(ctl_args_t *args)
{
const char *type = args->data[KNOT_CTL_IDX_TYPE];
if (type == NULL || strlen(type) == 0) {
return KNOT_EOK;
}
char buff[2048] = "";
int ret;
if (strcasecmp(type, "version") == 0) {
ret = snprintf(buff, sizeof(buff), "Version: %s", PACKAGE_VERSION);
} else if (strcasecmp(type, "workers") == 0) {
ret = snprintf(buff, sizeof(buff), "UDP workers: %zu, TCP workers %zu, "
"background workers: %zu", conf_udp_threads(conf()),
conf_tcp_threads(conf()), conf_bg_threads(conf()));
} else if (strcasecmp(type, "configure") == 0) {
ret = snprintf(buff, sizeof(buff), "%s", CONFIGURE_SUMMARY);
} else {
return KNOT_EINVAL;
}
if (ret <= 0 || ret >= sizeof(buff)) {
return KNOT_ESPACE;
}
args->data[KNOT_CTL_IDX_DATA] = buff;
return knot_ctl_send(args->ctl, KNOT_CTL_TYPE_DATA, &args->data);
}
static int ctl_server(ctl_args_t *args, ctl_cmd_t cmd)
{
int ret = KNOT_EOK;
switch (cmd) {
case CTL_STATUS:
ret = KNOT_EOK;
ret = server_status(args);
if (ret != KNOT_EOK) {
send_error(args, knot_strerror(ret));
}
break;
case CTL_STOP:
ret = KNOT_CTL_ESTOP;
......@@ -1182,6 +1216,7 @@ static int ctl_stats(ctl_args_t *args, ctl_cmd_t cmd)
int ret = snprintf(value, sizeof(value), "%"PRIu64,
i->val(args->server));
if (ret <= 0 || ret >= sizeof(value)) {
ret = KNOT_ESPACE;
send_error(args, knot_strerror(ret));
return ret;
}
......
......@@ -206,6 +206,34 @@ static void axfr_cleanup(struct refresh_data *data)
zone_contents_deep_free(&data->axfr.zone);
}
/*! \brief Routine for calling call_rcu() easier way.
*
* TODO: move elsewhere, as it has no direct relation to AXFR
*/
typedef struct {
struct rcu_head rcuhead;
void (*ptr_free_fun)(void **);
void *ptr;
} callrcu_wrapper_t;
static void callrcu_wrapper_cb(struct rcu_head *param)
{
callrcu_wrapper_t *wrap = (callrcu_wrapper_t *)param;
wrap->ptr_free_fun(&wrap->ptr);
free(wrap);
}
/* note: does nothing if not-enough-memory */
static void callrcu_wrapper(void *ptr, void (*ptr_free_fun)(void **))
{
callrcu_wrapper_t *wrap = calloc(1, sizeof(callrcu_wrapper_t));
if (wrap != NULL) {
wrap->ptr = ptr;
wrap->ptr_free_fun = ptr_free_fun;
call_rcu((struct rcu_head *)wrap, callrcu_wrapper_cb);
}
}
static int axfr_finalize(struct refresh_data *data)
{
zone_contents_t *new_zone = data->axfr.zone;
......@@ -222,11 +250,9 @@ static int axfr_finalize(struct refresh_data *data)
zone_contents_t *old_zone = zone_switch_contents(data->zone, new_zone);
xfr_log_publish(data->zone->name, data->remote, old_zone, new_zone);
synchronize_rcu();
data->axfr.zone = NULL; // seized
zone_contents_deep_free(&old_zone);
callrcu_wrapper(old_zone, (void (*)(void **))zone_contents_deep_free);
return KNOT_EOK;
}
......@@ -362,18 +388,30 @@ static void ixfr_cleanup(struct refresh_data *data)
changesets_free(&data->ixfr.changesets);
}
static void ixfr_finalize_cleanup(void **ptr)
{
apply_ctx_t *ctx = *ptr;
update_free_zone(&ctx->contents);
update_cleanup(ctx);
free(ctx);
}
static int ixfr_finalize(struct refresh_data *data)
{
zone_contents_t *new_zone = NULL;
apply_ctx_t ctx = { 0 };
apply_ctx_t *ctx = calloc(1, sizeof(apply_ctx_t));
if (ctx == NULL) {
return KNOT_ENOMEM;
}
apply_init_ctx(&ctx, NULL, APPLY_STRICT);
int ret = apply_changesets(&ctx, data->zone->contents,
apply_init_ctx(ctx, NULL, APPLY_STRICT);
int ret = apply_changesets(ctx, data->zone->contents,
&data->ixfr.changesets, &new_zone);
if (ret != KNOT_EOK) {
IXFRIN_LOG(LOG_WARNING, data->zone->name, data->remote,
"failed to apply changes to zone (%s)",
knot_strerror(ret));
free(ctx);
return ret;
}
......@@ -381,8 +419,9 @@ static int ixfr_finalize(struct refresh_data *data)
ret = xfr_validate(new_zone, data);
if (ret != KNOT_EOK) {
update_rollback(&ctx);
update_rollback(ctx);
update_free_zone(&new_zone);
free(ctx);
return ret;
}
......@@ -392,18 +431,17 @@ static int ixfr_finalize(struct refresh_data *data)
IXFRIN_LOG(LOG_WARNING, data->zone->name, data->remote,
"failed to write changes to journal (%s)",
knot_strerror(ret));
update_rollback(&ctx);
update_rollback(ctx);
update_free_zone(&new_zone);
free(ctx);
return ret;
}
zone_contents_t *old_zone = zone_switch_contents(data->zone, new_zone);
xfr_log_publish(data->zone->name, data->remote, old_zone, new_zone);
synchronize_rcu();
update_free_zone(&old_zone);
update_cleanup(&ctx);
ctx->contents = old_zone;
callrcu_wrapper(ctx, ixfr_finalize_cleanup);
return KNOT_EOK;
}
......@@ -752,13 +790,15 @@ static int soa_query_consume(knot_layer_t *layer, knot_pkt_t *pkt)
uint32_t local_serial = knot_soa_serial(&data->soa->rrs);
uint32_t remote_serial = knot_soa_serial(&rr->rrs);
bool current = serial_is_current(local_serial, remote_serial);
bool master_uptodate = serial_is_current(remote_serial, local_serial);
REFRESH_LOG(LOG_INFO, data->zone->name, data->remote,
"remote serial %u, %s", remote_serial,
current ? "zone is up-to-date" : "zone is outdated");
current ? (master_uptodate ? "zone is up-to-date" :
"master is outdated") : "zone is outdated");
if (current) {
return KNOT_STATE_DONE;
return master_uptodate ? KNOT_STATE_DONE : KNOT_STATE_FAIL;
} else {
data->state = STATE_TRANSFER;
return KNOT_STATE_RESET;
......
......@@ -124,8 +124,10 @@ typedef struct {
metadata_t shadow_md;
} txn_t;
static void md_get(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t *res);
static void md_set(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t val);
static void md_get(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint64_t *res);
static void md_get32(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t *res);
static void md_set(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint64_t val);
static void md_set32(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t val);
static void txn_init(txn_t *txn, knot_db_txn_t *db_txn, journal_t *j)
{
......@@ -201,21 +203,29 @@ static int txn_cmpkey(txn_t *txn, knot_db_val_t *key2)
return memcmp(txn->key.data, key2->data, key2->len);
}
static void txn_val_u32(txn_t *txn, uint32_t *res)
static void txn_val_u64(txn_t *txn, uint64_t *res)
{
if (txn->ret != KNOT_EOK) {
return;
}
if (txn->val.len != sizeof(uint32_t)) {
uint32_t beval32;
uint64_t beval;
switch (txn->val.len) {
case sizeof(uint32_t):
memcpy(&beval32, (uint32_t *)txn->val.data, sizeof(beval32));
*res = (uint64_t)be32toh(beval32);
break;
case sizeof(uint64_t):
memcpy(&beval, (uint64_t *)txn->val.data, sizeof(beval));
*res = be64toh(beval);
break;
default:
txn->ret = KNOT_EMALF;
}
uint32_t beval;
memcpy(&beval, (uint32_t *)txn->val.data, sizeof(beval));
*res = be32toh(beval);
}
#define txn_begin_md(md) md_get(txn, txn->j->zone, #md, &txn->shadow_md.md)
#define txn_commit_md(md) md_set(txn, txn->j->zone, #md, txn->shadow_md.md)
#define txn_begin_md(md) md_get32(txn, txn->j->zone, #md, &txn->shadow_md.md)
#define txn_commit_md(md) md_set32(txn, txn->j->zone, #md, txn->shadow_md.md)
#define txn_check(txn) if ((txn)->ret != KNOT_EOK) return
#define txn_check_ret(txn) if ((txn)->ret != KNOT_EOK) return ((txn)->ret)
......@@ -225,8 +235,10 @@ static void txn_val_u32(txn_t *txn, uint32_t *res)
static void txn_begin(txn_t *txn, bool write_allowed)
{
if (txn->ret != KNOT_ESEMCHECK) {
if (txn->ret == KNOT_EOK) {
txn->ret = KNOT_EINVAL;
}
if (txn->ret != KNOT_ESEMCHECK) {
return;
}
......@@ -404,17 +416,28 @@ static void txn_unreuse(txn_t **txn, txn_t *reused)
* ********************************************************************
*/
static void md_get(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t *res)
static void md_get(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint64_t *res)
{
txn_check(txn);
txn_key_str(txn, zone, mdkey);
uint32_t res1 = 0;
uint64_t res1 = 0;
if (txn_find(txn)) {
txn_val_u32(txn, &res1);
txn_val_u64(txn, &res1);
}
*res = res1;
}
static void md_get32(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t *res)
{
uint64_t res1 = 0;
md_get(txn, zone, mdkey, &res1);
if (res1 > UINT32_MAX) {
txn->ret = KNOT_EMALF;
} else {
*res = (uint32_t)res1;
}
}
// allocates res
static void md_get_common_last_inserter_zone(txn_t *txn, knot_dname_t **res)
{
......@@ -438,14 +461,34 @@ static int md_set_common_last_inserter_zone(txn_t *txn, knot_dname_t *zone)
return txn->ret;
}
static void md_del_last_inserter_zone(txn_t *txn, knot_dname_t *if_equals)
{
txn_check(txn);
txn_key_str(txn, NULL, MDKEY_GLOBAL_LAST_INSERTER_ZONE);
if (txn_find(txn)) {
if (if_equals == NULL || knot_dname_is_equal(txn->val.data, if_equals)) {
txn_del(txn);
}
}
}
static void md_get_common_last_occupied(txn_t *txn, size_t *res)
{
uint32_t sres = 0;
uint64_t sres = 0;
md_get(txn, NULL, MDKEY_GLOBAL_LAST_TOTAL_OCCUPIED, &sres);
*res = (size_t) sres;
}
static void md_set(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t val)
static void md_set(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint64_t val)
{
txn_key_str(txn, zone, mdkey);
uint64_t val1 = htobe64(val);
txn->val.len = sizeof(uint64_t);
txn->val.data = &val1;
txn_insert(txn);
}
static void md_set32(txn_t *txn, const knot_dname_t *zone, const char *mdkey, uint32_t val)
{
txn_key_str(txn, zone, mdkey);
uint32_t val1 = htobe32(val);
......@@ -517,7 +560,7 @@ static int first_digit(char * of)
static void md_update_journal_count(txn_t * txn, int change_amount)
{
uint32_t jcnt = 0;
uint64_t jcnt = 0;
md_get(txn, NULL, MDKEY_GLOBAL_JOURNAL_COUNT, &jcnt);
md_set(txn, NULL, MDKEY_GLOBAL_JOURNAL_COUNT, jcnt + change_amount);
}
......@@ -869,6 +912,8 @@ static int drop_journal(journal_t *j, txn_t *_txn)
if (md_flag(txn, SERIAL_TO_VALID)) {
delete_upto(j, txn, txn->shadow_md.first_serial, txn->shadow_md.last_serial);
}
md_del_last_inserter_zone(txn, j->zone);
md_set(txn, j->zone, MDKEY_PERZONE_OCCUPIED, 0);
unreuse_txn(txn, _txn);
txn_ret(txn);
}
......@@ -1110,17 +1155,19 @@ static int store_changesets(journal_t *j, list_t *changesets)
md_set(txn, NULL, MDKEY_GLOBAL_LAST_TOTAL_OCCUPIED, occupied_now);
if (occupied_now != occupied_last) {
knot_dname_t *last_zone = NULL;
uint32_t lz_occupied;
uint64_t lz_occupied;
md_get_common_last_inserter_zone(txn, &last_zone);
md_get(txn, last_zone, MDKEY_PERZONE_OCCUPIED, &lz_occupied);
lz_occupied += occupied_now - occupied_last;
md_set(txn, last_zone, MDKEY_PERZONE_OCCUPIED, lz_occupied);
free(last_zone);
if (last_zone != NULL) {
md_get(txn, last_zone, MDKEY_PERZONE_OCCUPIED, &lz_occupied);
lz_occupied += occupied_now - occupied_last;
md_set(txn, last_zone, MDKEY_PERZONE_OCCUPIED, lz_occupied);
free(last_zone);
}
}
md_set_common_last_inserter_zone(txn, j->zone);
// PART 3 : check if we exceeded designed occupation and delete some
uint32_t occupied = 0, occupied_max;
uint64_t occupied = 0, occupied_max;
md_get(txn, j->zone, MDKEY_PERZONE_OCCUPIED, &occupied);
occupied_max = journal_max_usage(j);
occupied += serialized_size_total;
......@@ -1550,6 +1597,9 @@ int scrape_journal(journal_t *j)
txn->ret = j->db->db_api->del(txn->txn, (knot_db_val_t *)del_one->d);
}
md_update_journal_count(txn, -1);
md_del_last_inserter_zone(txn, j->zone);
txn->ret = j->db->db_api->txn_commit(txn->txn);
}
scrape_end:
......@@ -1588,7 +1638,7 @@ void journal_metadata_info(journal_t *j, bool *is_empty, uint32_t *serial_from,
int journal_db_list_zones(journal_db_t **db, list_t *zones)
{
uint32_t expected_count;
uint64_t expected_count;
if (list_size(zones) > 0) {
return KNOT_EINVAL;
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -33,7 +33,7 @@
const yp_item_t scheme_mod_dnstap[] = {
{ C_ID, YP_TSTR, YP_VNONE },
{ MOD_SINK, YP_TSTR, YP_VNONE },
{ MOD_SINK, YP_TSTR, YP_VSTR = { "" } },
{ MOD_IDENTITY, YP_TSTR, YP_VNONE },
{ MOD_VERSION, YP_TSTR, YP_VSTR = { "Knot DNS " PACKAGE_VERSION } },
{ MOD_QUERIES, YP_TBOOL, YP_VBOOL = { true } },
......@@ -46,7 +46,7 @@ int check_mod_dnstap(conf_check_t *args)
{
conf_val_t sink = conf_rawid_get_txn(args->conf, args->txn, C_MOD_DNSTAP,
MOD_SINK, args->id, args->id_len);
if (sink.code != KNOT_EOK) {
if (conf_str(&sink)[0] == '\0') {
args->err_str = "no sink specified";
return KNOT_EINVAL;
}
......@@ -235,17 +235,19 @@ int dnstap_load(struct query_module *self)
/* Set identity. */
val = conf_mod_get(self->config, MOD_IDENTITY, self->id);
if (val.code == KNOT_EOK) {
ctx->identity = strdup(conf_str(&val));
const char *ident = conf_str(&val);
ctx->identity = (ident != NULL) ? strdup(ident) : NULL;
} else {
ctx->identity = sockaddr_hostname();
ctx->identity = strdup(self->config->hostname);
}
ctx->identity_len = (ctx->identity != NULL) ? strlen(ctx->identity) : 0;
/* Set version. */
val = conf_mod_get(self->config, MOD_VERSION, self->id);
ctx->version = strdup(conf_str(&val));
ctx->version = strdup(conf_str(&val)); // Default ensures != NULL.
ctx->version_len = strlen(ctx->version);
/* Set sink. */
val = conf_mod_get(self->config, MOD_SINK, self->id);
const char *sink = conf_str(&val);
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -27,7 +27,7 @@
const yp_item_t scheme_mod_rosedb[] = {
{ C_ID, YP_TSTR, YP_VNONE },
{ MOD_DBDIR, YP_TSTR, YP_VNONE },
{ MOD_DBDIR, YP_TSTR, YP_VSTR = { "" } },
{ C_COMMENT, YP_TSTR, YP_VNONE },
{ NULL }
};
......@@ -36,7 +36,7 @@ int check_mod_rosedb(conf_check_t *args)
{
conf_val_t dir = conf_rawid_get_txn(args->conf, args->txn, C_MOD_ROSEDB,
MOD_DBDIR, args->id, args->id_len);
if (dir.code != KNOT_EOK) {
if (conf_str(&dir)[0] == '\0') {
args->err_str = "no database directory specified";
return KNOT_EINVAL;
}
......@@ -468,11 +468,11 @@ static int rosedb_send_log(int sock, struct sockaddr_storage *dst_addr, knot_pkt
/* Host name / Component. */
conf_val_t val = conf_get(conf(), C_SRV, C_IDENT);
if (val.code != KNOT_EOK || val.len <= 1) {
STREAM_WRITE(stream, &maxlen, snprintf, "%s ", conf()->hostname);
} else {
STREAM_WRITE(stream, &maxlen, snprintf, "%s ", conf_str(&val));
const char *ident = conf_str(&val);
if (ident == NULL || ident[0] == '\0') {
ident = conf()->hostname;
}
STREAM_WRITE(stream, &maxlen, snprintf, "%s ", ident);
STREAM_WRITE(stream, &maxlen, snprintf, "%s[%lu]: ", PACKAGE_NAME, (unsigned long) getpid());
/* Prepare log message line. */
......
......@@ -20,7 +20,6 @@
#include "knot/nameserver/chaos.h"
#include "knot/conf/conf.h"
#include "libknot/libknot.h"
#include "dnssec/lib/dnssec/random.h"
#define WISH "Knot DNS developers wish you "
#define HOPE "Knot DNS developers hope you "
......@@ -40,74 +39,61 @@ static const char *wishes[] = {
HOPE "won't find surprising news in today's journal.",
HOPE "perform rollover often just when playing roulette.",
HOPE "get notified before your domain registration expires.",
/*! \todo add more */
};
#undef WISH
#undef HOPE
/*!
* \brief Get a string result for a given TXT query.
*/
static const char *get_txt_response_string(const knot_dname_t *qname)
static const char *get_txt_response_string(knot_pkt_t *response)
{
char *qname_str = knot_dname_to_str_alloc(qname);
const char *response = NULL;
char qname[32];
if (knot_dname_to_str(qname, knot_pkt_qname(response), sizeof(qname)) == NULL) {
return NULL;
}
/* id.server and hostname.bind should have similar meaning. */
if (strcasecmp("id.server.", qname_str) == 0 ||
strcasecmp("hostname.bind.", qname_str) == 0) {
const char *response_str = NULL;
/* Allow hostname.bind. for compatibility. */
if (strcasecmp("id.server.", qname) == 0 ||
strcasecmp("hostname.bind.", qname) == 0) {
conf_val_t val = conf_get(conf(), C_SRV, C_IDENT);
response = conf_str(&val);
/* No item means auto. */
if (val.code != KNOT_EOK) {
response = conf()->hostname;
if (val.code == KNOT_EOK) {
response_str = conf_str(&val); // Can be NULL!
} else {
response_str = conf()->hostname;
}
/* Allow both version version.{server, bind}. for compatibility. */
} else if (strcasecmp("version.server.", qname_str) == 0 ||
strcasecmp("version.bind.", qname_str) == 0) {
/* Allow version.bind. for compatibility. */
} else if (strcasecmp("version.server.", qname) == 0 ||
strcasecmp("version.bind.", qname) == 0) {
conf_val_t val = conf_get(conf(), C_SRV, C_VERSION);
response = conf_str(&val);
/* No item means auto. */
if (val.code != KNOT_EOK) {
response = "Knot DNS " PACKAGE_VERSION;
if (val.code == KNOT_EOK) {
response_str = conf_str(&val); // Can be NULL!
} else {
response_str = "Knot DNS " PACKAGE_VERSION;
}
} else if (strcasecmp("fortune.", qname_str) == 0) {
} else if (strcasecmp("fortune.", qname) == 0) {
conf_val_t val = conf_get(conf(), C_SRV, C_VERSION);
/* No item means auto. */
if (val.code != KNOT_EOK) {
uint16_t wishno = dnssec_random_uint16_t() %
uint16_t wishno = knot_wire_get_id(response->wire) %
(sizeof(wishes) / sizeof(wishes[0]));
response = wishes[wishno];
response_str = wishes[wishno];
}
}
free(qname_str);
return response;
return response_str;
}
/*!
* \brief Create TXT RR with a given string content.
*
* \param owner RR owner name.
* \param response String to be saved in RDATA. Truncated to 255 chars.
* \param mm Memory context.
* \param rrset Store here.
*
* \return KNOT_EOK
*/
static int create_txt_rrset(knot_rrset_t *rrset, const knot_dname_t *owner,
const char *response, knot_mm_t *mm)
const char *response_str, knot_mm_t *mm)
{
/* Truncate response to one TXT label. */
size_t response_len = strlen(response);
if (response_len > KNOT_DNAME_MAXLEN) {
response_len = KNOT_DNAME_MAXLEN;
size_t response_len = strlen(response_str);
if (response_len > UINT8_MAX) {
response_len = UINT8_MAX;
}
knot_dname_t *rowner = knot_dname_copy(owner, mm);
if (!rowner) {
if (rowner == NULL) {
return KNOT_ENOMEM;
}
......@@ -115,7 +101,7 @@ static int create_txt_rrset(knot_rrset_t *rrset, const knot_dname_t *owner,
uint8_t rdata[response_len + 1];
rdata[0] = response_len;
memcpy(&rdata[1], response, response_len);
memcpy(&rdata[1], response_str, response_len);
int ret = knot_rrset_add_rdata(rrset, rdata, response_len + 1, 0, mm);
if (ret != KNOT_EOK) {
......@@ -126,22 +112,16 @@ static int create_txt_rrset(knot_rrset_t *rrset, const knot_dname_t *owner,
return KNOT_EOK;
}
/*!
* \brief Create a response for a TXT CHAOS query.
*
* \param return KNOT_RCODE_NOERROR if the response was successfully created,
* otherwise an RCODE representing the failure.
*/
static int answer_txt(knot_pkt_t *response)
{
const knot_dname_t *qname = knot_pkt_qname(response);
const char *response_str = get_txt_response_string(qname);
const char *response_str = get_txt_response_string(response);
if (response_str == NULL || response_str[0] == '\0') {
return KNOT_RCODE_REFUSED;
}
knot_rrset_t rrset;
int ret = create_txt_rrset(&rrset, qname, response_str, &response->mm);
int ret = create_txt_rrset(&rrset, knot_pkt_qname(response),
response_str, &response->mm);
if (ret != KNOT_EOK) {
return KNOT_RCODE_SERVFAIL;
}
......
......@@ -105,10 +105,11 @@ static int dname_cname_synth(const knot_rrset_t *dname_rr,
*/
static bool dname_cname_cannot_synth(const knot_rrset_t *rrset, const knot_dname_t *qname)
{
if (knot_dname_labels(qname, NULL)
- knot_dname_labels(rrset->owner, NULL)
+ knot_dname_labels(knot_dname_target(&rrset->rrs), NULL)
> KNOT_DNAME_MAXLABELS) {
if (knot_dname_labels(qname, NULL) - knot_dname_labels(rrset->owner, NULL) +
knot_dname_labels(knot_dname_target(&rrset->rrs), NULL) > KNOT_DNAME_MAXLABELS) {
return true;
} else if (knot_dname_size(qname) - knot_dname_size(rrset->owner) +
knot_dname_size(knot_dname_target(&rrset->rrs)) > KNOT_DNAME_MAXLEN) {
return true;
} else {
return false;
......@@ -309,20 +310,20 @@ static int follow_cname(knot_pkt_t *pkt, uint16_t rrtype, struct query_data *qda
if (rrtype == KNOT_RRTYPE_DNAME) {
if (dname_cname_cannot_synth(&cname_rr, qdata->name)) {
qdata->rcode = KNOT_RCODE_YXDOMAIN;
return ERROR;
}
knot_rrset_t dname_rr = cname_rr;
int ret = dname_cname_synth(&dname_rr, qdata->name, &cname_rr,
&pkt->mm);
if (ret != KNOT_EOK) {
qdata->rcode = KNOT_RCODE_SERVFAIL;
return ERROR;
}
ret = process_query_put_rr(pkt, qdata, &cname_rr, NULL, 0, KNOT_PF_FREE);
switch (ret) {
case KNOT_EOK: break;
case KNOT_ESPACE: return TRUNC;
default: return ERROR;
} else {
knot_rrset_t dname_rr = cname_rr;
int ret = dname_cname_synth(&dname_rr, qdata->name,
&cname_rr, &pkt->mm);
if (ret != KNOT_EOK) {
qdata->rcode = KNOT_RCODE_SERVFAIL;
return ERROR;
}
ret = process_query_put_rr(pkt, qdata, &cname_rr, NULL, 0, KNOT_PF_FREE);
switch (ret) {
case KNOT_EOK: break;
case KNOT_ESPACE: return TRUNC;
default: return ERROR;
}
}
}
......
/* Copyright (C) 2016 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -410,12 +410,13 @@ static void set_rcode_to_packet(knot_pkt_t *pkt, struct query_data *qdata)
static int process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt)
{
assert(pkt && ctx);
assert(ctx && pkt);
struct query_data *qdata = QUERY_DATA(ctx);
/* Initialize response from query packet. */
knot_pkt_t *query = qdata->query;
knot_pkt_init_response(pkt, query);
(void)knot_pkt_init_response(pkt, query);
knot_wire_clear_cd(pkt->wire);
/* Set TC bit if required. */
......@@ -426,31 +427,45 @@ static int process_query_err(knot_layer_t *ctx, knot_pkt_t *pkt)
/* Restore original QNAME. */
process_query_qname_case_restore(pkt, qdata);
/* Add OPT and TSIG (best effort, send reply anyway if fails). */
/* Move to Additionals to add OPT and TSIG. */
if (pkt->current != KNOT_ADDITIONAL) {
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
(void)knot_pkt_begin(pkt, KNOT_ADDITIONAL);
}
/* Put OPT RR to the additional section. */
if (answer_edns_reserve(pkt, qdata) == KNOT_EOK) {
(void)answer_edns_put(pkt, qdata);
} else {
qdata->rcode = KNOT_RCODE_SERVFAIL;
if (answer_edns_reserve(pkt, qdata) != KNOT_EOK ||
answer_edns_put(pkt, qdata) != KNOT_EOK) {
qdata->rcode = KNOT_RCODE_FORMERR;
}
/* Set final RCODE to packet. */
if (qdata->rcode == KNOT_RCODE_NOERROR) {
/* Default RCODE is SERVFAIL if not otherwise specified. */
qdata->rcode = KNOT_RCODE_SERVFAIL;
}
set_rcode_to_packet(pkt, qdata);
/* Transaction security (if applicable). */
(void)process_query_sign_response(pkt, qdata);
if (process_query_sign_response(pkt, qdata) != KNOT_EOK) {
set_rcode_to_packet(pkt, qdata);
}
return KNOT_STATE_DONE;
}
/*! \brief Helper for repetitive code. */
#define PROCESS_STAGE(plan, query_stage, step, next_state, qdata) \
#define PROCESS_BEGIN(plan, step, next_state, qdata) \
if (plan != NULL) { \
WALK_LIST(step, plan->stage[query_stage]) { \
WALK_LIST(step, plan->stage[QPLAN_BEGIN]) { \
next_state = step->process(next_state, pkt, qdata, step->ctx); \
if (next_state == KNOT_STATE_FAIL) { \
goto finish; \
} \
} \
}
#define PROCESS_END(plan, step, next_state, qdata) \
if (plan != NULL) { \
WALK_LIST(step, plan->stage[QPLAN_END]) { \
next_state = step->process(next_state, pkt, qdata, step->ctx); \
if (next_state == KNOT_STATE_FAIL) { \
next_state = process_query_err(ctx, pkt); \
......@@ -490,11 +505,11 @@ static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
}
/* Before query processing code. */
PROCESS_STAGE(plan, QPLAN_BEGIN, step, next_state, qdata);
PROCESS_STAGE(zone_plan, QPLAN_BEGIN, step, next_state, qdata);
PROCESS_BEGIN(plan, step, next_state, qdata);
PROCESS_BEGIN(zone_plan, step, next_state, qdata);
/* Answer based on qclass. */
if (next_state != KNOT_STATE_DONE) {
if (next_state == KNOT_STATE_PRODUCE) {
switch (knot_pkt_qclass(pkt)) {
case KNOT_CLASS_CH:
next_state = query_chaos(pkt, ctx);
......@@ -512,16 +527,17 @@ static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
/* Postprocessing. */
if (next_state == KNOT_STATE_DONE || next_state == KNOT_STATE_PRODUCE) {
/* Restore original QNAME. */
process_query_qname_case_restore(pkt, qdata);
/* Move to Additionals to add OPT and TSIG. */
if (pkt->current != KNOT_ADDITIONAL) {
knot_pkt_begin(pkt, KNOT_ADDITIONAL);
(void)knot_pkt_begin(pkt, KNOT_ADDITIONAL);
}
/* Put OPT RR to the additional section. */
if (answer_edns_put(pkt, qdata) != KNOT_EOK) {
qdata->rcode = KNOT_RCODE_FORMERR;
next_state = KNOT_STATE_FAIL;
goto finish;
}
......@@ -534,23 +550,16 @@ static int process_query_out(knot_layer_t *ctx, knot_pkt_t *pkt)
}
finish:
/* Error processing. */
switch (next_state) {
case KNOT_STATE_FAIL:
/* Default RCODE is SERVFAIL if not otherwise specified. */
if (qdata->rcode == KNOT_RCODE_NOERROR) {
qdata->rcode = KNOT_RCODE_SERVFAIL;
}
next_state = process_query_err(ctx, pkt);
break;
default:
/* Store Extended RCODE - divide between header and OPT. */
if (next_state != KNOT_STATE_FAIL) {
set_rcode_to_packet(pkt, qdata);
} else {
/* Error processing. */
next_state = process_query_err(ctx, pkt);
}
/* After query processing code. */
PROCESS_STAGE(zone_plan, QPLAN_END, step, next_state, qdata);
PROCESS_STAGE(plan, QPLAN_END, step, next_state, qdata);
PROCESS_END(plan, step, next_state, qdata);
PROCESS_END(zone_plan, step, next_state, qdata);
rcu_read_unlock();
......@@ -698,7 +707,7 @@ int process_query_sign_response(knot_pkt_t *pkt, struct query_data *qdata)
}
}
return ret;
return KNOT_EOK;
/* Server failure in signing. */
fail:
......
......@@ -46,6 +46,14 @@
#include "knot/nameserver/internet.h"
#include "contrib/ucw/lists.h"
#ifdef HAVE_ATOMIC
#define ATOMIC_ADD(dst, val) __atomic_add_fetch(dst, val, __ATOMIC_RELAXED);
#define ATOMIC_SUB(dst, val) __atomic_sub_fetch(dst, val, __ATOMIC_RELAXED);
#else
#define ATOMIC_ADD(dst, val) __sync_fetch_and_add(dst, val);
#define ATOMIC_SUB(dst, val) __sync_fetch_and_sub(dst, val);
#endif
#define MODULE_ERR(mod, msg, ...) \
log_error("module '%.*s', " msg, mod[0], mod + 1, ##__VA_ARGS__)
......@@ -133,7 +141,7 @@ inline static void mod_ctr_incr(mod_ctr_t *stats, uint32_t idx, uint64_t val)
mod_ctr_t *ctr = stats + idx;
assert(ctr->count == 1);
__atomic_add_fetch(&ctr->counter, val, __ATOMIC_RELAXED);
ATOMIC_ADD(&ctr->counter, val);
}
inline static void mod_ctr_decr(mod_ctr_t *stats, uint32_t idx, uint64_t val)
......@@ -141,7 +149,7 @@ inline static void mod_ctr_decr(mod_ctr_t *stats, uint32_t idx, uint64_t val)
mod_ctr_t *ctr = stats + idx;
assert(ctr->count == 1);
__atomic_sub_fetch(&ctr->counter, val, __ATOMIC_RELAXED);
ATOMIC_SUB(&ctr->counter, val);
}
inline static void mod_ctrs_incr(mod_ctr_t *stats, uint32_t idx, uint32_t offset, uint64_t val)
......@@ -151,9 +159,9 @@ inline static void mod_ctrs_incr(mod_ctr_t *stats, uint32_t idx, uint32_t offset
// Increment the last counter if offset overflows.
if (offset < ctr->count) {
__atomic_add_fetch(&ctr->counters[offset], val, __ATOMIC_RELAXED);
ATOMIC_ADD(&ctr->counters[offset], val);
} else {
__atomic_add_fetch(&ctr->counters[ctr->count - 1], val, __ATOMIC_RELAXED);
ATOMIC_ADD(&ctr->counters[ctr->count - 1], val);
}
}
......@@ -164,9 +172,9 @@ inline static void mod_ctrs_decr(mod_ctr_t *stats, uint32_t idx, uint32_t offset
// Increment the last counter if offset overflows.
if (offset < ctr->count) {
__atomic_sub_fetch(&ctr->counters[offset], val, __ATOMIC_RELAXED);
ATOMIC_SUB(&ctr->counters[offset], val);
} else {
__atomic_sub_fetch(&ctr->counters[ctr->count - 1], val, __ATOMIC_RELAXED);
ATOMIC_SUB(&ctr->counters[ctr->count - 1], val);
}
}
......
......@@ -198,7 +198,7 @@ static void process_requests(conf_t *conf, zone_t *zone, list_t *requests)
struct timespec t_end = time_now();
log_zone_info(zone->name, "DDNS, update finished, serial %u -> %u, "
"%.02f seconds", old_serial, new_serial,
time_diff_ms(&t_start, &t_end));
time_diff_ms(&t_start, &t_end) / 1000.0);
zone_events_schedule_at(zone, ZONE_EVENT_NOTIFY, time(NULL) + 1);
}
......
......@@ -182,7 +182,7 @@ static int server_init_iface(iface_t *new_if, struct sockaddr_storage *addr, int
udp_bind_flags |= NET_BIND_NONLOCAL;
sock = net_bound_socket(SOCK_DGRAM, (struct sockaddr *)addr, udp_bind_flags);
if (sock >= 0 && !warn_bind) {
log_warning("address '%s' is not available", addr_str);
log_warning("address '%s' bound, but required nonlocal bind", addr_str);
warn_bind = true;
}
}
......
......@@ -320,9 +320,14 @@ int knot_pkt_init_response(knot_pkt_t *pkt, const knot_pkt_t *query)
}
pkt->size = base_size;
pkt->qname_size = query->qname_size;
memcpy(pkt->wire, query->wire, base_size);
pkt->qname_size = query->qname_size;
if (query->qname_size == 0) {
/* Reset question count if malformed. */
knot_wire_set_qdcount(pkt->wire, 0);
}
/* Update size and flags. */
knot_wire_set_qr(pkt->wire);
knot_wire_clear_tc(pkt->wire);
......@@ -695,7 +700,6 @@ static int check_rr_constraints(knot_pkt_t *pkt, knot_rrset_t *rr, size_t rr_siz
pkt->size -= rr_size;
pkt->tsig_wire.pos = pkt->wire + pkt->parsed;
pkt->tsig_wire.len = rr_size;
knot_wire_set_id(pkt->wire, knot_tsig_rdata_orig_id(rr));
knot_wire_set_arcount(pkt->wire, knot_wire_get_arcount(pkt->wire) - 1);
}
break;
......
......@@ -546,6 +546,9 @@ static int check_digest(const knot_rrset_t *tsig_rr,
memset(wire_to_sign, 0, size);
memcpy(wire_to_sign, wire, size);
// restore message ID to which the signature had been created with
knot_wire_set_id(wire_to_sign, knot_tsig_rdata_orig_id(tsig_rr));
uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
size_t digest_tmp_len = 0;
assert(tsig_rr->rrs.rr_count > 0);
......