From: wpk Date: Wed, 28 Dec 2016 09:06:40 +0000 (+0100) Subject: 4545. [func] Make dnstap-read output more functionally usable. X-Git-Tag: v9.12.0a1~585 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=e910d1800754df3be06be4bb0bf78550fcaa9e96;p=thirdparty%2Fbind9.git 4545. [func] Make dnstap-read output more functionally usable. [RT #43642] 4544. [func] Add message/payload size to dnstap-read YAML output. [RT #43622] --- diff --git a/CHANGES b/CHANGES index 33c581d9c59..99912796bba 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,9 @@ +4545. [func] Make dnstap-read output more functionally usable. + [RT #43642] + +4544. [func] Add message/payload size to dnstap-read YAML output. + [RT #43622] + 4543. [bug] dns_client_startupdate now delays sending the update request until isc_app_ctxrun has been called. [RT #43976] diff --git a/bin/tests/system/dnstap/ns2/example.db b/bin/tests/system/dnstap/ns2/example.db index 4073cbee4e8..8cb4da36116 100644 --- a/bin/tests/system/dnstap/ns2/example.db +++ b/bin/tests/system/dnstap/ns2/example.db @@ -18,6 +18,8 @@ ns2.example. A 10.53.0.2 $ORIGIN example. a A 10.0.0.1 +a A 10.0.0.3 +a A 10.0.0.5 MX 10 mail.example. mail A 10.0.0.2 diff --git a/bin/tests/system/dnstap/tests.sh b/bin/tests/system/dnstap/tests.sh index 45f622b056c..06fc24a9420 100644 --- a/bin/tests/system/dnstap/tests.sh +++ b/bin/tests/system/dnstap/tests.sh @@ -344,6 +344,18 @@ ret=0 if [ $ret != 0 ]; then echo "I: failed"; fi status=`expr $status + $ret` +HAS_PYYAML=0 +if [ -n "$PYTHON" ] ; then + $PYTHON -c "import yaml" && HAS_PYYAML=1 +fi + +if [ $HAS_PYYAML ] ; then + echo "I:checking dnstap-read YAML output" + ret=0 + $PYTHON ydump.py "$DNSTAPREAD" "ns3/dnstap.out.save" > /dev/null || ret=1 + if [ $ret != 0 ]; then echo "I: failed"; fi + status=`expr $status + $ret` +fi if [ -n "$FSTRM_CAPTURE" ] ; then $DIG +short @10.53.0.4 -p 5300 a.example > dig.out diff --git a/bin/tests/system/dnstap/ydump.py b/bin/tests/system/dnstap/ydump.py new file mode 100644 index 00000000000..1ce4783f4d3 --- /dev/null +++ b/bin/tests/system/dnstap/ydump.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +try: + import yaml +except: + print "I: No python yaml module, skipping" + exit(1) + +import subprocess +import pprint +import sys + +DNSTAP_READ=sys.argv[1] +DATAFILE=sys.argv[2] + +f = subprocess.Popen([DNSTAP_READ, '-y', DATAFILE], stdout=subprocess.PIPE) +pprint.pprint([l for l in yaml.load_all(f.stdout)]) diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c index 5bda5cc99e5..585a1dfb32d 100644 --- a/bin/tools/dnstap-read.c +++ b/bin/tools/dnstap-read.c @@ -83,10 +83,68 @@ usage(void) { } static void -print_yaml(dns_dtdata_t *d) { - Dnstap__Dnstap *frame = d->frame; +print_dtdata(dns_dtdata_t *dt) { + isc_result_t result; + isc_buffer_t *b = NULL; + + isc_buffer_allocate(mctx, &b, 2048); + if (b == NULL) + fatal("out of memory"); + + CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext"); + printf("%.*s\n", (int) isc_buffer_usedlength(b), + (char *) isc_buffer_base(b)); + + cleanup: + if (b != NULL) + isc_buffer_free(&b); +} + +static void +print_packet(dns_dtdata_t *dt, const dns_master_style_t *style) { + isc_buffer_t *b = NULL; + isc_result_t result; + + if (dt->msg != NULL) { + size_t textlen = 2048; + + isc_buffer_allocate(mctx, &b, textlen); + if (b == NULL) + fatal("out of memory"); + + for (;;) { + isc_buffer_reserve(&b, textlen); + if (b == NULL) + fatal("out of memory"); + + result = dns_message_totext(dt->msg, style, 0, b); + if (result == ISC_R_NOSPACE) { + textlen *= 2; + continue; + } else if (result == ISC_R_SUCCESS) { + printf("%.*s", + (int) isc_buffer_usedlength(b), + (char *) isc_buffer_base(b)); + isc_buffer_free(&b); + } else { + isc_buffer_free(&b); + CHECKM(result, "dns_message_totext"); + } + break; + } + } + + cleanup: + if (b != NULL) + isc_buffer_free(&b); +} + +static void +print_yaml(dns_dtdata_t *dt) { + Dnstap__Dnstap *frame = dt->frame; Dnstap__Message *m = frame->message; const ProtobufCEnumValue *ftype, *mtype; + static isc_boolean_t first = ISC_TRUE; ftype = protobuf_c_enum_descriptor_get_value( &dnstap__dnstap__type__descriptor, @@ -94,6 +152,11 @@ print_yaml(dns_dtdata_t *d) { if (ftype == NULL) return; + if (!first) + printf("---\n"); + else + first = ISC_FALSE; + printf("type: %s\n", ftype->name); if (frame->has_identity) @@ -117,18 +180,23 @@ print_yaml(dns_dtdata_t *d) { printf(" type: %s\n", mtype->name); - if (!isc_time_isepoch(&d->qtime)) { + if (!isc_time_isepoch(&dt->qtime)) { char buf[100]; - isc_time_formatISO8601(&d->qtime, buf, sizeof(buf)); + isc_time_formatISO8601(&dt->qtime, buf, sizeof(buf)); printf(" query_time: !!timestamp %s\n", buf); } - if (!isc_time_isepoch(&d->rtime)) { + if (!isc_time_isepoch(&dt->rtime)) { char buf[100]; - isc_time_formatISO8601(&d->rtime, buf, sizeof(buf)); + isc_time_formatISO8601(&dt->rtime, buf, sizeof(buf)); printf(" response_time: !!timestamp %s\n", buf); } + if (dt->msgdata.base != NULL) { + printf(" message_size: %zdb\n", (size_t) dt->msgdata.length); + } else + printf(" message_size: 0b\n"); + if (m->has_socket_family) { const ProtobufCEnumValue *type = protobuf_c_enum_descriptor_get_value( @@ -138,7 +206,7 @@ print_yaml(dns_dtdata_t *d) { printf(" socket_family: %s\n", type->name); } - printf(" socket_protocol: %s\n", d->tcp ? "TCP" : "UDP"); + printf(" socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP"); if (m->has_query_address) { ProtobufCBinaryData *ip = &m->query_address; @@ -186,9 +254,18 @@ print_yaml(dns_dtdata_t *d) { } } - if (d->msg != NULL) - printf(" %s: |\n", ((d->type & DNS_DTTYPE_QUERY) != 0) - ? "query_message" : "response_message"); + if (dt->msg != NULL) { + printf(" %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0) + ? "query_message_data" + : "response_message_data"); + + print_packet(dt, &dns_master_style_yaml); + + printf(" %s: |\n", ((dt->type & DNS_DTTYPE_QUERY) != 0) + ? "query_message" + : "response_message"); + print_packet(dt, &dns_master_style_indent); + } }; int @@ -197,7 +274,6 @@ main(int argc, char *argv[]) { dns_message_t *message = NULL; isc_buffer_t *b = NULL; dns_dtdata_t *dt = NULL; - const dns_master_style_t *style = &dns_master_style_debug; dns_dthandle_t *handle = NULL; int rv = 0, ch; @@ -212,9 +288,8 @@ main(int argc, char *argv[]) { break; case 'y': yaml = ISC_TRUE; - style = &dns_master_style_indent; - dns_master_indentstr = " "; - printmessage = ISC_TRUE; + dns_master_indentstr = " "; + dns_master_indent = 2; break; default: usage(); @@ -261,44 +336,15 @@ main(int argc, char *argv[]) { continue; } - if (yaml) + if (yaml) { print_yaml(dt); - else { - CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext"); - printf("%.*s\n", (int) isc_buffer_usedlength(b), - (char *) isc_buffer_base(b)); + } else if (printmessage) { + print_dtdata(dt); + print_packet(dt, &dns_master_style_debug); + } else { + print_dtdata(dt); } - if (printmessage && dt->msg != NULL) { - size_t textlen = 2048; - - isc_buffer_clear(b); - - for (;;) { - isc_buffer_reserve(&b, textlen); - if (b == NULL) - fatal("out of memory"); - result = dns_message_totext(dt->msg, style, - 0, b); - if (result == ISC_R_NOSPACE) { - textlen *= 2; - continue; - } else if (result == ISC_R_SUCCESS) { - printf("%.*s", - (int) isc_buffer_usedlength(b), - (char *) isc_buffer_base(b)); - isc_buffer_free(&b); - } else { - isc_buffer_free(&b); - CHECKM(result, "dns_message_totext"); - } - break; - } - } - - if (yaml) - printf("---\n"); - dns_dtdata_free(&dt); } diff --git a/bin/tools/dnstap-read.docbook b/bin/tools/dnstap-read.docbook index 3dfef705751..f8706fe2527 100644 --- a/bin/tools/dnstap-read.docbook +++ b/bin/tools/dnstap-read.docbook @@ -86,7 +86,7 @@ Print dnstap data in a detailed YAML - format. Implies . + format. diff --git a/lib/dns/include/dns/masterdump.h b/lib/dns/include/dns/masterdump.h index 4e01ea9ce01..84fd5671b75 100644 --- a/lib/dns/include/dns/masterdump.h +++ b/lib/dns/include/dns/masterdump.h @@ -103,6 +103,9 @@ typedef struct dns_master_style dns_master_style_t; /*% Indent output. */ #define DNS_STYLEFLAG_INDENT 0x40000000U +/*% Output in YAML style. */ +#define DNS_STYLEFLAG_YAML 0x80000000U + ISC_LANG_BEGINDECLS /*** @@ -167,14 +170,32 @@ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_indent; */ LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_keyzone; +/*% + * YAML-compatible output + */ +LIBDNS_EXTERNAL_DATA extern const dns_master_style_t dns_master_style_yaml; + /*% * The default indent string to prepend lines with when using - * styleflag DNS_STYLEFLAG_INDENT. This is set to "\t" by default. - * The indent preceeds everything else on the line, including comment - * characters (;). + * styleflag DNS_STYLEFLAG_INDENT or DNS_STYLEFLAG_YAML. + * This is set to "\t" by default. The indent is repeated + * 'dns_master_indent' times. This precedes everything else + * on the line, including comment characters (;). + * + * XXX: Changing this value at runtime is not thread-safe. */ LIBDNS_EXTERNAL_DATA extern const char *dns_master_indentstr; +/*% + * The number of copies of the indent string to put at the beginning + * of the line when using DNS_STYLEFLAG_INDENT or DNS_STYLEFLAG_YAML. + * This is set to 1 by default. It is increased and decreased + * to adjust indentation levels when producing YAML output. + * + * XXX: This is not thread-safe. + */ +LIBDNS_EXTERNAL_DATA extern unsigned int dns_master_indent; + /*** *** Functions ***/ @@ -394,6 +415,7 @@ dns_master_stylecreate2(dns_master_style_t **style, unsigned int flags, unsigned int type_column, unsigned int rdata_column, unsigned int line_length, unsigned int tab_width, unsigned int split_width, isc_mem_t *mctx); + void dns_master_styledestroy(dns_master_style_t **style, isc_mem_t *mctx); diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index dfcfeccfc98..b799e5287cc 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -185,11 +186,22 @@ dns_master_style_comment = { 24, 32, 40, 48, 80, 8, UINT_MAX }; +/*% + * YAML style + */ +LIBDNS_EXTERNAL_DATA const dns_master_style_t +dns_master_style_yaml = { + DNS_STYLEFLAG_YAML | + DNS_STYLEFLAG_REL_OWNER | + DNS_STYLEFLAG_INDENT, + 24, 32, 40, 48, 80, 8, UINT_MAX +}; /*% * Default indent string. */ LIBDNS_EXTERNAL_DATA const char *dns_master_indentstr = "\t"; +LIBDNS_EXTERNAL_DATA unsigned int dns_master_indent = 1; #define N_SPACES 10 static char spaces[N_SPACES+1] = " "; @@ -321,14 +333,15 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) { r.base[0] = '\n'; isc_buffer_add(&buf, 1); - if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0) { - unsigned int ilen = strlen(dns_master_indentstr); - isc_buffer_availableregion(&buf, &r); - if (r.length < ilen) - return (DNS_R_TEXTTOOLONG); - isc_buffer_putmem(&buf, - (const isc_uint8_t *) dns_master_indentstr, - (unsigned int)ilen); + if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || + (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) + { + unsigned int i, len = strlen(dns_master_indentstr); + for (i = 0; i < dns_master_indent; i++) { + if (isc_buffer_availablelength(&buf) < len) + return (DNS_R_TEXTTOOLONG); + isc_buffer_putstr(&buf, dns_master_indentstr); + } } if ((ctx->style.flags & DNS_STYLEFLAG_COMMENTDATA) != 0) { @@ -373,7 +386,11 @@ totext_ctx_init(const dns_master_style_t *style, dns_totext_ctx_t *ctx) { #define INDENT_TO(col) \ do { \ - if ((result = indent(&column, ctx->style.col, \ + if ((ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { \ + if ((result = str_totext(" ", target)) \ + != ISC_R_SUCCESS) \ + return (result); \ + } else if ((result = indent(&column, ctx->style.col, \ ctx->style.tab_width, target)) \ != ISC_R_SUCCESS) \ return (result); \ @@ -465,6 +482,7 @@ rdataset_totext(dns_rdataset_t *rdataset, unsigned int type_start; dns_fixedname_t fixed; dns_name_t *name = NULL; + unsigned int i; REQUIRE(DNS_RDATASET_VALID(rdataset)); @@ -487,8 +505,18 @@ rdataset_totext(dns_rdataset_t *rdataset, /* * Indent? */ - if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0) - RETERR(str_totext(dns_master_indentstr, target)); + if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || + (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) + for (i = 0; i < dns_master_indent; i++) + RETERR(str_totext(dns_master_indentstr, + target)); + + /* + * YAML enumerator? + */ + if ((ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) { + RETERR(str_totext("- ", target)); + } /* * Comment? @@ -612,9 +640,13 @@ rdataset_totext(dns_rdataset_t *rdataset, */ INDENT_TO(rdata_column); if ((rdataset->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) { - if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0) - RETERR(str_totext(dns_master_indentstr, - target)); + if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || + (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) + { + for (i = 0; i < dns_master_indent; i++) + RETERR(str_totext(dns_master_indentstr, + target)); + } if (NXDOMAIN(rdataset)) RETERR(str_totext(";-$NXDOMAIN\n", target)); else @@ -984,11 +1016,16 @@ dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name, for (i = 0; i < n; i++) { dns_rdataset_t *rds = sorted[i]; - if (ctx->style.flags & DNS_STYLEFLAG_TRUST) - fprintf(f, "%s; %s\n", - (ctx->style.flags & DNS_STYLEFLAG_INDENT) - ? dns_master_indentstr : "", - dns_trust_totext(rds->trust)); + if (ctx->style.flags & DNS_STYLEFLAG_TRUST) { + if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || + (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) + { + unsigned int j; + for (j = 0; j < dns_master_indent; j++) + fprintf(f, "%s", dns_master_indentstr); + } + fprintf(f, "; %s\n", dns_trust_totext(rds->trust)); + } if (((rds->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) && (ctx->style.flags & DNS_STYLEFLAG_NCACHE) == 0) { /* Omit negative cache entries */ @@ -1008,10 +1045,14 @@ dump_rdatasets_text(isc_mem_t *mctx, dns_name_t *name, memset(buf, 0, sizeof(buf)); isc_buffer_init(&b, buf, sizeof(buf) - 1); dns_time64_totext((isc_uint64_t)rds->resign, &b); - fprintf(f, "%s; resign=%s\n", - (ctx->style.flags & DNS_STYLEFLAG_INDENT) - ? dns_master_indentstr : "", - buf); + if ((ctx->style.flags & DNS_STYLEFLAG_INDENT) != 0 || + (ctx->style.flags & DNS_STYLEFLAG_YAML) != 0) + { + unsigned int j; + for (j = 0; j < dns_master_indent; j++) + fprintf(f, "%s", dns_master_indentstr); + } + fprintf(f, "; resign=%s\n", buf); } dns_rdataset_disassociate(rds); } @@ -2066,7 +2107,6 @@ dns_master_stylecreate2(dns_master_style_t **stylep, unsigned int flags, style->line_length = line_length; style->tab_width = tab_width; style->split_width = split_width; - *stylep = style; return (ISC_R_SUCCESS); } diff --git a/lib/dns/message.c b/lib/dns/message.c index 4df8a154fbb..c9732b2c113 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -80,8 +80,10 @@ hexdump(const char *msg, const char *msg2, void *base, size_t len) { #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \ && ((s) < DNS_SECTION_MAX)) #define ADD_STRING(b, s) {if (strlen(s) >= \ - isc_buffer_availablelength(b)) \ - return(ISC_R_NOSPACE); else \ + isc_buffer_availablelength(b)) { \ + result = ISC_R_NOSPACE; \ + goto cleanup; \ + } else \ isc_buffer_putstr(b, s);} #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \ && ((s) < DNS_PSEUDOSECTION_MAX)) @@ -3160,6 +3162,17 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) { } } +#define INDENT(sp) \ + do { \ + unsigned int __i, __flags = dns_master_styleflags(sp); \ + if ((__flags & DNS_STYLEFLAG_INDENT) == 0 && \ + (__flags & DNS_STYLEFLAG_YAML) == 0) \ + break; \ + for (__i = 0; __i < dns_master_indent; __i++) { \ + ADD_STRING(target, dns_master_indentstr); \ + } \ + } while (0) + isc_result_t dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, const dns_master_style_t *style, @@ -3167,20 +3180,29 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, isc_buffer_t *target) { dns_name_t *name, empty_name; dns_rdataset_t *rdataset; - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; isc_boolean_t seensoa = ISC_FALSE; - unsigned int sflags = dns_master_styleflags(style); + unsigned int sflags, saveindent; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); REQUIRE(VALID_SECTION(section)); + saveindent = dns_master_indent; + sflags = dns_master_styleflags(style); if (ISC_LIST_EMPTY(msg->sections[section])) - return (ISC_R_SUCCESS); + goto cleanup; + - if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); + if ((sflags & DNS_STYLEFLAG_YAML) != 0) { + if (msg->opcode != dns_opcode_update) { + ADD_STRING(target, sectiontext[section]); + } else { + ADD_STRING(target, updsectiontext[section]); + } + ADD_STRING(target, "_SECTION:\n"); + } else if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { ADD_STRING(target, ";; "); if (msg->opcode != dns_opcode_update) { ADD_STRING(target, sectiontext[section]); @@ -3193,7 +3215,10 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, dns_name_init(&empty_name, NULL); result = dns_message_firstname(msg, section); if (result != ISC_R_SUCCESS) { - return (result); + goto cleanup; + } + if ((sflags & DNS_STYLEFLAG_YAML) != 0) { + dns_master_indent++; } do { name = NULL; @@ -3211,10 +3236,12 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, seensoa = ISC_TRUE; } if (section == DNS_SECTION_QUESTION) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, - dns_master_indentstr); - ADD_STRING(target, ";"); + INDENT(style); + if ((sflags & DNS_STYLEFLAG_YAML) != 0) { + ADD_STRING(target, "- "); + } else { + ADD_STRING(target, ";"); + } result = dns_master_questiontotext(name, rdataset, style, @@ -3226,18 +3253,25 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section, target); } if (result != ISC_R_SUCCESS) - return (result); + goto cleanup; } result = dns_message_nextname(msg, section); } while (result == ISC_R_SUCCESS); + if ((sflags & DNS_STYLEFLAG_YAML) != 0) { + dns_master_indent--; + } if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && - (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0 && + (sflags & DNS_STYLEFLAG_YAML) == 0) + { + INDENT(style); ADD_STRING(target, "\n"); } if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; + + cleanup: + dns_master_indent = saveindent; return (result); } @@ -3247,6 +3281,7 @@ render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) { char addr[16], addr_text[64]; isc_uint16_t family; isc_uint8_t addrlen, addrbytes, scopelen; + isc_result_t result; /* * Note: This routine needs to handle malformed ECS options. @@ -3293,7 +3328,256 @@ render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) { ADD_STRING(target, addr_text); snprintf(addr_text, sizeof(addr_text), "/%d/%d", addrlen, scopelen); ADD_STRING(target, addr_text); - return (ISC_R_SUCCESS); + + result = ISC_R_SUCCESS; + + cleanup: + return (result); +} + + +static isc_result_t +dns_message_pseudosectiontoyaml(dns_message_t *msg, + dns_pseudosection_t section, + const dns_master_style_t *style, + dns_messagetextflag_t flags, + isc_buffer_t *target) +{ + dns_rdataset_t *ps = NULL; + dns_name_t *name = NULL; + isc_result_t result = ISC_R_SUCCESS; + char buf[sizeof("1234567890")]; + isc_uint32_t mbz; + dns_rdata_t rdata; + isc_buffer_t optbuf; + isc_uint16_t optcode, optlen; + unsigned char *optdata; + unsigned int saveindent = dns_master_indent; + + REQUIRE(DNS_MESSAGE_VALID(msg)); + REQUIRE(target != NULL); + REQUIRE(VALID_PSEUDOSECTION(section)); + + switch (section) { + case DNS_PSEUDOSECTION_OPT: + ps = dns_message_getopt(msg); + if (ps == NULL) { + goto cleanup; + } + + INDENT(style); + ADD_STRING(target, "OPT_PSEUDOSECTION:\n"); + dns_master_indent++; + + INDENT(style); + ADD_STRING(target, "EDNS:\n"); + dns_master_indent++; + + INDENT(style); + ADD_STRING(target, "version: "); + snprintf(buf, sizeof(buf), "%u", + (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + INDENT(style); + ADD_STRING(target, "flags:"); + if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0) + ADD_STRING(target, " do"); + ADD_STRING(target, "\n"); + mbz = ps->ttl & 0xffff; + mbz &= ~DNS_MESSAGEEXTFLAG_DO; /* Known Flags. */ + if (mbz != 0) { + INDENT(style); + ADD_STRING(target, "MBZ: "); + snprintf(buf, sizeof(buf), "0x%.4x", mbz); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + } + INDENT(style); + ADD_STRING(target, "udp: "); + snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass); + ADD_STRING(target, buf); + result = dns_rdataset_first(ps); + if (result != ISC_R_SUCCESS) { + result = ISC_R_SUCCESS; + goto cleanup; + } + + /* + * Print EDNS info, if any. + * + * WARNING: The option contents may be malformed as + * dig +ednsopt=value: does not validity + * checking. + */ + dns_rdata_init(&rdata); + dns_rdataset_current(ps, &rdata); + + isc_buffer_init(&optbuf, rdata.data, rdata.length); + isc_buffer_add(&optbuf, rdata.length); + while (isc_buffer_remaininglength(&optbuf) != 0) { + INSIST(isc_buffer_remaininglength(&optbuf) >= 4U); + optcode = isc_buffer_getuint16(&optbuf); + optlen = isc_buffer_getuint16(&optbuf); + INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); + + if (optcode == DNS_OPT_NSID) { + INDENT(style); + ADD_STRING(target, "NSID"); + } else if (optcode == DNS_OPT_COOKIE) { + INDENT(style); + ADD_STRING(target, "COOKIE"); + } else if (optcode == DNS_OPT_CLIENT_SUBNET) { + isc_buffer_t ecsbuf; + INDENT(style); + ADD_STRING(target, "CLIENT-SUBNET"); + isc_buffer_init(&ecsbuf, + isc_buffer_current(&optbuf), + optlen); + isc_buffer_add(&ecsbuf, optlen); + result = render_ecs(&ecsbuf, target); + if (result == ISC_R_NOSPACE) + goto cleanup; + if (result == ISC_R_SUCCESS) { + isc_buffer_forward(&optbuf, optlen); + ADD_STRING(target, "\n"); + continue; + } + ADD_STRING(target, "\n"); + } else if (optcode == DNS_OPT_EXPIRE) { + if (optlen == 4) { + isc_uint32_t secs; + secs = isc_buffer_getuint32(&optbuf); + INDENT(style); + ADD_STRING(target, "EXPIRE: "); + snprintf(buf, sizeof(buf), "%u", secs); + ADD_STRING(target, buf); + ADD_STRING(target, " ("); + result = dns_ttl_totext(secs, + ISC_TRUE, + target); + if (result != ISC_R_SUCCESS) + goto cleanup; + ADD_STRING(target, ")\n"); + continue; + } + INDENT(style); + ADD_STRING(target, "EXPIRE"); + } else if (optcode == DNS_OPT_PAD) { + INDENT(style); + ADD_STRING(target, "PAD"); + } else { + INDENT(style); + ADD_STRING(target, "OPT: "); + snprintf(buf, sizeof(buf), "%u", optcode); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + } + + if (optlen != 0) { + int i; + ADD_STRING(target, ": "); + + optdata = isc_buffer_current(&optbuf); + for (i = 0; i < optlen; i++) { + const char *sep; + switch (optcode) { + case DNS_OPT_COOKIE: + sep = ""; + break; + default: + sep = " "; + break; + } + snprintf(buf, sizeof(buf), "%02x%s", + optdata[i], sep); + ADD_STRING(target, buf); + } + + isc_buffer_forward(&optbuf, optlen); + + if (optcode == DNS_OPT_COOKIE) { + /* + * Valid server cookie? + */ + if (msg->cc_ok && optlen >= 16) + ADD_STRING(target, " (good)"); + /* + * Server cookie is not valid but + * we had our cookie echoed back. + */ + if (msg->cc_ok && optlen < 16) + ADD_STRING(target, " (echoed)"); + /* + * We didn't get our cookie echoed + * back. + */ + if (msg->cc_bad) + ADD_STRING(target, " (bad)"); + ADD_STRING(target, "\n"); + continue; + } + + if (optcode == DNS_OPT_CLIENT_SUBNET) { + ADD_STRING(target, "\n"); + continue; + } + + /* + * For non-COOKIE options, add a printable + * version + */ + ADD_STRING(target, "(\""); + if (isc_buffer_availablelength(target) < optlen) + { + result = ISC_R_NOSPACE; + goto cleanup; + } + for (i = 0; i < optlen; i++) { + if (isprint(optdata[i])) + isc_buffer_putmem(target, + &optdata[i], + 1); + else + isc_buffer_putstr(target, "."); + } + ADD_STRING(target, "\")"); + } + ADD_STRING(target, "\n"); + } + result = ISC_R_SUCCESS; + goto cleanup; + case DNS_PSEUDOSECTION_TSIG: + ps = dns_message_gettsig(msg, &name); + if (ps == NULL) { + result = ISC_R_SUCCESS; + goto cleanup; + } + INDENT(style); + ADD_STRING(target, "TSIG_PSEUDOSECTION:\n"); + result = dns_master_rdatasettotext(name, ps, style, target); + ADD_STRING(target, "\n"); + goto cleanup; + case DNS_PSEUDOSECTION_SIG0: + ps = dns_message_getsig0(msg, &name); + if (ps == NULL) { + result = ISC_R_SUCCESS; + goto cleanup; + } + INDENT(style); + ADD_STRING(target, "SIG0_PSEUDOSECTION:\n"); + result = dns_master_rdatasettotext(name, ps, style, target); + if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 && + (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) + ADD_STRING(target, "\n"); + goto cleanup; + } + + result = ISC_R_UNEXPECTED; + + cleanup: + dns_master_indent = saveindent; + return (result); } isc_result_t @@ -3312,25 +3596,25 @@ dns_message_pseudosectiontotext(dns_message_t *msg, isc_buffer_t optbuf; isc_uint16_t optcode, optlen; unsigned char *optdata; - unsigned int sflags = dns_master_styleflags(style); REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); REQUIRE(VALID_PSEUDOSECTION(section)); + if ((dns_master_styleflags(style) & DNS_STYLEFLAG_YAML) != 0) + return (dns_message_pseudosectiontoyaml(msg, section, style, + flags, target)); switch (section) { case DNS_PSEUDOSECTION_OPT: ps = dns_message_getopt(msg); if (ps == NULL) return (ISC_R_SUCCESS); if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); ADD_STRING(target, ";; OPT PSEUDOSECTION:\n"); } - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); ADD_STRING(target, "; EDNS: version: "); snprintf(buf, sizeof(buf), "%u", (unsigned int)((ps->ttl & 0x00ff0000) >> 16)); @@ -3372,8 +3656,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg, optlen = isc_buffer_getuint16(&optbuf); INSIST(isc_buffer_remaininglength(&optbuf) >= optlen); - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); if (optcode == DNS_OPT_NSID) { ADD_STRING(target, "; NSID"); @@ -3493,8 +3776,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg, ps = dns_message_gettsig(msg, &name); if (ps == NULL) return (ISC_R_SUCCESS); - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n"); result = dns_master_rdatasettotext(name, ps, style, target); @@ -3506,8 +3788,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg, ps = dns_message_getsig0(msg, &name); if (ps == NULL) return (ISC_R_SUCCESS); - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n"); result = dns_master_rdatasettotext(name, ps, style, target); @@ -3516,23 +3797,104 @@ dns_message_pseudosectiontotext(dns_message_t *msg, ADD_STRING(target, "\n"); return (result); } - return (ISC_R_UNEXPECTED); + result = ISC_R_UNEXPECTED; + cleanup: + return (result); } isc_result_t dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, dns_messagetextflag_t flags, isc_buffer_t *target) { - unsigned int sflags = dns_master_styleflags(style); char buf[sizeof("1234567890")]; isc_result_t result; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); - if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + if (((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) && + (dns_master_styleflags(style) & DNS_STYLEFLAG_YAML)) + { + INDENT(style); + ADD_STRING(target, "opcode: "); + ADD_STRING(target, opcodetext[msg->opcode]); + ADD_STRING(target, "\n"); + INDENT(style); + ADD_STRING(target, "status: "); + result = dns_rcode_totext(msg->rcode, target); + if (result != ISC_R_SUCCESS) + return (result); + ADD_STRING(target, "\n"); + INDENT(style); + ADD_STRING(target, "id: "); + snprintf(buf, sizeof(buf), "%6u", msg->id); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + INDENT(style); + ADD_STRING(target, "flags:"); + if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) + ADD_STRING(target, " qr"); + if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) + ADD_STRING(target, " aa"); + if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) + ADD_STRING(target, " tc"); + if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) + ADD_STRING(target, " rd"); + if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) + ADD_STRING(target, " ra"); + if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) + ADD_STRING(target, " ad"); + if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) + ADD_STRING(target, " cd"); + ADD_STRING(target, "\n"); + /* + * The final unnamed flag must be zero. + */ + if ((msg->flags & 0x0040U) != 0) { + INDENT(style); + ADD_STRING(target, "MBZ: 0x4"); + ADD_STRING(target, "\n"); + } + if (msg->opcode != dns_opcode_update) { + INDENT(style); + ADD_STRING(target, "QUESTION: "); + } else { + ADD_STRING(target, "ZONE: "); + } + snprintf(buf, sizeof(buf), "%1u", + msg->counts[DNS_SECTION_QUESTION]); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + if (msg->opcode != dns_opcode_update) { + INDENT(style); + ADD_STRING(target, "ANSWER: "); + } else { + INDENT(style); + ADD_STRING(target, "PREREQ: "); + } + snprintf(buf, sizeof(buf), "%1u", + msg->counts[DNS_SECTION_ANSWER]); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + if (msg->opcode != dns_opcode_update) { + INDENT(style); + ADD_STRING(target, "AUTHORITY: "); + } else { + INDENT(style); + ADD_STRING(target, "UPDATE: "); + } + snprintf(buf, sizeof(buf), "%1u", + msg->counts[DNS_SECTION_AUTHORITY]); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + INDENT(style); + ADD_STRING(target, "ADDITIONAL: "); + snprintf(buf, sizeof(buf), "%1u", + msg->counts[DNS_SECTION_ADDITIONAL]); + ADD_STRING(target, buf); + ADD_STRING(target, "\n"); + } else if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) { + INDENT(style); ADD_STRING(target, ";; ->>HEADER<<- opcode: "); ADD_STRING(target, opcodetext[msg->opcode]); ADD_STRING(target, ", status: "); @@ -3543,8 +3905,7 @@ dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, snprintf(buf, sizeof(buf), "%6u", msg->id); ADD_STRING(target, buf); ADD_STRING(target, "\n"); - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); ADD_STRING(target, ";; flags:"); if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) ADD_STRING(target, " qr"); @@ -3564,17 +3925,14 @@ dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, * The final unnamed flag must be zero. */ if ((msg->flags & 0x0040U) != 0) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); ADD_STRING(target, "; MBZ: 0x4"); } if (msg->opcode != dns_opcode_update) { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); ADD_STRING(target, "; QUESTION: "); } else { - if ((sflags & DNS_STYLEFLAG_INDENT) != 0) - ADD_STRING(target, dns_master_indentstr); + INDENT(style); ADD_STRING(target, "; ZONE: "); } snprintf(buf, sizeof(buf), "%1u", @@ -3637,7 +3995,8 @@ dns_message_totext(dns_message_t *msg, const dns_master_style_t *style, if (result != ISC_R_SUCCESS) return (result); - return (ISC_R_SUCCESS); + cleanup: + return (result); } isc_region_t * diff --git a/lib/dns/win32/libdns.def.in b/lib/dns/win32/libdns.def.in index db1be5cecd1..f2104fff6f8 100644 --- a/lib/dns/win32/libdns.def.in +++ b/lib/dns/win32/libdns.def.in @@ -501,6 +501,7 @@ dns_master_questiontotext dns_master_rdatasettotext dns_master_stylecreate dns_master_stylecreate2 +dns_master_stylecreate3 dns_master_styledestroy dns_master_styleflags dns_message_addname