예제 #1
0
/*
 * Load test data into the RBT.
 */
static void
add_test_data(isc_mem_t *mymctx, dns_rbt_t *rbt) {
	char buffer[1024];
	isc_buffer_t b;
	isc_result_t result;
	dns_fixedname_t fname;
	dns_name_t *name;
	dns_compress_t cctx;
	rbt_testdata_t *testdatap = testdata;

	dns_compress_init(&cctx, -1, mymctx);

	while (testdatap->name != NULL && testdatap->data.data != NULL) {
		memmove(buffer, testdatap->name, testdatap->name_len);

		isc_buffer_init(&b, buffer, testdatap->name_len);
		isc_buffer_add(&b, testdatap->name_len);
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
		result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			testdatap++;
			continue;
		}

		if (name != NULL) {
			result = dns_rbt_addname(rbt, name, &testdatap->data);
			ATF_CHECK_STREQ(dns_result_totext(result), "success");
		}
		testdatap++;
	}

	dns_compress_invalidate(&cctx);
}
예제 #2
0
/*
 * Arrange to send as much as we can of "stream" without blocking.
 *
 * Requires:
 *	The stream iterator is initialized and points at an RR,
 *      or possibly at the end of the stream (that is, the
 *      _first method of the iterator has been called).
 */
static void
sendstream(xfrout_ctx_t *xfr) {
	dns_message_t *tcpmsg = NULL;
	dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
	isc_result_t result;
	isc_region_t used;
	isc_region_t region;
	dns_rdataset_t *qrdataset;
	dns_name_t *msgname = NULL;
	dns_rdata_t *msgrdata = NULL;
	dns_rdatalist_t *msgrdl = NULL;
	dns_rdataset_t *msgrds = NULL;
	dns_compress_t cctx;
	isc_boolean_t cleanup_cctx = ISC_FALSE;
	isc_boolean_t is_tcp;

	int n_rrs;

	isc_buffer_clear(&xfr->buf);
	isc_buffer_clear(&xfr->txlenbuf);
	isc_buffer_clear(&xfr->txbuf);

	is_tcp = ISC_TF((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0);
	if (!is_tcp) {
		/*
		 * In the UDP case, we put the response data directly into
		 * the client message.
		 */
		msg = xfr->client->message;
		CHECK(dns_message_reply(msg, ISC_TRUE));
	} else {
		/*
		 * TCP. Build a response dns_message_t, temporarily storing
		 * the raw, uncompressed owner names and RR data contiguously
		 * in xfr->buf.  We know that if the uncompressed data fits
		 * in xfr->buf, the compressed data will surely fit in a TCP
		 * message.
		 */

		CHECK(dns_message_create(xfr->mctx,
					 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
		msg = tcpmsg;

		msg->id = xfr->id;
		msg->rcode = dns_rcode_noerror;
		msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
		if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
			msg->flags |= DNS_MESSAGEFLAG_RA;
		CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
		CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
		if (xfr->lasttsig != NULL)
			isc_buffer_free(&xfr->lasttsig);

		/*
		 * Add a EDNS option to the message?
		 */
		if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
			dns_rdataset_t *opt = NULL;

			CHECK(ns_client_addopt(xfr->client, msg, &opt));
			CHECK(dns_message_setopt(msg, opt));
			/*
			 * Add to first message only.
			 */
			xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
			xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
		}

		/*
		 * Account for reserved space.
		 */
		if (xfr->tsigkey != NULL)
			INSIST(msg->reserved != 0U);
		isc_buffer_add(&xfr->buf, msg->reserved);

		/*
		 * Include a question section in the first message only.
		 * BIND 8.2.1 will not recognize an IXFR if it does not
		 * have a question section.
		 */
		if (xfr->nmsg == 0) {
			dns_name_t *qname = NULL;
			isc_region_t r;

			/*
			 * Reserve space for the 12-byte message header
			 * and 4 bytes of question.
			 */
			isc_buffer_add(&xfr->buf, 12 + 4);

			qrdataset = NULL;
			result = dns_message_gettemprdataset(msg, &qrdataset);
			if (result != ISC_R_SUCCESS)
				goto failure;
			dns_rdataset_makequestion(qrdataset,
					xfr->client->message->rdclass,
					xfr->qtype);

			result = dns_message_gettempname(msg, &qname);
			if (result != ISC_R_SUCCESS)
				goto failure;
			dns_name_init(qname, NULL);
			isc_buffer_availableregion(&xfr->buf, &r);
			INSIST(r.length >= xfr->qname->length);
			r.length = xfr->qname->length;
			isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
					  xfr->qname->length);
			dns_name_fromregion(qname, &r);
			ISC_LIST_INIT(qname->list);
			ISC_LIST_APPEND(qname->list, qrdataset, link);

			dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
		} else {
			/*
			 * Reserve space for the 12-byte message header
			 */
			isc_buffer_add(&xfr->buf, 12);
			msg->tcp_continuation = 1;
		}
	}

	/*
	 * Try to fit in as many RRs as possible, unless "one-answer"
	 * format has been requested.
	 */
	for (n_rrs = 0; ; n_rrs++) {
		dns_name_t *name = NULL;
		isc_uint32_t ttl;
		dns_rdata_t *rdata = NULL;

		unsigned int size;
		isc_region_t r;

		msgname = NULL;
		msgrdata = NULL;
		msgrdl = NULL;
		msgrds = NULL;

		xfr->stream->methods->current(xfr->stream,
					      &name, &ttl, &rdata);
		size = name->length + 10 + rdata->length;
		isc_buffer_availableregion(&xfr->buf, &r);
		if (size >= r.length) {
			/*
			 * RR would not fit.  If there are other RRs in the
			 * buffer, send them now and leave this RR to the
			 * next message.  If this RR overflows the buffer
			 * all by itself, fail.
			 *
			 * In theory some RRs might fit in a TCP message
			 * when compressed even if they do not fit when
			 * uncompressed, but surely we don't want
			 * to send such monstrosities to an unsuspecting
			 * slave.
			 */
			if (n_rrs == 0) {
				xfrout_log(xfr, ISC_LOG_WARNING,
					   "RR too large for zone transfer "
					   "(%d bytes)", size);
				/* XXX DNS_R_RRTOOLARGE? */
				result = ISC_R_NOSPACE;
				goto failure;
			}
			break;
		}

		if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
			log_rr(name, rdata, ttl); /* XXX */

		result = dns_message_gettempname(msg, &msgname);
		if (result != ISC_R_SUCCESS)
			goto failure;
		dns_name_init(msgname, NULL);
		isc_buffer_availableregion(&xfr->buf, &r);
		INSIST(r.length >= name->length);
		r.length = name->length;
		isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
		dns_name_fromregion(msgname, &r);

		/* Reserve space for RR header. */
		isc_buffer_add(&xfr->buf, 10);

		result = dns_message_gettemprdata(msg, &msgrdata);
		if (result != ISC_R_SUCCESS)
			goto failure;
		isc_buffer_availableregion(&xfr->buf, &r);
		r.length = rdata->length;
		isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
		dns_rdata_init(msgrdata);
		dns_rdata_fromregion(msgrdata,
				     rdata->rdclass, rdata->type, &r);

		result = dns_message_gettemprdatalist(msg, &msgrdl);
		if (result != ISC_R_SUCCESS)
			goto failure;
		msgrdl->type = rdata->type;
		msgrdl->rdclass = rdata->rdclass;
		msgrdl->ttl = ttl;
		if (rdata->type == dns_rdatatype_sig ||
		    rdata->type == dns_rdatatype_rrsig)
			msgrdl->covers = dns_rdata_covers(rdata);
		else
			msgrdl->covers = dns_rdatatype_none;
		ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);

		result = dns_message_gettemprdataset(msg, &msgrds);
		if (result != ISC_R_SUCCESS)
			goto failure;
		result = dns_rdatalist_tordataset(msgrdl, msgrds);
		INSIST(result == ISC_R_SUCCESS);

		ISC_LIST_APPEND(msgname->list, msgrds, link);

		dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
		msgname = NULL;

		result = xfr->stream->methods->next(xfr->stream);
		if (result == ISC_R_NOMORE) {
			xfr->end_of_stream = ISC_TRUE;
			break;
		}
		CHECK(result);

		if (! xfr->many_answers)
			break;
		/*
		 * At this stage, at least 1 RR has been rendered into
		 * the message. Check if we want to clamp this message
		 * here (TCP only). 20480 was set as an upper limit to
		 * improve message compression.
		 */
		if ((isc_buffer_usedlength(&xfr->buf) >= 20480) && is_tcp)
			break;
	}

	if (is_tcp) {
		CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
		dns_compress_setsensitive(&cctx, ISC_TRUE);
		cleanup_cctx = ISC_TRUE;
		CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
		CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
		CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
		CHECK(dns_message_renderend(msg));
		dns_compress_invalidate(&cctx);
		cleanup_cctx = ISC_FALSE;

		isc_buffer_usedregion(&xfr->txbuf, &used);
		isc_buffer_putuint16(&xfr->txlenbuf,
				     (isc_uint16_t)used.length);
		region.base = xfr->txlenbuf.base;
		region.length = 2 + used.length;
		xfrout_log(xfr, ISC_LOG_DEBUG(8),
			   "sending TCP message of %d bytes",
			   used.length);
		CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
				      &region, xfr->client->task,
				      xfrout_senddone,
				      xfr));
		xfr->sends++;
	} else {
		xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
		ns_client_send(xfr->client);
		xfr->stream->methods->pause(xfr->stream);
		xfrout_ctx_destroy(&xfr);
		return;
	}

	/* Advance lasttsig to be the last TSIG generated */
	CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));

	xfr->nmsg++;

 failure:
	if (msgname != NULL) {
		if (msgrds != NULL) {
			if (dns_rdataset_isassociated(msgrds))
				dns_rdataset_disassociate(msgrds);
			dns_message_puttemprdataset(msg, &msgrds);
		}
		if (msgrdl != NULL) {
			ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
			dns_message_puttemprdatalist(msg, &msgrdl);
		}
		if (msgrdata != NULL)
			dns_message_puttemprdata(msg, &msgrdata);
		dns_message_puttempname(msg, &msgname);
	}

	if (tcpmsg != NULL)
		dns_message_destroy(&tcpmsg);

	if (cleanup_cctx)
		dns_compress_invalidate(&cctx);
	/*
	 * Make sure to release any locks held by database
	 * iterators before returning from the event handler.
	 */
	xfr->stream->methods->pause(xfr->stream);

	if (result == ISC_R_SUCCESS)
		return;

	xfrout_fail(xfr, result, "sending zone data");
}
예제 #3
0
static void
buildquery(void) {
	isc_result_t result;
	dns_rdataset_t *question = NULL;
	dns_name_t *qname = NULL;
	isc_region_t r, inr;
	dns_message_t *query;
	char nametext[] = "host.example";
	isc_buffer_t namesrc, namedst;
	unsigned char namedata[256];
	isc_sockaddr_t sa;
	dns_compress_t cctx;

	query = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &query);
	CHECK("dns_message_create", result);
	result = dns_message_setsig0key(query, key);
	CHECK("dns_message_setsig0key", result);

	result = dns_message_gettemprdataset(query, &question);
	CHECK("dns_message_gettemprdataset", result);
	dns_rdataset_init(question);
	dns_rdataset_makequestion(question, dns_rdataclass_in,
				  dns_rdatatype_a);
	result = dns_message_gettempname(query, &qname);
	CHECK("dns_message_gettempname", result);
	isc_buffer_init(&namesrc, nametext, strlen(nametext));
	isc_buffer_add(&namesrc, strlen(nametext));
	isc_buffer_init(&namedst, namedata, sizeof(namedata));
	dns_name_init(qname, NULL);
	result = dns_name_fromtext(qname, &namesrc, dns_rootname, ISC_FALSE,
				   &namedst);
	CHECK("dns_name_fromtext", result);
	ISC_LIST_APPEND(qname->list, question, link);
	dns_message_addname(query, qname, DNS_SECTION_QUESTION);

	isc_buffer_init(&qbuffer, qdata, sizeof(qdata));

	result = dns_compress_init(&cctx, -1, mctx);
	CHECK("dns_compress_init", result);
	result = dns_message_renderbegin(query, &cctx, &qbuffer);
	CHECK("dns_message_renderbegin", result);
	result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0);
	CHECK("dns_message_rendersection(question)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0);
	CHECK("dns_message_rendersection(answer)", result);
	result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0);
	CHECK("dns_message_rendersection(auth)", result);
	result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0);
	CHECK("dns_message_rendersection(add)", result);
	result = dns_message_renderend(query);
	CHECK("dns_message_renderend", result);
	dns_compress_invalidate(&cctx);

	isc_buffer_init(&outbuf, output, sizeof(output));
	result = dns_message_totext(query, style, 0, &outbuf);
	CHECK("dns_message_totext", result);
	printf("%.*s\n", (int)isc_buffer_usedlength(&outbuf),
	       (char *)isc_buffer_base(&outbuf));

	isc_buffer_usedregion(&qbuffer, &r);
	isc_sockaddr_any(&sa);
	result = isc_socket_bind(s, &sa);
	CHECK("isc_socket_bind", result);
	result = isc_socket_sendto(s, &r, task1, senddone, NULL, &address,
				   NULL);
	CHECK("isc_socket_sendto", result);

	inr.base = rdata;
	inr.length = sizeof(rdata);
	result = isc_socket_recv(s, &inr, 1, task1, recvdone, NULL);
	CHECK("isc_socket_recv", result);
	dns_message_destroy(&query);
}
예제 #4
0
static void
process_message(isc_buffer_t *source) {
	dns_message_t *message;
	isc_result_t result;
	int i;

	message = NULL;
	result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &message);
	CHECKRESULT(result, "dns_message_create failed");

	result = dns_message_parse(message, source, parseflags);
	if (result == DNS_R_RECOVERABLE)
		result = ISC_R_SUCCESS;
	CHECKRESULT(result, "dns_message_parse failed");

	result = printmessage(message);
	CHECKRESULT(result, "printmessage() failed");

	if (printmemstats)
		isc_mem_stats(mctx, stdout);

	if (dorender) {
		unsigned char b2[64 * 1024];
		isc_buffer_t buffer;
		dns_compress_t cctx;

		isc_buffer_init(&buffer, b2, sizeof(b2));

		/*
		 * XXXMLG
		 * Changing this here is a hack, and should not be done in
		 * reasonable application code, ever.
	 	*/
		message->from_to_wire = DNS_MESSAGE_INTENTRENDER;

 		for (i = 0; i < DNS_SECTION_MAX; i++)
			message->counts[i] = 0;  /* Another hack XXX */

		result = dns_compress_init(&cctx, -1, mctx);
		CHECKRESULT(result, "dns_compress_init() failed");

		result = dns_message_renderbegin(message, &cctx, &buffer);
		CHECKRESULT(result, "dns_message_renderbegin() failed");

		result = dns_message_rendersection(message,
						   DNS_SECTION_QUESTION, 0);
		CHECKRESULT(result,
			    "dns_message_rendersection(QUESTION) failed");

		result = dns_message_rendersection(message,
						   DNS_SECTION_ANSWER, 0);
		CHECKRESULT(result,
			    "dns_message_rendersection(ANSWER) failed");

		result = dns_message_rendersection(message,
						   DNS_SECTION_AUTHORITY, 0);
		CHECKRESULT(result,
			    "dns_message_rendersection(AUTHORITY) failed");

		result = dns_message_rendersection(message,
						   DNS_SECTION_ADDITIONAL, 0);
		CHECKRESULT(result,
			    "dns_message_rendersection(ADDITIONAL) failed");

		dns_message_renderend(message);

		dns_compress_invalidate(&cctx);

		message->from_to_wire = DNS_MESSAGE_INTENTPARSE;
		dns_message_destroy(&message);

		printf("Message rendered.\n");
		if (printmemstats)
			isc_mem_stats(mctx, stdout);

		result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
					    &message);
		CHECKRESULT(result, "dns_message_create failed");

		result = dns_message_parse(message, &buffer, parseflags);
		CHECKRESULT(result, "dns_message_parse failed");

		result = printmessage(message);
		CHECKRESULT(result, "printmessage() failed");
	}
	dns_message_destroy(&message);
}
예제 #5
0
static isc_result_t
add_tsig(dst_context_t *tsigctx, dns_tsigkey_t *key, isc_buffer_t *target) {
	dns_compress_t cctx;
	dns_rdata_any_tsig_t tsig;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	dns_rdatalist_t rdatalist;
	dns_rdataset_t rdataset;
	isc_buffer_t *dynbuf = NULL;
	isc_buffer_t databuf;
	isc_buffer_t sigbuf;
	isc_region_t r;
	isc_result_t result = ISC_R_SUCCESS;
	isc_stdtime_t now;
	unsigned char tsigbuf[1024];
	unsigned int count;
	unsigned int sigsize;
	isc_boolean_t invalidate_ctx = ISC_FALSE;

	CHECK(dns_compress_init(&cctx, -1, mctx));
	invalidate_ctx = ISC_TRUE;

	memset(&tsig, 0, sizeof(tsig));
	       tsig.common.rdclass = dns_rdataclass_any;
	tsig.common.rdtype = dns_rdatatype_tsig;
	ISC_LINK_INIT(&tsig.common, link);
	dns_name_init(&tsig.algorithm, NULL);
	dns_name_clone(key->algorithm, &tsig.algorithm);

	isc_stdtime_get(&now);
	tsig.timesigned = now;
	tsig.fudge = DNS_TSIG_FUDGE;
	tsig.originalid = 50;
	tsig.error = dns_rcode_noerror;
	tsig.otherlen = 0;
	tsig.other = NULL;

	isc_buffer_init(&databuf, tsigbuf, sizeof(tsigbuf));
	isc_buffer_putuint48(&databuf, tsig.timesigned);
	isc_buffer_putuint16(&databuf, tsig.fudge);
	isc_buffer_usedregion(&databuf, &r);
	CHECK(dst_context_adddata(tsigctx, &r));

	CHECK(dst_key_sigsize(key->key, &sigsize));
	tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize);
	if (tsig.signature == NULL)
		CHECK(ISC_R_NOMEMORY);
	isc_buffer_init(&sigbuf, tsig.signature, sigsize);
	CHECK(dst_context_sign(tsigctx, &sigbuf));
	tsig.siglen = isc_buffer_usedlength(&sigbuf);

	CHECK(isc_buffer_allocate(mctx, &dynbuf, 512));
	CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_any,
				   dns_rdatatype_tsig, &tsig, dynbuf));
	dns_rdatalist_init(&rdatalist);
	rdatalist.rdclass = dns_rdataclass_any;
	rdatalist.type = dns_rdatatype_tsig;
	ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
	dns_rdataset_init(&rdataset);
	CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset));
	CHECK(dns_rdataset_towire(&rdataset, &key->name, &cctx,
				  target, 0, &count));

	/*
	 * Fixup additional record count.
	 */
	((unsigned char*)target->base)[11]++;
	if (((unsigned char*)target->base)[11] == 0)
		((unsigned char*)target->base)[10]++;
 cleanup:
	if (tsig.signature != NULL)
		isc_mem_put(mctx, tsig.signature, sigsize);
	if (dynbuf != NULL)
		isc_buffer_free(&dynbuf);
	if (invalidate_ctx)
		dns_compress_invalidate(&cctx);

	return (result);
}
예제 #6
0
static void
render(isc_buffer_t *buf, unsigned flags, dns_tsigkey_t *key,
       isc_buffer_t **tsigin, isc_buffer_t **tsigout,
       dst_context_t *tsigctx)
{
	dns_message_t *msg = NULL;
	dns_compress_t cctx;
	isc_result_t result;

	result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &msg);
	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
			 "dns_message_create: %s",
			 dns_result_totext(result));

	msg->id = 50;
	msg->rcode = dns_rcode_noerror;
	msg->flags = flags;

	if (tsigin == tsigout)
		msg->tcp_continuation = 1;

	if (tsigctx == NULL) {
		result = dns_message_settsigkey(msg, key);
		ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
				 "dns_message_settsigkey: %s",
				 dns_result_totext(result));

		result = dns_message_setquerytsig(msg, *tsigin);
		ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
				 "dns_message_setquerytsig: %s",
				 dns_result_totext(result));
	}

	result = dns_compress_init(&cctx, -1, mctx);
	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
			 "dns_compress_init: %s",
			 dns_result_totext(result));

	result = dns_message_renderbegin(msg, &cctx, buf);
	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
			 "dns_message_renderbegin: %s",
			 dns_result_totext(result));

	result = dns_message_renderend(msg);
	ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
			 "dns_message_renderend: %s",
			 dns_result_totext(result));

	if (tsigctx != NULL) {
		isc_region_t r;

		isc_buffer_usedregion(buf, &r);
		result = dst_context_adddata(tsigctx, &r);
	} else {
		if (tsigin == tsigout && *tsigin != NULL)
			isc_buffer_free(tsigin);

		result = dns_message_getquerytsig(msg, mctx, tsigout);
		ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS,
				 "dns_message_getquerytsig: %s",
				 dns_result_totext(result));
	}

	dns_compress_invalidate(&cctx);
	dns_message_destroy(&msg);
}
예제 #7
0
ATF_TC_BODY(send, tc) {
	isc_result_t result;
	dns_dtenv_t *dtenv = NULL;
	dns_dthandle_t handle;
	isc_uint8_t *data;
	size_t dsize;
	unsigned char zone[DNS_NAME_MAXWIRE];
	unsigned char qambuffer[4096], rambuffer[4096];
	unsigned char qrmbuffer[4096], rrmbuffer[4096];
	isc_buffer_t zb, qamsg, ramsg, qrmsg, rrmsg;
	size_t qasize, qrsize, rasize, rrsize;
	dns_fixedname_t zfname;
	dns_name_t *zname;
	dns_dtmsgtype_t dt;
	dns_view_t *view = NULL;
	dns_compress_t cctx;
	isc_region_t zr;
	isc_sockaddr_t addr;
	struct in_addr in;
	isc_stdtime_t now;
	isc_time_t p, f;

	UNUSED(tc);

	cleanup();

	result = dns_test_begin(NULL, ISC_TRUE);
	ATF_REQUIRE(result == ISC_R_SUCCESS);

	result = dns_test_makeview("test", &view);

	result = dns_dt_create(mctx, dns_dtmode_file, TAPFILE, 1, &dtenv);
	ATF_REQUIRE(result == ISC_R_SUCCESS);

	dns_dt_attach(dtenv, &view->dtenv);
	view->dttypes = DNS_DTTYPE_ALL;

	/*
	 * Set up some test data
	 */
	dns_fixedname_init(&zfname);
	zname = dns_fixedname_name(&zfname);
	isc_buffer_constinit(&zb, "example.com.", 12);
	isc_buffer_add(&zb, 12);
	result = dns_name_fromtext(zname, &zb, NULL, 0, NULL);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	memset(&zr, 0, sizeof(zr));
	isc_buffer_init(&zb, zone, sizeof(zone));
	result = dns_compress_init(&cctx, -1, mctx);
	dns_compress_setmethods(&cctx, DNS_COMPRESS_NONE);
	result = dns_name_towire(zname, &cctx, &zb);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	dns_compress_invalidate(&cctx);
	isc_buffer_usedregion(&zb, &zr);

	in.s_addr = inet_addr("10.53.0.1");
	isc_sockaddr_fromin(&addr, &in, 2112);

	isc_stdtime_get(&now);
	isc_time_set(&p, now - 3600, 0); /* past */
	isc_time_set(&f, now + 3600, 0); /* future */

	result = dns_test_getdata("testdata/dnstap/query.auth",
				  qambuffer, sizeof(qambuffer), &qasize);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	isc_buffer_init(&qamsg, qambuffer, qasize);
	isc_buffer_add(&qamsg, qasize);

	result = dns_test_getdata("testdata/dnstap/response.auth",
				  rambuffer, sizeof(rambuffer), &rasize);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	isc_buffer_init(&ramsg, rambuffer, rasize);
	isc_buffer_add(&ramsg, rasize);

	result = dns_test_getdata("testdata/dnstap/query.recursive", qrmbuffer,
				  sizeof(qrmbuffer), &qrsize);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	isc_buffer_init(&qrmsg, qrmbuffer, qrsize);
	isc_buffer_add(&qrmsg, qrsize);

	result = dns_test_getdata("testdata/dnstap/response.recursive",
				  rrmbuffer, sizeof(rrmbuffer), &rrsize);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
	isc_buffer_init(&rrmsg, rrmbuffer, rrsize);
	isc_buffer_add(&rrmsg, rrsize);

	for (dt = DNS_DTTYPE_SQ; dt <= DNS_DTTYPE_TR; dt <<= 1) {
		isc_buffer_t *m;

		switch (dt) {
		case DNS_DTTYPE_AQ:
			m = &qamsg;
			break;
		case DNS_DTTYPE_AR:
			m = &ramsg;
			break;
		default:
			m = &qrmsg;
			if ((dt & DNS_DTTYPE_RESPONSE) != 0)
				m = &ramsg;
			break;
		}

		dns_dt_send(view, dt, &addr, ISC_FALSE, &zr, &p, &f, m);
		dns_dt_send(view, dt, &addr, ISC_FALSE, &zr, NULL, &f, m);
		dns_dt_send(view, dt, &addr, ISC_FALSE, &zr, &p, NULL, m);
		dns_dt_send(view, dt, &addr, ISC_FALSE, &zr, NULL, NULL, m);
		dns_dt_send(view, dt, &addr, ISC_TRUE, &zr, &p, &f, m);
		dns_dt_send(view, dt, &addr, ISC_TRUE, &zr, NULL, &f, m);
		dns_dt_send(view, dt, &addr, ISC_TRUE, &zr, &p, NULL, m);
		dns_dt_send(view, dt, &addr, ISC_TRUE, &zr, NULL, NULL, m);
	}

	dns_dt_detach(&view->dtenv);
	dns_dt_detach(&dtenv);
	dns_dt_shutdown();
	dns_view_detach(&view);

	/*
	 * XXX now read back and check content.
	 */

	result = dns_dt_open(TAPFILE, dns_dtmode_file, &handle);
	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);

	while (dns_dt_getframe(&handle, &data, &dsize) == ISC_R_SUCCESS) {
		dns_dtdata_t *dtdata = NULL;
		isc_region_t r;
		static dns_dtmsgtype_t expected = DNS_DTTYPE_SQ;
		static int n = 0;

		r.base = data;
		r.length = dsize;

		result = dns_dt_parse(mctx, &r, &dtdata);
		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
		if (result != ISC_R_SUCCESS) {
			n++;
			continue;
		}

		ATF_CHECK_EQ(dtdata->type, expected);
		if (++n % 8 == 0)
			expected <<= 1;

		dns_dtdata_free(&dtdata);
	}

	dns_dt_close(&handle);
	cleanup();

	dns_test_end();
}
예제 #8
0
void
test(unsigned int allowed, dns_name_t *name1, dns_name_t *name2,
     dns_name_t *name3, unsigned char *result, unsigned int length)
{
	isc_mem_t *mctx = NULL;
	dns_compress_t cctx;
	dns_decompress_t dctx;
	isc_buffer_t source;
	isc_buffer_t target;
	dns_name_t name;
	unsigned char buf1[1024];
	unsigned char buf2[1024];

	if (verbose) {
		const char *s;
		switch (allowed) {
		case DNS_COMPRESS_NONE: s = "DNS_COMPRESS_NONE"; break;
		case DNS_COMPRESS_GLOBAL14: s = "DNS_COMPRESS_GLOBAL14"; break;
		/* case DNS_COMPRESS_ALL: s = "DNS_COMPRESS_ALL"; break; */
		default: s = "UNKNOWN"; break;
		}
		fprintf(stdout, "Allowed = %s\n", s);
	}
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
	isc_buffer_init(&source, buf1, sizeof(buf1));
	RUNTIME_CHECK(dns_compress_init(&cctx, -1, mctx) == ISC_R_SUCCESS);

	RUNTIME_CHECK(dns_name_towire(name1, &cctx, &source) == ISC_R_SUCCESS);

	/*
	RUNTIME_CHECK(dns_compress_localinit(&cctx, name1, &source) ==
		      ISC_R_SUCCESS);
	*/
	dns_compress_setmethods(&cctx, allowed);
	RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == ISC_R_SUCCESS);
	RUNTIME_CHECK(dns_name_towire(name2, &cctx, &source) == ISC_R_SUCCESS);
	RUNTIME_CHECK(dns_name_towire(name3, &cctx, &source) == ISC_R_SUCCESS);

	/*
	dns_compress_localinvalidate(&cctx);
	*/
	dns_compress_rollback(&cctx, 0);	/* testing only */
	dns_compress_invalidate(&cctx);

	if (raw) {
		unsigned int i;
		for (i = 0; i < source.used; /* */ ) {
			fprintf(stdout, "%02x",
				((unsigned char *)source.base)[i]);
			if ((++i % 20) == 0)
				fputs("\n", stdout);
			else
				if (i == source.used)
					fputs("\n", stdout);
				else
					fputs(" ", stdout);
		}
	}

	isc_buffer_setactive(&source, source.used);
	isc_buffer_init(&target, buf2, sizeof(buf2));
	dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_STRICT);

	dns_name_init(&name, NULL);
	RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
					&target) == ISC_R_SUCCESS);
	dns_decompress_setmethods(&dctx, allowed);
	/*
	dns_decompress_localinit(&dctx, &name, &source);
	*/
	RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
					&target) == ISC_R_SUCCESS);
	RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
					&target) == ISC_R_SUCCESS);
	RUNTIME_CHECK(dns_name_fromwire(&name, &source, &dctx, ISC_FALSE,
					&target) == ISC_R_SUCCESS);
	/*
	dns_decompress_localinvalidate(&dctx);
	*/
	dns_decompress_invalidate(&dctx);

	if (raw) {
		unsigned int i;
		for (i = 0; i < target.used; /* */ ) {
			fprintf(stdout, "%02x",
				((unsigned char *)target.base)[i]);
			if ((++i % 20) == 0)
				fputs("\n", stdout);
			else
				if (i == target.used)
					fputs("\n", stdout);
				else
					fputs(" ", stdout);
		}
		fputs("\n", stdout);
		fflush(stdout);
	}

	RUNTIME_CHECK(target.used == length);
	RUNTIME_CHECK(memcmp(target.base, result, target.used) == 0);
	isc_mem_destroy(&mctx);
}