"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/bin/tools/dnstap-read.c" (7 Sep 2020, 8612 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "dnstap-read.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  */
   11 
   12 /*
   13  * Portions of this code were adapted from dnstap-ldns:
   14  *
   15  * Copyright (c) 2014 by Farsight Security, Inc.
   16  *
   17  * Licensed under the Apache License, Version 2.0 (the "License");
   18  * you may not use this file except in compliance with the License.
   19  * You may obtain a copy of the License at
   20  *
   21  *    http://www.apache.org/licenses/LICENSE-2.0
   22  *
   23  * Unless required by applicable law or agreed to in writing, software
   24  * distributed under the License is distributed on an "AS IS" BASIS,
   25  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   26  * See the License for the specific language governing permissions and
   27  * limitations under the License.
   28  */
   29 
   30 #include <config.h>
   31 
   32 #include <inttypes.h>
   33 #include <stdbool.h>
   34 #include <stdlib.h>
   35 
   36 #include <isc/buffer.h>
   37 #include <isc/commandline.h>
   38 #include <isc/mem.h>
   39 #include <isc/print.h>
   40 #include <isc/string.h>
   41 #include <isc/util.h>
   42 
   43 #include <dns/dnstap.h>
   44 #include <dns/fixedname.h>
   45 #include <dns/masterdump.h>
   46 #include <dns/message.h>
   47 #include <dns/name.h>
   48 #include <dns/result.h>
   49 
   50 #include <protobuf-c/protobuf-c.h>
   51 #include "lib/dns/dnstap.pb-c.h"
   52 
   53 isc_mem_t *mctx = NULL;
   54 bool memrecord = false;
   55 bool printmessage = false;
   56 bool yaml = false;
   57 
   58 const char *program = "dnstap-read";
   59 
   60 #define CHECKM(op, msg) \
   61     do { result = (op);                   \
   62            if (result != ISC_R_SUCCESS) {             \
   63             fprintf(stderr,               \
   64                 "%s: %s: %s\n", program, msg,     \
   65                       isc_result_totext(result)); \
   66             goto cleanup;                 \
   67         }                         \
   68     } while (0)
   69 
   70 ISC_PLATFORM_NORETURN_PRE static void
   71 fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
   72 
   73 static void
   74 fatal(const char *format, ...) {
   75     va_list args;
   76 
   77     fprintf(stderr, "%s: fatal: ", program);
   78     va_start(args, format);
   79     vfprintf(stderr, format, args);
   80     va_end(args);
   81     fprintf(stderr, "\n");
   82     exit(1);
   83 }
   84 
   85 static void
   86 usage(void) {
   87     fprintf(stderr, "dnstap-read [-mp] [filename]\n");
   88     fprintf(stderr, "\t-m\ttrace memory allocations\n");
   89     fprintf(stderr, "\t-p\tprint the full DNS message\n");
   90     fprintf(stderr, "\t-y\tprint YAML format (implies -p)\n");
   91 }
   92 
   93 static void
   94 print_dtdata(dns_dtdata_t *dt) {
   95     isc_result_t result;
   96     isc_buffer_t *b = NULL;
   97 
   98     isc_buffer_allocate(mctx, &b, 2048);
   99     if (b == NULL)
  100         fatal("out of memory");
  101 
  102     CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext");
  103     printf("%.*s\n", (int) isc_buffer_usedlength(b),
  104            (char *) isc_buffer_base(b));
  105 
  106  cleanup:
  107     if (b != NULL)
  108         isc_buffer_free(&b);
  109 }
  110 
  111 static void
  112 print_packet(dns_dtdata_t *dt, const dns_master_style_t *style) {
  113     isc_buffer_t *b = NULL;
  114     isc_result_t result;
  115 
  116     if (dt->msg != NULL) {
  117         size_t textlen = 2048;
  118 
  119         isc_buffer_allocate(mctx, &b, textlen);
  120         if (b == NULL)
  121             fatal("out of memory");
  122 
  123         for (;;) {
  124             isc_buffer_reserve(&b, textlen);
  125             if (b == NULL)
  126                 fatal("out of memory");
  127 
  128             result = dns_message_totext(dt->msg, style, 0, b);
  129             if (result == ISC_R_NOSPACE) {
  130                 isc_buffer_clear(b);
  131                 textlen *= 2;
  132                 continue;
  133             } else if (result == ISC_R_SUCCESS) {
  134                 printf("%.*s",
  135                        (int) isc_buffer_usedlength(b),
  136                        (char *) isc_buffer_base(b));
  137                 isc_buffer_free(&b);
  138             } else {
  139                 isc_buffer_free(&b);
  140                 CHECKM(result, "dns_message_totext");
  141             }
  142             break;
  143         }
  144     }
  145 
  146  cleanup:
  147     if (b != NULL)
  148         isc_buffer_free(&b);
  149 }
  150 
  151 static void
  152 print_yaml(dns_dtdata_t *dt) {
  153     Dnstap__Dnstap *frame = dt->frame;
  154     Dnstap__Message *m = frame->message;
  155     const ProtobufCEnumValue *ftype, *mtype;
  156     static bool first = true;
  157 
  158     ftype = protobuf_c_enum_descriptor_get_value(
  159                      &dnstap__dnstap__type__descriptor,
  160                      frame->type);
  161     if (ftype == NULL)
  162         return;
  163 
  164     if (!first)
  165         printf("---\n");
  166     else
  167         first = false;
  168 
  169     printf("type: %s\n", ftype->name);
  170 
  171     if (frame->has_identity)
  172         printf("identity: %.*s\n", (int) frame->identity.len,
  173                frame->identity.data);
  174 
  175     if (frame->has_version)
  176         printf("version: %.*s\n", (int) frame->version.len,
  177                frame->version.data);
  178 
  179     if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE)
  180         return;
  181 
  182     printf("message:\n");
  183 
  184     mtype = protobuf_c_enum_descriptor_get_value(
  185                      &dnstap__message__type__descriptor,
  186                      m->type);
  187     if (mtype == NULL)
  188         return;
  189 
  190     printf("  type: %s\n", mtype->name);
  191 
  192     if (!isc_time_isepoch(&dt->qtime)) {
  193         char buf[100];
  194         isc_time_formatISO8601(&dt->qtime, buf, sizeof(buf));
  195         printf("  query_time: !!timestamp %s\n", buf);
  196     }
  197 
  198     if (!isc_time_isepoch(&dt->rtime)) {
  199         char buf[100];
  200         isc_time_formatISO8601(&dt->rtime, buf, sizeof(buf));
  201         printf("  response_time: !!timestamp %s\n", buf);
  202     }
  203 
  204     if (dt->msgdata.base != NULL) {
  205         printf("  message_size: %zub\n", (size_t) dt->msgdata.length);
  206     } else
  207         printf("  message_size: 0b\n");
  208 
  209     if (m->has_socket_family) {
  210         const ProtobufCEnumValue *type =
  211             protobuf_c_enum_descriptor_get_value(
  212                 &dnstap__socket_family__descriptor,
  213                 m->socket_family);
  214         if (type != NULL)
  215             printf("  socket_family: %s\n", type->name);
  216     }
  217 
  218     printf("  socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP");
  219 
  220     if (m->has_query_address) {
  221         ProtobufCBinaryData *ip = &m->query_address;
  222         char buf[100];
  223 
  224         (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6,
  225                 ip->data, buf, sizeof(buf));
  226         printf("  query_address: %s\n", buf);
  227     }
  228 
  229     if (m->has_response_address) {
  230         ProtobufCBinaryData *ip = &m->response_address;
  231         char buf[100];
  232 
  233         (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6,
  234                 ip->data, buf, sizeof(buf));
  235         printf("  response_address: %s\n", buf);
  236     }
  237 
  238     if (m->has_query_port)
  239         printf("  query_port: %u\n", m->query_port);
  240 
  241     if (m->has_response_port)
  242         printf("  response_port: %u\n", m->response_port);
  243 
  244     if (m->has_query_zone) {
  245         isc_result_t result;
  246         dns_fixedname_t fn;
  247         dns_name_t *name;
  248         isc_buffer_t b;
  249         dns_decompress_t dctx;
  250 
  251         name = dns_fixedname_initname(&fn);
  252 
  253         isc_buffer_init(&b, m->query_zone.data, m->query_zone.len);
  254         isc_buffer_add(&b, m->query_zone.len);
  255 
  256         dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
  257         result = dns_name_fromwire(name, &b, &dctx, 0, NULL);
  258         if (result == ISC_R_SUCCESS) {
  259             printf("  query_zone: ");
  260             dns_name_print(name, stdout);
  261             printf("\n");
  262         }
  263     }
  264 
  265     if (dt->msg != NULL) {
  266         printf("  %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
  267                      ? "query_message_data"
  268                      : "response_message_data");
  269 
  270         print_packet(dt, &dns_master_style_yaml);
  271 
  272         printf("  %s: |\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
  273                      ? "query_message"
  274                      : "response_message");
  275         print_packet(dt, &dns_master_style_indent);
  276     }
  277 };
  278 
  279 int
  280 main(int argc, char *argv[]) {
  281     isc_result_t result;
  282     dns_message_t *message = NULL;
  283     isc_buffer_t *b = NULL;
  284     dns_dtdata_t *dt = NULL;
  285     dns_dthandle_t *handle = NULL;
  286     int rv = 0, ch;
  287 
  288     while ((ch = isc_commandline_parse(argc, argv, "mpy")) != -1) {
  289         switch (ch) {
  290             case 'm':
  291                 isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
  292                 memrecord = true;
  293                 break;
  294             case 'p':
  295                 printmessage = true;
  296                 break;
  297             case 'y':
  298                 yaml = true;
  299                 dns_master_indentstr = "  ";
  300                 dns_master_indent = 2;
  301                 break;
  302             default:
  303                 usage();
  304                 exit(1);
  305         }
  306     }
  307 
  308     argc -= isc_commandline_index;
  309     argv += isc_commandline_index;
  310 
  311     if (argc < 1)
  312         fatal("no file specified");
  313 
  314     RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
  315 
  316     dns_result_register();
  317 
  318     CHECKM(dns_dt_open(argv[0], dns_dtmode_file, mctx, &handle),
  319            "dns_dt_openfile");
  320 
  321     for (;;) {
  322         isc_region_t input;
  323         uint8_t *data;
  324         size_t datalen;
  325 
  326         result = dns_dt_getframe(handle, &data, &datalen);
  327         if (result == ISC_R_NOMORE)
  328             break;
  329         else
  330             CHECKM(result, "dns_dt_getframe");
  331 
  332         input.base = data;
  333         input.length = datalen;
  334 
  335         if (b != NULL)
  336             isc_buffer_free(&b);
  337         isc_buffer_allocate(mctx, &b, 2048);
  338         if (b == NULL)
  339             fatal("out of memory");
  340 
  341         result = dns_dt_parse(mctx, &input, &dt);
  342         if (result != ISC_R_SUCCESS) {
  343             isc_buffer_free(&b);
  344             continue;
  345         }
  346 
  347         if (yaml) {
  348             print_yaml(dt);
  349         } else if (printmessage) {
  350             print_dtdata(dt);
  351             print_packet(dt, &dns_master_style_debug);
  352         } else {
  353             print_dtdata(dt);
  354         }
  355 
  356         dns_dtdata_free(&dt);
  357     }
  358 
  359  cleanup:
  360     if (dt != NULL)
  361         dns_dtdata_free(&dt);
  362     if (handle != NULL)
  363         dns_dt_close(&handle);
  364     if (message != NULL)
  365         dns_message_destroy(&message);
  366     if (b != NULL)
  367         isc_buffer_free(&b);
  368     isc_mem_destroy(&mctx);
  369 
  370     exit(rv);
  371 }