📄 message.c
字号:
DNS_LOGMODULE_MESSAGE, ISC_LOG_DEBUG(3), "message has %u byte(s) of trailing garbage", r.length); } truncated: if ((options & DNS_MESSAGEPARSE_CLONEBUFFER) == 0) isc_buffer_usedregion(&origsource, &msg->saved); else { msg->saved.length = isc_buffer_usedlength(&origsource); msg->saved.base = isc_mem_get(msg->mctx, msg->saved.length); if (msg->saved.base == NULL) return (ISC_R_NOMEMORY); memcpy(msg->saved.base, isc_buffer_base(&origsource), msg->saved.length); msg->free_saved = 1; } if (ret == ISC_R_UNEXPECTEDEND && ignore_tc) return (DNS_R_RECOVERABLE); if (seen_problem == ISC_TRUE) return (DNS_R_RECOVERABLE); return (ISC_R_SUCCESS);}isc_result_tdns_message_renderbegin(dns_message_t *msg, dns_compress_t *cctx, isc_buffer_t *buffer){ isc_region_t r; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(buffer != NULL); REQUIRE(msg->buffer == NULL); REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); msg->cctx = cctx; /* * Erase the contents of this buffer. */ isc_buffer_clear(buffer); /* * Make certain there is enough for at least the header in this * buffer. */ isc_buffer_availableregion(buffer, &r); if (r.length < DNS_MESSAGE_HEADERLEN) return (ISC_R_NOSPACE); if (r.length < msg->reserved) return (ISC_R_NOSPACE); /* * Reserve enough space for the header in this buffer. */ isc_buffer_add(buffer, DNS_MESSAGE_HEADERLEN); msg->buffer = buffer; return (ISC_R_SUCCESS);}isc_result_tdns_message_renderchangebuffer(dns_message_t *msg, isc_buffer_t *buffer) { isc_region_t r, rn; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(buffer != NULL); REQUIRE(msg->buffer != NULL); /* * Ensure that the new buffer is empty, and has enough space to * hold the current contents. */ isc_buffer_clear(buffer); isc_buffer_availableregion(buffer, &rn); isc_buffer_usedregion(msg->buffer, &r); REQUIRE(rn.length > r.length); /* * Copy the contents from the old to the new buffer. */ isc_buffer_add(buffer, r.length); memcpy(rn.base, r.base, r.length); msg->buffer = buffer; return (ISC_R_SUCCESS);}voiddns_message_renderrelease(dns_message_t *msg, unsigned int space) { REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(space <= msg->reserved); msg->reserved -= space;}isc_result_tdns_message_renderreserve(dns_message_t *msg, unsigned int space) { isc_region_t r; REQUIRE(DNS_MESSAGE_VALID(msg)); if (msg->buffer != NULL) { isc_buffer_availableregion(msg->buffer, &r); if (r.length < (space + msg->reserved)) return (ISC_R_NOSPACE); } msg->reserved += space; return (ISC_R_SUCCESS);}static inline isc_boolean_twrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { int pass_needed; /* * If we are not rendering class IN, this ordering is bogus. */ if (rds->rdclass != dns_rdataclass_in) return (ISC_FALSE); switch (rds->type) { case dns_rdatatype_a: case dns_rdatatype_aaaa: if (preferred_glue == rds->type) pass_needed = 4; else pass_needed = 3; break; case dns_rdatatype_rrsig: case dns_rdatatype_dnskey: pass_needed = 2; break; default: pass_needed = 1; } if (pass_needed >= pass) return (ISC_FALSE); return (ISC_TRUE);}isc_result_tdns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, unsigned int options){ dns_namelist_t *section; dns_name_t *name, *next_name; dns_rdataset_t *rdataset, *next_rdataset; unsigned int count, total; isc_result_t result; isc_buffer_t st; /* for rollbacks */ int pass; isc_boolean_t partial = ISC_FALSE; unsigned int rd_options; dns_rdatatype_t preferred_glue = 0; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(msg->buffer != NULL); REQUIRE(VALID_NAMED_SECTION(sectionid)); section = &msg->sections[sectionid]; if ((sectionid == DNS_SECTION_ADDITIONAL) && (options & DNS_MESSAGERENDER_ORDERED) == 0) { if ((options & DNS_MESSAGERENDER_PREFER_A) != 0) { preferred_glue = dns_rdatatype_a; pass = 4; } else if ((options & DNS_MESSAGERENDER_PREFER_AAAA) != 0) { preferred_glue = dns_rdatatype_aaaa; pass = 4; } else pass = 3; } else pass = 1; if ((options & DNS_MESSAGERENDER_OMITDNSSEC) == 0) rd_options = 0; else rd_options = DNS_RDATASETTOWIRE_OMITDNSSEC; /* * Shrink the space in the buffer by the reserved amount. */ msg->buffer->length -= msg->reserved; total = 0; if (msg->reserved == 0 && (options & DNS_MESSAGERENDER_PARTIAL) != 0) partial = ISC_TRUE; do { name = ISC_LIST_HEAD(*section); if (name == NULL) { msg->buffer->length += msg->reserved; msg->counts[sectionid] += total; return (ISC_R_SUCCESS); } while (name != NULL) { next_name = ISC_LIST_NEXT(name, link); rdataset = ISC_LIST_HEAD(name->list); while (rdataset != NULL) { next_rdataset = ISC_LIST_NEXT(rdataset, link); if ((rdataset->attributes & DNS_RDATASETATTR_RENDERED) != 0) goto next; if (((options & DNS_MESSAGERENDER_ORDERED) == 0) && (sectionid == DNS_SECTION_ADDITIONAL) && wrong_priority(rdataset, pass, preferred_glue)) goto next; st = *(msg->buffer); count = 0; if (partial) result = dns_rdataset_towirepartial( rdataset, name, msg->cctx, msg->buffer, msg->order, msg->order_arg, rd_options, &count, NULL); else result = dns_rdataset_towiresorted( rdataset, name, msg->cctx, msg->buffer, msg->order, msg->order_arg, rd_options, &count); total += count; /* * If out of space, record stats on what we * rendered so far, and return that status. * * XXXMLG Need to change this when * dns_rdataset_towire() can render partial * sets starting at some arbitary point in the * set. This will include setting a bit in the * rdataset to indicate that a partial * rendering was done, and some state saved * somewhere (probably in the message struct) * to indicate where to continue from. */ if (partial && result == ISC_R_NOSPACE) { msg->buffer->length += msg->reserved; msg->counts[sectionid] += total; return (result); } if (result != ISC_R_SUCCESS) { INSIST(st.used < 65536); dns_compress_rollback(msg->cctx, (isc_uint16_t)st.used); *(msg->buffer) = st; /* rollback */ msg->buffer->length += msg->reserved; msg->counts[sectionid] += total; return (result); } /* * If we have rendered non-validated data, * ensure that the AD bit is not set. */ if (rdataset->trust != dns_trust_secure && (sectionid == DNS_SECTION_ANSWER || sectionid == DNS_SECTION_AUTHORITY)) msg->flags &= ~DNS_MESSAGEFLAG_AD; rdataset->attributes |= DNS_RDATASETATTR_RENDERED; next: rdataset = next_rdataset; } name = next_name; } } while (--pass != 0); msg->buffer->length += msg->reserved; msg->counts[sectionid] += total; return (ISC_R_SUCCESS);}voiddns_message_renderheader(dns_message_t *msg, isc_buffer_t *target) { isc_uint16_t tmp; isc_region_t r; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(target != NULL); isc_buffer_availableregion(target, &r); REQUIRE(r.length >= DNS_MESSAGE_HEADERLEN); isc_buffer_putuint16(target, msg->id); tmp = ((msg->opcode << DNS_MESSAGE_OPCODE_SHIFT) & DNS_MESSAGE_OPCODE_MASK); tmp |= (msg->rcode & DNS_MESSAGE_RCODE_MASK); tmp |= (msg->flags & DNS_MESSAGE_FLAG_MASK); INSIST(msg->counts[DNS_SECTION_QUESTION] < 65536 && msg->counts[DNS_SECTION_ANSWER] < 65536 && msg->counts[DNS_SECTION_AUTHORITY] < 65536 && msg->counts[DNS_SECTION_ADDITIONAL] < 65536); isc_buffer_putuint16(target, tmp); isc_buffer_putuint16(target, (isc_uint16_t)msg->counts[DNS_SECTION_QUESTION]); isc_buffer_putuint16(target, (isc_uint16_t)msg->counts[DNS_SECTION_ANSWER]); isc_buffer_putuint16(target, (isc_uint16_t)msg->counts[DNS_SECTION_AUTHORITY]); isc_buffer_putuint16(target, (isc_uint16_t)msg->counts[DNS_SECTION_ADDITIONAL]);}isc_result_tdns_message_renderend(dns_message_t *msg) { isc_buffer_t tmpbuf; isc_region_t r; int result; unsigned int count; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(msg->buffer != NULL); if ((msg->rcode & ~DNS_MESSAGE_RCODE_MASK) != 0 && msg->opt == NULL) { /* * We have an extended rcode but are not using EDNS. */ return (DNS_R_FORMERR); } /* * If we've got an OPT record, render it. */ if (msg->opt != NULL) { dns_message_renderrelease(msg, msg->opt_reserved); msg->opt_reserved = 0; /* * Set the extended rcode. */ msg->opt->ttl &= ~DNS_MESSAGE_EDNSRCODE_MASK; msg->opt->ttl |= ((msg->rcode << 20) & DNS_MESSAGE_EDNSRCODE_MASK); /* * Render. */ count = 0; result = dns_rdataset_towire(msg->opt, dns_rootname, msg->cctx, msg->buffer, 0, &count); msg->counts[DNS_SECTION_ADDITIONAL] += count; if (result != ISC_R_SUCCESS) return (result); } /* * If we're adding a TSIG or SIG(0) to a truncated message, * clear all rdatasets from the message except for the question * before adding the TSIG or SIG(0). If the question doesn't fit, * don't include it. */ if ((msg->tsigkey != NULL || msg->sig0key != NULL) && (msg->flags & DNS_MESSAGEFLAG_TC) != 0) { isc_buffer_t *buf; msgresetnames(msg, DNS_SECTION_ANSWER); buf = msg->buffer; dns_message_renderreset(msg); msg->buffer = buf; isc_buffer_clear(msg->buffer); isc_buffer_add(msg->buffer, DNS_MESSAGE_HEADERLEN); dns_compress_rollback(msg->cctx, 0); result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0); if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) return (result); } /* * If we're adding a TSIG record, generate and render it. */ if (msg->tsigkey != NULL) { dns_message_renderrelease(msg, msg->sig_reserved); msg->sig_reserved = 0; result = dns_tsig_sign(msg); if (result != ISC_R_SUCCESS) return (result); count = 0; result = dns_rdataset_towire(msg->tsig, msg->tsigname, msg->cctx, msg->buffer, 0, &count); msg->counts[DNS_SECTION_ADDITIONAL] += count; if (result != ISC_R_SUCCESS) return (result); } /* * If we're adding a SIG(0) record, generate and render it. */ if (msg->sig0key != NULL) { dns_message_renderrelease(msg, msg->sig_reserved); msg->sig_reserved = 0; result = dns_dnssec_signmessage(msg, msg->sig0key); if (result != ISC_R_SUCCESS) return (result); count = 0; /* * Note: dns_rootname is used here, not msg->sig0name, since * the owner name of a SIG(0) is irrelevant, and will not * be set in a message being rendered. */ result = dns_rdataset_towire(msg->sig0, dns_rootname, msg->cctx, msg->buffer, 0, &count); msg->counts[DNS_SECTION_ADDITIONAL] += count; if (result != ISC_R_SUCCESS) return (result); } isc_buffer_usedregion(msg->buffer, &r); isc_buffer_init(&tmpbuf, r.base, r.length); dns_message_renderheader(msg, &tmpbuf); msg->buffer = NULL; /* forget about this buffer only on success XXX */ return (ISC_R_SUCCESS);}voiddns_message_renderreset(dns_message_t *msg) { unsigned int i; dns_name_t *name; dns_rdataset_t *rds; /* * Reset the message so that it may be rendered again. */ REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); msg->buffer = NULL; for (i = 0; i < DNS_SECTION_MAX; i++) { msg->cursors[i] = NULL; msg->counts[i] = 0; for (name = ISC_LIST_HEAD(msg->sections[i]); name != NULL; name = ISC_LIST_NEXT(name, link)) { for (rds = ISC_LIST_HEAD(name->list); rds != NULL; rds = ISC_LIST_NEXT(rds, link)) { rds->attributes &= ~DNS_RDATASETATTR_RENDERED; } } } if (msg->tsigname != NULL) dns_message_puttempname(msg, &msg->tsigname); if (msg->tsig != NULL) { dns_rdataset_disassociate(msg->tsig); dns_message_puttemprdataset(msg, &msg->tsig); } if (msg->sig0 != NULL) { dns_rdataset_disassociate(msg->sig0); dns_message_puttemprdataset(msg, &msg->sig0); }}isc_result_tdns_message_firstname(dns_message_t *msg, dns_section_t section) { REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(VALID_NAMED_SECTION(section)); msg->cursors[section] = ISC_LIST_HEAD(msg->sections[section]); if (msg->cursors[section] == NULL) return (ISC_R_NOMORE); return (ISC_R_SUCCESS);}isc_result_tdns_message_nextname(dns_message_t *msg, dns_section_t section) { REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(VALID_NAMED_SECTION(section)); REQUIRE(msg->cursors[section] != NULL); msg->cursors[section] = ISC_LIST_NEXT(msg->cursors[section], link); if (msg->cursors[section] == NULL) return (ISC_R_NOMORE); return (ISC_R_SUCCESS);}voiddns_message_currentname(dns_message_t *msg, dns_section_t section, dns_name_t **name){ REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(VALID_NAMED_SECTION(section)); REQUIRE(name != NULL && *name == NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -