Commit 568f5fc1 authored by Lubos Slovak's avatar Lubos Slovak

Merge branch 'master' into lowercase

Conflicts:
	Knot.files
parents 69627e82 a053cc38
Doxyfile
KNOWN_ISSUES
Makefile.am
README
configure.ac
......@@ -73,6 +71,11 @@ src/common/mem.c
src/common/mem.h
src/common/mempool.c
src/common/mempool.h
src/common/namedb/namedb.h
src/common/namedb/namedb_lmdb.c
src/common/namedb/namedb_lmdb.h
src/common/namedb/namedb_trie.c
src/common/namedb/namedb_trie.h
src/dnstap/Makefile.am
src/dnstap/convert.c
src/dnstap/convert.h
......@@ -202,6 +205,8 @@ src/knot/zone/events/handlers.h
src/knot/zone/events/handlers.c
src/knot/zone/events/replan.c
src/knot/zone/events/replan.h
src/knot/zone/timers.c
src/knot/zone/timers.h
src/libknot/binary.c
src/libknot/binary.h
src/libknot/common.h
......@@ -249,6 +254,7 @@ src/libknot/rrset-dump.h
src/libknot/rrset.c
src/libknot/rrset.h
src/libknot/rrtype/dnskey.h
src/libknot/rrtype/naptr.h
src/libknot/rrtype/nsec.h
src/libknot/rrtype/nsec3.c
src/libknot/rrtype/nsec3.h
......@@ -326,6 +332,7 @@ tests/fdset.c
tests/hattrie.c
tests/hhash.c
tests/journal.c
tests/namedb.c
tests/node.c
tests/pkt.c
tests/process_answer.c
......@@ -347,4 +354,4 @@ tests/zone_events.c
tests/zone_update.c
tests/zonedb.c
tests/ztree.c
src/libknot/rrtype/naptr.h
tests/zone_timers.c
......@@ -312,6 +312,10 @@ dt_DNSTAP([
])
AM_CONDITIONAL([HAVE_DNSTAP], test "$opt_dnstap" != "no")
dnl Check for LMDB
KNOT_CHECK_HEADER([lmdb], [LMDB], [auto], [lmdb.h], [], [-llmdb])
AS_IF([test "$enable_lmdb" = yes], [AC_DEFINE([HAVE_LMDB], [1], [Define to 1 to enable LMDB support])])
AC_SEARCH_LIBS([pow], [m])
AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR([pthreads not found])])
AC_SEARCH_LIBS([dlopen], [dl])
......@@ -407,6 +411,7 @@ AC_MSG_RESULT([
Systemd integration: ${enable_systemd}
Dnstap support: ${opt_dnstap}
Code coverage: ${enable_code_coverage}
LMDB support: ${enable_lmdb}
Continue with 'make' command
])
# KNOT_CHECK_HEADER([prefix], [name], [default], [header], [cflags], [libs])
# -----------------------------------------------------------------------------
# Check presence of a library by checking for a header file.
#
# - adds --enable-prefix configure flag
#
# - if $enable_prefix is yes or auto, checks for the header file
#
# - emits an error if $enable_prefix is yes and the header is not present
#
# - check can be overridden by setting prefix_CFLAGS and prefix_LIBS
# environment variables
#
# Output variables: $enable_foo (yes or no), $foo_CFLAGS, and $foo_LIBS
#
AC_DEFUN([KNOT_CHECK_HEADER],
[
AC_ARG_ENABLE([$1], AC_HELP_STRING([--enable-$1], [Support for $2 [default $3]]),
[enable_][$1][=$enableval], [enable_][$1][=][$3])
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $2, overriding defaults])
AC_ARG_VAR([$1][_LIBS], [linker flags for $2, overriding defaults])
AS_CASE([$enable_][$1],
[no], [
[$1][_CFLAGS]=
[$1][_LIBS]=
],
[auto|yes], [
AS_IF([test -n "$][$1][_LIBS"], [
dnl: skip header check if environment variable is set
[enable_][$1][=yes]
],[
dnl: check for header
AC_CHECK_HEADER([$4], [
[enable_][$1]=yes
[$1][_CFLAGS]=[$5]
[$1][_LIBS]=[$6]
], [
AS_IF([test "$enable_][$1][" = auto],
[[enable_][$1]=no],
[AC_MSG_ERROR([Header file "$4" for $2 not found])]
)
])
])
],
[AC_MSG_ERROR([Invalid value of --enable-$1])]
)
])
......@@ -112,6 +112,11 @@ libknotcs_la_SOURCES = \
common/mem.h \
common/mempool.c \
common/mempool.h \
common/namedb/namedb.h \
common/namedb/namedb_lmdb.h \
common/namedb/namedb_lmdb.c \
common/namedb/namedb_trie.h \
common/namedb/namedb_trie.c \
common/log.c \
common/log.h
......@@ -306,6 +311,8 @@ libknotd_la_SOURCES = \
knot/zone/node.h \
knot/zone/semantic-check.c \
knot/zone/semantic-check.h \
knot/zone/timers.c \
knot/zone/timers.h \
knot/zone/zone-diff.c \
knot/zone/zone-diff.h \
knot/zone/zone-dump.c \
......@@ -326,17 +333,20 @@ libknotd_la_SOURCES = \
# libraries
libknot_la_LIBADD = libknotcs.la zscanner/libzscanner.la
libknotd_la_LIBADD = libknots.la libknotcs.la libknot.la
libknotus_la_LIBADD = libknots.la libknotcs.la libknot.la
libknotd_la_CPPFLAGS = $(AM_CPPFLAGS) $(lmdb_CFLAGS)
libknotd_la_LDFLAGS = $(AM_LDFLAGS) $(lmdb_LIBS)
libknotus_la_CPPFLAGS = $(AM_CPPFLAGS) $(libidn_CFLAGS)
libknotus_la_LDFLAGS = $(AM_LDFLAGS) $(libidn_LIBS)
libknotcs_la_CPPFLAGS = $(AM_CPPFLAGS) $(systemd_CFLAGS)
libknotcs_la_LDFLAGS = $(AM_LDFLAGS) $(systemd_LIBS)
libknotcs_la_CPPFLAGS = $(AM_CPPFLAGS) $(systemd_CFLAGS) $(lmdb_CFLAGS)
libknotcs_la_LDFLAGS = $(AM_LDFLAGS) $(systemd_LIBS) $(lmdb_LIBS)
# sbin programs
knotd_LDADD = libknot.la libknotd.la $(systemd_LIBS)
knotd_LDADD = libknot.la libknotd.la $(systemd_LIBS) $(lmdb_LIBS)
knotc_LDADD = libknot.la libknotd.la
# bin programs
BIN_LIBS = libknotus.la libknotcs.la libknots.la libknot.la
BIN_LIBS = libknotus.la libknots.la
kdig_LDADD = $(BIN_LIBS) $(libidn_LIBS)
khost_LDADD = $(BIN_LIBS) $(libidn_LIBS)
knsupdate_LDADD = $(BIN_LIBS) zscanner/libzscanner.la
......
/* Copyright (C) 2014 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "libknot/dname.h"
enum {
KNOT_NAMEDB_RDONLY = 1 << 0,
KNOT_NAMEDB_SORTED = 1 << 1
};
typedef void knot_namedb_t;
typedef void knot_iter_t;
typedef struct knot_val {
void *data;
size_t len;
} knot_val_t;
typedef struct knot_txn {
knot_namedb_t *db;
void *txn;
} knot_txn_t;
struct namedb_api {
const char *name;
/* Context operations */
knot_namedb_t *(*init)(const char *handle, mm_ctx_t *mm);
void (*deinit)(knot_namedb_t *db);
/* Transactions */
int (*txn_begin)(knot_namedb_t *db, knot_txn_t *txn, unsigned flags);
int (*txn_commit)(knot_txn_t *txn);
void (*txn_abort)(knot_txn_t *txn);
/* Data access */
int (*count)(knot_txn_t *txn);
int (*find)(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags);
int (*insert)(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags);
int (*del)(knot_txn_t *txn,knot_val_t *key);
/* Iteration */
knot_iter_t *(*iter_begin)(knot_txn_t *txn, unsigned flags);
knot_iter_t *(*iter_next)(knot_iter_t *iter);
int (*iter_key)(knot_iter_t *iter, knot_val_t *key);
int (*iter_val)(knot_iter_t *iter, knot_val_t *val);
void (*iter_finish)(knot_iter_t *iter);
};
/* Copyright (C) 2014 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_LMDB
#include <lmdb.h>
#include "common/namedb/namedb_lmdb.h"
#include "libknot/errcode.h"
struct lmdb_env
{
MDB_dbi dbi;
MDB_env *env;
mm_ctx_t *pool;
};
static int dbase_open(struct lmdb_env *env, const char *handle)
{
int ret = mdb_env_create(&env->env);
if (ret != 0) {
return ret;
}
ret = mdb_env_open(env->env, handle, 0, 0644);
if (ret != 0) {
mdb_env_close(env->env);
return ret;
}
MDB_txn *txn = NULL;
ret = mdb_txn_begin(env->env, NULL, 0, &txn);
if (ret != 0) {
mdb_env_close(env->env);
return ret;
}
ret = mdb_open(txn, NULL, 0, &env->dbi);
if (ret != 0) {
mdb_txn_abort(txn);
mdb_env_close(env->env);
return ret;
}
ret = mdb_txn_commit(txn);
if (ret != 0) {
mdb_env_close(env->env);
return ret;
}
return 0;
}
static void dbase_close(struct lmdb_env *env)
{
mdb_close(env->env, env->dbi);
mdb_env_close(env->env);
}
static knot_namedb_t *init(const char *handle, mm_ctx_t *mm)
{
struct lmdb_env *env = mm_alloc(mm, sizeof(struct lmdb_env));
if (env == NULL) {
return NULL;
}
memset(env, 0, sizeof(struct lmdb_env));
int ret = dbase_open(env, handle);
if (ret != 0) {
mm_free(mm, env);
return NULL;
}
env->pool = mm;
return env;
}
static void deinit(knot_namedb_t *db)
{
if (db) {
struct lmdb_env *env = db;
dbase_close(env);
mm_free(env->pool, env);
}
}
static int txn_begin(knot_namedb_t *db, knot_txn_t *txn, unsigned flags)
{
txn->db = db;
txn->txn = NULL;
unsigned txn_flags = 0;
if (flags & KNOT_NAMEDB_RDONLY) {
txn_flags |= MDB_RDONLY;
}
struct lmdb_env *env = db;
int ret = mdb_txn_begin(env->env, NULL, txn_flags, (MDB_txn **)&txn->txn);
if (ret != 0) {
return KNOT_ERROR;
}
return KNOT_EOK;
}
static int txn_commit(knot_txn_t *txn)
{
int ret = mdb_txn_commit((MDB_txn *)txn->txn);
if (ret != 0) {
return KNOT_ERROR;
}
return KNOT_EOK;
}
static void txn_abort(knot_txn_t *txn)
{
mdb_txn_abort((MDB_txn *)txn->txn);
}
static int count(knot_txn_t *txn)
{
struct lmdb_env *env = txn->db;
MDB_stat stat;
int ret = mdb_stat(txn->txn, env->dbi, &stat);
if (ret != 0) {
return KNOT_ERROR;
}
return stat.ms_entries;
}
static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
struct lmdb_env *env = txn->db;
MDB_val db_key = { key->len, key->data };
MDB_val data = { 0, NULL };
int ret = mdb_get(txn->txn, env->dbi, &db_key, &data);
if (ret != 0) {
if (ret == MDB_NOTFOUND) {
return KNOT_ENOENT;
} else {
return KNOT_ERROR;
}
}
val->data = data.mv_data;
val->len = data.mv_size;
return KNOT_EOK;
}
static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
struct lmdb_env *env = txn->db;
MDB_cursor *cursor = NULL;
int ret = mdb_cursor_open(txn->txn, env->dbi, &cursor);
if (ret != 0) {
return KNOT_ERROR;
}
MDB_val db_key = { key->len, key->data };
MDB_val data = { val->len, val->data };
ret = mdb_cursor_get(cursor, &db_key, NULL, MDB_SET);
if (ret != 0) {
mdb_cursor_close(cursor);
if (ret == MDB_NOTFOUND) {
// Insert new item
ret = mdb_put(txn->txn, env->dbi, &db_key, &data, 0);
if (ret != 0) {
return KNOT_ERROR;
}
return KNOT_EOK;
} else {
return ret;
}
}
ret = mdb_cursor_put(cursor, &db_key, &data, MDB_CURRENT);
mdb_cursor_close(cursor);
if (ret != 0) {
return KNOT_ERROR;
}
return KNOT_EOK;
}
static int del(knot_txn_t *txn, knot_val_t *key)
{
struct lmdb_env *env = txn->db;
MDB_val db_key = { key->len, key->data };
MDB_val data = { 0, NULL };
int ret = mdb_del(txn->txn, env->dbi, &db_key, &data);
if (ret != 0) {
return KNOT_ERROR;
}
return KNOT_EOK;
}
static knot_iter_t *iter_begin(knot_txn_t *txn, unsigned flags)
{
struct lmdb_env *env = txn->db;
MDB_cursor *cursor = NULL;
int ret = mdb_cursor_open(txn->txn, env->dbi, &cursor);
if (ret != 0) {
return NULL;
}
ret = mdb_cursor_get(cursor, NULL, NULL, MDB_FIRST);
if (ret != 0) {
mdb_cursor_close(cursor);
return NULL;
}
return cursor;
}
static knot_iter_t *iter_next(knot_iter_t *iter)
{
MDB_cursor *cursor = iter;
int ret = mdb_cursor_get(cursor, NULL, NULL, MDB_NEXT);
if (ret != 0) {
mdb_cursor_close(cursor);
return NULL;
}
return cursor;
}
static int iter_key(knot_iter_t *iter, knot_val_t *key)
{
MDB_cursor *cursor = iter;
MDB_val mdb_key, mdb_val;
int ret = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT);
if (ret != 0) {
return KNOT_ERROR;
}
key->data = mdb_key.mv_data;
key->len = mdb_key.mv_size;
return KNOT_EOK;
}
static int iter_val(knot_iter_t *iter, knot_val_t *val)
{
MDB_cursor *cursor = iter;
MDB_val mdb_key, mdb_val;
int ret = mdb_cursor_get(cursor, &mdb_key, &mdb_val, MDB_GET_CURRENT);
if (ret != 0) {
return KNOT_ERROR;
}
val->data = mdb_val.mv_data;
val->len = mdb_val.mv_size;
return KNOT_EOK;
}
static void iter_finish(knot_iter_t *iter)
{
if (iter == NULL) {
return;
}
MDB_cursor *cursor = iter;
mdb_cursor_close(cursor);
}
struct namedb_api *namedb_lmdb_api(void)
{
static struct namedb_api api = {
"lmdb",
init, deinit,
txn_begin, txn_commit, txn_abort,
count, find, insert, del,
iter_begin, iter_next, iter_key, iter_val, iter_finish
};
return &api;
}
#else
#include <stdlib.h>
struct namedb_api *namedb_lmdb_api(void)
{
return NULL;
}
#endif
/* Copyright (C) 2014 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/namedb/namedb.h"
struct namedb_api *namedb_lmdb_api(void);
/* Copyright (C) 2014 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/namedb/namedb_trie.h"
#include "common-knot/hattrie/hat-trie.h"
#include "libknot/errcode.h"
static knot_namedb_t *init(const char *handle, mm_ctx_t *mm)
{
return hattrie_create_n(TRIE_BUCKET_SIZE, mm);
}
static void deinit(knot_namedb_t *db)
{
hattrie_free((hattrie_t *)db);
}
static int txn_begin(knot_namedb_t *db, knot_txn_t *txn, unsigned flags)
{
txn->txn = (void *)(size_t)flags;
txn->db = db;
return KNOT_EOK; /* N/A */
}
static int txn_commit(knot_txn_t *txn)
{
/* Rebuild order index only for WR transactions. */
if ((size_t)txn->txn & KNOT_NAMEDB_RDONLY) {
return KNOT_EOK;
}
hattrie_build_index((hattrie_t *)txn->db);
return KNOT_EOK;
}
static void txn_abort(knot_txn_t *txn)
{
}
static int count(knot_txn_t *txn)
{
return hattrie_weight((hattrie_t *)txn->db);
}
static int find(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
value_t *ret = hattrie_tryget((hattrie_t *)txn->db, key->data, key->len);
if (ret == NULL) {
return KNOT_ENOENT;
}
val->data = *ret;
val->len = sizeof(value_t); /* Trie doesn't support storing length. */
return KNOT_EOK;
}
static int insert(knot_txn_t *txn, knot_val_t *key, knot_val_t *val, unsigned flags)
{
value_t *ret = hattrie_get((hattrie_t *)txn->db, key->data, key->len);
if (ret == NULL) {
return KNOT_ENOMEM;
}
*ret = val->data;
return KNOT_EOK;
}
static int del(knot_txn_t *txn, knot_val_t *key)
{
return hattrie_del((hattrie_t *)txn->db, key->data, key->len);
}
static knot_iter_t *iter_begin(knot_txn_t *txn, unsigned flags)
{
return hattrie_iter_begin((hattrie_t *)txn->db, (flags & KNOT_NAMEDB_SORTED));
}
static knot_iter_t *iter_next(knot_iter_t *iter)
{
hattrie_iter_next((hattrie_iter_t *)iter);
if (hattrie_iter_finished((hattrie_iter_t *)iter)) {
hattrie_iter_free((hattrie_iter_t *)iter);
return NULL;
}
return iter;
}
static int iter_key(knot_iter_t *iter, knot_val_t *val)
{
val->data = (void *)hattrie_iter_key((hattrie_iter_t *)iter, &val->len);
if (val->data == NULL) {
return KNOT_ENOENT;
}
return KNOT_EOK;
}
static int iter_val(knot_iter_t *iter, knot_val_t *val)
{
value_t *ret = hattrie_iter_val((hattrie_iter_t *)iter);
if (ret == NULL) {
return KNOT_ENOENT;
}
val->data = *ret;
val->len = sizeof(value_t);
return KNOT_EOK;
}
static void iter_finish(knot_iter_t *iter)
{
hattrie_iter_free((hattrie_iter_t *)iter);
}
struct namedb_api *namedb_trie_api(void)
{
static struct namedb_api api = {
"hattrie",
init, deinit,
txn_begin, txn_commit, txn_abort,
count, find, insert, del,
iter_begin, iter_next, iter_key, iter_val, iter_finish
};
return &api;
}
/* Copyright (C) 2014 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/namedb/namedb.h"
struct namedb_api *namedb_trie_api(void);
......@@ -33,6 +33,7 @@
#include "knot/knot.h"
#include "knot/ctl/remote.h"
#include "knot/nameserver/internet.h"
#include "knot/zone/timers.h"
/*
* Defaults.
......@@ -724,6 +725,10 @@ void conf_truncate(conf_t *conf, int unload_hooks)
/* Free remote control iface. */