Exemplo n.º 1
0
/**
 * Remove NSEC records between start and end points.
 * By walking the tree, the tree is sorted canonically.
 * @param neg: negative cache.
 * @param zone: the zone
 * @param el: element to start walking at.
 * @param nsec: the nsec record with the end point
 */
static void wipeout(struct val_neg_cache* neg, struct val_neg_zone* zone, 
	struct val_neg_data* el, struct ub_packed_rrset_key* nsec)
{
	struct packed_rrset_data* d = (struct packed_rrset_data*)nsec->
		entry.data;
	uint8_t* end;
	size_t end_len;
	int end_labs, m;
	rbnode_t* walk, *next;
	struct val_neg_data* cur;
	uint8_t buf[257];
	/* get endpoint */
	if(!d || d->count == 0 || d->rr_len[0] < 2+1)
		return;
	if(ntohs(nsec->rk.type) == LDNS_RR_TYPE_NSEC) {
		end = d->rr_data[0]+2;
		end_len = dname_valid(end, d->rr_len[0]-2);
		end_labs = dname_count_labels(end);
	} else {
		/* NSEC3 */
		if(!nsec3_get_nextowner_b32(nsec, 0, buf, sizeof(buf)))
			return;
		end = buf;
		end_labs = dname_count_size_labels(end, &end_len);
	}

	/* sanity check, both owner and end must be below the zone apex */
	if(!dname_subdomain_c(el->name, zone->name) || 
		!dname_subdomain_c(end, zone->name))
		return;

	/* detect end of zone NSEC ; wipe until the end of zone */
	if(query_dname_compare(end, zone->name) == 0) {
		end = NULL;
	}

	walk = rbtree_next(&el->node);
	while(walk && walk != RBTREE_NULL) {
		cur = (struct val_neg_data*)walk;
		/* sanity check: must be larger than start */
		if(dname_canon_lab_cmp(cur->name, cur->labs, 
			el->name, el->labs, &m) <= 0) {
			/* r == 0 skip original record. */
			/* r < 0  too small! */
			walk = rbtree_next(walk);
			continue;
		}
		/* stop at endpoint, also data at empty nonterminals must be
		 * removed (no NSECs there) so everything between 
		 * start and end */
		if(end && dname_canon_lab_cmp(cur->name, cur->labs,
			end, end_labs, &m) >= 0) {
			break;
		}
		/* this element has to be deleted, but we cannot do it
		 * now, because we are walking the tree still ... */
		/* get the next element: */
		next = rbtree_next(walk);
		/* now delete the original element, this may trigger
		 * rbtree rebalances, but really, the next element is
		 * the one we need.
		 * But it may trigger delete of other data and the
		 * entire zone. However, if that happens, this is done
		 * by deleting the *parents* of the element for deletion,
		 * and maybe also the entire zone if it is empty. 
		 * But parents are smaller in canonical compare, thus,
		 * if a larger element exists, then it is not a parent,
		 * it cannot get deleted, the zone cannot get empty.
		 * If the next==NULL, then zone can be empty. */
		if(cur->in_use)
			neg_delete_data(neg, cur);
		walk = next;
	}
}
Exemplo n.º 2
0
/** remove a random item */
static void remove_item(struct val_neg_cache* neg)
{
	int n, i;
	struct val_neg_data* d;
	rbnode_t* walk;
	struct val_neg_zone* z;
	
	lock_basic_lock(&neg->lock);
	if(neg->tree.count == 0) {
		lock_basic_unlock(&neg->lock);
		return; /* nothing to delete */
	}

	/* pick a random zone */
	walk = rbtree_first(&neg->tree); /* first highest parent, big count */
	z = (struct val_neg_zone*)walk;
	n = random() % (int)(z->count);
	if(negverbose)
		printf("neg stress delete zone %d\n", n);
	i=0;
	walk = rbtree_first(&neg->tree);
	z = (struct val_neg_zone*)walk;
	while(i!=n+1 && walk && walk != RBTREE_NULL && !z->in_use) {
		walk = rbtree_next(walk);
		z = (struct val_neg_zone*)walk;
		if(z->in_use)
			i++;
	}
	if(!walk || walk == RBTREE_NULL) {
		lock_basic_unlock(&neg->lock);
		return;
	}
	if(!z->in_use) {
		lock_basic_unlock(&neg->lock);
		return;
	}
	if(negverbose)
		log_nametypeclass(0, "delete zone", z->name, 0, 0);

	/* pick a random nsec item. - that is in use */
	walk = rbtree_first(&z->tree); /* first is highest parent */
	d = (struct val_neg_data*)walk;
	n = random() % (int)(d->count);
	if(negverbose)
		printf("neg stress delete item %d\n", n);
	i=0;
	walk = rbtree_first(&z->tree);
	d = (struct val_neg_data*)walk;
	while(i!=n+1 && walk && walk != RBTREE_NULL && !d->in_use) {
		walk = rbtree_next(walk);
		d = (struct val_neg_data*)walk;
		if(d->in_use)
			i++;
	}
	if(!walk || walk == RBTREE_NULL) {
		lock_basic_unlock(&neg->lock);
		return;
	}
	if(d->in_use) {
		if(negverbose)
			log_nametypeclass(0, "neg delete item:", d->name, 0, 0);
		neg_delete_data(neg, d);
	}
	lock_basic_unlock(&neg->lock);
}