2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-23 10:39:16 +00:00
bind/bin/tests/wire_test.c

569 lines
13 KiB
C
Raw Normal View History

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>
#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);
}
}
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)) {
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);
}
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
}
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
}
#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);
}
#endif /* !NOMAIN */