message.c revision 15a44745412679c30a6d022733925af70a38b715
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.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15a44745412679c30a6d022733925af70a38b715David Lawrence * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
15a44745412679c30a6d022733925af70a38b715David Lawrence * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15a44745412679c30a6d022733925af70a38b715David Lawrence/* $Id: message.c,v 1.137 2000/07/27 09:46:15 tale Exp $ */
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 \
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer#define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
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
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic const char *sectiontext[] = {
58c40ca8bda08458804d7f15cf97942dea2a17acMichael Sawyerstatic const char *updsectiontext[] = {
58c40ca8bda08458804d7f15cf97942dea2a17acMichael Sawyer "PREREQUISITE",
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic const char *opcodetext[] = {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED10",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED11",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED12",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED13",
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer "RESERVED14",
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrencestatic const 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
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);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtonmsgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_message_renderrelease(msg, msg->sig_reserved);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington INSIST(dns_rdataset_isassociated(msg->tsig));
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington isc_mempool_put(msg->rdspool, msg->querytsig);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington isc_mempool_put(msg->namepool, msg->tsigname);
6dc130c7c95107748fff5f767161c2bb742f9f87Brian Wellington } else if (msg->querytsig != NULL && !replying) {
22057930cd2a71e1073781b650c7296739c869a6Brian Wellington isc_mempool_put(msg->rdspool, msg->querytsig);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington INSIST(dns_rdataset_isassociated(msg->sig0));
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington isc_mempool_put(msg->namepool, msg->sig0name);
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.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtonstatic unsigned int
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtonspacefortsig(dns_tsigkey_t *key, int otherlen) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington unsigned int x;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * The space required for an TSIG record is:
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * n1 bytes for the name
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the type
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the class
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 4 bytes for the ttl
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 6 bytes for the time signed
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the fudge
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the MAC size
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * x bytes for the MAC
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the original id
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the error
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the other data length
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * y bytes for the other data (at most)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * ---------------------------------
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 30 + n1 + n2 + x + y bytes
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington return (24 + r1.length + r2.length + x + otherlen);
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));
99eba32b06d21623b14161bd6543c91201d9cbafAndreas Gustafssonfindname(dns_name_t **foundname, dns_name_t *target,
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
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * dereferenced, but it must still be non-NULL. Casting
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * 1 rather than "" avoids warnings about discarding
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * the const attribute of a string, for compilers that
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence * would warn about such things.
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.
99eba32b06d21623b14161bd6543c91201d9cbafAndreas Gustafsson result = findname(&name2, name, section);
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.
167f530b5bd1f8cd218fdffb221bb87d773aaf03Michael Sawyer (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, rdclass,
99eba32b06d21623b14161bd6543c91201d9cbafAndreas Gustafsson result = getrdata(source, msg, dctx, msg->rdclass,
2f6040ed6717dd47da8afb20da053ce408f702a8Bob Halley if (rdtype == dns_rdatatype_sig && rdata->length > 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 ||
c637772ac34b4abb76a250eca89930e6f2bc2ce9Brian 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.
99eba32b06d21623b14161bd6543c91201d9cbafAndreas Gustafsson result = findname(&name2, name, 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.
c637772ac34b4abb76a250eca89930e6f2bc2ce9Brian 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,
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if (msg->tsig != NULL || msg->tsigkey != NULL || msg->sig0 != 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) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_availableregion(msg->buffer, &r);
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,
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington * If we're adding a TSIG or SIG(0) to a truncated message,
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington * clear all rdatasets from the message except for the question
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington * before adding the TSIG or SIG(0).
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if ((msg->tsigkey != NULL || msg->sig0key != NULL) &&
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington * If we're adding a TSIG record, generate and render it.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_message_renderrelease(msg, msg->sig_reserved);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington result = dns_rdataset_towire(msg->tsig, msg->tsigname,
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington msg->counts[DNS_SECTION_ADDITIONAL] += count;
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington * If we're adding a SIG(0) record, generate and render it.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_message_renderrelease(msg, msg->sig_reserved);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington result = dns_dnssec_signmessage(msg, msg->sig0key);
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington * Note: dns_rootname is used here, not msg->sig0name, since
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington * the owner name of a SIG(0) is irrelevant, and will not
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington * be set in a message being rendered.
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,
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.
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.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * This saves the query TSIG status, if the query was signed, and
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * reserves space in the reply for the TSIG.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington unsigned int otherlen = 0;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (msg->querytsigstatus == dns_tsigerror_badtime)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_message_renderreserve(msg, msg->sig_reserved);
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'.
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellingtondns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington * Set the TSIG key for 'msg'
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellingtondns_message_gettsigkey(dns_message_t *msg) {
af602636644fdfaabc331bd926b0aabb9432e152Brian Wellington * Get the TSIG key for 'msg'
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtondns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_message_gettemprdata(msg, &rdata);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_message_gettemprdatalist(msg, &list);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_message_gettemprdataset(msg, &set);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = isc_buffer_allocate(msg->mctx, &buf, r.length);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_rdatalist_tordataset(list, set);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtondns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington REQUIRE(querytsig != NULL && *querytsig == NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = isc_buffer_allocate(mctx, querytsig, r.length);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington isc_buffer_putmem(*querytsig, r.base, r.length);
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellingtondns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington * Get the SIG(0) record for 'msg'.
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington /* If dns_message_getsig0 is called on a rendered message
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington * after the SIG(0) has been applied, we need to return the
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington * root name, not NULL.
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtondns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington unsigned int x;
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * Set the SIG(0) key for 'msg'
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * The space required for an SIG(0) record is:
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 1 byte for the name
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the type
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the class
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 4 bytes for the ttl
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the type covered
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 1 byte for the algorithm
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 1 bytes for the labels
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 4 bytes for the original ttl
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 4 bytes for the signature expiration
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 4 bytes for the signature inception
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 2 bytes for the key tag
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * n bytes for the signer's name
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * x bytes for the signature
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * ---------------------------------
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * 27 + n + x bytes
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_message_renderreserve(msg, msg->sig_reserved);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellingtondns_message_getsig0key(dns_message_t *msg) {
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington * Get the SIG(0) key 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);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if (msg->tsig == NULL && msg->sig0 == NULL)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_rdata_tostruct(&rdata, &sig, NULL);
5caab9f99d19ab9ebb0a0ba64c09c8de80e89e29Brian Wellington if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
0f80bfec687db08a6e6ce945ef1d818da06c7ca9Brian Wellington result = dns_rdata_tostruct(&rdata, &tsig, NULL);
0b764d91c9021259f15b32c4beec852f2888f40cBrian Wellington identity = dns_tsigkey_identity(msg->tsigkey);
b984520acca2532d048eae929dc0682dd334c7a3Brian Wellingtondns_message_checksig(dns_message_t *msg, dns_view_t *view) {
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence isc_buffer_init(&msgb, msg->saved->base, msg->saved->length);
fe0e3c7707580da885bb6819e4f307986eb60cd0Brian Wellington if (msg->tsigkey != NULL || msg->tsig != NULL)
6f17d90364f01c3e81073a9ffb40b0093878c8e2Brian Wellington return (dns_view_checksig(view, &msgb, msg));
81b438273a0c3141144d169a7ccb110150757337Brian Wellington * This can occur when the message is a dynamic update, since
81b438273a0c3141144d169a7ccb110150757337Brian Wellington * the rdata length checking is relaxed. This should not
81b438273a0c3141144d169a7ccb110150757337Brian Wellington * happen in a well-formed message, since the SIG(0) is only
81b438273a0c3141144d169a7ccb110150757337Brian Wellington * looked for in the additional section, and the dynamic update
81b438273a0c3141144d169a7ccb110150757337Brian Wellington * meta-records are in the prerequisite and update sections.
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);
a9bc95f22ef2dd4a12e79be99412c9f18b814a5dBrian Wellington result = dst_key_fromdns(&sig.signer, &b, view->mctx,
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,
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer omit_final_dot = ISC_TF((flags & DNS_MESSAGETEXTFLAG_OMITDOT) != 0);
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer result = dns_message_firstname(msg, section);
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer dns_message_currentname(msg, section, &name);
d1eee4693871f9e02fc8598e2e2f8fac80df25a3Brian Wellington result = dns_rdataset_totext(rdataset, name,
194de894f0697562f94e048f573d99260a18a639Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0)
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyerdns_message_pseudosectiontotext(dns_message_t *msg,
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer omit_final_dot = ISC_TF((flags & DNS_MESSAGETEXTFLAG_OMITDOT) != 0);
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_rdataset_totext(ps, name, omit_final_dot,
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
41faaa9b35bb5b3c72ca964e108ba398eaa63f3dBrian Wellington result = dns_rdataset_totext(ps, name, omit_final_dot,
194de894f0697562f94e048f573d99260a18a639Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0)
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyerdns_message_totext(dns_message_t *msg, dns_messagetextflag_t flags,
c7868e2262d57451c7f0ce246be5f44e8c33f1e0Michael Sawyer if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
c95a89b433e42ecf9108b6c263f405fecc0d8a65Michael Sawyer ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
9b3a69e6a701ffe2fc49fbb750d0761b3a822b37Michael Sawyer sprintf(buf, "%1u", msg->counts[DNS_SECTION_QUESTION]);
9b3a69e6a701ffe2fc49fbb750d0761b3a822b37Michael Sawyer sprintf(buf, "%1u", msg->counts[DNS_SECTION_ANSWER]);
9b3a69e6a701ffe2fc49fbb750d0761b3a822b37Michael Sawyer sprintf(buf, "%1u", msg->counts[DNS_SECTION_AUTHORITY]);
9b3a69e6a701ffe2fc49fbb750d0761b3a822b37Michael Sawyer sprintf(buf, "%1u", msg->counts[DNS_SECTION_ADDITIONAL]);
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_message_pseudosectiontotext(msg,
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
1ed4ba5a1fcb6aecd1c92fdcc75c6b4bbb7cc60fMichael Sawyer result = dns_message_pseudosectiontotext(msg,