mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 17:30:22 -04:00
checkpoint
This commit is contained in:
parent
08dbab20ef
commit
8198371caa
1 changed files with 348 additions and 72 deletions
|
|
@ -15,6 +15,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define NOISY
|
||||
#include <config.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
|
@ -29,9 +30,39 @@
|
|||
#include <dns/types.h>
|
||||
#include <dns/result.h>
|
||||
#include <dns/name.h>
|
||||
#include <dns/rdata.h>
|
||||
#include <dns/compress.h>
|
||||
|
||||
#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
|
||||
|
||||
dns_decompress_t dctx;
|
||||
unsigned int rdcount, rlcount, ncount;
|
||||
dns_name_t names[MAX_PREALLOCATED];
|
||||
dns_rdata_t rdatas[MAX_PREALLOCATED];
|
||||
dns_rdatalist_t lists[MAX_PREALLOCATED];
|
||||
|
||||
static void
|
||||
print_wirename(isc_region_t *name) {
|
||||
|
|
@ -70,29 +101,27 @@ getshort(isc_buffer_t *buffer) {
|
|||
}
|
||||
|
||||
static unsigned int
|
||||
getname(isc_buffer_t *source) {
|
||||
unsigned char t[255];
|
||||
getname(dns_name_t *name, isc_buffer_t *source, isc_buffer_t *target) {
|
||||
unsigned char c[255];
|
||||
dns_result_t result;
|
||||
dns_name_t name;
|
||||
isc_buffer_t target, text;
|
||||
isc_buffer_t text;
|
||||
isc_region_t r;
|
||||
unsigned int current;
|
||||
|
||||
isc_buffer_init(&target, t, 255, ISC_BUFFERTYPE_BINARY);
|
||||
isc_buffer_init(&text, c, 255, ISC_BUFFERTYPE_TEXT);
|
||||
dns_name_init(&name, NULL);
|
||||
dns_name_init(name, NULL);
|
||||
|
||||
current = source->current;
|
||||
result = dns_name_fromwire(&name, source, &dctx, ISC_FALSE, &target);
|
||||
result = dns_name_fromwire(name, source, &dctx, ISC_FALSE, target);
|
||||
|
||||
#ifdef NOISY
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
dns_name_toregion(&name, &r);
|
||||
dns_name_toregion(name, &r);
|
||||
print_wirename(&r);
|
||||
printf("%u labels, %u bytes.\n",
|
||||
dns_name_countlabels(&name),
|
||||
dns_name_countlabels(name),
|
||||
r.length);
|
||||
result = dns_name_totext(&name, 0, &text);
|
||||
result = dns_name_totext(name, ISC_FALSE, &text);
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
isc_buffer_used(&text, &r);
|
||||
printf("%.*s\n", (int)r.length, r.base);
|
||||
|
|
@ -100,23 +129,309 @@ getname(isc_buffer_t *source) {
|
|||
printf("%s\n", dns_result_totext(result));
|
||||
} else
|
||||
printf("%s\n", dns_result_totext(result));
|
||||
#else
|
||||
if (result != DNS_R_SUCCESS)
|
||||
printf("%s\n", dns_result_totext(result));
|
||||
#endif
|
||||
|
||||
return (source->current - current);
|
||||
}
|
||||
|
||||
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) {
|
||||
ISC_LIST(dns_rdatalist_t) list;
|
||||
|
||||
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);
|
||||
list.head = name->list.head;
|
||||
list.tail = name->list.tail;
|
||||
ISC_LIST_APPEND(list, rdatalist, link);
|
||||
} 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_name_t rname;
|
||||
unsigned char *data, *sdata;
|
||||
dns_rdata_t *rdata;
|
||||
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);
|
||||
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);
|
||||
}
|
||||
data = (unsigned char *)target->base + target->used;
|
||||
/* This is also naughty. */
|
||||
if (type == 2 && class == 1) {
|
||||
if (getname(&rname, source, target) != rdlength) {
|
||||
printf("rdata length mismatch\n");
|
||||
exit(11);
|
||||
}
|
||||
} else {
|
||||
isc_region_t r;
|
||||
|
||||
isc_buffer_available(target, &r);
|
||||
if (r.length < rdlength) {
|
||||
printf("no space in target\n");
|
||||
exit(12);
|
||||
}
|
||||
sdata = (unsigned char *)source->base +
|
||||
source->current;
|
||||
memcpy(data, sdata, (size_t)rdlength);
|
||||
isc_buffer_add(target, rdlength);
|
||||
isc_buffer_forward(source, rdlength);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
if (rdcount == MAX_PREALLOCATED) {
|
||||
printf("out of rdata\n");
|
||||
exit(1);
|
||||
}
|
||||
rdata = &rdatas[rdcount++];
|
||||
|
||||
/* This is naughty. */
|
||||
rdata->class = class;
|
||||
rdata->type = type;
|
||||
rdata->data = data;
|
||||
rdata->length = rdlength;
|
||||
|
||||
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
printf("\n;; QUERY SECTION:\n");
|
||||
}
|
||||
|
||||
static void
|
||||
printsection(dns_namelist_t *section, char *section_name) {
|
||||
dns_name_t *name;
|
||||
dns_rdatalist_t *rdatalist;
|
||||
dns_rdata_t *rdata;
|
||||
char t[1000];
|
||||
isc_buffer_t target;
|
||||
dns_result_t result;
|
||||
|
||||
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);
|
||||
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)) {
|
||||
for (rdata = ISC_LIST_HEAD(rdatalist->rdata);
|
||||
rdata != NULL;
|
||||
rdata = ISC_LIST_NEXT(rdata, link)) {
|
||||
printf("%.*s\t%u %u %u\t",
|
||||
(int)target.used,
|
||||
target.base,
|
||||
rdatalist->ttl,
|
||||
rdatalist->class,
|
||||
rdatalist->type);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
printmessage(dns_message_t *message) {
|
||||
isc_boolean_t did_flag = ISC_FALSE;
|
||||
unsigned int opcode, rcode;
|
||||
|
||||
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;
|
||||
}
|
||||
printf("; QUERY: %u ANSWER: %u, AUTHORITY: %u, ADDITIONAL: %u\n",
|
||||
message->qcount, message->ancount, message->aucount,
|
||||
message->adcount);
|
||||
printquestions(&message->question);
|
||||
printsection(&message->answer, "ANSWER");
|
||||
printsection(&message->authority, "AUTHORITY");
|
||||
printsection(&message->additional, "ADDITIONAL");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
char s[1000];
|
||||
char *cp;
|
||||
unsigned char *bp;
|
||||
unsigned char b[255];
|
||||
isc_buffer_t source;
|
||||
isc_buffer_t source, target;
|
||||
isc_region_t r;
|
||||
size_t len, i;
|
||||
int n;
|
||||
FILE *f;
|
||||
isc_boolean_t need_close = ISC_FALSE;
|
||||
unsigned int ui, tc, type, class;
|
||||
unsigned char b[1000];
|
||||
char s[1000];
|
||||
char t[5000];
|
||||
dns_message_t message;
|
||||
|
||||
if (argc > 1) {
|
||||
f = fopen(argv[1], "r");
|
||||
|
|
@ -157,73 +472,34 @@ main(int argc, char *argv[]) {
|
|||
if (need_close)
|
||||
fclose(f);
|
||||
|
||||
dctx.allowed = DNS_COMPRESS_GLOBAL14 | DNS_COMPRESS_GLOBAL16;
|
||||
rdcount = 0;
|
||||
rlcount = 0;
|
||||
ncount = 0;
|
||||
|
||||
dctx.allowed = DNS_COMPRESS_GLOBAL14;
|
||||
dns_name_init(&dctx.owner_name, NULL);
|
||||
|
||||
isc_buffer_init(&source, b, 255, ISC_BUFFERTYPE_BINARY);
|
||||
isc_buffer_init(&source, b, sizeof b, ISC_BUFFERTYPE_BINARY);
|
||||
isc_buffer_add(&source, bp - b);
|
||||
isc_buffer_init(&target, t, sizeof t, ISC_BUFFERTYPE_BINARY);
|
||||
|
||||
ui = getshort(&source);
|
||||
printf("id = %u\n", ui);
|
||||
ui = getshort(&source);
|
||||
printf("2nd short = %u\n", ui);
|
||||
ui = getshort(&source);
|
||||
printf("qdcount = %u\n", ui);
|
||||
if (ui > 1) {
|
||||
printf("qdcount > 1 not supported\n");
|
||||
exit(6);
|
||||
}
|
||||
if (ui == 0) {
|
||||
printf("qdcount 0\n");
|
||||
exit(6);
|
||||
}
|
||||
ui = getshort(&source);
|
||||
printf("ancount = %u\n", ui);
|
||||
tc = ui;
|
||||
ui = getshort(&source);
|
||||
printf("nscount = %u\n", ui);
|
||||
tc += ui;
|
||||
ui = getshort(&source);
|
||||
printf("arcount = %u\n", ui);
|
||||
tc += ui;
|
||||
message.id = getshort(&source);
|
||||
message.flags = getshort(&source);
|
||||
message.qcount = getshort(&source);
|
||||
message.ancount = getshort(&source);
|
||||
message.aucount = getshort(&source);
|
||||
message.adcount = getshort(&source);
|
||||
|
||||
(void)getname(&source);
|
||||
ui = getshort(&source);
|
||||
printf("type = %u\n", ui);
|
||||
ui = getshort(&source);
|
||||
printf("class = %u\n\n", ui);
|
||||
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);
|
||||
|
||||
while (tc > 0) {
|
||||
tc--;
|
||||
|
||||
(void)getname(&source);
|
||||
type = getshort(&source);
|
||||
printf("type = %u\n", type);
|
||||
class = getshort(&source);
|
||||
printf("class = %u\n", class);
|
||||
ui = getshort(&source);
|
||||
ui *= 65536;
|
||||
ui += getshort(&source);
|
||||
printf("ttl = %u\n", ui);
|
||||
ui = getshort(&source);
|
||||
printf("rdlength = %u\n", ui);
|
||||
isc_buffer_remaining(&source, &r);
|
||||
if (r.length < ui) {
|
||||
printf("unexpected end of rdata\n");
|
||||
exit(7);
|
||||
}
|
||||
if (type == 2 && class == 1) {
|
||||
if (getname(&source) != ui) {
|
||||
printf("rdata length mismatch\n");
|
||||
exit(11);
|
||||
}
|
||||
} else
|
||||
isc_buffer_forward(&source, ui);
|
||||
printf("\n");
|
||||
}
|
||||
isc_buffer_remaining(&source, &r);
|
||||
if (r.length != 0)
|
||||
printf("extra data at end of packet.\n");
|
||||
|
||||
printmessage(&message);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue