Exemplo n.º 1
0
/** perf test a packet */
static void
perftestpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out, 
	const char* hex)
{
	struct query_info qi;
	struct reply_info* rep = 0;
	int ret;
	uint16_t id;
	uint16_t flags;
	time_t timenow = 0;
	struct regional* region = regional_create();
	struct edns_data edns;

	hex_to_buf(pkt, hex);
	memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
	if(sldns_buffer_limit(pkt) < 2)
		flags = 0;
	else	memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
	flags = ntohs(flags);
	ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
	if(ret != 0) {
		char rbuf[16];
		sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
		if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
		if(ret == LDNS_RCODE_FORMERR)
			checkformerr(pkt);
		unit_assert(ret != LDNS_RCODE_SERVFAIL);
	} else {
		perf_encode(&qi, rep, id, flags, out, timenow, &edns);
	} 

	query_info_clear(&qi);
	reply_info_parsedelete(rep, alloc);
	regional_destroy(region);
}
Exemplo n.º 2
0
int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc,
        struct query_info* qinf, struct reply_info** rep, 
	struct regional* region, struct edns_data* edns)
{
	/* use scratch pad region-allocator during parsing. */
	struct msg_parse* msg;
	int ret;
	
	qinf->qname = NULL;
	*rep = NULL;
	if(!(msg = regional_alloc(region, sizeof(*msg)))) {
		return LDNS_RCODE_SERVFAIL;
	}
	memset(msg, 0, sizeof(*msg));
	
	sldns_buffer_set_position(pkt, 0);
	if((ret = parse_packet(pkt, msg, region)) != 0) {
		return ret;
	}
	if((ret = parse_extract_edns(msg, edns)) != 0)
		return ret;

	/* parse OK, allocate return structures */
	/* this also performs dname decompression */
	if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) {
		query_info_clear(qinf);
		reply_info_parsedelete(*rep, alloc);
		*rep = NULL;
		return LDNS_RCODE_SERVFAIL;
	}
	return 0;
}
/** verify and test an entry - every rr in the message */
static void
verifytest_entry(struct entry* e, struct alloc_cache* alloc, 
	struct regional* region, ldns_buffer* pkt, 
	struct ub_packed_rrset_key* dnskey, struct module_env* env, 
	struct val_env* ve)
{
	struct query_info qinfo;
	struct reply_info* rep = NULL;
	size_t i;

	regional_free_all(region);
	if(vsig) {
		printf("verifying pkt:\n");
		ldns_pkt_print(stdout, e->reply_list->reply);
		printf("\n");
	}
	entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);

	for(i=0; i<rep->rrset_count; i++) {
		verifytest_rrset(env, ve, rep->rrsets[i], dnskey, &qinfo);
	}

	reply_info_parsedelete(rep, alloc);
	query_info_clear(&qinfo);
}
Exemplo n.º 4
0
int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
        struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
	struct regional* region, uint32_t flags)
{
	struct reply_info* rep = NULL;
	/* alloc, malloc properly (not in region, like msg is) */
	rep = reply_info_copy(msgrep, env->alloc, NULL);
	if(!rep)
		return 0;
	/* ttl must be relative ;i.e. 0..86400 not  time(0)+86400.
	 * the env->now is added to message and RRsets in this routine. */
	/* the leeway is used to invalidate other rrsets earlier */

	if(is_referral) {
		/* store rrsets */
		struct rrset_ref ref;
		size_t i;
		for(i=0; i<rep->rrset_count; i++) {
			packed_rrset_ttl_add((struct packed_rrset_data*)
				rep->rrsets[i]->entry.data, *env->now);
			ref.key = rep->rrsets[i];
			ref.id = rep->rrsets[i]->id;
			/*ignore ret: it was in the cache, ref updated */
			/* no leeway for typeNS */
			(void)rrset_cache_update(env->rrset_cache, &ref, 
				env->alloc, *env->now + 
				((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
				 && !pside) ? 0:leeway));
		}
		free(rep);
		return 1;
	} else {
		/* store msg, and rrsets */
		struct query_info qinf;
		hashvalue_type h;

		qinf = *msgqinf;
		qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
		if(!qinf.qname) {
			reply_info_parsedelete(rep, env->alloc);
			return 0;
		}
		/* fixup flags to be sensible for a reply based on the cache */
		/* this module means that RA is available. It is an answer QR. 
		 * Not AA from cache. Not CD in cache (depends on client bit). */
		rep->flags |= (BIT_RA | BIT_QR);
		rep->flags &= ~(BIT_AA | BIT_CD);
		h = query_info_hash(&qinf, (uint16_t)flags);
		dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
			flags, region);
		/* qname is used inside query_info_entrysetup, and set to 
		 * NULL. If it has not been used, free it. free(0) is safe. */
		free(qinf.qname);
	}
	return 1;
}
Exemplo n.º 5
0
struct reply_info* 
reply_info_copy(struct reply_info* rep, struct alloc_cache* alloc, 
	struct regional* region)
{
	struct reply_info* cp;
	cp = construct_reply_info_base(region, rep->flags, rep->qdcount, 
		rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, 
		rep->ns_numrrsets, rep->ar_numrrsets, rep->rrset_count, 
		rep->security);
	if(!cp)
		return NULL;
	/* allocate ub_key structures special or not */
	if(!repinfo_alloc_rrset_keys(cp, alloc, region)) {
		if(!region)
			reply_info_parsedelete(cp, alloc);
		return NULL;
	}
	if(!repinfo_copy_rrsets(cp, rep, region)) {
		if(!region)
			reply_info_parsedelete(cp, alloc);
		return NULL;
	}
	return cp;
}
Exemplo n.º 6
0
/** Test hash algo - NSEC3 hash it and compare result */
static void
nsec3_hash_test_entry(struct entry* e, rbtree_type* ct,
	struct alloc_cache* alloc, struct regional* region, 
	sldns_buffer* buf)
{
	struct query_info qinfo;
	struct reply_info* rep = NULL;
	struct ub_packed_rrset_key* answer, *nsec3;
	struct nsec3_cached_hash* hash = NULL;
	int ret;
	uint8_t* qname;

	if(vsig) {
		char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
			e->reply_list->reply_len);
		printf("verifying NSEC3 hash:\n%s\n", s?s:"outofmemory");
		free(s);
	}
	entry_to_repinfo(e, alloc, region, buf, &qinfo, &rep);
	nsec3 = find_rrset_type(rep, LDNS_RR_TYPE_NSEC3);
	answer = find_rrset_type(rep, LDNS_RR_TYPE_AAAA);
	qname = regional_alloc_init(region, qinfo.qname, qinfo.qname_len);
	/* check test is OK */
	unit_assert(nsec3 && answer && qname);

	ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname,
		qinfo.qname_len, &hash);
	if(ret != 1) {
		printf("Bad nsec3_hash_name retcode %d\n", ret);
		unit_assert(ret == 1);
	}
	unit_assert(hash->dname && hash->hash && hash->hash_len &&
		hash->b32 && hash->b32_len);
	unit_assert(hash->b32_len == (size_t)answer->rk.dname[0]);
	/* does not do lowercasing. */
	unit_assert(memcmp(hash->b32, answer->rk.dname+1, hash->b32_len) 
		== 0);

	reply_info_parsedelete(rep, alloc);
	query_info_clear(&qinfo);
}
Exemplo n.º 7
0
/** DS sig test an entry - get DNSKEY and DS in entry and verify */
static void
dstest_entry(struct entry* e, struct alloc_cache* alloc, 
	struct regional* region, sldns_buffer* pkt, struct module_env* env)
{
	struct query_info qinfo;
	struct reply_info* rep = NULL;
	struct ub_packed_rrset_key* ds, *dnskey;
	int ret;

	regional_free_all(region);
	if(vsig) {
		char* s = sldns_wire2str_pkt(e->reply_list->reply_pkt,
			e->reply_list->reply_len);
		printf("verifying DS-DNSKEY match:\n%s\n", s?s:"outofmemory");
		free(s);
	}
	entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
	ds = find_rrset_type(rep, LDNS_RR_TYPE_DS);
	dnskey = find_rrset_type(rep, LDNS_RR_TYPE_DNSKEY);
	/* check test is OK */
	unit_assert(ds && dnskey);

