Commit 43adb042 authored by Daniel Salzman's avatar Daniel Salzman

Optimize dig structures + reduce host code.

Each query has own settings now.

refs #2137
parent b9e0e758
......@@ -307,8 +307,6 @@ src/utils/dig/dig_exec.h
src/utils/dig/dig_main.c
src/utils/dig/dig_params.c
src/utils/dig/dig_params.h
src/utils/host/host_exec.c
src/utils/host/host_exec.h
src/utils/host/host_main.c
src/utils/host/host_params.c
src/utils/host/host_params.h
......
......@@ -72,9 +72,7 @@ khost_SOURCES = \
utils/host/host_params.c \
utils/host/host_params.h \
utils/dig/dig_exec.c \
utils/dig/dig_exec.h \
utils/host/host_exec.c \
utils/host/host_exec.h
utils/dig/dig_exec.h
knsupdate_SOURCES = \
utils/common/msg.h \
......
......@@ -165,7 +165,7 @@ void list_dup(list *dst, list *src, size_t itemsz)
*
* This function counts nodes in list @l and returns this number.
*/
size_t list_size(list *l)
size_t list_size(const list *l)
{
size_t count = 0;
......
......@@ -81,7 +81,7 @@ void add_tail_list(list *, list *);
void init_list(list *);
void insert_node(node *, node *);
void list_dup(list *dst, list *src, size_t itemsz);
size_t list_size(list *);
size_t list_size(const list *);
/*!
* \brief List item for string lists.
......
......@@ -30,18 +30,16 @@
#include "utils/common/netio.h" // get_socktype
#include "utils/common/exec.h" // print_packet
static knot_packet_t* create_query_packet(const dig_params_t *params,
const query_t *query,
uint8_t **data,
size_t *data_len)
static knot_packet_t* create_query_packet(const query_t *query,
uint8_t **data,
size_t *data_len)
{
knot_question_t q;
// Set packet buffer size.
int max_size = MAX_PACKET_SIZE;
if (get_socktype(query->protocol, query->qtype) != SOCK_STREAM) {
// For UDP default or specified EDNS size.
max_size = params->udp_size;
if (get_socktype(query->protocol, query->type_num) != SOCK_STREAM) {
max_size = query->udp_size;
}
// Create packet skeleton.
......@@ -60,9 +58,9 @@ static knot_packet_t* create_query_packet(const dig_params_t *params,
}
// Fill auxiliary question structure.
q.qclass = query->qclass;
q.qtype = query->qtype;
q.qname = knot_dname_new_from_str(query->qname, strlen(query->qname), 0);
q.qclass = query->class_num;
q.qtype = query->type_num;
q.qname = knot_dname_new_from_str(query->owner, strlen(query->owner), 0);
if (q.qname == NULL) {
knot_dname_release(q.qname);
......@@ -78,7 +76,7 @@ static knot_packet_t* create_query_packet(const dig_params_t *params,
}
// For IXFR query add authority section.
if (query->qtype == KNOT_RRTYPE_IXFR) {
if (query->type_num == KNOT_RRTYPE_IXFR) {
int ret;
size_t pos = 0;
// SOA rdata in wireformat.
......@@ -107,7 +105,7 @@ static knot_packet_t* create_query_packet(const dig_params_t *params,
// Create rrset with SOA record.
knot_rrset_t *soa = knot_rrset_new(q.qname,
KNOT_RRTYPE_SOA,
params->class_num,
query->class_num,
0);
ret = knot_rrset_add_rdata(soa, soa_data);
......@@ -222,7 +220,7 @@ static bool last_serial_check(const uint32_t serial, const knot_packet_t *reply)
}
}
void process_query(const dig_params_t *params, const query_t *query)
void process_query(const query_t *query)
{
float elapsed;
bool id_ok, stop;
......@@ -237,18 +235,18 @@ void process_query(const dig_params_t *params, const query_t *query)
size_t total_len = 0;
size_t msg_count = 0;
if (params == NULL || query == NULL) {
if (query == NULL) {
return;
}
// Create query packet.
out_packet = create_query_packet(params, query, &out, &out_len);
out_packet = create_query_packet(query, &out, &out_len);
if (out_packet == NULL) {
return;
}
WALK_LIST(server, params->servers) {
WALK_LIST(server, query->servers) {
int sockfd;
int rcode;
......@@ -257,9 +255,9 @@ void process_query(const dig_params_t *params, const query_t *query)
// Send query message.
sockfd = send_msg((server_t *)server,
get_iptype(params->ip),
get_socktype(query->protocol, query->qtype),
params->wait, out, out_len);
get_iptype(query->ip),
get_socktype(query->protocol, query->type_num),
query->wait, out, out_len);
if (sockfd < 0) {
continue;
......@@ -271,8 +269,8 @@ void process_query(const dig_params_t *params, const query_t *query)
while (id_ok == false) {
// Receive reply message.
in_len = receive_msg(sockfd,
get_socktype(query->protocol, query->qtype),
params->wait, in, sizeof(in));
get_socktype(query->protocol, query->type_num),
query->wait, in, sizeof(in));
if (in_len <= 0) {
stop = true;
......@@ -308,7 +306,7 @@ void process_query(const dig_params_t *params, const query_t *query)
}
// Check rcode.
rcode = check_rcode(params->servfail_stop, in_packet);
rcode = check_rcode(query->servfail_stop, in_packet);
// Servfail + stop if servfail -> stop processing.
if (rcode == -1) {
......@@ -324,8 +322,8 @@ void process_query(const dig_params_t *params, const query_t *query)
check_question(out_packet, in_packet);
// Dump one standard reply message and finish.
if (query->qtype != KNOT_RRTYPE_AXFR &&
query->qtype != KNOT_RRTYPE_IXFR) {
if (query->type_num != KNOT_RRTYPE_AXFR &&
query->type_num != KNOT_RRTYPE_IXFR) {
// Stop meassuring of query time.
gettimeofday(&t_end, NULL);
......@@ -354,7 +352,7 @@ void process_query(const dig_params_t *params, const query_t *query)
total_len += in_len;
// Start XFR dump.
print_header_xfr(&query->style, query->qtype);
print_header_xfr(&query->style, query->type_num);
print_data_xfr(&query->style, in_packet);
......@@ -375,8 +373,8 @@ void process_query(const dig_params_t *params, const query_t *query)
// Receive reply message.
in_len = receive_msg(sockfd,
get_socktype(query->protocol, query->qtype),
params->wait, in, sizeof(in));
get_socktype(query->protocol, query->type_num),
query->wait, in, sizeof(in));
if (in_len <= 0) {
stop = true;
......@@ -405,7 +403,7 @@ void process_query(const dig_params_t *params, const query_t *query)
id_ok = check_id(out_packet, in_packet);
// Check rcode.
rcode = check_rcode(params->servfail_stop, in_packet);
rcode = check_rcode(query->servfail_stop, in_packet);
if (rcode != KNOT_RCODE_NOERROR) {
stop = true;
......@@ -448,25 +446,26 @@ void process_query(const dig_params_t *params, const query_t *query)
int dig_exec(const dig_params_t *params)
{
node *query = NULL;
node *n = NULL;
if (params == NULL) {
return KNOT_EINVAL;
}
switch (params->operation) {
case OPERATION_QUERY:
// Loop over query list.
WALK_LIST(query, params->queries) {
process_query(params, (query_t *)query);
}
// Loop over query list.
WALK_LIST(n, params->queries) {
query_t *query = (query_t *)n;
break;
case OPERATION_LIST_SOA:
break;
default:
ERR("unsupported operation\n");
break;
switch (query->operation) {
case OPERATION_QUERY:
process_query(query);
break;
case OPERATION_LIST_SOA:
break;
default:
ERR("unsupported operation\n");
break;
}
}
return KNOT_EOK;
......
......@@ -32,7 +32,7 @@
int dig_exec(const dig_params_t *params);
void process_query(const dig_params_t *params, const query_t *query);
void process_query(const query_t *query);
#endif // _DIG__DIG_EXEC_H_
......
This diff is collapsed.
......@@ -31,22 +31,30 @@
#include "utils/common/params.h" // params_t
/*! \brief Operation mode of dig. */
typedef enum {
/*!< Classic queries in list. */
OPERATION_QUERY,
/*!< Query for NS and all authoritative SOA records. */
OPERATION_LIST_SOA,
} operation_t;
/*! \brief DNS header flags. */
typedef struct {
/*!< Authoritative answer flag. */
bool aa_flag;
bool aa_flag;
/*!< Truncated flag. */
bool tc_flag;
bool tc_flag;
/*!< Recursion desired flag. */
bool rd_flag;
bool rd_flag;
/*!< Recursion available flag. */
bool ra_flag;
bool ra_flag;
/*!< Z flag. */
bool z_flag;
bool z_flag;
/*!< Authenticated data flag. */
bool ad_flag;
bool ad_flag;
/*!< Checking disabled flag. */
bool cd_flag;
bool cd_flag;
} flags_t;
/*! \brief Basic parameters for DNS query. */
......@@ -54,42 +62,16 @@ typedef struct {
/*!< List node (for list container). */
node n;
/*!< Name to query on. */
char *qname;
/*!< Class number (16unsigned + -1 uninitialized). */
int32_t qclass;
/*!< Type number (16unsigned + -1 uninitialized). */
int32_t qtype;
/*!< SOA serial for XFR. */
uint32_t xfr_serial;
/*!< Protocol type. */
protocol_t protocol;
/*!< Header flags. */
flags_t flags;
/*!< Output settings. */
style_t style;
} query_t;
/*! \brief Operation mode of dig. */
typedef enum {
/*!< Classic queries in list. */
OPERATION_QUERY,
/*!< Query for NS and all authoritative SOA records. */
OPERATION_LIST_SOA,
} operation_t;
/*! \brief Settings for dig. */
typedef struct {
char *owner;
/*!< List of nameservers to query to. */
list servers;
/*!< List of DNS queries to process. */
list queries;
/*!< Operation mode. */
operation_t operation;
/*!< Version of ip protocol to use. */
ip_t ip;
/*!< Protocol type (TCP, UDP) to use. */
protocol_t protocol;
/*!< Default port/service to connect to. */
/*!< Port/service to connect to. */
char *port;
/*!< UDP buffer size. */
uint32_t udp_size;
......@@ -99,27 +81,34 @@ typedef struct {
int32_t wait;
/*!< Stop quering if servfail. */
bool servfail_stop;
/*!< Default class number (16unsigned + -1 uninitialized). */
/*!< Class number (16unsigned + -1 uninitialized). */
int32_t class_num;
/*!< Default type number (16unsigned + -1 uninitialized). */
/*!< Type number (16unsigned + -1 uninitialized). */
int32_t type_num;
/*!< Default SOA serial for XFR. */
/*!< SOA serial for XFR. */
uint32_t xfr_serial;
/*!< Header flags. */
flags_t flags;
/*!< Default output settings. */
/*!< Output settings. */
style_t style;
} query_t;
/*! \brief Settings for dig. */
typedef struct {
/*!< List of DNS queries to process. */
list queries;
/*!< Default settings for queries. */
query_t *config;
} dig_params_t;
/*! \brief Default header flags. */
extern const flags_t DEFAULT_FLAGS;
query_t* query_create(const char *qname,
const int32_t qtype,
const int32_t qclass);
query_t* query_create(const char *owner, const query_t *config);
void query_free(query_t *query);
void query_set(query_t *query, const dig_params_t *params);
void complete_queries(list *queries, const query_t *conf);
int dig_init(dig_params_t *params);
int dig_parse(dig_params_t *params, int argc, char *argv[]);
void dig_clean(dig_params_t *params);
......
/* Copyright (C) 2011 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 "utils/host/host_exec.h"
#include "common/lists.h" // list
#include "common/errcode.h" // KNOT_EOK
#include "utils/common/msg.h" // WARN
#include "utils/dig/dig_params.h" // dig_params_t
#include "utils/dig/dig_exec.h" // process_query
int host_exec(const dig_params_t *params)
{
node *query = NULL;
if (params == NULL) {
return KNOT_EINVAL;
}
switch (params->operation) {
case OPERATION_QUERY:
// Loop over query list.
WALK_LIST(query, params->queries) {
process_query(params, (query_t *)query);
}
break;
case OPERATION_LIST_SOA:
break;
default:
ERR("unsupported operation\n");
break;
}
return KNOT_EOK;
}
/* Copyright (C) 2011 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 host_exec.h
*
* \author Daniel Salzman <daniel.salzman@nic.cz>
*
* \brief host executives.
*
* \addtogroup knot_utils
* @{
*/
#ifndef _HOST__HOST_EXEC_H_
#define _HOST__HOST_EXEC_H_
#include "utils/dig/dig_params.h" // dig_params_t
int host_exec(const dig_params_t *params);
#endif // _HOST__HOST_EXEC_H_
/*! @} */
......@@ -17,8 +17,8 @@
#include <stdlib.h> // EXIT_FAILURE
#include "common/errcode.h" // KNOT_EOK
#include "utils/host/host_params.h" // host_params_parse
#include "utils/host/host_exec.h" // host_exec
#include "utils/host/host_params.h" // host_parse
#include "utils/dig/dig_exec.h" // dig_exec
int main(int argc, char *argv[])
{
......@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
dig_params_t params;
if (host_parse(&params, argc, argv) == KNOT_EOK) {
if (host_exec(&params) != KNOT_EOK) {
if (dig_exec(&params) != KNOT_EOK) {
ret = EXIT_FAILURE;
}
} else {
......
......@@ -33,71 +33,39 @@
static int host_init(dig_params_t *params)
{
memset(params, 0, sizeof(*params));
// Initialize params with dig defaults.
int ret = dig_init(params);
// Initialize servers and queries lists.
init_list(&params->servers);
init_list(&params->queries);
// Default settings.
params->operation = OPERATION_QUERY;
params->ip = IP_ALL;
params->protocol = PROTO_ALL;
params->port = strdup(DEFAULT_DNS_PORT);
params->udp_size = DEFAULT_UDP_SIZE;
params->retries = DEFAULT_RETRIES_HOST;
params->wait = DEFAULT_TIMEOUT_HOST;
params->servfail_stop = false;
params->class_num = KNOT_CLASS_IN;
params->type_num = -1;
params->xfr_serial = 0;
// Default flags.
params->flags = DEFAULT_FLAGS;
if (ret != KNOT_EOK) {
return ret;
}
// Default style.
params->style = DEFAULT_STYLE;
params->style.format = FORMAT_HOST;
// Set host specific defaults.
params->config->retries = DEFAULT_RETRIES_HOST;
params->config->wait = DEFAULT_TIMEOUT_HOST;
params->config->class_num = KNOT_CLASS_IN;
params->config->style.format = FORMAT_HOST;
return KNOT_EOK;
}
void host_clean(dig_params_t *params)
{
node *n = NULL, *nxt = NULL;
if (params == NULL) {
return;
}
// Clean up servers.
WALK_LIST_DELSAFE(n, nxt, params->servers) {
server_free((server_t *)n);
}
// Clean up queries.
WALK_LIST_DELSAFE(n, nxt, params->queries) {
query_free((query_t *)n);
}
free(params->port);
// Clean up the structure.
memset(params, 0, sizeof(*params));
dig_clean(params);
}
static int host_parse_name(const char *name, dig_params_t *params)
static int parse_name(const char *value, list *queries, const query_t *conf)
{
char *reverse = get_reverse_name(name);
char *reverse = get_reverse_name(value);
char *fqd_name = NULL;
query_t *query;
// If name is not FQDN, append trailing dot.
fqd_name = get_fqd_name(name);
fqd_name = get_fqd_name(value);
// RR type is known.
if (params->type_num >= 0) {
if (params->type_num == KNOT_RRTYPE_PTR) {
if (conf->type_num >= 0) {
if (conf->type_num == KNOT_RRTYPE_PTR) {
// Check for correct address.
if (reverse == NULL) {
ERR("invalid IPv4 or IPv6 address\n");
......@@ -106,74 +74,62 @@ static int host_parse_name(const char *name, dig_params_t *params)
}
// Add reverse query for address.
query = query_create(reverse, params->type_num,
params->class_num);
query = query_create(reverse, conf);
if (query == NULL) {
free(reverse);
free(fqd_name);
return KNOT_ENOMEM;
}
query_set(query, params);
add_tail(&params->queries, (node *)query);
add_tail(queries, (node *)query);
} else {
// Add query for name and specified type.
query = query_create(fqd_name, params->type_num,
params->class_num);
query = query_create(fqd_name, conf);
if (query == NULL) {
free(reverse);
free(fqd_name);
return KNOT_ENOMEM;
}
// Set SOA serial for IXFR query.
if (params->type_num == KNOT_RRTYPE_IXFR) {
query->xfr_serial = params->xfr_serial;
}
query_set(query, params);
add_tail(&params->queries, (node *)query);
add_tail(queries, (node *)query);
}
// RR type is unknown, use defaults.
} else {
if (reverse == NULL) {
// Add query for name and type A.
query = query_create(fqd_name, KNOT_RRTYPE_A,
params->class_num);
query = query_create(fqd_name, conf);
if (query == NULL) {
free(fqd_name);
return KNOT_ENOMEM;
}
query_set(query, params);
add_tail(&params->queries, (node *)query);
query->type_num = KNOT_RRTYPE_A;
add_tail(queries, (node *)query);
// Add query for name and type AAAA.
query = query_create(fqd_name, KNOT_RRTYPE_AAAA,
params->class_num);
query = query_create(fqd_name, conf);
if (query == NULL) {
free(fqd_name);
return KNOT_ENOMEM;
}
query_set(query, params);
add_tail(&params->queries, (node *)query);
query->type_num = KNOT_RRTYPE_AAAA;
add_tail(queries, (node *)query);
// Add query for name and type MX.
query = query_create(fqd_name, KNOT_RRTYPE_MX,
params->class_num);
query = query_create(fqd_name, conf);
if (query == NULL) {
free(fqd_name);
return KNOT_ENOMEM;
}
query_set(query, params);
add_tail(&params->queries, (node *)query);
query->type_num = KNOT_RRTYPE_MX;
add_tail(queries, (node *)query);
} else {
// Add reverse query for address.
query = query_create(reverse, KNOT_RRTYPE_PTR,
params->class_num);
query = query_create(fqd_name, conf);
if (query == NULL) {
free(reverse);
free(fqd_name);
return KNOT_ENOMEM;
}
query_set(query, params);
add_tail(&params->queries, (node *)query);
query->type_num = KNOT_RRTYPE_PTR;
add_tail(queries, (node *)query);
}
}
......@@ -202,6 +158,7 @@ int host_parse(dig_params_t *params, int argc, char *argv[])
return KNOT_ERROR;
}
query_t *conf = params->config;
uint16_t rclass, rtype;
uint32_t serial;
......@@ -209,46 +166,47 @@ int host_parse(dig_params_t *params, int argc, char *argv[])
while ((opt = getopt(argc, argv, "46aCdlrsTvwc:R:t:W:")) != -1) {
switch (opt) {
case '4':
params->ip = IP_4;
conf->ip = IP_4;
break;
case '6':
params->ip = IP_6;
conf->ip = IP_6;
break;
case 'a':
params->type_num = KNOT_RRTYPE_ANY;
params->style.format = FORMAT_VERBOSE;
conf->type_num = KNOT_RRTYPE_ANY;
conf->style.format = FORMAT_VERBOSE;
break;
case 'C':
params->type_num = KNOT_RRTYPE_SOA;
params->operation = OPERATION_LIST_SOA;
conf->type_num = KNOT_RRTYPE_SOA;
conf->operation = OPERATION_LIST_SOA;
break;
case 'd':
case 'v': // Fall through.
params->style.format = FORMAT_VERBOSE;
conf->style.format = FORMAT_VERBOSE;
break;
case 'l':
params->type_num = KNOT_RRTYPE_AXFR;
conf->type_num = KNOT_RRTYPE_AXFR;
break;
case 'r':
params->flags.rd_flag = false;
conf->flags.rd_flag = false;
break;
case 's':
params->servfail_stop = true;
conf->servfail_stop = true;
break;
case 'T':
params->protocol = PROTO_TCP;
conf->protocol = PROTO_TCP;
break;
case 'w':
params->wait = -1;
conf->wait = -1;
break;
case 'c':
if (params_parse_class(optarg, &rclass) != KNOT_EOK) {
if (params_parse_class(optarg, &rclass)
!= KNOT_EOK) {
return KNOT_EINVAL;
}
params->class_num = rclass;
conf->class_num = rclass;
break;
case 'R':
if (params_parse_num(optarg, &params->retries)
if (params_parse_num(optarg, &conf->retries)
!= KNOT_EOK) {
return KNOT_EINVAL;
}
......@@ -258,11 +216,11 @@ int host_parse(dig_params_t *params, int argc, char *argv[])
!= KNOT_EOK) {
return KNOT_EINVAL;
}
params->type_num = rtype;
params->xfr_serial = serial;
conf->type_num = rtype;
conf->xfr_serial = serial;
break;
case 'W':
if (params_parse_interval(optarg, &params->wait)
if (params_parse_interval(optarg, &conf->wait)
!= KNOT_EOK) {
return KNOT_EINVAL;
}
......@@ -276,14 +234,14 @@ int host_parse(dig_params_t *params, int argc, char *argv[])
// Process non-option parameters.