int zone_tree_apply_inorder(zone_tree_t *tree, zone_tree_apply_cb_t function, void *data) { if (function == NULL) { return KNOT_EINVAL; } if (zone_tree_is_empty(tree)) { return KNOT_EOK; } int result = KNOT_EOK; hattrie_iter_t *i = hattrie_iter_begin(tree, 1); while(!hattrie_iter_finished(i)) { result = function((zone_node_t **)hattrie_iter_val(i), data); if (result != KNOT_EOK) { break; } hattrie_iter_next(i); } hattrie_iter_free(i); return result; }
int zone_tree_remove(zone_tree_t *tree, const knot_dname_t *owner, zone_node_t **removed) { if (owner == NULL) { return KNOT_EINVAL; } if (zone_tree_is_empty(tree)) { return KNOT_ENONODE; } uint8_t lf[KNOT_DNAME_MAXLEN]; knot_dname_lf(lf, owner, NULL); value_t *rval = hattrie_tryget(tree, (char*)lf+1, *lf); if (rval == NULL) { return KNOT_ENOENT; } else { *removed = (zone_node_t *)(*rval); } hattrie_del(tree, (char*)lf+1, *lf); return KNOT_EOK; }
int zone_tree_get_less_or_equal(zone_tree_t *tree, const knot_dname_t *owner, zone_node_t **found, zone_node_t **previous) { if (owner == NULL || found == NULL || previous == NULL) { return KNOT_EINVAL; } if (zone_tree_is_empty(tree)) { return KNOT_ENONODE; } uint8_t lf[KNOT_DNAME_MAXLEN]; knot_dname_lf(lf, owner, NULL); value_t *fval = NULL; int ret = hattrie_find_leq(tree, (char*)lf+1, *lf, &fval); if (fval) { *found = (zone_node_t *)(*fval); } int exact_match = 0; if (ret == 0) { if (fval) { *previous = (*found)->prev; } exact_match = 1; } else if (ret < 0) { *previous = *found; *found = NULL; } else if (ret > 0) { /* Previous should be the rightmost node. * For regular zone it is the node left of apex, but for some * cases like NSEC3, there is no such sort of thing (name wise). */ /*! \todo We could store rightmost node in zonetree probably. */ hattrie_iter_t *i = hattrie_iter_begin(tree, 1); *previous = *(zone_node_t **)hattrie_iter_val(i); /* leftmost */ *previous = (*previous)->prev; /* rightmost */ *found = NULL; hattrie_iter_free(i); } /* Previous node for proof must be non-empty and authoritative. */ if (*previous && ((*previous)->rrset_count == 0 || (*previous)->flags & NODE_FLAGS_NONAUTH)) { *previous = (*previous)->prev; } return exact_match; }
int zone_tree_apply(zone_tree_t *tree, zone_tree_apply_cb_t function, void *data) { if (function == NULL) { return KNOT_EINVAL; } if (zone_tree_is_empty(tree)) { return KNOT_EOK; } return hattrie_apply_rev(tree, (int (*)(value_t*,void*))function, data); }
static int axfr_query_init(struct query_data *qdata) { assert(qdata); /* Check AXFR query validity. */ int state = axfr_query_check(qdata); if (state == KNOT_NS_PROC_FAIL) { if (qdata->rcode == KNOT_RCODE_FORMERR) { return KNOT_EMALF; } else { return KNOT_EDENIED; } } /* Create transfer processing context. */ mm_ctx_t *mm = qdata->mm; zone_contents_t *zone = qdata->zone->contents; struct axfr_proc *axfr = mm_alloc(mm, sizeof(struct axfr_proc)); if (axfr == NULL) { return KNOT_ENOMEM; } memset(axfr, 0, sizeof(struct axfr_proc)); init_list(&axfr->proc.nodes); /* Put data to process. */ gettimeofday(&axfr->proc.tstamp, NULL); ptrlist_add(&axfr->proc.nodes, zone->nodes, mm); /* Put NSEC3 data if exists. */ if (!zone_tree_is_empty(zone->nsec3_nodes)) { ptrlist_add(&axfr->proc.nodes, zone->nsec3_nodes, mm); } /* Set up cleanup callback. */ qdata->ext = axfr; qdata->ext_cleanup = &axfr_query_cleanup; /* No zone changes during multipacket answer (unlocked in axfr_answer_cleanup) */ rcu_read_lock(); return KNOT_EOK; }
/*! * \brief Deletes NSEC3 chain if NSEC should be used. * * \param zone Zone to fix. * \param changeset Changeset to be used. * \return KNOT_E* */ static int delete_nsec3_chain(const zone_contents_t *zone, changeset_t *changeset) { assert(zone); assert(changeset); if (zone_tree_is_empty(zone->nsec3_nodes)) { return KNOT_EOK; } zone_tree_t *empty_tree = zone_tree_create(); if (!empty_tree) { return KNOT_ENOMEM; } int result = zone_tree_add_diff(zone->nsec3_nodes, empty_tree, changeset); zone_tree_free(&empty_tree); return result; }
int zone_tree_get(zone_tree_t *tree, const knot_dname_t *owner, zone_node_t **found) { if (owner == NULL) { return KNOT_EINVAL; } if (zone_tree_is_empty(tree)) { return KNOT_ENONODE; } uint8_t lf[KNOT_DNAME_MAXLEN]; knot_dname_lf(lf, owner, NULL); value_t *val = hattrie_tryget(tree, (char*)lf+1, *lf); if (val == NULL) { *found = NULL; } else { *found = (zone_node_t*)(*val); } return KNOT_EOK; }
/*! * \brief Marks all NSEC3 nodes in zone from which RRSets are to be removed. * * For each NSEC3 RRSet in the changeset finds its node and marks it with the * 'removed' flag. */ static int mark_removed_nsec3(changeset_t *out_ch, const zone_contents_t *zone) { if (zone_tree_is_empty(zone->nsec3_nodes)) { return KNOT_EOK; } changeset_iter_t itt; changeset_iter_rem(&itt, out_ch, false); knot_rrset_t rr = changeset_iter_next(&itt); while (!knot_rrset_empty(&rr)) { int ret = mark_nsec3(&rr, zone->nsec3_nodes); if (ret != KNOT_EOK) { changeset_iter_clear(&itt); return ret; } rr = changeset_iter_next(&itt); } changeset_iter_clear(&itt); return KNOT_EOK; }