"Fossies" - the Fresh Open Source Software Archive

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