Commit 5185ca20 authored by Marek Vavruša's avatar Marek Vavruša

dynzone: module for dynamic zonedb (A records)

parent ccf0ed90
......@@ -115,6 +115,9 @@ src/knot/knot.h
src/knot/main.c
src/knot/modules/dnstap.c
src/knot/modules/dnstap.h
src/knot/modules/dynzone.c
src/knot/modules/dynzone.h
src/knot/modules/dynzone_tool.c
src/knot/modules/synth_record.c
src/knot/modules/synth_record.h
src/knot/nameserver/axfr.c
......
......@@ -348,6 +348,18 @@ khost_LDADD += dnstap/libdnstap.la
libknotd_la_LIBADD += dnstap/libdnstap.la
endif
if HAVE_LMDB
libknotd_la_SOURCES += \
knot/modules/dynzone.c \
knot/modules/dynzone.h
dynzone_tool_SOURCES = \
knot/modules/dynzone_tool.c
bin_PROGRAMS += dynzone_tool
dynzone_tool_LDADD = libknot.la libknotd.la
endif
# Create storage and run-time directories
install-data-hook:
$(INSTALL) -d $(DESTDIR)/@config_dir@
......
This diff is collapsed.
/*!
* \file synth_record.h
*
* \author Marek Vavrusa <marek.vavrusa@nic.cz>
*
* \brief Synthetic records module
*
* Accepted configurations:
* * "forward <prefix> <ttl> <address>/<netblock>"
* * "reverse <prefix> <zone> <ttl> <address>/<netblock>"
*
* Module synthetises forward/reverse records based on a template when
* the queried record can't be found in the zone contents.
*
* \addtogroup query_processing
* @{
*/
/* 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 "knot/nameserver/query_module.h"
/*! \brief Module interface. */
int dynzone_load(struct query_plan *plan, struct query_module *self);
int dynzone_unload(struct query_module *self);
/*! @} */
#include <string.h>
#include <stdlib.h>
#include <lmdb.h>
#include "knot/modules/dynzone.c"
static int dynzone_add(struct cache *cache, int argc, char *argv[]);
static int dynzone_del(struct cache *cache, int argc, char *argv[]);
static int dynzone_get(struct cache *cache, int argc, char *argv[]);
static int dynzone_list(struct cache *cache, int argc, char *argv[]);
struct tool_action {
const char *name;
int (*func)(struct cache *, int, char *[]);
int min_args;
const char *info;
};
#define TOOL_ACTION_COUNT 4
static struct tool_action TOOL_ACTION[TOOL_ACTION_COUNT] = {
{ "add", dynzone_add, 4, "<zone> <ip> <threat_code> <syslog_ip>" },
{ "del", dynzone_del, 1, "<zone>" },
{ "get", dynzone_get, 1, "<zone>" },
{ "list", dynzone_list, 0, "" },
};
static int help(void)
{
printf("Usage: dynzone_tool <dbdir> <action> [params]\n");
printf("Actions:\n");
for (unsigned i = 0; i < TOOL_ACTION_COUNT; ++i) {
struct tool_action *ta = &TOOL_ACTION[i];
printf("\t%s %s\n", ta->name, ta->info);
}
return 1;
}
int main(int argc, char *argv[])
{
if (argc < 3) {
return help();
}
/* Get mandatory parameters. */
int ret = EXIT_FAILURE;
char *dbdir = argv[1];
char *action = argv[2];
argv += 3;
argc -= 3;
/* Open cache for operations. */
struct cache *cache = cache_open(dbdir, 0, NULL);
/* Execute action. */
for (unsigned i = 0; i < TOOL_ACTION_COUNT; ++i) {
struct tool_action *ta = &TOOL_ACTION[i];
if (strcmp(ta->name, action) == 0) {
/* Check param count. */
if (argc < ta->min_args) {
return help();
}
ret = ta->func(cache, argc, argv);
if (ret != 0) {
fprintf(stderr, "FAILED\n");
}
break;
}
}
cache_close(cache);
return ret;
}
static int dynzone_add(struct cache *cache, int argc, char *argv[])
{
printf("ADD %s\t%s\t%s\t%s\n", argv[0], argv[1], argv[2], argv[3]);
knot_dname_t *key = knot_dname_from_str(argv[0]);
struct entry entry;
entry.ip = argv[1];
entry.threat_code = argv[2];
entry.syslog_ip = argv[3];
/* Check IPs. */
struct sockaddr_storage addr;
if (sockaddr_set(&addr, AF_INET, entry.ip, 0) != KNOT_EOK) {
fprintf(stderr, "invalid address: '%s'\n", entry.ip);
return KNOT_ERROR;
}
if (sockaddr_set(&addr, AF_INET, entry.syslog_ip, 0) != KNOT_EOK) {
fprintf(stderr, "invalid address: '%s'\n", entry.syslog_ip);
return KNOT_ERROR;
}
MDB_txn *txn = NULL;
int ret = mdb_txn_begin(cache->env, NULL, 0, &txn);
if (ret != 0) {
return ret;
}
ret = cache_insert(txn, cache->dbi, key, &entry);
mdb_txn_commit(txn);
return ret;
}
static int dynzone_del(struct cache *cache, int argc, char *argv[])
{
printf("DEL %s\n", argv[0]);
MDB_txn *txn = NULL;
int ret = mdb_txn_begin(cache->env, NULL, 0, &txn);
if (ret != 0) {
return ret;
}
knot_dname_t *key = knot_dname_from_str(argv[0]);
ret = cache_remove(txn, cache->dbi, key);
knot_dname_free(&key, NULL);
mdb_txn_commit(txn);
return ret;
}
static int dynzone_get(struct cache *cache, int argc, char *argv[])
{
MDB_txn *txn = NULL;
int ret = mdb_txn_begin(cache->env, NULL, MDB_RDONLY, &txn);
if (ret != 0) {
return ret;
}
struct entry entry;
knot_dname_t *key = knot_dname_from_str(argv[0]);
ret = cache_query_fetch(txn, cache->dbi, key, &entry);
knot_dname_free(&key, NULL);
if (ret == 0) {
printf("%s\t%s\t%s\t%s\n", argv[0], entry.ip, entry.threat_code, entry.syslog_ip);
cache_query_release(&entry);
}
mdb_txn_abort(txn);
return ret;
}
static int dynzone_list(struct cache *cache, int argc, char *argv[])
{
MDB_txn *txn = NULL;
int ret = mdb_txn_begin(cache->env, NULL, MDB_RDONLY, &txn);
if (ret != 0) {
return ret;
}
MDB_cursor *cursor = cursor_acquire(txn, cache->dbi);
MDB_val key, data;
ret = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
while (ret == 0) {
struct entry entry;
unpack_entry(&data, &entry);
char *zone = knot_dname_to_str(key.mv_data);
printf("%s\t%s\t%s\t%s\n", zone, entry.ip, entry.threat_code, entry.syslog_ip);
free(zone);
ret = mdb_cursor_get(cursor, &key, &data, MDB_NEXT);
}
cursor_release(cursor);
mdb_txn_abort(txn);
return KNOT_EOK;
}
......@@ -414,7 +414,7 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
/* Check parse state. */
knot_pkt_t *query = qdata->query;
int next_state = NS_PROC_DONE;
int next_state = NS_PROC_FAIL;
if (query->parsed < query->size) {
dbg_ns("%s: incompletely parsed query, FORMERR\n", __func__);
knot_pkt_clear(pkt);
......@@ -441,18 +441,20 @@ static int process_query_out(knot_pkt_t *pkt, knot_process_t *ctx)
}
/* Answer based on qclass. */
switch (knot_pkt_qclass(pkt)) {
case KNOT_CLASS_CH:
next_state = query_chaos(pkt, ctx);
break;
case KNOT_CLASS_ANY:
case KNOT_CLASS_IN:
next_state = query_internet(pkt, ctx);
break;
default:
qdata->rcode = KNOT_RCODE_REFUSED;
next_state = NS_PROC_FAIL;
break;
if (next_state != NS_PROC_DONE) {
switch (knot_pkt_qclass(pkt)) {
case KNOT_CLASS_CH:
next_state = query_chaos(pkt, ctx);
break;
case KNOT_CLASS_ANY:
case KNOT_CLASS_IN:
next_state = query_internet(pkt, ctx);
break;
default:
qdata->rcode = KNOT_RCODE_REFUSED;
next_state = NS_PROC_FAIL;
break;
}
}
/*
......
......@@ -4,6 +4,9 @@
#include "common-knot/strlcpy.h"
/* Compiled-in module headers. */
#ifdef HAVE_LMDB
#include "knot/modules/dynzone.h"
#endif
#include "knot/modules/synth_record.h"
#if USE_DNSTAP
#include "knot/modules/dnstap.h"
......@@ -18,6 +21,9 @@ struct compiled_module {
/*! \note All modules should be dynamically loaded later on. */
struct compiled_module MODULES[] = {
#ifdef HAVE_LMDB
{ "dynzone", &dynzone_load, &dynzone_unload },
#endif
{ "synth_record", &synth_record_load, &synth_record_unload },
#if USE_DNSTAP
{ "dnstap", &dnstap_load, &dnstap_unload }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment