Commit 79a55d4f authored by Mukund Sivaraman's avatar Mukund Sivaraman

Add option to tools to print RRs in unknown presentation format (#41595)

parent 9267cc8e
4316. [func] Add option to tools to print RRs in unknown
presentation format [RT #41595].
4315. [bug] Check that configured view class isn't a meta class.
[RT #41572].
......
......@@ -114,7 +114,8 @@ static isc_boolean_t
nocrypto = ISC_FALSE,
nottl = ISC_FALSE,
multiline = ISC_FALSE,
short_form = ISC_FALSE;
short_form = ISC_FALSE,
print_unknown_format = ISC_FALSE;
static isc_boolean_t
resolve_trace = ISC_FALSE,
......@@ -184,6 +185,7 @@ usage(void) {
" +[no]comments (Control display of comment lines)\n"
" +[no]rrcomments (Control display of per-record "
"comments)\n"
" +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" format)\n"
" +[no]short (Short form answer)\n"
" +[no]split=## (Split hex/base64 fields into chunks)\n"
" +[no]tcp (TCP mode)\n"
......@@ -508,6 +510,8 @@ setup_style(dns_master_style_t **stylep) {
styleflags |= DNS_STYLEFLAG_REL_OWNER;
if (showcomments)
styleflags |= DNS_STYLEFLAG_COMMENT;
if (print_unknown_format)
styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
if (rrcomments)
styleflags |= DNS_STYLEFLAG_RRCOMMENT;
if (nottl)
......@@ -1132,6 +1136,10 @@ plus_option(char *option) {
goto invalid_option;
}
break;
case 'u':
FULLCHECK("unknownformat");
print_unknown_format = state;
break;
case 't':
switch (cmd[1]) {
case 'c': /* tcp */
......
......@@ -664,6 +664,17 @@
</varlistentry>
</variablelist>
<varlistentry>
<term><option>+[no]unknownformat</option></term>
<listitem>
<para>
Print all RDATA in unknown RR type presentation format
(RFC 3597). The default is to print RDATA for known types
in the type's presentation format.
</para>
</listitem>
</varlistentry>
</para>
</refsection>
......
......@@ -231,6 +231,7 @@ help(void) {
" +tries=### (Set number of UDP attempts) [3]\n"
" +[no]ttlid (Control display of ttls in records)\n"
" +[no]ttlunits (Display TTLs in human-readable units)\n"
" +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" format)\n"
" +[no]vc (TCP mode (+[no]tcp))\n"
" +[no]zflag (Set Z flag in query)\n"
" global d-opts and servers (before host name) affect all queries.\n"
......@@ -334,6 +335,8 @@ say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {
styleflags |= DNS_STYLEFLAG_RRCOMMENT;
if (nocrypto)
styleflags |= DNS_STYLEFLAG_NOCRYPTO;
if (query->lookup->print_unknown_format)
styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0,
splitwidth, " ", buf);
if (result == ISC_R_NOSPACE)
......@@ -478,6 +481,8 @@ printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
styleflags |= DNS_STYLEFLAG_REL_OWNER;
if (query->lookup->comments)
styleflags |= DNS_STYLEFLAG_COMMENT;
if (query->lookup->print_unknown_format)
styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
/* Turn on rrcomments if explicitly enabled */
if (rrcomments > 0)
styleflags |= DNS_STYLEFLAG_RRCOMMENT;
......@@ -1412,6 +1417,10 @@ plus_option(const char *option, isc_boolean_t is_batchfile,
goto invalid_option;
}
break;
case 'u':
FULLCHECK("unknownformat");
lookup->print_unknown_format = state;
break;
case 'v':
FULLCHECK("vc");
if (!is_batchfile) {
......
......@@ -1151,6 +1151,17 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>+[no]unknownformat</option></term>
<listitem>
<para>
Print all RDATA in unknown RR type presentation format
(RFC 3597). The default is to print RDATA for known types
in the type's presentation format.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>+[no]vc</option></term>
<listitem>
......
......@@ -806,6 +806,7 @@ make_empty_lookup(void) {
looknew->aaonly = ISC_FALSE;
looknew->adflag = ISC_FALSE;
looknew->cdflag = ISC_FALSE;
looknew->print_unknown_format = ISC_FALSE;
looknew->zflag = ISC_FALSE;
looknew->ns_search_only = ISC_FALSE;
looknew->origin = NULL;
......@@ -909,6 +910,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
looknew->aaonly = lookold->aaonly;
looknew->adflag = lookold->adflag;
looknew->cdflag = lookold->cdflag;
looknew->print_unknown_format = lookold->print_unknown_format;
looknew->zflag = lookold->zflag;
looknew->ns_search_only = lookold->ns_search_only;
looknew->tcp_mode = lookold->tcp_mode;
......
......@@ -137,7 +137,8 @@ struct dig_lookup {
nsid, /*% Name Server ID (RFC 5001) */
header_only,
ednsneg,
mapped;
mapped,
print_unknown_format;
#ifdef DIG_SIGCHASE
isc_boolean_t sigchase;
#if DIG_SIGCHASE_TD
......
......@@ -34,6 +34,14 @@ if [ -x ${DIG} ] ; then
ret=0
$DIG $DIGOPTS @10.53.0.3 +split=4 -t sshfp foo.example > dig.out.test$n || ret=1
grep " 9ABC DEF6 7890 " < dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I:checking dig +unknownformat works ($n)"
ret=0
$DIG $DIGOPTS @10.53.0.3 +unknownformat a a.example > dig.out.test$n || ret=1
grep "CLASS1[[:space:]][[:space:]]*TYPE1[[:space:]][[:space:]]*\\\\# 4 0A000001" < dig.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
......@@ -337,6 +345,14 @@ if [ -x ${DELV} ] ; then
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I:checking delv +unknownformat works ($n)"
ret=0
$DELV $DELVOPTS @10.53.0.3 +unknownformat a a.example > delv.out.test$n || ret=1
grep "CLASS1[[:space:]][[:space:]]*TYPE1[[:space:]][[:space:]]*\\\\# 4 0A000001" < delv.out.test$n > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
n=`expr $n + 1`
echo "I:checking delv with IPv6 on IPv4 does not work ($n)"
if $TESTSOCK6 fd92:7065:b8e:ffff::3
......
......@@ -103,11 +103,12 @@ static isc_boolean_t display_ttlunits = ISC_TRUE;
static isc_boolean_t display_ttl = ISC_TRUE;
static isc_boolean_t display_class = ISC_TRUE;
static isc_boolean_t display_crypto = ISC_TRUE;
static isc_boolean_t display_multiline = ISC_TRUE;
static isc_boolean_t display_multiline = ISC_FALSE;
static isc_boolean_t display_question = ISC_TRUE;
static isc_boolean_t display_answer = ISC_TRUE;
static isc_boolean_t display_authority = ISC_TRUE;
static isc_boolean_t display_additional = ISC_TRUE;
static isc_boolean_t display_unknown_format = ISC_FALSE;
static isc_uint32_t display_splitwidth = 0xffffffff;
static isc_sockaddr_t srcaddr;
static char *server;
......@@ -247,6 +248,8 @@ recvresponse(isc_task_t *task, isc_event_t *event) {
styleflags |= DNS_STYLEFLAG_REL_OWNER;
if (display_comments)
styleflags |= DNS_STYLEFLAG_COMMENT;
if (display_unknown_format)
styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
if (display_rrcomments)
styleflags |= DNS_STYLEFLAG_RRCOMMENT;
if (display_ttlunits)
......@@ -378,6 +381,8 @@ buftoosmall:
if (!display_crypto)
answerstyleflags |= DNS_STYLEFLAG_NOCRYPTO;
if (display_unknown_format)
answerstyleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
dns_name_init(&empty_name, NULL);
result = dns_message_firstname(response, DNS_SECTION_ANSWER);
......@@ -759,6 +764,7 @@ help(void) {
" form of answer)\n"
" +[no]ttlid (Control display of ttls in records)\n"
" +[no]ttlunits (Display TTLs in human-readable units)\n"
" +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" format)\n"
" +[no]all (Set or clear all display flags)\n"
" +[no]multiline (Print records in an expanded format)\n"
" +[no]split=## (Split hex/base64 fields into chunks)\n"
......@@ -1470,14 +1476,24 @@ plus_option(char *option, struct query *query, isc_boolean_t global)
}
break;
case 'u':
FULLCHECK("udptimeout");
if (value == NULL)
goto need_value;
if (!state)
switch (cmd[1]) {
case 'd':
FULLCHECK("udptimeout");
if (value == NULL)
goto need_value;
if (!state)
goto invalid_option;
result = parse_uint(&query->udptimeout, value,
MAXTIMEOUT, "udptimeout");
CHECK("parse_uint(udptimeout)", result);
break;
case 'n':
FULLCHECK("unknownformat");
display_unknown_format = state;
break;
default:
goto invalid_option;
result = parse_uint(&query->udptimeout, value,
MAXTIMEOUT, "udptimeout");
CHECK("parse_uint(udptimeout)", result);
}
break;
case 'v':
FULLCHECK("vc");
......
......@@ -646,6 +646,17 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>+[no]unknownformat</option></term>
<listitem>
<para>
Print all RDATA in unknown RR type presentation format
(RFC 3597). The default is to print RDATA for known types
in the type's presentation format.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>+[no]zflag</option></term>
<listitem>
......
......@@ -49,6 +49,19 @@ usage(void) {
fprintf(stderr, "\t-P: list the supported private type names\n");
fprintf(stderr, "\t-T: list the supported standard type names\n");
fprintf(stderr, "\t-u: print the record in unknown record format\n");
exit(0);
}
static void
fatal(const char *format, ...) {
va_list args;
fprintf(stderr, "named-rrchecker: ");
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
fputc('\n', stderr);
exit(1);
}
int
......@@ -75,15 +88,6 @@ main(int argc, char *argv[]) {
while ((c = isc_commandline_parse(argc, argv, "ho:puCPT")) != -1) {
switch (c) {
case '?':
case 'h':
if (isc_commandline_option != '?' &&
isc_commandline_option != 'h')
fprintf(stderr, "%s: invalid argument -%c\n",
argv[0], isc_commandline_option);
usage();
exit(1);
case 'o':
origin = isc_commandline_argument;
break;
......@@ -127,6 +131,16 @@ main(int argc, char *argv[]) {
}
doexit = ISC_TRUE;
break;
case '?':
case 'h':
/* Does not return. */
usage();
default:
fprintf(stderr, "%s: unhandled option -%c\n",
argv[0], isc_commandline_option);
exit(1);
}
}
if (doexit)
......@@ -153,10 +167,8 @@ main(int argc, char *argv[]) {
name = dns_fixedname_name(&fixed);
result = dns_name_fromstring(name, origin, 0, NULL);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_name_fromstring: %s\n",
dns_result_totext(result));
fflush(stderr);
exit(1);
fatal("dns_name_fromstring: %s",
dns_result_totext(result));
}
}
......@@ -167,8 +179,7 @@ main(int argc, char *argv[]) {
if (token.type == isc_tokentype_eol)
continue;
if (once) {
fprintf(stderr, "extra data\n");
exit(1);
fatal("extra data");
}
/*
* Get class.
......@@ -176,37 +187,27 @@ main(int argc, char *argv[]) {
if (token.type == isc_tokentype_number) {
rdclass = (dns_rdataclass_t) token.value.as_ulong;
if (token.value.as_ulong > 0xffffu) {
fprintf(stderr, "class value too big %lu\n",
token.value.as_ulong);
fflush(stderr);
exit(1);
fatal("class value too big %lu",
token.value.as_ulong);
}
if (dns_rdataclass_ismeta(rdclass)) {
fprintf(stderr, "class %lu is a meta value\n",
token.value.as_ulong);
fflush(stderr);
exit(1);
fatal("class %lu is a meta value",
token.value.as_ulong);
}
} else if (token.type == isc_tokentype_string) {
result = dns_rdataclass_fromtext(&rdclass,
&token.value.as_textregion);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_rdataclass_fromtext: %s\n",
dns_result_totext(result));
fflush(stderr);
exit(1);
fatal("dns_rdataclass_fromtext: %s",
dns_result_totext(result));
}
if (dns_rdataclass_ismeta(rdclass)) {
fprintf(stderr,
"class %.*s(%d) is a meta value\n",
(int)token.value.as_textregion.length,
token.value.as_textregion.base, rdclass);
fflush(stderr);
exit(1);
fatal("class %.*s(%d) is a meta value",
(int)token.value.as_textregion.length,
token.value.as_textregion.base, rdclass);
}
} else {
fprintf(stderr, "unexpected token %u\n", token.type);
exit(1);
fatal("unexpected token %u", token.type);
}
result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
......@@ -224,96 +225,93 @@ main(int argc, char *argv[]) {
if (token.type == isc_tokentype_number) {
rdtype = (dns_rdatatype_t) token.value.as_ulong;
if (token.value.as_ulong > 0xffffu) {
fprintf(stderr, "type value too big %lu\n",
token.value.as_ulong);
exit(1);
fatal("type value too big %lu",
token.value.as_ulong);
}
if (dns_rdatatype_ismeta(rdtype)) {
fprintf(stderr, "type %lu is a meta value\n",
token.value.as_ulong);
fflush(stderr);
exit(1);
fatal("type %lu is a meta value",
token.value.as_ulong);
}
} else if (token.type == isc_tokentype_string) {
result = dns_rdatatype_fromtext(&rdtype,
&token.value.as_textregion);
if (result != ISC_R_SUCCESS) {
fprintf(stdout, "dns_rdatatype_fromtext: %s\n",
dns_result_totext(result));
fflush(stdout);
exit(1);
fatal("dns_rdatatype_fromtext: %s",
dns_result_totext(result));
}
if (dns_rdatatype_ismeta(rdtype)) {
fprintf(stderr,
"type %.*s(%d) is a meta value\n",
(int)token.value.as_textregion.length,
token.value.as_textregion.base, rdtype);
fflush(stderr);
exit(1);
fatal("type %.*s(%d) is a meta value",
(int)token.value.as_textregion.length,
token.value.as_textregion.base, rdtype);
}
} else {
fprintf(stderr, "unexpected token %u\n", token.type);
exit(1);
fatal("unexpected token %u", token.type);
}
isc_buffer_init(&dbuf, data, sizeof(data));
result = dns_rdata_fromtext(&rdata, rdclass, rdtype, lex,
name, 0, mctx, &dbuf, NULL);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_rdata_fromtext: %s\n",
dns_result_totext(result));
fflush(stderr);
exit(1);
fatal("dns_rdata_fromtext: %s",
dns_result_totext(result));
}
once = ISC_TRUE;
}
if (result != ISC_R_EOF) {
fprintf(stderr, "eof not found\n");
exit(1);
fatal("eof not found");
}
if (!once) {
fprintf(stderr, "no records found\n");
exit(1);
fatal("no records found");
}
if (print) {
isc_buffer_init(&tbuf, text, sizeof(text));
result = dns_rdataclass_totext(rdclass, &tbuf);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_rdataclass_totext: %s\n",
dns_result_totext(result));
fflush(stderr);
exit(1);
fatal("dns_rdataclass_totext: %s",
dns_result_totext(result));
}
isc_buffer_putstr(&tbuf, "\t");
result = dns_rdatatype_totext(rdtype, &tbuf);
if (result != ISC_R_SUCCESS) {
fprintf(stderr, "dns_rdatatype_totext: %s\n",
dns_result_totext(result));
fflush(stderr);
exit(1);
fatal("dns_rdatatype_totext: %s",
dns_result_totext(result));
}
isc_buffer_putstr(&tbuf, "\t");
result = dns_rdata_totext(&rdata, NULL, &tbuf);
if (result != ISC_R_SUCCESS)
fprintf(stderr, "dns_rdata_totext: %s\n",
dns_result_totext(result));
else
fprintf(stdout, "%.*s\n", (int)tbuf.used,
(char*)tbuf.base);
if (result != ISC_R_SUCCESS) {
fatal("dns_rdata_totext: %s",
dns_result_totext(result));
}
printf("%.*s\n", (int)tbuf.used, (char*)tbuf.base);
fflush(stdout);
}
if (unknown) {
fprintf(stdout, "CLASS%u\tTYPE%u\t\\# %u", rdclass, rdtype,
rdata.length);
if (rdata.length != 0) {
unsigned int i;
fprintf(stdout, " ");
for (i = 0; i < rdata.length; i++)
fprintf(stdout, "%02x", rdata.data[i]);
isc_buffer_init(&tbuf, text, sizeof(text));
result = dns_rdataclass_tounknowntext(rdclass, &tbuf);
if (result != ISC_R_SUCCESS) {
fatal("dns_rdataclass_tounknowntext: %s",
dns_result_totext(result));
}
fprintf(stdout, "\n");
isc_buffer_putstr(&tbuf, "\t");
result = dns_rdatatype_tounknowntext(rdtype, &tbuf);
if (result != ISC_R_SUCCESS) {
fatal("dns_rdatatype_tounknowntext: %s",
dns_result_totext(result));
}
isc_buffer_putstr(&tbuf, "\t");
result = dns_rdata_tofmttext(&rdata, NULL,
DNS_STYLEFLAG_UNKNOWNFORMAT,
0, 0, "", &tbuf);
if (result != ISC_R_SUCCESS) {
fatal("dns_rdata_tofmttext: %sn",
dns_result_totext(result));
}
printf("%.*s\n", (int)tbuf.used, (char*)tbuf.base);
fflush(stdout);
}
isc_lex_close(lex);
......
......@@ -174,6 +174,9 @@ struct dns_rdata {
/*% Output KEYDATA in human readable format. */
#define DNS_STYLEFLAG_KEYDATA 0x00000008U
/*% Output textual RR type and RDATA in RFC 3597 unknown format */
#define DNS_STYLEFLAG_UNKNOWNFORMAT 0x00000010U
#define DNS_RDATA_DOWNCASE DNS_NAME_DOWNCASE
#define DNS_RDATA_CHECKNAMES DNS_NAME_CHECKNAMES
#define DNS_RDATA_CHECKNAMESFAIL DNS_NAME_CHECKNAMESFAIL
......
......@@ -62,6 +62,26 @@ dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target);
*\li #ISC_R_NOSPACE target buffer is too small
*/
isc_result_t
dns_rdataclass_tounknowntext(dns_rdataclass_t rdclass, isc_buffer_t *target);
/*%<
* Put textual RFC3597 CLASSXXXX representation of class 'rdclass' into
* 'target'.
*
* Requires:
*\li 'rdclass' is a valid class.
*
*\li 'target' is a valid text buffer.
*
* Ensures,
* if the result is success:
*\li The used space in 'target' is updated.
*
* Returns:
*\li #ISC_R_SUCCESS on success
*\li #ISC_R_NOSPACE target buffer is too small
*/
void
dns_rdataclass_format(dns_rdataclass_t rdclass,
char *array, unsigned int size);
......
......@@ -62,6 +62,26 @@ dns_rdatatype_totext(dns_rdatatype_t type, isc_buffer_t *target);
*\li #ISC_R_NOSPACE target buffer is too small
*/
isc_result_t
dns_rdatatype_tounknowntext(dns_rdatatype_t type, isc_buffer_t *target);
/*%<
* Put textual RFC3597 TYPEXXXX representation of type 'type' into
* 'target'.
*
* Requires:
*\li 'type' is a valid type.
*
*\li 'target' is a valid text buffer.
*
* Ensures,
* if the result is success:
*\li The used space in 'target' is updated.
*
* Returns:
*\li #ISC_R_SUCCESS on success
*\li #ISC_R_NOSPACE target buffer is too small
*/
void
dns_rdatatype_format(dns_rdatatype_t rdtype,
char *array, unsigned int size);
......
......@@ -570,8 +570,12 @@ rdataset_totext(dns_rdataset_t *rdataset,
unsigned int class_start;
INDENT_TO(class_column);
class_start = target->used;
result = dns_rdataclass_totext(rdataset->rdclass,
target);
if ((ctx->style.flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0)
result = dns_rdataclass_tounknowntext
(rdataset->rdclass, target);
else
result = dns_rdataclass_totext
(rdataset->rdclass, target);
if (result != ISC_R_SUCCESS)
return (result);
column += (target->used - class_start);
......@@ -603,7 +607,10 @@ rdataset_totext(dns_rdataset_t *rdataset,
}
/* FALLTHROUGH */
default:
result = dns_rdatatype_totext(type, target);
if ((ctx->style.flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0)
result = dns_rdatatype_tounknowntext(type, target);
else
result = dns_rdatatype_totext(type, target);
if (result != ISC_R_SUCCESS)
return (result);
}
......@@ -707,7 +714,12 @@ question_totext(dns_rdataset_t *rdataset,
unsigned int class_start;
INDENT_TO(class_column);
class_start = target->used;
result = dns_rdataclass_totext(rdataset->rdclass, target);
if ((ctx->style.flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0)
result = dns_rdataclass_tounknowntext(rdataset->rdclass,
target);
else
result = dns_rdataclass_totext(rdataset->rdclass,
target);
if (result != ISC_R_SUCCESS)
return (result);
column += (target->used - class_start);
......@@ -718,7 +730,12 @@ question_totext(dns_rdataset_t *rdataset,
unsigned int type_start;
INDENT_TO(type_column);
type_start = target->used;
result = dns_rdatatype_totext(rdataset->type, target);
if ((ctx->style.flags & DNS_STYLEFLAG_UNKNOWNFORMAT) != 0)
result = dns_rdatatype_tounknowntext(rdataset->type,
target);
else
result = dns_rdatatype_totext(rdataset->type,
target);
if (result != ISC_R_SUCCESS)
return (result);