Commit b533bb40 authored by Daniel Salzman's avatar Daniel Salzman

Integrate new configuration

parent 35421065
#
# This is a sample of a minimal configuration file for Knot DNS.
#
# For exhaustive list of all options see man 5 knot.conf or refer to user manual.
#
system {
# Identity of the server (see RFC 4892).
identity on;
# Version of the server (see RFC 4892)
version on;
# User for running server
# May also specify user.group (e.g. knot.knot)
user knot.knot;
# Directory for storing run-time data
# e.g. PID file and control sockets
# default: ${localstatedir}/run/knot, configured with --with-rundir
# rundir "@run_dir@";
}
interfaces {
all_ipv4 {
address 0.0.0.0;
port 53;
}
all_ipv6 {
address [::];
port 53;
}
}
control {
# Default: knot.sock (relative to rundir)
listen-on "knot.sock";
# As an alternative, you can use an IPv4/v6 address and port
# Same syntax as for 'interfaces' items
# listen-on { address 127.0.0.1@5533; }
# Specifies ACL list for remote control
# Same syntax as for ACLs in zones
# List of remotes or groups delimited by comma
# Notice: keep in mind that ACLs bear no effect with UNIX sockets
# allow server0, admins;
}
#remotes {
# master0 {
# address 198.51.100.1@53;
# }
# slave0 {
# address 203.0.113.1@53;
# }
#}
zones {
# This is a default directory to place slave zone files, journals etc.
# default: ${localstatedir}/lib/knot, configured with --with-storage
# storage "@storage_dir@";
#
# Example master zone
# example.com {
# file "@config_dir@/example.com.zone";
# xfr-out slave0;
# notify-out slave0;
# }
#
# Example slave zone
# example.net {
# file "@storage_dir@/example.net.zone
# xfr-in master0;
# notify-in master0;
# }
}
log {
syslog {
# Log info and more serious events to syslog
any info;
}
# Log warnings, errors and criticals to stderr
stderr {
any warning;
}
}
server:
# Identity of the server.
identity: "Knot DNS"
# Version of the server (automatic value).
version: ""
# Listening interfaces (all configured IPv4 and IPv6 interfaces).
listen: 0.0.0.0@53
listen: ::@53
remote:
- id: slave
address: 203.0.113.1@53
- id: master
address: 198.51.100.1@53
acl:
- id: acl_slave
address: 203.0.113.1
action: xfer
- id: acl_master
address: 198.51.100.1
action: notify
template:
- id: default
storage: "@storage_dir@"
zone:
# Master zone.
- domain: example.com
file: "@storage_dir@/example.com.zone"
notify: slave
acl: acl_slave
# Slave zone.
- domain: example.net
file: "@storage_dir@/example.net.zone"
master: master
acl: acl_master
log:
# Log info and more serious events to syslog.
- to: syslog
any: info
# Log warnings, errors and criticals to stderr.
- to: stderr
any: warning
ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
SUBDIRS = zscanner dnssec dnstap .
lib_LTLIBRARIES = \
libknot-int.la \
libknot.la \
lib_LTLIBRARIES = \
libknot-int.la \
libknot.la \
libknot-yparser.la
noinst_LTLIBRARIES =
......@@ -54,9 +54,9 @@ nobase_libknot_int_la_HEADERS = \
libknot_yparser_ladir = $(includedir)
nobase_libknot_yparser_la_HEADERS = \
libknot/yparser/yparser.h \
libknot/yparser/ypformat.h \
libknot/yparser/ypscheme.h \
libknot/yparser/yparser.h \
libknot/yparser/ypformat.h \
libknot/yparser/ypscheme.h \
libknot/yparser/yptrafo.h
# dynamic: libknot internal sources
......@@ -85,11 +85,11 @@ libknot_int_la_SOURCES = \
$(nobase_libknot_int_la_HEADERS)
libknot_yparser_la_SOURCES = \
libknot/yparser/yparser.c \
libknot/yparser/ypbody.c \
libknot/yparser/ypformat.c \
libknot/yparser/ypscheme.c \
libknot/yparser/yptrafo.c \
libknot/yparser/yparser.c \
libknot/yparser/ypbody.c \
libknot/yparser/ypformat.c \
libknot/yparser/ypscheme.c \
libknot/yparser/yptrafo.c \
$(nobase_libknot_yparser_la_HEADERS)
# dynamic: libknot headers
......@@ -168,12 +168,12 @@ libknot_la_LIBADD = libknot-int.la dnssec/libdnssec.la zscanner/libzscanner.la
pkgconfig_DATA = libknot.pc libknot-int.pc
if !HAVE_LMDB
libknot_int_la_SOURCES += \
libknot/internal/namedb/mdb.c \
libknot/internal/namedb/midl.c \
libknot/internal/namedb/lmdb.h \
libknot_int_la_SOURCES += \
libknot/internal/namedb/mdb.c \
libknot/internal/namedb/midl.c \
libknot/internal/namedb/lmdb.h \
libknot/internal/namedb/midl.h
libknot_int_la_CPPFLAGS += \
libknot_int_la_CPPFLAGS += \
-I$(srcdir)/libknot/internal/namedb/
endif
......@@ -330,8 +330,8 @@ libknotd_la_CPPFLAGS = $(AM_CPPFLAGS) $(systemd_CFLAGS)
libknotd_la_LDFLAGS = $(AM_LDFLAGS) $(systemd_LIBS)
libknotd_la_LIBADD = libknot.la
knotd_LDADD = libknotd.la
knotc_LDADD = libknotd.la
knotd_LDADD = libknotd.la libknot-yparser.la
knotc_LDADD = libknotd.la libknot-yparser.la
####################################
# Optional Knot DNS Daemon modules #
......
......@@ -20,7 +20,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h> // strftime
#include <time.h>
#include <urcu.h>
#ifdef ENABLE_SYSTEMD
......@@ -165,11 +165,8 @@ int log_init()
{
/* Setup initial state. */
int ret = KNOT_EOK;
int emask = LOG_MASK(LOG_WARNING)|LOG_MASK(LOG_ERR)|LOG_MASK(LOG_CRIT);
int imask = LOG_MASK(LOG_INFO)|LOG_MASK(LOG_NOTICE);
/* Add debug messages. */
emask |= LOG_MASK(LOG_DEBUG);
int emask = LOG_MASK(LOG_CRIT) | LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING);
int imask = LOG_MASK(LOG_NOTICE) | LOG_MASK(LOG_INFO) | LOG_MASK(LOG_DEBUG);
/* Publish base log sink. */
struct log_sink *log = sink_setup(0);
......@@ -427,28 +424,6 @@ int log_msg_zone_str(int priority, const char *zone, const char *fmt, ...)
return result;
}
void hex_log(const char *data, int length)
{
int ptr = 0;
char lbuf[512]={0}; int llen = 0;
for (; ptr < length; ptr++) {
if (ptr > 0 && ptr % 16 == 0) {
lbuf[llen] = '\0';
log_msg(LOG_DEBUG, "%s\n", lbuf);
llen = 0;
}
int ret = snprintf(lbuf + llen, sizeof(lbuf) - llen, "0x%02x ",
(unsigned char)*(data + ptr));
if (ret < 0 || ret >= sizeof(lbuf) - llen) {
return;
}
llen += ret;
}
if (llen > 0) {
log_msg(LOG_DEBUG, "%s\n", lbuf);
}
}
int log_update_privileges(int uid, int gid)
{
for (unsigned i = 0; i < s_log->file_count; ++i) {
......@@ -460,13 +435,28 @@ int log_update_privileges(int uid, int gid)
return KNOT_EOK;
}
int log_reconfigure(const list_t *logs, void *data)
static logtype_t get_logtype(const char *logname)
{
assert(logname);
if (strcasecmp(logname, "syslog") == 0) {
return LOGT_SYSLOG;
} else if (strcasecmp(logname, "stderr") == 0) {
return LOGT_STDERR;
} else if (strcasecmp(logname, "stdout") == 0) {
return LOGT_STDOUT;
} else {
return LOGT_FILE;
}
}
int log_reconfigure(conf_t *conf, void *data)
{
// Data not used
UNUSED(data);
// Use defaults if no 'log' section is configured.
if (EMPTY_LIST(*logs)) {
if (conf_id_count(conf, C_LOG) == 0) {
log_close();
log_init();
return KNOT_EOK;
......@@ -474,13 +464,16 @@ int log_reconfigure(const list_t *logs, void *data)
// Find maximum log facility id
unsigned files = 0;
node_t *list_node = NULL;
WALK_LIST(list_node, *logs) {
conf_log_t* log = (conf_log_t*)list_node;
if (log->type == LOGT_FILE) {
conf_iter_t iter = conf_iter(conf, C_LOG);
while (iter.code == KNOT_EOK) {
conf_val_t id = conf_iter_id(conf, &iter);
if (get_logtype(conf_str(&id)) == LOGT_FILE) {
++files;
}
conf_iter_next(conf, &iter);
}
conf_iter_finish(conf, &iter);
// Initialize logsystem
struct log_sink *log = sink_setup(files);
......@@ -489,49 +482,46 @@ int log_reconfigure(const list_t *logs, void *data)
}
// Setup logs
list_node = NULL;
WALK_LIST(list_node, *logs) {
iter = conf_iter(conf, C_LOG);
while (iter.code == KNOT_EOK) {
conf_val_t id = conf_iter_id(conf, &iter);
const char *logname = conf_str(&id);
// Calculate offset
conf_log_t* facility_conf = (conf_log_t*)list_node;
int facility = facility_conf->type;
// Get facility.
int facility = get_logtype(logname);
if (facility == LOGT_FILE) {
facility = log_open_file(log, facility_conf->file);
facility = log_open_file(log, logname);
if (facility < 0) {
log_error("failed to open log, file '%s'",
facility_conf->file);
logname);
conf_iter_next(conf, &iter);
continue;
}
}
// Setup sources mapping
node_t *m = 0;
WALK_LIST(m, facility_conf->map) {
conf_val_t level_val;
unsigned level;
// Assign mapped level
conf_log_map_t *map = (conf_log_map_t*)m;
sink_levels_add(log, facility, map->source, map->prios);
}
}
// Set SERVER logging.
level_val = conf_id_get(conf, C_LOG, C_SERVER, &id);
level = conf_opt(&level_val);
sink_levels_add(log, facility, LOG_SERVER, level);
sink_publish(log);
// Set ZONE logging.
level_val = conf_id_get(conf, C_LOG, C_ZONE, &id);
level = conf_opt(&level_val);
sink_levels_add(log, facility, LOG_ZONE, level);
return KNOT_EOK;
}
// Set ANY logging.
level_val = conf_id_get(conf, C_LOG, C_ANY, &id);
level = conf_opt(&level_val);
sink_levels_add(log, facility, LOG_ANY, level);
void log_free(conf_log_t *log)
{
if (!log) {
return;
conf_iter_next(conf, &iter);
}
conf_iter_finish(conf, &iter);
free(log->file);
/* Free loglevel mapping. */
node_t *n = NULL, *nxt = NULL;
WALK_LIST_DELSAFE(n, nxt, log->map) {
free((conf_log_map_t*)n);
}
sink_publish(log);
free(log);
return KNOT_EOK;
}
......@@ -39,9 +39,8 @@
#include <stdbool.h>
#include <assert.h>
#include "libknot/internal/lists.h"
#include "libknot/dname.h"
#include "knot/conf/conf.h"
/*! \brief Log facility types. */
typedef enum {
......@@ -61,25 +60,6 @@ typedef enum {
LOG_ANY = 7 /*!< Any module. */
} logsrc_t;
/*!
* \brief Mapping of loglevels to message sources.
*/
typedef struct conf_log_map {
node_t n;
int source; /*!< Log message source mask. */
int prios; /*!< Log priorities mask. */
} conf_log_map_t;
/*!
* \brief Log facility descriptor.
*/
typedef struct conf_log {
node_t n;
logtype_t type; /*!< Type of the log (SYSLOG/STDERR/FILE). */
char *file; /*!< Filename in case of LOG_FILE, else NULL. */
list_t map; /*!< Log levels mapping. */
} conf_log_t;
/*! \brief Format for timestamps in log files. */
#define KNOT_LOG_TIME_FORMAT "%Y-%m-%dT%H:%M:%S"
......@@ -172,8 +152,6 @@ int log_msg_zone(int priority, const knot_dname_t *zone, const char *fmt, ...)
int log_msg_zone_str(int priority, const char *zone, const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
void hex_log(const char *data, int length);
/* Convenient logging. */
#define log_fatal(msg...) log_msg(LOG_CRIT, msg)
......@@ -215,9 +193,6 @@ int log_update_privileges(int uid, int gid);
* \retval KNOT_EINVAL on invalid parameters.
* \retval KNOT_ENOMEM out of memory error.
*/
int log_reconfigure(const list_t *logs, void *data);
/*! \brief Free log config. */
void log_free(conf_log_t *log);
int log_reconfigure(conf_t *conf, void *data);
/*! @} */
This diff is collapsed.
......@@ -21,36 +21,38 @@
#include <string.h>
#include <signal.h>
#include <grp.h>
#include <unistd.h>
#include <assert.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <pwd.h>
#include <urcu.h>
#include "libknot/internal/mem.h"
#include "libknot/libknot.h"
#include "knot/ctl/process.h"
#include "knot/conf/conf.h"
#include "knot/common/log.h"
#include "libknot/errcode.h"
#include "libknot/internal/mem.h"
#include "libknot/libknot.h"
#define LOCK_FILE "knot.lock"
char* pid_filename()
{
rcu_read_lock();
/* Read configuration. */
char* ret = NULL;
if (conf()) {
if (conf()->pidfile != NULL)
ret = strdup(conf()->pidfile);
else if (conf()->rundir != NULL)
ret = strcdup(conf()->rundir, "/knot.pid");
}
conf_val_t val = conf_get(conf(), C_SRV, C_RUNDIR);
char *rundir = conf_abs_path(&val, NULL);
val = conf_get(conf(), C_SRV, C_PIDFILE);
char *pidfile = conf_abs_path(&val, rundir);
rcu_read_unlock();
return ret;
if (rundir != NULL) {
free(rundir);
return pidfile;
} else {
return NULL;
}
}
pid_t pid_read(const char* fn)
......@@ -171,35 +173,39 @@ int proc_update_privileges(int uid, int gid)
}
}
/* Check storage writeability. */
int ret = KNOT_EOK;
const bool sorted = false;
hattrie_iter_t *z_iter = hattrie_iter_begin(conf()->zones, sorted);
if (z_iter == NULL) {
return KNOT_ERROR;
}
for (; !hattrie_iter_finished(z_iter); hattrie_iter_next(z_iter)) {
conf_zone_t *zone = (conf_zone_t *)*hattrie_iter_val(z_iter);
char *lfile = strcdup(zone->storage, "/knot.lock");
/* Check storage writability. */
conf_iter_t iter = conf_iter(conf(), C_ZONE);
while (iter.code == KNOT_EOK) {
conf_val_t id = conf_iter_id(conf(), &iter);
conf_val_t val = conf_zone_get(conf(), C_STORAGE, conf_dname(&id));
char *storage = conf_abs_path(&val, NULL);
if (storage == NULL) {
conf_iter_finish(conf(), &iter);
return KNOT_ENOMEM;
}
char *lfile = sprintf_alloc("%s/%s", storage, LOCK_FILE);
assert(lfile != NULL);
FILE* fp = fopen(lfile, "w");
FILE *fp = fopen(lfile, "w");
if (fp == NULL) {
log_warning("storage directory '%s' is not writable",
zone->storage);
ret = KNOT_EACCES;
log_error("storage directory '%s' is not writable",
storage);
free(lfile);
free(storage);
conf_iter_finish(conf(), &iter);
return KNOT_EACCES;
} else {
fclose(fp);
unlink(lfile);
}
free(lfile);
free(storage);
if (ret != KNOT_EOK) {
break;
}
conf_iter_next(conf(), &iter);
}
hattrie_iter_free(z_iter);
conf_iter_finish(conf(), &iter);
return ret;
return KNOT_EOK;
}
char *pid_check_and_create()
......
......@@ -16,6 +16,7 @@
#include <assert.h>
#include <sys/stat.h>
#include <urcu.h>
#include "dnssec/random.h"
#include "knot/common/debug.h"
......@@ -172,7 +173,11 @@ static int remote_zone_refresh(zone_t *zone, remote_cmdargs_t *a)
{
UNUSED(a);
if (zone_master(zone) == NULL) {
rcu_read_lock();
bool is_master = zone_is_master(zone);
rcu_read_unlock();
if (is_master) {
return KNOT_EINVAL;
}
......@@ -194,7 +199,11 @@ static int remote_zone_retransfer(zone_t *zone, remote_cmdargs_t *a)
{
UNUSED(a);
if (zone_master(zone) == NULL) {
rcu_read_lock();
bool is_master = zone_is_master(zone);
rcu_read_unlock();
if (is_master) {
return KNOT_EINVAL;
}
......@@ -221,7 +230,12 @@ static int remote_zone_sign(zone_t *zone, remote_cmdargs_t *a)
{
UNUSED(a);
if (zone == NULL || !zone->conf->dnssec_enable) {
rcu_read_lock();
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_ENABLE, zone->name);
bool dnssec_enable = conf_bool(&val);
rcu_read_unlock();
if (zone == NULL || !dnssec_enable) {
return KNOT_EINVAL;
}
......@@ -342,15 +356,22 @@ static int remote_zonestatus(zone_t *zone, remote_cmdargs_t *a)
/* Prepare zone info. */
char buf[512] = { '\0' };
char dnssec_buf[128] = { '\0' };
char *zone_name = knot_dname_to_str_alloc(zone->name);
conf_val_t val = conf_zone_get(conf(), C_DNSSEC_ENABLE, zone->name);
bool dnssec_enable = conf_bool(&val);
bool is_master = zone_is_master(zone);
int n = snprintf(buf, sizeof(buf),
"%s\ttype=%s | serial=%u | %s %s | %s %s\n",
zone->conf->name,
zone_master(zone) ? "slave" : "master",
zone_name,
is_master ? "master" : "slave",
serial,
next_name,
when,
zone->conf->dnssec_enable ? "automatic DNSSEC, resigning at:" : "DNSSEC signing disabled",
zone->conf->dnssec_enable ? dnssec_info(zone, dnssec_buf, sizeof(dnssec_buf)) : "");
dnssec_enable ? "automatic DNSSEC, resigning at:" : "DNSSEC signing disabled",
dnssec_enable ? dnssec_info(zone, dnssec_buf, sizeof(dnssec_buf)) : "");
free(zone_name);
if (n < 0 || n >= sizeof(buf)) {
return KNOT_ESPACE;
}
......@@ -495,21 +516,21 @@ static int remote_senderr(int c, uint8_t *qbuf, size_t buflen)
/* Public APIs. */
int remote_bind(conf_iface_t *desc)
int remote_bind(struct sockaddr_storage *addr)
{
if (desc == NULL) {
if (addr == NULL) {
return KNOT_EINVAL;
}
char addr_str[SOCKADDR_STRLEN] = {0};
sockaddr_tostr(addr_str, sizeof(addr_str), &desc->addr);
char addr_str[SOCKADDR_STRLEN] = { 0 };
sockaddr_tostr(addr_str, sizeof(addr_str), addr);
log_info("remote control, binding to '%s'", addr_str);
/* Create new socket. */
mode_t old_umask = umask(KNOT_CTL_SOCKET_UMASK);
int sock = net_bound_socket(SOCK_STREAM, &desc->addr, 0);
int sock = net_bound_socket(SOCK_STREAM, addr, 0);
if (sock == KNOT_EADDRNOTAVAIL) {
sock = net_bound_socket(SOCK_STREAM, &desc->addr, NET_BIND_NONLOCAL);
sock = net_bound_socket(SOCK_STREAM, addr, NET_BIND_NONLOCAL);
if (sock >= 0) {
log_warning("remote control, address '%s' is not available",
addr_str);
......@@ -533,16 +554,16 @@ int remote_bind(conf_iface_t *desc)
return sock;
}
int remote_unbind(conf_iface_t *desc, int sock)
int remote_unbind(struct sockaddr_storage *addr, int sock)
{
if (desc == NULL || sock < 0) {
if (addr == NULL || sock < 0) {
return KNOT_EINVAL;
}
/* Remove control socket file. */
if (desc->addr.ss_family == AF_UNIX) {
char addr_str[SOCKADDR_STRLEN] = {0};
sockaddr_tostr(addr_str, sizeof(addr_str), &desc->addr);
if (addr->ss_family == AF_UNIX) {
char addr_str[SOCKADDR_STRLEN] = { 0 };
sockaddr_tostr(addr_str, sizeof(addr_str), addr);
unlink(addr_str);
}
......@@ -852,7 +873,7 @@ static int zones_verify_tsig_query(const knot_pkt_t *query,
return ret;
}
int remote_process(server_t *s, conf_iface_t *ctl_if, int sock,
int remote_process(server_t *s, struct sockaddr_storage *ctl_addr, int sock,
uint8_t* buf, size_t buflen)
{
knot_pkt_t *pkt = knot_pkt_new(buf, buflen, NULL);
......@@ -876,40 +897,38 @@ int remote_process(server_t *s, conf_iface_t *ctl_if, int sock,
/* Parse packet and answer if OK. */
int ret = remote_parse(pkt);
if (ret == KNOT_EOK && ctl_if->addr.ss_family != AF_UNIX) {
/* Check ACL list. */
char addr_str[SOCKADDR_STRLEN] = {0};
if (ret == KNOT_EOK && ctl_addr->ss_family != AF_UNIX) {
char addr_str[SOCKADDR_STRLEN] = { 0 };
sockaddr_tostr(addr_str, sizeof(addr_str), &ss);
knot_tsig_key_t *tsig_key = NULL;
const knot_dname_t *tsig_name = NULL;
/* Prepare tsig parameters. */
knot_tsig_key_t tsig = { NULL };
if (pkt->tsig_rr) {
tsig_name = pkt->tsig_rr->owner;
tsig.name = pkt->tsig_rr->owner;
tsig.algorithm = knot_tsig_rdata_alg(pkt->tsig_rr);
}
conf_iface_t *match = acl_find(&conf()->ctl.allow, &ss, tsig_name);
uint16_t ts_rc = 0;
uint16_t ts_trc = 0;
uint64_t ts_tmsigned = 0;
if (match == NULL) {
/* Check ACL. */
rcu_read_lock();
conf_val_t acl = conf_get(conf(), C_CTL, C_ACL);
bool allowed = acl_allowed(&acl, ACL_ACTION_CNTL, &ss, &tsig);
rcu_read_unlock();
if (!allowed) {
log_warning("remote control, denied '%s', "
"no matching ACL", addr_str);
remote_senderr(client, pkt->wire, pkt->size);