diff --git a/.gitignore b/.gitignore index c6cb5692c43ae14dea5ddbb73be0f7e7f158817d..1b897e7f53499b827acbc00e93bb38ed91bbf067 100644 --- a/.gitignore +++ b/.gitignore @@ -50,5 +50,6 @@ m4/ltversion.m4 m4/lt~obsolete.m4 src/unittests-xfr INSTALL +kdig khost knsupdate diff --git a/Knot.files b/Knot.files index f5ff754baf23abb4e2e1bd8b34d22ad0b7a77d33..e33b84e4084772c993f08577288cf9594ee36ac4 100644 --- a/Knot.files +++ b/Knot.files @@ -283,6 +283,11 @@ src/utils/common/netio.c src/utils/common/netio.h src/utils/common/rr-serialize.c src/utils/common/rr-serialize.h +src/utils/dig/dig_exec.c +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 diff --git a/src/Makefile.am b/src/Makefile.am index 13acc648a5c8e81d820b1bc5932664c97193a720..1d9f2633aad2e8555810d3944decf5516d377080 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ ACLOCAL_AMFLAGS = -I ../m4 -libexec_PROGRAMS = knot-zcompile unittests unittests-zcompile unittests-xfr unittests-zscanner khost knsupdate +libexec_PROGRAMS = knot-zcompile unittests unittests-zcompile unittests-xfr unittests-zscanner kdig khost knsupdate sbin_PROGRAMS = knotc knotd dist_man_MANS = knot.conf.5 knotc.8 knotd.8 @@ -30,6 +30,25 @@ CLEANFILES = \ knotc_SOURCES = \ knot/ctl/knotc_main.c +kdig_SOURCES = \ + utils/common/msg.h \ + utils/common/msg.c \ + utils/common/exec.c \ + utils/common/exec.h \ + utils/common/params.c \ + utils/common/params.h \ + utils/common/resolv.c \ + utils/common/resolv.h \ + utils/common/netio.c \ + utils/common/netio.h \ + utils/common/rr-serialize.h \ + utils/common/rr-serialize.c \ + utils/dig/dig_main.c \ + utils/dig/dig_params.c \ + utils/dig/dig_params.h \ + utils/dig/dig_exec.c \ + utils/dig/dig_exec.h + khost_SOURCES = \ utils/common/msg.h \ utils/common/msg.c \ @@ -317,6 +336,7 @@ libknots_la_LIBADD = @LIBOBJS@ libzscanner_la_LIBADD = libknots.la knotd_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@ knotc_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@ +kdig_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@ khost_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@ knsupdate_LDADD = libknotd.la libknot.la libknots.la libzscanner.la @LIBOBJS@ knot_zcompile_LDADD = libknots.la libknot.la libknotd.la @LIBOBJS@ diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c new file mode 100644 index 0000000000000000000000000000000000000000..905027ae8913d6e4ec43fea8efd906bff650aaa5 --- /dev/null +++ b/src/utils/dig/dig_exec.c @@ -0,0 +1,50 @@ +/* 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/dig/dig_exec.h" + +#include "common/lists.h" // list +#include "common/errcode.h" // KNOT_EOK + +#include "utils/common/msg.h" // WARN +#include "utils/common/params.h" // params_t +#include "utils/common/exec.h" // process_query + +int dig_exec(const 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; +} diff --git a/src/utils/dig/dig_exec.h b/src/utils/dig/dig_exec.h new file mode 100644 index 0000000000000000000000000000000000000000..7bae9fe03cbf0c4d40e6046640380d31d75a3411 --- /dev/null +++ b/src/utils/dig/dig_exec.h @@ -0,0 +1,36 @@ +/* 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 dig_exec.h + * + * \author Daniel Salzman <daniel.salzman@nic.cz> + * + * \brief dig executives. + * + * \addtogroup utils + * @{ + */ + +#ifndef _DIG__DIG_EXEC_H_ +#define _DIG__DIG_EXEC_H_ + +#include "utils/common/params.h" // params_t + +int dig_exec(const params_t *params); + +#endif // _DIG__DIG_EXEC_H_ + +/*! @} */ diff --git a/src/utils/dig/dig_main.c b/src/utils/dig/dig_main.c new file mode 100644 index 0000000000000000000000000000000000000000..4a600126ee821f71709945e9a02553d6b1ad5c43 --- /dev/null +++ b/src/utils/dig/dig_main.c @@ -0,0 +1,37 @@ +/* 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 <stdlib.h> // EXIT_FAILURE + +#include "common/errcode.h" // KNOT_EOK +#include "utils/dig/dig_params.h" // dig_params_parse +#include "utils/dig/dig_exec.h" // dig_exec + +int main(int argc, char *argv[]) +{ + params_t params; + + if (dig_params_parse(¶ms, argc, argv) != KNOT_EOK) { + return EXIT_FAILURE; + } + + dig_exec(¶ms); + + dig_params_clean(¶ms); + + return EXIT_SUCCESS; +} + diff --git a/src/utils/dig/dig_params.c b/src/utils/dig/dig_params.c new file mode 100644 index 0000000000000000000000000000000000000000..363a09774103251021233136ee4598f5f434a245 --- /dev/null +++ b/src/utils/dig/dig_params.c @@ -0,0 +1,332 @@ +/* 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/dig/dig_params.h" + +#include <string.h> // strncmp +#include <stdio.h> // printf +#include <getopt.h> // getopt +#include <stdlib.h> // free + +#include "common/lists.h" // list +#include "common/errcode.h" // KNOT_EOK +#include "libknot/util/descriptor.h" // KNOT_CLASS_IN +#include "utils/common/msg.h" // WARN +#include "utils/common/params.h" // parse_class +#include "utils/common/resolv.h" // get_nameservers +#include "utils/common/netio.h" + +static void dig_params_init(params_t *params) +{ + memset(params, 0, sizeof(*params)); + + // Read default nameservers. + if (get_nameservers(¶ms->servers) <= 0) { + WARN("can't read any default nameservers\n"); + } + + // Initialize list of queries. + init_list(¶ms->queries); + + // Default values. + params->operation = OPERATION_QUERY; + params->ip = IP_ALL; + params->protocol = PROTO_ALL; + params->udp_size = DEFAULT_UDP_SIZE; + params->class_num = KNOT_CLASS_IN; + params->type_num = -1; + params->xfr_serial = -1; + params->recursion = true; + params->retries = 1; + params->wait = DEFAULT_WAIT_INTERVAL; + params->servfail_stop = false; + params->format = FORMAT_VERBOSE; +} + +void dig_params_clean(params_t *params) +{ + node *n = NULL, *nxt = NULL; + + if (params == NULL) { + return; + } + + // Clean up server list. + WALK_LIST_DELSAFE(n, nxt, params->servers) { + server_free((server_t *)n); + } + + // Clean up query list. + WALK_LIST_DELSAFE(n, nxt, params->queries) { + query_free((query_t *)n); + } + + // Clean up the structure. + memset(params, 0, sizeof(*params)); +} + +static void dig_params_flag_all(params_t *params) +{ + params->type_num = KNOT_RRTYPE_ANY; + params->format = FORMAT_VERBOSE; +} + +static void dig_params_flag_soa(params_t *params) +{ + params->type_num = KNOT_RRTYPE_SOA; + params->operation = OPERATION_LIST_SOA; +} + +static void dig_params_flag_axfr(params_t *params) +{ + params->type_num = KNOT_RRTYPE_AXFR; +} + +static void dig_params_flag_nonrecursive(params_t *params) +{ + params->recursion = false; +} + +static void dig_params_flag_ipv4(params_t *params) +{ + params->ip = IP_4; +} + +static void dig_params_flag_ipv6(params_t *params) +{ + params->ip = IP_6; +} + +static void dig_params_flag_servfail(params_t *params) +{ + params->servfail_stop = true; +} + +static void dig_params_flag_nowait(params_t *params) +{ + params->wait = -1; +} + +static int dig_params_parse_name(params_t *params, const char *name) +{ + char *reverse = get_reverse_name(name); + char *fqd_name = NULL; + query_t *query; + + // If name is not FQDN, append trailing dot. + fqd_name = get_fqd_name(name); + + // RR type is known. + if (params->type_num >= 0) { + if (params->type_num == KNOT_RRTYPE_PTR) { + // Check for correct address. + if (reverse == NULL) { + ERR("invalid IPv4 or IPv6 address\n"); + free(fqd_name); + return KNOT_EINVAL; + } + + // Add reverse query for address. + query = query_create(reverse, params->type_num); + if (query == NULL) { + free(reverse); + free(fqd_name); + return KNOT_ENOMEM; + } + add_tail(¶ms->queries, (node *)query); + } else { + // Add query for name and specified type. + query = query_create(fqd_name, params->type_num); + 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_set_serial(query, params->xfr_serial); + } + add_tail(¶ms->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); + if (query == NULL) { + free(fqd_name); + return KNOT_ENOMEM; + } + add_tail(¶ms->queries, (node *)query); + + // Add query for name and type AAAA. + query = query_create(fqd_name, KNOT_RRTYPE_AAAA); + if (query == NULL) { + free(fqd_name); + return KNOT_ENOMEM; + } + add_tail(¶ms->queries, (node *)query); + + // Add query for name and type MX. + query = query_create(fqd_name, KNOT_RRTYPE_MX); + if (query == NULL) { + free(fqd_name); + return KNOT_ENOMEM; + } + add_tail(¶ms->queries, (node *)query); + } else { + // Add reverse query for address. + query = query_create(reverse, KNOT_RRTYPE_PTR); + if (query == NULL) { + free(reverse); + free(fqd_name); + return KNOT_ENOMEM; + } + add_tail(¶ms->queries, (node *)query); + } + } + + free(reverse); + free(fqd_name); + + return KNOT_EOK; +} + +static int dig_params_parse_server(params_t *params, const char *name) +{ + node *n = NULL, *nxt = NULL; + + // Remove default nameservers. + WALK_LIST_DELSAFE(n, nxt, params->servers) { + server_free((server_t *)n); + } + + // Initialize blank server list. + init_list(¶ms->servers); + + // Add specified nameserver. + server_t *server = parse_nameserver(name); + if (server == NULL) { + return KNOT_ENOMEM; + } + add_tail(¶ms->servers, (node *)server); + + return KNOT_EOK; +} + +static void dig_params_help(int argc, char *argv[]) +{ + printf("Usage: %s [-aCdlrsTvw] [-4] [-6] [-c class] [-R retries]\n" + " %*c [-t type] [-W time] name [server]\n", + argv[0], (int)strlen(argv[0]), ' '); +} + +int dig_params_parse(params_t *params, int argc, char *argv[]) +{ + int opt = 0; + + if (params == NULL || argv == NULL) { + return KNOT_EINVAL; + } + + dig_params_init(params); + + // Command line options processing. + while ((opt = getopt(argc, argv, "46aCdlrsTvwc:R:t:W:")) != -1) { + switch (opt) { + case '4': + dig_params_flag_ipv4(params); + break; + case '6': + dig_params_flag_ipv6(params); + break; + case 'a': + dig_params_flag_all(params); + break; + case 'C': + dig_params_flag_soa(params); + break; + case 'd': + case 'v': // Fall through. + params_flag_verbose(params); + break; + case 'l': + dig_params_flag_axfr(params); + break; + case 'r': + dig_params_flag_nonrecursive(params); + break; + case 's': + dig_params_flag_servfail(params); + break; + case 'T': + params_flag_tcp(params); + break; + case 'w': + dig_params_flag_nowait(params); + break; + case 'c': + if (parse_class(optarg, &(params->class_num)) + != KNOT_EOK) { + return KNOT_EINVAL; + } + break; + case 'R': + if (params_parse_num(optarg, &(params->retries)) + != KNOT_EOK) { + return KNOT_EINVAL; + } + break; + case 't': + if (parse_type(optarg, &(params->type_num), + &(params->xfr_serial)) + != KNOT_EOK) { + return KNOT_EINVAL; + } + break; + case 'W': + if (params_parse_interval(optarg, &(params->wait)) + != KNOT_EOK) { + return KNOT_EINVAL; + } + break; + default: + dig_params_help(argc, argv); + return KNOT_ENOTSUP; + } + } + + // Process non-option parameters. + switch (argc - optind) { + case 2: + if (dig_params_parse_server(params, argv[optind + 1]) + != KNOT_EOK) { + return KNOT_EINVAL; + } + case 1: // Fall through. + if (dig_params_parse_name(params, argv[optind]) + != KNOT_EOK) { + return KNOT_EINVAL; + } + break; + default: + dig_params_help(argc, argv); + return KNOT_ENOTSUP; + } + + return KNOT_EOK; +} + diff --git a/src/utils/dig/dig_params.h b/src/utils/dig/dig_params.h new file mode 100644 index 0000000000000000000000000000000000000000..37f9e84305d806f0cdc26d2fabccd906aec358ef --- /dev/null +++ b/src/utils/dig/dig_params.h @@ -0,0 +1,39 @@ +/* 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 dig_params.h + * + * \author Daniel Salzman <daniel.salzman@nic.cz> + * + * \brief Dig command line parameters. + * + * \addtogroup knot + * @{ + */ + +#ifndef _DIG__DIG_PARAMS_H_ +#define _DIG__DIG_PARAMS_H_ + +#include "utils/common/params.h" // params_t + + + +int host_params_parse(params_t *params, int argc, char *argv[]); +void host_params_clean(params_t *params); + +#endif // _DIG__DIG_PARAMS_H_ + +/*! @} */ diff --git a/src/utils/host/host_params.h b/src/utils/host/host_params.h index 2f1f4a43a472309d39d468dce22dd9ea5d45f9a4..0e5335b04b039c209a11f29af55bdbedc0270748 100644 --- a/src/utils/host/host_params.h +++ b/src/utils/host/host_params.h @@ -18,9 +18,9 @@ * * \author Daniel Salzman <daniel.salzman@nic.cz> * - * \brief Host command line parameters. + * \brief host command line parameters. * - * \addtogroup knot_utils + * \addtogroup utils * @{ */