/*----------------------------------------------------------------------------*/ _public_ int knot_dname_cmp_wire(const knot_dname_t *d1, const knot_dname_t *d2, const uint8_t *pkt) { /* This would be hard to catch since -1 is a good result, assert instead. */ assert(d1 != NULL || d2 != NULL); /* Convert to lookup format. */ uint8_t d1_lf[KNOT_DNAME_MAXLEN], d2_lf[KNOT_DNAME_MAXLEN]; if (knot_dname_lf(d1_lf, d1, pkt) < 0 || knot_dname_lf(d2_lf, d2, pkt) < 0) { assert(0); /* This must not happend as the d1, d2 are checked. */ return KNOT_EINVAL; } /* Compare common part. */ uint8_t common = d1_lf[0]; if (common > d2_lf[0]) common = d2_lf[0]; int ret = memcmp(d1_lf+1, d2_lf+1, common); if (ret != 0) return ret; /* If they match, compare lengths. */ if (d1_lf[0] < d2_lf[0]) return -1; if (d1_lf[0] > d2_lf[0]) return 1; return 0; }
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; }
zone_node_t *zone_tree_get_next(zone_tree_t *tree, const knot_dname_t *owner) { if (tree == NULL || owner == NULL) { return NULL; } uint8_t lf[KNOT_DNAME_MAXLEN]; knot_dname_lf(lf, owner, NULL); value_t *fval = NULL; zone_node_t *n = NULL; (void)hattrie_find_next(tree, (char*)lf + 1, *lf, &fval); if (fval == NULL) { /* Return first node. */ hattrie_iter_t *it = hattrie_iter_begin(tree, true); if (it == NULL) { return NULL; } fval = hattrie_iter_val(it); hattrie_iter_free(it); } n = (zone_node_t *)*fval; /* Next node must be non-empty and auth. */ if (n->rrset_count == 0 || n->flags & NODE_FLAGS_NONAUTH) { return zone_tree_get_next(tree, n->owner); } else { return n; } }
int zone_tree_insert(zone_tree_t *tree, zone_node_t *node) { if (tree == NULL) { return KNOT_EINVAL; } assert(tree && node && node->owner); uint8_t lf[KNOT_DNAME_MAXLEN]; knot_dname_lf(lf, node->owner, NULL); *hattrie_get(tree, (char*)lf+1, *lf) = node; 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_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; }