parse dynamic updates, and tsig's right
This commit is contained in:
@@ -244,11 +244,6 @@ resolve_packet(isc_mem_t *mctx, dns_message_t *query, isc_buffer_t *target) {
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_OPT,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_TSIG,
|
||||
0, 0);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
|
||||
@@ -220,8 +220,7 @@ printmessage(dns_message_t *msg) {
|
||||
msg->counts[DNS_SECTION_ANSWER],
|
||||
msg->counts[DNS_SECTION_AUTHORITY],
|
||||
msg->counts[DNS_SECTION_ADDITIONAL]);
|
||||
printf("; PSEUDOSECTIONS: OPT: %u, TSIG: %u\n",
|
||||
msg->counts[DNS_SECTION_OPT],
|
||||
printf("; PSEUDOSECTIONS: TSIG: %u\n",
|
||||
msg->counts[DNS_SECTION_TSIG]);
|
||||
|
||||
result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION");
|
||||
@@ -234,9 +233,6 @@ printmessage(dns_message_t *msg) {
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
result = printsection(msg, DNS_SECTION_ADDITIONAL, "ADDITIONAL");
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
result = printsection(msg, DNS_SECTION_OPT, "PSEUDOSECTION OPT");
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
result = printsection(msg, DNS_SECTION_TSIG, "PSEUDOSECTION TSIG");
|
||||
@@ -354,10 +350,6 @@ main(int argc, char *argv[]) {
|
||||
0, 0);
|
||||
CHECKRESULT(result, "dns_message_rendersection(ADDITIONAL) failed");
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_OPT,
|
||||
0, 0);
|
||||
CHECKRESULT(result, "dns_message_rendersection(OPT) failed");
|
||||
|
||||
result = dns_message_rendersection(message, DNS_SECTION_TSIG,
|
||||
0, 0);
|
||||
CHECKRESULT(result, "dns_message_rendersection(TSIG) failed");
|
||||
|
||||
@@ -80,9 +80,15 @@ typedef int dns_section_t;
|
||||
#define DNS_SECTION_ANSWER 1
|
||||
#define DNS_SECTION_AUTHORITY 2
|
||||
#define DNS_SECTION_ADDITIONAL 3
|
||||
#define DNS_SECTION_OPT 4 /* pseudo-section */
|
||||
#define DNS_SECTION_TSIG 5 /* pseudo-section */
|
||||
#define DNS_SECTION_MAX 6
|
||||
#define DNS_SECTION_TSIG 4 /* pseudo-section */
|
||||
#define DNS_SECTION_MAX 5
|
||||
|
||||
/*
|
||||
* Dynamic update named for these sections.
|
||||
*/
|
||||
#define DNS_SECTION_ZONE DNS_SECTION_QUESTION
|
||||
#define DNS_SECTION_PREREQUISITE DNS_SECTION_ANSWER
|
||||
#define DNS_SECTION_UPDATE DNS_SECTION_AUTHORITY
|
||||
|
||||
/*
|
||||
* These tell the message library how the created dns_message_t will be used.
|
||||
@@ -102,10 +108,11 @@ typedef struct {
|
||||
unsigned int opcode;
|
||||
dns_rdataclass_t rdclass;
|
||||
|
||||
/* 4 real, 2 pseudo */
|
||||
/* 4 real, 1 pseudo */
|
||||
unsigned int counts[DNS_SECTION_MAX];
|
||||
dns_namelist_t sections[DNS_SECTION_MAX];
|
||||
dns_name_t *cursors[DNS_SECTION_MAX];
|
||||
dns_rdata_t *opt;
|
||||
|
||||
int state;
|
||||
unsigned int from_to_wire : 2;
|
||||
|
||||
@@ -110,6 +110,16 @@ enum {
|
||||
dns_rcode_badmode = 19
|
||||
};
|
||||
|
||||
/*
|
||||
* opcodes
|
||||
*/
|
||||
enum {
|
||||
dns_opcode_query = 0,
|
||||
dns_opcode_iquery = 1,
|
||||
dns_opcode_status = 2,
|
||||
dns_opcode_update = 5 /* dynamic update */
|
||||
};
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_TYPES_H */
|
||||
|
||||
@@ -329,6 +329,7 @@ msginit(dns_message_t *m)
|
||||
m->cursors[i] = NULL;
|
||||
m->counts[i] = 0;
|
||||
}
|
||||
m->opt = NULL;
|
||||
|
||||
m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
|
||||
|
||||
@@ -750,12 +751,13 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx)
|
||||
rdclass = isc_buffer_getuint16(source);
|
||||
|
||||
/*
|
||||
* If this class is different than the one we alrady read,
|
||||
* If this class is different than the one we already read,
|
||||
* this is an error.
|
||||
*/
|
||||
if (msg->state == DNS_SECTION_ANY) {
|
||||
msg->state = DNS_SECTION_QUESTION;
|
||||
msg->rdclass = rdclass;
|
||||
msg->state = DNS_SECTION_QUESTION;
|
||||
} else if (msg->rdclass != rdclass)
|
||||
return (DNS_R_FORMERR);
|
||||
|
||||
@@ -764,7 +766,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx)
|
||||
* If it was found, this is an error, return FORMERR.
|
||||
*/
|
||||
result = findtype(NULL, name, rdtype);
|
||||
|
||||
if (result == DNS_R_SUCCESS)
|
||||
return (DNS_R_FORMERR);
|
||||
|
||||
@@ -812,9 +813,9 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
dns_ttl_t ttl;
|
||||
dns_namelist_t *section;
|
||||
|
||||
section = &msg->sections[sectionid];
|
||||
|
||||
for (count = 0 ; count < msg->counts[sectionid] ; count++) {
|
||||
section = &msg->sections[sectionid];
|
||||
|
||||
name = newname(msg);
|
||||
if (name == NULL)
|
||||
return (DNS_R_NOMEMORY);
|
||||
@@ -828,24 +829,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
if (result != DNS_R_SUCCESS)
|
||||
return (result);
|
||||
|
||||
/*
|
||||
* Run through the section, looking to see if this name
|
||||
* is already there. If it is found, put back the allocated
|
||||
* name since we no longer need it, and set our name pointer
|
||||
* to point to the name we found.
|
||||
*/
|
||||
result = findname(&name2, name, section);
|
||||
|
||||
/*
|
||||
* If it is a new name, append to the section.
|
||||
*/
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
releasename(msg, name);
|
||||
name = name2;
|
||||
} else {
|
||||
ISC_LIST_APPEND(*section, name, link);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get type, class, ttl, and rdatalen. Verify that at least
|
||||
* rdatalen bytes remain. (Some of this is deferred to
|
||||
@@ -858,14 +841,21 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
rdclass = isc_buffer_getuint16(source);
|
||||
|
||||
/*
|
||||
* If this class is different than the one we already read,
|
||||
* this is an error.
|
||||
* If this class is different than the one in the question
|
||||
* section, bail.
|
||||
*/
|
||||
if (msg->state == DNS_SECTION_ANY) {
|
||||
msg->state = sectionid;
|
||||
msg->rdclass = rdclass;
|
||||
} else if (msg->rdclass != rdclass)
|
||||
if (msg->rdclass != rdclass)
|
||||
return (DNS_R_FORMERR);
|
||||
|
||||
/*
|
||||
* If it is a tsig, verify that it is in the additional data
|
||||
* section, and switch sections for the rest of this rdata.
|
||||
*/
|
||||
if (rdtype == dns_rdatatype_tsig) {
|
||||
if (sectionid != DNS_SECTION_ADDITIONAL)
|
||||
return (DNS_R_FORMERR);
|
||||
section = &msg->sections[DNS_SECTION_TSIG];
|
||||
}
|
||||
|
||||
/*
|
||||
* ... now get ttl and rdatalen, and check buffer.
|
||||
@@ -877,10 +867,49 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
return (DNS_R_UNEXPECTEDEND);
|
||||
|
||||
/*
|
||||
* Search name for the particular type and class.
|
||||
* If it was found, this is an error, return FORMERR.
|
||||
* If we are doing a dynamic update don't bother searching
|
||||
* for a name, just append this one to the end of the message.
|
||||
*/
|
||||
result = findtype(&rdataset, name, rdtype);
|
||||
if (msg->opcode == dns_opcode_update
|
||||
|| rdtype == dns_rdatatype_tsig) {
|
||||
ISC_LIST_APPEND(*section, name, link);
|
||||
} else {
|
||||
/*
|
||||
* Run through the section, looking to see if this name
|
||||
* is already there. If it is found, put back the
|
||||
* allocated name since we no longer need it, and set
|
||||
* our name pointer to point to the name we found.
|
||||
*/
|
||||
result = findname(&name2, name, section);
|
||||
|
||||
/*
|
||||
* If it is a new name, append to the section.
|
||||
*/
|
||||
if (result == DNS_R_SUCCESS) {
|
||||
releasename(msg, name);
|
||||
name = name2;
|
||||
} else {
|
||||
ISC_LIST_APPEND(*section, name, link);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is an OPT record, There Can Be Only One.
|
||||
*/
|
||||
#if 0 /* until there is a dns_rdatatype_opt XXXMLG */
|
||||
if (rdtype == dns_rdatatype_opt && msg->opt != NULL)
|
||||
return (DNS_R_FORMERR);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Search name for the particular type and class.
|
||||
* Skip this stage if in update mode, or this is a TSIG.
|
||||
*/
|
||||
if (msg->opcode == dns_opcode_update
|
||||
|| rdtype == dns_rdatatype_tsig)
|
||||
result = DNS_R_NOTFOUND;
|
||||
else
|
||||
result = findtype(&rdataset, name, rdtype);
|
||||
|
||||
/*
|
||||
* If we found an rdataset that matches, we need to
|
||||
@@ -928,6 +957,14 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
rdatalist = (dns_rdatalist_t *)(rdataset->private1);
|
||||
|
||||
ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
|
||||
|
||||
/*
|
||||
* If this is an OPT record, remember it.
|
||||
*/
|
||||
#if 0 /* until there is a dns_rdatatype_opt XXXMLG */
|
||||
if (rdtype == dns_rdatatype_opt)
|
||||
msg->opt = rdata;
|
||||
#endif
|
||||
}
|
||||
|
||||
return (DNS_R_SUCCESS);
|
||||
@@ -1176,7 +1213,7 @@ dns_message_renderend(dns_message_t *msg)
|
||||
{
|
||||
isc_buffer_t tmpbuf;
|
||||
isc_region_t r;
|
||||
isc_uint16_t tmpflags;
|
||||
isc_uint16_t tmp;
|
||||
|
||||
REQUIRE(VALID_MESSAGE(msg));
|
||||
REQUIRE(msg->buffer != NULL);
|
||||
@@ -1186,16 +1223,18 @@ dns_message_renderend(dns_message_t *msg)
|
||||
|
||||
isc_buffer_putuint16(&tmpbuf, msg->id);
|
||||
|
||||
tmpflags = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
|
||||
& DNS_MESSAGE_OPCODE_MASK);
|
||||
tmpflags |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); /* XXX edns? */
|
||||
tmpflags |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
|
||||
tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
|
||||
& DNS_MESSAGE_OPCODE_MASK);
|
||||
tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); /* XXX edns? */
|
||||
tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
|
||||
|
||||
isc_buffer_putuint16(&tmpbuf, tmpflags);
|
||||
isc_buffer_putuint16(&tmpbuf, tmp);
|
||||
isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_QUESTION]);
|
||||
isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_ANSWER]);
|
||||
isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_AUTHORITY]);
|
||||
isc_buffer_putuint16(&tmpbuf, msg->counts[DNS_SECTION_ADDITIONAL]);
|
||||
tmp = msg->counts[DNS_SECTION_ADDITIONAL]
|
||||
+ msg->counts[DNS_SECTION_TSIG];
|
||||
isc_buffer_putuint16(&tmpbuf, tmp);
|
||||
|
||||
msg->buffer = NULL; /* forget about this buffer only on success XXX */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user