diff --git a/Knot.files b/Knot.files index b48a5a247ca7cb127672f4999e2a0fdd7ccd4877..bf9e7b8f8191a7fc9916500b35dda6a5cb24b376 100644 --- a/Knot.files +++ b/Knot.files @@ -4,18 +4,15 @@ Makefile.am README configure.ac doc/Makefile.am -doc/configuration.texi -doc/indices.texi -doc/installation.texi -doc/introduction.texi -doc/knot.texi -doc/migration.texi -doc/reference.texi -doc/requirements.texi -doc/running.texi -doc/security.texi -doc/synth_record.texi -doc/troubleshooting.texi +doc/configuration.rst +doc/index.rst +doc/installation.rst +doc/introduction.rst +doc/migration.rst +doc/reference.rst +doc/requirements.rst +doc/running.rst +doc/troubleshooting.rst libtap/Makefile.am libtap/runtests.c libtap/tap/basic.c @@ -114,6 +111,8 @@ src/knot/dnssec/zone-sign.c src/knot/dnssec/zone-sign.h src/knot/knot.h src/knot/main.c +src/knot/modules/dnstap.c +src/knot/modules/dnstap.h src/knot/modules/synth_record.c src/knot/modules/synth_record.h src/knot/nameserver/axfr.c diff --git a/scripts/update-project-files.py b/scripts/update-project-files.py index 6dcb7153a2c120849f4995f65880181803bef6c7..bc49167300632b5f0dda1b90a2dd269f51a3022a 100755 --- a/scripts/update-project-files.py +++ b/scripts/update-project-files.py @@ -7,7 +7,7 @@ SOURCES = [ # documentation "README", "KNOWN_ISSUES", - "Doxyfile*", "Doxy.file.h", "doc/*.texi", + "Doxyfile*", "Doxy.file.h", "doc/*.rst", # build-system "*.ac", "*.am", diff --git a/src/Makefile.am b/src/Makefile.am index e383ed79869ee35e9f37fd7e32bd6bdfd0c8e76d..dd31888e4f33047aa0bb79713bc2ed891d1f3bf9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -172,19 +172,19 @@ libknot_la_SOURCES = \ libknot/rdata/nsec.h \ libknot/rdata/nsec3.c \ libknot/rdata/nsec3.h \ - libknot/rdata/nsec3param.h \ - libknot/rdata/nsec3param.c \ + libknot/rdata/nsec3param.h \ + libknot/rdata/nsec3param.c \ libknot/rdata/nsec.h \ libknot/rdata/rrsig.h \ libknot/rdata/soa.h \ - libknot/rdata/tsig.c \ - libknot/rdata/tsig.h \ + libknot/rdata/tsig.c \ + libknot/rdata/tsig.h \ libknot/rrset-dump.c \ libknot/rrset-dump.h \ libknot/rdata.c \ libknot/rdata.h \ - libknot/rdataset.c \ - libknot/rdataset.h \ + libknot/rdataset.c \ + libknot/rdataset.h \ libknot/rrset.c \ libknot/rrset.h \ libknot/tsig-op.c \ @@ -242,8 +242,6 @@ libknotd_la_SOURCES = \ knot/nameserver/update.h \ knot/modules/synth_record.c \ knot/modules/synth_record.h \ - knot/modules/dnstap.c \ - knot/modules/dnstap.h \ knot/other/debug.h \ knot/server/dthreads.c \ knot/server/dthreads.h \ @@ -255,8 +253,8 @@ libknotd_la_SOURCES = \ knot/server/rrl.h \ knot/server/server.c \ knot/server/server.h \ - knot/server/net.c \ - knot/server/net.h \ + knot/server/net.c \ + knot/server/net.h \ knot/server/tcp-handler.c \ knot/server/tcp-handler.h \ knot/server/udp-handler.c \ @@ -316,6 +314,10 @@ knsupdate_LDADD = libknotus.la libknots.la libknot.la zscanner/libzscanner.la knsec3hash_LDADD = libknotus.la libknots.la libknot.la if HAVE_DNSTAP +libknotd_la_SOURCES += \ + knot/modules/dnstap.c \ + knot/modules/dnstap.h + kdig_LDADD += dnstap/libdnstap.la khost_LDADD += dnstap/libdnstap.la libknotd_la_LIBADD += dnstap/libdnstap.la diff --git a/src/knot/nameserver/query_module.c b/src/knot/nameserver/query_module.c index 1110b80e9deb0471a7f74a46751fe962659b04e6..5e9d9fcb1181a85ddbce49a324ccfa22fd39bbd5 100644 --- a/src/knot/nameserver/query_module.c +++ b/src/knot/nameserver/query_module.c @@ -4,7 +4,9 @@ /* Compiled-in module headers. */ #include "knot/modules/synth_record.h" +#if USE_DNSTAP #include "knot/modules/dnstap.h" +#endif /* Compiled-in module table. */ struct compiled_module { @@ -12,13 +14,17 @@ struct compiled_module { qmodule_load_t load; qmodule_unload_t unload; }; + /*! \note All modules should be dynamically loaded later on. */ -#define MODULE_COUNT 2 -struct compiled_module MODULES[MODULE_COUNT] = { +struct compiled_module MODULES[] = { { "synth_record", &synth_record_load, &synth_record_unload }, +#if USE_DNSTAP { "dnstap", &dnstap_load, &dnstap_unload } +#endif }; +#define MODULE_COUNT sizeof(MODULES) / sizeof(MODULES[0]) + struct query_plan *query_plan_create(mm_ctx_t *mm) { struct query_plan *plan = mm_alloc(mm, sizeof(struct query_plan)); diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c index 27f914330c33665470eb9eba4f636368ea227d89..48ca4835aa7ea4b35ee6e3f49719b4246a1ca0b2 100644 --- a/src/utils/dig/dig_exec.c +++ b/src/utils/dig/dig_exec.c @@ -26,7 +26,7 @@ #include "common/print.h" // time_diff #include "common/errcode.h" // KNOT_EOK #include "common/descriptor.h" // KNOT_RRTYPE_ -#include "common/sockaddr.h" +#include "common/sockaddr.h" // sockaddr_set_raw #include "utils/common/msg.h" // WARN #include "utils/common/netio.h" // get_socktype #include "utils/common/exec.h" // print_packet @@ -34,7 +34,182 @@ #if USE_DNSTAP # include "dnstap/message.h" # include "dnstap/writer.h" -#endif + +static int dump_dnstap(dt_writer_t *writer, + const Dnstap__Message__Type msg_type, + const uint8_t *wire, + const size_t wire_len, + net_t *net, + const struct timeval *qtime, + const struct timeval *rtime) +{ + const struct sockaddr *qa = NULL; + const struct sockaddr *ra = NULL; + Dnstap__Message msg; + int ret; + + if (writer == NULL) { + return KNOT_EOK; + } + + net_set_local_info(net); + + if (msg_type == DNSTAP__MESSAGE__TYPE__TOOL_QUERY) { + qa = net->srv->ai_addr; + ra = net->local_info->ai_addr; + } else if (msg_type == DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE) { + qa = net->local_info->ai_addr; + ra = net->srv->ai_addr; + } + + ret = dt_message_fill(&msg, msg_type, qa, ra, + net->srv->ai_protocol, wire, wire_len, + qtime, rtime); + if (ret != KNOT_EOK) { + return ret; + } + + return dt_writer_write(writer, (const ProtobufCMessage *) &msg); +} + +static float get_query_time(const Dnstap__Dnstap *frame) +{ + struct timeval from = { + .tv_sec = frame->message->query_time_sec, + .tv_usec = frame->message->query_time_nsec / 1000 + }; + + struct timeval to = { + .tv_sec = frame->message->response_time_sec, + .tv_usec = frame->message->response_time_nsec / 1000 + }; + + return time_diff(&from, &to); +} + +static void process_dnstap(const query_t *query) +{ + dt_reader_t *reader = query->dt_reader; + int ret; + + if (query->dt_reader == NULL) { + return; + } + + for (;;) { + Dnstap__Dnstap *frame = NULL; + ProtobufCBinaryData *msg = NULL; + bool is_response; + + // Read next message. + ret = dt_reader_read(reader, &frame); + if (ret == KNOT_EOF) { + break; + } else if (ret != KNOT_EOK) { + ERR("can't read dnstap message\n"); + break; + } + + // Check for dnstap message. + if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE) { + WARN("ignoring non-dnstap message\n"); + dt_reader_free_frame(reader, &frame); + continue; + } + + // Check for the type of dnstap message. + if (frame->message->has_response_message) { + msg = &frame->message->response_message; + is_response = true; + } else if (frame->message->has_query_message) { + if (!query->style.show_query) { + dt_reader_free_frame(reader, &frame); + continue; + } + msg = &frame->message->query_message; + is_response = false; + } else { + WARN("unsupported dnstap message\n"); + dt_reader_free_frame(reader, &frame); + continue; + } + + // Create dns packet based on dnstap wire data. + knot_pkt_t *pkt = knot_pkt_new(msg->data, msg->len, NULL); + if (pkt == NULL) { + ERR("can't allocate packet\n"); + dt_reader_free_frame(reader, &frame); + break; + } + + // Parse packet and reconstruct required data. + if (knot_pkt_parse(pkt, 0) == KNOT_EOK) { + ProtobufCBinaryData *addr = NULL; + uint32_t port = 0; + time_t timestamp = 0; + float query_time = 0.0; + net_t net_ctx = { 0 }; + + if (is_response) { + addr = &frame->message->response_address; + port = frame->message->response_port; + + timestamp = frame->message->response_time_sec; + query_time = get_query_time(frame); + } else { + addr = &frame->message->query_address; + port = frame->message->query_port; + + timestamp = frame->message->query_time_sec; + } + + // Prepare connection information string. + if (addr->data != NULL && + frame->message->has_socket_family && + frame->message->has_socket_protocol) { + struct sockaddr_storage ss; + int family = AF_UNSPEC, proto = 0; + + switch (frame->message->socket_family) { + case DNSTAP__SOCKET_FAMILY__INET: + family = AF_INET; + break; + case DNSTAP__SOCKET_FAMILY__INET6: + family = AF_INET6; + break; + default: + break; + } + + switch (frame->message->socket_protocol) { + case DNSTAP__SOCKET_PROTOCOL__UDP: + proto = SOCK_DGRAM; + break; + case DNSTAP__SOCKET_PROTOCOL__TCP: + proto = SOCK_STREAM; + break; + default: + break; + } + + sockaddr_set_raw(&ss, family, addr->data); + sockaddr_port_set(&ss, port); + get_addr_str(&ss, proto, &net_ctx.remote_str); + } + + print_packet(pkt, &net_ctx, pkt->size, query_time, + timestamp, is_response, &query->style); + + net_clean(&net_ctx); + } else { + ERR("can't print dnstap message\n"); + } + + knot_pkt_free(&pkt); + dt_reader_free_frame(reader, &frame); + } +} +#endif // USE_DNSTAP static knot_pkt_t* create_query_packet(const query_t *query) { @@ -268,46 +443,6 @@ static bool last_serial_check(const uint32_t serial, const knot_pkt_t *reply) } } -static int dump_dnstap(dt_writer_t *writer, - const Dnstap__Message__Type msg_type, - const uint8_t *wire, - const size_t wire_len, - net_t *net, - const struct timeval *qtime, - const struct timeval *rtime) -{ -#if USE_DNSTAP - const struct sockaddr *qa = NULL; - const struct sockaddr *ra = NULL; - Dnstap__Message msg; - int ret; - - if (writer == NULL) { - return KNOT_EOK; - } - - net_set_local_info(net); - - if (msg_type == DNSTAP__MESSAGE__TYPE__TOOL_QUERY) { - qa = net->srv->ai_addr; - ra = net->local_info->ai_addr; - } else if (msg_type == DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE) { - qa = net->local_info->ai_addr; - ra = net->srv->ai_addr; - } - - ret = dt_message_fill(&msg, msg_type, qa, ra, - net->srv->ai_protocol, wire, wire_len, - qtime, rtime); - if (ret != KNOT_EOK) { - return ret; - } - - return dt_writer_write(writer, (const ProtobufCMessage *) &msg); -#endif - return KNOT_EOK; -} - static int process_query_packet(const knot_pkt_t *query, net_t *net, const query_t *query_ctx, @@ -341,10 +476,12 @@ static int process_query_packet(const knot_pkt_t *query, // Get stop query time and start reply time. gettimeofday(&t_query, NULL); +#if USE_DNSTAP // Make the dnstap copy of the query. dump_dnstap(query_ctx->dt_writer, DNSTAP__MESSAGE__TYPE__TOOL_QUERY, query->wire, query->size, net, &t_query, NULL); +#endif // USE_DNSTAP // Print query packet if required. if (style->show_query) { @@ -378,10 +515,12 @@ static int process_query_packet(const knot_pkt_t *query, // Get stop reply time. gettimeofday(&t_end, NULL); +#if USE_DNSTAP // Make the dnstap copy of the response. dump_dnstap(query_ctx->dt_writer, DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE, in, in_len, net, &t_query, &t_end); +#endif // USE_DNSTAP // Create reply packet structure to fill up. reply = knot_pkt_new(in, in_len, NULL); @@ -590,10 +729,12 @@ static int process_xfr_packet(const knot_pkt_t *query, // Get stop query time and start reply time. gettimeofday(&t_query, NULL); +#if USE_DNSTAP // Make the dnstap copy of the query. dump_dnstap(query_ctx->dt_writer, DNSTAP__MESSAGE__TYPE__TOOL_QUERY, query->wire, query->size, net, &t_query, NULL); +#endif // USE_DNSTAP // Print query packet if required. if (style->show_query) { @@ -618,10 +759,12 @@ static int process_xfr_packet(const knot_pkt_t *query, // Get stop message time. gettimeofday(&t_end, NULL); +#if USE_DNSTAP // Make the dnstap copy of the response. dump_dnstap(query_ctx->dt_writer, DNSTAP__MESSAGE__TYPE__TOOL_RESPONSE, in, in_len, net, &t_query, &t_end); +#endif // USE_DNSTAP // Create reply packet structure to fill up. reply = knot_pkt_new(in, in_len, NULL); @@ -782,148 +925,6 @@ static void process_xfr(const query_t *query) knot_pkt_free(&out_packet); } -#if USE_DNSTAP -static float get_query_time(const Dnstap__Dnstap *frame) -{ - struct timeval from = { - .tv_sec = frame->message->query_time_sec, - .tv_usec = frame->message->query_time_nsec / 1000 - }; - - struct timeval to = { - .tv_sec = frame->message->response_time_sec, - .tv_usec = frame->message->response_time_nsec / 1000 - }; - - return time_diff(&from, &to); -} -#endif - -static void process_dnstap(const query_t *query) -{ -#if USE_DNSTAP - dt_reader_t *reader = query->dt_reader; - int ret; - - if (query->dt_reader == NULL) { - return; - } - - for (;;) { - Dnstap__Dnstap *frame = NULL; - ProtobufCBinaryData *msg = NULL; - bool is_response; - - // Read next message. - ret = dt_reader_read(reader, &frame); - if (ret == KNOT_EOF) { - break; - } else if (ret != KNOT_EOK) { - ERR("can't read dnstap message\n"); - break; - } - - // Check for dnstap message. - if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE) { - WARN("ignoring non-dnstap message\n"); - dt_reader_free_frame(reader, &frame); - continue; - } - - // Check for the type of dnstap message. - if (frame->message->has_response_message) { - msg = &frame->message->response_message; - is_response = true; - } else if (frame->message->has_query_message) { - if (!query->style.show_query) { - dt_reader_free_frame(reader, &frame); - continue; - } - msg = &frame->message->query_message; - is_response = false; - } else { - WARN("unsupported dnstap message\n"); - dt_reader_free_frame(reader, &frame); - continue; - } - - // Create dns packet based on dnstap wire data. - knot_pkt_t *pkt = knot_pkt_new(msg->data, msg->len, NULL); - if (pkt == NULL) { - ERR("can't allocate packet\n"); - dt_reader_free_frame(reader, &frame); - break; - } - - // Parse packet and reconstruct required data. - if (knot_pkt_parse(pkt, 0) == KNOT_EOK) { - ProtobufCBinaryData *addr = NULL; - uint32_t port = 0; - time_t timestamp = 0; - float query_time = 0.0; - net_t net_ctx = { 0 }; - - if (is_response) { - addr = &frame->message->response_address; - port = frame->message->response_port; - - timestamp = frame->message->response_time_sec; - query_time = get_query_time(frame); - } else { - addr = &frame->message->query_address; - port = frame->message->query_port; - - timestamp = frame->message->query_time_sec; - } - - // Prepare connection information string. - if (addr->data != NULL && - frame->message->has_socket_family && - frame->message->has_socket_protocol) { - struct sockaddr_storage ss; - int family = AF_UNSPEC, proto = 0; - - switch (frame->message->socket_family) { - case DNSTAP__SOCKET_FAMILY__INET: - family = AF_INET; - break; - case DNSTAP__SOCKET_FAMILY__INET6: - family = AF_INET6; - break; - default: - break; - } - - switch (frame->message->socket_protocol) { - case DNSTAP__SOCKET_PROTOCOL__UDP: - proto = SOCK_DGRAM; - break; - case DNSTAP__SOCKET_PROTOCOL__TCP: - proto = SOCK_STREAM; - break; - default: - break; - } - - sockaddr_set_raw(&ss, family, addr->data); - sockaddr_port_set(&ss, port); - get_addr_str(&ss, proto, &net_ctx.remote_str); - } - - print_packet(pkt, &net_ctx, pkt->size, query_time, - timestamp, is_response, &query->style); - - net_clean(&net_ctx); - } else { - ERR("can't print dnstap message\n"); - } - - knot_pkt_free(&pkt); - dt_reader_free_frame(reader, &frame); - } -#endif -} - int dig_exec(const dig_params_t *params) { node_t *n = NULL; @@ -944,9 +945,11 @@ int dig_exec(const dig_params_t *params) case OPERATION_XFR: process_xfr(query); break; +#if USE_DNSTAP case OPERATION_LIST_DNSTAP: process_dnstap(query); break; +#endif // USE_DNSTAP case OPERATION_LIST_SOA: break; default: diff --git a/src/utils/dig/dig_params.c b/src/utils/dig/dig_params.c index b714dd715d882c5f07f8547b04d2741ac76f5f3e..34b2c8afc5401687cb7b7ea926f4d38d2af256ce 100644 --- a/src/utils/dig/dig_params.c +++ b/src/utils/dig/dig_params.c @@ -797,7 +797,7 @@ query_t* query_create(const char *owner, const query_t *conf) #if USE_DNSTAP query->dt_reader = NULL; query->dt_writer = NULL; -#endif +#endif // USE_DNSTAP } else { query->conf = conf; if (conf->local != NULL) { @@ -831,7 +831,7 @@ query_t* query_create(const char *owner, const query_t *conf) #if USE_DNSTAP query->dt_reader = conf->dt_reader; query->dt_writer = conf->dt_writer; -#endif +#endif // USE_DNSTAP if (knot_copy_key_params(&conf->key_params, &query->key_params) != KNOT_EOK) { @@ -883,7 +883,7 @@ void query_free(query_t *query) dt_writer_free(query->dt_writer); } } -#endif +#endif // USE_DNSTAP free(query->owner); free(query->port); @@ -1141,7 +1141,7 @@ static int parse_dnstap_input(const char *value, query_t *query) return KNOT_EOK; } -#endif +#endif // USE_DNSTAP static void complete_servers(query_t *query, const query_t *conf) { @@ -1472,7 +1472,7 @@ static int parse_opt1(const char *opt, const char *value, dig_params_t *params, #else ERR("no dnstap support but -E specified\n"); return KNOT_EINVAL; -#endif +#endif // USE_DNSTAP break; case 'G': #if USE_DNSTAP @@ -1498,7 +1498,7 @@ static int parse_opt1(const char *opt, const char *value, dig_params_t *params, #else ERR("no dnstap support but -G specified\n"); return KNOT_EINVAL; -#endif +#endif // USE_DNSTAP break; case '-': if (strcmp(opt, "-help") == 0) { diff --git a/src/utils/dig/dig_params.h b/src/utils/dig/dig_params.h index c1d6a446785820637b82c34e8693d26b8261a438..0a953779e56a32ac9dd407b839bec29b39267ff2 100644 --- a/src/utils/dig/dig_params.h +++ b/src/utils/dig/dig_params.h @@ -35,7 +35,7 @@ #if USE_DNSTAP # include "dnstap/reader.h" # include "dnstap/writer.h" -#endif +#endif // USE_DNSTAP #define KDIG_VERSION "kdig, version " PACKAGE_VERSION "\n" @@ -129,7 +129,7 @@ struct query { dt_reader_t *dt_reader; /*!< Context for dnstap writer output. */ dt_writer_t *dt_writer; -#endif +#endif // USE_DNSTAP }; /*! \brief Settings for dig. */