00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <config.h>
00025 #include <ctype.h>
00026
00027 #include <isc/buffer.h>
00028 #include <isc/mem.h>
00029 #include <isc/print.h>
00030 #include <isc/string.h>
00031 #include <isc/util.h>
00032
00033 #include <dns/dnssec.h>
00034 #include <dns/keyvalues.h>
00035 #include <dns/log.h>
00036 #include <dns/masterdump.h>
00037 #include <dns/message.h>
00038 #include <dns/opcode.h>
00039 #include <dns/rdata.h>
00040 #include <dns/rdatalist.h>
00041 #include <dns/rdataset.h>
00042 #include <dns/rdatastruct.h>
00043 #include <dns/result.h>
00044 #include <dns/tsig.h>
00045 #include <dns/ttl.h>
00046 #include <dns/view.h>
00047
00048 #ifdef SKAN_MSG_DEBUG
00049 static void
00050 hexdump(const char *msg, const char *msg2, void *base, size_t len) {
00051 unsigned char *p;
00052 unsigned int cnt;
00053
00054 p = base;
00055 cnt = 0;
00056
00057 printf("*** %s [%s] (%u bytes @ %p)\n", msg, msg2, len, base);
00058
00059 while (cnt < len) {
00060 if (cnt % 16 == 0)
00061 printf("%p: ", p);
00062 else if (cnt % 8 == 0)
00063 printf(" |");
00064 printf(" %02x %c", *p, (isprint(*p) ? *p : ' '));
00065 p++;
00066 cnt++;
00067
00068 if (cnt % 16 == 0)
00069 printf("\n");
00070 }
00071
00072 if (cnt % 16 != 0)
00073 printf("\n");
00074 }
00075 #endif
00076
00077 #define DNS_MESSAGE_OPCODE_MASK 0x7800U
00078 #define DNS_MESSAGE_OPCODE_SHIFT 11
00079 #define DNS_MESSAGE_RCODE_MASK 0x000fU
00080 #define DNS_MESSAGE_FLAG_MASK 0x8ff0U
00081 #define DNS_MESSAGE_EDNSRCODE_MASK 0xff000000U
00082 #define DNS_MESSAGE_EDNSRCODE_SHIFT 24
00083 #define DNS_MESSAGE_EDNSVERSION_MASK 0x00ff0000U
00084 #define DNS_MESSAGE_EDNSVERSION_SHIFT 16
00085
00086 #define VALID_NAMED_SECTION(s) (((s) > DNS_SECTION_ANY) \
00087 && ((s) < DNS_SECTION_MAX))
00088 #define VALID_SECTION(s) (((s) >= DNS_SECTION_ANY) \
00089 && ((s) < DNS_SECTION_MAX))
00090 #define ADD_STRING(b, s) {if (strlen(s) >= \
00091 isc_buffer_availablelength(b)) \
00092 return(ISC_R_NOSPACE); else \
00093 isc_buffer_putstr(b, s);}
00094 #define VALID_PSEUDOSECTION(s) (((s) >= DNS_PSEUDOSECTION_ANY) \
00095 && ((s) < DNS_PSEUDOSECTION_MAX))
00096
00097 #define OPTOUT(x) (((x)->attributes & DNS_RDATASETATTR_OPTOUT) != 0)
00098
00099
00100
00101
00102
00103
00104 #define SCRATCHPAD_SIZE 512
00105 #define NAME_COUNT 8
00106 #define OFFSET_COUNT 4
00107 #define RDATA_COUNT 8
00108 #define RDATALIST_COUNT 8
00109 #define RDATASET_COUNT RDATALIST_COUNT
00110
00111
00112
00113
00114
00115 static const char *sectiontext[] = {
00116 "QUESTION",
00117 "ANSWER",
00118 "AUTHORITY",
00119 "ADDITIONAL"
00120 };
00121
00122 static const char *updsectiontext[] = {
00123 "ZONE",
00124 "PREREQUISITE",
00125 "UPDATE",
00126 "ADDITIONAL"
00127 };
00128
00129 static const char *opcodetext[] = {
00130 "QUERY",
00131 "IQUERY",
00132 "STATUS",
00133 "RESERVED3",
00134 "NOTIFY",
00135 "UPDATE",
00136 "RESERVED6",
00137 "RESERVED7",
00138 "RESERVED8",
00139 "RESERVED9",
00140 "RESERVED10",
00141 "RESERVED11",
00142 "RESERVED12",
00143 "RESERVED13",
00144 "RESERVED14",
00145 "RESERVED15"
00146 };
00147
00148 static const char *rcodetext[] = {
00149 "NOERROR",
00150 "FORMERR",
00151 "SERVFAIL",
00152 "NXDOMAIN",
00153 "NOTIMP",
00154 "REFUSED",
00155 "YXDOMAIN",
00156 "YXRRSET",
00157 "NXRRSET",
00158 "NOTAUTH",
00159 "NOTZONE",
00160 "RESERVED11",
00161 "RESERVED12",
00162 "RESERVED13",
00163 "RESERVED14",
00164 "RESERVED15",
00165 "BADVERS"
00166 };
00167
00168
00169
00170
00171
00172
00173
00174 struct dns_msgblock {
00175 unsigned int count;
00176 unsigned int remaining;
00177 ISC_LINK(dns_msgblock_t) link;
00178 };
00179
00180 static inline dns_msgblock_t *
00181 msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
00182
00183 #define msgblock_get(block, type) \
00184 ((type *)msgblock_internalget(block, sizeof(type)))
00185
00186 static inline void *
00187 msgblock_internalget(dns_msgblock_t *, unsigned int);
00188
00189 static inline void
00190 msgblock_reset(dns_msgblock_t *);
00191
00192 static inline void
00193 msgblock_free(isc_mem_t *, dns_msgblock_t *, unsigned int);
00194
00195 static void
00196 logfmtpacket(dns_message_t *message, const char *description,
00197 isc_sockaddr_t *address, isc_logcategory_t *category,
00198 isc_logmodule_t *module, const dns_master_style_t *style,
00199 int level, isc_mem_t *mctx);
00200
00201
00202
00203
00204
00205 static inline dns_msgblock_t *
00206 msgblock_allocate(isc_mem_t *mctx, unsigned int sizeof_type,
00207 unsigned int count)
00208 {
00209 dns_msgblock_t *block;
00210 unsigned int length;
00211
00212 length = sizeof(dns_msgblock_t) + (sizeof_type * count);
00213
00214 block = isc_mem_get(mctx, length);
00215 if (block == NULL)
00216 return (NULL);
00217
00218 block->count = count;
00219 block->remaining = count;
00220
00221 ISC_LINK_INIT(block, link);
00222
00223 return (block);
00224 }
00225
00226
00227
00228
00229
00230 static inline void *
00231 msgblock_internalget(dns_msgblock_t *block, unsigned int sizeof_type) {
00232 void *ptr;
00233
00234 if (block == NULL || block->remaining == 0)
00235 return (NULL);
00236
00237 block->remaining--;
00238
00239 ptr = (((unsigned char *)block)
00240 + sizeof(dns_msgblock_t)
00241 + (sizeof_type * block->remaining));
00242
00243 return (ptr);
00244 }
00245
00246 static inline void
00247 msgblock_reset(dns_msgblock_t *block) {
00248 block->remaining = block->count;
00249 }
00250
00251
00252
00253
00254 static inline void
00255 msgblock_free(isc_mem_t *mctx, dns_msgblock_t *block, unsigned int sizeof_type)
00256 {
00257 unsigned int length;
00258
00259 length = sizeof(dns_msgblock_t) + (sizeof_type * block->count);
00260
00261 isc_mem_put(mctx, block, length);
00262 }
00263
00264
00265
00266
00267
00268
00269 static inline isc_result_t
00270 newbuffer(dns_message_t *msg, unsigned int size) {
00271 isc_result_t result;
00272 isc_buffer_t *dynbuf;
00273
00274 dynbuf = NULL;
00275 result = isc_buffer_allocate(msg->mctx, &dynbuf, size);
00276 if (result != ISC_R_SUCCESS)
00277 return (ISC_R_NOMEMORY);
00278
00279 ISC_LIST_APPEND(msg->scratchpad, dynbuf, link);
00280 return (ISC_R_SUCCESS);
00281 }
00282
00283 static inline isc_buffer_t *
00284 currentbuffer(dns_message_t *msg) {
00285 isc_buffer_t *dynbuf;
00286
00287 dynbuf = ISC_LIST_TAIL(msg->scratchpad);
00288 INSIST(dynbuf != NULL);
00289
00290 return (dynbuf);
00291 }
00292
00293 static inline void
00294 releaserdata(dns_message_t *msg, dns_rdata_t *rdata) {
00295 ISC_LIST_PREPEND(msg->freerdata, rdata, link);
00296 }
00297
00298 static inline dns_rdata_t *
00299 newrdata(dns_message_t *msg) {
00300 dns_msgblock_t *msgblock;
00301 dns_rdata_t *rdata;
00302
00303 rdata = ISC_LIST_HEAD(msg->freerdata);
00304 if (rdata != NULL) {
00305 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
00306 return (rdata);
00307 }
00308
00309 msgblock = ISC_LIST_TAIL(msg->rdatas);
00310 rdata = msgblock_get(msgblock, dns_rdata_t);
00311 if (rdata == NULL) {
00312 msgblock = msgblock_allocate(msg->mctx, sizeof(dns_rdata_t),
00313 RDATA_COUNT);
00314 if (msgblock == NULL)
00315 return (NULL);
00316
00317 ISC_LIST_APPEND(msg->rdatas, msgblock, link);
00318
00319 rdata = msgblock_get(msgblock, dns_rdata_t);
00320 }
00321
00322 dns_rdata_init(rdata);
00323 return (rdata);
00324 }
00325
00326 static inline void
00327 releaserdatalist(dns_message_t *msg, dns_rdatalist_t *rdatalist) {
00328 ISC_LIST_PREPEND(msg->freerdatalist, rdatalist, link);
00329 }
00330
00331 static inline dns_rdatalist_t *
00332 newrdatalist(dns_message_t *msg) {
00333 dns_msgblock_t *msgblock;
00334 dns_rdatalist_t *rdatalist;
00335
00336 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
00337 if (rdatalist != NULL) {
00338 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
00339 goto out;
00340 }
00341
00342 msgblock = ISC_LIST_TAIL(msg->rdatalists);
00343 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
00344 if (rdatalist == NULL) {
00345 msgblock = msgblock_allocate(msg->mctx,
00346 sizeof(dns_rdatalist_t),
00347 RDATALIST_COUNT);
00348 if (msgblock == NULL)
00349 return (NULL);
00350
00351 ISC_LIST_APPEND(msg->rdatalists, msgblock, link);
00352
00353 rdatalist = msgblock_get(msgblock, dns_rdatalist_t);
00354 }
00355 out:
00356 if (rdatalist != NULL)
00357 dns_rdatalist_init(rdatalist);
00358
00359 return (rdatalist);
00360 }
00361
00362 static inline dns_offsets_t *
00363 newoffsets(dns_message_t *msg) {
00364 dns_msgblock_t *msgblock;
00365 dns_offsets_t *offsets;
00366
00367 msgblock = ISC_LIST_TAIL(msg->offsets);
00368 offsets = msgblock_get(msgblock, dns_offsets_t);
00369 if (offsets == NULL) {
00370 msgblock = msgblock_allocate(msg->mctx,
00371 sizeof(dns_offsets_t),
00372 OFFSET_COUNT);
00373 if (msgblock == NULL)
00374 return (NULL);
00375
00376 ISC_LIST_APPEND(msg->offsets, msgblock, link);
00377
00378 offsets = msgblock_get(msgblock, dns_offsets_t);
00379 }
00380
00381 return (offsets);
00382 }
00383
00384 static inline void
00385 msginitheader(dns_message_t *m) {
00386 m->id = 0;
00387 m->flags = 0;
00388 m->rcode = 0;
00389 m->opcode = 0;
00390 m->rdclass = 0;
00391 }
00392
00393 static inline void
00394 msginitprivate(dns_message_t *m) {
00395 unsigned int i;
00396
00397 for (i = 0; i < DNS_SECTION_MAX; i++) {
00398 m->cursors[i] = NULL;
00399 m->counts[i] = 0;
00400 }
00401 m->opt = NULL;
00402 m->sig0 = NULL;
00403 m->sig0name = NULL;
00404 m->tsig = NULL;
00405 m->tsigname = NULL;
00406 m->state = DNS_SECTION_ANY;
00407 m->opt_reserved = 0;
00408 m->sig_reserved = 0;
00409 m->reserved = 0;
00410 m->buffer = NULL;
00411 }
00412
00413 static inline void
00414 msginittsig(dns_message_t *m) {
00415 m->tsigstatus = dns_rcode_noerror;
00416 m->querytsigstatus = dns_rcode_noerror;
00417 m->tsigkey = NULL;
00418 m->tsigctx = NULL;
00419 m->sigstart = -1;
00420 m->sig0key = NULL;
00421 m->sig0status = dns_rcode_noerror;
00422 m->timeadjust = 0;
00423 }
00424
00425
00426
00427
00428
00429 static inline void
00430 msginit(dns_message_t *m) {
00431 msginitheader(m);
00432 msginitprivate(m);
00433 msginittsig(m);
00434 m->header_ok = 0;
00435 m->question_ok = 0;
00436 m->tcp_continuation = 0;
00437 m->verified_sig = 0;
00438 m->verify_attempted = 0;
00439 m->order = NULL;
00440 m->order_arg = NULL;
00441 m->query.base = NULL;
00442 m->query.length = 0;
00443 m->free_query = 0;
00444 m->saved.base = NULL;
00445 m->saved.length = 0;
00446 m->free_saved = 0;
00447 m->sitok = 0;
00448 m->sitbad = 0;
00449 m->querytsig = NULL;
00450 }
00451
00452 static inline void
00453 msgresetnames(dns_message_t *msg, unsigned int first_section) {
00454 unsigned int i;
00455 dns_name_t *name, *next_name;
00456 dns_rdataset_t *rds, *next_rds;
00457
00458
00459
00460
00461 for (i = first_section; i < DNS_SECTION_MAX; i++) {
00462 name = ISC_LIST_HEAD(msg->sections[i]);
00463 while (name != NULL) {
00464 next_name = ISC_LIST_NEXT(name, link);
00465 ISC_LIST_UNLINK(msg->sections[i], name, link);
00466
00467 rds = ISC_LIST_HEAD(name->list);
00468 while (rds != NULL) {
00469 next_rds = ISC_LIST_NEXT(rds, link);
00470 ISC_LIST_UNLINK(name->list, rds, link);
00471
00472 INSIST(dns_rdataset_isassociated(rds));
00473 dns_rdataset_disassociate(rds);
00474 isc_mempool_put(msg->rdspool, rds);
00475 rds = next_rds;
00476 }
00477 if (dns_name_dynamic(name))
00478 dns_name_free(name, msg->mctx);
00479 isc_mempool_put(msg->namepool, name);
00480 name = next_name;
00481 }
00482 }
00483 }
00484
00485 static void
00486 msgresetopt(dns_message_t *msg)
00487 {
00488 if (msg->opt != NULL) {
00489 if (msg->opt_reserved > 0) {
00490 dns_message_renderrelease(msg, msg->opt_reserved);
00491 msg->opt_reserved = 0;
00492 }
00493 INSIST(dns_rdataset_isassociated(msg->opt));
00494 dns_rdataset_disassociate(msg->opt);
00495 isc_mempool_put(msg->rdspool, msg->opt);
00496 msg->opt = NULL;
00497 msg->sitok = 0;
00498 msg->sitbad = 0;
00499 }
00500 }
00501
00502 static void
00503 msgresetsigs(dns_message_t *msg, isc_boolean_t replying) {
00504 if (msg->sig_reserved > 0) {
00505 dns_message_renderrelease(msg, msg->sig_reserved);
00506 msg->sig_reserved = 0;
00507 }
00508 if (msg->tsig != NULL) {
00509 INSIST(dns_rdataset_isassociated(msg->tsig));
00510 INSIST(msg->namepool != NULL);
00511 if (replying) {
00512 INSIST(msg->querytsig == NULL);
00513 msg->querytsig = msg->tsig;
00514 } else {
00515 dns_rdataset_disassociate(msg->tsig);
00516 isc_mempool_put(msg->rdspool, msg->tsig);
00517 if (msg->querytsig != NULL) {
00518 dns_rdataset_disassociate(msg->querytsig);
00519 isc_mempool_put(msg->rdspool, msg->querytsig);
00520 }
00521 }
00522 if (dns_name_dynamic(msg->tsigname))
00523 dns_name_free(msg->tsigname, msg->mctx);
00524 isc_mempool_put(msg->namepool, msg->tsigname);
00525 msg->tsig = NULL;
00526 msg->tsigname = NULL;
00527 } else if (msg->querytsig != NULL && !replying) {
00528 dns_rdataset_disassociate(msg->querytsig);
00529 isc_mempool_put(msg->rdspool, msg->querytsig);
00530 msg->querytsig = NULL;
00531 }
00532 if (msg->sig0 != NULL) {
00533 INSIST(dns_rdataset_isassociated(msg->sig0));
00534 dns_rdataset_disassociate(msg->sig0);
00535 isc_mempool_put(msg->rdspool, msg->sig0);
00536 if (msg->sig0name != NULL) {
00537 if (dns_name_dynamic(msg->sig0name))
00538 dns_name_free(msg->sig0name, msg->mctx);
00539 isc_mempool_put(msg->namepool, msg->sig0name);
00540 }
00541 msg->sig0 = NULL;
00542 msg->sig0name = NULL;
00543 }
00544 }
00545
00546
00547
00548
00549
00550 static void
00551 msgreset(dns_message_t *msg, isc_boolean_t everything) {
00552 dns_msgblock_t *msgblock, *next_msgblock;
00553 isc_buffer_t *dynbuf, *next_dynbuf;
00554 dns_rdata_t *rdata;
00555 dns_rdatalist_t *rdatalist;
00556
00557 msgresetnames(msg, 0);
00558 msgresetopt(msg);
00559 msgresetsigs(msg, ISC_FALSE);
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 rdata = ISC_LIST_HEAD(msg->freerdata);
00571 while (rdata != NULL) {
00572 ISC_LIST_UNLINK(msg->freerdata, rdata, link);
00573 rdata = ISC_LIST_HEAD(msg->freerdata);
00574 }
00575 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
00576 while (rdatalist != NULL) {
00577 ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link);
00578 rdatalist = ISC_LIST_HEAD(msg->freerdatalist);
00579 }
00580
00581 dynbuf = ISC_LIST_HEAD(msg->scratchpad);
00582 INSIST(dynbuf != NULL);
00583 if (!everything) {
00584 isc_buffer_clear(dynbuf);
00585 dynbuf = ISC_LIST_NEXT(dynbuf, link);
00586 }
00587 while (dynbuf != NULL) {
00588 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
00589 ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link);
00590 isc_buffer_free(&dynbuf);
00591 dynbuf = next_dynbuf;
00592 }
00593
00594 msgblock = ISC_LIST_HEAD(msg->rdatas);
00595 if (!everything && msgblock != NULL) {
00596 msgblock_reset(msgblock);
00597 msgblock = ISC_LIST_NEXT(msgblock, link);
00598 }
00599 while (msgblock != NULL) {
00600 next_msgblock = ISC_LIST_NEXT(msgblock, link);
00601 ISC_LIST_UNLINK(msg->rdatas, msgblock, link);
00602 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t));
00603 msgblock = next_msgblock;
00604 }
00605
00606
00607
00608
00609
00610 msgblock = ISC_LIST_HEAD(msg->rdatalists);
00611 if (!everything && msgblock != NULL) {
00612 msgblock_reset(msgblock);
00613 msgblock = ISC_LIST_NEXT(msgblock, link);
00614 }
00615 while (msgblock != NULL) {
00616 next_msgblock = ISC_LIST_NEXT(msgblock, link);
00617 ISC_LIST_UNLINK(msg->rdatalists, msgblock, link);
00618 msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t));
00619 msgblock = next_msgblock;
00620 }
00621
00622 msgblock = ISC_LIST_HEAD(msg->offsets);
00623 if (!everything && msgblock != NULL) {
00624 msgblock_reset(msgblock);
00625 msgblock = ISC_LIST_NEXT(msgblock, link);
00626 }
00627 while (msgblock != NULL) {
00628 next_msgblock = ISC_LIST_NEXT(msgblock, link);
00629 ISC_LIST_UNLINK(msg->offsets, msgblock, link);
00630 msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t));
00631 msgblock = next_msgblock;
00632 }
00633
00634 if (msg->tsigkey != NULL) {
00635 dns_tsigkey_detach(&msg->tsigkey);
00636 msg->tsigkey = NULL;
00637 }
00638
00639 if (msg->tsigctx != NULL)
00640 dst_context_destroy(&msg->tsigctx);
00641
00642 if (msg->query.base != NULL) {
00643 if (msg->free_query != 0)
00644 isc_mem_put(msg->mctx, msg->query.base,
00645 msg->query.length);
00646 msg->query.base = NULL;
00647 msg->query.length = 0;
00648 }
00649
00650 if (msg->saved.base != NULL) {
00651 if (msg->free_saved != 0)
00652 isc_mem_put(msg->mctx, msg->saved.base,
00653 msg->saved.length);
00654 msg->saved.base = NULL;
00655 msg->saved.length = 0;
00656 }
00657
00658
00659
00660
00661 dynbuf = ISC_LIST_HEAD(msg->cleanup);
00662 while (dynbuf != NULL) {
00663 next_dynbuf = ISC_LIST_NEXT(dynbuf, link);
00664 ISC_LIST_UNLINK(msg->cleanup, dynbuf, link);
00665 isc_buffer_free(&dynbuf);
00666 dynbuf = next_dynbuf;
00667 }
00668
00669
00670
00671
00672 if (!everything)
00673 msginit(msg);
00674
00675 ENSURE(isc_mempool_getallocated(msg->namepool) == 0);
00676 ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);
00677 }
00678
00679 static unsigned int
00680 spacefortsig(dns_tsigkey_t *key, int otherlen) {
00681 isc_region_t r1, r2;
00682 unsigned int x;
00683 isc_result_t result;
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 dns_name_toregion(&key->name, &r1);
00707 dns_name_toregion(key->algorithm, &r2);
00708 if (key->key == NULL)
00709 x = 0;
00710 else {
00711 result = dst_key_sigsize(key->key, &x);
00712 if (result != ISC_R_SUCCESS)
00713 x = 0;
00714 }
00715 return (26 + r1.length + r2.length + x + otherlen);
00716 }
00717
00718 isc_result_t
00719 dns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp)
00720 {
00721 dns_message_t *m;
00722 isc_result_t result;
00723 isc_buffer_t *dynbuf;
00724 unsigned int i;
00725
00726 REQUIRE(mctx != NULL);
00727 REQUIRE(msgp != NULL);
00728 REQUIRE(*msgp == NULL);
00729 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
00730 || intent == DNS_MESSAGE_INTENTRENDER);
00731
00732 m = isc_mem_get(mctx, sizeof(dns_message_t));
00733 if (m == NULL)
00734 return (ISC_R_NOMEMORY);
00735
00736
00737
00738
00739
00740
00741 m->magic = DNS_MESSAGE_MAGIC;
00742 m->from_to_wire = intent;
00743 msginit(m);
00744
00745 for (i = 0; i < DNS_SECTION_MAX; i++)
00746 ISC_LIST_INIT(m->sections[i]);
00747
00748 m->mctx = NULL;
00749 isc_mem_attach(mctx, &m->mctx);
00750
00751 ISC_LIST_INIT(m->scratchpad);
00752 ISC_LIST_INIT(m->cleanup);
00753 m->namepool = NULL;
00754 m->rdspool = NULL;
00755 ISC_LIST_INIT(m->rdatas);
00756 ISC_LIST_INIT(m->rdatalists);
00757 ISC_LIST_INIT(m->offsets);
00758 ISC_LIST_INIT(m->freerdata);
00759 ISC_LIST_INIT(m->freerdatalist);
00760
00761
00762
00763
00764
00765 result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool);
00766 if (result != ISC_R_SUCCESS)
00767 goto cleanup;
00768 isc_mempool_setfreemax(m->namepool, NAME_COUNT);
00769 isc_mempool_setname(m->namepool, "msg:names");
00770
00771 result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t),
00772 &m->rdspool);
00773 if (result != ISC_R_SUCCESS)
00774 goto cleanup;
00775 isc_mempool_setfreemax(m->rdspool, NAME_COUNT);
00776 isc_mempool_setname(m->rdspool, "msg:rdataset");
00777
00778 dynbuf = NULL;
00779 result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE);
00780 if (result != ISC_R_SUCCESS)
00781 goto cleanup;
00782 ISC_LIST_APPEND(m->scratchpad, dynbuf, link);
00783
00784 m->cctx = NULL;
00785
00786 *msgp = m;
00787 return (ISC_R_SUCCESS);
00788
00789
00790
00791
00792 cleanup:
00793 dynbuf = ISC_LIST_HEAD(m->scratchpad);
00794 if (dynbuf != NULL) {
00795 ISC_LIST_UNLINK(m->scratchpad, dynbuf, link);
00796 isc_buffer_free(&dynbuf);
00797 }
00798 if (m->namepool != NULL)
00799 isc_mempool_destroy(&m->namepool);
00800 if (m->rdspool != NULL)
00801 isc_mempool_destroy(&m->rdspool);
00802 m->magic = 0;
00803 isc_mem_putanddetach(&mctx, m, sizeof(dns_message_t));
00804
00805 return (ISC_R_NOMEMORY);
00806 }
00807
00808 void
00809 dns_message_reset(dns_message_t *msg, unsigned int intent) {
00810 REQUIRE(DNS_MESSAGE_VALID(msg));
00811 REQUIRE(intent == DNS_MESSAGE_INTENTPARSE
00812 || intent == DNS_MESSAGE_INTENTRENDER);
00813
00814 msgreset(msg, ISC_FALSE);
00815 msg->from_to_wire = intent;
00816 }
00817
00818 void
00819 dns_message_destroy(dns_message_t **msgp) {
00820 dns_message_t *msg;
00821
00822 REQUIRE(msgp != NULL);
00823 REQUIRE(DNS_MESSAGE_VALID(*msgp));
00824
00825 msg = *msgp;
00826 *msgp = NULL;
00827
00828 msgreset(msg, ISC_TRUE);
00829 isc_mempool_destroy(&msg->namepool);
00830 isc_mempool_destroy(&msg->rdspool);
00831 msg->magic = 0;
00832 isc_mem_putanddetach(&msg->mctx, msg, sizeof(dns_message_t));
00833 }
00834
00835 static isc_result_t
00836 findname(dns_name_t **foundname, dns_name_t *target,
00837 dns_namelist_t *section)
00838 {
00839 dns_name_t *curr;
00840
00841 for (curr = ISC_LIST_TAIL(*section);
00842 curr != NULL;
00843 curr = ISC_LIST_PREV(curr, link)) {
00844 if (dns_name_equal(curr, target)) {
00845 if (foundname != NULL)
00846 *foundname = curr;
00847 return (ISC_R_SUCCESS);
00848 }
00849 }
00850
00851 return (ISC_R_NOTFOUND);
00852 }
00853
00854 isc_result_t
00855 dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass,
00856 dns_rdatatype_t type, dns_rdatatype_t covers,
00857 dns_rdataset_t **rdataset)
00858 {
00859 dns_rdataset_t *curr;
00860
00861 if (rdataset != NULL) {
00862 REQUIRE(*rdataset == NULL);
00863 }
00864
00865 for (curr = ISC_LIST_TAIL(name->list);
00866 curr != NULL;
00867 curr = ISC_LIST_PREV(curr, link)) {
00868 if (curr->rdclass == rdclass &&
00869 curr->type == type && curr->covers == covers) {
00870 if (rdataset != NULL)
00871 *rdataset = curr;
00872 return (ISC_R_SUCCESS);
00873 }
00874 }
00875
00876 return (ISC_R_NOTFOUND);
00877 }
00878
00879 isc_result_t
00880 dns_message_findtype(dns_name_t *name, dns_rdatatype_t type,
00881 dns_rdatatype_t covers, dns_rdataset_t **rdataset)
00882 {
00883 dns_rdataset_t *curr;
00884
00885 REQUIRE(name != NULL);
00886 if (rdataset != NULL) {
00887 REQUIRE(*rdataset == NULL);
00888 }
00889
00890 for (curr = ISC_LIST_TAIL(name->list);
00891 curr != NULL;
00892 curr = ISC_LIST_PREV(curr, link)) {
00893 if (curr->type == type && curr->covers == covers) {
00894 if (rdataset != NULL)
00895 *rdataset = curr;
00896 return (ISC_R_SUCCESS);
00897 }
00898 }
00899
00900 return (ISC_R_NOTFOUND);
00901 }
00902
00903
00904
00905
00906 static isc_result_t
00907 getname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg,
00908 dns_decompress_t *dctx)
00909 {
00910 isc_buffer_t *scratch;
00911 isc_result_t result;
00912 unsigned int tries;
00913
00914 scratch = currentbuffer(msg);
00915
00916
00917
00918
00919
00920 tries = 0;
00921 while (tries < 2) {
00922 result = dns_name_fromwire(name, source, dctx, ISC_FALSE,
00923 scratch);
00924
00925 if (result == ISC_R_NOSPACE) {
00926 tries++;
00927
00928 result = newbuffer(msg, SCRATCHPAD_SIZE);
00929 if (result != ISC_R_SUCCESS)
00930 return (result);
00931
00932 scratch = currentbuffer(msg);
00933 dns_name_reset(name);
00934 } else {
00935 return (result);
00936 }
00937 }
00938
00939 INSIST(0);
00940 return (ISC_R_UNEXPECTED);
00941 }
00942
00943 static isc_result_t
00944 getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
00945 dns_rdataclass_t rdclass, dns_rdatatype_t rdtype,
00946 unsigned int rdatalen, dns_rdata_t *rdata)
00947 {
00948 isc_buffer_t *scratch;
00949 isc_result_t result;
00950 unsigned int tries;
00951 unsigned int trysize;
00952
00953 scratch = currentbuffer(msg);
00954
00955 isc_buffer_setactive(source, rdatalen);
00956
00957
00958
00959
00960
00961
00962
00963
00964 tries = 0;
00965 trysize = 0;
00966
00967 for (;;) {
00968 result = dns_rdata_fromwire(rdata, rdclass, rdtype,
00969 source, dctx, 0,
00970 scratch);
00971
00972 if (result == ISC_R_NOSPACE) {
00973 if (tries == 0) {
00974 trysize = 2 * rdatalen;
00975 if (trysize < SCRATCHPAD_SIZE)
00976 trysize = SCRATCHPAD_SIZE;
00977 } else {
00978 INSIST(trysize != 0);
00979 if (trysize >= 65535)
00980 return (ISC_R_NOSPACE);
00981
00982 trysize *= 2;
00983 }
00984 tries++;
00985 result = newbuffer(msg, trysize);
00986 if (result != ISC_R_SUCCESS)
00987 return (result);
00988
00989 scratch = currentbuffer(msg);
00990 } else {
00991 return (result);
00992 }
00993 }
00994 }
00995
00996 #define DO_FORMERR \
00997 do { \
00998 if (best_effort) \
00999 seen_problem = ISC_TRUE; \
01000 else { \
01001 result = DNS_R_FORMERR; \
01002 goto cleanup; \
01003 } \
01004 } while (0)
01005
01006 static isc_result_t
01007 getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
01008 unsigned int options)
01009 {
01010 isc_region_t r;
01011 unsigned int count;
01012 dns_name_t *name;
01013 dns_name_t *name2;
01014 dns_offsets_t *offsets;
01015 dns_rdataset_t *rdataset;
01016 dns_rdatalist_t *rdatalist;
01017 isc_result_t result;
01018 dns_rdatatype_t rdtype;
01019 dns_rdataclass_t rdclass;
01020 dns_namelist_t *section;
01021 isc_boolean_t free_name;
01022 isc_boolean_t best_effort;
01023 isc_boolean_t seen_problem;
01024
01025 section = &msg->sections[DNS_SECTION_QUESTION];
01026
01027 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
01028 seen_problem = ISC_FALSE;
01029
01030 name = NULL;
01031 rdataset = NULL;
01032 rdatalist = NULL;
01033
01034 for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
01035 name = isc_mempool_get(msg->namepool);
01036 if (name == NULL)
01037 return (ISC_R_NOMEMORY);
01038 free_name = ISC_TRUE;
01039
01040 offsets = newoffsets(msg);
01041 if (offsets == NULL) {
01042 result = ISC_R_NOMEMORY;
01043 goto cleanup;
01044 }
01045 dns_name_init(name, *offsets);
01046
01047
01048
01049
01050 isc_buffer_remainingregion(source, &r);
01051 isc_buffer_setactive(source, r.length);
01052 result = getname(name, source, msg, dctx);
01053 if (result != ISC_R_SUCCESS)
01054 goto cleanup;
01055
01056
01057
01058
01059
01060
01061
01062 result = findname(&name2, name, section);
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 if (result != ISC_R_SUCCESS) {
01075 if (!ISC_LIST_EMPTY(*section))
01076 DO_FORMERR;
01077 ISC_LIST_APPEND(*section, name, link);
01078 free_name = ISC_FALSE;
01079 } else {
01080 isc_mempool_put(msg->namepool, name);
01081 name = name2;
01082 name2 = NULL;
01083 free_name = ISC_FALSE;
01084 }
01085
01086
01087
01088
01089 isc_buffer_remainingregion(source, &r);
01090 if (r.length < 4) {
01091 result = ISC_R_UNEXPECTEDEND;
01092 goto cleanup;
01093 }
01094 rdtype = isc_buffer_getuint16(source);
01095 rdclass = isc_buffer_getuint16(source);
01096
01097
01098
01099
01100
01101 if (msg->state == DNS_SECTION_ANY) {
01102 msg->state = DNS_SECTION_QUESTION;
01103 msg->rdclass = rdclass;
01104 } else if (msg->rdclass != rdclass)
01105 DO_FORMERR;
01106
01107
01108
01109
01110 result = dns_message_find(name, rdclass, rdtype, 0, NULL);
01111 if (result == ISC_R_SUCCESS)
01112 DO_FORMERR;
01113
01114
01115
01116
01117 rdatalist = newrdatalist(msg);
01118 if (rdatalist == NULL) {
01119 result = ISC_R_NOMEMORY;
01120 goto cleanup;
01121 }
01122 rdataset = isc_mempool_get(msg->rdspool);
01123 if (rdataset == NULL) {
01124 result = ISC_R_NOMEMORY;
01125 goto cleanup;
01126 }
01127
01128
01129
01130
01131
01132 rdatalist->type = rdtype;
01133 rdatalist->rdclass = rdclass;
01134
01135 dns_rdataset_init(rdataset);
01136 result = dns_rdatalist_tordataset(rdatalist, rdataset);
01137 if (result != ISC_R_SUCCESS)
01138 goto cleanup;
01139
01140 rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
01141
01142 ISC_LIST_APPEND(name->list, rdataset, link);
01143 rdataset = NULL;
01144 }
01145
01146 if (seen_problem)
01147 return (DNS_R_RECOVERABLE);
01148 return (ISC_R_SUCCESS);
01149
01150 cleanup:
01151 if (rdataset != NULL) {
01152 INSIST(!dns_rdataset_isassociated(rdataset));
01153 isc_mempool_put(msg->rdspool, rdataset);
01154 }
01155 #if 0
01156 if (rdatalist != NULL)
01157 isc_mempool_put(msg->rdlpool, rdatalist);
01158 #endif
01159 if (free_name)
01160 isc_mempool_put(msg->namepool, name);
01161
01162 return (result);
01163 }
01164
01165 static isc_boolean_t
01166 update(dns_section_t section, dns_rdataclass_t rdclass) {
01167 if (section == DNS_SECTION_PREREQUISITE)
01168 return (ISC_TF(rdclass == dns_rdataclass_any ||
01169 rdclass == dns_rdataclass_none));
01170 if (section == DNS_SECTION_UPDATE)
01171 return (ISC_TF(rdclass == dns_rdataclass_any));
01172 return (ISC_FALSE);
01173 }
01174
01175 static isc_result_t
01176 getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
01177 dns_section_t sectionid, unsigned int options)
01178 {
01179 isc_region_t r;
01180 unsigned int count, rdatalen;
01181 dns_name_t *name;
01182 dns_name_t *name2;
01183 dns_offsets_t *offsets;
01184 dns_rdataset_t *rdataset;
01185 dns_rdatalist_t *rdatalist;
01186 isc_result_t result;
01187 dns_rdatatype_t rdtype, covers;
01188 dns_rdataclass_t rdclass;
01189 dns_rdata_t *rdata;
01190 dns_ttl_t ttl;
01191 dns_namelist_t *section;
01192 isc_boolean_t free_name, free_rdataset;
01193 isc_boolean_t preserve_order, best_effort, seen_problem;
01194 isc_boolean_t issigzero;
01195
01196 preserve_order = ISC_TF(options & DNS_MESSAGEPARSE_PRESERVEORDER);
01197 best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT);
01198 seen_problem = ISC_FALSE;
01199
01200 for (count = 0; count < msg->counts[sectionid]; count++) {
01201 int recstart = source->current;
01202 isc_boolean_t skip_name_search, skip_type_search;
01203
01204 section = &msg->sections[sectionid];
01205
01206 skip_name_search = ISC_FALSE;
01207 skip_type_search = ISC_FALSE;
01208 free_rdataset = ISC_FALSE;
01209
01210 name = isc_mempool_get(msg->namepool);
01211 if (name == NULL)
01212 return (ISC_R_NOMEMORY);
01213 free_name = ISC_TRUE;
01214
01215 offsets = newoffsets(msg);
01216 if (offsets == NULL) {
01217 result = ISC_R_NOMEMORY;
01218 goto cleanup;
01219 }
01220 dns_name_init(name, *offsets);
01221
01222
01223
01224
01225 isc_buffer_remainingregion(source, &r);
01226 isc_buffer_setactive(source, r.length);
01227 result = getname(name, source, msg, dctx);
01228 if (result != ISC_R_SUCCESS)
01229 goto cleanup;
01230
01231
01232
01233
01234
01235
01236 isc_buffer_remainingregion(source, &r);
01237 if (r.length < 2 + 2 + 4 + 2) {
01238 result = ISC_R_UNEXPECTEDEND;
01239 goto cleanup;
01240 }
01241 rdtype = isc_buffer_getuint16(source);
01242 rdclass = isc_buffer_getuint16(source);
01243
01244
01245
01246
01247
01248 if (msg->state == DNS_SECTION_ANY &&
01249 rdtype != dns_rdatatype_opt &&
01250 rdtype != dns_rdatatype_tsig &&
01251 rdtype != dns_rdatatype_tkey) {
01252 msg->rdclass = rdclass;
01253 msg->state = DNS_SECTION_QUESTION;
01254 }
01255
01256
01257
01258
01259
01260 if (msg->opcode != dns_opcode_update
01261 && rdtype != dns_rdatatype_tsig
01262 && rdtype != dns_rdatatype_opt
01263 && rdtype != dns_rdatatype_dnskey
01264 && rdtype != dns_rdatatype_sig
01265 && rdtype != dns_rdatatype_tkey
01266 && msg->rdclass != dns_rdataclass_any
01267 && msg->rdclass != rdclass)
01268 DO_FORMERR;
01269
01270
01271
01272
01273 if (rdtype == dns_rdatatype_tsig) {
01274
01275
01276
01277
01278 if (sectionid != DNS_SECTION_ADDITIONAL ||
01279 rdclass != dns_rdataclass_any ||
01280 count != msg->counts[sectionid] - 1)
01281 DO_FORMERR;
01282 msg->sigstart = recstart;
01283 skip_name_search = ISC_TRUE;
01284 skip_type_search = ISC_TRUE;
01285 } else if (rdtype == dns_rdatatype_opt) {
01286
01287
01288
01289
01290
01291 if (!dns_name_equal(dns_rootname, name) ||
01292 msg->opt != NULL)
01293 DO_FORMERR;
01294 skip_name_search = ISC_TRUE;
01295 skip_type_search = ISC_TRUE;
01296 } else if (rdtype == dns_rdatatype_tkey) {
01297
01298
01299
01300
01301
01302
01303
01304 dns_section_t tkeysection;
01305
01306 if ((msg->flags & DNS_MESSAGEFLAG_QR) == 0)
01307 tkeysection = DNS_SECTION_ADDITIONAL;
01308 else
01309 tkeysection = DNS_SECTION_ANSWER;
01310 if (sectionid != tkeysection &&
01311 sectionid != DNS_SECTION_ANSWER)
01312 DO_FORMERR;
01313 }
01314
01315
01316
01317
01318 ttl = isc_buffer_getuint32(source);
01319 rdatalen = isc_buffer_getuint16(source);
01320 r.length -= (2 + 2 + 4 + 2);
01321 if (r.length < rdatalen) {
01322 result = ISC_R_UNEXPECTEDEND;
01323 goto cleanup;
01324 }
01325
01326
01327
01328
01329
01330
01331
01332 rdata = newrdata(msg);
01333 if (rdata == NULL) {
01334 result = ISC_R_NOMEMORY;
01335 goto cleanup;
01336 }
01337 if (msg->opcode == dns_opcode_update &&
01338 update(sectionid, rdclass)) {
01339 if (rdatalen != 0) {
01340 result = DNS_R_FORMERR;
01341 goto cleanup;
01342 }
01343
01344
01345
01346
01347
01348
01349
01350 rdata->data = (unsigned char *)1;
01351 rdata->length = 0;
01352 rdata->rdclass = rdclass;
01353 rdata->type = rdtype;
01354 rdata->flags = DNS_RDATA_UPDATE;
01355 result = ISC_R_SUCCESS;
01356 } else if (rdclass == dns_rdataclass_none &&
01357 msg->opcode == dns_opcode_update &&
01358 sectionid == DNS_SECTION_UPDATE) {
01359 result = getrdata(source, msg, dctx, msg->rdclass,
01360 rdtype, rdatalen, rdata);
01361 } else
01362 result = getrdata(source, msg, dctx, rdclass,
01363 rdtype, rdatalen, rdata);
01364 if (result != ISC_R_SUCCESS)
01365 goto cleanup;
01366 rdata->rdclass = rdclass;
01367 issigzero = ISC_FALSE;
01368 if (rdtype == dns_rdatatype_rrsig &&
01369 rdata->flags == 0) {
01370 covers = dns_rdata_covers(rdata);
01371 if (covers == 0)
01372 DO_FORMERR;
01373 } else if (rdtype == dns_rdatatype_sig &&
01374 rdata->flags == 0) {
01375 covers = dns_rdata_covers(rdata);
01376 if (covers == 0) {
01377 if (sectionid != DNS_SECTION_ADDITIONAL ||
01378 count != msg->counts[sectionid] - 1)
01379 DO_FORMERR;
01380 msg->sigstart = recstart;
01381 skip_name_search = ISC_TRUE;
01382 skip_type_search = ISC_TRUE;
01383 issigzero = ISC_TRUE;
01384 }
01385 } else
01386 covers = 0;
01387
01388
01389
01390
01391 if (rdtype == dns_rdatatype_nsec3 &&
01392 !dns_rdata_checkowner(name, msg->rdclass, rdtype,
01393 ISC_FALSE)) {
01394 result = DNS_R_BADOWNERNAME;
01395 goto cleanup;
01396 }
01397
01398
01399
01400
01401
01402
01403 if (preserve_order || msg->opcode == dns_opcode_update ||
01404 skip_name_search) {
01405 if (rdtype != dns_rdatatype_opt &&
01406 rdtype != dns_rdatatype_tsig &&
01407 !issigzero)
01408 {
01409 ISC_LIST_APPEND(*section, name, link);
01410 free_name = ISC_FALSE;
01411 }
01412 } else {
01413
01414
01415
01416
01417
01418
01419 result = findname(&name2, name, section);
01420
01421
01422
01423
01424 if (result == ISC_R_SUCCESS) {
01425 isc_mempool_put(msg->namepool, name);
01426 name = name2;
01427 } else {
01428 ISC_LIST_APPEND(*section, name, link);
01429 }
01430 free_name = ISC_FALSE;
01431 }
01432
01433
01434
01435
01436
01437 if (preserve_order || msg->opcode == dns_opcode_update ||
01438 skip_type_search)
01439 result = ISC_R_NOTFOUND;
01440 else {
01441
01442
01443
01444
01445 if (dns_rdatatype_questiononly(rdtype))
01446 DO_FORMERR;
01447
01448 rdataset = NULL;
01449 result = dns_message_find(name, rdclass, rdtype,
01450 covers, &rdataset);
01451 }
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464 if (result == ISC_R_SUCCESS) {
01465 if (dns_rdatatype_issingleton(rdtype)) {
01466 dns_rdata_t *first;
01467 dns_rdatalist_fromrdataset(rdataset,
01468 &rdatalist);
01469 first = ISC_LIST_HEAD(rdatalist->rdata);
01470 INSIST(first != NULL);
01471 if (dns_rdata_compare(rdata, first) != 0)
01472 DO_FORMERR;
01473 }
01474 }
01475
01476 if (result == ISC_R_NOTFOUND) {
01477 rdataset = isc_mempool_get(msg->rdspool);
01478 if (rdataset == NULL) {
01479 result = ISC_R_NOMEMORY;
01480 goto cleanup;
01481 }
01482 free_rdataset = ISC_TRUE;
01483
01484 rdatalist = newrdatalist(msg);
01485 if (rdatalist == NULL) {
01486 result = ISC_R_NOMEMORY;
01487 goto cleanup;
01488 }
01489
01490 rdatalist->type = rdtype;
01491 rdatalist->covers = covers;
01492 rdatalist->rdclass = rdclass;
01493 rdatalist->ttl = ttl;
01494
01495 dns_rdataset_init(rdataset);
01496 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist,
01497 rdataset)
01498 == ISC_R_SUCCESS);
01499 dns_rdataset_setownercase(rdataset, name);
01500
01501 if (rdtype != dns_rdatatype_opt &&
01502 rdtype != dns_rdatatype_tsig &&
01503 !issigzero)
01504 {
01505 ISC_LIST_APPEND(name->list, rdataset, link);
01506 free_rdataset = ISC_FALSE;
01507 }
01508 }
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518 if (ttl != rdataset->ttl) {
01519 rdataset->attributes |= DNS_RDATASETATTR_TTLADJUSTED;
01520 if (ttl < rdataset->ttl)
01521 rdataset->ttl = ttl;
01522 }
01523
01524
01525 dns_rdatalist_fromrdataset(rdataset, &rdatalist);
01526 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
01527
01528
01529
01530
01531
01532
01533 if (rdtype == dns_rdatatype_opt && msg->opt == NULL) {
01534 dns_rcode_t ercode;
01535
01536 msg->opt = rdataset;
01537 rdataset = NULL;
01538 free_rdataset = ISC_FALSE;
01539 ercode = (dns_rcode_t)
01540 ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK)
01541 >> 20);
01542 msg->rcode |= ercode;
01543 isc_mempool_put(msg->namepool, name);
01544 free_name = ISC_FALSE;
01545 }
01546
01547
01548
01549
01550
01551
01552 if (issigzero && msg->sig0 == NULL) {
01553 msg->sig0 = rdataset;
01554 msg->sig0name = name;
01555 rdataset = NULL;
01556 free_rdataset = ISC_FALSE;
01557 free_name = ISC_FALSE;
01558 } else if (rdtype == dns_rdatatype_tsig && msg->tsig == NULL) {
01559 msg->tsig = rdataset;
01560 msg->tsigname = name;
01561
01562 msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
01563 rdataset = NULL;
01564 free_rdataset = ISC_FALSE;
01565 free_name = ISC_FALSE;
01566 }
01567
01568 if (seen_problem) {
01569 if (free_name)
01570 isc_mempool_put(msg->namepool, name);
01571 if (free_rdataset)
01572 isc_mempool_put(msg->rdspool, rdataset);
01573 free_name = free_rdataset = ISC_FALSE;
01574 }
01575 INSIST(free_name == ISC_FALSE);
01576 INSIST(free_rdataset == ISC_FALSE);
01577 }
01578
01579 if (seen_problem)
01580 return (DNS_R_RECOVERABLE);
01581 return (ISC_R_SUCCESS);
01582
01583 cleanup:
01584 if (free_name)
01585 isc_mempool_put(msg->namepool, name);
01586 if (free_rdataset)
01587 isc_mempool_put(msg->rdspool, rdataset);
01588
01589 return (result);
01590 }
01591
01592 isc_result_t
01593 dns_message_parse(dns_message_t *msg, isc_buffer_t *source,
01594 unsigned int options)
01595 {
01596 isc_region_t r;
01597 dns_decompress_t dctx;
01598 isc_result_t ret;
01599 isc_uint16_t tmpflags;
01600 isc_buffer_t origsource;
01601 isc_boolean_t seen_problem;
01602 isc_boolean_t ignore_tc;
01603
01604 REQUIRE(DNS_MESSAGE_VALID(msg));
01605 REQUIRE(source != NULL);
01606 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
01607
01608 seen_problem = ISC_FALSE;
01609 ignore_tc = ISC_TF(options & DNS_MESSAGEPARSE_IGNORETRUNCATION);
01610
01611 origsource = *source;
01612
01613 msg->header_ok = 0;
01614 msg->question_ok = 0;
01615
01616 isc_buffer_remainingregion(source, &r);
01617 if (r.length < DNS_MESSAGE_HEADERLEN)
01618 return (ISC_R_UNEXPECTEDEND);
01619
01620 msg->id = isc_buffer_getuint16(source);
01621 tmpflags = isc_buffer_getuint16(source);
01622 msg->opcode = ((tmpflags & DNS_MESSAGE_OPCODE_MASK)
01623 >> DNS_MESSAGE_OPCODE_SHIFT);
01624 msg->rcode = (dns_rcode_t)(tmpflags & DNS_MESSAGE_RCODE_MASK);
01625 msg->flags = (tmpflags & DNS_MESSAGE_FLAG_MASK);
01626 msg->counts[DNS_SECTION_QUESTION] = isc_buffer_getuint16(source);
01627 msg->counts[DNS_SECTION_ANSWER] = isc_buffer_getuint16(source);
01628 msg->counts[DNS_SECTION_AUTHORITY] = isc_buffer_getuint16(source);
01629 msg->counts[DNS_SECTION_ADDITIONAL] = isc_buffer_getuint16(source);
01630
01631 msg->header_ok = 1;
01632
01633
01634
01635
01636 dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_ANY);
01637
01638 dns_decompress_setmethods(&dctx, DNS_COMPRESS_GLOBAL14);
01639
01640 ret = getquestions(source, msg, &dctx, options);
01641 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
01642 goto truncated;
01643 if (ret == DNS_R_RECOVERABLE) {
01644 seen_problem = ISC_TRUE;
01645 ret = ISC_R_SUCCESS;
01646 }
01647 if (ret != ISC_R_SUCCESS)
01648 return (ret);
01649 msg->question_ok = 1;
01650
01651 ret = getsection(source, msg, &dctx, DNS_SECTION_ANSWER, options);
01652 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
01653 goto truncated;
01654 if (ret == DNS_R_RECOVERABLE) {
01655 seen_problem = ISC_TRUE;
01656 ret = ISC_R_SUCCESS;
01657 }
01658 if (ret != ISC_R_SUCCESS)
01659 return (ret);
01660
01661 ret = getsection(source, msg, &dctx, DNS_SECTION_AUTHORITY, options);
01662 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
01663 goto truncated;
01664 if (ret == DNS_R_RECOVERABLE) {
01665 seen_problem = ISC_TRUE;
01666 ret = ISC_R_SUCCESS;
01667 }
01668 if (ret != ISC_R_SUCCESS)
01669 return (ret);
01670
01671 ret = getsection(source, msg, &dctx, DNS_SECTION_ADDITIONAL, options);
01672 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
01673 goto truncated;
01674 if (ret == DNS_R_RECOVERABLE) {
01675 seen_problem = ISC_TRUE;
01676 ret = ISC_R_SUCCESS;
01677 }
01678 if (ret != ISC_R_SUCCESS)
01679 return (ret);
01680
01681 isc_buffer_remainingregion(source, &r);
01682 if (r.length != 0) {
01683 isc_log_write(dns_lctx, ISC_LOGCATEGORY_GENERAL,
01684 DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3),
01685 "message has %u byte(s) of trailing garbage",
01686 r.length);
01687 }
01688
01689 truncated:
01690 if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0)
01691 isc_buffer_usedregion(&origsource, &msg->saved);
01692 else {
01693 msg->saved.length = isc_buffer_usedlength(&origsource);
01694 msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length);
01695 if (msg->saved.base == NULL)
01696 return (ISC_R_NOMEMORY);
01697 memmove(msg->saved.base, isc_buffer_base(&origsource),
01698 msg->saved.length);
01699 msg->free_saved = 1;
01700 }
01701
01702 if (ret == ISC_R_UNEXPECTEDEND && ignore_tc)
01703 return (DNS_R_RECOVERABLE);
01704 if (seen_problem == ISC_TRUE)
01705 return (DNS_R_RECOVERABLE);
01706 return (ISC_R_SUCCESS);
01707 }
01708
01709 isc_result_t
01710 dns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx,
01711 isc_buffer_t *buffer)
01712 {
01713 isc_region_t r;
01714
01715 REQUIRE(DNS_MESSAGE_VALID(msg));
01716 REQUIRE(buffer != NULL);
01717 REQUIRE(msg->buffer == NULL);
01718 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
01719
01720 msg->cctx = cctx;
01721
01722
01723
01724
01725 isc_buffer_clear(buffer);
01726
01727
01728
01729
01730
01731 isc_buffer_availableregion(buffer, &r);
01732 if (r.length < DNS_MESSAGE_HEADERLEN)
01733 return (ISC_R_NOSPACE);
01734
01735 if (r.length < msg->reserved)
01736 return (ISC_R_NOSPACE);
01737
01738
01739
01740
01741 isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN);
01742
01743 msg->buffer = buffer;
01744
01745 return (ISC_R_SUCCESS);
01746 }
01747
01748 isc_result_t
01749 dns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) {
01750 isc_region_t r, rn;
01751
01752 REQUIRE(DNS_MESSAGE_VALID(msg));
01753 REQUIRE(buffer != NULL);
01754 REQUIRE(msg->buffer != NULL);
01755
01756
01757
01758
01759
01760 isc_buffer_clear(buffer);
01761
01762 isc_buffer_availableregion(buffer, &rn);
01763 isc_buffer_usedregion(msg->buffer, &r);
01764 REQUIRE(rn.length > r.length);
01765
01766
01767
01768
01769 isc_buffer_add(buffer, r.length);
01770 memmove(rn.base, r.base, r.length);
01771
01772 msg->buffer = buffer;
01773
01774 return (ISC_R_SUCCESS);
01775 }
01776
01777 void
01778 dns_message_renderrelease(dns_message_t *msg, unsigned int space) {
01779 REQUIRE(DNS_MESSAGE_VALID(msg));
01780 REQUIRE(space <= msg->reserved);
01781
01782 msg->reserved -= space;
01783 }
01784
01785 isc_result_t
01786 dns_message_renderreserve(dns_message_t *msg, unsigned int space) {
01787 isc_region_t r;
01788
01789 REQUIRE(DNS_MESSAGE_VALID(msg));
01790
01791 if (msg->buffer != NULL) {
01792 isc_buffer_availableregion(msg->buffer, &r);
01793 if (r.length < (space + msg->reserved))
01794 return (ISC_R_NOSPACE);
01795 }
01796
01797 msg->reserved += space;
01798
01799 return (ISC_R_SUCCESS);
01800 }
01801
01802 static inline isc_boolean_t
01803 wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) {
01804 int pass_needed;
01805
01806
01807
01808
01809 if (rds->rdclass != dns_rdataclass_in)
01810 return (ISC_FALSE);
01811
01812 switch (rds->type) {
01813 case dns_rdatatype_a:
01814 case dns_rdatatype_aaaa:
01815 if (preferred_glue == rds->type)
01816 pass_needed = 4;
01817 else
01818 pass_needed = 3;
01819 break;
01820 case dns_rdatatype_rrsig:
01821 case dns_rdatatype_dnskey:
01822 pass_needed = 2;
01823 break;
01824 default:
01825 pass_needed = 1;
01826 }
01827
01828 if (pass_needed >= pass)
01829 return (ISC_FALSE);
01830
01831 return (ISC_TRUE);
01832 }
01833
01834 #ifdef ALLOW_FILTER_AAAA
01835
01836
01837
01838 static inline isc_boolean_t
01839 norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options)
01840 {
01841 switch (rdataset->type) {
01842 case dns_rdatatype_aaaa:
01843 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0)
01844 return (ISC_FALSE);
01845 break;
01846
01847 case dns_rdatatype_rrsig:
01848 if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 ||
01849 rdataset->covers != dns_rdatatype_aaaa)
01850 return (ISC_FALSE);
01851 break;
01852
01853 default:
01854 return (ISC_FALSE);
01855 }
01856
01857 if (rdataset->rdclass != dns_rdataclass_in)
01858 return (ISC_FALSE);
01859
01860 return (ISC_TRUE);
01861 }
01862
01863 #endif
01864 isc_result_t
01865 dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid,
01866 unsigned int options)
01867 {
01868 dns_namelist_t *section;
01869 dns_name_t *name, *next_name;
01870 dns_rdataset_t *rdataset, *next_rdataset;
01871 unsigned int count, total;
01872 isc_result_t result;
01873 isc_buffer_t st;
01874 int pass;
01875 isc_boolean_t partial = ISC_FALSE;
01876 unsigned int rd_options;
01877 dns_rdatatype_t preferred_glue = 0;
01878
01879 REQUIRE(DNS_MESSAGE_VALID(msg));
01880 REQUIRE(msg->buffer != NULL);
01881 REQUIRE(VALID_NAMED_SECTION(sectionid));
01882
01883 section = &msg->sections[sectionid];
01884
01885 if ((sectionid == DNS_SECTION_ADDITIONAL)
01886 && (options & DNS_MESSAGERENDER_ORDERED) == 0) {
01887 if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) {
01888 preferred_glue = dns_rdatatype_a;
01889 pass = 4;
01890 } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) {
01891 preferred_glue = dns_rdatatype_aaaa;
01892 pass = 4;
01893 } else
01894 pass = 3;
01895 } else
01896 pass = 1;
01897
01898 if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0)
01899 rd_options = 0;
01900 else
01901 rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC;
01902
01903
01904
01905
01906 msg->buffer->length -= msg->reserved;
01907
01908 total = 0;
01909 if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0)
01910 partial = ISC_TRUE;
01911
01912
01913
01914
01915 name = ISC_LIST_HEAD(*section);
01916 if (name != NULL) {
01917 rdataset = ISC_LIST_HEAD(name->list);
01918 if (rdataset != NULL &&
01919 (rdataset->attributes & DNS_RDATASETATTR_REQUIREDGLUE) != 0 &&
01920 (rdataset->attributes & DNS_RDATASETATTR_RENDERED) == 0) {
01921 const void *order_arg = msg->order_arg;
01922 st = *(msg->buffer);
01923 count = 0;
01924 if (partial)
01925 result = dns_rdataset_towirepartial(rdataset,
01926 name,
01927 msg->cctx,
01928 msg->buffer,
01929 msg->order,
01930 order_arg,
01931 rd_options,
01932 &count,
01933 NULL);
01934 else
01935 result = dns_rdataset_towiresorted(rdataset,
01936 name,
01937 msg->cctx,
01938 msg->buffer,
01939 msg->order,
01940 order_arg,
01941 rd_options,
01942 &count);
01943 total += count;
01944 if (partial && result == ISC_R_NOSPACE) {
01945 msg->flags |= DNS_MESSAGEFLAG_TC;
01946 msg->buffer->length += msg->reserved;
01947 msg->counts[sectionid] += total;
01948 return (result);
01949 }
01950 if (result == ISC_R_NOSPACE)
01951 msg->flags |= DNS_MESSAGEFLAG_TC;
01952 if (result != ISC_R_SUCCESS) {
01953 INSIST(st.used < 65536);
01954 dns_compress_rollback(msg->cctx,
01955 (isc_uint16_t)st.used);
01956 *(msg->buffer) = st;
01957 msg->buffer->length += msg->reserved;
01958 msg->counts[sectionid] += total;
01959 return (result);
01960 }
01961 rdataset->attributes |= DNS_RDATASETATTR_RENDERED;
01962 }
01963 }
01964
01965 do {
01966 name = ISC_LIST_HEAD(*section);
01967 if (name == NULL) {
01968 msg->buffer->length += msg->reserved;
01969 msg->counts[sectionid] += total;
01970 return (ISC_R_SUCCESS);
01971 }
01972
01973 while (name != NULL) {
01974 next_name = ISC_LIST_NEXT(name, link);
01975
01976 rdataset = ISC_LIST_HEAD(name->list);
01977 while (rdataset != NULL) {
01978 next_rdataset = ISC_LIST_NEXT(rdataset, link);
01979
01980 if ((rdataset->attributes &
01981 DNS_RDATASETATTR_RENDERED) != 0)
01982 goto next;
01983
01984 if (((options & DNS_MESSAGERENDER_ORDERED)
01985 == 0)
01986 && (sectionid == DNS_SECTION_ADDITIONAL)
01987 && wrong_priority(rdataset, pass,
01988 preferred_glue))
01989 goto next;
01990
01991 #ifdef ALLOW_FILTER_AAAA
01992
01993
01994
01995
01996
01997 if (norender_rdataset(rdataset, options) &&
01998 sectionid != DNS_SECTION_QUESTION) {
01999 if (sectionid == DNS_SECTION_ANSWER ||
02000 sectionid == DNS_SECTION_AUTHORITY)
02001 msg->flags &= ~DNS_MESSAGEFLAG_AD;
02002 if (OPTOUT(rdataset))
02003 msg->flags &= ~DNS_MESSAGEFLAG_AD;
02004 goto next;
02005 }
02006
02007 #endif
02008 st = *(msg->buffer);
02009
02010 count = 0;
02011 if (partial)
02012 result = dns_rdataset_towirepartial(
02013 rdataset,
02014 name,
02015 msg->cctx,
02016 msg->buffer,
02017 msg->order,
02018 msg->order_arg,
02019 rd_options,
02020 &count,
02021 NULL);
02022 else
02023 result = dns_rdataset_towiresorted(
02024 rdataset,
02025 name,
02026 msg->cctx,
02027 msg->buffer,
02028 msg->order,
02029 msg->order_arg,
02030 rd_options,
02031 &count);
02032
02033 total += count;
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048 if (partial && result == ISC_R_NOSPACE) {
02049 msg->buffer->length += msg->reserved;
02050 msg->counts[sectionid] += total;
02051 return (result);
02052 }
02053 if (result != ISC_R_SUCCESS) {
02054 INSIST(st.used < 65536);
02055 dns_compress_rollback(msg->cctx,
02056 (isc_uint16_t)st.used);
02057 *(msg->buffer) = st;
02058 msg->buffer->length += msg->reserved;
02059 msg->counts[sectionid] += total;
02060 return (result);
02061 }
02062
02063
02064
02065
02066
02067 if (rdataset->trust != dns_trust_secure &&
02068 (sectionid == DNS_SECTION_ANSWER ||
02069 sectionid == DNS_SECTION_AUTHORITY))
02070 msg->flags &= ~DNS_MESSAGEFLAG_AD;
02071 if (OPTOUT(rdataset))
02072 msg->flags &= ~DNS_MESSAGEFLAG_AD;
02073
02074 rdataset->attributes |=
02075 DNS_RDATASETATTR_RENDERED;
02076
02077 next:
02078 rdataset = next_rdataset;
02079 }
02080
02081 name = next_name;
02082 }
02083 } while (--pass != 0);
02084
02085 msg->buffer->length += msg->reserved;
02086 msg->counts[sectionid] += total;
02087
02088 return (ISC_R_SUCCESS);
02089 }
02090
02091 void
02092 dns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) {
02093 isc_uint16_t tmp;
02094 isc_region_t r;
02095
02096 REQUIRE(DNS_MESSAGE_VALID(msg));
02097 REQUIRE(target != NULL);
02098
02099 isc_buffer_availableregion(target, &r);
02100 REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN);
02101
02102 isc_buffer_putuint16(target, msg->id);
02103
02104 tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT)
02105 & DNS_MESSAGE_OPCODE_MASK);
02106 tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK);
02107 tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK);
02108
02109 INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 &&
02110 msg->counts[DNS_SECTION_ANSWER] < 65536 &&
02111 msg->counts[DNS_SECTION_AUTHORITY] < 65536 &&
02112 msg->counts[DNS_SECTION_ADDITIONAL] < 65536);
02113
02114 isc_buffer_putuint16(target, tmp);
02115 isc_buffer_putuint16(target,
02116 (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]);
02117 isc_buffer_putuint16(target,
02118 (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]);
02119 isc_buffer_putuint16(target,
02120 (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]);
02121 isc_buffer_putuint16(target,
02122 (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);
02123 }
02124
02125 isc_result_t
02126 dns_message_renderend(dns_message_t *msg) {
02127 isc_buffer_t tmpbuf;
02128 isc_region_t r;
02129 int result;
02130 unsigned int count;
02131
02132 REQUIRE(DNS_MESSAGE_VALID(msg));
02133 REQUIRE(msg->buffer != NULL);
02134
02135 if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) {
02136
02137
02138
02139 return (DNS_R_FORMERR);
02140 }
02141
02142
02143
02144
02145
02146
02147
02148 if ((msg->tsigkey != NULL || msg->sig0key != NULL || msg->opt) &&
02149 (msg->flags & DNS_MESSAGEFLAG_TC) != 0)
02150 {
02151 isc_buffer_t *buf;
02152
02153 msgresetnames(msg, DNS_SECTION_ANSWER);
02154 buf = msg->buffer;
02155 dns_message_renderreset(msg);
02156 msg->buffer = buf;
02157 isc_buffer_clear(msg->buffer);
02158 isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN);
02159 dns_compress_rollback(msg->cctx, 0);
02160 result = dns_message_rendersection(msg, DNS_SECTION_QUESTION,
02161 0);
02162 if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)
02163 return (result);
02164 }
02165
02166
02167
02168
02169 if (msg->opt != NULL) {
02170 dns_message_renderrelease(msg, msg->opt_reserved);
02171 msg->opt_reserved = 0;
02172
02173
02174
02175 msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK;
02176 msg->opt->ttl |= ((msg->rcode << 20) &
02177 DNS_MESSAGE_EDNSRCODE_MASK);
02178
02179
02180
02181 count = 0;
02182 result = dns_rdataset_towire(msg->opt, dns_rootname,
02183 msg->cctx, msg->buffer, 0,
02184 &count);
02185 msg->counts[DNS_SECTION_ADDITIONAL] += count;
02186 if (result != ISC_R_SUCCESS)
02187 return (result);
02188 }
02189
02190
02191
02192
02193 if (msg->tsigkey != NULL) {
02194 dns_message_renderrelease(msg, msg->sig_reserved);
02195 msg->sig_reserved = 0;
02196 result = dns_tsig_sign(msg);
02197 if (result != ISC_R_SUCCESS)
02198 return (result);
02199 count = 0;
02200 result = dns_rdataset_towire(msg->tsig, msg->tsigname,
02201 msg->cctx, msg->buffer, 0,
02202 &count);
02203 msg->counts[DNS_SECTION_ADDITIONAL] += count;
02204 if (result != ISC_R_SUCCESS)
02205 return (result);
02206 }
02207
02208
02209
02210
02211 if (msg->sig0key != NULL) {
02212 dns_message_renderrelease(msg, msg->sig_reserved);
02213 msg->sig_reserved = 0;
02214 result = dns_dnssec_signmessage(msg, msg->sig0key);
02215 if (result != ISC_R_SUCCESS)
02216 return (result);
02217 count = 0;
02218
02219
02220
02221
02222
02223 result = dns_rdataset_towire(msg->sig0, dns_rootname,
02224 msg->cctx, msg->buffer, 0,
02225 &count);
02226 msg->counts[DNS_SECTION_ADDITIONAL] += count;
02227 if (result != ISC_R_SUCCESS)
02228 return (result);
02229 }
02230
02231 isc_buffer_usedregion(msg->buffer, &r);
02232 isc_buffer_init(&tmpbuf, r.base, r.length);
02233
02234 dns_message_renderheader(msg, &tmpbuf);
02235
02236 msg->buffer = NULL;
02237
02238 return (ISC_R_SUCCESS);
02239 }
02240
02241 void
02242 dns_message_renderreset(dns_message_t *msg) {
02243 unsigned int i;
02244 dns_name_t *name;
02245 dns_rdataset_t *rds;
02246
02247
02248
02249
02250
02251 REQUIRE(DNS_MESSAGE_VALID(msg));
02252 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
02253
02254 msg->buffer = NULL;
02255
02256 for (i = 0; i < DNS_SECTION_MAX; i++) {
02257 msg->cursors[i] = NULL;
02258 msg->counts[i] = 0;
02259 for (name = ISC_LIST_HEAD(msg->sections[i]);
02260 name != NULL;
02261 name = ISC_LIST_NEXT(name, link)) {
02262 for (rds = ISC_LIST_HEAD(name->list);
02263 rds != NULL;
02264 rds = ISC_LIST_NEXT(rds, link)) {
02265 rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
02266 }
02267 }
02268 }
02269 if (msg->tsigname != NULL)
02270 dns_message_puttempname(msg, &msg->tsigname);
02271 if (msg->tsig != NULL) {
02272 dns_rdataset_disassociate(msg->tsig);
02273 dns_message_puttemprdataset(msg, &msg->tsig);
02274 }
02275 if (msg->sig0 != NULL) {
02276 dns_rdataset_disassociate(msg->sig0);
02277 dns_message_puttemprdataset(msg, &msg->sig0);
02278 }
02279 }
02280
02281 isc_result_t
02282 dns_message_firstname(dns_message_t *msg, dns_section_t section) {
02283 REQUIRE(DNS_MESSAGE_VALID(msg));
02284 REQUIRE(VALID_NAMED_SECTION(section));
02285
02286 msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]);
02287
02288 if (msg->cursors[section] == NULL)
02289 return (ISC_R_NOMORE);
02290
02291 return (ISC_R_SUCCESS);
02292 }
02293
02294 isc_result_t
02295 dns_message_nextname(dns_message_t *msg, dns_section_t section) {
02296 REQUIRE(DNS_MESSAGE_VALID(msg));
02297 REQUIRE(VALID_NAMED_SECTION(section));
02298 REQUIRE(msg->cursors[section] != NULL);
02299
02300 msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link);
02301
02302 if (msg->cursors[section] == NULL)
02303 return (ISC_R_NOMORE);
02304
02305 return (ISC_R_SUCCESS);
02306 }
02307
02308 void
02309 dns_message_currentname(dns_message_t *msg, dns_section_t section,
02310 dns_name_t **name)
02311 {
02312 REQUIRE(DNS_MESSAGE_VALID(msg));
02313 REQUIRE(VALID_NAMED_SECTION(section));
02314 REQUIRE(name != NULL && *name == NULL);
02315 REQUIRE(msg->cursors[section] != NULL);
02316
02317 *name = msg->cursors[section];
02318 }
02319
02320 isc_result_t
02321 dns_message_findname(dns_message_t *msg, dns_section_t section,
02322 dns_name_t *target, dns_rdatatype_t type,
02323 dns_rdatatype_t covers, dns_name_t **name,
02324 dns_rdataset_t **rdataset)
02325 {
02326 dns_name_t *foundname;
02327 isc_result_t result;
02328
02329
02330
02331
02332
02333
02334
02335 REQUIRE(msg != NULL);
02336 REQUIRE(VALID_SECTION(section));
02337 REQUIRE(target != NULL);
02338 if (name != NULL)
02339 REQUIRE(*name == NULL);
02340 if (type == dns_rdatatype_any) {
02341 REQUIRE(rdataset == NULL);
02342 } else {
02343 if (rdataset != NULL)
02344 REQUIRE(*rdataset == NULL);
02345 }
02346
02347 result = findname(&foundname, target,
02348 &msg->sections[section]);
02349
02350 if (result == ISC_R_NOTFOUND)
02351 return (DNS_R_NXDOMAIN);
02352 else if (result != ISC_R_SUCCESS)
02353 return (result);
02354
02355 if (name != NULL)
02356 *name = foundname;
02357
02358
02359
02360
02361 if (type == dns_rdatatype_any)
02362 return (ISC_R_SUCCESS);
02363
02364 result = dns_message_findtype(foundname, type, covers, rdataset);
02365 if (result == ISC_R_NOTFOUND)
02366 return (DNS_R_NXRRSET);
02367
02368 return (result);
02369 }
02370
02371 void
02372 dns_message_movename(dns_message_t *msg, dns_name_t *name,
02373 dns_section_t fromsection,
02374 dns_section_t tosection)
02375 {
02376 REQUIRE(msg != NULL);
02377 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
02378 REQUIRE(name != NULL);
02379 REQUIRE(VALID_NAMED_SECTION(fromsection));
02380 REQUIRE(VALID_NAMED_SECTION(tosection));
02381
02382
02383
02384
02385 ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
02386 ISC_LIST_APPEND(msg->sections[tosection], name, link);
02387 }
02388
02389 void
02390 dns_message_addname(dns_message_t *msg, dns_name_t *name,
02391 dns_section_t section)
02392 {
02393 REQUIRE(msg != NULL);
02394 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
02395 REQUIRE(name != NULL);
02396 REQUIRE(VALID_NAMED_SECTION(section));
02397
02398 ISC_LIST_APPEND(msg->sections[section], name, link);
02399 }
02400
02401 void
02402 dns_message_removename(dns_message_t *msg, dns_name_t *name,
02403 dns_section_t section)
02404 {
02405 REQUIRE(msg != NULL);
02406 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
02407 REQUIRE(name != NULL);
02408 REQUIRE(VALID_NAMED_SECTION(section));
02409
02410 ISC_LIST_UNLINK(msg->sections[section], name, link);
02411 }
02412
02413 isc_result_t
02414 dns_message_gettempname(dns_message_t *msg, dns_name_t **item) {
02415 REQUIRE(DNS_MESSAGE_VALID(msg));
02416 REQUIRE(item != NULL && *item == NULL);
02417
02418 *item = isc_mempool_get(msg->namepool);
02419 if (*item == NULL)
02420 return (ISC_R_NOMEMORY);
02421 dns_name_init(*item, NULL);
02422
02423 return (ISC_R_SUCCESS);
02424 }
02425
02426 isc_result_t
02427 dns_message_gettempoffsets(dns_message_t *msg, dns_offsets_t **item) {
02428 REQUIRE(DNS_MESSAGE_VALID(msg));
02429 REQUIRE(item != NULL && *item == NULL);
02430
02431 *item = newoffsets(msg);
02432 if (*item == NULL)
02433 return (ISC_R_NOMEMORY);
02434
02435 return (ISC_R_SUCCESS);
02436 }
02437
02438 isc_result_t
02439 dns_message_gettemprdata(dns_message_t *msg, dns_rdata_t **item) {
02440 REQUIRE(DNS_MESSAGE_VALID(msg));
02441 REQUIRE(item != NULL && *item == NULL);
02442
02443 *item = newrdata(msg);
02444 if (*item == NULL)
02445 return (ISC_R_NOMEMORY);
02446
02447 return (ISC_R_SUCCESS);
02448 }
02449
02450 isc_result_t
02451 dns_message_gettemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
02452 REQUIRE(DNS_MESSAGE_VALID(msg));
02453 REQUIRE(item != NULL && *item == NULL);
02454
02455 *item = isc_mempool_get(msg->rdspool);
02456 if (*item == NULL)
02457 return (ISC_R_NOMEMORY);
02458
02459 dns_rdataset_init(*item);
02460
02461 return (ISC_R_SUCCESS);
02462 }
02463
02464 isc_result_t
02465 dns_message_gettemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
02466 REQUIRE(DNS_MESSAGE_VALID(msg));
02467 REQUIRE(item != NULL && *item == NULL);
02468
02469 *item = newrdatalist(msg);
02470 if (*item == NULL)
02471 return (ISC_R_NOMEMORY);
02472
02473 return (ISC_R_SUCCESS);
02474 }
02475
02476 void
02477 dns_message_puttempname(dns_message_t *msg, dns_name_t **item) {
02478 REQUIRE(DNS_MESSAGE_VALID(msg));
02479 REQUIRE(item != NULL && *item != NULL);
02480
02481 if (dns_name_dynamic(*item))
02482 dns_name_free(*item, msg->mctx);
02483 isc_mempool_put(msg->namepool, *item);
02484 *item = NULL;
02485 }
02486
02487 void
02488 dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
02489 REQUIRE(DNS_MESSAGE_VALID(msg));
02490 REQUIRE(item != NULL && *item != NULL);
02491
02492 releaserdata(msg, *item);
02493 *item = NULL;
02494 }
02495
02496 void
02497 dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) {
02498 REQUIRE(DNS_MESSAGE_VALID(msg));
02499 REQUIRE(item != NULL && *item != NULL);
02500
02501 REQUIRE(!dns_rdataset_isassociated(*item));
02502 isc_mempool_put(msg->rdspool, *item);
02503 *item = NULL;
02504 }
02505
02506 void
02507 dns_message_puttemprdatalist(dns_message_t *msg, dns_rdatalist_t **item) {
02508 REQUIRE(DNS_MESSAGE_VALID(msg));
02509 REQUIRE(item != NULL && *item != NULL);
02510
02511 releaserdatalist(msg, *item);
02512 *item = NULL;
02513 }
02514
02515 isc_result_t
02516 dns_message_peekheader(isc_buffer_t *source, dns_messageid_t *idp,
02517 unsigned int *flagsp)
02518 {
02519 isc_region_t r;
02520 isc_buffer_t buffer;
02521 dns_messageid_t id;
02522 unsigned int flags;
02523
02524 REQUIRE(source != NULL);
02525
02526 buffer = *source;
02527
02528 isc_buffer_remainingregion(&buffer, &r);
02529 if (r.length < DNS_MESSAGE_HEADERLEN)
02530 return (ISC_R_UNEXPECTEDEND);
02531
02532 id = isc_buffer_getuint16(&buffer);
02533 flags = isc_buffer_getuint16(&buffer);
02534 flags &= DNS_MESSAGE_FLAG_MASK;
02535
02536 if (flagsp != NULL)
02537 *flagsp = flags;
02538 if (idp != NULL)
02539 *idp = id;
02540
02541 return (ISC_R_SUCCESS);
02542 }
02543
02544 isc_result_t
02545 dns_message_reply(dns_message_t *msg, isc_boolean_t want_question_section) {
02546 unsigned int clear_after;
02547 isc_result_t result;
02548
02549 REQUIRE(DNS_MESSAGE_VALID(msg));
02550 REQUIRE((msg->flags & DNS_MESSAGEFLAG_QR) == 0);
02551
02552 if (!msg->header_ok)
02553 return (DNS_R_FORMERR);
02554 if (msg->opcode != dns_opcode_query &&
02555 msg->opcode != dns_opcode_notify)
02556 want_question_section = ISC_FALSE;
02557 if (msg->opcode == dns_opcode_update)
02558 clear_after = DNS_SECTION_PREREQUISITE;
02559 else if (want_question_section) {
02560 if (!msg->question_ok)
02561 return (DNS_R_FORMERR);
02562 clear_after = DNS_SECTION_ANSWER;
02563 } else
02564 clear_after = DNS_SECTION_QUESTION;
02565 msg->from_to_wire = DNS_MESSAGE_INTENTRENDER;
02566 msgresetnames(msg, clear_after);
02567 msgresetopt(msg);
02568 msgresetsigs(msg, ISC_TRUE);
02569 msginitprivate(msg);
02570
02571
02572
02573
02574 msg->flags &= DNS_MESSAGE_REPLYPRESERVE;
02575 msg->flags |= DNS_MESSAGEFLAG_QR;
02576
02577
02578
02579
02580
02581 if (msg->tsigkey != NULL) {
02582 unsigned int otherlen = 0;
02583 msg->querytsigstatus = msg->tsigstatus;
02584 msg->tsigstatus = dns_rcode_noerror;
02585 if (msg->querytsigstatus == dns_tsigerror_badtime)
02586 otherlen = 6;
02587 msg->sig_reserved = spacefortsig(msg->tsigkey, otherlen);
02588 result = dns_message_renderreserve(msg, msg->sig_reserved);
02589 if (result != ISC_R_SUCCESS) {
02590 msg->sig_reserved = 0;
02591 return (result);
02592 }
02593 }
02594 if (msg->saved.base != NULL) {
02595 msg->query.base = msg->saved.base;
02596 msg->query.length = msg->saved.length;
02597 msg->free_query = msg->free_saved;
02598 msg->saved.base = NULL;
02599 msg->saved.length = 0;
02600 msg->free_saved = 0;
02601 }
02602
02603 return (ISC_R_SUCCESS);
02604 }
02605
02606 dns_rdataset_t *
02607 dns_message_getopt(dns_message_t *msg) {
02608
02609
02610
02611
02612
02613 REQUIRE(DNS_MESSAGE_VALID(msg));
02614
02615 return (msg->opt);
02616 }
02617
02618 isc_result_t
02619 dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) {
02620 isc_result_t result;
02621 dns_rdata_t rdata = DNS_RDATA_INIT;
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641 REQUIRE(DNS_MESSAGE_VALID(msg));
02642 REQUIRE(opt->type == dns_rdatatype_opt);
02643 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
02644 REQUIRE(msg->state == DNS_SECTION_ANY);
02645
02646 msgresetopt(msg);
02647
02648 result = dns_rdataset_first(opt);
02649 if (result != ISC_R_SUCCESS)
02650 goto cleanup;
02651 dns_rdataset_current(opt, &rdata);
02652 msg->opt_reserved = 11 + rdata.length;
02653 result = dns_message_renderreserve(msg, msg->opt_reserved);
02654 if (result != ISC_R_SUCCESS) {
02655 msg->opt_reserved = 0;
02656 goto cleanup;
02657 }
02658
02659 msg->opt = opt;
02660
02661 return (ISC_R_SUCCESS);
02662
02663 cleanup:
02664 dns_rdataset_disassociate(opt);
02665 dns_message_puttemprdataset(msg, &opt);
02666 return (result);
02667 }
02668
02669 dns_rdataset_t *
02670 dns_message_gettsig(dns_message_t *msg, dns_name_t **owner) {
02671
02672
02673
02674
02675
02676 REQUIRE(DNS_MESSAGE_VALID(msg));
02677 REQUIRE(owner == NULL || *owner == NULL);
02678
02679 if (owner != NULL)
02680 *owner = msg->tsigname;
02681 return (msg->tsig);
02682 }
02683
02684 isc_result_t
02685 dns_message_settsigkey(dns_message_t *msg, dns_tsigkey_t *key) {
02686 isc_result_t result;
02687
02688
02689
02690
02691
02692 REQUIRE(DNS_MESSAGE_VALID(msg));
02693 REQUIRE(msg->state == DNS_SECTION_ANY);
02694
02695 if (key == NULL && msg->tsigkey != NULL) {
02696 if (msg->sig_reserved != 0) {
02697 dns_message_renderrelease(msg, msg->sig_reserved);
02698 msg->sig_reserved = 0;
02699 }
02700 dns_tsigkey_detach(&msg->tsigkey);
02701 }
02702 if (key != NULL) {
02703 REQUIRE(msg->tsigkey == NULL && msg->sig0key == NULL);
02704 dns_tsigkey_attach(key, &msg->tsigkey);
02705 if (msg->from_to_wire == DNS_MESSAGE_INTENTRENDER) {
02706 msg->sig_reserved = spacefortsig(msg->tsigkey, 0);
02707 result = dns_message_renderreserve(msg,
02708 msg->sig_reserved);
02709 if (result != ISC_R_SUCCESS) {
02710 dns_tsigkey_detach(&msg->tsigkey);
02711 msg->sig_reserved = 0;
02712 return (result);
02713 }
02714 }
02715 }
02716 return (ISC_R_SUCCESS);
02717 }
02718
02719 dns_tsigkey_t *
02720 dns_message_gettsigkey(dns_message_t *msg) {
02721
02722
02723
02724
02725
02726 REQUIRE(DNS_MESSAGE_VALID(msg));
02727
02728 return (msg->tsigkey);
02729 }
02730
02731 isc_result_t
02732 dns_message_setquerytsig(dns_message_t *msg, isc_buffer_t *querytsig) {
02733 dns_rdata_t *rdata = NULL;
02734 dns_rdatalist_t *list = NULL;
02735 dns_rdataset_t *set = NULL;
02736 isc_buffer_t *buf = NULL;
02737 isc_region_t r;
02738 isc_result_t result;
02739
02740 REQUIRE(DNS_MESSAGE_VALID(msg));
02741 REQUIRE(msg->querytsig == NULL);
02742
02743 if (querytsig == NULL)
02744 return (ISC_R_SUCCESS);
02745
02746 result = dns_message_gettemprdata(msg, &rdata);
02747 if (result != ISC_R_SUCCESS)
02748 goto cleanup;
02749
02750 result = dns_message_gettemprdatalist(msg, &list);
02751 if (result != ISC_R_SUCCESS)
02752 goto cleanup;
02753 result = dns_message_gettemprdataset(msg, &set);
02754 if (result != ISC_R_SUCCESS)
02755 goto cleanup;
02756
02757 isc_buffer_usedregion(querytsig, &r);
02758 result = isc_buffer_allocate(msg->mctx, &buf, r.length);
02759 if (result != ISC_R_SUCCESS)
02760 goto cleanup;
02761 isc_buffer_putmem(buf, r.base, r.length);
02762 isc_buffer_usedregion(buf, &r);
02763 dns_rdata_init(rdata);
02764 dns_rdata_fromregion(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &r);
02765 dns_message_takebuffer(msg, &buf);
02766 ISC_LIST_APPEND(list->rdata, rdata, link);
02767 result = dns_rdatalist_tordataset(list, set);
02768 if (result != ISC_R_SUCCESS)
02769 goto cleanup;
02770
02771 msg->querytsig = set;
02772
02773 return (result);
02774
02775 cleanup:
02776 if (rdata != NULL)
02777 dns_message_puttemprdata(msg, &rdata);
02778 if (list != NULL)
02779 dns_message_puttemprdatalist(msg, &list);
02780 if (set != NULL)
02781 dns_message_puttemprdataset(msg, &set);
02782 return (ISC_R_NOMEMORY);
02783 }
02784
02785 isc_result_t
02786 dns_message_getquerytsig(dns_message_t *msg, isc_mem_t *mctx,
02787 isc_buffer_t **querytsig) {
02788 isc_result_t result;
02789 dns_rdata_t rdata = DNS_RDATA_INIT;
02790 isc_region_t r;
02791
02792 REQUIRE(DNS_MESSAGE_VALID(msg));
02793 REQUIRE(mctx != NULL);
02794 REQUIRE(querytsig != NULL && *querytsig == NULL);
02795
02796 if (msg->tsig == NULL)
02797 return (ISC_R_SUCCESS);
02798
02799 result = dns_rdataset_first(msg->tsig);
02800 if (result != ISC_R_SUCCESS)
02801 return (result);
02802 dns_rdataset_current(msg->tsig, &rdata);
02803 dns_rdata_toregion(&rdata, &r);
02804
02805 result = isc_buffer_allocate(mctx, querytsig, r.length);
02806 if (result != ISC_R_SUCCESS)
02807 return (result);
02808 isc_buffer_putmem(*querytsig, r.base, r.length);
02809 return (ISC_R_SUCCESS);
02810 }
02811
02812 dns_rdataset_t *
02813 dns_message_getsig0(dns_message_t *msg, dns_name_t **owner) {
02814
02815
02816
02817
02818
02819 REQUIRE(DNS_MESSAGE_VALID(msg));
02820 REQUIRE(owner == NULL || *owner == NULL);
02821
02822 if (msg->sig0 != NULL && owner != NULL) {
02823
02824
02825
02826
02827 if (msg->sig0name == NULL)
02828 *owner = dns_rootname;
02829 else
02830 *owner = msg->sig0name;
02831 }
02832 return (msg->sig0);
02833 }
02834
02835 isc_result_t
02836 dns_message_setsig0key(dns_message_t *msg, dst_key_t *key) {
02837 isc_region_t r;
02838 unsigned int x;
02839 isc_result_t result;
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864 REQUIRE(DNS_MESSAGE_VALID(msg));
02865 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
02866 REQUIRE(msg->state == DNS_SECTION_ANY);
02867
02868 if (key != NULL) {
02869 REQUIRE(msg->sig0key == NULL && msg->tsigkey == NULL);
02870 dns_name_toregion(dst_key_name(key), &r);
02871 result = dst_key_sigsize(key, &x);
02872 if (result != ISC_R_SUCCESS) {
02873 msg->sig_reserved = 0;
02874 return (result);
02875 }
02876 msg->sig_reserved = 27 + r.length + x;
02877 result = dns_message_renderreserve(msg, msg->sig_reserved);
02878 if (result != ISC_R_SUCCESS) {
02879 msg->sig_reserved = 0;
02880 return (result);
02881 }
02882 msg->sig0key = key;
02883 }
02884 return (ISC_R_SUCCESS);
02885 }
02886
02887 dst_key_t *
02888 dns_message_getsig0key(dns_message_t *msg) {
02889
02890
02891
02892
02893
02894 REQUIRE(DNS_MESSAGE_VALID(msg));
02895
02896 return (msg->sig0key);
02897 }
02898
02899 void
02900 dns_message_takebuffer(dns_message_t *msg, isc_buffer_t **buffer) {
02901 REQUIRE(DNS_MESSAGE_VALID(msg));
02902 REQUIRE(buffer != NULL);
02903 REQUIRE(ISC_BUFFER_VALID(*buffer));
02904
02905 ISC_LIST_APPEND(msg->cleanup, *buffer, link);
02906 *buffer = NULL;
02907 }
02908
02909 isc_result_t
02910 dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
02911 isc_result_t result = ISC_R_SUCCESS;
02912 dns_rdata_t rdata = DNS_RDATA_INIT;
02913
02914 REQUIRE(DNS_MESSAGE_VALID(msg));
02915 REQUIRE(signer != NULL);
02916 REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTPARSE);
02917
02918 if (msg->tsig == NULL && msg->sig0 == NULL)
02919 return (ISC_R_NOTFOUND);
02920
02921 if (msg->verify_attempted == 0)
02922 return (DNS_R_NOTVERIFIEDYET);
02923
02924 if (!dns_name_hasbuffer(signer)) {
02925 isc_buffer_t *dynbuf = NULL;
02926 result = isc_buffer_allocate(msg->mctx, &dynbuf, 512);
02927 if (result != ISC_R_SUCCESS)
02928 return (result);
02929 dns_name_setbuffer(signer, dynbuf);
02930 dns_message_takebuffer(msg, &dynbuf);
02931 }
02932
02933 if (msg->sig0 != NULL) {
02934 dns_rdata_sig_t sig;
02935
02936 result = dns_rdataset_first(msg->sig0);
02937 INSIST(result == ISC_R_SUCCESS);
02938 dns_rdataset_current(msg->sig0, &rdata);
02939
02940 result = dns_rdata_tostruct(&rdata, &sig, NULL);
02941 if (result != ISC_R_SUCCESS)
02942 return (result);
02943
02944 if (msg->verified_sig && msg->sig0status == dns_rcode_noerror)
02945 result = ISC_R_SUCCESS;
02946 else
02947 result = DNS_R_SIGINVALID;
02948 dns_name_clone(&sig.signer, signer);
02949 dns_rdata_freestruct(&sig);
02950 } else {
02951 dns_name_t *identity;
02952 dns_rdata_any_tsig_t tsig;
02953
02954 result = dns_rdataset_first(msg->tsig);
02955 INSIST(result == ISC_R_SUCCESS);
02956 dns_rdataset_current(msg->tsig, &rdata);
02957
02958 result = dns_rdata_tostruct(&rdata, &tsig, NULL);
02959 INSIST(result == ISC_R_SUCCESS);
02960 if (msg->tsigstatus != dns_rcode_noerror)
02961 result = DNS_R_TSIGVERIFYFAILURE;
02962 else if (tsig.error != dns_rcode_noerror)
02963 result = DNS_R_TSIGERRORSET;
02964 else
02965 result = ISC_R_SUCCESS;
02966 dns_rdata_freestruct(&tsig);
02967
02968 if (msg->tsigkey == NULL) {
02969
02970
02971
02972
02973
02974
02975 INSIST(result != ISC_R_SUCCESS);
02976 } else {
02977 identity = dns_tsigkey_identity(msg->tsigkey);
02978 if (identity == NULL) {
02979 if (result == ISC_R_SUCCESS)
02980 result = DNS_R_NOIDENTITY;
02981 identity = &msg->tsigkey->name;
02982 }
02983 dns_name_clone(identity, signer);
02984 }
02985 }
02986
02987 return (result);
02988 }
02989
02990 void
02991 dns_message_resetsig(dns_message_t *msg) {
02992 REQUIRE(DNS_MESSAGE_VALID(msg));
02993 msg->verified_sig = 0;
02994 msg->verify_attempted = 0;
02995 msg->tsigstatus = dns_rcode_noerror;
02996 msg->sig0status = dns_rcode_noerror;
02997 msg->timeadjust = 0;
02998 if (msg->tsigkey != NULL) {
02999 dns_tsigkey_detach(&msg->tsigkey);
03000 msg->tsigkey = NULL;
03001 }
03002 }
03003
03004 isc_result_t
03005 dns_message_rechecksig(dns_message_t *msg, dns_view_t *view) {
03006 dns_message_resetsig(msg);
03007 return (dns_message_checksig(msg, view));
03008 }
03009
03010 #ifdef SKAN_MSG_DEBUG
03011 void
03012 dns_message_dumpsig(dns_message_t *msg, char *txt1) {
03013 dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
03014 dns_rdata_any_tsig_t querytsig;
03015 isc_result_t result;
03016
03017 if (msg->tsig != NULL) {
03018 result = dns_rdataset_first(msg->tsig);
03019 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03020 dns_rdataset_current(msg->tsig, &querytsigrdata);
03021 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
03022 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03023 hexdump(txt1, "TSIG", querytsig.signature,
03024 querytsig.siglen);
03025 }
03026
03027 if (msg->querytsig != NULL) {
03028 result = dns_rdataset_first(msg->querytsig);
03029 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03030 dns_rdataset_current(msg->querytsig, &querytsigrdata);
03031 result = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL);
03032 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03033 hexdump(txt1, "QUERYTSIG", querytsig.signature,
03034 querytsig.siglen);
03035 }
03036 }
03037 #endif
03038
03039 isc_result_t
03040 dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
03041 isc_buffer_t b, msgb;
03042
03043 REQUIRE(DNS_MESSAGE_VALID(msg));
03044
03045 if (msg->tsigkey == NULL && msg->tsig == NULL && msg->sig0 == NULL)
03046 return (ISC_R_SUCCESS);
03047
03048 INSIST(msg->saved.base != NULL);
03049 isc_buffer_init(&msgb, msg->saved.base, msg->saved.length);
03050 isc_buffer_add(&msgb, msg->saved.length);
03051 if (msg->tsigkey != NULL || msg->tsig != NULL) {
03052 #ifdef SKAN_MSG_DEBUG
03053 dns_message_dumpsig(msg, "dns_message_checksig#1");
03054 #endif
03055 if (view != NULL)
03056 return (dns_view_checksig(view, &msgb, msg));
03057 else
03058 return (dns_tsig_verify(&msgb, msg, NULL, NULL));
03059 } else {
03060 dns_rdata_t rdata = DNS_RDATA_INIT;
03061 dns_rdata_sig_t sig;
03062 dns_rdataset_t keyset;
03063 isc_result_t result;
03064
03065 result = dns_rdataset_first(msg->sig0);
03066 INSIST(result == ISC_R_SUCCESS);
03067 dns_rdataset_current(msg->sig0, &rdata);
03068
03069
03070
03071
03072
03073
03074
03075
03076 if (rdata.length == 0)
03077 return (ISC_R_UNEXPECTEDEND);
03078
03079 result = dns_rdata_tostruct(&rdata, &sig, msg->mctx);
03080 if (result != ISC_R_SUCCESS)
03081 return (result);
03082
03083 dns_rdataset_init(&keyset);
03084 if (view == NULL)
03085 return (DNS_R_KEYUNAUTHORIZED);
03086 result = dns_view_simplefind(view, &sig.signer,
03087 dns_rdatatype_key ,
03088 0, 0, ISC_FALSE, &keyset, NULL);
03089
03090 if (result != ISC_R_SUCCESS) {
03091
03092 result = DNS_R_KEYUNAUTHORIZED;
03093 goto freesig;
03094 } else if (keyset.trust < dns_trust_secure) {
03095
03096 result = DNS_R_KEYUNAUTHORIZED;
03097 goto freesig;
03098 }
03099 result = dns_rdataset_first(&keyset);
03100 INSIST(result == ISC_R_SUCCESS);
03101 for (;
03102 result == ISC_R_SUCCESS;
03103 result = dns_rdataset_next(&keyset))
03104 {
03105 dst_key_t *key = NULL;
03106
03107 dns_rdata_reset(&rdata);
03108 dns_rdataset_current(&keyset, &rdata);
03109 isc_buffer_init(&b, rdata.data, rdata.length);
03110 isc_buffer_add(&b, rdata.length);
03111
03112 result = dst_key_fromdns(&sig.signer, rdata.rdclass,
03113 &b, view->mctx, &key);
03114 if (result != ISC_R_SUCCESS)
03115 continue;
03116 if (dst_key_alg(key) != sig.algorithm ||
03117 dst_key_id(key) != sig.keyid ||
03118 !(dst_key_proto(key) == DNS_KEYPROTO_DNSSEC ||
03119 dst_key_proto(key) == DNS_KEYPROTO_ANY))
03120 {
03121 dst_key_free(&key);
03122 continue;
03123 }
03124 result = dns_dnssec_verifymessage(&msgb, msg, key);
03125 dst_key_free(&key);
03126 if (result == ISC_R_SUCCESS)
03127 break;
03128 }
03129 if (result == ISC_R_NOMORE)
03130 result = DNS_R_KEYUNAUTHORIZED;
03131
03132 freesig:
03133 if (dns_rdataset_isassociated(&keyset))
03134 dns_rdataset_disassociate(&keyset);
03135 dns_rdata_freestruct(&sig);
03136 return (result);
03137 }
03138 }
03139
03140 isc_result_t
03141 dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
03142 const dns_master_style_t *style,
03143 dns_messagetextflag_t flags,
03144 isc_buffer_t *target) {
03145 dns_name_t *name, empty_name;
03146 dns_rdataset_t *rdataset;
03147 isc_result_t result;
03148 isc_boolean_t seensoa = ISC_FALSE;
03149
03150 REQUIRE(DNS_MESSAGE_VALID(msg));
03151 REQUIRE(target != NULL);
03152 REQUIRE(VALID_SECTION(section));
03153
03154 if (ISC_LIST_EMPTY(msg->sections[section]))
03155 return (ISC_R_SUCCESS);
03156
03157 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0) {
03158 ADD_STRING(target, ";; ");
03159 if (msg->opcode != dns_opcode_update) {
03160 ADD_STRING(target, sectiontext[section]);
03161 } else {
03162 ADD_STRING(target, updsectiontext[section]);
03163 }
03164 ADD_STRING(target, " SECTION:\n");
03165 }
03166
03167 dns_name_init(&empty_name, NULL);
03168 result = dns_message_firstname(msg, section);
03169 if (result != ISC_R_SUCCESS) {
03170 return (result);
03171 }
03172 do {
03173 name = NULL;
03174 dns_message_currentname(msg, section, &name);
03175 for (rdataset = ISC_LIST_HEAD(name->list);
03176 rdataset != NULL;
03177 rdataset = ISC_LIST_NEXT(rdataset, link)) {
03178 if (section == DNS_SECTION_ANSWER &&
03179 rdataset->type == dns_rdatatype_soa) {
03180 if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
03181 continue;
03182 if (seensoa &&
03183 (flags & DNS_MESSAGETEXTFLAG_ONESOA) != 0)
03184 continue;
03185 seensoa = ISC_TRUE;
03186 }
03187 if (section == DNS_SECTION_QUESTION) {
03188 ADD_STRING(target, ";");
03189 result = dns_master_questiontotext(name,
03190 rdataset,
03191 style,
03192 target);
03193 } else {
03194 result = dns_master_rdatasettotext(name,
03195 rdataset,
03196 style,
03197 target);
03198 }
03199 if (result != ISC_R_SUCCESS)
03200 return (result);
03201 }
03202 result = dns_message_nextname(msg, section);
03203 } while (result == ISC_R_SUCCESS);
03204 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
03205 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
03206 ADD_STRING(target, "\n");
03207 if (result == ISC_R_NOMORE)
03208 result = ISC_R_SUCCESS;
03209 return (result);
03210 }
03211
03212 static isc_result_t
03213 render_ecs(isc_buffer_t *optbuf, isc_buffer_t *target) {
03214 int i;
03215 char addr[16], addr_text[64];
03216 isc_uint16_t family;
03217 isc_uint8_t addrlen, addrbytes, scopelen;
03218
03219 INSIST(isc_buffer_remaininglength(optbuf) >= 4);
03220 family = isc_buffer_getuint16(optbuf);
03221 addrlen = isc_buffer_getuint8(optbuf);
03222 scopelen = isc_buffer_getuint8(optbuf);
03223
03224 addrbytes = (addrlen + 7) / 8;
03225 INSIST(isc_buffer_remaininglength(optbuf) >= addrbytes);
03226
03227 memset(addr, 0, sizeof(addr));
03228 for (i = 0; i < addrbytes; i ++)
03229 addr[i] = isc_buffer_getuint8(optbuf);
03230
03231 if (family == 1)
03232 inet_ntop(AF_INET, addr, addr_text, sizeof(addr_text));
03233 else if (family == 2)
03234 inet_ntop(AF_INET6, addr, addr_text, sizeof(addr_text));
03235 else {
03236 snprintf(addr_text, sizeof(addr_text),
03237 "Unsupported family %u", family);
03238 ADD_STRING(target, addr_text);
03239 return (ISC_R_SUCCESS);
03240 }
03241
03242 ADD_STRING(target, addr_text);
03243 snprintf(addr_text, sizeof(addr_text), "/%d/%d", addrlen, scopelen);
03244 ADD_STRING(target, addr_text);
03245 return (ISC_R_SUCCESS);
03246 }
03247
03248 isc_result_t
03249 dns_message_pseudosectiontotext(dns_message_t *msg,
03250 dns_pseudosection_t section,
03251 const dns_master_style_t *style,
03252 dns_messagetextflag_t flags,
03253 isc_buffer_t *target)
03254 {
03255 dns_rdataset_t *ps = NULL;
03256 dns_name_t *name = NULL;
03257 isc_result_t result;
03258 char buf[sizeof("1234567890")];
03259 isc_uint32_t mbz;
03260 dns_rdata_t rdata;
03261 isc_buffer_t optbuf;
03262 isc_uint16_t optcode, optlen;
03263 unsigned char *optdata;
03264
03265 REQUIRE(DNS_MESSAGE_VALID(msg));
03266 REQUIRE(target != NULL);
03267 REQUIRE(VALID_PSEUDOSECTION(section));
03268
03269 switch (section) {
03270 case DNS_PSEUDOSECTION_OPT:
03271 ps = dns_message_getopt(msg);
03272 if (ps == NULL)
03273 return (ISC_R_SUCCESS);
03274 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
03275 ADD_STRING(target, ";; OPT PSEUDOSECTION:\n");
03276 ADD_STRING(target, "; EDNS: version: ");
03277 snprintf(buf, sizeof(buf), "%u",
03278 (unsigned int)((ps->ttl & 0x00ff0000) >> 16));
03279 ADD_STRING(target, buf);
03280 ADD_STRING(target, ", flags:");
03281 if ((ps->ttl & DNS_MESSAGEEXTFLAG_DO) != 0)
03282 ADD_STRING(target, " do");
03283 mbz = ps->ttl & 0xffff;
03284 mbz &= ~DNS_MESSAGEEXTFLAG_DO;
03285 if (mbz != 0) {
03286 ADD_STRING(target, "; MBZ: ");
03287 snprintf(buf, sizeof(buf), "%.4x ", mbz);
03288 ADD_STRING(target, buf);
03289 ADD_STRING(target, ", udp: ");
03290 } else
03291 ADD_STRING(target, "; udp: ");
03292 snprintf(buf, sizeof(buf), "%u\n", (unsigned int)ps->rdclass);
03293 ADD_STRING(target, buf);
03294
03295 result = dns_rdataset_first(ps);
03296 if (result != ISC_R_SUCCESS)
03297 return (ISC_R_SUCCESS);
03298
03299
03300 dns_rdata_init(&rdata);
03301 dns_rdataset_current(ps, &rdata);
03302
03303 isc_buffer_init(&optbuf, rdata.data, rdata.length);
03304 isc_buffer_add(&optbuf, rdata.length);
03305 while (isc_buffer_remaininglength(&optbuf) != 0) {
03306 INSIST(isc_buffer_remaininglength(&optbuf) >= 4U);
03307 optcode = isc_buffer_getuint16(&optbuf);
03308 optlen = isc_buffer_getuint16(&optbuf);
03309 INSIST(isc_buffer_remaininglength(&optbuf) >= optlen);
03310
03311 if (optcode == DNS_OPT_NSID) {
03312 ADD_STRING(target, "; NSID");
03313 } else if (optcode == DNS_OPT_SIT) {
03314 ADD_STRING(target, "; SIT");
03315 } else if (optcode == DNS_OPT_CLIENT_SUBNET) {
03316 ADD_STRING(target, "; CLIENT-SUBNET: ");
03317 render_ecs(&optbuf, target);
03318 ADD_STRING(target, "\n");
03319 continue;
03320 } else if (optcode == DNS_OPT_EXPIRE) {
03321 if (optlen == 4) {
03322 isc_uint32_t secs;
03323 secs = isc_buffer_getuint32(&optbuf);
03324 ADD_STRING(target, "; EXPIRE: ");
03325 snprintf(buf, sizeof(buf), "%u", secs);
03326 ADD_STRING(target, buf);
03327 ADD_STRING(target, " (");
03328 dns_ttl_totext(secs, ISC_TRUE, target);
03329 ADD_STRING(target, ")\n");
03330 continue;
03331 }
03332 ADD_STRING(target, "; EXPIRE");
03333 } else {
03334 ADD_STRING(target, "; OPT=");
03335 snprintf(buf, sizeof(buf), "%u", optcode);
03336 ADD_STRING(target, buf);
03337 }
03338
03339 if (optlen != 0) {
03340 int i;
03341 ADD_STRING(target, ": ");
03342
03343 optdata = isc_buffer_current(&optbuf);
03344 for (i = 0; i < optlen; i++) {
03345 const char *sep;
03346 switch (optcode) {
03347 case DNS_OPT_SIT:
03348 sep = "";
03349 break;
03350 default:
03351 sep = " ";
03352 break;
03353 }
03354 snprintf(buf, sizeof(buf), "%02x%s",
03355 optdata[i], sep);
03356 ADD_STRING(target, buf);
03357 }
03358
03359 isc_buffer_forward(&optbuf, optlen);
03360
03361 if (optcode == DNS_OPT_SIT) {
03362 if (msg->sitok)
03363 ADD_STRING(target, " (good)");
03364 if (msg->sitbad)
03365 ADD_STRING(target, " (bad)");
03366 ADD_STRING(target, "\n");
03367 continue;
03368 }
03369
03370
03371
03372
03373
03374 ADD_STRING(target, "(\"");
03375 if (isc_buffer_availablelength(target) < optlen)
03376 return (ISC_R_NOSPACE);
03377 for (i = 0; i < optlen; i++) {
03378 if (isprint(optdata[i]))
03379 isc_buffer_putmem(target,
03380 &optdata[i],
03381 1);
03382 else
03383 isc_buffer_putstr(target, ".");
03384 }
03385 ADD_STRING(target, "\")");
03386 }
03387 ADD_STRING(target, "\n");
03388 }
03389 return (ISC_R_SUCCESS);
03390 case DNS_PSEUDOSECTION_TSIG:
03391 ps = dns_message_gettsig(msg, &name);
03392 if (ps == NULL)
03393 return (ISC_R_SUCCESS);
03394 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
03395 ADD_STRING(target, ";; TSIG PSEUDOSECTION:\n");
03396 result = dns_master_rdatasettotext(name, ps, style, target);
03397 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
03398 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
03399 ADD_STRING(target, "\n");
03400 return (result);
03401 case DNS_PSEUDOSECTION_SIG0:
03402 ps = dns_message_getsig0(msg, &name);
03403 if (ps == NULL)
03404 return (ISC_R_SUCCESS);
03405 if ((flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
03406 ADD_STRING(target, ";; SIG0 PSEUDOSECTION:\n");
03407 result = dns_master_rdatasettotext(name, ps, style, target);
03408 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0 &&
03409 (flags & DNS_MESSAGETEXTFLAG_NOCOMMENTS) == 0)
03410 ADD_STRING(target, "\n");
03411 return (result);
03412 }
03413 return (ISC_R_UNEXPECTED);
03414 }
03415
03416 isc_result_t
03417 dns_message_totext(dns_message_t *msg, const dns_master_style_t *style,
03418 dns_messagetextflag_t flags, isc_buffer_t *target) {
03419 char buf[sizeof("1234567890")];
03420 isc_result_t result;
03421
03422 REQUIRE(DNS_MESSAGE_VALID(msg));
03423 REQUIRE(target != NULL);
03424
03425 if ((flags & DNS_MESSAGETEXTFLAG_NOHEADERS) == 0) {
03426 ADD_STRING(target, ";; ->>HEADER<<- opcode: ");
03427 ADD_STRING(target, opcodetext[msg->opcode]);
03428 ADD_STRING(target, ", status: ");
03429 if (msg->rcode < (sizeof(rcodetext)/sizeof(rcodetext[0]))) {
03430 ADD_STRING(target, rcodetext[msg->rcode]);
03431 } else {
03432 snprintf(buf, sizeof(buf), "%4u", msg->rcode);
03433 ADD_STRING(target, buf);
03434 }
03435 ADD_STRING(target, ", id: ");
03436 snprintf(buf, sizeof(buf), "%6u", msg->id);
03437 ADD_STRING(target, buf);
03438 ADD_STRING(target, "\n;; flags:");
03439 if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
03440 ADD_STRING(target, " qr");
03441 if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
03442 ADD_STRING(target, " aa");
03443 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
03444 ADD_STRING(target, " tc");
03445 if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
03446 ADD_STRING(target, " rd");
03447 if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
03448 ADD_STRING(target, " ra");
03449 if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
03450 ADD_STRING(target, " ad");
03451 if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
03452 ADD_STRING(target, " cd");
03453
03454
03455
03456 if ((msg->flags & 0x0040U) != 0)
03457 ADD_STRING(target, "; MBZ: 0x4");
03458 if (msg->opcode != dns_opcode_update) {
03459 ADD_STRING(target, "; QUESTION: ");
03460 } else {
03461 ADD_STRING(target, "; ZONE: ");
03462 }
03463 snprintf(buf, sizeof(buf), "%1u",
03464 msg->counts[DNS_SECTION_QUESTION]);
03465 ADD_STRING(target, buf);
03466 if (msg->opcode != dns_opcode_update) {
03467 ADD_STRING(target, ", ANSWER: ");
03468 } else {
03469 ADD_STRING(target, ", PREREQ: ");
03470 }
03471 snprintf(buf, sizeof(buf), "%1u",
03472 msg->counts[DNS_SECTION_ANSWER]);
03473 ADD_STRING(target, buf);
03474 if (msg->opcode != dns_opcode_update) {
03475 ADD_STRING(target, ", AUTHORITY: ");
03476 } else {
03477 ADD_STRING(target, ", UPDATE: ");
03478 }
03479 snprintf(buf, sizeof(buf), "%1u",
03480 msg->counts[DNS_SECTION_AUTHORITY]);
03481 ADD_STRING(target, buf);
03482 ADD_STRING(target, ", ADDITIONAL: ");
03483 snprintf(buf, sizeof(buf), "%1u",
03484 msg->counts[DNS_SECTION_ADDITIONAL]);
03485 ADD_STRING(target, buf);
03486 ADD_STRING(target, "\n");
03487 }
03488 result = dns_message_pseudosectiontotext(msg,
03489 DNS_PSEUDOSECTION_OPT,
03490 style, flags, target);
03491 if (result != ISC_R_SUCCESS)
03492 return (result);
03493
03494 result = dns_message_sectiontotext(msg, DNS_SECTION_QUESTION,
03495 style, flags, target);
03496 if (result != ISC_R_SUCCESS)
03497 return (result);
03498 result = dns_message_sectiontotext(msg, DNS_SECTION_ANSWER,
03499 style, flags, target);
03500 if (result != ISC_R_SUCCESS)
03501 return (result);
03502 result = dns_message_sectiontotext(msg, DNS_SECTION_AUTHORITY,
03503 style, flags, target);
03504 if (result != ISC_R_SUCCESS)
03505 return (result);
03506 result = dns_message_sectiontotext(msg, DNS_SECTION_ADDITIONAL,
03507 style, flags, target);
03508 if (result != ISC_R_SUCCESS)
03509 return (result);
03510
03511 result = dns_message_pseudosectiontotext(msg,
03512 DNS_PSEUDOSECTION_TSIG,
03513 style, flags, target);
03514 if (result != ISC_R_SUCCESS)
03515 return (result);
03516
03517 result = dns_message_pseudosectiontotext(msg,
03518 DNS_PSEUDOSECTION_SIG0,
03519 style, flags, target);
03520 if (result != ISC_R_SUCCESS)
03521 return (result);
03522
03523 return (ISC_R_SUCCESS);
03524 }
03525
03526 isc_region_t *
03527 dns_message_getrawmessage(dns_message_t *msg) {
03528 REQUIRE(DNS_MESSAGE_VALID(msg));
03529 return (&msg->saved);
03530 }
03531
03532 void
03533 dns_message_setsortorder(dns_message_t *msg, dns_rdatasetorderfunc_t order,
03534 const void *order_arg)
03535 {
03536 REQUIRE(DNS_MESSAGE_VALID(msg));
03537 msg->order = order;
03538 msg->order_arg = order_arg;
03539 }
03540
03541 void
03542 dns_message_settimeadjust(dns_message_t *msg, int timeadjust) {
03543 REQUIRE(DNS_MESSAGE_VALID(msg));
03544 msg->timeadjust = timeadjust;
03545 }
03546
03547 int
03548 dns_message_gettimeadjust(dns_message_t *msg) {
03549 REQUIRE(DNS_MESSAGE_VALID(msg));
03550 return (msg->timeadjust);
03551 }
03552
03553 isc_result_t
03554 dns_opcode_totext(dns_opcode_t opcode, isc_buffer_t *target) {
03555
03556 REQUIRE(opcode < 16);
03557
03558 if (isc_buffer_availablelength(target) < strlen(opcodetext[opcode]))
03559 return (ISC_R_NOSPACE);
03560 isc_buffer_putstr(target, opcodetext[opcode]);
03561 return (ISC_R_SUCCESS);
03562 }
03563
03564 void
03565 dns_message_logpacket(dns_message_t *message, const char *description,
03566 isc_logcategory_t *category, isc_logmodule_t *module,
03567 int level, isc_mem_t *mctx)
03568 {
03569 logfmtpacket(message, description, NULL, category, module,
03570 &dns_master_style_debug, level, mctx);
03571 }
03572
03573 void
03574 dns_message_logpacket2(dns_message_t *message,
03575 const char *description, isc_sockaddr_t *address,
03576 isc_logcategory_t *category, isc_logmodule_t *module,
03577 int level, isc_mem_t *mctx)
03578 {
03579 REQUIRE(address != NULL);
03580
03581 logfmtpacket(message, description, address, category, module,
03582 &dns_master_style_debug, level, mctx);
03583 }
03584
03585 void
03586 dns_message_logfmtpacket(dns_message_t *message, const char *description,
03587 isc_logcategory_t *category, isc_logmodule_t *module,
03588 const dns_master_style_t *style, int level,
03589 isc_mem_t *mctx)
03590 {
03591 logfmtpacket(message, description, NULL, category, module, style,
03592 level, mctx);
03593 }
03594
03595 void
03596 dns_message_logfmtpacket2(dns_message_t *message,
03597 const char *description, isc_sockaddr_t *address,
03598 isc_logcategory_t *category, isc_logmodule_t *module,
03599 const dns_master_style_t *style, int level,
03600 isc_mem_t *mctx)
03601 {
03602 REQUIRE(address != NULL);
03603
03604 logfmtpacket(message, description, address, category, module, style,
03605 level, mctx);
03606 }
03607
03608 static void
03609 logfmtpacket(dns_message_t *message, const char *description,
03610 isc_sockaddr_t *address, isc_logcategory_t *category,
03611 isc_logmodule_t *module, const dns_master_style_t *style,
03612 int level, isc_mem_t *mctx)
03613 {
03614 char addrbuf[ISC_SOCKADDR_FORMATSIZE] = { 0 };
03615 const char *newline = "\n";
03616 const char *space = " ";
03617 isc_buffer_t buffer;
03618 char *buf = NULL;
03619 int len = 1024;
03620 isc_result_t result;
03621
03622 if (! isc_log_wouldlog(dns_lctx, level))
03623 return;
03624
03625
03626
03627
03628
03629
03630 if (address != NULL)
03631 isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));
03632 else
03633 newline = space = "";
03634
03635 do {
03636 buf = isc_mem_get(mctx, len);
03637 if (buf == NULL)
03638 break;
03639 isc_buffer_init(&buffer, buf, len);
03640 result = dns_message_totext(message, style, 0, &buffer);
03641 if (result == ISC_R_NOSPACE) {
03642 isc_mem_put(mctx, buf, len);
03643 len += 1024;
03644 } else if (result == ISC_R_SUCCESS)
03645 isc_log_write(dns_lctx, category, module, level,
03646 "%s%s%s%s%.*s", description, space,
03647 addrbuf, newline,
03648 (int)isc_buffer_usedlength(&buffer),
03649 buf);
03650 } while (result == ISC_R_NOSPACE);
03651
03652 if (buf != NULL)
03653 isc_mem_put(mctx, buf, len);
03654 }
03655
03656 isc_result_t
03657 dns_message_buildopt(dns_message_t *message, dns_rdataset_t **rdatasetp,
03658 unsigned int version, isc_uint16_t udpsize,
03659 unsigned int flags, dns_ednsopt_t *ednsopts, size_t count)
03660 {
03661 dns_rdataset_t *rdataset = NULL;
03662 dns_rdatalist_t *rdatalist = NULL;
03663 dns_rdata_t *rdata = NULL;
03664 isc_result_t result;
03665 unsigned int len = 0, i;
03666
03667 REQUIRE(DNS_MESSAGE_VALID(message));
03668 REQUIRE(rdatasetp != NULL && *rdatasetp == NULL);
03669
03670 result = dns_message_gettemprdatalist(message, &rdatalist);
03671 if (result != ISC_R_SUCCESS)
03672 return (result);
03673 result = dns_message_gettemprdata(message, &rdata);
03674 if (result != ISC_R_SUCCESS)
03675 goto cleanup;
03676 result = dns_message_gettemprdataset(message, &rdataset);
03677 if (result != ISC_R_SUCCESS)
03678 goto cleanup;
03679 dns_rdataset_init(rdataset);
03680
03681 rdatalist->type = dns_rdatatype_opt;
03682
03683
03684
03685
03686 rdatalist->rdclass = udpsize;
03687
03688
03689
03690
03691 rdatalist->ttl = (version << 16);
03692 rdatalist->ttl |= (flags & 0xffff);
03693
03694
03695
03696
03697 if (count != 0U) {
03698 isc_buffer_t *buf = NULL;
03699 for (i = 0; i < count; i++)
03700 len += ednsopts[i].length + 4;
03701
03702 if (len > 0xffffU) {
03703 result = ISC_R_NOSPACE;
03704 goto cleanup;
03705 }
03706
03707 result = isc_buffer_allocate(message->mctx, &buf, len);
03708 if (result != ISC_R_SUCCESS)
03709 goto cleanup;
03710
03711 for (i = 0; i < count; i++) {
03712 isc_buffer_putuint16(buf, ednsopts[i].code);
03713 isc_buffer_putuint16(buf, ednsopts[i].length);
03714 isc_buffer_putmem(buf, ednsopts[i].value,
03715 ednsopts[i].length);
03716 }
03717 rdata->data = isc_buffer_base(buf);
03718 rdata->length = len;
03719 dns_message_takebuffer(message, &buf);
03720 } else {
03721 rdata->data = NULL;
03722 rdata->length = 0;
03723 }
03724
03725 rdata->rdclass = rdatalist->rdclass;
03726 rdata->type = rdatalist->type;
03727 rdata->flags = 0;
03728
03729 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
03730 result = dns_rdatalist_tordataset(rdatalist, rdataset);
03731 RUNTIME_CHECK(result == ISC_R_SUCCESS);
03732
03733 *rdatasetp = rdataset;
03734 return (ISC_R_SUCCESS);
03735
03736 cleanup:
03737 if (rdata != NULL)
03738 dns_message_puttemprdata(message, &rdata);
03739 if (rdataset != NULL)
03740 dns_message_puttemprdataset(message, &rdataset);
03741 if (rdatalist != NULL)
03742 dns_message_puttemprdatalist(message, &rdatalist);
03743 return (result);
03744 }