Commit e8599597 authored by Marek Vavruša's avatar Marek Vavruša

Merge branch 'master' into resolver_compat

Conflicts:
	Knot.files
	src/Makefile.am
parents a6dec641 8d1a0d17
......@@ -231,6 +231,8 @@ src/libknot/packet/net.c
src/libknot/packet/net.h
src/libknot/packet/pkt.c
src/libknot/packet/pkt.h
src/libknot/packet/rrset-wire.c
src/libknot/packet/rrset-wire.h
src/libknot/packet/wire.h
src/libknot/processing/layer.c
src/libknot/processing/layer.h
......@@ -338,6 +340,7 @@ tests/rdataset.c
tests/requestor.c
tests/rrl.c
tests/rrset.c
tests/rrset_wire.c
tests/sample_conf.h
tests/server.c
tests/slab.c
......@@ -347,4 +350,5 @@ tests/worker_queue.c
tests/zone_events.c
tests/zone_update.c
tests/zonedb.c
tests/zone-update.c
tests/ztree.c
......@@ -68,7 +68,7 @@ Features:
- Synthetic IPv4/IPv6 reverse/forward records (optional module)
- dnstap support in both utilities & server (optional module)
- NOTIFY message support and new TSIG section in kdig
- Multi-master support
- Zone transfer master failover
Improvements:
-------------
......
......@@ -79,6 +79,12 @@ AXFR::
}
}
Note that the ``xfr-in`` option accepts a list of multiple remotes.
The first remote in the list is used as a primary master, and the rest is used
for failover should the connection with the primary master fail.
The list is rotated in this case, and a new primary is elected.
The preference list is reset on the configuration reload.
You can also use TSIG for access control. For this, you need to configure a TSIG key
and assign it to a remote. Supported algorithms for TSIG key are:
| ``hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384, hmac-sha512``
......
......@@ -173,6 +173,8 @@ libknot_la_SOURCES = \
libknot/packet/pkt.h \
libknot/packet/net.c \
libknot/packet/net.h \
libknot/packet/rrset-wire.c \
libknot/packet/rrset-wire.h \
libknot/packet/wire.h \
libknot/processing/layer.c \
libknot/processing/layer.h \
......
/* 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 "knot/nameserver/ixfr.h"
#include "knot/nameserver/axfr.h"
#include "knot/nameserver/internet.h"
......@@ -308,6 +324,21 @@ static int ixfr_answer_soa(knot_pkt_t *pkt, struct query_data *qdata)
#define IXFRIN_LOG(severity, msg...) \
ANSWER_LOG(severity, adata, "IXFR, incoming", msg)
/*! \brief Checks whether IXFR response contains enough data for processing. */
static bool ixfr_enough_data(const knot_pkt_t *pkt)
{
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
return answer->count >= 2;
}
/*! \brief Checks whether server responded with AXFR-style IXFR. */
static bool ixfr_is_axfr(const knot_pkt_t *pkt)
{
const knot_pktsection_t *answer = knot_pkt_section(pkt, KNOT_ANSWER);
return answer->rr[0].type == KNOT_RRTYPE_SOA &&
answer->rr[1].type != KNOT_RRTYPE_SOA;
}
/*! \brief Cleans up data allocated by IXFR-in processing. */
static void ixfrin_cleanup(struct answer_data *data)
{
......@@ -351,7 +382,7 @@ static int ixfrin_finalize(struct answer_data *adata)
zone_contents_t *new_contents;
int ret = apply_changesets(ixfr->zone, &ixfr->changesets, &new_contents);
if (ret != KNOT_EOK) {
IXFRIN_LOG(LOG_ERR, "failed to apply changes to zone (%s)",
IXFRIN_LOG(LOG_WARNING, "failed to apply changes to zone (%s)",
knot_strerror(ret));
return ret;
}
......@@ -359,7 +390,7 @@ static int ixfrin_finalize(struct answer_data *adata)
/* Write changes to journal. */
ret = zone_changes_store(ixfr->zone, &ixfr->changesets);
if (ret != KNOT_EOK) {
IXFRIN_LOG(LOG_ERR, "failed to write changes to journal (%s)",
IXFRIN_LOG(LOG_WARNING, "failed to write changes to journal (%s)",
knot_strerror(ret));
updates_rollback(&ixfr->changesets);
update_free_zone(&new_contents);
......@@ -563,7 +594,7 @@ static int process_ixfrin_packet(knot_pkt_t *pkt, struct answer_data *adata)
int ret = ixfrin_step(rr, ixfr);
if (ret != KNOT_EOK) {
IXFRIN_LOG(LOG_ERR, "failed (%s)", knot_strerror(ret));
IXFRIN_LOG(LOG_WARNING, "failed (%s)", knot_strerror(ret));
return NS_PROC_FAIL;
}
......@@ -628,7 +659,7 @@ int ixfr_query(knot_pkt_t *pkt, struct query_data *qdata)
case KNOT_EOK: /* Last response. */
gettimeofday(&now, NULL);
IXFROUT_LOG(LOG_INFO,
"finished, %.02f seconds, %u messages, %u bytes",
"finished, %.02f seconds, %u messages, %u bytes",
time_diff(&ixfr->proc.tstamp, &now) / 1000.0,
ixfr->proc.npkts, ixfr->proc.nbytes);
ret = NS_PROC_DONE;
......@@ -647,17 +678,27 @@ int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
if (pkt == NULL || adata == NULL) {
return NS_PROC_FAIL;
}
if (!ixfr_enough_data(pkt)) {
return NS_PROC_FAIL;
}
/* Check for AXFR-style IXFR. */
if (ixfr_is_axfr(pkt)) {
IXFRIN_LOG(LOG_NOTICE, "fallback to AXFR");
return axfr_answer_process(pkt, adata);
}
/* Check RCODE. */
uint8_t rcode = knot_wire_get_rcode(pkt->wire);
if (rcode != KNOT_RCODE_NOERROR) {
knot_lookup_table_t *lut = knot_lookup_by_id(knot_rcode_names, rcode);
if (lut != NULL) {
IXFRIN_LOG(LOG_ERR, "server responded with %s", lut->name);
IXFRIN_LOG(LOG_WARNING, "server responded with %s", lut->name);
}
return NS_PROC_FAIL;
}
/* Initialize processing with first packet. */
if (adata->ext == NULL) {
NS_NEED_TSIG_SIGNED(&adata->param->tsig_ctx, 0);
......@@ -670,7 +711,7 @@ int ixfr_process_answer(knot_pkt_t *pkt, struct answer_data *adata)
// First packet with IXFR, init context
int ret = ixfrin_answer_init(adata);
if (ret != KNOT_EOK) {
IXFRIN_LOG(LOG_ERR, "failed (%s)", knot_strerror(ret));
IXFRIN_LOG(LOG_WARNING, "failed (%s)", knot_strerror(ret));
return NS_PROC_FAIL;
}
} else {
......
......@@ -264,7 +264,7 @@ zone_contents_t *zonefile_load(zloader_t *loader)
}
if (loader->scanner->error_counter > 0) {
ERROR(zname, "failed to load zone, file '%s', %"PRIu64"errors",
ERROR(zname, "failed to load zone, file '%s', %"PRIu64" errors",
loader->source, loader->scanner->error_counter);
goto fail;
}
......
......@@ -37,11 +37,6 @@
#define KNOT_DNAME_MAXLEN 255 /*!< 1-byte maximum. */
#define KNOT_DNAME_MAXLABELS 127 /*!< 1-char labels. */
/*!
* \brief Often used sizes.
*/
#define KNOT_RR_HEADER_SIZE 10
/*!
* \brief Address family numbers.
*
......
......@@ -29,6 +29,7 @@
#include <stdio.h> // size_t
#define KNOT_MAX_RDATA_BLOCKS 8
#define KNOT_MAX_RDATA_DNAMES 2 // update this when defining new RR types
/*!
* \brief Resource record class codes.
......
......@@ -166,32 +166,16 @@ knot_dname_t *knot_dname_copy_part(const knot_dname_t *name, unsigned len,
int knot_dname_to_wire(uint8_t *dst, const knot_dname_t *src, size_t maxlen)
{
if (dst == NULL || src == NULL)
if (dst == NULL || src == NULL) {
return KNOT_EINVAL;
/* Write out non or partially compressed name. */
int len = 0;
while (*src != '\0' && !knot_wire_is_pointer(src)) {
uint8_t lblen = *src + 1;
if (len + lblen > maxlen)
return KNOT_ESPACE;
memcpy(dst + len, src, lblen);
len += lblen;
src += lblen;
}
/* Terminated either FQDN \x00, or as a pointer. */
if (*src == '\0') {
if (len + 1> maxlen)
return KNOT_ESPACE;
*(dst + len) = '\0';
len += 1; /* \x00 */
} else {
if (len + 2 > maxlen)
return KNOT_ESPACE;
memcpy(dst + len, src, sizeof(uint16_t));
len += 2; /* ptr */
int len = knot_dname_size(src);
if (len > maxlen) {
return KNOT_ESPACE;
}
memcpy(dst, src, len);
return len;
}
......@@ -263,7 +247,12 @@ char *knot_dname_to_str(const knot_dname_t *name)
if (isalnum(c) != 0 || c == '-' || c == '_' || c == '*' ||
c == '/') {
res[str_len++] = c;
} else if (ispunct(c) != 0) {
} else if (ispunct(c) != 0 && c != '#') {
/* Exclusion of '#' character is to avoid possible
* collision with rdata hex notation '\#'. So it is
* encoded in \ddd notation.
*/
// Increase output size for \x format.
alloc_size += 1;
char *extended = realloc(res, alloc_size);
......
......@@ -28,6 +28,7 @@
#include "libknot/packet/wire.h"
#include "libknot/rrset.h"
#include "libknot/rrtype/rrsig.h"
#include "libknot/packet/rrset-wire.h"
#define RRSIG_RDATA_SIGNER_OFFSET 18
......
......@@ -22,6 +22,7 @@
#include "libknot/dnssec/sig0.h"
#include "libknot/dnssec/sign.h"
#include "libknot/packet/wire.h"
#include "libknot/packet/rrset-wire.h"
/*!
* \brief Lifetime fudge of the SIG(0) packets in seconds.
......
......@@ -27,6 +27,7 @@
#include "libknot/packet/wire.h"
#include "libknot/rrtype/tsig.h"
#include "libknot/tsig-op.h"
#include "libknot/packet/rrset-wire.h"
/*! \brief Scan packet for RRSet existence. */
static bool pkt_contains(const knot_pkt_t *packet,
......@@ -618,54 +619,6 @@ int knot_pkt_parse_question(knot_pkt_t *pkt)
return KNOT_EOK;
}
/*! \note Legacy code, mainly for transfers and updates.
* RRSets should use packet memory context for allocation and
* should be copied if they are supposed to be stored in zone permanently.
*/
static int knot_pkt_rr_from_wire(const uint8_t *wire, size_t *pos,
size_t size, mm_ctx_t *mm, knot_rrset_t *rrset)
{
dbg_packet("%s(%p, %zu, %zu)\n", __func__, wire, *pos, size);
assert(wire);
assert(pos);
knot_dname_t *owner = knot_dname_parse(wire, pos, size, mm);
if (owner == NULL) {
return KNOT_EMALF;
}
knot_dname_to_lower(owner);
if (size - *pos < KNOT_RR_HEADER_SIZE) {
dbg_packet("%s: not enough data to parse RR HEADER\n", __func__);
knot_dname_free(&owner, mm);
return KNOT_EMALF;
}
uint16_t type = knot_wire_read_u16(wire + *pos);
uint16_t rclass = knot_wire_read_u16(wire + *pos + sizeof(uint16_t));
uint32_t ttl = knot_wire_read_u32(wire + *pos + 2 * sizeof(uint16_t));
uint16_t rdlength = knot_wire_read_u16(wire + *pos + 4 * sizeof(uint16_t));
*pos += KNOT_RR_HEADER_SIZE;
if (size - *pos < rdlength) {
dbg_packet("%s: not enough data to parse RDATA\n", __func__);
knot_dname_free(&owner, mm);
return KNOT_EMALF;
}
knot_rrset_init(rrset, owner, type, rclass);
int ret = knot_rrset_rdata_from_wire_one(rrset, wire, pos, size, ttl,
rdlength, mm);
if (ret != KNOT_EOK) {
dbg_packet("%s: failed to parse RDATA (%d)\n", __func__, ret);
knot_rrset_clear(rrset, mm);
return ret;
}
return KNOT_EOK;
}
/* \note Private for check_rr_constraints(). */
#define CHECK_AR_CONSTRAINTS(pkt, rr, var, check_func) \
if ((pkt)->current != KNOT_ADDITIONAL) { \
......@@ -730,8 +683,8 @@ int knot_pkt_parse_rr(knot_pkt_t *pkt, unsigned flags)
/* Parse wire format. */
size_t rr_size = pkt->parsed;
knot_rrset_t *rr = &pkt->rr[pkt->rrset_count];
ret = knot_pkt_rr_from_wire(pkt->wire, &pkt->parsed, pkt->max_size,
&pkt->mm, rr);
ret = knot_rrset_rr_from_wire(pkt->wire, &pkt->parsed, pkt->max_size,
&pkt->mm, rr);
if (ret != KNOT_EOK) {
dbg_packet("%s: failed to parse RR\n", __func__);
return ret;
......
/*!
* \file pkt.h
*
* \author Lubos Slovak <lubos.slovak@nic.cz>
* \author Marek Vavrusa <marek.vavrusa@nic.cz>
*
* \brief Structure for holding DNS packet data and metadata.
*
......
This diff is collapsed.
/* 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/>.
*/
/*!
* \file rrset.h
*
* \author Lubos Slovak <lubos.slovak@nic.cz>
* \author Jan Vcelak <jan.vcelak@nic.cz>
*
* \brief RRSet from/to wire conversion functions.
*
* \addtogroup libknot
* @{
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "libknot/mempattern.h"
#include "libknot/dname.h"
#include "libknot/rrset.h"
struct knot_compr;
/*!
* \brief Flags controlling RR set from/to wire conversion.
*/
enum knot_rrset_wire_flags {
KNOT_RRSET_WIRE_NONE = 0,
KNOT_RRSET_WIRE_CANONICAL = 1 << 0,
};
typedef enum knot_rrset_wire_flags knot_rrset_wire_flags_t;
/*!
* \brief Write RR Set content to a wire.
*
* Function accepts \ref KNOT_RRSET_WIRE_CANONICAL flag, which causes the
* output to be written in canonical representation.
*
* \param rrset RRSet to be converted.
* \param wire Output wire buffer.
* \param max_size Capacity of wire buffer.
* \param compr Compression context.
* \param flags Flags controlling the output.
*
* \return Output size, negative number on error (KNOT_E*).
*/
int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, uint16_t max_size,
struct knot_compr *compr, knot_rrset_wire_flags_t flags);
/*!
* \brief Creates one RR from wire, stores it into \a rrset.
*
* \param pkt_wire Source wire (the whole packet).
* \param pos Position in \a wire where to start parsing.
* \param pkt_size Total size of data in \a wire (size of the packet).
* \param mm Memory context.
* \param rrset Destination RRSet.
*
* \return KNOT_E*
*/
int knot_rrset_rr_from_wire(const uint8_t *pkt_wire, size_t *pos,
size_t pkt_size, mm_ctx_t *mm, knot_rrset_t *rrset);
This diff is collapsed.
This diff is collapsed.
......@@ -34,8 +34,6 @@
#include "libknot/dname.h"
#include "libknot/rdataset.h"
struct knot_compr;
/*!
* \brief Structure for representing RRSet.
*
......@@ -123,53 +121,6 @@ void knot_rrset_free(knot_rrset_t **rrset, mm_ctx_t *mm);
*/
void knot_rrset_clear(knot_rrset_t *rrset, mm_ctx_t *mm);
/* ---------- Wire conversions (legacy, to be done in knot_pkt_t) ----------- */
/*!
* \brief Flags controlling RR set from/to wire conversion.
*/
enum knot_rrset_wire_flags {
KNOT_RRSET_WIRE_NONE = 0,
KNOT_RRSET_WIRE_CANONICAL = 1 << 0,
};
typedef enum knot_rrset_wire_flags knot_rrset_wire_flags_t;
/*!
* \brief Write RR Set content to a wire.
*
* Function accepts \ref KNOT_RRSET_WIRE_CANONICAL flag, which causes the
* output to be written in canonical representation.
*
* \param rrset RRSet to be converted.
* \param wire Output wire buffer.
* \param max_size Capacity of wire buffer.
* \param compr Compression context.
* \param flags Flags controlling the output.
*
* \return Output size, negative number on error (KNOT_E*).
*/
int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, uint16_t max_size,
struct knot_compr *compr, knot_rrset_wire_flags_t flags);
/*!
* \brief Creates one RR from wire, stores it into 'rrset'
*
* \param rrset Destination RRSet.
* \param wire Source wire.
* \param pos Position in wire.
* \param total_size Size of wire.
* \param ttl Use this TTL to create RR.
* \param rdlength RDLENGTH.
* \param mm Memory context.
*
* \return KNOT_E*
*/
int knot_rrset_rdata_from_wire_one(knot_rrset_t *rrset,
const uint8_t *wire, size_t *pos,
size_t total_size, uint32_t ttl, size_t rdlength,
mm_ctx_t *mm);
/* ---------- RR addition. (legacy, functionality in knot_rdataset_t) ------- */
/*!
......
......@@ -31,6 +31,7 @@
#include "libknot/packet/wire.h"
#include "libknot/consts.h"
#include "libknot/dnssec/key.h"
#include "libknot/packet/rrset-wire.h"
const int KNOT_TSIG_MAX_DIGEST_SIZE = 64; // size of HMAC-SHA512 digest
const uint16_t KNOT_TSIG_FUDGE_DEFAULT = 300; // default Fudge value
......
......@@ -337,7 +337,6 @@ static knot_pkt_t* create_query_packet(const query_t *query)
if (query->type_num == KNOT_RRTYPE_IXFR) {
// SOA rdata in wireformat.
uint8_t wire[22] = { 0x0 };
size_t pos = 0;
// Create rrset with SOA record.
knot_rrset_t *soa = knot_rrset_new(qname,
......@@ -351,10 +350,8 @@ static knot_pkt_t* create_query_packet(const query_t *query)
}
// Fill in blank SOA rdata to rrset.
ret = knot_rrset_rdata_from_wire_one(soa, wire, &pos,
sizeof(wire),
0, sizeof(wire),
&packet->mm);
ret = knot_rrset_add_rdata(soa, wire, sizeof(wire), 0,
&packet->mm);
if (ret != KNOT_EOK) {
knot_rrset_free(&soa, &packet->mm);
knot_pkt_free(&packet);
......
......@@ -342,12 +342,8 @@ static int rr_list_append(zs_scanner_t *s, list_t *target_list, mm_ctx_t *mm)
}
/* Create RDATA. */
size_t pos = 0;
int ret = knot_rrset_rdata_from_wire_one(rr, s->r_data, &pos,
s->r_data_length,
s->r_ttl,
s->r_data_length,
NULL);
int ret = knot_rrset_add_rdata(rr, s->r_data, s->r_data_length,
s->r_ttl, NULL);
if (ret != KNOT_EOK) {
DBG("%s: failed to set rrset from wire - %s\n",
__func__, knot_strerror(ret));
......
......@@ -69,6 +69,40 @@ str-test HINFO "" ""
TXT "\\" "\""
TXT "ahoj" "" "nevim"
NAPTR 20 0 "s" "SIP+D2U" "" sip._udp.wild.
\035leading.hash.char A 1.2.3.4
cname.to.hash.dname CNAME \035leading.hash.char
; All possible values for dname characters
\000\001\002\003\004\005\006\007\008\009 MX 0 \000\001\002\003\004\005\006\007\008\009
\010\011\012\013\014\015\016\017\018\019 MX 0 \010\011\012\013\014\015\016\017\018\019
\020\021\022\023\024\025\026\027\028\029 MX 0 \020\021\022\023\024\025\026\027\028\029
\030\031\032\033\034\035\036\037\038\039 MX 0 \030\031\032\033\034\035\036\037\038\039
\040\041\042\043\044\045\046\047\048\049 MX 0 \040\041\042\043\044\045\046\047\048\049
\050\051\052\053\054\055\056\057\058\059 MX 0 \050\051\052\053\054\055\056\057\058\059
\060\061\062\063\064\065\066\067\068\069 MX 0 \060\061\062\063\064\065\066\067\068\069
\070\071\072\073\074\075\076\077\078\079 MX 0 \070\071\072\073\074\075\076\077\078\079
\080\081\082\083\084\085\086\087\088\089 MX 0 \080\081\082\083\084\085\086\087\088\089
\090\091\092\093\094\095\096\097\098\099 MX 0 \090\091\092\093\094\095\096\097\098\099
\100\101\102\103\104\105\106\107\108\109 MX 0 \100\101\102\103\104\105\106\107\108\109
\110\111\112\113\114\115\116\117\118\119 MX 0 \110\111\112\113\114\115\116\117\118\119
\120\121\122\123\124\125\126\127\128\129 MX 0 \120\121\122\123\124\125\126\127\128\129
\130\131\132\133\134\135\136\137\138\139 MX 0 \130\131\132\133\134\135\136\137\138\139
\140\141\142\143\144\145\146\147\148\149 MX 0 \140\141\142\143\144\145\146\147\148\149
\150\151\152\153\154\155\156\157\158\159 MX 0 \150\151\152\153\154\155\156\157\158\159
\160\161\162\163\164\165\166\167\168\169 MX 0 \160\161\162\163\164\165\166\167\168\169
\170\171\172\173\174\175\176\177\178\179 MX 0 \170\171\172\173\174\175\176\177\178\179
\180\181\182\183\184\185\186\187\188\189 MX 0 \180\181\182\183\184\185\186\187\188\189
\190\191\192\193\194\195\196\197\198\199 MX 0 \190\191\192\193\194\195\196\197\198\199
\200\201\202\203\204\205\206\207\208\209 MX 0 \200\201\202\203\204\205\206\207\208\209
\210\211\212\213\214\215\216\217\218\219 MX 0 \210\211\212\213\214\215\216\217\218\219
\220\221\222\223\224\225\226\227\228\229 MX 0 \220\221\222\223\224\225\226\227\228\229
\230\231\232\233\234\235\236\237\238\239 MX 0 \230\231\232\233\234\235\236\237\238\239
\240\241\242\243\244\245\246\247\248\249 MX 0 \240\241\242\243\244\245\246\247\248\249
\250\251\252\253\254\255 MX 0 \250\251\252\253\254\255
; Maximal dname label length
123456789012345678901234567890123456789012345678901234567890123 MX 0 123456789012345678901234567890123456789012345678901234567890123
; Maximal dname length
1234567890123456789012345678901234567890123456789.1234567890123456789012345678901234567890123456789.1234567890123456789012345678901234567890123456789.1234567890123456789012345678901234567890123456789.123456789012345678901234567890123456789012345.records. MX 0 1234567890123456789012345678901234567890123456789.1234567890123456789012345678901234567890123456789.1234567890123456789012345678901234567890123456789.1234567890123456789012345678901234567890123456789.123456789012345678901234567890123456789012345.records.
; CNAME loop
*.loop1 CNAME a.loop2
......
......@@ -979,7 +979,7 @@ class Knot(Server):
s.begin("log")
s.begin("stdout")
s.item("any", "info")
s.item("any", "debug")
s.end()
s.begin("stderr")
s.end()
......
......@@ -34,6 +34,7 @@ check_PROGRAMS = \
rdata \
rdataset \
rrset \
rrset_wire \
node \
edns \
pkt \
......
/* 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 <assert.h>
#include <tap/basic.h>
#include <libknot/packet/rrset-wire.h>
#include <libknot/descriptor.h>
#include <libknot/errcode.h>
// Wire initializers
#define MESSAGE_HEADER(AN, AUTH, ADD) 0xd4, 0xec, 0x81, 0xa0, 0x00, 0x01, \
0x00, AN, 0x00, AUTH, 0x00, ADD
#define QUERY(qname, type) qname, 0x00, type, 0x00, 0x01
#define RR_HEADER(owner, type, rdlength0, rdlength1) owner, 0x00, type, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, rdlength0, rdlength1
#define QNAME_POINTER 0xc0, 0x0c
// Initializers' sizes
#define QUERY_SIZE 12 + 4
#define RR_HEADER_SIZE 10
// Sample domain names
#define QNAME 0x03, 0x6e, 0x69, 0x63, 0x02, 0x63, 0x7a, 0x00
#define QNAME_SIZE 8
#define QNAME_LONG \
0x3f,'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', \
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', \
'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', \
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'w', 'y', \
'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 0x3f,\
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', \
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', \
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', \
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'x', 'y', 'z', \
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 0x3f,'a', \
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', \
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', \
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', \
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'x', 'y', 'z', 'a', \
'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'i', 'k', 0x3d,'a', 'b', \
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', \
'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', \
'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', \
'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'x', 'y', 'z', 'a', 'b', \
'c', 'd', 'e', 'f', 'g', 'h', 'i', 0x00
#define QNAME_LONG_SIZE 255
#define POINTER_SIZE 2
struct wire_data {
uint8_t wire[65535];
size_t size;
size_t pos;
int code;
const char *msg;
};
#define FROM_CASE_COUNT 16
static const struct wire_data FROM_CASES[FROM_CASE_COUNT] = {
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_A)},
.size = QUERY_SIZE + QNAME_SIZE,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EMALF,
.msg = "No header" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_A), 0x00, 0x00, 0x01},
.size = QUERY_SIZE + QNAME_SIZE + 3,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EMALF,
.msg = "Partial header" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_A),
RR_HEADER(QNAME, KNOT_RRTYPE_A, 0x00, 0x04) },
.size = QUERY_SIZE + RR_HEADER_SIZE + QNAME_SIZE * 2,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EMALF,
.msg = "No RDATA" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_A),
RR_HEADER(QNAME, KNOT_RRTYPE_A, 0x00, 0x04), 0x01 },
.size = QUERY_SIZE + RR_HEADER_SIZE + QNAME_SIZE * 2 + 1,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EMALF,
.msg = "Partial RDATA" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_A),
RR_HEADER(QNAME, KNOT_RRTYPE_A, 0x00, 0x04), 0x01, 0x02, 0x03, 0x04 },
.size = QUERY_SIZE + RR_HEADER_SIZE + QNAME_SIZE * 2 + 4,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EOK,
.msg = "OK RDATA" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_A),
RR_HEADER(QNAME, KNOT_RRTYPE_A, 0x00, 0x05), 0x01, 0x02, 0x03, 0x04, 0x05 },
.size = QUERY_SIZE + RR_HEADER_SIZE + QNAME_SIZE * 2 + 5,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EMALF,
.msg = "Trailing RDATA" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME_LONG, KNOT_RRTYPE_SOA),
RR_HEADER(QNAME_POINTER, KNOT_RRTYPE_SOA, 0x00, 0x18), QNAME_POINTER, QNAME_POINTER,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.size = QUERY_SIZE + RR_HEADER_SIZE + QNAME_LONG_SIZE + 6 + 20,
.pos = QUERY_SIZE + QNAME_LONG_SIZE,
.code = KNOT_EOK,
.msg = "Max DNAME" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME, KNOT_RRTYPE_SIG),
RR_HEADER(QNAME_POINTER, KNOT_RRTYPE_SIG, 0xff, 0xdb),
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, QNAME },
.size = 65535,
.pos = QUERY_SIZE + QNAME_SIZE,
.code = KNOT_EOK,
.msg = "Max RDLENGTH" },
{ .wire = { MESSAGE_HEADER(1, 0, 0), QUERY(QNAME_LONG, KNOT_RRTYPE_SIG),
RR_HEADER(QNAME_POINTER, KNOT_RRTYPE_SIG, 0xff, 0xff),
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, QNAME_POINTER },