Commit 0d6fccb9 authored by Marek Vavrusa's avatar Marek Vavrusa

Merge branch 'master' into chain-fix

Conflicts:
	src/knot/server/zones.c
	src/libknot/dnssec/zone-events.c
	src/libknot/dnssec/zone-events.h
	src/libknot/updates/xfr-in.c
parents 687410a9 39ab923b
......@@ -19,6 +19,8 @@
/src/tests/Makefile.in
/src/zscanner/Makefile
/src/zscanner/Makefile.in
/patches/Makefile
/patches/Makefile.in
/samples/Makefile
/samples/Makefile.in
/doc/Makefile
......
......@@ -16,6 +16,7 @@ doc/running.texi
doc/security.texi
doc/troubleshooting.texi
man/Makefile.am
patches/Makefile.am
samples/Makefile.am
src/Makefile.am
src/common/acl.c
......@@ -141,6 +142,7 @@ src/libknot/dnssec/key.h
src/libknot/dnssec/nsec-bitmap.h
src/libknot/dnssec/nsec3.c
src/libknot/dnssec/nsec3.h
src/libknot/dnssec/policy.c
src/libknot/dnssec/policy.h
src/libknot/dnssec/random.h
src/libknot/dnssec/rrset-sign.c
......@@ -160,16 +162,27 @@ src/libknot/dnssec/zone-sign.h
src/libknot/edns.c
src/libknot/edns.h
src/libknot/libknot.h
src/libknot/nameserver/axfr.c
src/libknot/nameserver/axfr.h
src/libknot/nameserver/chaos.c
src/libknot/nameserver/chaos.h
src/libknot/nameserver/internet.c
src/libknot/nameserver/internet.h
src/libknot/nameserver/ixfr.c
src/libknot/nameserver/ixfr.h
src/libknot/nameserver/name-server.c
src/libknot/nameserver/name-server.h
src/libknot/packet/packet.c
src/libknot/packet/packet.h
src/libknot/packet/query.c
src/libknot/packet/query.h
src/libknot/packet/response.c
src/libknot/packet/response.h
src/libknot/nameserver/ns_proc_query.c
src/libknot/nameserver/ns_proc_query.h
src/libknot/nameserver/nsec_proofs.c
src/libknot/nameserver/nsec_proofs.h
src/libknot/nameserver/update.c
src/libknot/nameserver/update.h
src/libknot/packet/compr.c
src/libknot/packet/compr.h
src/libknot/packet/pkt.c
src/libknot/packet/pkt.h
src/libknot/packet/wire.h
src/libknot/rdata.h
src/libknot/rrset-dump.c
src/libknot/rrset-dump.h
......@@ -192,7 +205,6 @@ src/libknot/util/tolower.c
src/libknot/util/tolower.h
src/libknot/util/utils.c
src/libknot/util/utils.h
src/libknot/util/wire.h
src/libknot/zone/node.c
src/libknot/zone/node.h
src/libknot/zone/zone-contents.c
......@@ -269,6 +281,8 @@ tests/fdset.c
tests/hattrie.c
tests/hhash.c
tests/journal.c
tests/ns.c
tests/pkt.c
tests/rrl.c
tests/rrset.c
tests/runtests.c
......
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src samples doc man
SUBDIRS = src samples doc man patches
include $(srcdir)/tests/Makefile.inc
Knot DNS NEWS
v1.4.2 - Jan 27, 2014
---------------------
Bugfixes:
* AXFR/IXFR compatibility issues with tinydns/axfrdns
* Journal file is created only when needed
* Zone-related log messages are logged into correct category
* DNSSEC: Refresh signatures earlier (3 days before their expiration
with the default signature lifetime)
* Fixed RCU synchronization causing deadlock on 'knotc signzone'
* RRSIG not fitting in the additional records doesn't cause truncation
v1.4.1 - Jan 13, 2014
---------------------
Bugfixes:
......
# -*- Autoconf -*-
AC_PREREQ([2.60])
AC_INIT([knot], [1.4.1], [knot-dns@labs.nic.cz])
AC_INIT([knot], [1.4.2], [knot-dns@labs.nic.cz])
AM_INIT_AUTOMAKE([gnits subdir-objects dist-xz -Wall -Werror])
AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR([src/knot/main.c])
......@@ -285,7 +285,7 @@ AS_IF([test "$with_openssl" = "no"],[
AC_EGREP_CPP(openssl_version_ok,
[#include <openssl/crypto.h>
#if (OPENSSL_VERSION_NUMBER >= 0x1000000fL)
#if (OPENSSL_VERSION_NUMBER >= 0x10000000L)
openssl_version_ok
#endif
],[],[AC_MSG_ERROR([OpenSSL library version >= 1.0.0 is required.])]
......@@ -347,6 +347,7 @@ AC_CONFIG_FILES([Makefile
man/Makefile
src/Makefile
samples/Makefile
patches/Makefile
src/zscanner/Makefile
man/khost.1
man/knotc.8
......
......@@ -899,11 +899,10 @@ Default value (in @code{zone} config): inherited from @code{zones} section
Specifies how long should the automatically generated DNSSEC signatures be valid.
Expiration will thus be set as current time (in the moment of signing)
+ @code{signature-lifetime}.
Possible values are from 10801 to INT_MAX. The lower limit is because the server
will trigger resign when any of the signatures expires in 7200 seconds or less
and it was chosen as a reasonable value with regard to signing overhead. Setting
the signature lifetime to minimum value will result in re-signing the zone each
hour. For information about zone expiration date, invoke the
Possible values are from 10801 to INT_MAX. The signatures are refreshed one
tenth of the signature lifetime before the signature expiration (i.e., 3 days
before the expiration with the default value). For information about zone
expiration date, invoke the
@code{knotc zonestatus} command.
Default value: @kbd{30d} (@kbd{2592000})
......
......@@ -270,9 +270,8 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# Default value: 30d (30 days or 2592000 seconds)
# It is also possible to suffix with unit size [s/m/h/d]
# f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
# The lower limit is because the server will trigger resign when any of the
# signatures expires in 7200 seconds or less and it was chosen as a
# reasonable value with regard to signing overhead.
# The signatures are refreshed one tenth of the signature lifetime before
# the signature expiration (i.e., 3 days before by default)
signature-lifetime 30d;
# Serial policy after DDNS and automatic DNSSEC signing.
......
EXTRA_DIST = strptime_susv3.patch
diff --git a/src/libknot/dnssec/key.c b/src/libknot/dnssec/key.c
index 7dc0540..3e351bb 100644
--- a/src/libknot/dnssec/key.c
+++ b/src/libknot/dnssec/key.c
@@ -260,7 +260,15 @@ static int key_param_time(const void *save_to, char *value)
struct tm parsed = { 0 };
- if (!strptime(value, "%Y%m%d%H%M%S", &parsed)) {
+ if (strlen(value) != 14) {
+ return KNOT_EINVAL;
+ }
+
+ char *v = value;
+ char buf[32] = "";
+ int ret = sprintf(buf, "%.4s %.2s %.2s %.2s %.2s %.2s",
+ v, v + 4, v + 6, v + 8, v + 10, v + 12);
+ if (ret != 19 || !strptime(buf, "%Y %m %d %H %M %S", &parsed)) {
return KNOT_EINVAL;
}
......@@ -266,9 +266,8 @@ zones {
# Default value: 30d (30 days or 2592000 seconds)
# It is also possible to suffix with unit size [s/m/h/d]
# f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
# The lower limit is because the server will trigger resign when any of the
# signatures expires in less than 7200 seconds and it was chosen as a
# reasonable value with regard to signing overhead.
# The signatures are refreshed one tenth of the signature lifetime before
# the signature expiration (i.e., 3 days before by default)
# signature-lifetime 30d;
# Serial policy after DDNS and automatic DNSSEC signing.
......
This diff is collapsed.
......@@ -108,14 +108,12 @@ libknot_la_SOURCES = \
libknot/util/utils.h \
libknot/util/tolower.h \
libknot/util/tolower.c \
libknot/util/wire.h \
libknot/util/endian.h \
libknot/packet/query.c \
libknot/packet/response.c \
libknot/packet/packet.c \
libknot/packet/packet.h \
libknot/packet/query.h \
libknot/packet/response.h \
libknot/packet/pkt.c \
libknot/packet/pkt.h \
libknot/packet/compr.c \
libknot/packet/compr.h \
libknot/packet/wire.h \
libknot/zone/zone.c \
libknot/zone/zone-contents.c \
libknot/zone/zone-tree.c \
......@@ -128,10 +126,22 @@ libknot_la_SOURCES = \
libknot/zone/node.c \
libknot/zone/zone-diff.h \
libknot/zone/zone-diff.c \
libknot/nameserver/nsec_proofs.h \
libknot/nameserver/nsec_proofs.c \
libknot/nameserver/name-server.h \
libknot/nameserver/name-server.c \
libknot/nameserver/chaos.h \
libknot/nameserver/chaos.c \
libknot/nameserver/internet.h \
libknot/nameserver/internet.c \
libknot/nameserver/axfr.h \
libknot/nameserver/axfr.c \
libknot/nameserver/ixfr.h \
libknot/nameserver/ixfr.c \
libknot/nameserver/update.h \
libknot/nameserver/update.c \
libknot/nameserver/ns_proc_query.h \
libknot/nameserver/ns_proc_query.c \
libknot/updates/changesets.h \
libknot/updates/changesets.c \
libknot/updates/xfr-in.h \
......@@ -163,6 +173,7 @@ libknot_la_SOURCES = \
libknot/dnssec/nsec-bitmap.h \
libknot/dnssec/nsec3.c \
libknot/dnssec/nsec3.h \
libknot/dnssec/policy.c \
libknot/dnssec/policy.h \
libknot/dnssec/random.h \
libknot/dnssec/rrset-sign.c \
......
......@@ -26,6 +26,7 @@
#include "common/errcode.h"
#include "common/acl.h"
#include "libknot/util/endian.h"
#include "libknot/tsig.h"
static inline uint32_t ipv4_chunk(const sockaddr_t *a)
{
......@@ -81,7 +82,7 @@ static uint32_t acl_fill_mask32(short nbits)
return htonl(r);
}
static int acl_compare(const sockaddr_t *a1, const sockaddr_t *a2)
static int addr_match(const sockaddr_t *a1, const sockaddr_t *a2)
{
int ret = 0;
uint32_t mask = 0xffffffff;
......@@ -141,55 +142,27 @@ void acl_delete(acl_t **acl)
*acl = 0;
}
int acl_insert(acl_t *acl, const sockaddr_t *addr, void *val)
int acl_insert(acl_t *acl, const sockaddr_t *addr, knot_tsig_key_t *key)
{
if (acl == NULL || addr == NULL) {
return KNOT_EINVAL;
}
/* Create new match. */
acl_match_t *key = malloc(sizeof(acl_match_t));
if (key == NULL) {
acl_match_t *match = malloc(sizeof(acl_match_t));
if (match == NULL) {
return KNOT_ENOMEM;
}
memcpy(&key->addr, addr, sizeof(sockaddr_t));
key->val = val;
/* Sort by prefix length.
* This way the longest prefix match always goes first.
*/
if (EMPTY_LIST(*acl)) {
add_head(acl, &key->n);
} else {
bool inserted = false;
acl_match_t *cur = NULL, *prev = NULL;
WALK_LIST(cur, *acl) {
/* Next node prefix is equal/shorter than current key.
* This means we need to insert before the next node.
*/
if (cur->addr.prefix < addr->prefix) {
if (prev == NULL) { /* First node. */
add_head(acl, &key->n);
} else {
insert_node(&key->n, &prev->n);
}
inserted = true;
break;
}
prev = cur;
}
sockaddr_copy(&match->addr, addr);
match->key = key;
/* Didn't find any better fit, insert at the end. */
if (!inserted) {
add_tail(acl, &key->n);
}
}
add_tail(acl, &match->n);
return KNOT_EOK;
}
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr)
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr, const knot_dname_t *key_name)
{
if (acl == NULL || addr == NULL) {
return NULL;
......@@ -197,11 +170,25 @@ acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr)
acl_match_t *cur = NULL;
WALK_LIST(cur, *acl) {
/* Since the list is sorted by prefix length, the first match
* is guaranteed to be longest prefix match (most precise).
*/
if (acl_compare(&cur->addr, addr) == 0) {
return cur;
if (addr_match(&cur->addr, addr) == 0) {
/* NOKEY entry. */
if (cur->key == NULL) {
if (key_name == NULL) {
return cur;
}
/* NOKEY entry, but key provided. */
continue;
}
/* NOKEY provided, but key required. */
if (key_name == NULL) {
continue;
}
/* Key name match. */
if (knot_dname_is_equal(cur->key->name, key_name)) {
return cur;
}
}
}
......
......@@ -32,6 +32,10 @@
#include "common/lists.h"
#include "common/sockaddr.h"
#include "common/mempattern.h"
#include "libknot/tsig.h"
struct knot_tsig_key;
/*! \brief ACL structure. */
typedef list_t acl_t;
......@@ -40,7 +44,7 @@ typedef list_t acl_t;
typedef struct acl_match {
node_t n;
sockaddr_t addr; /*!< \brief Address for comparison. */
void *val; /*!< \brief Associated value (or NULL). */
struct knot_tsig_key *key; /*!< \brief TSIG key. */
} acl_match_t;
/*!
......@@ -69,7 +73,7 @@ void acl_delete(acl_t **acl);
* \retval KNOT_EINVAL
* \retval KNOT_ENOMEM
*/
int acl_insert(acl_t *acl, const sockaddr_t *addr, void *val);
int acl_insert(acl_t *acl, const sockaddr_t *addr, knot_tsig_key_t *key);
/*!
* \brief Match address against ACL.
......@@ -80,7 +84,7 @@ int acl_insert(acl_t *acl, const sockaddr_t *addr, void *val);
* \retval Matching rule instance if found.
* \retval NULL if it didn't find a match.
*/
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr);
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr, const knot_dname_t *key_name);
/*!
* \brief Truncate ACL.
......
......@@ -384,7 +384,7 @@ void hhash_build_index(hhash_t* tbl)
/* Free old index. */
if (tbl->index) {
if (tbl->mm.free) {
free(tbl->index);
tbl->mm.free(tbl->index);
}
tbl->index = NULL;
}
......
......@@ -177,3 +177,51 @@ size_t list_size(const list_t *l)
return count;
}
/**
* ptrlist_add - add pointer to pointer list
* @to: destination list
* @val: added pointer
* @mm: memory context
*/
ptrnode_t *ptrlist_add(list_t *to, const void *val, mm_ctx_t *mm)
{
ptrnode_t *node = mm->alloc(mm->ctx, sizeof(ptrnode_t));
if (node == NULL) {
return NULL;
} else {
node->d = val;
}
add_tail(to, &node->n);
return node;
}
/**
* ptrlist_free - free all nodes in pointer list
* @list: list nodes
* @mm: memory context
*/
void ptrlist_free(list_t *list, mm_ctx_t *mm)
{
node_t *n = NULL, *nxt = NULL;
WALK_LIST_DELSAFE(n, nxt, *list) {
mm->free(n);
}
init_list(list);
}
/**
* ptrlist_contains - check if list contains pointer
* @list: target list
* @val: searched pointer
*/
bool ptrlist_contains(list_t *list, const void *val)
{
ptrnode_t *n = NULL;
WALK_LIST(n, *list) {
if (n->d == val) {
return true;
}
}
return false;
}
......@@ -83,13 +83,19 @@ void insert_node(node_t *, node_t *);
void list_dup(list_t *dst, list_t *src, size_t itemsz);
size_t list_size(const list_t *);
#include <stdbool.h>
#include "common/mempattern.h"
/*!
* \brief List item for string lists.
* \brief Generic pointer list implementation.
*/
typedef struct strnode_t {
typedef struct ptrnode {
node_t n;
char *str;
} strnode_t;
const void *d;
} ptrnode_t;
ptrnode_t *ptrlist_add(list_t *, const void *, mm_ctx_t *);
void ptrlist_free(list_t *, mm_ctx_t *);
bool ptrlist_contains(list_t *, const void *);
/*! \todo This is broken atm.
#ifndef _BIRD_LISTS_C_
......
......@@ -223,8 +223,7 @@ static int _log_msg(logsrc_t src, int level, const char *msg)
precise = true;
#endif /* ENABLE_MICROSECONDS_LOG */
tlen = strftime(tstr, sizeof(tstr),
"%Y-%m-%dT%H:%M:%S ", &lt);
tlen = strftime(tstr, sizeof(tstr), KNOT_LOG_TIME_FORMAT " ", &lt);
if (precise && tlen > 0) {
char pm = (lt.tm_gmtoff > 0) ? '+' : '-';
......
......@@ -62,6 +62,9 @@ typedef enum {
/*! \brief Severity mapping. */
#define LOG_FATAL LOG_CRIT /*!< Fatal errors cannot be masked. */
/*! \brief Format for timestamps in log files. */
#define KNOT_LOG_TIME_FORMAT "%Y-%m-%dT%H:%M:%S"
/* Logging facility setup. */
/*!
......
......@@ -27,6 +27,7 @@
#include "common/mempattern.h"
#include "common/log.h"
#include "common/slab/alloc-common.h"
#include "common/mempool.h"
static void *mm_malloc(void *ctx, size_t n)
{
......@@ -41,6 +42,13 @@ void mm_ctx_init(mm_ctx_t *mm)
mm->free = free;
}
void mm_ctx_mempool(mm_ctx_t *mm, size_t chunk_size)
{
mm->ctx = mp_new(chunk_size);
mm->alloc = (mm_alloc_t)mp_alloc;
mm->free = mm_nofree;
}
void* xmalloc(size_t l)
{
void *p = malloc(l);
......
......@@ -47,6 +47,9 @@ typedef struct mm_ctx {
/*! \brief Initialize default memory allocation context. */
void mm_ctx_init(mm_ctx_t *mm);
/*! \brief Memory pool context. */
void mm_ctx_mempool(mm_ctx_t *mm, size_t chunk_size);
/*! \brief Allocate memory or die. */
void* xmalloc(size_t l);
......
......@@ -33,6 +33,7 @@
#include "libknot/dname.h"
#include "libknot/binary.h"
#include "libknot/edns.h"
#include "knot/server/rrl.h"
#include "knot/conf/conf.h"
#include "knot/conf/libknotd_la-cf-parse.h" /* Automake generated header. */
......@@ -652,7 +653,7 @@ system:
SET_SIZE(new_config->rrl_size, $3.i, "rate-limit-size");
}
| system RATE_LIMIT_SLIP NUM ';' {
SET_INT(new_config->rrl_slip, $3.i, "rate-limit-slip");
SET_NUM(new_config->rrl_slip, $3.i, 1, RRL_SLIP_MAX, "rate-limit-slip");
}
| system TRANSFERS NUM ';' {
SET_INT(new_config->xfers, $3.i, "transfers");
......
......@@ -443,7 +443,7 @@ static int conf_process(conf_t *conf)
sockaddr_init(&addr, -1);
sockaddr_set(&addr, i->family, i->address, 0);
sockaddr_setprefix(&addr, i->prefix);
acl_insert(conf->ctl.acl, &addr, i);
acl_insert(conf->ctl.acl, &addr, i->key);
}
return ret;
......
......@@ -34,9 +34,7 @@
#include "knot/zone/zone-load.h"
#include "knot/server/socket.h"
#include "knot/server/tcp-handler.h"
#include "libknot/util/wire.h"
#include "libknot/packet/query.h"
#include "libknot/packet/response.h"
#include "libknot/packet/wire.h"
#include "knot/zone/zone-load.h"
#include "knot/zone/estimator.h"
......@@ -137,46 +135,46 @@ static int cmd_remote_print_reply(const knot_rrset_t *rr)
static int cmd_remote_reply(int c)
{
uint8_t *rwire = malloc(SOCKET_MTU_SZ);
knot_packet_t *reply = knot_packet_new();
if (!rwire || !reply) {
free(rwire);
knot_packet_free(&reply);
knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
if (!pkt) {
return KNOT_ENOMEM;
}
/* Read response packet. */
int n = tcp_recv(c, rwire, SOCKET_MTU_SZ, NULL);
int n = tcp_recv(c, pkt->wire, pkt->max_size, NULL);
if (n <= 0) {
dbg_server("remote: couldn't receive response = %d\n", n);
knot_packet_free(&reply);
free(rwire);
dbg_server("remote: couldn't receive response = %s\n", knot_strerror(n));
knot_pkt_free(&pkt);
return KNOT_ECONN;
} else {
pkt->size = n;
}
/* Parse packet and check response. */
int ret = remote_parse(reply, rwire, n);
if (ret == KNOT_EOK) {
/* Check RCODE */
ret = knot_packet_rcode(reply);
switch(ret) {
case KNOT_RCODE_NOERROR:
if (knot_packet_authority_rrset_count(reply) > 0) {
ret = cmd_remote_print_reply(reply->authority[0]);
}
break;
case KNOT_RCODE_REFUSED:
ret = KNOT_EDENIED;
break;
default:
ret = KNOT_ERROR;
break;
int ret = remote_parse(pkt);
if (ret != KNOT_EOK) {
knot_pkt_free(&pkt);
return ret;
}
/* Check RCODE */
const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY);
ret = knot_wire_get_rcode(pkt->wire);
switch(ret) {
case KNOT_RCODE_NOERROR:
if (authority->count > 0) {
ret = cmd_remote_print_reply(authority->rr[0]);
}
break;
case KNOT_RCODE_REFUSED:
ret = KNOT_EDENIED;
break;
default:
ret = KNOT_ERROR;
break;
}
/* Response cleanup. */
knot_packet_free(&reply);
free(rwire);
knot_pkt_free(&pkt);
return ret;
}
......@@ -193,16 +191,15 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
}
/* Make query. */
uint8_t *buf = NULL;
size_t buflen = 0;
knot_packet_t *qr = remote_query(cmd, r->key);
if (!qr) {
knot_pkt_t *pkt = remote_query(cmd, r->key);
if (!pkt) {
log_server_warning("Could not prepare query for '%s'.\n",
cmd);
return 1;
}
/* Build query data. */
knot_pkt_begin(pkt, KNOT_AUTHORITY);
knot_rrset_t *rr = NULL;
if (argc > 0) {
rr = remote_build_rr("data.", rrt);
......@@ -217,23 +214,30 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
break;
}
}
remote_query_append(qr, rr);
}
if (knot_packet_to_wire(qr, &buf, &buflen) != KNOT_EOK) {
knot_rrset_deep_free(&rr, 1);
knot_packet_free(&qr);
return 1;
int res = knot_pkt_put(pkt, 0, rr, KNOT_PF_FREE);
if (res != KNOT_EOK) {
log_server_error("Couldn't create the query.\n");
knot_rrset_deep_free(&rr, 1);
knot_pkt_free(&pkt);
return 1;
}
}
if (r->key) {
remote_query_sign(buf, &buflen, qr->max_size, r->key);
int res = remote_query_sign(pkt->wire, &pkt->size, pkt->max_size, r->key);
if (res != KNOT_EOK) {
log_server_error("Couldn't sign the packet.\n");
knot_pkt_free(&pkt);
return 1;
}
}
dbg_server("%s: sending query size %zu\n", __func__, pkt->size);
/* Send query. */
int s = socket_create(r->family, SOCK_STREAM, 0);
int conn_state = socket_connect(s, r->family, r->address, r->port);
if (conn_state != KNOT_EOK || tcp_send(s, buf, buflen) <= 0) {
if (conn_state != KNOT_EOK || tcp_send(s, pkt->wire, pkt->size) <= 0) {
char portstr[32] = { '\0' };