1999-01-06 05:42:58 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 1999 Internet Software Consortium.
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
|
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
|
|
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <isc/assertions.h>
|
|
|
|
#include <isc/boolean.h>
|
|
|
|
#include <isc/region.h>
|
|
|
|
|
|
|
|
#include <dns/types.h>
|
|
|
|
#include <dns/result.h>
|
|
|
|
#include <dns/name.h>
|
1999-01-13 19:11:26 +00:00
|
|
|
#include <dns/rdata.h>
|
1999-01-20 07:49:50 +00:00
|
|
|
#include <dns/rdataclass.h>
|
|
|
|
#include <dns/rdatatype.h>
|
1999-01-15 03:30:36 +00:00
|
|
|
#include <dns/rdatalist.h>
|
|
|
|
#include <dns/rdataset.h>
|
1999-01-06 20:05:09 +00:00
|
|
|
#include <dns/compress.h>
|
|
|
|
|
1999-01-13 19:11:26 +00:00
|
|
|
#define DNS_FLAG_QR 0x8000U
|
|
|
|
#define DNS_FLAG_AA 0x0400U
|
|
|
|
#define DNS_FLAG_TC 0x0200U
|
|
|
|
#define DNS_FLAG_RD 0x0100U
|
|
|
|
#define DNS_FLAG_RA 0x0080U
|
|
|
|
|
|
|
|
#define DNS_OPCODE_MASK 0x7000U
|
|
|
|
#define DNS_OPCODE_SHIFT 11
|
|
|
|
#define DNS_RCODE_MASK 0x000FU
|
|
|
|
|
|
|
|
typedef struct dns_message {
|
|
|
|
unsigned int id;
|
|
|
|
unsigned int flags;
|
|
|
|
unsigned int qcount;
|
|
|
|
unsigned int ancount;
|
|
|
|
unsigned int aucount;
|
|
|
|
unsigned int adcount;
|
|
|
|
dns_namelist_t question;
|
|
|
|
dns_namelist_t answer;
|
|
|
|
dns_namelist_t authority;
|
|
|
|
dns_namelist_t additional;
|
|
|
|
} dns_message_t;
|
|
|
|
|
|
|
|
#define MAX_PREALLOCATED 100
|
|
|
|
|
1999-01-06 20:05:09 +00:00
|
|
|
dns_decompress_t dctx;
|
1999-01-13 19:11:26 +00:00
|
|
|
unsigned int rdcount, rlcount, ncount;
|
|
|
|
dns_name_t names[MAX_PREALLOCATED];
|
|
|
|
dns_rdata_t rdatas[MAX_PREALLOCATED];
|
|
|
|
dns_rdatalist_t lists[MAX_PREALLOCATED];
|
1999-01-06 05:42:58 +00:00
|
|
|
|
1999-01-19 19:50:10 +00:00
|
|
|
void getmessage(dns_message_t *message, isc_buffer_t *source,
|
|
|
|
isc_buffer_t *target);
|
|
|
|
dns_result_t printmessage(dns_message_t *message);
|
|
|
|
|
1999-01-13 19:50:05 +00:00
|
|
|
#ifdef NOISY
|
1999-01-06 05:42:58 +00:00
|
|
|
static void
|
|
|
|
print_wirename(isc_region_t *name) {
|
|
|
|
unsigned char *ccurr, *cend;
|
|
|
|
|
|
|
|
ccurr = name->base;
|
|
|
|
cend = ccurr + name->length;
|
|
|
|
while (ccurr != cend)
|
|
|
|
printf("%02x ", *ccurr++);
|
|
|
|
printf("\n");
|
|
|
|
}
|
1999-01-13 19:50:05 +00:00
|
|
|
#endif
|
1999-01-06 05:42:58 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
fromhex(char c) {
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
return (c - '0');
|
|
|
|
else if (c >= 'a' && c <= 'f')
|
|
|
|
return (c - 'a' + 10);
|
|
|
|
else if (c >= 'A' && c <= 'F')
|
|
|
|
return (c - 'A' + 10);
|
|
|
|
printf("bad input format: %02x\n", c);
|
|
|
|
exit(3);
|
|
|
|
}
|
|
|
|
|
1999-01-07 02:08:05 +00:00
|
|
|
static isc_uint16_t
|
1999-01-06 05:42:58 +00:00
|
|
|
getshort(isc_buffer_t *buffer) {
|
|
|
|
isc_region_t r;
|
|
|
|
|
|
|
|
isc_buffer_remaining(buffer, &r);
|
|
|
|
if (r.length < 2) {
|
|
|
|
printf("not enough input\n");
|
|
|
|
exit(5);
|
|
|
|
}
|
|
|
|
|
1999-01-07 02:08:05 +00:00
|
|
|
return (isc_buffer_getuint16(buffer));
|
1999-01-06 05:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
1999-01-13 19:11:26 +00:00
|
|
|
getname(dns_name_t *name, isc_buffer_t *source, isc_buffer_t *target) {
|
1999-01-06 05:42:58 +00:00
|
|
|
unsigned char c[255];
|
|
|
|
dns_result_t result;
|
1999-01-13 19:11:26 +00:00
|
|
|
isc_buffer_t text;
|
1999-01-06 05:42:58 +00:00
|
|
|
unsigned int current;
|
1999-01-13 19:50:05 +00:00
|
|
|
#ifdef NOISY
|
|
|
|
isc_region_t r;
|
|
|
|
#endif
|
1999-01-06 05:42:58 +00:00
|
|
|
|
|
|
|
isc_buffer_init(&text, c, 255, ISC_BUFFERTYPE_TEXT);
|
1999-01-13 19:11:26 +00:00
|
|
|
dns_name_init(name, NULL);
|
1999-01-06 05:42:58 +00:00
|
|
|
|
|
|
|
current = source->current;
|
1999-01-13 19:11:26 +00:00
|
|
|
result = dns_name_fromwire(name, source, &dctx, ISC_FALSE, target);
|
1999-01-06 05:42:58 +00:00
|
|
|
|
1999-01-13 19:11:26 +00:00
|
|
|
#ifdef NOISY
|
1999-01-06 05:42:58 +00:00
|
|
|
if (result == DNS_R_SUCCESS) {
|
1999-01-13 19:11:26 +00:00
|
|
|
dns_name_toregion(name, &r);
|
1999-01-06 05:42:58 +00:00
|
|
|
print_wirename(&r);
|
|
|
|
printf("%u labels, %u bytes.\n",
|
1999-01-13 19:11:26 +00:00
|
|
|
dns_name_countlabels(name),
|
1999-01-06 05:42:58 +00:00
|
|
|
r.length);
|
1999-01-13 19:11:26 +00:00
|
|
|
result = dns_name_totext(name, ISC_FALSE, &text);
|
1999-01-06 05:42:58 +00:00
|
|
|
if (result == DNS_R_SUCCESS) {
|
|
|
|
isc_buffer_used(&text, &r);
|
|
|
|
printf("%.*s\n", (int)r.length, r.base);
|
|
|
|
} else
|
|
|
|
printf("%s\n", dns_result_totext(result));
|
|
|
|
} else
|
|
|
|
printf("%s\n", dns_result_totext(result));
|
1999-01-13 19:11:26 +00:00
|
|
|
#else
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
printf("%s\n", dns_result_totext(result));
|
|
|
|
#endif
|
1999-01-06 05:42:58 +00:00
|
|
|
|
|
|
|
return (source->current - current);
|
|
|
|
}
|
|
|
|
|
1999-01-13 19:11:26 +00:00
|
|
|
static void
|
|
|
|
getquestions(isc_buffer_t *source, dns_namelist_t *section, unsigned int count,
|
|
|
|
isc_buffer_t *target)
|
|
|
|
{
|
|
|
|
unsigned int type, class;
|
|
|
|
dns_name_t *name, *curr;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
|
|
|
|
|
|
|
ISC_LIST_INIT(*section);
|
|
|
|
while (count > 0) {
|
|
|
|
count--;
|
|
|
|
|
|
|
|
if (ncount == MAX_PREALLOCATED) {
|
|
|
|
printf("out of names\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
name = &names[ncount++];
|
|
|
|
(void)getname(name, source, target);
|
|
|
|
for (curr = ISC_LIST_HEAD(*section);
|
|
|
|
curr != NULL;
|
|
|
|
curr = ISC_LIST_NEXT(curr, link)) {
|
|
|
|
if (dns_name_compare(curr, name) == 0) {
|
|
|
|
ncount--;
|
|
|
|
name = curr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (name != curr)
|
|
|
|
ISC_LIST_APPEND(*section, name, link);
|
|
|
|
type = getshort(source);
|
|
|
|
class = getshort(source);
|
|
|
|
for (rdatalist = ISC_LIST_HEAD(name->list);
|
|
|
|
rdatalist != NULL;
|
|
|
|
rdatalist = ISC_LIST_NEXT(rdatalist, link)) {
|
|
|
|
if (rdatalist->class == class &&
|
|
|
|
rdatalist->type == type)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rdatalist == NULL) {
|
|
|
|
if (rlcount == MAX_PREALLOCATED) {
|
|
|
|
printf("out of rdatalists\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
rdatalist = &lists[rlcount++];
|
|
|
|
rdatalist->class = class;
|
|
|
|
rdatalist->type = type;
|
|
|
|
rdatalist->ttl = 0;
|
|
|
|
ISC_LIST_INIT(rdatalist->rdata);
|
1999-01-13 19:50:05 +00:00
|
|
|
ISC_LIST_APPEND(name->list, rdatalist, link);
|
1999-01-13 19:11:26 +00:00
|
|
|
} else
|
|
|
|
printf(";; duplicate question\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
getsection(isc_buffer_t *source, dns_namelist_t *section, unsigned int count,
|
|
|
|
isc_buffer_t *target)
|
|
|
|
{
|
|
|
|
unsigned int type, class, ttl, rdlength;
|
|
|
|
isc_region_t r;
|
|
|
|
dns_name_t *name, *curr;
|
|
|
|
dns_rdata_t *rdata;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
1999-01-20 02:43:23 +00:00
|
|
|
dns_result_t result;
|
1999-01-13 19:11:26 +00:00
|
|
|
|
|
|
|
ISC_LIST_INIT(*section);
|
|
|
|
while (count > 0) {
|
|
|
|
count--;
|
|
|
|
|
|
|
|
if (ncount == MAX_PREALLOCATED) {
|
|
|
|
printf("out of names\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
name = &names[ncount++];
|
|
|
|
(void)getname(name, source, target);
|
|
|
|
for (curr = ISC_LIST_HEAD(*section);
|
|
|
|
curr != NULL;
|
|
|
|
curr = ISC_LIST_NEXT(curr, link)) {
|
|
|
|
if (dns_name_compare(curr, name) == 0) {
|
|
|
|
ncount--;
|
|
|
|
name = curr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (name != curr)
|
|
|
|
ISC_LIST_APPEND(*section, name, link);
|
|
|
|
type = getshort(source);
|
|
|
|
class = getshort(source);
|
|
|
|
ttl = getshort(source);
|
|
|
|
ttl *= 65536;
|
|
|
|
ttl += getshort(source);
|
|
|
|
rdlength = getshort(source);
|
|
|
|
isc_buffer_remaining(source, &r);
|
|
|
|
if (r.length < rdlength) {
|
|
|
|
printf("unexpected end of rdata\n");
|
|
|
|
exit(7);
|
|
|
|
}
|
1999-01-20 02:43:23 +00:00
|
|
|
isc_buffer_setactive(source, rdlength);
|
|
|
|
if (rdcount == MAX_PREALLOCATED) {
|
|
|
|
printf("out of rdata\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
rdata = &rdatas[rdcount++];
|
|
|
|
result = dns_rdata_fromwire(rdata, class, type,
|
|
|
|
source, &dctx, ISC_FALSE,
|
|
|
|
target);
|
|
|
|
if (result != DNS_R_SUCCESS) {
|
|
|
|
printf("%s\n", dns_result_totext(result));
|
|
|
|
exit(1);
|
1999-01-13 19:11:26 +00:00
|
|
|
}
|
|
|
|
for (rdatalist = ISC_LIST_HEAD(name->list);
|
|
|
|
rdatalist != NULL;
|
|
|
|
rdatalist = ISC_LIST_NEXT(rdatalist, link)) {
|
|
|
|
if (rdatalist->class == class &&
|
|
|
|
rdatalist->type == type)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rdatalist == NULL) {
|
|
|
|
if (rlcount == MAX_PREALLOCATED) {
|
|
|
|
printf("out of rdatalists\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
rdatalist = &lists[rlcount++];
|
|
|
|
rdatalist->class = class;
|
|
|
|
rdatalist->type = type;
|
|
|
|
rdatalist->ttl = ttl;
|
|
|
|
ISC_LIST_INIT(rdatalist->rdata);
|
|
|
|
ISC_LIST_APPEND(name->list, rdatalist, link);
|
|
|
|
} else {
|
|
|
|
if (ttl < rdatalist->ttl)
|
|
|
|
rdatalist->ttl = ttl;
|
|
|
|
}
|
|
|
|
|
|
|
|
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-19 06:35:54 +00:00
|
|
|
void
|
1999-01-15 08:04:27 +00:00
|
|
|
getmessage(dns_message_t *message, isc_buffer_t *source,
|
|
|
|
isc_buffer_t *target)
|
|
|
|
{
|
|
|
|
isc_region_t r;
|
|
|
|
|
|
|
|
message->id = getshort(source);
|
|
|
|
message->flags = getshort(source);
|
|
|
|
message->qcount = getshort(source);
|
|
|
|
message->ancount = getshort(source);
|
|
|
|
message->aucount = getshort(source);
|
|
|
|
message->adcount = getshort(source);
|
|
|
|
|
|
|
|
getquestions(source, &message->question, message->qcount, target);
|
|
|
|
getsection(source, &message->answer, message->ancount, target);
|
|
|
|
getsection(source, &message->authority, message->aucount, target);
|
|
|
|
getsection(source, &message->additional, message->adcount, target);
|
|
|
|
|
|
|
|
isc_buffer_remaining(source, &r);
|
|
|
|
if (r.length != 0)
|
|
|
|
printf("extra data at end of packet.\n");
|
|
|
|
}
|
|
|
|
|
1999-01-13 19:11:26 +00:00
|
|
|
static char *opcodetext[] = {
|
|
|
|
"QUERY",
|
|
|
|
"IQUERY",
|
|
|
|
"STATUS",
|
|
|
|
"RESERVED3",
|
|
|
|
"NOTIFY",
|
|
|
|
"UPDATE",
|
|
|
|
"RESERVED6",
|
|
|
|
"RESERVED7",
|
|
|
|
"RESERVED8",
|
|
|
|
"RESERVED9",
|
|
|
|
"RESERVED10",
|
|
|
|
"RESERVED11",
|
|
|
|
"RESERVED12",
|
|
|
|
"RESERVED13",
|
|
|
|
"RESERVED14",
|
|
|
|
"RESERVED15"
|
|
|
|
};
|
|
|
|
|
|
|
|
static char *rcodetext[] = {
|
|
|
|
"NOERROR",
|
|
|
|
"FORMERR",
|
|
|
|
"SERVFAIL",
|
|
|
|
"NXDOMAIN",
|
|
|
|
"NOTIMPL",
|
|
|
|
"REFUSED",
|
|
|
|
"YXDOMAIN",
|
|
|
|
"YXRRSET",
|
|
|
|
"NXRRSET",
|
|
|
|
"NOTAUTH",
|
|
|
|
"NOTZONE",
|
|
|
|
"RESERVED11",
|
|
|
|
"RESERVED12",
|
|
|
|
"RESERVED13",
|
|
|
|
"RESERVED14",
|
|
|
|
"RESERVED15"
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
printquestions(dns_namelist_t *section) {
|
1999-01-13 19:50:05 +00:00
|
|
|
dns_name_t *name;
|
|
|
|
dns_rdatalist_t *rdatalist;
|
|
|
|
char t[1000];
|
|
|
|
isc_buffer_t target;
|
|
|
|
dns_result_t result;
|
|
|
|
|
|
|
|
printf(";; QUERY SECTION:\n");
|
|
|
|
for (name = ISC_LIST_HEAD(*section);
|
|
|
|
name != NULL;
|
|
|
|
name = ISC_LIST_NEXT(name, link)) {
|
|
|
|
isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_TEXT);
|
|
|
|
result = dns_name_totext(name, ISC_FALSE, &target);
|
|
|
|
if (result != DNS_R_SUCCESS) {
|
|
|
|
printf("%s\n", dns_result_totext(result));
|
|
|
|
exit(15);
|
|
|
|
}
|
|
|
|
for (rdatalist = ISC_LIST_HEAD(name->list);
|
|
|
|
rdatalist != NULL;
|
|
|
|
rdatalist = ISC_LIST_NEXT(rdatalist, link)) {
|
1999-01-20 07:49:50 +00:00
|
|
|
printf(";;\t%.*s, type = ", (int)target.used,
|
|
|
|
(char *)target.base);
|
|
|
|
isc_buffer_clear(&target);
|
1999-01-25 21:41:52 +00:00
|
|
|
result = dns_rdatatype_totext(rdatalist->type,
|
|
|
|
&target);
|
|
|
|
if (result != DNS_R_SUCCESS) {
|
|
|
|
printf("%s\n",
|
|
|
|
dns_result_totext(result));
|
|
|
|
exit(16);
|
1999-01-20 07:49:50 +00:00
|
|
|
}
|
|
|
|
printf("%.*s, class = ", (int)target.used,
|
|
|
|
(char *)target.base);
|
|
|
|
isc_buffer_clear(&target);
|
|
|
|
result = dns_rdataclass_totext(rdatalist->class,
|
|
|
|
&target);
|
|
|
|
if (result != DNS_R_SUCCESS) {
|
|
|
|
printf("%s\n", dns_result_totext(result));
|
|
|
|
exit(17);
|
|
|
|
}
|
|
|
|
printf("%.*s\n", (int)target.used,
|
|
|
|
(char *)target.base);
|
1999-01-13 19:50:05 +00:00
|
|
|
}
|
|
|
|
}
|
1999-01-13 19:11:26 +00:00
|
|
|
}
|
|
|
|
|
1999-01-15 19:36:33 +00:00
|
|
|
static dns_result_t
|
1999-01-13 19:11:26 +00:00
|
|
|
printsection(dns_namelist_t *section, char *section_name) {
|
1999-01-15 20:02:22 +00:00
|
|
|
dns_name_t *name, *print_name;
|
1999-01-13 19:11:26 +00:00
|
|
|
dns_rdatalist_t *rdatalist;
|
1999-01-15 19:36:33 +00:00
|
|
|
dns_rdataset_t rdataset;
|
1999-01-13 19:11:26 +00:00
|
|
|
isc_buffer_t target;
|
|
|
|
dns_result_t result;
|
1999-01-15 19:36:33 +00:00
|
|
|
isc_region_t r;
|
1999-01-15 20:02:22 +00:00
|
|
|
dns_name_t empty_name;
|
1999-01-15 19:36:33 +00:00
|
|
|
char t[1000];
|
1999-01-15 20:02:22 +00:00
|
|
|
isc_boolean_t first;
|
1999-01-13 19:11:26 +00:00
|
|
|
|
1999-01-15 19:36:33 +00:00
|
|
|
dns_rdataset_init(&rdataset);
|
1999-01-15 20:02:22 +00:00
|
|
|
dns_name_init(&empty_name, NULL);
|
1999-01-13 19:11:26 +00:00
|
|
|
printf("\n;; %s SECTION:\n", section_name);
|
|
|
|
for (name = ISC_LIST_HEAD(*section);
|
|
|
|
name != NULL;
|
|
|
|
name = ISC_LIST_NEXT(name, link)) {
|
|
|
|
isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_TEXT);
|
1999-01-15 20:02:22 +00:00
|
|
|
first = ISC_TRUE;
|
|
|
|
print_name = name;
|
1999-01-13 19:11:26 +00:00
|
|
|
for (rdatalist = ISC_LIST_HEAD(name->list);
|
|
|
|
rdatalist != NULL;
|
|
|
|
rdatalist = ISC_LIST_NEXT(rdatalist, link)) {
|
1999-01-15 19:36:33 +00:00
|
|
|
result = dns_rdatalist_tordataset(rdatalist,
|
|
|
|
&rdataset);
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
return (result);
|
1999-01-15 20:02:22 +00:00
|
|
|
result = dns_rdataset_totext(&rdataset, print_name,
|
1999-01-15 19:36:33 +00:00
|
|
|
ISC_FALSE, &target);
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
1999-01-15 20:02:22 +00:00
|
|
|
#ifdef USEINITALWS
|
|
|
|
if (first) {
|
|
|
|
print_name = &empty_name;
|
|
|
|
first = ISC_FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
1999-01-13 19:11:26 +00:00
|
|
|
}
|
1999-01-15 19:36:33 +00:00
|
|
|
isc_buffer_used(&target, &r);
|
|
|
|
printf("%.*s", (int)r.length, (char *)r.base);
|
1999-01-13 19:11:26 +00:00
|
|
|
}
|
1999-01-15 19:36:33 +00:00
|
|
|
|
|
|
|
return (DNS_R_SUCCESS);
|
1999-01-13 19:11:26 +00:00
|
|
|
}
|
|
|
|
|
1999-01-19 06:35:54 +00:00
|
|
|
dns_result_t
|
1999-01-13 19:11:26 +00:00
|
|
|
printmessage(dns_message_t *message) {
|
|
|
|
isc_boolean_t did_flag = ISC_FALSE;
|
|
|
|
unsigned int opcode, rcode;
|
1999-01-15 19:36:33 +00:00
|
|
|
dns_result_t result;
|
1999-01-13 19:11:26 +00:00
|
|
|
|
|
|
|
opcode = (message->flags & DNS_OPCODE_MASK) >> DNS_OPCODE_SHIFT;
|
|
|
|
rcode = message->flags & DNS_RCODE_MASK;
|
|
|
|
printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
|
|
|
|
opcodetext[opcode], rcodetext[rcode], message->id);
|
|
|
|
printf(";; flags: ");
|
|
|
|
if ((message->flags & DNS_FLAG_QR) != 0) {
|
|
|
|
printf("qr");
|
|
|
|
did_flag = ISC_TRUE;
|
|
|
|
}
|
|
|
|
if ((message->flags & DNS_FLAG_AA) != 0) {
|
|
|
|
printf("%saa", did_flag ? " " : "");
|
|
|
|
did_flag = ISC_TRUE;
|
|
|
|
}
|
|
|
|
if ((message->flags & DNS_FLAG_TC) != 0) {
|
|
|
|
printf("%stc", did_flag ? " " : "");
|
|
|
|
did_flag = ISC_TRUE;
|
|
|
|
}
|
|
|
|
if ((message->flags & DNS_FLAG_RD) != 0) {
|
|
|
|
printf("%srd", did_flag ? " " : "");
|
|
|
|
did_flag = ISC_TRUE;
|
|
|
|
}
|
|
|
|
if ((message->flags & DNS_FLAG_RA) != 0) {
|
|
|
|
printf("%sra", did_flag ? " " : "");
|
|
|
|
did_flag = ISC_TRUE;
|
|
|
|
}
|
1999-01-13 19:58:40 +00:00
|
|
|
printf("; QUERY: %u, ANSWER: %u, AUTHORITY: %u, ADDITIONAL: %u\n",
|
1999-01-13 19:11:26 +00:00
|
|
|
message->qcount, message->ancount, message->aucount,
|
|
|
|
message->adcount);
|
|
|
|
printquestions(&message->question);
|
1999-01-15 19:36:33 +00:00
|
|
|
result = printsection(&message->answer, "ANSWER");
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = printsection(&message->authority, "AUTHORITY");
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
return (result);
|
|
|
|
result = printsection(&message->additional, "ADDITIONAL");
|
|
|
|
|
|
|
|
return (result);
|
1999-01-13 19:11:26 +00:00
|
|
|
}
|
|
|
|
|
1999-01-19 06:35:54 +00:00
|
|
|
#ifndef NOMAIN
|
1999-01-06 05:42:58 +00:00
|
|
|
int
|
|
|
|
main(int argc, char *argv[]) {
|
1999-01-13 19:57:13 +00:00
|
|
|
char *rp, *wp;
|
1999-01-06 05:42:58 +00:00
|
|
|
unsigned char *bp;
|
1999-01-13 19:11:26 +00:00
|
|
|
isc_buffer_t source, target;
|
1999-01-06 05:42:58 +00:00
|
|
|
size_t len, i;
|
|
|
|
int n;
|
|
|
|
FILE *f;
|
|
|
|
isc_boolean_t need_close = ISC_FALSE;
|
1999-01-13 19:11:26 +00:00
|
|
|
unsigned char b[1000];
|
|
|
|
char s[1000];
|
|
|
|
char t[5000];
|
|
|
|
dns_message_t message;
|
1999-01-15 19:36:33 +00:00
|
|
|
dns_result_t result;
|
1999-01-06 05:42:58 +00:00
|
|
|
|
|
|
|
if (argc > 1) {
|
|
|
|
f = fopen(argv[1], "r");
|
|
|
|
if (f == NULL) {
|
|
|
|
printf("fopen failed\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
need_close = ISC_TRUE;
|
|
|
|
} else
|
|
|
|
f = stdin;
|
|
|
|
|
|
|
|
bp = b;
|
|
|
|
while (fgets(s, sizeof s, f) != NULL) {
|
1999-01-13 19:57:13 +00:00
|
|
|
rp = s;
|
|
|
|
wp = s;
|
|
|
|
len = 0;
|
|
|
|
while (*rp != '\0') {
|
|
|
|
if (*rp != ' ' && *rp != '\t' &&
|
|
|
|
*rp != '\r' && *rp != '\n') {
|
|
|
|
*wp++ = *rp;
|
|
|
|
len++;
|
|
|
|
}
|
|
|
|
rp++;
|
1999-01-06 05:42:58 +00:00
|
|
|
}
|
|
|
|
if (len == 0)
|
|
|
|
break;
|
|
|
|
if (len % 2 != 0) {
|
|
|
|
printf("bad input format: %d\n", len);
|
|
|
|
exit(1);
|
|
|
|
}
|
1999-01-13 19:57:13 +00:00
|
|
|
if (len > (sizeof b) * 2) {
|
1999-01-06 05:42:58 +00:00
|
|
|
printf("input too long\n");
|
|
|
|
exit(2);
|
|
|
|
}
|
1999-01-13 19:57:13 +00:00
|
|
|
rp = s;
|
1999-01-06 05:42:58 +00:00
|
|
|
for (i = 0; i < len; i += 2) {
|
1999-01-13 19:57:13 +00:00
|
|
|
n = fromhex(*rp++);
|
1999-01-06 05:42:58 +00:00
|
|
|
n *= 16;
|
1999-01-13 19:57:13 +00:00
|
|
|
n += fromhex(*rp++);
|
1999-01-06 05:42:58 +00:00
|
|
|
*bp++ = n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (need_close)
|
|
|
|
fclose(f);
|
1999-01-06 20:05:09 +00:00
|
|
|
|
1999-01-13 19:11:26 +00:00
|
|
|
rdcount = 0;
|
|
|
|
rlcount = 0;
|
|
|
|
ncount = 0;
|
|
|
|
|
|
|
|
dctx.allowed = DNS_COMPRESS_GLOBAL14;
|
1999-01-09 00:34:18 +00:00
|
|
|
dns_name_init(&dctx.owner_name, NULL);
|
1999-01-06 20:05:09 +00:00
|
|
|
|
1999-01-13 19:11:26 +00:00
|
|
|
isc_buffer_init(&source, b, sizeof b, ISC_BUFFERTYPE_BINARY);
|
1999-01-06 05:42:58 +00:00
|
|
|
isc_buffer_add(&source, bp - b);
|
1999-01-13 19:11:26 +00:00
|
|
|
isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_BINARY);
|
|
|
|
|
1999-01-15 08:04:27 +00:00
|
|
|
getmessage(&message, &source, &target);
|
1999-01-15 19:36:33 +00:00
|
|
|
result = printmessage(&message);
|
|
|
|
if (result != DNS_R_SUCCESS)
|
|
|
|
printf("printmessage() failed: %s\n",
|
|
|
|
dns_result_totext(result));
|
1999-01-13 19:11:26 +00:00
|
|
|
|
1999-01-06 05:42:58 +00:00
|
|
|
return (0);
|
|
|
|
}
|
1999-01-19 06:35:54 +00:00
|
|
|
#endif /* !NOMAIN */
|