"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.16.7/bin/tools/dnstap-read.c" (4 Sep 2020, 9559 Bytes) of package /linux/misc/dns/bind9/9.16.7/bind-9.16.7.tar.xz:


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 <inttypes.h>
   31 #include <stdbool.h>
   32 #include <stdlib.h>
   33 
   34 #include <protobuf-c/protobuf-c.h>
   35 
   36 #include <isc/buffer.h>
   37 #include <isc/commandline.h>
   38 #include <isc/hex.h>
   39 #include <isc/mem.h>
   40 #include <isc/print.h>
   41 #include <isc/string.h>
   42 #include <isc/util.h>
   43 
   44 #include <dns/dnstap.h>
   45 #include <dns/fixedname.h>
   46 #include <dns/masterdump.h>
   47 #include <dns/message.h>
   48 #include <dns/name.h>
   49 #include <dns/result.h>
   50 
   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 hexmessage = false;
   57 bool yaml = false;
   58 
   59 const char *program = "dnstap-read";
   60 
   61 #define CHECKM(op, msg)                                               \
   62     do {                                                          \
   63         result = (op);                                        \
   64         if (result != ISC_R_SUCCESS) {                        \
   65             fprintf(stderr, "%s: %s: %s\n", program, msg, \
   66                 isc_result_totext(result));           \
   67             goto cleanup;                                 \
   68         }                                                     \
   69     } while (0)
   70 
   71 ISC_PLATFORM_NORETURN_PRE static void
   72 fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
   73 
   74 static void
   75 fatal(const char *format, ...) {
   76     va_list args;
   77 
   78     fprintf(stderr, "%s: fatal: ", program);
   79     va_start(args, format);
   80     vfprintf(stderr, format, args);
   81     va_end(args);
   82     fprintf(stderr, "\n");
   83     exit(1);
   84 }
   85 
   86 static void
   87 usage(void) {
   88     fprintf(stderr, "dnstap-read [-mpxy] [filename]\n");
   89     fprintf(stderr, "\t-m\ttrace memory allocations\n");
   90     fprintf(stderr, "\t-p\tprint the full DNS message\n");
   91     fprintf(stderr, "\t-x\tuse hex format to print DNS message\n");
   92     fprintf(stderr, "\t-y\tprint YAML format (implies -p)\n");
   93 }
   94 
   95 static void
   96 print_dtdata(dns_dtdata_t *dt) {
   97     isc_result_t result;
   98     isc_buffer_t *b = NULL;
   99 
  100     isc_buffer_allocate(mctx, &b, 2048);
  101     if (b == NULL) {
  102         fatal("out of memory");
  103     }
  104 
  105     CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext");
  106     printf("%.*s\n", (int)isc_buffer_usedlength(b),
  107            (char *)isc_buffer_base(b));
  108 
  109 cleanup:
  110     if (b != NULL) {
  111         isc_buffer_free(&b);
  112     }
  113 }
  114 
  115 static void
  116 print_hex(dns_dtdata_t *dt) {
  117     isc_buffer_t *b = NULL;
  118     isc_result_t result;
  119     size_t textlen;
  120 
  121     if (dt->msg == NULL) {
  122         return;
  123     }
  124 
  125     textlen = (dt->msgdata.length * 2) + 1;
  126     isc_buffer_allocate(mctx, &b, textlen);
  127     if (b == NULL) {
  128         fatal("out of memory");
  129     }
  130 
  131     result = isc_hex_totext(&dt->msgdata, 0, "", b);
  132     CHECKM(result, "isc_hex_totext");
  133 
  134     printf("%.*s\n", (int)isc_buffer_usedlength(b),
  135            (char *)isc_buffer_base(b));
  136 
  137 cleanup:
  138     if (b != NULL) {
  139         isc_buffer_free(&b);
  140     }
  141 }
  142 
  143 static void
  144 print_packet(dns_dtdata_t *dt, const dns_master_style_t *style) {
  145     isc_buffer_t *b = NULL;
  146     isc_result_t result;
  147 
  148     if (dt->msg != NULL) {
  149         size_t textlen = 2048;
  150 
  151         isc_buffer_allocate(mctx, &b, textlen);
  152         if (b == NULL) {
  153             fatal("out of memory");
  154         }
  155 
  156         for (;;) {
  157             isc_buffer_reserve(&b, textlen);
  158             if (b == NULL) {
  159                 fatal("out of memory");
  160             }
  161 
  162             result = dns_message_totext(dt->msg, style, 0, b);
  163             if (result == ISC_R_NOSPACE) {
  164                 isc_buffer_clear(b);
  165                 textlen *= 2;
  166                 continue;
  167             } else if (result == ISC_R_SUCCESS) {
  168                 printf("%.*s", (int)isc_buffer_usedlength(b),
  169                        (char *)isc_buffer_base(b));
  170                 isc_buffer_free(&b);
  171             } else {
  172                 isc_buffer_free(&b);
  173                 CHECKM(result, "dns_message_totext");
  174             }
  175             break;
  176         }
  177     }
  178 
  179 cleanup:
  180     if (b != NULL) {
  181         isc_buffer_free(&b);
  182     }
  183 }
  184 
  185 static void
  186 print_yaml(dns_dtdata_t *dt) {
  187     Dnstap__Dnstap *frame = dt->frame;
  188     Dnstap__Message *m = frame->message;
  189     const ProtobufCEnumValue *ftype, *mtype;
  190     static bool first = true;
  191 
  192     ftype = protobuf_c_enum_descriptor_get_value(
  193         &dnstap__dnstap__type__descriptor, frame->type);
  194     if (ftype == NULL) {
  195         return;
  196     }
  197 
  198     if (!first) {
  199         printf("---\n");
  200     } else {
  201         first = false;
  202     }
  203 
  204     printf("type: %s\n", ftype->name);
  205 
  206     if (frame->has_identity) {
  207         printf("identity: %.*s\n", (int)frame->identity.len,
  208                frame->identity.data);
  209     }
  210 
  211     if (frame->has_version) {
  212         printf("version: %.*s\n", (int)frame->version.len,
  213                frame->version.data);
  214     }
  215 
  216     if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE) {
  217         return;
  218     }
  219 
  220     printf("message:\n");
  221 
  222     mtype = protobuf_c_enum_descriptor_get_value(
  223         &dnstap__message__type__descriptor, m->type);
  224     if (mtype == NULL) {
  225         return;
  226     }
  227 
  228     printf("  type: %s\n", mtype->name);
  229 
  230     if (!isc_time_isepoch(&dt->qtime)) {
  231         char buf[100];
  232         isc_time_formatISO8601(&dt->qtime, buf, sizeof(buf));
  233         printf("  query_time: !!timestamp %s\n", buf);
  234     }
  235 
  236     if (!isc_time_isepoch(&dt->rtime)) {
  237         char buf[100];
  238         isc_time_formatISO8601(&dt->rtime, buf, sizeof(buf));
  239         printf("  response_time: !!timestamp %s\n", buf);
  240     }
  241 
  242     if (dt->msgdata.base != NULL) {
  243         printf("  message_size: %zub\n", (size_t)dt->msgdata.length);
  244     } else {
  245         printf("  message_size: 0b\n");
  246     }
  247 
  248     if (m->has_socket_family) {
  249         const ProtobufCEnumValue *type =
  250             protobuf_c_enum_descriptor_get_value(
  251                 &dnstap__socket_family__descriptor,
  252                 m->socket_family);
  253         if (type != NULL) {
  254             printf("  socket_family: %s\n", type->name);
  255         }
  256     }
  257 
  258     printf("  socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP");
  259 
  260     if (m->has_query_address) {
  261         ProtobufCBinaryData *ip = &m->query_address;
  262         char buf[100];
  263 
  264         (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data,
  265                 buf, sizeof(buf));
  266         printf("  query_address: %s\n", buf);
  267     }
  268 
  269     if (m->has_response_address) {
  270         ProtobufCBinaryData *ip = &m->response_address;
  271         char buf[100];
  272 
  273         (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data,
  274                 buf, sizeof(buf));
  275         printf("  response_address: %s\n", buf);
  276     }
  277 
  278     if (m->has_query_port) {
  279         printf("  query_port: %u\n", m->query_port);
  280     }
  281 
  282     if (m->has_response_port) {
  283         printf("  response_port: %u\n", m->response_port);
  284     }
  285 
  286     if (m->has_query_zone) {
  287         isc_result_t result;
  288         dns_fixedname_t fn;
  289         dns_name_t *name;
  290         isc_buffer_t b;
  291         dns_decompress_t dctx;
  292 
  293         name = dns_fixedname_initname(&fn);
  294 
  295         isc_buffer_init(&b, m->query_zone.data, m->query_zone.len);
  296         isc_buffer_add(&b, m->query_zone.len);
  297 
  298         dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
  299         result = dns_name_fromwire(name, &b, &dctx, 0, NULL);
  300         if (result == ISC_R_SUCCESS) {
  301             printf("  query_zone: ");
  302             dns_name_print(name, stdout);
  303             printf("\n");
  304         }
  305     }
  306 
  307     if (dt->msg != NULL) {
  308         dt->msg->indent.count = 2;
  309         dt->msg->indent.string = "  ";
  310         printf("  %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
  311                       ? "query_message_data"
  312                       : "response_message_data");
  313 
  314         print_packet(dt, &dns_master_style_yaml);
  315 
  316         printf("  %s: |\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
  317                         ? "query_message"
  318                         : "response_message");
  319         print_packet(dt, &dns_master_style_indent);
  320     }
  321 }
  322 
  323 int
  324 main(int argc, char *argv[]) {
  325     isc_result_t result;
  326     dns_message_t *message = NULL;
  327     isc_buffer_t *b = NULL;
  328     dns_dtdata_t *dt = NULL;
  329     dns_dthandle_t *handle = NULL;
  330     int rv = 0, ch;
  331 
  332     while ((ch = isc_commandline_parse(argc, argv, "mpxy")) != -1) {
  333         switch (ch) {
  334         case 'm':
  335             isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
  336             memrecord = true;
  337             break;
  338         case 'p':
  339             printmessage = true;
  340             break;
  341         case 'x':
  342             hexmessage = true;
  343             break;
  344         case 'y':
  345             yaml = true;
  346             break;
  347         default:
  348             usage();
  349             exit(1);
  350         }
  351     }
  352 
  353     argc -= isc_commandline_index;
  354     argv += isc_commandline_index;
  355 
  356     if (argc < 1) {
  357         fatal("no file specified");
  358     }
  359 
  360     isc_mem_create(&mctx);
  361 
  362     dns_result_register();
  363 
  364     CHECKM(dns_dt_open(argv[0], dns_dtmode_file, mctx, &handle),
  365            "dns_dt_openfile");
  366 
  367     for (;;) {
  368         isc_region_t input;
  369         uint8_t *data;
  370         size_t datalen;
  371 
  372         result = dns_dt_getframe(handle, &data, &datalen);
  373         if (result == ISC_R_NOMORE) {
  374             break;
  375         } else {
  376             CHECKM(result, "dns_dt_getframe");
  377         }
  378 
  379         input.base = data;
  380         input.length = datalen;
  381 
  382         if (b != NULL) {
  383             isc_buffer_free(&b);
  384         }
  385         isc_buffer_allocate(mctx, &b, 2048);
  386         if (b == NULL) {
  387             fatal("out of memory");
  388         }
  389 
  390         result = dns_dt_parse(mctx, &input, &dt);
  391         if (result != ISC_R_SUCCESS) {
  392             isc_buffer_free(&b);
  393             continue;
  394         }
  395 
  396         if (yaml) {
  397             print_yaml(dt);
  398         } else if (hexmessage) {
  399             print_dtdata(dt);
  400             print_hex(dt);
  401         } else if (printmessage) {
  402             print_dtdata(dt);
  403             print_packet(dt, &dns_master_style_debug);
  404         } else {
  405             print_dtdata(dt);
  406         }
  407 
  408         dns_dtdata_free(&dt);
  409     }
  410 
  411 cleanup:
  412     if (dt != NULL) {
  413         dns_dtdata_free(&dt);
  414     }
  415     if (handle != NULL) {
  416         dns_dt_close(&handle);
  417     }
  418     if (message != NULL) {
  419         dns_message_destroy(&message);
  420     }
  421     if (b != NULL) {
  422         isc_buffer_free(&b);
  423     }
  424     isc_mem_destroy(&mctx);
  425 
  426     exit(rv);
  427 }