Commit 93b6a42a authored by Jan Kadlec's avatar Jan Kadlec

Merge remote-tracking branch 'origin/zone-events-queue' into events-ixfrin

Conflicts:
	src/knot/nameserver/process_answer.c
parents de3adda6 6332c2b8
......@@ -127,6 +127,8 @@ src/knot/nameserver/query_module.c
src/knot/nameserver/query_module.h
src/knot/nameserver/requestor.c
src/knot/nameserver/requestor.h
src/knot/nameserver/requestor_tsig.c
src/knot/nameserver/requestor_tsig.h
src/knot/nameserver/update.c
src/knot/nameserver/update.h
src/knot/other/debug.h
......
......@@ -240,6 +240,8 @@ libknotd_la_SOURCES = \
knot/nameserver/process_answer.h \
knot/nameserver/requestor.c \
knot/nameserver/requestor.h \
knot/nameserver/requestor_tsig.c \
knot/nameserver/requestor_tsig.h \
knot/nameserver/query_module.c \
knot/nameserver/query_module.h \
knot/nameserver/update.c \
......
......@@ -25,16 +25,6 @@ static int noop(knot_pkt_t *pkt, knot_process_t *ctx)
return NS_PROC_NOOP;
}
/*! \brief Module implementation. */
const knot_process_module_t _process_answer = {
&process_answer_begin,
&process_answer_reset,
&process_answer_finish,
&process_answer,
&noop, /* No output */
&noop /* No error processing. */
};
/*! \brief Accessor to query-specific data. */
#define ANSWER_DATA(ctx) ((struct answer_data *)(ctx)->data)
......@@ -56,7 +46,7 @@ static bool is_answer_to_query(const knot_pkt_t *query, knot_pkt_t *answer)
knot_dname_is_equal(knot_pkt_qname(query), knot_pkt_qname(answer));
}
int process_answer_begin(knot_process_t *ctx, void *module_param)
static int process_answer_begin(knot_process_t *ctx, void *module_param)
{
/* Initialize context. */
assert(ctx);
......@@ -70,7 +60,7 @@ int process_answer_begin(knot_process_t *ctx, void *module_param)
return NS_PROC_MORE;
}
int process_answer_reset(knot_process_t *ctx)
static int process_answer_reset(knot_process_t *ctx)
{
assert(ctx);
......@@ -81,7 +71,7 @@ int process_answer_reset(knot_process_t *ctx)
return NS_PROC_MORE;
}
int process_answer_finish(knot_process_t *ctx)
static int process_answer_finish(knot_process_t *ctx)
{
process_answer_reset(ctx);
mm_free(&ctx->mm, ctx->data);
......@@ -97,7 +87,7 @@ int process_answer_finish(knot_process_t *ctx)
return ret; \
}
int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
static int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
{
assert(pkt && ctx);
struct answer_data *data = ANSWER_DATA(ctx);
......@@ -113,8 +103,6 @@ int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
/* Class specific answer processing. */
ANSWER_REQUIRES(knot_pkt_qclass(pkt) == KNOT_CLASS_IN, NS_PROC_NOOP);
#warning TODO: check TSIG here?
/* Call appropriate processing handler. */
int next_state = NS_PROC_NOOP;
switch(knot_pkt_type(pkt)) {
......@@ -140,3 +128,18 @@ int process_answer(knot_pkt_t *pkt, knot_process_t *ctx)
}
#undef ANSWER_REQUIRES
/*! \brief Module implementation. */
static const knot_process_module_t PROCESS_ANSWER_MODULE = {
&process_answer_begin,
&process_answer_reset,
&process_answer_finish,
&process_answer,
&noop, /* No output. */
&noop /* No error processing. */
};
const knot_process_module_t *process_answer_get_module(void)
{
return &PROCESS_ANSWER_MODULE;
}
\ No newline at end of file
......@@ -19,8 +19,8 @@
#include "knot/nameserver/process_query.h"
/* Query processing module implementation. */
extern const knot_process_module_t _process_answer;
#define NS_PROC_ANSWER (&_process_answer)
const knot_process_module_t *process_answer_get_module(void);
#define NS_PROC_ANSWER process_answer_get_module()
#define NS_PROC_ANSWER_ID 2
/*! \brief Answer processsing logging base. */
......@@ -30,7 +30,6 @@ extern const knot_process_module_t _process_answer;
what " of '%s' from '%s': ", msg); \
} while(0)
/* Module load parameters. */
struct process_answer_param {
zone_t *zone;
......@@ -49,40 +48,3 @@ struct answer_data
struct process_answer_param *param; /*!< Module parameters. */
mm_ctx_t *mm; /*!< Memory context. */
};
/*!
* \brief Initialize answer processing context.
*
* \param ctx
* \param module_param
* \return MORE (awaits answer)
*/
int process_answer_begin(knot_process_t *ctx, void *module_param);
/*!
* \brief Reset answer processing context.
*
* \param ctx
* \return MORE (awaits next answer)
*/
int process_answer_reset(knot_process_t *ctx);
/*!
* \brief Finish and close current answer processing.
*
* \param ctx
* \return NOOP (context will be inoperable further on)
*/
int process_answer_finish(knot_process_t *ctx);
/*!
* \brief Process single answer packet.
*
* \param pkt
* \param ctx
* \retval NOOP (unsupported answer)
* \return MORE (awaits next answer)
* \retval DONE (processing finished)
* \retval FAIL (processing failed)
*/
int process_answer(knot_pkt_t *pkt, knot_process_t *ctx);
......@@ -221,7 +221,7 @@ int process_query_err(knot_pkt_t *pkt, knot_process_t *ctx)
bool process_query_acl_check(acl_t *acl, struct query_data *qdata)
{
knot_pkt_t *query = qdata->query;
struct sockaddr_storage *query_source = qdata->param->remote;
const struct sockaddr_storage *query_source = qdata->param->remote;
const knot_dname_t *key_name = NULL;
knot_tsig_algorithm_t key_alg = KNOT_TSIG_ALG_NULL;
......
......@@ -65,7 +65,7 @@ struct process_query_param {
uint16_t proc_flags;
server_t *server;
int socket;
struct sockaddr_storage *remote;
const struct sockaddr_storage *remote;
};
/*! \brief Query processing intermediate data. */
......
......@@ -14,6 +14,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include "knot/nameserver/requestor.h"
#include "knot/nameserver/process_answer.h"
#include "knot/server/net.h"
......@@ -53,6 +55,7 @@ static void request_close(mm_ctx_t *mm, struct request *request)
knot_process_finish(&request->process);
rem_node(&request->data.node);
requestor_tsig_cleanup(&request->data.tsig_ctx);
close(request->data.fd);
knot_pkt_free(&request->data.query);
mm_free(mm, request->pkt_buf);
......@@ -139,11 +142,10 @@ bool requestor_finished(struct requestor *requestor)
}
struct request *requestor_make(struct requestor *requestor,
const struct sockaddr_storage *from,
const struct sockaddr_storage *to,
const conf_iface_t *remote,
knot_pkt_t *query)
{
if (requestor == NULL || query == NULL || to == NULL) {
if (requestor == NULL || query == NULL || remote == NULL) {
return NULL;
}
......@@ -154,10 +156,10 @@ struct request *requestor_make(struct requestor *requestor,
}
request->state = NS_PROC_DONE;
memcpy(&request->data.origin, from, sizeof(struct sockaddr_storage));
memcpy(&request->data.remote, to, sizeof(struct sockaddr_storage));
request->data.remote = remote;
request->data.fd = -1;
request->data.query = query;
requestor_tsig_init(&request->data.tsig_ctx, remote->key);
return request;
}
......@@ -168,8 +170,8 @@ int requestor_enqueue(struct requestor *requestor, struct request * request, voi
}
/* Fetch a bound socket. */
int fd = net_connected_socket(SOCK_STREAM, &request->data.remote,
&request->data.origin, O_NONBLOCK);
int fd = net_connected_socket(SOCK_STREAM, &request->data.remote->addr,
&request->data.remote->via, O_NONBLOCK);
if (fd < 0) {
return KNOT_ECONN;
}
......@@ -197,12 +199,39 @@ int requestor_dequeue(struct requestor *requestor)
return KNOT_EOK;
}
/*!
* \brief Sign outbound packet using TSIG.
*/
static int request_sign(struct request *request)
{
assert(request);
return requestor_tsig_sign_packet(&request->data.tsig_ctx,
request->data.query);
}
/*!
* \brief Check inbound packet TSIG signature.
*/
static int request_verify(struct request *request)
{
assert(request);
return requestor_tsig_verify_packet(&request->data.tsig_ctx,
request->data.query);
}
static int exec_request(struct request *last, struct timeval *timeout)
{
int ret = KNOT_EOK;
/* Process any pending data. */
if (last->state == NS_PROC_FULL) {
ret = request_sign(last);
if (ret != KNOT_EOK) {
return ret;
}
ret = request_send(last, timeout);
if (ret != KNOT_EOK) {
return ret;
......@@ -211,12 +240,17 @@ static int exec_request(struct request *last, struct timeval *timeout)
}
/* Receive and process expected answers. */
while(last->state == NS_PROC_MORE) {
while (last->state == NS_PROC_MORE) {
int rcvd = request_recv(last, timeout);
if (rcvd <= 0) {
return rcvd;
}
ret = request_verify(last);
if (ret != KNOT_EOK) {
return ret;
}
last->state = knot_process_in(last->pkt_buf, rcvd, &last->process);
if (last->state == NS_PROC_FAIL) {
return KNOT_EMALF;
......
......@@ -18,6 +18,7 @@
#include "knot/nameserver/process_query.h"
#include "knot/nameserver/process_answer.h"
#include "knot/nameserver/requestor_tsig.h"
#include "common/lists.h"
struct request;
......@@ -40,8 +41,9 @@ struct requestor {
struct request_data {
node_t node;
int fd;
struct sockaddr_storage remote, origin;
const conf_iface_t *remote;
knot_pkt_t *query;
requestor_tsig_ctx_t tsig_ctx;
};
/*!
......@@ -60,8 +62,7 @@ bool requestor_finished(struct requestor *requestor);
/*! \brief Make request out of endpoints and query. */
struct request *requestor_make(struct requestor *requestor,
const struct sockaddr_storage *from,
const struct sockaddr_storage *to,
const conf_iface_t *remote,
knot_pkt_t *query);
/*!
......
/* 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 <string.h>
#include <stdint.h>
#include <stdlib.h>
#include "common/errcode.h"
#include "libknot/rdata/tsig.h"
#include "libknot/tsig-op.h"
#include "knot/nameserver/requestor_tsig.h"
void requestor_tsig_init(requestor_tsig_ctx_t *ctx, const knot_tsig_key_t *key)
{
if (!ctx) {
return;
}
memset(ctx, 0, sizeof(*ctx));
ctx->key = key;
}
void requestor_tsig_cleanup(requestor_tsig_ctx_t *ctx)
{
if (!ctx) {
return;
}
free(ctx->digest);
memset(ctx, 0, sizeof(*ctx));
}
int requestor_tsig_sign_packet(requestor_tsig_ctx_t *ctx, knot_pkt_t *packet)
{
if (!ctx || !packet) {
return KNOT_EINVAL;
}
if (ctx->key == NULL) {
return KNOT_EOK;
}
int ret = KNOT_ERROR;
if (ctx->digest_size == 0) {
ctx->digest_size = knot_tsig_digest_length(ctx->key->algorithm);
ctx->digest = malloc(ctx->digest_size);
if (!ctx->digest) {
return KNOT_ENOMEM;
}
ret = knot_tsig_sign(packet->wire, &packet->size, packet->max_size,
NULL, 0,
ctx->digest, &ctx->digest_size,
ctx->key, 0, 0);
} else {
uint8_t previous_digest[ctx->digest_size];
memcpy(previous_digest, ctx->digest, ctx->digest_size);
ret = knot_tsig_sign_next(packet->wire, &packet->size, packet->max_size,
previous_digest, ctx->digest_size,
ctx->digest, &ctx->digest_size,
ctx->key, packet->wire, packet->size);
}
return ret;
}
int requestor_tsig_verify_packet(requestor_tsig_ctx_t *ctx, knot_pkt_t *packet)
{
if (!ctx || !packet) {
return KNOT_EINVAL;
}
if (ctx->key == NULL) {
return KNOT_EOK;
}
#warning "TODO: TSIG verify invocation."
//return KNOT_ENOTSUP;
return KNOT_EOK;
}
/* 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 <stdint.h>
#include <stdlib.h>
#include "libknot/packet/pkt.h"
#include "libknot/rdata/tsig.h"
typedef struct requestor_tsig_ctx {
const knot_tsig_key_t *key;
uint8_t *digest;
size_t digest_size;
} requestor_tsig_ctx_t;
void requestor_tsig_init(requestor_tsig_ctx_t *ctx, const knot_tsig_key_t *key);
void requestor_tsig_cleanup(requestor_tsig_ctx_t *ctx);
int requestor_tsig_sign_packet(requestor_tsig_ctx_t *ctx, knot_pkt_t *packet);
int requestor_tsig_verify_packet(requestor_tsig_ctx_t *ctx, knot_pkt_t *packet);
......@@ -86,7 +86,6 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
case KNOT_QUERY_AXFR: query_type = KNOT_RRTYPE_AXFR; break;
case KNOT_QUERY_IXFR: query_type = KNOT_RRTYPE_IXFR; break;
case KNOT_QUERY_NOTIFY: opcode = KNOT_OPCODE_NOTIFY; break;
case KNOT_QUERY_UPDATE: opcode = KNOT_OPCODE_UPDATE; break;
}
/* Create a memory pool for this task. */
......@@ -94,7 +93,7 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
mm_ctx_t mm;
mm_ctx_mempool(&mm, 4096);
/* Create a zone transfer request. */
/* Create a query message. */
knot_pkt_t *query = zone_query(zone, query_type, &mm);
if (query == NULL) {
return KNOT_ENOMEM;
......@@ -114,7 +113,11 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
requestor_init(&re, NS_PROC_ANSWER, &mm);
/* Create a request. */
struct request *req = requestor_make(&re, &remote->via, &remote->addr, query);
struct request *req = requestor_make(&re, remote, query);
if (req == NULL) {
return KNOT_ENOMEM;
}
struct process_answer_param param;
param.zone = zone;
param.query = query;
......@@ -327,7 +330,7 @@ static int event_update(zone_t *zone)
/* Create minimal query data context. */
struct process_query_param param = {0};
param.remote = &update->remote;
param.remote = &update->remote->addr;
struct query_data qdata = {0};
qdata.param = &param;
qdata.query = update->query;
......
......@@ -93,7 +93,7 @@ int knot_process_out(uint8_t *wire, uint16_t *wire_len, knot_process_t *ctx)
{
knot_pkt_t *pkt = knot_pkt_new(wire, *wire_len, &ctx->mm);
switch(ctx->state) {
switch (ctx->state) {
case NS_PROC_FULL: ctx->state = ctx->module->out(pkt, ctx); break;
case NS_PROC_FAIL: ctx->state = ctx->module->err(pkt, ctx); break;
default:
......
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