static int axfr_put_rrsets(knot_pkt_t *pkt, zone_node_t *node, struct axfr_proc *state) { assert(node != NULL); int ret = KNOT_EOK; int i = state->cur_rrset; uint16_t rrset_count = node->rrset_count; unsigned flags = KNOT_PF_NOTRUNC; /* Append all RRs. */ for (;i < rrset_count; ++i) { knot_rrset_t rrset = node_rrset_at(node, i); if (rrset.type == KNOT_RRTYPE_SOA) { continue; } ret = knot_pkt_put(pkt, 0, &rrset, flags); /* If something failed, remember the current RR for later. */ if (ret != KNOT_EOK) { state->cur_rrset = i; return ret; } } state->cur_rrset = 0; return ret; }
/*! * \brief Checks whether the node is empty or eventually contains only NSEC and * RRSIGs. */ bool knot_nsec_empty_nsec_and_rrsigs_in_node(const zone_node_t *n) { assert(n); for (int i = 0; i < n->rrset_count; ++i) { knot_rrset_t rrset = node_rrset_at(n, i); if (rrset.type != KNOT_RRTYPE_NSEC && rrset.type != KNOT_RRTYPE_RRSIG) { return false; } } return true; }
static int knot_zone_diff_add_node(const zone_node_t *node, changeset_t *changeset) { /* Add all rrsets from node. */ for (unsigned i = 0; i < node->rrset_count; i++) { knot_rrset_t rrset = node_rrset_at(node, i); int ret = changeset_add_rrset(changeset, &rrset); if (ret != KNOT_EOK) { dbg_zonediff("zone_diff: add_node: Cannot add RRSet (%s).\n", knot_strerror(ret)); return ret; } } return KNOT_EOK; }
static int knot_zone_diff_remove_node(changeset_t *changeset, const zone_node_t *node) { /* Remove all the RRSets of the node. */ for (unsigned i = 0; i < node->rrset_count; i++) { knot_rrset_t rrset = node_rrset_at(node, i); int ret = changeset_rem_rrset(changeset, &rrset); if (ret != KNOT_EOK) { dbg_zonediff("zone_diff: remove_node: Failed to " "remove rrset. Error: %s\n", knot_strerror(ret)); return ret; } } return KNOT_EOK; }
/*!< \todo this could be generic function for adding / removing. */ static int knot_zone_diff_node(zone_node_t **node_ptr, void *data) { if (node_ptr == NULL || *node_ptr == NULL || data == NULL) { return KNOT_EINVAL; } zone_node_t *node = *node_ptr; struct zone_diff_param *param = (struct zone_diff_param *)data; if (param->changeset == NULL) { return KNOT_EINVAL; } /* * First, we have to search the second tree to see if there's according * node, if not, the whole node has been removed. */ const zone_node_t *node_in_second_tree = NULL; const knot_dname_t *node_owner = node->owner; assert(node_owner); zone_tree_find(param->nodes, node_owner, &node_in_second_tree); if (node_in_second_tree == NULL) { return knot_zone_diff_remove_node(param->changeset, node); } assert(node_in_second_tree != node); /* The nodes are in both trees, we have to diff each RRSet. */ if (node->rrset_count == 0) { /* * If there are no RRs in the first tree, all of the RRs * in the second tree will have to be inserted to ADD section. */ return knot_zone_diff_add_node(node_in_second_tree, param->changeset); } for (unsigned i = 0; i < node->rrset_count; i++) { /* Search for the RRSet in the node from the second tree. */ knot_rrset_t rrset = node_rrset_at(node, i); /* SOAs are handled explicitely. */ if (rrset.type == KNOT_RRTYPE_SOA) { continue; } knot_rrset_t rrset_from_second_node = node_rrset(node_in_second_tree, rrset.type); if (knot_rrset_empty(&rrset_from_second_node)) { /* RRSet has been removed. Make a copy and remove. */ int ret = changeset_rem_rrset( param->changeset, &rrset); if (ret != KNOT_EOK) { return ret; } } else { /* Diff RRSets. */ int ret = knot_zone_diff_rrsets(&rrset, &rrset_from_second_node, param->changeset); if (ret != KNOT_EOK) { return ret; } } } for (unsigned i = 0; i < node_in_second_tree->rrset_count; i++) { /* Search for the RRSet in the node from the second tree. */ knot_rrset_t rrset = node_rrset_at(node_in_second_tree, i); /* SOAs are handled explicitely. */ if (rrset.type == KNOT_RRTYPE_SOA) { continue; } knot_rrset_t rrset_from_first_node = node_rrset(node, rrset.type); if (knot_rrset_empty(&rrset_from_first_node)) { /* RRSet has been added. Make a copy and add. */ int ret = changeset_add_rrset( param->changeset, &rrset); if (ret != KNOT_EOK) { return ret; } } } return KNOT_EOK; }