message.c revision 0fd13c7aca8533fbc86e4c7aa326cc828844b9b5
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999, 2000 Internet Software Consortium.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Permission to use, copy, modify, and distribute this software for any
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * purpose with or without fee is hereby granted, provided that the above
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * copyright notice and this permission notice appear in all copies.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
6028d1ce0380d0ba7f6c6ecd1ad20b31ddd1becbDavid Lawrence#include <isc/string.h> /* Required for HP/UX (and others?) */
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
f9df80f4348ef68043903efa08299480324f4823Michael Graff#define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer return(ISC_R_NOSPACE); else \
f9df80f4348ef68043903efa08299480324f4823Michael Graff * This is the size of each individual scratchpad buffer, and the numbers
f9df80f4348ef68043903efa08299480324f4823Michael Graff * of various block allocations used within the server.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * XXXMLG These should come from a config setting.
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer * Text representation of the different items, for message_totext
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyerstatic char *sectiontext[] = {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyerstatic char *opcodetext[] = {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED10",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED11",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED12",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED13",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED14",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyerstatic char *rcodetext[] = {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED11",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED12",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED13",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED14",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED15",
f9df80f4348ef68043903efa08299480324f4823Michael Graff * "helper" type, which consists of a block of some type, and is linkable.
f9df80f4348ef68043903efa08299480324f4823Michael Graff * For it to work, sizeof(dns_msgblock_t) must be a multiple of the pointer
f9df80f4348ef68043903efa08299480324f4823Michael Graff * size, or the allocated elements will not be alligned correctly.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff unsigned int count;
f9df80f4348ef68043903efa08299480324f4823Michael Graff}; /* dynamically sized */
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ((type *)msgblock_internalget(block, sizeof(type)))
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void *
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_internalget(dns_msgblock_t *, unsigned int);
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic inline void
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffstatic inline void
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graffmsgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Allocate a new dns_msgblock_t, and return a pointer to it. If no memory
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * is free, return NULL.
f9df80f4348ef68043903efa08299480324f4823Michael Graffmsgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int count)
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff unsigned int length;
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff length = sizeof(dns_msgblock_t) + (sizeof_type * count);
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Return an element from the msgblock. If no more are available, return
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void *
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencemsgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
8c55a67a6d185de7036e39da30561a5c1637d22bAndreas Gustafsson if (block == NULL || block->remaining == 0)
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic inline void
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graff * Release memory associated with a message block.
9178881e1bf6a4b01db886b355406c8bed61cc2aMichael Graffstatic inline void
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencemsgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff unsigned int length;
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Allocate a new dynamic buffer, and attach it to this message as the
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * "current" buffer. (which is always the last on the list, for our
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencenewbuffer(dns_message_t *msg, unsigned int size) {
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencereleaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_PREPEND(msg->freerdata, rdata, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline dns_rdata_t *
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffstatic inline void
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencereleaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
f9df80f4348ef68043903efa08299480324f4823Michael Graffstatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley unsigned int i;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley for (i = 0; i < DNS_SECTION_MAX; i++) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff m->state = DNS_SECTION_ANY; /* indicate nothing parsed or rendered */
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellingtonstatic inline void
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington m->tsigstatus = m->querytsigstatus = dns_rcode_noerror;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * Init elements to default state. Used both when allocating a new element
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * and when resetting one.
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleystatic inline void
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleymsgresetnames(dns_message_t *msg, unsigned int first_section) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int i;
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Clean up name lists by calling the rdataset disassociate function.
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley for (i = first_section; i < DNS_SECTION_MAX; i++) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->sections[i], name, link);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley dns_message_renderrelease(msg, msg->opt_reserved);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington INSIST(dns_rdataset_isassociated(msg->tsigset));
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington isc_mempool_put(msg->rdspool, msg->tsigset);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington isc_mempool_put(msg->namepool, msg->tsigname);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington INSIST(dns_rdataset_isassociated(msg->sig0));
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * Free all but one (or everything) for this message. This is used by
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * both dns_message_reset() and dns_message_parse().
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencemsgreset(dns_message_t *msg, isc_boolean_t everything) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Clean up linked lists.
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff * Run through the free lists, and just unlink anything found there.
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff * The memory isn't lost since these are part of message blocks we
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff * have allocated.
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
70fd62761dfe44f2254fb63ac3ded1b02663713fMichael Graff rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * rdatalists could be empty.
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff next_msgblock = ISC_LIST_NEXT(msgblock, link);
ddd035637d92035a0d9e2bc32a7e2c9cc8a99d3fMichael Graff ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_mem_put(msg->mctx, msg->query->base, msg->query->length);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington isc_mem_put(msg->mctx, msg->query, sizeof(isc_region_t));
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington isc_mem_put(msg->mctx, msg->saved->base, msg->saved->length);
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington isc_mem_put(msg->mctx, msg->saved, sizeof(isc_region_t));
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * cleanup the buffer cleanup list
069104dd6a1bba610d0c3a413459accf73f3921bBrian Wellington ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Set other bits to normal default values.
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleydns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
f9df80f4348ef68043903efa08299480324f4823Michael Graff unsigned int i;
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * No allocations until further notice. Just initialize all lists
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * and other members that are freed in the cleanup phase here.
f9df80f4348ef68043903efa08299480324f4823Michael Graff for (i = 0 ; i < DNS_SECTION_MAX ; i++)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff * Ok, it is safe to allocate (and then "goto cleanup" if failure)
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_setfreemax(m->namepool, NAME_COUNT);
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff isc_mempool_setfillcount(m->namepool, NAME_COUNT);
0583bf2d0affe0a90ca2284cc27840b160029ff9Michael Graff isc_mempool_setname(m->namepool, "msg:names");
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
d8f304288d2fb29fccd2da1672d72ea06af73f8dMichael Graff isc_mempool_setfillcount(m->rdspool, NAME_COUNT);
0583bf2d0affe0a90ca2284cc27840b160029ff9Michael Graff isc_mempool_setname(m->rdspool, "msg:rdataset");
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_rdata_t),
f9df80f4348ef68043903efa08299480324f4823Michael Graff msgblock = msgblock_allocate(mctx, sizeof(dns_rdatalist_t),
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(m->rdatalists, msgblock, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Cleanup for error returns.
af6e7e5cd2643e2aaaffefe1dd804a03394b4928Michael Graff msgblock_free(mctx, msgblock, sizeof(dns_rdata_t));
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_reset(dns_message_t *msg, unsigned int intent) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halleyfindname(dns_name_t **foundname, dns_name_t *target, unsigned int attributes,
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graffdns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff dns_rdatatype_t covers, dns_rdataset_t **rdataset)
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley if (curr->type == type && curr->covers == covers) {
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Read a name from buffer "source".
e223094b2248afa2697c531f75e6f84855638becMichael Graffgetname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
e223094b2248afa2697c531f75e6f84855638becMichael Graff unsigned int tries;
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * First try: use current buffer.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * Second try: allocate a new buffer and use that.
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson result = newbuffer(msg, SCRATCHPAD_SIZE);
ecb6c5782ea248307e86c4bceac6c371d27576a6David Lawrencegetrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
ecb6c5782ea248307e86c4bceac6c371d27576a6David Lawrence dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff unsigned int tries;
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * In dynamic update messages, the rdata can be empty.
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson if (msg->opcode == dns_opcode_update && rdatalen == 0) {
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * When the rdata is empty, the data pointer is never
3b40e78974c55304af90c7c9c63af7e933846543Andreas Gustafsson * dereferenced, but it must still be non-NULL.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * First try: use current buffer.
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * Second try: allocate a new buffer of size
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen)
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * (the data will fit if it was not more than 50% compressed)
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson * Subsequent tries: double buffer size on each try.
9dee95b41cfe1d33d542cc2ec0337d66b28b75abBrian Wellington /* XXX possibly change this to a while (tries < 2) loop */
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff result = dns_rdata_fromwire(rdata, rdclass, rdtype,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson /* XXX DNS_R_RRTOOLONG? */
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffgetquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx)
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff unsigned int count;
e223094b2248afa2697c531f75e6f84855638becMichael Graff section = &msg->sections[DNS_SECTION_QUESTION];
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (count = 0 ; count < msg->counts[DNS_SECTION_QUESTION] ; count++) {
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Parse the name out of this packet.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Run through the section, looking to see if this name
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * is already there. If it is found, put back the allocated
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * name since we no longer need it, and set our name pointer
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * to point to the name we found.
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * If it is the first name in the section, accept it.
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * If it is not, but is not the same as the name already
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * in the question section, append to the section. Note that
e223094b2248afa2697c531f75e6f84855638becMichael Graff * here in the question section this is illegal, so return
e223094b2248afa2697c531f75e6f84855638becMichael Graff * FORMERR. In the future, check the opcode to see if
e223094b2248afa2697c531f75e6f84855638becMichael Graff * this should be legal or not. In either case we no longer
e223094b2248afa2697c531f75e6f84855638becMichael Graff * need this name pointer.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Get type and class.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If this class is different than the one we already read,
e223094b2248afa2697c531f75e6f84855638becMichael Graff * this is an error.
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff * If this is a type that cannot occur in a question section,
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff * return failure.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff * Can't ask the same question twice.
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff result = dns_message_findtype(name, rdtype, 0, NULL);
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Allocate a new rdatalist.
d68838693666ba930ec4143f848c18bff2bfc244Michael Graff * Convert rdatalist to rdataset, and attach the latter to
e223094b2248afa2697c531f75e6f84855638becMichael Graff result = dns_rdatalist_tordataset(rdatalist, rdataset);
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
d68838693666ba930ec4143f848c18bff2bfc244Michael Graffgetsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson dns_section_t sectionid, isc_boolean_t preserve_order)
e223094b2248afa2697c531f75e6f84855638becMichael Graff for (count = 0 ; count < msg->counts[sectionid] ; count++) {
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley isc_boolean_t skip_name_search, skip_type_search;
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Parse the name out of this packet.
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Get type, class, ttl, and rdatalen. Verify that at least
e223094b2248afa2697c531f75e6f84855638becMichael Graff * rdatalen bytes remain. (Some of this is deferred to
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson * If there was no question section, we may not yet have
57cf89b149a6c4a9794c24613f9b765e02a54b2fAndreas Gustafsson * established a class. Do so now.
fb12d257efa7dad8ab467d51cb7e5081f4f22b34Michael Graff if (rdclass == 0 || rdclass == dns_rdataclass_any) {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If this class is different than the one in the question
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * section, bail.
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington && rdtype != dns_rdatatype_key /* XXX in a TKEY query */
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington && rdtype != dns_rdatatype_sig /* XXX SIG(0) */
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington * Special type handling for TSIG, OPT, and TKEY.
bf555703f27295798de30fa8c04d727410788f66Bob Halley * If it is a tsig, verify that it is in the
bf555703f27295798de30fa8c04d727410788f66Bob Halley * additional data section, and switch sections for
bf555703f27295798de30fa8c04d727410788f66Bob Halley * the rest of this rdata.
bf555703f27295798de30fa8c04d727410788f66Bob Halley * The name of an OPT record must be ".", it
bf555703f27295798de30fa8c04d727410788f66Bob Halley * must be in the additional data section, and
bf555703f27295798de30fa8c04d727410788f66Bob Halley * it must be the first OPT we've seen.
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington * A TKEY must be in the additional section if this
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington * is a query, and the answer section if this is a
1672aaee14415d8ce643ce401b4a29635dfd8fd6Brian Wellington * Its class is ignored.
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
e223094b2248afa2697c531f75e6f84855638becMichael Graff * ... now get ttl and rdatalen, and check buffer.
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * Read the rdata from the wire format. Interpret the
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * rdata according to its actual class, even if it had a
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * DynDNS meta-class in the packet (unless this is a TSIG).
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley * Then put the meta-class back into the finished rdata.
ecb6c5782ea248307e86c4bceac6c371d27576a6David Lawrence result = getrdata(source, msg, dctx, msg->rdclass,
ecb6c5782ea248307e86c4bceac6c371d27576a6David Lawrence result = getrdata(source, msg, dctx, rdclass,
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (rdtype == dns_rdatatype_sig && rdata->length > 0) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else if (covers == 0) {
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If we are doing a dynamic update don't bother searching
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * for a name, just append this one to the end of the message.
bf555703f27295798de30fa8c04d727410788f66Bob Halley if (preserve_order || msg->opcode == dns_opcode_update ||
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington !(rdtype == dns_rdatatype_sig && covers == 0))
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * Run through the section, looking to see if this name
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * is already there. If it is found, put back the
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * allocated name since we no longer need it, and set
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * our name pointer to point to the name we found.
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley result = findname(&name2, name, attributes, section);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * If it is a new name, append to the section.
e223094b2248afa2697c531f75e6f84855638becMichael Graff * Search name for the particular type and class.
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff * Skip this stage if in update mode, or this is a TSIG.
bf555703f27295798de30fa8c04d727410788f66Bob Halley if (preserve_order || msg->opcode == dns_opcode_update ||
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff * If this is a type that can only occur in
7ec579cd5d07228c0d6cece58b80694ad8d59de9Michael Graff * the question section, fail.
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff result = dns_message_findtype(name, rdtype, covers,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * If we found an rdataset that matches, we need to
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * append this rdata to that set. If we did not, we need
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * to create a new rdatalist, store the important bits there,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * convert it to an rdataset, and link the latter to the name.
3bb3b7ac462a90c2b8b1fb783324d800e2ba748cMichael Graff * Yuck. When appending, make certain that the type isn't
3bb3b7ac462a90c2b8b1fb783324d800e2ba748cMichael Graff * a singleton type, such as SOA or CNAME.
3bb3b7ac462a90c2b8b1fb783324d800e2ba748cMichael Graff * Note that this check will be bypassed when preserving order,
3bb3b7ac462a90c2b8b1fb783324d800e2ba748cMichael Graff * the opcode is an update, or the type search is skipped.
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff dns_rdatalist_tordataset(rdatalist, rdataset);
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * Minimize TTLs.
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * Section 5.2 of RFC 2181 says we should drop
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * nonauthoritative rrsets where the TTLs differ, but we
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * currently treat them the as if they were authoritative and
7ab5937e0b0d5d83e6f4eb1e50a4b041fb68df48Bob Halley * minimize them.
59602a44858a55fce25565491d4fec6d2cdcca19Michael Graff rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * XXXMLG Perform a totally ugly hack here to pull
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * the rdatalist out of the private field in the rdataset,
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff * and append this rdata to the rdatalist's linked list
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff rdatalist = (dns_rdatalist_t *)(rdataset->private1);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * If this is an OPT record, remember it. Also, set
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * the extended rcode.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley unsigned int ercode;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley ercode = (msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington * If this is an SIG(0) or TSIG record, remember it.
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington if (rdtype == dns_rdatatype_sig && covers == 0) {
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafssondns_message_parse(dns_message_t *msg, isc_buffer_t *source,
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
fccf7905e8a06067d49ec00c53d4d57a38a71e52Michael Graff msg->rcode = (tmpflags & DNS_MESSAGE_RCODE_MASK);
b02262cbcd550c63f85df76edc6fff556ea5e95dMichael Graff msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
e223094b2248afa2697c531f75e6f84855638becMichael Graff msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
d49555e76c5d02943fdd6606113aebf2317390d5Michael Graff * -1 means no EDNS.
94a08e09db3dc844b6ee4841c368a2d7074a9c3fAndreas Gustafsson dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY,
d347e7af94d77a83244cb592291ac0cc4edc4b62Andreas Gustafsson ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence if (msg->tsigset != NULL || msg->tsigkey != NULL ||
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved = isc_mem_get(msg->mctx, sizeof(isc_region_t));
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington msg->saved->base = isc_mem_get(msg->mctx, msg->saved->length);
5c688a008a28f215cd772377774e6a1ed07d0525Brian Wellington memcpy(msg->saved->base, r.base, msg->saved->length);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_renderbegin(dns_message_t *msg, isc_buffer_t *buffer) {
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Erase the contents of this buffer.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Make certain there is enough for at least the header in this
1d7987f4227c838f7fa790ad57255d3df3332ccaMichael Graff result = dns_compress_init(&msg->cctx, -1, msg->mctx);
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Reserve enough space for the header in this buffer.
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * Ensure that the new buffer is empty, and has enough space to
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * hold the current contents.
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff * Copy the contents from the old to the new buffer.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_renderrelease(dns_message_t *msg, unsigned int space) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_renderreserve(dns_message_t *msg, unsigned int space) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencewrong_priority(dns_rdataset_t *rds, int pass) {
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * If we are not rendering class IN, this ordering is bogus.
a920f559c3689f52731519a9d5169ad5814866edMichael Graffdns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff unsigned int options)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff && (options & DNS_MESSAGERENDER_ORDERED) == 0)
bfbf3f2d770dc093ac5c74d5fd716ac9521e8715Michael Graff * Shrink the space in the buffer by the reserved amount.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff next_rdataset = ISC_LIST_NEXT(rdataset, link);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * If out of space, record stats on what we
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * rendered so far, and return that status.
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * XXXMLG Need to change this when
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * dns_rdataset_towire() can render partial
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * sets starting at some arbitary point in the
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * set. This will include setting a bit in the
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * rdataset to indicate that a partial
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * rendering was done, and some state saved
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * somewhere (probably in the message struct)
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff * to indicate where to continue from.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * If we have rendered pending data, ensure
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence * that the AD bit is not set.
0fd13c7aca8533fbc86e4c7aa326cc828844b9b5Andreas Gustafsson if (rdataset->trust == dns_trust_pending &&
733b16eb0be2e15fa70db85291b386a3bef1d77cMichael Graff } while (--pass != 0);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
2726950412a5c598e123554e4d758fe66a2ebc21Michael Graff tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
c866769e664ba0a6a5e6f9375245f5ccca393009David Lawrence msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley unsigned int count;
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * We have an extended rcode but are not using EDNS.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * If we've got an OPT record, render it.
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley dns_message_renderrelease(msg, msg->opt_reserved);
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Set the extended rcode.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley result = dns_rdataset_towire(msg->opt, dns_rootname,
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington result = dns_rdataset_towire(msg->tsigset, msg->tsigname,
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington msg->counts[DNS_SECTION_ADDITIONAL] += count;
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_dnssec_signmessage(msg, msg->sig0key);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington result = dns_rdataset_towire(msg->sig0, dns_rootname,
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington msg->counts[DNS_SECTION_ADDITIONAL] += count;
e690d225ad09e0b4617554c753b68abc82f0583aMichael Graff msg->buffer = NULL; /* forget about this buffer only on success XXX */
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley unsigned int i;
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley * Reset the message so that it may be rendered again.
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
435abcf2e22d777afbdccdc3048d0ad3df65240aBob Halley for (i = 0; i < DNS_SECTION_MAX; i++) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_firstname(dns_message_t *msg, dns_section_t section) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_nextname(dns_message_t *msg, dns_section_t section) {
f9df80f4348ef68043903efa08299480324f4823Michael Graff msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_currentname(dns_message_t *msg, dns_section_t section,
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_findname(dns_message_t *msg, dns_section_t section,
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley unsigned int attributes;
f9df80f4348ef68043903efa08299480324f4823Michael Graff * XXX These requirements are probably too intensive, especially
f9df80f4348ef68043903efa08299480324f4823Michael Graff * where things can be NULL, but as they are they ensure that if
f9df80f4348ef68043903efa08299480324f4823Michael Graff * something is NON-NULL, indicating that the caller expects it
f9df80f4348ef68043903efa08299480324f4823Michael Graff * to be filled in, that we can in fact fill it in.
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley * Figure out what attributes we should look for.
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff * Search through, looking for the name.
004da17157c0a0eab619cc7c16aba897b9506d4bBob Halley result = findname(&foundname, target, attributes,
ded7456a4dc944742c4a98cbf7b055b860b7569cMichael Graff * And now look for the type.
186817c92c7bd1a65aa562d73415abee2e79922bMichael Graff result = dns_message_findtype(foundname, type, covers, rdataset);
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_movename(dns_message_t *msg, dns_name_t *name,
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff * Unlink the name from the old section
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(msg->sections[tosection], name, link);
f9df80f4348ef68043903efa08299480324f4823Michael Graffdns_message_addname(dns_message_t *msg, dns_name_t *name,
97e7d389d54a9e3a1ba8313ed140b04afabc7081Michael Graff REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
f9df80f4348ef68043903efa08299480324f4823Michael Graff ISC_LIST_APPEND(msg->sections[section], name, link);
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graffdns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff unsigned int *flagsp)
4c208bd46f94379b011b57ee7edb84ac9c706704Michael Graff unsigned int flags;
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halleydns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * We now clear most flags and then set QR, ensuring that the
d8705ff90a299e0aa9fc2b4286bc0a71cf221872Bob Halley * reply's flags will be in a reasonable state.
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * This saves the query TSIG information for later use, if there is
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * any. This only happens once - that is, if dns_message_reply
6d4886fa7430889a96dbf9b88a2a4eb6f9d04674Brian Wellington * has already moved the variables, this has no effect.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Get the OPT record for 'msg'.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halleydns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * Set the OPT record for 'msg'.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * The space required for an OPT record is:
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 1 byte for the name
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 2 bytes for the type
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 2 bytes for the class
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 4 bytes for the ttl
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * 2 bytes for the rdata length
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * ---------------------------------
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley * plus the length of the rdata.
ac77fece9a62537a9e0e5852498ebeda7b2978c3Bob Halley REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
5eb8688b78ddf13d46cd52561301c35d24a5d52aBob Halley result = dns_message_renderreserve(msg, msg->opt_reserved);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellingtondns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington * Get the TSIG record and owner for 'msg'.
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington * Get the SIG(0) record for 'msg'.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencedns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellingtondns_message_signer(dns_message_t *msg, dns_name_t *signer) {
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington if ((msg->tsig == NULL || msg->tsigkey == NULL) && msg->sig0 == NULL)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington else if (msg->tsig->error != dns_rcode_noerror)
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington identity = dns_tsigkey_identity(msg->tsigkey);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtondns_message_checksig(dns_message_t *msg, dns_view_t *view) {
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington if (msg->tsigkey == NULL && msg->tsigset == NULL && msg->sig0 == NULL)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&msgb, msg->saved->base, msg->saved->length);
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington if (msg->tsigkey != NULL || msg->tsigset != NULL)
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington return (dns_view_checksig(view, &msgb, msg));
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington result = dns_view_simplefind(view, &sig.signer,
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington /* XXXBEW Should possibly create a fetch here */
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington } else if (keyset.trust < dns_trust_secure) {
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington /* XXXBEW Should call a validator here */
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&b, rdata.data, rdata.length);
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington * XXXBEW should actually pass in the key name,
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington * but it's not used anyway.
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington result = dst_key_fromdns("", &b, view->mctx, &key);
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington result = dns_dnssec_verifymessage(&msgb, msg, key);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyerdns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer result = dns_message_firstname(msg, section);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer dns_message_currentname(msg, section, &name);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyerdns_message_totext(dns_message_t *msg, isc_boolean_t comments,
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer isc_boolean_t headers, isc_boolean_t omit_final_dot,
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer sprintf(buf, "%3u", msg->counts[DNS_SECTION_QUESTION]);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer sprintf(buf, "%3u", msg->counts[DNS_SECTION_ANSWER]);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer sprintf(buf, "%3u", msg->counts[DNS_SECTION_AUTHORITY]);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer sprintf(buf, "%3u", msg->counts[DNS_SECTION_ADDITIONAL]);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer ADD_STRING(target, ";; PSEUDOSECTIONS: TSIG\n");
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION])) {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY])) {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL])) {