-
Jan Kadlec authored
- previously static function 'put_rr' in internet.c has been made public, it handles additions of RRSIGs as well now, by adding the to a list that is traversed after each section has been solved.
742f3066
Forked from
Knot projects / Knot DNS
11134 commits behind the upstream repository.
process_query.c 8.25 KiB
/* 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/>.
*/
#include <config.h>
#include <tap/basic.h>
#include <string.h>
#include <stdlib.h>
#include "common/mempool.h"
#include "common/descriptor.h"
#include "libknot/packet/wire.h"
#include "knot/nameserver/process_query.h"
#include "knot/server/zones.h"
/* SOA RDATA. */
#define SOA_RDLEN 30
static const uint8_t SOA_RDATA[SOA_RDLEN] = {
0x02, 0x6e, 0x73, 0x00, /* ns. */
0x04, 'm', 'a', 'i', 'l', 0x00,/* mail. */
0x77, 0xdf, 0x1e, 0x63, /* serial */
0x00, 0x01, 0x51, 0x80, /* refresh */
0x00, 0x00, 0x1c, 0x20, /* retry */
0x00, 0x0a, 0x8c, 0x00, /* expire */
0x00, 0x00, 0x0e, 0x10 /* min ttl */
};
/* Create fake root zone. */
void create_root_zone(server_t *server, mm_ctx_t *mm)
{
/* Insert root zone. */
conf_zone_t *conf = malloc(sizeof(conf_zone_t));
conf_init_zone(conf);
conf->name = strdup(".");
zone_t *root = zone_new(conf);
root->contents = knot_zone_contents_new(root->name);
knot_dname_t *root_name = knot_dname_copy(root->name);
knot_rrset_t *soa_rrset = knot_rrset_new(root_name,
KNOT_RRTYPE_SOA, KNOT_CLASS_IN,
NULL);
knot_rrset_add_rr(soa_rrset, SOA_RDATA, SOA_RDLEN, 7200, NULL);
knot_node_add_rrset(root->contents->apex, soa_rrset, NULL);
/* Bake the zone. */
knot_node_t *first_nsec3 = NULL, *last_nsec3 = NULL;
knot_zone_contents_adjust_full(root->contents, &first_nsec3, &last_nsec3);
/* Switch zone db. */
knot_zonedb_free(&server->zone_db);
server->zone_db = knot_zonedb_new(1);
knot_zonedb_insert(server->zone_db, root);
knot_zonedb_build_index(server->zone_db);
}
/* Basic response check (4 TAP tests). */
static void answer_sanity_check(const uint8_t *query,
const uint8_t *answer, uint16_t answer_len,
uint8_t expected_rcode, const char *name)
{
ok(answer_len >= KNOT_WIRE_HEADER_SIZE, "ns: len(%s answer) >= DNS header", name);
if (answer_len >= KNOT_WIRE_HEADER_SIZE) {
ok(knot_wire_get_qr(answer), "ns: %s answer has QR=1", name);
is_int(expected_rcode, knot_wire_get_rcode(answer), "ns: %s answer RCODE=%d", name, expected_rcode);
is_int(knot_wire_get_id(query), knot_wire_get_id(answer), "ns: %s MSGID match", name);
} else {
skip_block(3, "ns: can't check DNS header");
}
}
/* Resolve query and check answer for sanity (2 TAP tests). */
static void exec_query(knot_process_t *query_ctx, const char *name,
const uint8_t *query, uint16_t query_len,
uint8_t expected_rcode)
{
uint16_t answer_len = KNOT_WIRE_MAX_PKTSIZE;
uint8_t answer[KNOT_WIRE_MAX_PKTSIZE];
/* Input packet. */
int state = knot_process_in(query, query_len, query_ctx);
ok(state & (NS_PROC_FULL|NS_PROC_FAIL), "ns: process %s query", name);
/* Create answer. */
state = knot_process_out(answer, &answer_len, query_ctx);
if (state & NS_PROC_FAIL) {
/* Allow 1 generic error response. */
answer_len = KNOT_WIRE_MAX_PKTSIZE;
state = knot_process_out(answer, &answer_len, query_ctx);
}
ok(state == NS_PROC_DONE, "ns: answer %s query", name);
/* Check answer. */
answer_sanity_check(query, answer, answer_len, expected_rcode, name);
}
/* \internal Helpers */
#define WIRE_COPY(dst, dst_len, src, src_len) \
memcpy(dst, src, src_len); \
dst_len = src_len;
#define ROOT_DNAME ((const uint8_t *)"")
int main(int argc, char *argv[])
{
plan(8*6 + 3); /* exec_query = 6 TAP tests */
/* Create processing context. */
knot_process_t query_ctx;
memset(&query_ctx, 0, sizeof(knot_process_t));
mm_ctx_mempool(&query_ctx.mm, sizeof(knot_pkt_t));
/* Create name server. */
server_t server;
server_init(&server);
server.opt_rr = knot_edns_new();
knot_edns_set_version(server.opt_rr, EDNS_VERSION);
knot_edns_set_payload(server.opt_rr, 4096);
conf()->identity = strdup("bogus.ns");
conf()->version = strdup("0.11");
/* Insert root zone. */
create_root_zone(&server, &query_ctx.mm);
zone_t *zone = knot_zonedb_find(server.zone_db, ROOT_DNAME);
/* Prepare. */
int state = NS_PROC_FAIL;
uint8_t query_wire[KNOT_WIRE_MAX_PKTSIZE];
uint16_t query_len = KNOT_WIRE_MAX_PKTSIZE;
knot_pkt_t *query = knot_pkt_new(query_wire, query_len, &query_ctx.mm);
/* Create query processing parameter. */
struct sockaddr_storage ss;
memset(&ss, 0, sizeof(struct sockaddr_storage));
sockaddr_set(&ss, AF_INET, "127.0.0.1", 53);
struct process_query_param param = {0};
param.query_source = &ss;
param.server = &server;
/* Query processor (CH zone) */
state = knot_process_begin(&query_ctx, ¶m, NS_PROC_QUERY);
const uint8_t chaos_dname[] = "\2""id""\6""server"; /* id.server */
knot_pkt_clear(query);
knot_pkt_put_question(query, chaos_dname, KNOT_CLASS_CH, KNOT_RRTYPE_TXT);
exec_query(&query_ctx, "CH TXT", query->wire, query->size, KNOT_RCODE_NOERROR);
/* Query processor (valid input). */
state = knot_process_reset(&query_ctx);
knot_pkt_clear(query);
knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
exec_query(&query_ctx, "IN/root", query->wire, query->size, KNOT_RCODE_NOERROR);
/* Query processor (-1 bytes, not enough data). */
state = knot_process_reset(&query_ctx);
exec_query(&query_ctx, "IN/few-data", query->wire, query->size - 1, KNOT_RCODE_FORMERR);
/* Query processor (+1 bytes trailing). */
state = knot_process_reset(&query_ctx);
query->wire[query->size] = '\1'; /* Initialize the "garbage" value. */
exec_query(&query_ctx, "IN/trail-garbage", query->wire, query->size + 1, KNOT_RCODE_FORMERR);
/* Forge NOTIFY query from SOA query. */
state = knot_process_reset(&query_ctx);
knot_wire_set_opcode(query->wire, KNOT_OPCODE_NOTIFY);
exec_query(&query_ctx, "IN/notify", query->wire, query->size, KNOT_RCODE_NOTAUTH);
/* Forge AXFR query. */
knot_process_reset(&query_ctx);
knot_pkt_clear(query);
knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_AXFR);
exec_query(&query_ctx, "IN/axfr", query->wire, query->size, KNOT_RCODE_NOTAUTH);
/* Forge IXFR query (badly formed, no SOA in AUTHORITY section). */
knot_process_reset(&query_ctx);
knot_pkt_clear(query);
knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_IXFR);
exec_query(&query_ctx, "IN/ixfr-formerr", query->wire, query->size, KNOT_RCODE_FORMERR);
/* Forge IXFR query (well formed). */
knot_process_reset(&query_ctx);
/* Append SOA RR. */
knot_rrset_t *soa_rr = knot_node_get_rrset(zone->contents->apex, KNOT_RRTYPE_SOA);
knot_pkt_begin(query, KNOT_AUTHORITY);
knot_pkt_put(query, COMPR_HINT_NONE, soa_rr, 0);
exec_query(&query_ctx, "IN/ixfr", query->wire, query->size, KNOT_RCODE_NOTAUTH);
/* \note Tests below are not possible without proper zone and zone data. */
/* #189 Process UPDATE query. */
/* #189 Process AXFR client. */
/* #189 Process IXFR client. */
/* Query processor (smaller than DNS header, ignore). */
state = knot_process_reset(&query_ctx);
knot_pkt_clear(query);
knot_pkt_put_question(query, ROOT_DNAME, KNOT_CLASS_IN, KNOT_RRTYPE_SOA);
state = knot_process_in(query->wire, KNOT_WIRE_HEADER_SIZE - 1, &query_ctx);
ok(state == NS_PROC_NOOP, "ns: IN/less-than-header query ignored");
/* Query processor (response, ignore). */
state = knot_process_reset(&query_ctx);
knot_wire_set_qr(query->wire);
state = knot_process_in(query->wire, query->size, &query_ctx);
ok(state == NS_PROC_NOOP, "ns: IN/less-than-header query ignored");
/* Finish. */
state = knot_process_finish(&query_ctx);
ok(state == NS_PROC_NOOP, "ns: processing end" );
/* Cleanup. */
mp_delete((struct mempool *)query_ctx.mm.ctx);
server_deinit(&server);
return 0;
}
#undef WIRE_COPY