From f449f278dd3c70e479a035f50a9bb817a9b433ba Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 17:24:08 +0200 Subject: Adding upstream version 3.2.6. Signed-off-by: Daniel Baumann --- src/knot/nameserver/xfr.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/knot/nameserver/xfr.c (limited to 'src/knot/nameserver/xfr.c') diff --git a/src/knot/nameserver/xfr.c b/src/knot/nameserver/xfr.c new file mode 100644 index 0000000..b54a4ff --- /dev/null +++ b/src/knot/nameserver/xfr.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2018 CZ.NIC, z.s.p.o. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ + +#include "knot/nameserver/xfr.h" +#include "contrib/mempattern.h" + +int xfr_process_list(knot_pkt_t *pkt, xfr_put_cb put, knotd_qdata_t *qdata) +{ + if (pkt == NULL || qdata == NULL || qdata->extra->ext == NULL) { + return KNOT_EINVAL; + } + + int ret = KNOT_EOK; + knot_mm_t *mm = qdata->mm; + struct xfr_proc *xfer = qdata->extra->ext; + + /* Check if the zone wasn't expired during multi-message transfer. */ + const zone_contents_t *contents = qdata->extra->contents; + if (contents == NULL) { + return KNOT_ENOZONE; + } + knot_rrset_t soa_rr = node_rrset(contents->apex, KNOT_RRTYPE_SOA); + + /* Prepend SOA on first packet. */ + if (xfer->stats.messages == 0) { + ret = knot_pkt_put(pkt, 0, &soa_rr, KNOT_PF_NOTRUNC); + if (ret != KNOT_EOK) { + return ret; + } + } + + /* Process all items in the list. */ + while (!EMPTY_LIST(xfer->nodes)) { + ptrnode_t *head = HEAD(xfer->nodes); + ret = put(pkt, head->d, xfer); + if (ret == KNOT_EOK) { /* Finished. */ + /* Complete change set. */ + rem_node((node_t *)head); + mm_free(mm, head); + } else { /* Packet full or other error. */ + break; + } + } + + /* Append SOA on last packet. */ + if (ret == KNOT_EOK) { + ret = knot_pkt_put(pkt, 0, &soa_rr, KNOT_PF_NOTRUNC); + } + + /* Update counters. */ + xfr_stats_add(&xfer->stats, pkt->size + knot_rrset_size(&qdata->opt_rr)); + + /* If a rrset is larger than the message, + * fail to avoid infinite loop of empty messages */ + if (ret == KNOT_ESPACE && pkt->rrset_count < 1) { + return KNOT_ENOXFR; + } + + return ret; +} + +void xfr_stats_begin(struct xfr_stats *stats) +{ + assert(stats); + + memset(stats, 0, sizeof(*stats)); + stats->begin = time_now(); +} + +void xfr_stats_add(struct xfr_stats *stats, unsigned bytes) +{ + assert(stats); + + stats->messages += 1; + stats->bytes += bytes; +} + +void xfr_stats_end(struct xfr_stats *stats) +{ + assert(stats); + + stats->end = time_now(); +} -- cgit v1.2.3