コード例 #1
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
/** enter tagstring into zone */
static int
lz_enter_zone_tag(struct local_zones* zones, char* zname, uint8_t* list,
	size_t len, uint16_t rr_class)
{
	uint8_t dname[LDNS_MAX_DOMAINLEN+1];
	size_t dname_len = sizeof(dname);
	int dname_labs, r = 0;
	struct local_zone* z;

	if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
		log_err("cannot parse zone name in local-zone-tag: %s", zname);
		return 0;
	}
	dname_labs = dname_count_labels(dname);
	
	lock_rw_rdlock(&zones->lock);
	z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
	if(!z) {
		lock_rw_unlock(&zones->lock);
		log_err("no local-zone for tag %s", zname);
		return 0;
	}
	lock_rw_wrlock(&z->lock);
	lock_rw_unlock(&zones->lock);
	free(z->taglist);
	z->taglist = memdup(list, len);
	z->taglen = len;
	if(z->taglist)
		r = 1;
	lock_rw_unlock(&z->lock);
	return r;
}
コード例 #2
0
ファイル: cachedump.c プロジェクト: Bluecoreg/monero
/** dump lruhash msg cache */
static int
dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
{
	struct lruhash_entry* e;
	struct query_info* k;
	struct reply_info* d;

	/* lruhash already locked by caller */
	/* walk in order of lru; best first */
	for(e=h->lru_start; e; e = e->lru_next) {
		regional_free_all(worker->scratchpad);
		lock_rw_rdlock(&e->lock);
		/* make copy of rrset in worker buffer */
		if(!copy_msg(worker->scratchpad, e, &k, &d)) {
			lock_rw_unlock(&e->lock);
			return 0;
		}
		lock_rw_unlock(&e->lock);
		/* release lock so we can lookup the rrset references 
		 * in the rrset cache */
		if(!dump_msg(ssl, k, d, *worker->env.now)) {
			return 0;
		}
	}
	return 1;
}
コード例 #3
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
/** enter a data RR into auth data; a zone for it must exist */
static int
lz_enter_rr_str(struct local_zones* zones, const char* rr)
{
	uint8_t* rr_name;
	uint16_t rr_class;
	size_t len;
	int labs;
	struct local_zone* z;
	int r;
	if(!get_rr_nameclass(rr, &rr_name, &rr_class)) {
		log_err("bad rr %s", rr);
		return 0;
	}
	labs = dname_count_size_labels(rr_name, &len);
	lock_rw_rdlock(&zones->lock);
	z = local_zones_lookup(zones, rr_name, len, labs, rr_class);
	if(!z) {
		lock_rw_unlock(&zones->lock);
		fatal_exit("internal error: no zone for rr %s", rr);
	}
	lock_rw_wrlock(&z->lock);
	lock_rw_unlock(&zones->lock);
	free(rr_name);
	r = lz_enter_rr_into_zone(z, rr);
	lock_rw_unlock(&z->lock);
	return r;
}
コード例 #4
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
void local_zones_del_data(struct local_zones* zones, 
	uint8_t* name, size_t len, int labs, uint16_t dclass)
{
	/* find zone */
	struct local_zone* z;
	struct local_data* d;
	lock_rw_rdlock(&zones->lock);
	z = local_zones_lookup(zones, name, len, labs, dclass);
	if(!z) {
		/* no such zone, we're done */
		lock_rw_unlock(&zones->lock);
		return;
	}
	lock_rw_wrlock(&z->lock);
	lock_rw_unlock(&zones->lock);

	/* find the domain */
	d = lz_find_node(z, name, len, labs);
	if(d) {
		/* no memory recycling for zone deletions ... */
		d->rrsets = NULL;
		/* did we delete the soa record ? */
		if(query_dname_compare(d->name, z->name) == 0)
			z->soa = NULL;

		/* cleanup the empty nonterminals for this name */
		del_empty_term(z, d, name, len, labs);
	}

	lock_rw_unlock(&z->lock);
}
コード例 #5
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
int 
local_zones_answer(struct local_zones* zones, struct query_info* qinfo,
	struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
	struct comm_reply* repinfo, uint8_t* taglist, size_t taglen,
	uint8_t* tagactions, size_t tagactionssize,
	struct config_strlist** tag_datas, size_t tag_datas_size,
	char** tagname, int num_tags)
{
	/* see if query is covered by a zone,
	 * 	if so:	- try to match (exact) local data 
	 * 		- look at zone type for negative response. */
	int labs = dname_count_labels(qinfo->qname);
	struct local_data* ld = NULL;
	struct local_zone* z;
	enum localzone_type lzt;
	int r, tag = -1;
	lock_rw_rdlock(&zones->lock);
	z = local_zones_tags_lookup(zones, qinfo->qname,
		qinfo->qname_len, labs, qinfo->qclass, taglist, taglen, 0);
	if(!z) {
		lock_rw_unlock(&zones->lock);
		return 0;
	}
	lock_rw_rdlock(&z->lock);
	lock_rw_unlock(&zones->lock);

	lzt = lz_type(taglist, taglen, z->taglist, z->taglen, tagactions,
		tagactionssize, z->type, repinfo, z->override_tree, &tag,
		tagname, num_tags);

	if((lzt == local_zone_inform || lzt == local_zone_inform_deny)
		&& repinfo)
		lz_inform_print(z, qinfo, repinfo);

	if(lzt != local_zone_always_refuse && lzt != local_zone_always_transparent
		&& lzt != local_zone_always_nxdomain
		&& local_data_answer(z, qinfo, edns, buf, temp, labs, &ld, lzt,
		tag, tag_datas, tag_datas_size, tagname, num_tags)) {
		lock_rw_unlock(&z->lock);
		return 1;
	}
	r = lz_zone_answer(z, qinfo, edns, buf, temp, ld, lzt);
	lock_rw_unlock(&z->lock);
	return r;
}
コード例 #6
0
ファイル: cachedump.c プロジェクト: Bluecoreg/monero
/** dump lruhash rrset cache */
static int
dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
{
	struct lruhash_entry* e;
	/* lruhash already locked by caller */
	/* walk in order of lru; best first */
	for(e=h->lru_start; e; e = e->lru_next) {
		lock_rw_rdlock(&e->lock);
		if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key,
			(struct packed_rrset_data*)e->data, now)) {
			lock_rw_unlock(&e->lock);
			return 0;
		}
		lock_rw_unlock(&e->lock);
	}
	return 1;
}
コード例 #7
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
/** lookup a zone in rbtree; exact match only; SLOW due to parse */
static int
lz_exists(struct local_zones* zones, const char* name)
{
	struct local_zone z;
	z.node.key = &z;
	z.dclass = LDNS_RR_CLASS_IN;
	if(!parse_dname(name, &z.name, &z.namelen, &z.namelabs)) {
		log_err("bad name %s", name);
		return 0;
	}
	lock_rw_rdlock(&zones->lock);
	if(rbtree_search(&zones->ztree, &z.node)) {
		lock_rw_unlock(&zones->lock);
		free(z.name);
		return 1;
	}
	lock_rw_unlock(&zones->lock);
	free(z.name);
	return 0;
}
コード例 #8
0
ファイル: dns.c プロジェクト: derekmarcotte/freebsd
/** store rrsets in the rrset cache. 
 * @param env: module environment with caches.
 * @param rep: contains list of rrsets to store.
 * @param now: current time.
 * @param leeway: during prefetch how much leeway to update TTLs.
 * 	This makes rrsets (other than type NS) timeout sooner so they get
 * 	updated with a new full TTL.
 * 	Type NS does not get this, because it must not be refreshed from the
 * 	child domain, but keep counting down properly.
 * @param pside: if from parentside discovered NS, so that its NS is okay
 * 	in a prefetch situation to be updated (without becoming sticky).
 * @param qrep: update rrsets here if cache is better
 * @param region: for qrep allocs.
 */
