📄 message.c
字号:
while (rdatalist != NULL) { ISC_LIST_UNLINK(msg->freerdatalist, rdatalist, link); rdatalist = ISC_LIST_HEAD(msg->freerdatalist); } dynbuf = ISC_LIST_HEAD(msg->scratchpad); INSIST(dynbuf != NULL); if (!everything) { isc_buffer_clear(dynbuf); dynbuf = ISC_LIST_NEXT(dynbuf, link); } while (dynbuf != NULL) { next_dynbuf = ISC_LIST_NEXT(dynbuf, link); ISC_LIST_UNLINK(msg->scratchpad, dynbuf, link); isc_buffer_free(&dynbuf); dynbuf = next_dynbuf; } msgblock = ISC_LIST_HEAD(msg->rdatas); if (!everything && msgblock != NULL) { msgblock_reset(msgblock); msgblock = ISC_LIST_NEXT(msgblock, link); } while (msgblock != NULL) { next_msgblock = ISC_LIST_NEXT(msgblock, link); ISC_LIST_UNLINK(msg->rdatas, msgblock, link); msgblock_free(msg->mctx, msgblock, sizeof(dns_rdata_t)); msgblock = next_msgblock; } /* * rdatalists could be empty. */ msgblock = ISC_LIST_HEAD(msg->rdatalists); if (!everything && msgblock != NULL) { msgblock_reset(msgblock); msgblock = ISC_LIST_NEXT(msgblock, link); } while (msgblock != NULL) { next_msgblock = ISC_LIST_NEXT(msgblock, link); ISC_LIST_UNLINK(msg->rdatalists, msgblock, link); msgblock_free(msg->mctx, msgblock, sizeof(dns_rdatalist_t)); msgblock = next_msgblock; } msgblock = ISC_LIST_HEAD(msg->offsets); if (!everything && msgblock != NULL) { msgblock_reset(msgblock); msgblock = ISC_LIST_NEXT(msgblock, link); } while (msgblock != NULL) { next_msgblock = ISC_LIST_NEXT(msgblock, link); ISC_LIST_UNLINK(msg->offsets, msgblock, link); msgblock_free(msg->mctx, msgblock, sizeof(dns_offsets_t)); msgblock = next_msgblock; } if (msg->tsigkey != NULL) { dns_tsigkey_detach(&msg->tsigkey); msg->tsigkey = NULL; } if (msg->query.base != NULL) { if (msg->free_query != 0) isc_mem_put(msg->mctx, msg->query.base, msg->query.length); msg->query.base = NULL; msg->query.length = 0; } if (msg->saved.base != NULL) { if (msg->free_saved != 0) isc_mem_put(msg->mctx, msg->saved.base, msg->saved.length); msg->saved.base = NULL; msg->saved.length = 0; } /* * cleanup the buffer cleanup list */ dynbuf = ISC_LIST_HEAD(msg->cleanup); while (dynbuf != NULL) { next_dynbuf = ISC_LIST_NEXT(dynbuf, link); ISC_LIST_UNLINK(msg->cleanup, dynbuf, link); isc_buffer_free(&dynbuf); dynbuf = next_dynbuf; } /* * Set other bits to normal default values. */ if (!everything) msginit(msg); ENSURE(isc_mempool_getallocated(msg->namepool) == 0); ENSURE(isc_mempool_getallocated(msg->rdspool) == 0);}static unsigned intspacefortsig(dns_tsigkey_t *key, int otherlen) { isc_region_t r1, r2; unsigned int x; isc_result_t result; /* * The space required for an TSIG record is: * * n1 bytes for the name * 2 bytes for the type * 2 bytes for the class * 4 bytes for the ttl * 2 bytes for the rdlength * n2 bytes for the algorithm name * 6 bytes for the time signed * 2 bytes for the fudge * 2 bytes for the MAC size * x bytes for the MAC * 2 bytes for the original id * 2 bytes for the error * 2 bytes for the other data length * y bytes for the other data (at most) * --------------------------------- * 26 + n1 + n2 + x + y bytes */ dns_name_toregion(&key->name, &r1); dns_name_toregion(key->algorithm, &r2); if (key->key == NULL) x = 0; else { result = dst_key_sigsize(key->key, &x); if (result != ISC_R_SUCCESS) x = 0; } return (26 + r1.length + r2.length + x + otherlen);}isc_result_tdns_message_create(isc_mem_t *mctx, unsigned int intent, dns_message_t **msgp){ dns_message_t *m; isc_result_t result; isc_buffer_t *dynbuf; unsigned int i; REQUIRE(mctx != NULL); REQUIRE(msgp != NULL); REQUIRE(*msgp == NULL); REQUIRE(intent == DNS_MESSAGE_INTENTPARSE || intent == DNS_MESSAGE_INTENTRENDER); m = isc_mem_get(mctx, sizeof(dns_message_t)); if (m == NULL) return (ISC_R_NOMEMORY); /* * No allocations until further notice. Just initialize all lists * and other members that are freed in the cleanup phase here. */ m->magic = DNS_MESSAGE_MAGIC; m->from_to_wire = intent; msginit(m); for (i = 0; i < DNS_SECTION_MAX; i++) ISC_LIST_INIT(m->sections[i]); m->mctx = mctx; ISC_LIST_INIT(m->scratchpad); ISC_LIST_INIT(m->cleanup); m->namepool = NULL; m->rdspool = NULL; ISC_LIST_INIT(m->rdatas); ISC_LIST_INIT(m->rdatalists); ISC_LIST_INIT(m->offsets); ISC_LIST_INIT(m->freerdata); ISC_LIST_INIT(m->freerdatalist); /* * Ok, it is safe to allocate (and then "goto cleanup" if failure) */ result = isc_mempool_create(m->mctx, sizeof(dns_name_t), &m->namepool); if (result != ISC_R_SUCCESS) goto cleanup; isc_mempool_setfreemax(m->namepool, NAME_COUNT); isc_mempool_setname(m->namepool, "msg:names"); result = isc_mempool_create(m->mctx, sizeof(dns_rdataset_t), &m->rdspool); if (result != ISC_R_SUCCESS) goto cleanup; isc_mempool_setfreemax(m->rdspool, NAME_COUNT); isc_mempool_setname(m->rdspool, "msg:rdataset"); dynbuf = NULL; result = isc_buffer_allocate(mctx, &dynbuf, SCRATCHPAD_SIZE); if (result != ISC_R_SUCCESS) goto cleanup; ISC_LIST_APPEND(m->scratchpad, dynbuf, link); m->cctx = NULL; *msgp = m; return (ISC_R_SUCCESS); /* * Cleanup for error returns. */ cleanup: dynbuf = ISC_LIST_HEAD(m->scratchpad); if (dynbuf != NULL) { ISC_LIST_UNLINK(m->scratchpad, dynbuf, link); isc_buffer_free(&dynbuf); } if (m->namepool != NULL) isc_mempool_destroy(&m->namepool); if (m->rdspool != NULL) isc_mempool_destroy(&m->rdspool); m->magic = 0; isc_mem_put(mctx, m, sizeof(dns_message_t)); return (ISC_R_NOMEMORY);}voiddns_message_reset(dns_message_t *msg, unsigned int intent) { REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(intent == DNS_MESSAGE_INTENTPARSE || intent == DNS_MESSAGE_INTENTRENDER); msgreset(msg, ISC_FALSE); msg->from_to_wire = intent;}voiddns_message_destroy(dns_message_t **msgp) { dns_message_t *msg; REQUIRE(msgp != NULL); REQUIRE(DNS_MESSAGE_VALID(*msgp)); msg = *msgp; *msgp = NULL; msgreset(msg, ISC_TRUE); isc_mempool_destroy(&msg->namepool); isc_mempool_destroy(&msg->rdspool); msg->magic = 0; isc_mem_put(msg->mctx, msg, sizeof(dns_message_t));}static isc_result_tfindname(dns_name_t **foundname, dns_name_t *target, dns_namelist_t *section){ dns_name_t *curr; for (curr = ISC_LIST_TAIL(*section); curr != NULL; curr = ISC_LIST_PREV(curr, link)) { if (dns_name_equal(curr, target)) { if (foundname != NULL) *foundname = curr; return (ISC_R_SUCCESS); } } return (ISC_R_NOTFOUND);}isc_result_tdns_message_findtype(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, dns_rdataset_t **rdataset){ dns_rdataset_t *curr; if (rdataset != NULL) { REQUIRE(*rdataset == NULL); } for (curr = ISC_LIST_TAIL(name->list); curr != NULL; curr = ISC_LIST_PREV(curr, link)) { if (curr->type == type && curr->covers == covers) { if (rdataset != NULL) *rdataset = curr; return (ISC_R_SUCCESS); } } return (ISC_R_NOTFOUND);}/* * Read a name from buffer "source". */static isc_result_tgetname(dns_name_t *name, isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx){ isc_buffer_t *scratch; isc_result_t result; unsigned int tries; scratch = currentbuffer(msg); /* * First try: use current buffer. * Second try: allocate a new buffer and use that. */ tries = 0; while (tries < 2) { result = dns_name_fromwire(name, source, dctx, ISC_FALSE, scratch); if (result == ISC_R_NOSPACE) { tries++; result = newbuffer(msg, SCRATCHPAD_SIZE); if (result != ISC_R_SUCCESS) return (result); scratch = currentbuffer(msg); dns_name_reset(name); } else { return (result); } } INSIST(0); /* Cannot get here... */ return (ISC_R_UNEXPECTED);}static isc_result_tgetrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_rdataclass_t rdclass, dns_rdatatype_t rdtype, unsigned int rdatalen, dns_rdata_t *rdata){ isc_buffer_t *scratch; isc_result_t result; unsigned int tries; unsigned int trysize; scratch = currentbuffer(msg); isc_buffer_setactive(source, rdatalen); /* * First try: use current buffer. * Second try: allocate a new buffer of size * max(SCRATCHPAD_SIZE, 2 * compressed_rdatalen) * (the data will fit if it was not more than 50% compressed) * Subsequent tries: double buffer size on each try. */ tries = 0; trysize = 0; /* XXX possibly change this to a while (tries < 2) loop */ for (;;) { result = dns_rdata_fromwire(rdata, rdclass, rdtype, source, dctx, 0, scratch); if (result == ISC_R_NOSPACE) { if (tries == 0) { trysize = 2 * rdatalen; if (trysize < SCRATCHPAD_SIZE) trysize = SCRATCHPAD_SIZE; } else { INSIST(trysize != 0); if (trysize >= 65535) return (ISC_R_NOSPACE); /* XXX DNS_R_RRTOOLONG? */ trysize *= 2; } tries++; result = newbuffer(msg, trysize); if (result != ISC_R_SUCCESS) return (result); scratch = currentbuffer(msg); } else { return (result); } }}#define DO_FORMERR \ do { \ if (best_effort) \ seen_problem = ISC_TRUE; \ else { \ result = DNS_R_FORMERR; \ goto cleanup; \ } \ } while (0)static isc_result_tgetquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, unsigned int options){ isc_region_t r; unsigned int count; dns_name_t *name; dns_name_t *name2; dns_offsets_t *offsets; dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; isc_result_t result; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; dns_namelist_t *section; isc_boolean_t free_name; isc_boolean_t best_effort; isc_boolean_t seen_problem; section = &msg->sections[DNS_SECTION_QUESTION]; best_effort = ISC_TF(options & DNS_MESSAGEPARSE_BESTEFFORT); seen_problem = ISC_FALSE; name = NULL; rdataset = NULL; rdatalist = NULL; for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { name = isc_mempool_get(msg->namepool); if (name == NULL) return (ISC_R_NOMEMORY); free_name = ISC_TRUE; offsets = newoffsets(msg); if (offsets == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } dns_name_init(name, *offsets); /* * Parse the name out of this packet. */ isc_buffer_remainingregion(source, &r); isc_buffer_setactive(source, r.length); result = getname(name, source, msg, dctx); if (result != ISC_R_SUCCESS) goto cleanup; /* * Run through the section, looking to see if this name * is already there. If it is found, put back the allocated * name since we no longer need it, and set our name pointer * to point to the name we found. */ result = findname(&name2, name, section); /* * If it is the first name in the section, accept it. * * If it is not, but is not the same as the name already * in the question section, append to the section. Note that * here in the question section this is illegal, so return * FORMERR. In the future, check the opcode to see if * this should be legal or not. In either case we no longer * need this name pointer. */ if (result != ISC_R_SUCCESS) { if (!ISC_LIST_EMPTY(*section)) DO_FORMERR; ISC_LIST_APPEND(*section, name, link); free_name = ISC_FALSE; } else { isc_mempool_put(msg->namepool, name); name = name2; name2 = NULL; free_name = ISC_FALSE; } /* * Get type and class. */ isc_buffer_remainingregion(source, &r); if (r.length < 4) { result = ISC_R_UNEXPECTEDEND; goto cleanup; } rdtype = isc_buffer_getuint16(source); rdclass = isc_buffer_getuint16(source); /* * If this class is different than the one we already read, * this is an error. */ if (msg->state == DNS_SECTION_ANY) { msg->state = DNS_SECTION_QUESTION; msg->rdclass = rdclass; } else if (msg->rdclass != rdclass) DO_FORMERR; /* * Can't ask the same question twice. */ result = dns_message_findtype(name, rdtype, 0, NULL); if (result == ISC_R_SUCCESS) DO_FORMERR; /* * Allocate a new rdatalist. */ rdatalist = newrdatalist(msg); if (rdatalist == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } rdataset = isc_mempool_get(msg->rdspool); if (rdataset == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } /* * Convert rdatalist to rdataset, and attach the latter to * the name. */ rdatalist->type = rdtype; rdatalist->covers = 0; rdatalist->rdclass = rdclass; rdatalist->ttl = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -