Beispiel #1
0
struct val_anchors* 
anchors_create(void)
{
	struct val_anchors* a = (struct val_anchors*)calloc(1, sizeof(*a));
	if(!a)
		return NULL;
	a->region = regional_create();
	if(!a->region) {
		free(a);
		return NULL;
	}
	a->tree = rbtree_create(anchor_cmp);
	if(!a->tree) {
		anchors_delete(a);
		return NULL;
	}
	a->autr = autr_global_create();
	if(!a->autr) {
		anchors_delete(a);
		return NULL;
	}
	lock_basic_init(&a->lock);
	lock_protect(&a->lock, a, sizeof(*a));
	lock_protect(&a->lock, a->autr, sizeof(*a->autr));
	return a;
}
Beispiel #2
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);
}
Beispiel #3
0
/** create a new localzone */
static struct local_zone*
local_zone_create(uint8_t* nm, size_t len, int labs, 
	enum localzone_type t, uint16_t dclass)
{
	struct local_zone* z = (struct local_zone*)calloc(1, sizeof(*z));
	if(!z) {
		return NULL;
	}
	z->node.key = z;
	z->dclass = dclass;
	z->type = t;
	z->name = nm;
	z->namelen = len;
	z->namelabs = labs;
	lock_rw_init(&z->lock);
	z->region = regional_create();
	if(!z->region) {
		free(z);
		return NULL;
	}
	rbtree_init(&z->data, &local_data_cmp);
	lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_t));
	/* also the zones->lock protects node, parent, name*, class */
	return z;
}
Beispiel #4
0
/** performance test message encoding */
static void
perf_encode(struct query_info* qi, struct reply_info* rep, uint16_t id, 
	uint16_t flags, sldns_buffer* out, time_t timenow, 
	struct edns_data* edns)
{
	static int num = 0;
	int ret;
	size_t max = 10000;
	size_t i;
	struct timeval start, end;
	double dt;
	struct regional* r2 = regional_create();
	if(gettimeofday(&start, NULL) < 0)
		fatal_exit("gettimeofday: %s", strerror(errno));
	/* encode a couple times */
	for(i=0; i<max; i++) {
		ret = reply_info_encode(qi, rep, id, flags, out, timenow,
			r2, 65535, (int)(edns->bits & EDNS_DO) );
		unit_assert(ret != 0); /* udp packets should fit */
		attach_edns_record(out, edns);
		regional_free_all(r2);
	}
	if(gettimeofday(&end, NULL) < 0)
		fatal_exit("gettimeofday: %s", strerror(errno));
	/* time in millisec */
	dt = (double)(end.tv_sec - start.tv_sec)*1000. + 
		((double)end.tv_usec - (double)start.tv_usec)/1000.;
	printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++,
		(unsigned)max, dt, (double)max / (dt/1000.), 
		(int)sldns_buffer_limit(out));
	regional_destroy(r2);
}
/** verify DS matches DNSKEY from a file */
static void
dstest_file(const char* fname)
{
	/* 
	 * The file contains a list of ldns-testpkts entries.
	 * The first entry must be a query for DNSKEY.
	 * The answer rrset is the keyset that will be used for verification
	 */
	struct regional* region = regional_create();
	struct alloc_cache alloc;
	ldns_buffer* buf = ldns_buffer_new(65535);
	struct entry* e;
	struct entry* list = read_datafile(fname);
	struct module_env env;

	if(!list)
		fatal_exit("could not read %s: %s", fname, strerror(errno));
	alloc_init(&alloc, NULL, 1);
	memset(&env, 0, sizeof(env));
	env.scratch = region;
	env.scratch_buffer = buf;
	unit_assert(region && buf);

	/* ready to go! */
	for(e = list; e; e = e->next) {
		dstest_entry(e, &alloc, region, buf, &env);
	}

	delete_entry(list);
	regional_destroy(region);
	alloc_clear(&alloc);
	ldns_buffer_free(buf);
}
Beispiel #6
0
void 
log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
{
	/* not particularly fast but flexible, make wireformat and print */
	ldns_buffer* buf = ldns_buffer_new(65535);
	struct regional* region = regional_create();
	if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, 
		region, 65535, 1)) {
		log_info("%s: log_dns_msg: out of memory", str);
	} else {
		ldns_status s;
		ldns_pkt* pkt = NULL;
		s = ldns_buffer2pkt_wire(&pkt, buf);
		if(s != LDNS_STATUS_OK) {
			log_info("%s: log_dns_msg: ldns parse gave: %s",
				str, ldns_get_errorstr_by_id(s));
		} else {
			ldns_buffer_clear(buf);
			s = ldns_pkt2buffer_str(buf, pkt);
			if(s != LDNS_STATUS_OK) {
				log_info("%s: log_dns_msg: ldns tostr gave: %s",
					str, ldns_get_errorstr_by_id(s));
			} else {
				log_info("%s %s", 
					str, (char*)ldns_buffer_begin(buf));
			}
		}
		ldns_pkt_free(pkt);
	}
	ldns_buffer_free(buf);
	regional_destroy(region);
}
Beispiel #7
0
struct acl_list* 
acl_list_create(void)
{
	struct acl_list* acl = (struct acl_list*)calloc(1,
		sizeof(struct acl_list));
	if(!acl)
		return NULL;
	acl->region = regional_create();
	if(!acl->region) {
		acl_list_delete(acl);
		return NULL;
	}
	return acl;
}
Beispiel #8
0
struct respip_set*
respip_set_create(void)
{
	struct respip_set* set = calloc(1, sizeof(*set));
	if(!set)
		return NULL;
	set->region = regional_create();
	if(!set->region) {
		free(set);
		return NULL;
	}
	addr_tree_init(&set->ip_tree);
	return set;
}
Beispiel #9
0
/** check if module works with config */
static void
check_mod(struct config_file* cfg, struct module_func_block* fb)
{
	struct module_env env;
	memset(&env, 0, sizeof(env));
	env.cfg = cfg;
	env.scratch = regional_create();
	env.scratch_buffer = ldns_buffer_new(BUFSIZ);
	if(!env.scratch || !env.scratch_buffer)
		fatal_exit("out of memory");
	if(!(*fb->init)(&env, 0)) {
		fatal_exit("bad config for %s module", fb->name);
	}
	(*fb->deinit)(&env, 0);
	ldns_buffer_free(env.scratch_buffer);
	regional_destroy(env.scratch);
}
/** verify from a file */
static void
verifytest_file(const char* fname, const char* at_date)
{
	/* 
	 * The file contains a list of ldns-testpkts entries.
	 * The first entry must be a query for DNSKEY.
	 * The answer rrset is the keyset that will be used for verification
	 */
	struct ub_packed_rrset_key* dnskey;
	struct regional* region = regional_create();
	struct alloc_cache alloc;
	ldns_buffer* buf = ldns_buffer_new(65535);
	struct entry* e;
	struct entry* list = read_datafile(fname);
	struct module_env env;
	struct val_env ve;
	uint32_t now = time(NULL);

	if(!list)
		fatal_exit("could not read %s: %s", fname, strerror(errno));
	alloc_init(&alloc, NULL, 1);
	memset(&env, 0, sizeof(env));
	memset(&ve, 0, sizeof(ve));
	env.scratch = region;
	env.scratch_buffer = buf;
	env.now = &now;
	ve.date_override = cfg_convert_timeval(at_date);
	unit_assert(region && buf);
	dnskey = extract_keys(list, &alloc, region, buf);
	if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey",
			dnskey->rk.dname, ntohs(dnskey->rk.type), 
			ntohs(dnskey->rk.rrset_class));
	/* ready to go! */
	for(e = list->next; e; e = e->next) {
		verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve);
	}

	ub_packed_rrset_parsedelete(dnskey, &alloc);
	delete_entry(list);
	regional_destroy(region);
	alloc_clear(&alloc);
	ldns_buffer_free(buf);
}
Beispiel #11
0
void 
log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
{
	/* not particularly fast but flexible, make wireformat and print */
	sldns_buffer* buf = sldns_buffer_new(65535);
	struct regional* region = regional_create();
	if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, 
		region, 65535, 1)) {
		log_info("%s: log_dns_msg: out of memory", str);
	} else {
		char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf),
			sldns_buffer_limit(buf));
		if(!s) {
			log_info("%s: log_dns_msg: ldns tostr failed", str);
		} else {
			log_info("%s %s", str, s);
		}
		free(s);
	}
	sldns_buffer_free(buf);
	regional_destroy(region);
}
/** Read file to test NSEC3 hash algo */
static void
nsec3_hash_test(const char* fname)
{
	/* 
	 * The list contains a list of ldns-testpkts entries.
	 * Every entry is a test.
	 * 	The qname is hashed.
	 * 	The answer section AAAA RR name is the required result.
	 * 	The auth section NSEC3 is used to get hash parameters.
	 * The hash cache is maintained per file.
	 *
	 * The test does not perform canonicalization during the compare.
	 */
	rbtree_t ct;
	struct regional* region = regional_create();
	struct alloc_cache alloc;
	ldns_buffer* buf = ldns_buffer_new(65535);
	struct entry* e;
	struct entry* list = read_datafile(fname);

	if(!list)
		fatal_exit("could not read %s: %s", fname, strerror(errno));
	rbtree_init(&ct, &nsec3_hash_cmp);
	alloc_init(&alloc, NULL, 1);
	unit_assert(region && buf);

	/* ready to go! */
	for(e = list; e; e = e->next) {
		nsec3_hash_test_entry(e, &ct, &alloc, region, buf);
	}

	delete_entry(list);
	regional_destroy(region);
	alloc_clear(&alloc);
	ldns_buffer_free(buf);
}
Beispiel #13
0
/** process answer from bg worker */
static int
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
                      ub_callback_t* cb, void** cbarg, int* err,
                      struct ub_result** res)
{
    struct ctx_query* q;
    if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
        log_err("error: bad data from bg worker %d",
                (int)context_serial_getcmd(msg, len));
        return 0;
    }

    lock_basic_lock(&ctx->cfglock);
    q = context_deserialize_answer(ctx, msg, len, err);
    if(!q) {
        lock_basic_unlock(&ctx->cfglock);
        /* probably simply the lookup that failed, i.e.
         * response returned before cancel was sent out, so noerror */
        return 1;
    }
    log_assert(q->async);

    /* grab cb while locked */
    if(q->cancelled) {
        *cb = NULL;
        *cbarg = NULL;
    } else {
        *cb = q->cb;
        *cbarg = q->cb_arg;
    }
    if(*err) {
        *res = NULL;
        ub_resolve_free(q->res);
    } else {
        /* parse the message, extract rcode, fill result */
        ldns_buffer* buf = ldns_buffer_new(q->msg_len);
        struct regional* region = regional_create();
        *res = q->res;
        (*res)->rcode = LDNS_RCODE_SERVFAIL;
        if(region && buf) {
            ldns_buffer_clear(buf);
            ldns_buffer_write(buf, q->msg, q->msg_len);
            ldns_buffer_flip(buf);
            libworker_enter_result(*res, buf, region,
                                   q->msg_security);
        }
        (*res)->answer_packet = q->msg;
        (*res)->answer_len = (int)q->msg_len;
        q->msg = NULL;
        ldns_buffer_free(buf);
        regional_destroy(region);
    }
    q->res = NULL;
    /* delete the q from list */
    (void)rbtree_delete(&ctx->queries, q->node.key);
    ctx->num_async--;
    context_query_delete(q);
    lock_basic_unlock(&ctx->cfglock);

    if(*cb) return 2;
    ub_resolve_free(*res);
    return 1;
}
Beispiel #14
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);
}