static void
store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
	time_t leeway, int pside, struct reply_info* qrep,
	struct regional* region)
{
        size_t i;
        /* see if rrset already exists in cache, if not insert it. */
        for(i=0; i<rep->rrset_count; i++) {
                rep->ref[i].key = rep->rrsets[i];
                rep->ref[i].id = rep->rrsets[i]->id;
		/* update ref if it was in the cache */ 
		switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
                        env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
			LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
		case 0: /* ref unchanged, item inserted */
			break;
		case 2: /* ref updated, cache is superior */
			if(region) {
				struct ub_packed_rrset_key* ck;
				lock_rw_rdlock(&rep->ref[i].key->entry.lock);
				/* if deleted rrset, do not copy it */
				if(rep->ref[i].key->id == 0)
					ck = NULL;
				else 	ck = packed_rrset_copy_region(
					rep->ref[i].key, region, now);
				lock_rw_unlock(&rep->ref[i].key->entry.lock);
				if(ck) {
					/* use cached copy if memory allows */
					qrep->rrsets[i] = ck;
				}
			}
			/* no break: also copy key item */
			/* the line below is matched by gcc regex and silences
			 * the fallthrough warning */
			/* fallthrough */
		case 1: /* ref updated, item inserted */
                        rep->rrsets[i] = rep->ref[i].key;
		}
        }
}
コード例 #9
0
ファイル: respip.c プロジェクト: Bluecoreg/monero
int
respip_rewrite_reply(const struct query_info* qinfo,
	const struct respip_client_info* cinfo, const struct reply_info* rep,
	struct reply_info** new_repp, struct respip_action_info* actinfo,
	struct ub_packed_rrset_key** alias_rrset, int search_only,
	struct regional* region)
{
	const uint8_t* ctaglist;
	size_t ctaglen;
	const uint8_t* tag_actions;
	size_t tag_actions_size;
	struct config_strlist** tag_datas;
	size_t tag_datas_size;
	struct view* view = NULL;
	struct respip_set* ipset = NULL;
	size_t rrset_id = 0;
	enum respip_action action = respip_none;
	int tag = -1;
	const struct resp_addr* raddr = NULL;
	int ret = 1;
	struct ub_packed_rrset_key* redirect_rrset = NULL;

