Пример #1
0
int 
reply_info_encode(struct query_info* qinfo, struct reply_info* rep, 
	uint16_t id, uint16_t flags, sldns_buffer* buffer, time_t timenow, 
	struct regional* region, uint16_t udpsize, int dnssec)
{
	uint16_t ancount=0, nscount=0, arcount=0;
	struct compress_tree_node* tree = 0;
	int r;
	size_t rr_offset; 

	sldns_buffer_clear(buffer);
	if(udpsize < sldns_buffer_limit(buffer))
		sldns_buffer_set_limit(buffer, udpsize);
	if(sldns_buffer_remaining(buffer) < LDNS_HEADER_SIZE)
		return 0;

	sldns_buffer_write(buffer, &id, sizeof(uint16_t));
	sldns_buffer_write_u16(buffer, flags);
	sldns_buffer_write_u16(buffer, rep->qdcount);
	/* set an, ns, ar counts to zero in case of small packets */
	sldns_buffer_write(buffer, "\000\000\000\000\000\000", 6);

	/* insert query section */
	if(rep->qdcount) {
		if((r=insert_query(qinfo, &tree, buffer, region)) != 
			RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* create truncated message */
				sldns_buffer_write_u16_at(buffer, 4, 0);
				LDNS_TC_SET(sldns_buffer_begin(buffer));
				sldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
	}
	/* roundrobin offset. using query id for random number.  With ntohs
	 * for different roundrobins for sequential id client senders. */
	rr_offset = RRSET_ROUNDROBIN?ntohs(id):0;

	/* "prepend" any local alias records in the answer section if this
	 * response is supposed to be authoritative.  Currently it should
	 * be a single CNAME record (sanity-checked in worker_handle_request())
	 * but it can be extended if and when we support more variations of
	 * aliases. */
	if(qinfo->local_alias && (flags & BIT_AA)) {
		struct reply_info arep;
		time_t timezero = 0; /* to use the 'authoritative' TTL */
		memset(&arep, 0, sizeof(arep));
		arep.flags = rep->flags;
		arep.an_numrrsets = 1;
		arep.rrset_count = 1;
		arep.rrsets = &qinfo->local_alias->rrset;
		if((r=insert_section(&arep, 1, &ancount, buffer, 0,
			timezero, region, &tree, LDNS_SECTION_ANSWER,
			qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* create truncated message */
				sldns_buffer_write_u16_at(buffer, 6, ancount);
				LDNS_TC_SET(sldns_buffer_begin(buffer));
				sldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
	}

	/* insert answer section */
	if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer, 
		0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype, 
		dnssec, rr_offset)) != RETVAL_OK) {
		if(r == RETVAL_TRUNC) {
			/* create truncated message */
			sldns_buffer_write_u16_at(buffer, 6, ancount);
			LDNS_TC_SET(sldns_buffer_begin(buffer));
			sldns_buffer_flip(buffer);
			return 1;
		}
		return 0;
	}
	sldns_buffer_write_u16_at(buffer, 6, ancount);

	/* if response is positive answer, auth/add sections are not required */
	if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) {
		/* insert auth section */
		if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer, 
			rep->an_numrrsets, timenow, region, &tree,
			LDNS_SECTION_AUTHORITY, qinfo->qtype,
			dnssec, rr_offset)) != RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* create truncated message */
				sldns_buffer_write_u16_at(buffer, 8, nscount);
				LDNS_TC_SET(sldns_buffer_begin(buffer));
				sldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
		sldns_buffer_write_u16_at(buffer, 8, nscount);

		/* insert add section */
		if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer, 
			rep->an_numrrsets + rep->ns_numrrsets, timenow, region, 
			&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype, 
			dnssec, rr_offset)) != RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* no need to set TC bit, this is the additional */
				sldns_buffer_write_u16_at(buffer, 10, arcount);
				sldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
		sldns_buffer_write_u16_at(buffer, 10, arcount);
	}
	sldns_buffer_flip(buffer);
	return 1;
}
Пример #2
0
int 
reply_info_encode(struct query_info* qinfo, struct reply_info* rep, 
	uint16_t id, uint16_t flags, ldns_buffer* buffer, uint32_t timenow, 
	struct regional* region, uint16_t udpsize, int dnssec)
{
	uint16_t ancount=0, nscount=0, arcount=0;
	struct compress_tree_node* tree = 0;
	int r;
	size_t rr_offset; 

	ldns_buffer_clear(buffer);
	if(udpsize < ldns_buffer_limit(buffer))
		ldns_buffer_set_limit(buffer, udpsize);
	if(ldns_buffer_remaining(buffer) < LDNS_HEADER_SIZE)
		return 0;

	ldns_buffer_write(buffer, &id, sizeof(uint16_t));
	ldns_buffer_write_u16(buffer, flags);
	ldns_buffer_write_u16(buffer, rep->qdcount);
	/* set an, ns, ar counts to zero in case of small packets */
	ldns_buffer_write(buffer, "\000\000\000\000\000\000", 6);

	/* insert query section */
	if(rep->qdcount) {
		if((r=insert_query(qinfo, &tree, buffer, region)) != 
			RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* create truncated message */
				ldns_buffer_write_u16_at(buffer, 4, 0);
				LDNS_TC_SET(ldns_buffer_begin(buffer));
				ldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
	}
	/* roundrobin offset. using query id for random number */
	rr_offset = RRSET_ROUNDROBIN?id:0;

	/* insert answer section */
	if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer, 
		0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype, 
		dnssec, rr_offset)) != RETVAL_OK) {
		if(r == RETVAL_TRUNC) {
			/* create truncated message */
			ldns_buffer_write_u16_at(buffer, 6, ancount);
			LDNS_TC_SET(ldns_buffer_begin(buffer));
			ldns_buffer_flip(buffer);
			return 1;
		}
		return 0;
	}
	ldns_buffer_write_u16_at(buffer, 6, ancount);

	/* if response is positive answer, auth/add sections are not required */
	if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) {
		/* insert auth section */
		if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer, 
			rep->an_numrrsets, timenow, region, &tree,
			LDNS_SECTION_AUTHORITY, qinfo->qtype,
			dnssec, rr_offset)) != RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* create truncated message */
				ldns_buffer_write_u16_at(buffer, 8, nscount);
				LDNS_TC_SET(ldns_buffer_begin(buffer));
				ldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
		ldns_buffer_write_u16_at(buffer, 8, nscount);

		/* insert add section */
		if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer, 
			rep->an_numrrsets + rep->ns_numrrsets, timenow, region, 
			&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype, 
			dnssec, rr_offset)) != RETVAL_OK) {
			if(r == RETVAL_TRUNC) {
				/* no need to set TC bit, this is the additional */
				ldns_buffer_write_u16_at(buffer, 10, arcount);
				ldns_buffer_flip(buffer);
				return 1;
			}
			return 0;
		}
		ldns_buffer_write_u16_at(buffer, 10, arcount);
	} else {
		ldns_buffer_write_u16_at(buffer, 8, nscount);
		ldns_buffer_write_u16_at(buffer, 10, arcount);
	}
	ldns_buffer_flip(buffer);
	return 1;
}