	ret = ds_digest_match_dnskey(env, dnskey, 0, ds, 0);
	if(strncmp((char*)qinfo.qname, "\003yes", 4) == 0) {
		if(vsig) {
			printf("result(yes)= %s\n", ret?"yes":"no");
		}
		unit_assert(ret);
	} else if (strncmp((char*)qinfo.qname, "\002no", 3) == 0) {
		if(vsig) {
			printf("result(no)= %s\n", ret?"yes":"no");
		}
		unit_assert(!ret);
		verbose(VERB_QUERY, "DS fail: OK; matched unit test");
	} else {
		fatal_exit("Bad qname in DS unit test, yes or no");
	}

	reply_info_parsedelete(rep, alloc);
	query_info_clear(&qinfo);
}
/** extract DNSKEY rrset from answer and convert it */
static struct ub_packed_rrset_key* 
extract_keys(struct entry* e, struct alloc_cache* alloc, 
	struct regional* region, ldns_buffer* pkt)
{
	struct ub_packed_rrset_key* dnskey = NULL;
	struct query_info qinfo;
	struct reply_info* rep = NULL;
	size_t i;

	entry_to_repinfo(e, alloc, region, pkt, &qinfo, &rep);
	for(i=0; i<rep->an_numrrsets; i++) {
		if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_DNSKEY) {
			dnskey = rep->rrsets[i];
			rep->rrsets[i] = NULL;
			break;
		}
	}
	unit_assert(dnskey);

	reply_info_parsedelete(rep, alloc);
	query_info_clear(&qinfo);
	return dnskey;
}
Exemplo n.º 9
0
/** test a packet */
static void
testpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out, 
	const char* hex)
{
	struct query_info qi;
	struct reply_info* rep = 0;
	int ret;
	uint16_t id;
	uint16_t flags;
	uint32_t timenow = 0;
	struct regional* region = regional_create();
	struct edns_data edns;

	hex_to_buf(pkt, hex);
	memmove(&id, sldns_buffer_begin(pkt), sizeof(id));
	if(sldns_buffer_limit(pkt) < 2)
		flags = 0;
	else	memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags));
	flags = ntohs(flags);
	ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns);
	if(ret != 0) {
		char rbuf[16];
		sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf));
		if(vbmp) printf("parse code %d: %s\n", ret, rbuf);
		if(ret == LDNS_RCODE_FORMERR) {
			unit_assert(!check_formerr_gone);
			checkformerr(pkt);
		}
		unit_assert(ret != LDNS_RCODE_SERVFAIL);
	} else if(!check_formerr_gone) {
		const size_t lim = 512;
		ret = reply_info_encode(&qi, rep, id, flags, out, timenow,
			region, 65535, (int)(edns.bits & EDNS_DO) );
		unit_assert(ret != 0); /* udp packets should fit */
		attach_edns_record(out, &edns);
		if(vbmp) printf("inlen %u outlen %u\n", 
			(unsigned)sldns_buffer_limit(pkt),
			(unsigned)sldns_buffer_limit(out));
		if(!check_nosameness)
			test_buffers(pkt, out);
		if(check_rrsigs)
			check_the_rrsigs(&qi, rep);

		if(sldns_buffer_limit(out) > lim) {
			ret = reply_info_encode(&qi, rep, id, flags, out, 
				timenow, region, 
				lim - calc_edns_field_size(&edns),
				(int)(edns.bits & EDNS_DO));
			unit_assert(ret != 0); /* should fit, but with TC */
			attach_edns_record(out, &edns);
			if( LDNS_QDCOUNT(sldns_buffer_begin(out)) !=
				LDNS_QDCOUNT(sldns_buffer_begin(pkt)) ||
				LDNS_ANCOUNT(sldns_buffer_begin(out)) !=
				LDNS_ANCOUNT(sldns_buffer_begin(pkt)) ||
				LDNS_NSCOUNT(sldns_buffer_begin(out)) !=
				LDNS_NSCOUNT(sldns_buffer_begin(pkt)))
				unit_assert(
				LDNS_TC_WIRE(sldns_buffer_begin(out)));
				/* must set TC bit if shortened */
			unit_assert(sldns_buffer_limit(out) <= lim);
		}
	} 

	query_info_clear(&qi);
	reply_info_parsedelete(rep, alloc);
	regional_destroy(region);
}