Beispiel #1
0
static void
ldns_dnssec_name_make_hashed_name(ldns_dnssec_zone *zone,
		ldns_dnssec_name* name, ldns_rr* nsec3rr)
{
	ldns_rbnode_t* new_node;

	assert(name != NULL);
	if (! zone->_nsec3params) {
		if (! nsec3rr) {
			return;
		}
		ldns_dnssec_zone_hashed_names_from_nsec3(zone, nsec3rr);

	} else if (! nsec3rr) {
		nsec3rr = zone->_nsec3params;
	}
	name->hashed_name = ldns_nsec3_hash_name_frm_nsec3(nsec3rr, name->name);

	/* Also store in zone->hashed_names */
	if ((new_node = LDNS_MALLOC(ldns_rbnode_t))) {

		new_node->key  = name->hashed_name;
		new_node->data = name;

		if (ldns_rbtree_insert(zone->hashed_names, new_node) == NULL) {

				LDNS_FREE(new_node);
		}
	}
}
Beispiel #2
0
/**
 * Add zone.
 *
 */
zone_type*
zonelist_add_zone(zonelist_type* zlist, zone_type* zone)
{
    ldns_rbnode_t* new_node = NULL;
    if (!zone) {
        return NULL;
    }
    if (!zlist || !zlist->zones) {
        zone_cleanup(zone);
        return NULL;
    }
    /* look up */
    if (zonelist_lookup_zone(zlist, zone) != NULL) {
        ods_log_warning("[%s] unable to add zone %s: already present", zl_str,
                        zone->name);
        zone_cleanup(zone);
        return NULL;
    }
    /* add */
    new_node = zone2node(zone);
    if (ldns_rbtree_insert(zlist->zones, new_node) == NULL) {
        ods_log_error("[%s] unable to add zone %s: ldns_rbtree_insert() "
                      "failed", zl_str, zone->name);
        free((void*) new_node);
        zone_cleanup(zone);
        return NULL;
    }
    zone->zl_status = ZONE_ZL_ADDED;
    zlist->just_added++;
    return zone;
}
Beispiel #3
0
ldns_status
ldns_dnssec_zone_add_rr(ldns_dnssec_zone *zone, ldns_rr *rr)
{
	ldns_status result = LDNS_STATUS_OK;
	ldns_dnssec_name *cur_name;
	ldns_rbnode_t *cur_node;
	ldns_rr_type type_covered = 0;

	if (!zone || !rr) {
		return LDNS_STATUS_ERR;
	}

	if (!zone->names) {
		zone->names = ldns_rbtree_create(ldns_dname_compare_v);
                if(!zone->names) return LDNS_STATUS_MEM_ERR;
	}

	/* we need the original of the hashed name if this is
	   an NSEC3, or an RRSIG that covers an NSEC3 */
	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG) {
		type_covered = ldns_rdf2rr_type(ldns_rr_rrsig_typecovered(rr));
	}
	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_NSEC3 ||
	    type_covered == LDNS_RR_TYPE_NSEC3) {
		cur_node = ldns_dnssec_zone_find_nsec3_original(zone, rr);
		if (!cur_node) {
			return LDNS_STATUS_DNSSEC_NSEC3_ORIGINAL_NOT_FOUND;
		}
	} else {
		cur_node = ldns_rbtree_search(zone->names, ldns_rr_owner(rr));
	}
	if (!cur_node) {
		/* add */
		cur_name = ldns_dnssec_name_new_frm_rr(rr);
                if(!cur_name) return LDNS_STATUS_MEM_ERR;
		cur_node = LDNS_MALLOC(ldns_rbnode_t);
                if(!cur_node) {
                        ldns_dnssec_name_free(cur_name);
                        return LDNS_STATUS_MEM_ERR;
                }
		cur_node->key = ldns_rr_owner(rr);
		cur_node->data = cur_name;
		(void)ldns_rbtree_insert(zone->names, cur_node);
		ldns_dnssec_name_make_hashed_name(zone, cur_name, NULL);
	} else {
		cur_name = (ldns_dnssec_name *) cur_node->data;
		result = ldns_dnssec_name_add_rr(cur_name, rr);
	}
	if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
		zone->soa = cur_name;
	}
	return result;
}
Beispiel #4
0
struct getdns_dict_item *
getdns_dict_find_and_add(struct getdns_dict *dict, const char *key)
{
	struct getdns_dict_item *item;

	item = (struct getdns_dict_item *)
	       ldns_rbtree_search(&(dict->root), key);

	if (!item) {
		/* add a node */
		item = GETDNS_MALLOC(dict->mf, struct getdns_dict_item);
		item->node.key = getdns_strdup(&dict->mf, key);
		item->data.n = 0;
		ldns_rbtree_insert(&(dict->root), (ldns_rbnode_t *) item);
	}
Beispiel #5
0
int
schedule_flush_type(schedule_type* schedule, task_id id)
{
    ldns_rbnode_t *node, *nextnode;
    int nflushed = 0;
    
    ods_log_debug("[%s] flush task", schedule_str);
    if (!schedule || !schedule->tasks) return 0;

    pthread_mutex_lock(&schedule->schedule_lock);
        node = ldns_rbtree_first(schedule->tasks);
        while (node && node != LDNS_RBTREE_NULL) {
            nextnode = ldns_rbtree_next(node);
            if (node->data && ((task_type*)node->data)->what == id) {
                /* Merely setting flush is not enough. We must set it
                 * to the front of the queue as well. */
                node = ldns_rbtree_delete(schedule->tasks, node->data);
                if (!node) break; /* stange, bail out */
                if (node->data) { /* task */
                    ((task_type*)node->data)->flush = 1;
                    /* This is important for our tests only. If a task is
                     * set to flush it should not affect the current time.
                     * Otherwise timeleap will advance time. */
                    ((task_type*)node->data)->when = time_now();
                    if (!ldns_rbtree_insert(schedule->tasks, node)) {
                        ods_log_crit("[%s] Could not reschedule task "
                            "after flush. A task has been lost!",
                            schedule_str);
                        free(node);
                        /* Do not free node->data it is still in use
                         * by the other rbtree. */
                        break;
                    }
                    nflushed++;
                }
            }
            node = nextnode;
        }
        /* wakeup! work to do! */
        pthread_cond_signal(&schedule->schedule_cond);
    pthread_mutex_unlock(&schedule->schedule_lock);
    return nflushed;
}
Beispiel #6
0
ods_status
schedule_task(schedule_type* schedule, task_type* task)
{
    ldns_rbnode_t *node1, *node2;
    ods_status status;
    task_type* task2;

    if (!task) {
        ods_log_error("[%s] unable to schedule task: no task", schedule_str);
        return ODS_STATUS_ERR;
    }
    task->flush = 0;
    if (!schedule || !schedule->tasks) {
        ods_log_error("[%s] unable to schedule task: no schedule",
            schedule_str);
        return ODS_STATUS_ERR;
    }

    ods_log_debug("[%s] schedule task [%s] for %s", schedule_str,
        task_what2str(task->what), task_who2str(task->who));

    pthread_mutex_lock(&schedule->schedule_lock);
        status = ODS_STATUS_ERR;
        if ((node1 = task2node(task))) {
            if (ldns_rbtree_insert(schedule->tasks_by_name, node1)) {
                if ((node2 = task2node(task))) {
                    if(ldns_rbtree_insert(schedule->tasks, node2)) {
                        /* success inserting in two trees */
                        set_alarm(schedule);
                        status = ODS_STATUS_OK;
                    } else { /* insert in tasks tree failed */
                        ods_log_error("[%s] unable to schedule task [%s] for %s: "
                            " already present", schedule_str, task_what2str(task->what),
                            task_who2str(task->who));
                        /* this will free node1 */
                        free(ldns_rbtree_delete(schedule->tasks_by_name, node1));
                        free(node2);
                    }
                } else { /* could not alloc node2 */
                    /* this will free node1 */
                    free(ldns_rbtree_delete(schedule->tasks_by_name, node1));
                }

            } else {/* insert in name tree failed */
                free(node1);
                /**
                 * Task is already in tasks_by_name queue, so we must
                 * update it in tasks queue
                 */
                /* still in lock guaranteed to succeed. */
                node1 = ldns_rbtree_search(schedule->tasks_by_name, task);
                /* This copy of 'task' is referenced by both trees */
                task2 = (task_type*)node1->key;
                node1 = ldns_rbtree_delete(schedule->tasks, task2);
                if (task->when < task2->when)
                    task2->when = task->when;
                if (task2->context && task2->clean_context) {
                    task2->clean_context(task2);
                }
                task2->context = task->context;
                task2->clean_context = task->clean_context;
                task->context = NULL;
                task_cleanup(task);
                (void) ldns_rbtree_insert(schedule->tasks, node1);
                /* node1 now owned by tree */
                node1 = NULL;
                set_alarm(schedule);
                status = ODS_STATUS_OK;
            }
        } /* else {failure) */
    pthread_mutex_unlock(&schedule->schedule_lock);
    return status;
}
Beispiel #7
0
void
ldns_rbtree_insert_vref(ldns_rbnode_t *data, void *rbtree)
{
	(void) ldns_rbtree_insert((ldns_rbtree_t *) rbtree,
						 data);
}
Beispiel #8
0
ldns_status
ldns_dnssec_zone_add_empty_nonterminals(ldns_dnssec_zone *zone)
{
	ldns_dnssec_name *new_name;
	ldns_rdf *cur_name;
	ldns_rdf *next_name;
	ldns_rbnode_t *cur_node, *next_node, *new_node;

	/* for the detection */
	uint16_t i, cur_label_count, next_label_count;
	uint16_t soa_label_count = 0;
	ldns_rdf *l1, *l2;
	int lpos;

	if (!zone) {
		return LDNS_STATUS_ERR;
	}
	if (zone->soa && zone->soa->name) {
		soa_label_count = ldns_dname_label_count(zone->soa->name);
	}
	
	cur_node = ldns_rbtree_first(zone->names);
	while (cur_node != LDNS_RBTREE_NULL) {
		next_node = ldns_rbtree_next(cur_node);
		
		/* skip glue */
		while (next_node != LDNS_RBTREE_NULL && 
		       next_node->data &&
		       ((ldns_dnssec_name *)next_node->data)->is_glue
		) {
			next_node = ldns_rbtree_next(next_node);
		}

		if (next_node == LDNS_RBTREE_NULL) {
			next_node = ldns_rbtree_first(zone->names);
		}
		if (! cur_node->data || ! next_node->data) {
			return LDNS_STATUS_ERR;
		}
		cur_name = ((ldns_dnssec_name *)cur_node->data)->name;
		next_name = ((ldns_dnssec_name *)next_node->data)->name;
		cur_label_count = ldns_dname_label_count(cur_name);
		next_label_count = ldns_dname_label_count(next_name);

		/* Since the names are in canonical order, we can
		 * recognize empty non-terminals by their labels;
		 * every label after the first one on the next owner
		 * name is a non-terminal if it either does not exist
		 * in the current name or is different from the same
		 * label in the current name (counting from the end)
		 */
		for (i = 1; i < next_label_count - soa_label_count; i++) {
			lpos = (int)cur_label_count - (int)next_label_count + (int)i;
			if (lpos >= 0) {
				l1 = ldns_dname_clone_from(cur_name, (uint8_t)lpos);
			} else {
				l1 = NULL;
			}
			l2 = ldns_dname_clone_from(next_name, i);

			if (!l1 || ldns_dname_compare(l1, l2) != 0) {
				/* We have an empty nonterminal, add it to the
				 * tree
				 */
				new_name = ldns_dnssec_name_new();
				if (!new_name) {
					return LDNS_STATUS_MEM_ERR;
				}
				new_name->name = ldns_dname_clone_from(next_name,
				                                       i);
				if (!new_name->name) {
					ldns_dnssec_name_free(new_name);
					return LDNS_STATUS_MEM_ERR;
				}
				new_name->name_alloced = true;
				new_node = LDNS_MALLOC(ldns_rbnode_t);
				if (!new_node) {
					ldns_dnssec_name_free(new_name);
					return LDNS_STATUS_MEM_ERR;
				}
				new_node->key = new_name->name;
				new_node->data = new_name;
				(void)ldns_rbtree_insert(zone->names, new_node);
				ldns_dnssec_name_make_hashed_name(
						zone, new_name, NULL);
			}
			ldns_rdf_deep_free(l1);
			ldns_rdf_deep_free(l2);
		}
		
		/* we might have inserted a new node after
		 * the current one so we can't just use next()
		 */
		if (next_node != ldns_rbtree_first(zone->names)) {
			cur_node = next_node;
		} else {
			cur_node = LDNS_RBTREE_NULL;
		}
	}
	return LDNS_STATUS_OK;
}
Beispiel #9
0
static ldns_rbnode_t *MV_SHM_insert_virtaddress_node(ldns_rbtree_t *shm_root,
						shm_address_t *shm_node)
{
	shm_node->m_flag = SHM_VIRT_INSERT;
	return ldns_rbtree_insert(shm_root, &shm_node->virt_node);
}
Beispiel #10
0
static ldns_rbnode_t *MV_SHM_insert_phyaddress_node(ldns_rbtree_t *shm_root,
						shm_address_t *shm_node)
{
	shm_node->m_flag = SHM_PHYS_INSERT;
	return ldns_rbtree_insert(shm_root, &shm_node->phys_node);
}
Beispiel #11
0
static ldns_status
ldns_dnssec_zone_create_nsec3s_mkmap(ldns_dnssec_zone *zone,
		ldns_rr_list *new_rrs,
		uint8_t algorithm,
		uint8_t flags,
		uint16_t iterations,
		uint8_t salt_length,
		uint8_t *salt,
		ldns_rbtree_t **map)
{
	ldns_rbnode_t *first_name_node;
	ldns_rbnode_t *current_name_node;
	ldns_dnssec_name *current_name;
	ldns_status result = LDNS_STATUS_OK;
	ldns_rr *nsec_rr;
	ldns_rr_list *nsec3_list;
	uint32_t nsec_ttl;
	ldns_dnssec_rrsets *soa;
	ldns_rbnode_t *hashmap_node;

	if (!zone || !new_rrs || !zone->names) {
		return LDNS_STATUS_ERR;
	}

	/* the TTL of NSEC rrs should be set to the minimum TTL of
	 * the zone SOA (RFC4035 Section 2.3)
	 */
	soa = ldns_dnssec_name_find_rrset(zone->soa, LDNS_RR_TYPE_SOA);

	/* did the caller actually set it? if not,
	 * fall back to default ttl
	 */
	if (soa && soa->rrs && soa->rrs->rr
			&& ldns_rr_rdf(soa->rrs->rr, 6) != NULL) {
		nsec_ttl = ldns_rdf2native_int32(ldns_rr_rdf(soa->rrs->rr, 6));
	} else {
		nsec_ttl = LDNS_DEFAULT_TTL;
	}

	if (zone->hashed_names) {
		ldns_traverse_postorder(zone->hashed_names,
				ldns_hashed_names_node_free, NULL);
		LDNS_FREE(zone->hashed_names);
	}
	zone->hashed_names = ldns_rbtree_create(ldns_dname_compare_v);
	if (zone->hashed_names && map) {
		*map = zone->hashed_names;
	}

	first_name_node = ldns_dnssec_name_node_next_nonglue(
					  ldns_rbtree_first(zone->names));

	current_name_node = first_name_node;

	while (current_name_node && current_name_node != LDNS_RBTREE_NULL &&
			result == LDNS_STATUS_OK) {

		current_name = (ldns_dnssec_name *) current_name_node->data;
		nsec_rr = ldns_dnssec_create_nsec3(current_name,
		                                   NULL,
		                                   zone->soa->name,
		                                   algorithm,
		                                   flags,
		                                   iterations,
		                                   salt_length,
		                                   salt);
		/* by default, our nsec based generator adds rrsigs
		 * remove the bitmap for empty nonterminals */
		if (!current_name->rrsets) {
			ldns_rdf_deep_free(ldns_rr_pop_rdf(nsec_rr));
		}
		ldns_rr_set_ttl(nsec_rr, nsec_ttl);
		result = ldns_dnssec_name_add_rr(current_name, nsec_rr);
		ldns_rr_list_push_rr(new_rrs, nsec_rr);
		if (ldns_rr_owner(nsec_rr)) {
			hashmap_node = LDNS_MALLOC(ldns_rbnode_t);
			if (hashmap_node == NULL) {
				return LDNS_STATUS_MEM_ERR;
			}
			current_name->hashed_name = 
				ldns_dname_label(ldns_rr_owner(nsec_rr), 0);

			if (current_name->hashed_name == NULL) {
				LDNS_FREE(hashmap_node);
				return LDNS_STATUS_MEM_ERR;
			}
			hashmap_node->key  = current_name->hashed_name;
			hashmap_node->data = current_name;

			if (! ldns_rbtree_insert(zone->hashed_names
						, hashmap_node)) {
				LDNS_FREE(hashmap_node);
			}
		}
		current_name_node = ldns_dnssec_name_node_next_nonglue(
		                   ldns_rbtree_next(current_name_node));
	}
	if (result != LDNS_STATUS_OK) {
		return result;
	}

	/* Make sorted list of nsec3s (via zone->hashed_names)
	 */
	nsec3_list = ldns_rr_list_new();
	if (nsec3_list == NULL) {
		return LDNS_STATUS_MEM_ERR;
	}
	for ( hashmap_node  = ldns_rbtree_first(zone->hashed_names)
	    ; hashmap_node != LDNS_RBTREE_NULL
	    ; hashmap_node  = ldns_rbtree_next(hashmap_node)
	    ) {
		current_name = (ldns_dnssec_name *) hashmap_node->data;
		nsec_rr = ((ldns_dnssec_name *) hashmap_node->data)->nsec;
		if (nsec_rr) {
			ldns_rr_list_push_rr(nsec3_list, nsec_rr);
		}
	}
	result = ldns_dnssec_chain_nsec3_list(nsec3_list);
	ldns_rr_list_free(nsec3_list);

	return result;
}