diff --git a/Knot.files b/Knot.files index e5a0c40456815bd616505c48b0841f03d4ed0968..cf9458506f8e7731d63a2e70e7541ee3dba8e53a 100644 --- a/Knot.files +++ b/Knot.files @@ -168,6 +168,12 @@ src/libknot/nameserver/chaos.c src/libknot/nameserver/chaos.h src/libknot/nameserver/internet.c src/libknot/nameserver/internet.h +src/libknot/nameserver/axfr.c +src/libknot/nameserver/axfr.h +src/libknot/nameserver/ixfr.c +src/libknot/nameserver/ixfr.h +src/libknot/nameserver/update.c +src/libknot/nameserver/update.h src/libknot/nameserver/name-server.c src/libknot/nameserver/name-server.h src/libknot/nameserver/ns_proc_query.c diff --git a/src/Makefile.am b/src/Makefile.am index 48f1b177a6412ab60a6afdc3bc53554ed654a581..b78e3c0c1c38a90f48b0329e43c76b962252dd6a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -124,6 +124,12 @@ libknot_la_SOURCES = \ 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 \ diff --git a/src/libknot/nameserver/axfr.c b/src/libknot/nameserver/axfr.c new file mode 100644 index 0000000000000000000000000000000000000000..61dcdcfe96e54449bdf31c68b8802e074c5caaa2 --- /dev/null +++ b/src/libknot/nameserver/axfr.c @@ -0,0 +1,10 @@ +#include <config.h> + +#include "libknot/nameserver/axfr.h" +#include "libknot/nameserver/ns_proc_query.h" + +int axfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata) +{ + qdata->rcode = KNOT_RCODE_NOTIMPL; + return NS_PROC_FAIL; +} diff --git a/src/libknot/nameserver/axfr.h b/src/libknot/nameserver/axfr.h new file mode 100644 index 0000000000000000000000000000000000000000..e4b4729c5f4c164708a69f11e6d7a5683b62059e --- /dev/null +++ b/src/libknot/nameserver/axfr.h @@ -0,0 +1,40 @@ +/*! + * \file axfr.h + * + * \author Marek Vavrusa <marek.vavrusa@nic.cz> + * + * \brief AXFR processing. + * + * \addtogroup query_processing + * @{ + */ +/* Copyright (C) 2013 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/>. + */ + +#ifndef _KNOT_AXFR_H_ +#define _KNOT_AXFR_H_ + +#include "libknot/packet/pkt.h" +#include "libknot/zone/zonedb.h" +#include "libknot/nameserver/name-server.h" + +struct query_data; + +int axfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata); + +#endif /* _KNOT_AXFR_H_ */ + +/*! @} */ diff --git a/src/libknot/nameserver/internet.h b/src/libknot/nameserver/internet.h new file mode 100644 index 0000000000000000000000000000000000000000..d073bcd2fcd2f236b9a5c1caad2f25435f6b96a2 --- /dev/null +++ b/src/libknot/nameserver/internet.h @@ -0,0 +1,53 @@ +/*! + * \file internet.h + * + * \author Marek Vavrusa <marek.vavrusa@nic.cz> + * + * \brief IN zone lookup. + * + * \addtogroup query_processing + * @{ + */ +/* Copyright (C) 2013 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/>. + */ + +#ifndef _KNOT_INTERNET_H_ +#define _KNOT_INTERNET_H_ + +#include "libknot/packet/pkt.h" +#include "libknot/zone/zonedb.h" +#include "libknot/nameserver/name-server.h" + +/* Query data (from query processing). */ +struct query_data; + +/*! + * \brief Answer query from IN class zone. + */ +int internet_answer(knot_pkt_t *resp, struct query_data *qdata); + +/*! + * \brief Answer IN class zone NOTIFY message (RFC1996). + * \param response + * \param ns + * \param qdata + * \return + */ +int internet_notify(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata); + +#endif /* _KNOT_INTERNET_H_ */ + +/*! @} */ diff --git a/src/libknot/nameserver/ixfr.c b/src/libknot/nameserver/ixfr.c new file mode 100644 index 0000000000000000000000000000000000000000..560f867a600449a0b1ace314c15c6c0c2250351b --- /dev/null +++ b/src/libknot/nameserver/ixfr.c @@ -0,0 +1,42 @@ +#include <config.h> + +#include "libknot/nameserver/ixfr.h" +#include "libknot/nameserver/ns_proc_query.h" +#include "common/descriptor.h" + +int ixfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata) +{ + qdata->rcode = KNOT_RCODE_NOTIMPL; + return NS_PROC_FAIL; +} + +int ixfr_answer_soa(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata) +{ + if (pkt == NULL || ns == NULL || qdata == NULL) { + return NS_PROC_FAIL; + } + + /* Check zone state. */ + const knot_zone_t *zone = pkt->zone; + switch(knot_zone_state(zone)) { + case KNOT_EOK: + break; + case KNOT_ENOENT: + qdata->rcode = KNOT_RCODE_NOTAUTH; + return NS_PROC_FAIL; + default: + qdata->rcode = KNOT_RCODE_SERVFAIL; + return NS_PROC_FAIL; + } + + /* Guaranteed to have zone contents. */ + const knot_node_t *apex = zone->contents->apex; + const knot_rrset_t *soa_rr = knot_node_rrset(apex, KNOT_RRTYPE_SOA); + int ret = knot_pkt_put(pkt, 0, soa_rr, 0); + if (ret != KNOT_EOK) { + qdata->rcode = KNOT_RCODE_SERVFAIL; + return NS_PROC_FAIL; + } + + return NS_PROC_FINISH; +} diff --git a/src/libknot/nameserver/ixfr.h b/src/libknot/nameserver/ixfr.h new file mode 100644 index 0000000000000000000000000000000000000000..c65db7258874645ce4c32e24e56e4f4a3e3897bb --- /dev/null +++ b/src/libknot/nameserver/ixfr.h @@ -0,0 +1,42 @@ +/*! + * \file ixfr.h + * + * \author Marek Vavrusa <marek.vavrusa@nic.cz> + * + * \brief IXFR processing. + * + * \addtogroup query_processing + * @{ + */ +/* Copyright (C) 2013 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/>. + */ + +#ifndef _KNOT_IXFR_H_ +#define _KNOT_IXFR_H_ + +#include "libknot/packet/pkt.h" +#include "libknot/zone/zonedb.h" +#include "libknot/nameserver/name-server.h" + +struct query_data; + +int ixfr_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata); + +int ixfr_answer_soa(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata); + +#endif /* _KNOT_IXFR_H_ */ + +/*! @} */ diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c index 219f37a62cabc17e13f387e4595ee2796aab09a4..3006c5b84c784706db1cabe2435a98d420b62428 100644 --- a/src/libknot/nameserver/name-server.c +++ b/src/libknot/nameserver/name-server.c @@ -4110,6 +4110,8 @@ int ns_proc_begin(ns_proc_context_t *ctx, const ns_proc_module_t *module) /* #10 implement */ ctx->module = module; ctx->state = module->begin(ctx); + + dbg_ns("%s -> %d\n", __func__, ctx->state); return ctx->state; } @@ -4117,6 +4119,8 @@ int ns_proc_reset(ns_proc_context_t *ctx) { /* #10 implement */ ctx->state = ctx->module->reset(ctx); + + dbg_ns("%s -> %d\n", __func__, ctx->state); return ctx->state; } @@ -4124,13 +4128,25 @@ int ns_proc_finish(ns_proc_context_t *ctx) { /* #10 implement */ ctx->state = ctx->module->finish(ctx); + + /* Free packet buffers. */ + knot_pkt_free(&ctx->in); + knot_pkt_free(&ctx->out); + + dbg_ns("%s -> %d\n", __func__, ctx->state); return ctx->state; } int ns_proc_in(const uint8_t *wire, uint16_t wire_len, ns_proc_context_t *ctx) { /* #10 implement */ - knot_pkt_t *pkt = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm); + if (ctx->in == NULL) { + ctx->in = knot_pkt_new((uint8_t *)wire, wire_len, &ctx->mm); + } else { + knot_pkt_reset(ctx->in, (uint8_t *)wire, wire_len); + } + + knot_pkt_t *pkt = ctx->in; knot_pkt_parse(pkt, 0); switch(ctx->state) { @@ -4140,13 +4156,20 @@ int ns_proc_in(const uint8_t *wire, uint16_t wire_len, ns_proc_context_t *ctx) return NS_PROC_NOOP; } + dbg_ns("%s -> %d\n", __func__, ctx->state); return ctx->state; } int ns_proc_out(uint8_t *wire, uint16_t *wire_len, ns_proc_context_t *ctx) { /* #10 implement */ - knot_pkt_t *pkt = knot_pkt_new(wire, *wire_len, &ctx->mm); + if (ctx->out == NULL) { + ctx->out = knot_pkt_new(wire, *wire_len, &ctx->mm); + } else { + knot_pkt_reset(ctx->out, wire, *wire_len); + } + + knot_pkt_t *pkt = ctx->out; switch(ctx->state) { case NS_PROC_FULL: ctx->state = ctx->module->out(pkt, ctx); break; @@ -4158,9 +4181,7 @@ int ns_proc_out(uint8_t *wire, uint16_t *wire_len, ns_proc_context_t *ctx) *wire_len = pkt->size; - /* Free packet. */ - knot_pkt_free(&pkt); - + dbg_ns("%s -> %d\n", __func__, ctx->state); return ctx->state; } diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h index db498369330afe840743e035aa6a45f465a4b8f1..a64e007bf70447efbb520d539d35f754b7017b62 100644 --- a/src/libknot/nameserver/name-server.h +++ b/src/libknot/nameserver/name-server.h @@ -448,8 +448,10 @@ enum ns_proc_state { }; enum ns_proc_flag { - NS_NOFLAG = 0, + /* Common flags. */ NS_PKTSIZE_NOLIMIT = 1 << 0, /* Don't limit packet size (for TCP). */ + /* Module-specific flags. */ + NS_PROCFLAG = 1 << 8 }; struct ns_proc_module; @@ -460,6 +462,7 @@ typedef struct ns_proc_context uint16_t type; uint16_t flags; void *data; + knot_pkt_t *in, *out; int state; knot_nameserver_t *ns; diff --git a/src/libknot/nameserver/ns_proc_query.c b/src/libknot/nameserver/ns_proc_query.c index 493c8a5d1154827b2b4de5688762682871b678e9..4efe042a282adbaa865054148bfa461798746ba1 100644 --- a/src/libknot/nameserver/ns_proc_query.c +++ b/src/libknot/nameserver/ns_proc_query.c @@ -5,11 +5,16 @@ #include "libknot/nameserver/ns_proc_query.h" #include "libknot/consts.h" #include "libknot/util/debug.h" -#include "libknot/nameserver/chaos.h" -#include "libknot/nameserver/internet.h" #include "libknot/common.h" #include "common/descriptor.h" +/*! \todo Move close to server when done. */ +#include "libknot/nameserver/chaos.h" +#include "libknot/nameserver/internet.h" +#include "libknot/nameserver/axfr.h" +#include "libknot/nameserver/ixfr.h" +#include "libknot/nameserver/update.h" + /* Forward decls. */ static int tsig_check(knot_pkt_t *pkt); static const knot_zone_t *answer_zone_find(knot_pkt_t *pkt, knot_zonedb_t *zonedb); @@ -52,7 +57,7 @@ int ns_proc_query_reset(ns_proc_context_t *ctx) /* Clear */ assert(ctx); struct query_data *data = QUERY_DATA(ctx); - knot_pkt_free(&data->pkt); + data->pkt = NULL; data->rcode = KNOT_RCODE_NOERROR; data->rcode_tsig = 0; data->node = data->encloser = data->previous = NULL; @@ -81,9 +86,12 @@ int ns_proc_query_in(knot_pkt_t *pkt, ns_proc_context_t *ctx) switch(query_type) { case KNOT_QUERY_NORMAL: case KNOT_QUERY_NOTIFY: + case KNOT_QUERY_AXFR: + case KNOT_QUERY_IXFR: + case KNOT_QUERY_UPDATE: break; /* Supported. */ default: - dbg_ns("%s: query_type(%hu) NOT SUPPORTED", __func__, query_type); + dbg_ns("%s: query_type(%hu) NOT SUPPORTED\n", __func__, query_type); return NS_PROC_NOOP; /* Refuse to process. */ } @@ -187,6 +195,26 @@ int query_internet(knot_pkt_t *pkt, ns_proc_context_t *ctx) case KNOT_QUERY_NOTIFY: next_state = internet_notify(pkt, ctx->ns, data); break; + case KNOT_QUERY_AXFR: + if (ctx->flags & NS_QUERY_NO_AXFR) { + /* AXFR disabled, respond with NOTIMPL. */ + data->rcode = KNOT_RCODE_NOTIMPL; + next_state = NS_PROC_FAIL; + } else { + next_state = axfr_answer(pkt, ctx->ns, data); + } + break; + case KNOT_QUERY_IXFR: + if (ctx->flags & NS_QUERY_NO_IXFR) { + /* IXFR disabled, respond with SOA. */ + next_state = ixfr_answer_soa(pkt, ctx->ns, data); + } else { + next_state = ixfr_answer(pkt, ctx->ns, data); + } + break; + case KNOT_QUERY_UPDATE: + next_state = update_answer(pkt, ctx->ns, data); + break; default: assert(0); /* Should be caught earlier. */ data->rcode = KNOT_RCODE_SERVFAIL; @@ -271,7 +299,7 @@ static int prepare_answer(knot_pkt_t *query, knot_pkt_t *resp, ns_proc_context_t /* Copy DO bit if set (DNSSEC requested). */ if (knot_pkt_have_dnssec(query)) { dbg_ns("%s: setting DO=1 in OPT RR\n", __func__); - knot_edns_set_do(&(resp)->opt_rr); + knot_edns_set_do(&resp->opt_rr); } /* Set minimal supported size from EDNS(0). */ if (!(ctx->flags & NS_PKTSIZE_NOLIMIT)) { diff --git a/src/libknot/nameserver/ns_proc_query.h b/src/libknot/nameserver/ns_proc_query.h index b03185815876e3afd414d46d15fb1bf01c39d3a8..a1c3de4beabda0834bbba2d1c7ead98b57082c7e 100644 --- a/src/libknot/nameserver/ns_proc_query.h +++ b/src/libknot/nameserver/ns_proc_query.h @@ -29,10 +29,17 @@ #include "libknot/nameserver/name-server.h" +/* Query processing module implementation. */ extern const ns_proc_module_t _ns_proc_query; #define NS_PROC_QUERY (&_ns_proc_query) #define NS_PROC_QUERY_ID 1 +/* Query processing flags. */ +enum ns_proc_query_flag { + NS_QUERY_NO_AXFR = NS_PROCFLAG << 1, /* Don't process AXFR */ + NS_QUERY_NO_IXFR = NS_PROCFLAG << 2 /* Don't process IXFR */ +}; + struct query_data { uint16_t rcode; uint16_t rcode_tsig; diff --git a/src/libknot/nameserver/update.c b/src/libknot/nameserver/update.c new file mode 100644 index 0000000000000000000000000000000000000000..bc8be46d20b23525c6aa58d7966259538ef6f323 --- /dev/null +++ b/src/libknot/nameserver/update.c @@ -0,0 +1,10 @@ +#include <config.h> + +#include "libknot/nameserver/update.h" +#include "libknot/nameserver/ns_proc_query.h" + +int update_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata) +{ + qdata->rcode = KNOT_RCODE_NOTIMPL; + return NS_PROC_FAIL; +} diff --git a/src/libknot/nameserver/update.h b/src/libknot/nameserver/update.h new file mode 100644 index 0000000000000000000000000000000000000000..01788261f901e8198fd93236cd273cb80d43b5b5 --- /dev/null +++ b/src/libknot/nameserver/update.h @@ -0,0 +1,40 @@ +/*! + * \file update.h + * + * \author Marek Vavrusa <marek.vavrusa@nic.cz> + * + * \brief DDNS UPDATE processing. + * + * \addtogroup query_processing + * @{ + */ +/* Copyright (C) 2013 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/>. + */ + +#ifndef _KNOT_UPDATE_H_ +#define _KNOT_UPDATE_H_ + +#include "libknot/packet/pkt.h" +#include "libknot/zone/zonedb.h" +#include "libknot/nameserver/name-server.h" + +struct query_data; + +int update_answer(knot_pkt_t *pkt, knot_nameserver_t *ns, struct query_data *qdata); + +#endif /* _KNOT_UPDATE_H_ */ + +/*! @} */