	if(!cinfo)
		goto done;
	ctaglist = cinfo->taglist;
	ctaglen = cinfo->taglen;
	tag_actions = cinfo->tag_actions;
	tag_actions_size = cinfo->tag_actions_size;
	tag_datas = cinfo->tag_datas;
	tag_datas_size = cinfo->tag_datas_size;
	view = cinfo->view;
	ipset = cinfo->respip_set;

	/** Try to use response-ip config from the view first; use
	  * global response-ip config if we don't have the view or we don't
	  * have the matching per-view config (and the view allows the use
	  * of global data in this case).
	  * Note that we lock the view even if we only use view members that
	  * currently don't change after creation.  This is for safety for
	  * future possible changes as the view documentation seems to expect
	  * any of its member can change in the view's lifetime.
	  * Note also that we assume 'view' is valid in this function, which
	  * should be safe (see unbound bug #1191) */
	if(view) {
		lock_rw_rdlock(&view->lock);
		if(view->respip_set) {
			if((raddr = respip_addr_lookup(rep,
				&view->respip_set->ip_tree, &rrset_id))) {
				/** for per-view respip directives the action
				 * can only be direct (i.e. not tag-based) */
				action = raddr->action;
			}
		}
		if(!raddr && !view->isfirst)
			goto done;
	}
	if(!raddr && ipset && (raddr = respip_addr_lookup(rep, &ipset->ip_tree,
		&rrset_id))) {
		action = (enum respip_action)local_data_find_tag_action(
			raddr->taglist, raddr->taglen, ctaglist, ctaglen,
			tag_actions, tag_actions_size,
			(enum localzone_type)raddr->action, &tag,
			ipset->tagname, ipset->num_tags);
	}
	if(raddr && !search_only) {
		int result = 0;

		/* first, see if we have response-ip or tag action for the
		 * action except for 'always' variants. */
		if(action != respip_always_refuse
			&& action != respip_always_transparent
			&& action != respip_always_nxdomain
			&& (result = respip_data_answer(raddr, action,
			qinfo->qtype, rep, rrset_id, new_repp, tag, tag_datas,
			tag_datas_size, ipset->tagname, ipset->num_tags,
			&redirect_rrset, region)) < 0) {
			ret = 0;
			goto done;
		}

		/* if no action data applied, take action specific to the
		 * action without data. */
		if(!result && !respip_nodata_answer(qinfo->qtype, action, rep,
			rrset_id, new_repp, region)) {
			ret = 0;
			goto done;
		}
	}
  done:
	if(view) {
		lock_rw_unlock(&view->lock);
	}
	if(ret) {
		/* If we're redirecting the original answer to a
		 * CNAME, record the CNAME rrset so the caller can take
		 * the appropriate action.  Note that we don't check the
		 * action type; it should normally be 'redirect', but it
		 * can be of other type when a data-dependent tag action
		 * uses redirect response-ip data.
		 */
		if(redirect_rrset &&
			redirect_rrset->rk.type == ntohs(LDNS_RR_TYPE_CNAME) &&
			qinfo->qtype != LDNS_RR_TYPE_ANY)
			*alias_rrset = redirect_rrset;
		/* on success, populate respip result structure */
		ret = populate_action_info(actinfo, action, raddr,
			redirect_rrset, tag, ipset, search_only, region);
	}
	return ret;
}
コード例 #10
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
/** enter implicit transparent zone for local-data: without local-zone: */
static int
lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
{
	/* walk over all items that have no parent zone and find
	 * the name that covers them all (could be the root) and
	 * add that as a transparent zone */
	struct config_strlist* p;
	int have_name = 0;
	int have_other_classes = 0;
	uint16_t dclass = 0;
	uint8_t* nm = 0;
	size_t nmlen = 0;
	int nmlabs = 0;
	int match = 0; /* number of labels match count */

	init_parents(zones); /* to enable local_zones_lookup() */
	for(p = cfg->local_data; p; p = p->next) {
		uint8_t* rr_name;
		uint16_t rr_class;
		size_t len;
		int labs;
		if(!get_rr_nameclass(p->str, &rr_name, &rr_class)) {
			log_err("Bad local-data RR %s", p->str);
			return 0;
		}
		labs = dname_count_size_labels(rr_name, &len);
		lock_rw_rdlock(&zones->lock);
		if(!local_zones_lookup(zones, rr_name, len, labs, rr_class)) {
			if(!have_name) {
				dclass = rr_class;
				nm = rr_name;
				nmlen = len;
				nmlabs = labs;
				match = labs;
				have_name = 1;
			} else {
				int m;
				if(rr_class != dclass) {
					/* process other classes later */
					free(rr_name);
					have_other_classes = 1;
					lock_rw_unlock(&zones->lock);
					continue;
				}
				/* find smallest shared topdomain */
				(void)dname_lab_cmp(nm, nmlabs, 
					rr_name, labs, &m);
				free(rr_name);
				if(m < match)
					match = m;
			}
		} else free(rr_name);
		lock_rw_unlock(&zones->lock);
	}
	if(have_name) {
		uint8_t* n2;
		struct local_zone* z;
		/* allocate zone of smallest shared topdomain to contain em */
		n2 = nm;
		dname_remove_labels(&n2, &nmlen, nmlabs - match);
		n2 = memdup(n2, nmlen);
		free(nm);
		if(!n2) {
			log_err("out of memory");
			return 0;
		}
		log_nametypeclass(VERB_ALGO, "implicit transparent local-zone", 
			n2, 0, dclass);
		if(!(z=lz_enter_zone_dname(zones, n2, nmlen, match, 
			local_zone_transparent, dclass))) {
			return 0;
		}
		lock_rw_unlock(&z->lock);
	}
	if(have_other_classes) { 
		/* restart to setup other class */
		return lz_setup_implicit(zones, cfg);
	}
	return 1;
}
コード例 #11
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
/** enter override into zone */
static int
lz_enter_override(struct local_zones* zones, char* zname, char* netblock,
	char* type, uint16_t rr_class)
{
	uint8_t dname[LDNS_MAX_DOMAINLEN+1];
	size_t dname_len = sizeof(dname);
	int dname_labs;
	struct sockaddr_storage addr;
	int net;
	socklen_t addrlen;
	struct local_zone* z;
	enum localzone_type t;

	/* parse zone name */
	if(sldns_str2wire_dname_buf(zname, dname, &dname_len) != 0) {
		log_err("cannot parse zone name in local-zone-override: %s %s",
			zname, netblock);
		return 0;
	}
	dname_labs = dname_count_labels(dname);

	/* parse netblock */
	if(!netblockstrtoaddr(netblock, UNBOUND_DNS_PORT, &addr, &addrlen,
		&net)) {
		log_err("cannot parse netblock in local-zone-override: %s %s",
			zname, netblock);
		return 0;
	}

	/* parse zone type */
	if(!local_zone_str2type(type, &t)) {
		log_err("cannot parse type in local-zone-override: %s %s %s",
			zname, netblock, type);
		return 0;
	}

	/* find localzone entry */
	lock_rw_rdlock(&zones->lock);
	z = local_zones_find(zones, dname, dname_len, dname_labs, rr_class);
	if(!z) {
		lock_rw_unlock(&zones->lock);
		log_err("no local-zone for local-zone-override %s", zname);
		return 0;
	}
	lock_rw_wrlock(&z->lock);
	lock_rw_unlock(&zones->lock);

	/* create netblock addr_tree if not present yet */
	if(!z->override_tree) {
		z->override_tree = (struct rbtree_t*)regional_alloc_zero(
			z->region, sizeof(*z->override_tree));
		if(!z->override_tree) {
			lock_rw_unlock(&z->lock);
			log_err("out of memory");
			return 0;
		}
		addr_tree_init(z->override_tree);
	}
	/* add new elem to tree */
	if(z->override_tree) {
		struct local_zone_override* n;
		n = (struct local_zone_override*)regional_alloc_zero(
			z->region, sizeof(*n));
		if(!n) {
			lock_rw_unlock(&z->lock);
			log_err("out of memory");
			return 0;
		}
		n->type = t;
		if(!addr_tree_insert(z->override_tree,
			(struct addr_tree_node*)n, &addr, addrlen, net)) {
			lock_rw_unlock(&z->lock);
			log_err("duplicate local-zone-override %s %s",
				zname, netblock);
			return 1;
		}
	}

	lock_rw_unlock(&z->lock);
	return 1;
}
コード例 #12
0
ファイル: localzone.c プロジェクト: 2trill2spill/freebsd
void local_zones_print(struct local_zones* zones)
{
	struct local_zone* z;
	lock_rw_rdlock(&zones->lock);
	log_info("number of auth zones %u", (unsigned)zones->ztree.count);
	RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
		lock_rw_rdlock(&z->lock);
		switch(z->type) {
		case local_zone_deny:
			log_nametypeclass(0, "deny zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_refuse:
			log_nametypeclass(0, "refuse zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_redirect:
			log_nametypeclass(0, "redirect zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_transparent:
			log_nametypeclass(0, "transparent zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_typetransparent:
			log_nametypeclass(0, "typetransparent zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_static:
			log_nametypeclass(0, "static zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_inform:
			log_nametypeclass(0, "inform zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_inform_deny:
			log_nametypeclass(0, "inform_deny zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_always_transparent:
			log_nametypeclass(0, "always_transparent zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_always_refuse:
			log_nametypeclass(0, "always_refuse zone", 
				z->name, 0, z->dclass);
			break;
		case local_zone_always_nxdomain:
			log_nametypeclass(0, "always_nxdomain zone", 
				z->name, 0, z->dclass);
			break;
		default:
			log_nametypeclass(0, "badtyped zone", 
				z->name, 0, z->dclass);
			break;
		}
		local_zone_out(z);
		lock_rw_unlock(&z->lock);
	}
	lock_rw_unlock(&zones->lock);
}