This patch adds a new "forced generic" dump style which dumps resource
record types and data in the generic RFC 3597 representation format,
even for known resource record types. A corresponding +generic option to
kdig enables this dump style.
Generic representation format is very handy when dealing with older DNS
software that may not support a new resource record type, or with
systems where it is more convenient to use the generic format even with
known types. It is also a nice debugging / educational feature. (No need
to fire up Wireshark.)
---
 man/kdig.1.in                |  3 +++
 src/libknot/rrset-dump.c     | 10 +++++++++-
 src/libknot/rrset-dump.h     |  2 ++
 src/utils/kdig/kdig_params.c | 13 +++++++++++++
 4 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/man/kdig.1.in b/man/kdig.1.in
index 4772e27..b6f2286 100644
--- a/man/kdig.1.in
+++ b/man/kdig.1.in
@@ -178,6 +178,9 @@ Use EDNS version (default is 0).
 Disable IDN transformation to ASCII and vice versa.
 IDNA2003 support depends on libidn availability during project building!
 .TP
+.BR +generic
+Use the generic representation format when printing resource record types and data.
+.TP
 .BI +client= SUBN
 Set EDNS client subnet SUBN=IP/prefix.
 .TP
diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c
index dd4625d..2f503c1 100644
--- a/src/libknot/rrset-dump.c
+++ b/src/libknot/rrset-dump.c
@@ -1774,6 +1774,10 @@ int knot_rrset_txt_dump_data(const knot_rrset_t      *rrset,
                return ret;
        }
+       if (style->generic) {
+               return dump_unknown(&p);
+       }
+
        switch (rrset->type) {
                case KNOT_RRTYPE_A:
                        ret = dump_a(&p);
@@ -1941,7 +1945,11 @@ int knot_rrset_txt_dump_header(const knot_rrset_t      *rrset,
        }
        // Dump rrset type.
-       if (knot_rrtype_to_string(rrset->type, buf, sizeof(buf)) < 0) {
+       if (style->generic) {
+               if (snprintf(buf, sizeof(buf), "TYPE%u", rrset->type) < 0)
{
+                       return KNOT_ESPACE;
+               }
+       } else if (knot_rrtype_to_string(rrset->type, buf, sizeof(buf)) < 0) {
                return KNOT_ESPACE;
        }
        if (rrset->rrs.rr_count > 0) {
diff --git a/src/libknot/rrset-dump.h b/src/libknot/rrset-dump.h
index 4519159..e44cca3 100644
--- a/src/libknot/rrset-dump.h
+++ b/src/libknot/rrset-dump.h
@@ -46,6 +46,8 @@ typedef struct {
        bool    human_ttl;
        /*!< Format timestamp as YYYYMMDDHHmmSS. */
        bool    human_tmstamp;
+       /*!< Force generic data representation. */
+       bool    generic;
        /*!< ASCII string to IDN string transformation callback. */
        void (*ascii_to_idn)(char **name);
 } knot_dump_style_t;
diff --git a/src/utils/kdig/kdig_params.c b/src/utils/kdig/kdig_params.c
index ec7ec9f..6fafb22 100644
--- a/src/utils/kdig/kdig_params.c
+++ b/src/utils/kdig/kdig_params.c
@@ -54,6 +54,7 @@ static const style_t DEFAULT_STYLE_DIG = {
                .empty_ttl = false,
                .human_ttl = false,
                .human_tmstamp = true,
+               .generic = false,
                .ascii_to_idn = name_to_idn
        },
        .show_query = false,
@@ -551,6 +552,15 @@ static int opt_noidn(const char *arg, void *query)
        return KNOT_EOK;
 }
+static int opt_generic(const char *arg, void *query)
+{
+       query_t *q = query;
+
+       q->style.style.generic = true;
+
+       return KNOT_EOK;
+}
+
 static int opt_nsid(const char *arg, void *query)
 {
        query_t *q = query;
@@ -805,6 +815,8 @@ static const param_t kdig_opts2[] = {
        /* "idn" doesn't work since it must be called before query creation.
*/
        { "noidn",        ARG_NONE,     opt_noidn },
+       { "generic",      ARG_NONE,     opt_generic },
+
        { "client",       ARG_REQUIRED, opt_client },
        { "time",         ARG_REQUIRED, opt_time },
@@ -1363,6 +1375,7 @@ static void kdig_help(void)
               "       +[no]nsid       Request NSID.\n"
               "       +[no]edns=N     Use EDNS (=version).\n"
               "       +noidn          Disable IDN transformation.\n"
+              "       +generic        Use generic representation format.\n"
               "       +client=SUBN    Set EDNS client subnet IP/prefix.\n"
               "       +time=T         Set wait for reply interval in
seconds.\n"
               "       +retry=N        Set number of retries.\n"
--
2.1.4