mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Merge branch '3883-expose-data-about-transfers-in-progress' into 'main'
Draft: Implement exposing data about zone transfers in progress Closes #3883 See merge request isc-projects/bind9!7984
This commit is contained in:
commit
2eb8afde52
14 changed files with 1098 additions and 51 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
6255. [func] Expose data about incoming zone transfers in progress
|
||||
using statistics channel. [GL #3883]
|
||||
|
||||
6254. [cleanup] Add semantic patch to do an explicit cast from char
|
||||
to unsigned char in ctype.h class of functions.
|
||||
[GL #4327]
|
||||
|
|
|
|||
|
|
@ -303,6 +303,7 @@
|
|||
<a href="/xml/v3/status">Status</a>,
|
||||
<a href="/xml/v3/server">Server</a>,
|
||||
<a href="/xml/v3/zones">Zones</a>,
|
||||
<a href="/xml/v3/xfrins">Incoming Zone Transfers</a>,
|
||||
<a href="/xml/v3/net">Network</a>,
|
||||
<a href="/xml/v3/mem">Memory</a> and
|
||||
<a href="/xml/v3/traffic">Traffic Size</a></p>
|
||||
|
|
@ -907,6 +908,59 @@
|
|||
</xsl:for-each>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:if test="views/view/xfrins/xfrin">
|
||||
<xsl:for-each select="views/view">
|
||||
<h3>Incoming Zone Transfers for View <xsl:value-of select="@name"/></h3>
|
||||
<table class="xfrins">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Zone Name</th>
|
||||
<th>Zone Type</th>
|
||||
<th>Local Serial</th>
|
||||
<th>Remote Serial</th>
|
||||
<th>IXFR</th>
|
||||
<th>State</th>
|
||||
<th>Additional Refresh Queued</th>
|
||||
<th>Local Address</th>
|
||||
<th>Remote Address</th>
|
||||
<th>Transport</th>
|
||||
<th>TSIG Key Name</th>
|
||||
<th>Duration (s)</th>
|
||||
<th>Messages Received</th>
|
||||
<th>Records Received</th>
|
||||
<th>Bytes Received</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<xsl:for-each select="xfrins/xfrin">
|
||||
<xsl:variable name="css-class16">
|
||||
<xsl:choose>
|
||||
<xsl:when test="position() mod 2 = 0">even</xsl:when>
|
||||
<xsl:otherwise>odd</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:variable>
|
||||
<tr class="{$css-class16}">
|
||||
<td><xsl:value-of select="@name"/></td>
|
||||
<td><xsl:value-of select="type"/></td>
|
||||
<td><xsl:value-of select="serial"/></td>
|
||||
<td><xsl:value-of select="remoteserial"/></td>
|
||||
<td><xsl:value-of select="ixfr"/></td>
|
||||
<td><xsl:value-of select="state"/></td>
|
||||
<td><xsl:value-of select="refreshqueued"/></td>
|
||||
<td><xsl:value-of select="localaddr"/></td>
|
||||
<td><xsl:value-of select="remoteaddr"/></td>
|
||||
<td><xsl:value-of select="transport"/></td>
|
||||
<td><xsl:value-of select="tsigkeyname"/></td>
|
||||
<td><xsl:value-of select="duration"/></td>
|
||||
<td><xsl:value-of select="nmsg"/></td>
|
||||
<td><xsl:value-of select="nrecs"/></td>
|
||||
<td><xsl:value-of select="nbytes"/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</tbody>
|
||||
</table>
|
||||
</xsl:for-each>
|
||||
</xsl:if>
|
||||
<xsl:if test="memory/summary">
|
||||
<h2>Memory Usage Summary</h2>
|
||||
<table class="counters">
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@
|
|||
#include <dns/rdatatype.h>
|
||||
#include <dns/resolver.h>
|
||||
#include <dns/stats.h>
|
||||
#include <dns/transport.h>
|
||||
#include <dns/view.h>
|
||||
#include <dns/xfrin.h>
|
||||
#include <dns/zt.h>
|
||||
|
||||
#include <ns/stats.h>
|
||||
|
|
@ -1264,6 +1266,7 @@ cleanup:
|
|||
#define STATS_XML_STATUS 0x00 /* display only common statistics */
|
||||
#define STATS_XML_SERVER 0x01
|
||||
#define STATS_XML_ZONES 0x02
|
||||
#define STATS_XML_XFRINS 0x04
|
||||
#define STATS_XML_NET 0x08
|
||||
#define STATS_XML_MEM 0x10
|
||||
#define STATS_XML_TRAFFIC 0x20
|
||||
|
|
@ -1449,6 +1452,221 @@ cleanup:
|
|||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
xfrin_xmlrender(dns_zone_t *zone, void *arg) {
|
||||
isc_result_t result;
|
||||
char buf[1024 + 32]; /* sufficiently large for zone name and class */
|
||||
dns_rdataclass_t rdclass;
|
||||
const char *ztype;
|
||||
uint32_t serial;
|
||||
const isc_sockaddr_t *addrp = NULL;
|
||||
char addr_buf[ISC_SOCKADDR_FORMATSIZE];
|
||||
const dns_transport_t *transport = NULL;
|
||||
xmlTextWriterPtr writer = arg;
|
||||
dns_zonestat_level_t statlevel;
|
||||
int xmlrc;
|
||||
dns_xfrin_t *xfr = NULL;
|
||||
bool is_running, is_deferred, is_pending;
|
||||
bool needs_refresh;
|
||||
bool is_first_data_received, is_ixfr;
|
||||
unsigned int nmsg = 0;
|
||||
unsigned int nrecs = 0;
|
||||
uint64_t nbytes = 0;
|
||||
|
||||
statlevel = dns_zone_getstatlevel(zone);
|
||||
if (statlevel == dns_zonestat_none) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
result = dns_zone_getxfr(zone, &xfr, &is_running, &is_deferred,
|
||||
&is_pending, &needs_refresh);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!is_running && !is_deferred && !is_pending && !needs_refresh) {
|
||||
/* No ongoing/queued transfer. */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (is_running && xfr == NULL) {
|
||||
/* The transfer is finished, and it's shutting down. */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "xfrin"));
|
||||
|
||||
dns_zone_nameonly(zone, buf, sizeof(buf));
|
||||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "name",
|
||||
ISC_XMLCHAR buf));
|
||||
|
||||
rdclass = dns_zone_getclass(zone);
|
||||
dns_rdataclass_format(rdclass, buf, sizeof(buf));
|
||||
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "class",
|
||||
ISC_XMLCHAR buf));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "type"));
|
||||
ztype = user_zonetype(zone);
|
||||
if (ztype != NULL) {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ztype));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "serial"));
|
||||
if (dns_zone_getserial(zone, &serial) == ISC_R_SUCCESS) {
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%u", serial));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "remoteserial"));
|
||||
if (is_running) {
|
||||
serial = dns_xfrin_getendserial(xfr);
|
||||
if (serial != 0) {
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%u",
|
||||
serial));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "state"));
|
||||
if (is_running) {
|
||||
const char *xfr_state = NULL;
|
||||
|
||||
dns_xfrin_getstate(xfr, &xfr_state, &is_first_data_received,
|
||||
&is_ixfr);
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR xfr_state));
|
||||
} else if (is_deferred) {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "Deferred"));
|
||||
} else if (is_pending) {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "Pending"));
|
||||
} else if (needs_refresh) {
|
||||
TRY0(xmlTextWriterWriteString(writer,
|
||||
ISC_XMLCHAR "Needs Refresh"));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "refreshqueued"));
|
||||
TRY0(xmlTextWriterWriteString(
|
||||
writer, ISC_XMLCHAR(needs_refresh ? "Yes" : "No")));
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "localaddr"));
|
||||
if (is_running) {
|
||||
addrp = dns_xfrin_getsourceaddr(xfr);
|
||||
isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf));
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "remoteaddr"));
|
||||
if (is_running) {
|
||||
addrp = dns_xfrin_getprimaryaddr(xfr);
|
||||
isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf));
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR addr_buf));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "transport"));
|
||||
if (is_running) {
|
||||
transport = dns_xfrin_gettransport(xfr);
|
||||
if (transport == NULL ||
|
||||
dns_transport_get_type(transport) == DNS_TRANSPORT_TCP)
|
||||
{
|
||||
TRY0(xmlTextWriterWriteString(writer,
|
||||
ISC_XMLCHAR "TCP"));
|
||||
} else if (dns_transport_get_type(transport) ==
|
||||
DNS_TRANSPORT_TLS)
|
||||
{
|
||||
TRY0(xmlTextWriterWriteString(writer,
|
||||
ISC_XMLCHAR "TLS"));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "-"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tsigkeyname"));
|
||||
if (is_running) {
|
||||
const dns_name_t *tsigkeyname = dns_xfrin_gettsigkeyname(xfr);
|
||||
char tsigkeyname_buf[DNS_NAME_FORMATSIZE];
|
||||
|
||||
if (tsigkeyname != NULL) {
|
||||
dns_name_format(tsigkeyname, tsigkeyname_buf,
|
||||
sizeof(tsigkeyname_buf));
|
||||
TRY0(xmlTextWriterWriteString(
|
||||
writer, ISC_XMLCHAR tsigkeyname_buf));
|
||||
}
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "duration"));
|
||||
if (is_running) {
|
||||
isc_time_t start = dns_xfrin_getstarttime(xfr);
|
||||
isc_time_t now = isc_time_now();
|
||||
isc_time_t diff;
|
||||
uint32_t sec;
|
||||
|
||||
isc_time_subtract(&now, &start, &diff);
|
||||
sec = isc_time_seconds(&diff);
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu32, sec));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR "0"));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
if (is_running) {
|
||||
dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes);
|
||||
}
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nmsg"));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%u", nmsg));
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nrecs"));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%u", nrecs));
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "nbytes"));
|
||||
TRY0(xmlTextWriterWriteFormatString(writer, "%" PRIu64, nbytes));
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ixfr"));
|
||||
if (is_running && is_first_data_received) {
|
||||
TRY0(xmlTextWriterWriteString(
|
||||
writer, ISC_XMLCHAR(is_ixfr ? "Yes" : "No")));
|
||||
} else {
|
||||
TRY0(xmlTextWriterWriteString(writer, ISC_XMLCHAR ""));
|
||||
}
|
||||
TRY0(xmlTextWriterEndElement(writer));
|
||||
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* xfrin */
|
||||
|
||||
cleanup:
|
||||
if (xfr != NULL) {
|
||||
dns_xfrin_detach(&xfr);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"Failed at xfrin_xmlrender()");
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
||||
xmlChar **buf) {
|
||||
|
|
@ -1727,8 +1945,8 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
*/
|
||||
view = ISC_LIST_HEAD(server->viewlist);
|
||||
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "views"));
|
||||
while (view != NULL &&
|
||||
((flags & (STATS_XML_SERVER | STATS_XML_ZONES)) != 0))
|
||||
while (view != NULL && ((flags & (STATS_XML_SERVER | STATS_XML_ZONES |
|
||||
STATS_XML_XFRINS)) != 0))
|
||||
{
|
||||
isc_stats_t *istats = NULL;
|
||||
dns_stats_t *dstats = NULL;
|
||||
|
|
@ -1746,6 +1964,14 @@ generatexml(named_server_t *server, uint32_t flags, int *buflen,
|
|||
TRY0(xmlTextWriterEndElement(writer)); /* /zones */
|
||||
}
|
||||
|
||||
if ((flags & STATS_XML_XFRINS) != 0) {
|
||||
TRY0(xmlTextWriterStartElement(writer,
|
||||
ISC_XMLCHAR "xfrins"));
|
||||
CHECK(dns_zt_apply(view->zonetable, true, NULL,
|
||||
xfrin_xmlrender, writer));
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* /xfrins */
|
||||
}
|
||||
|
||||
if ((flags & STATS_XML_SERVER) == 0) {
|
||||
TRY0(xmlTextWriterEndElement(writer)); /* /view */
|
||||
view = ISC_LIST_NEXT(view, link);
|
||||
|
|
@ -1934,6 +2160,17 @@ render_xml_zones(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
|||
freecb, freecb_args));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
render_xml_xfrins(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
||||
void *arg, unsigned int *retcode, const char **retmsg,
|
||||
const char **mimetype, isc_buffer_t *b,
|
||||
isc_httpdfree_t **freecb, void **freecb_args) {
|
||||
UNUSED(httpd);
|
||||
UNUSED(urlinfo);
|
||||
return (render_xml(STATS_XML_XFRINS, arg, retcode, retmsg, mimetype, b,
|
||||
freecb, freecb_args));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
render_xml_net(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
||||
void *arg, unsigned int *retcode, const char **retmsg,
|
||||
|
|
@ -1976,6 +2213,7 @@ render_xml_traffic(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
|||
#define STATS_JSON_STATUS 0x00 /* display only common statistics */
|
||||
#define STATS_JSON_SERVER 0x01
|
||||
#define STATS_JSON_ZONES 0x02
|
||||
#define STATS_JSON_XFRINS 0x04
|
||||
#define STATS_JSON_NET 0x08
|
||||
#define STATS_JSON_MEM 0x10
|
||||
#define STATS_JSON_TRAFFIC 0x20
|
||||
|
|
@ -2226,6 +2464,211 @@ cleanup:
|
|||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
xfrin_jsonrender(dns_zone_t *zone, void *arg) {
|
||||
isc_result_t result;
|
||||
char buf[1024 + 32]; /* sufficiently large for zone name and class */
|
||||
char classbuf[64]; /* sufficiently large for class */
|
||||
char *zone_name_only = NULL;
|
||||
char *class_only = NULL;
|
||||
dns_rdataclass_t rdclass;
|
||||
uint32_t serial;
|
||||
json_object *xfrinarray = (json_object *)arg;
|
||||
json_object *xfrinobj = NULL;
|
||||
const isc_sockaddr_t *addrp = NULL;
|
||||
char addr_buf[ISC_SOCKADDR_FORMATSIZE];
|
||||
const dns_transport_t *transport = NULL;
|
||||
dns_zonestat_level_t statlevel;
|
||||
dns_xfrin_t *xfr = NULL;
|
||||
bool is_running, is_deferred, is_pending;
|
||||
bool needs_refresh;
|
||||
bool is_first_data_received, is_ixfr;
|
||||
unsigned int nmsg = 0;
|
||||
unsigned int nrecs = 0;
|
||||
uint64_t nbytes = 0;
|
||||
|
||||
statlevel = dns_zone_getstatlevel(zone);
|
||||
if (statlevel == dns_zonestat_none) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
dns_zone_nameonly(zone, buf, sizeof(buf));
|
||||
zone_name_only = buf;
|
||||
|
||||
rdclass = dns_zone_getclass(zone);
|
||||
dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
|
||||
class_only = classbuf;
|
||||
|
||||
if (dns_zone_getserial(zone, &serial) != ISC_R_SUCCESS) {
|
||||
xfrinobj = addzone(zone_name_only, class_only,
|
||||
user_zonetype(zone), 0, false);
|
||||
} else {
|
||||
xfrinobj = addzone(zone_name_only, class_only,
|
||||
user_zonetype(zone), serial, true);
|
||||
}
|
||||
|
||||
if (xfrinobj == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = dns_zone_getxfr(zone, &xfr, &is_running, &is_deferred,
|
||||
&is_pending, &needs_refresh);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!is_running && !is_deferred && !is_pending && !needs_refresh) {
|
||||
/* No ongoing/queued transfer. */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (is_running && xfr == NULL) {
|
||||
/* The transfer is finished, and it's shutting down. */
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
serial = dns_xfrin_getendserial(xfr);
|
||||
if (serial != 0) {
|
||||
json_object_object_add(xfrinobj, "remoteserial",
|
||||
json_object_new_int64(serial));
|
||||
}
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
const char *xfr_state = NULL;
|
||||
|
||||
dns_xfrin_getstate(xfr, &xfr_state, &is_first_data_received,
|
||||
&is_ixfr);
|
||||
json_object_object_add(xfrinobj, "state",
|
||||
json_object_new_string(xfr_state));
|
||||
} else if (is_deferred) {
|
||||
json_object_object_add(xfrinobj, "state",
|
||||
json_object_new_string("Deferred"));
|
||||
} else if (is_pending) {
|
||||
json_object_object_add(xfrinobj, "state",
|
||||
json_object_new_string("Pending"));
|
||||
} else if (needs_refresh) {
|
||||
json_object_object_add(xfrinobj, "state",
|
||||
json_object_new_string("Needs Refresh"));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
json_object_object_add(
|
||||
xfrinobj, "refreshqueued",
|
||||
json_object_new_string(needs_refresh ? "Yes" : "No"));
|
||||
|
||||
if (is_running) {
|
||||
addrp = dns_xfrin_getsourceaddr(xfr);
|
||||
isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf));
|
||||
json_object_object_add(xfrinobj, "localaddr",
|
||||
json_object_new_string(addr_buf));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "localaddr",
|
||||
json_object_new_string("-"));
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
addrp = dns_xfrin_getprimaryaddr(xfr);
|
||||
isc_sockaddr_format(addrp, addr_buf, sizeof(addr_buf));
|
||||
json_object_object_add(xfrinobj, "remoteaddr",
|
||||
json_object_new_string(addr_buf));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "remoteaddr",
|
||||
json_object_new_string("-"));
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
transport = dns_xfrin_gettransport(xfr);
|
||||
if (transport == NULL ||
|
||||
dns_transport_get_type(transport) == DNS_TRANSPORT_TCP)
|
||||
{
|
||||
json_object_object_add(xfrinobj, "transport",
|
||||
json_object_new_string("TCP"));
|
||||
} else if (dns_transport_get_type(transport) ==
|
||||
DNS_TRANSPORT_TLS)
|
||||
{
|
||||
json_object_object_add(xfrinobj, "transport",
|
||||
json_object_new_string("TLS"));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "transport",
|
||||
json_object_new_string("-"));
|
||||
}
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "transport",
|
||||
json_object_new_string("-"));
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
const dns_name_t *tsigkeyname = dns_xfrin_gettsigkeyname(xfr);
|
||||
char tsigkeyname_buf[DNS_NAME_FORMATSIZE];
|
||||
|
||||
if (tsigkeyname != NULL) {
|
||||
dns_name_format(tsigkeyname, tsigkeyname_buf,
|
||||
sizeof(tsigkeyname_buf));
|
||||
json_object_object_add(
|
||||
xfrinobj, "tsigkeyname",
|
||||
json_object_new_string(tsigkeyname_buf));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "tsigkeyname", NULL);
|
||||
}
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "tsigkeyname", NULL);
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
isc_time_t start = dns_xfrin_getstarttime(xfr);
|
||||
isc_time_t now = isc_time_now();
|
||||
isc_time_t diff;
|
||||
uint32_t sec;
|
||||
|
||||
isc_time_subtract(&now, &start, &diff);
|
||||
sec = isc_time_seconds(&diff);
|
||||
json_object_object_add(xfrinobj, "duration",
|
||||
json_object_new_int64((int64_t)sec));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "duration",
|
||||
json_object_new_int64(0));
|
||||
}
|
||||
|
||||
if (is_running) {
|
||||
dns_xfrin_getstats(xfr, &nmsg, &nrecs, &nbytes);
|
||||
}
|
||||
json_object_object_add(xfrinobj, "nmsg",
|
||||
json_object_new_int64((int64_t)nmsg));
|
||||
json_object_object_add(xfrinobj, "nrecs",
|
||||
json_object_new_int64((int64_t)nrecs));
|
||||
json_object_object_add(
|
||||
xfrinobj, "nbytes",
|
||||
json_object_new_int64(nbytes > INT64_MAX ? INT64_MAX
|
||||
: (int64_t)nbytes));
|
||||
|
||||
if (is_running && is_first_data_received) {
|
||||
json_object_object_add(
|
||||
xfrinobj, "ixfr",
|
||||
json_object_new_string(is_ixfr ? "Yes" : "No"));
|
||||
} else {
|
||||
json_object_object_add(xfrinobj, "ixfr",
|
||||
json_object_new_string(""));
|
||||
}
|
||||
|
||||
json_object_array_add(xfrinarray, xfrinobj);
|
||||
xfrinobj = NULL;
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (xfr != NULL) {
|
||||
dns_xfrin_detach(&xfr);
|
||||
}
|
||||
if (xfrinobj != NULL) {
|
||||
json_object_put(xfrinobj);
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
||||
json_object **rootp, uint32_t flags) {
|
||||
|
|
@ -2444,7 +2887,9 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
#endif /* ifdef HAVE_DNSTAP */
|
||||
}
|
||||
|
||||
if ((flags & (STATS_JSON_ZONES | STATS_JSON_SERVER)) != 0) {
|
||||
if ((flags &
|
||||
(STATS_JSON_SERVER | STATS_JSON_ZONES | STATS_JSON_XFRINS)) != 0)
|
||||
{
|
||||
viewlist = json_object_new_object();
|
||||
CHECKMEM(viewlist);
|
||||
|
||||
|
|
@ -2452,7 +2897,7 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
|
||||
view = ISC_LIST_HEAD(server->viewlist);
|
||||
while (view != NULL) {
|
||||
json_object *za, *v = json_object_new_object();
|
||||
json_object *za, *xa, *v = json_object_new_object();
|
||||
dns_adb_t *adb = NULL;
|
||||
|
||||
CHECKMEM(v);
|
||||
|
|
@ -2472,6 +2917,20 @@ generatejson(named_server_t *server, size_t *msglen, const char **msg,
|
|||
json_object_put(za);
|
||||
}
|
||||
|
||||
xa = json_object_new_array();
|
||||
CHECKMEM(xa);
|
||||
|
||||
if ((flags & STATS_JSON_XFRINS) != 0) {
|
||||
CHECK(dns_zt_apply(view->zonetable, true, NULL,
|
||||
xfrin_jsonrender, xa));
|
||||
}
|
||||
|
||||
if (json_object_array_length(xa) != 0) {
|
||||
json_object_object_add(v, "xfrins", xa);
|
||||
} else {
|
||||
json_object_put(xa);
|
||||
}
|
||||
|
||||
if ((flags & STATS_JSON_SERVER) != 0) {
|
||||
json_object *res = NULL;
|
||||
dns_stats_t *dstats = NULL;
|
||||
|
|
@ -2855,6 +3314,17 @@ render_json_zones(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
|||
freecb, freecb_args));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
render_json_xfrins(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
||||
void *arg, unsigned int *retcode, const char **retmsg,
|
||||
const char **mimetype, isc_buffer_t *b,
|
||||
isc_httpdfree_t **freecb, void **freecb_args) {
|
||||
UNUSED(httpd);
|
||||
UNUSED(urlinfo);
|
||||
return (render_json(STATS_JSON_XFRINS, arg, retcode, retmsg, mimetype,
|
||||
b, freecb, freecb_args));
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
render_json_mem(const isc_httpd_t *httpd, const isc_httpdurl_t *urlinfo,
|
||||
void *arg, unsigned int *retcode, const char **retmsg,
|
||||
|
|
@ -3060,6 +3530,9 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp,
|
|||
isc_httpdmgr_addurl(listener->httpdmgr,
|
||||
"/xml/v" STATS_XML_VERSION_MAJOR "/zones", false,
|
||||
render_xml_zones, server);
|
||||
isc_httpdmgr_addurl(listener->httpdmgr,
|
||||
"/xml/v" STATS_XML_VERSION_MAJOR "/xfrins", false,
|
||||
render_xml_xfrins, server);
|
||||
isc_httpdmgr_addurl(listener->httpdmgr,
|
||||
"/xml/v" STATS_XML_VERSION_MAJOR "/net", false,
|
||||
render_xml_net, server);
|
||||
|
|
@ -3085,6 +3558,9 @@ add_listener(named_server_t *server, named_statschannel_t **listenerp,
|
|||
isc_httpdmgr_addurl(listener->httpdmgr,
|
||||
"/json/v" STATS_JSON_VERSION_MAJOR "/zones", false,
|
||||
render_json_zones, server);
|
||||
isc_httpdmgr_addurl(listener->httpdmgr,
|
||||
"/json/v" STATS_JSON_VERSION_MAJOR "/xfrins", false,
|
||||
render_json_xfrins, server);
|
||||
isc_httpdmgr_addurl(listener->httpdmgr,
|
||||
"/json/v" STATS_JSON_VERSION_MAJOR "/net", false,
|
||||
render_json_net, server);
|
||||
|
|
|
|||
|
|
@ -32,4 +32,5 @@ rm -f traffic traffic.out.* traffic.json.* traffic.xml.*
|
|||
rm -f xml.*mem json.*mem
|
||||
rm -f xml.*stats json.*stats
|
||||
rm -f zones zones.out.* zones.json.* zones.xml.* zones.expect.*
|
||||
rm -f xfrins xfrins.json.* xfrins.xml.*
|
||||
rm -rf ./__pycache__
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ controls {
|
|||
inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
server 10.53.0.3 {
|
||||
transfer-format one-answer;
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
type primary;
|
||||
file "example.db";
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ set -e
|
|||
|
||||
DIGCMD="$DIG @10.53.0.2 -p ${PORT}"
|
||||
RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s"
|
||||
NS_PARAMS="-X named.lock -m record -c named.conf -d 99 -g -U 4 -T maxcachesize=2097152"
|
||||
|
||||
if ! $FEATURETEST --have-json-c
|
||||
then
|
||||
|
|
@ -48,6 +49,32 @@ if [ ! "$PERL_JSON" ] && [ ! "$PERL_XML" ]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
retry_quiet_fast() {
|
||||
__retries="${1}"
|
||||
shift
|
||||
|
||||
while :; do
|
||||
if "$@"; then
|
||||
return 0
|
||||
fi
|
||||
__retries=$((__retries-1))
|
||||
if [ "${__retries}" -gt 0 ]; then
|
||||
# sleep for 0.1 seconds
|
||||
perl -e 'select(undef, undef, undef, .1)'
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
wait_for_log_fast() (
|
||||
timeout="$1"
|
||||
msg="$2"
|
||||
file="$3"
|
||||
retry_quiet_fast "$timeout" _search_log "$msg" "$file" && return 0
|
||||
echo_i "exceeded time limit waiting for literal '$msg' in $file"
|
||||
return 1
|
||||
)
|
||||
|
||||
getzones() {
|
||||
sleep 1
|
||||
|
|
@ -63,6 +90,19 @@ getzones() {
|
|||
return $result
|
||||
}
|
||||
|
||||
getxfrins() {
|
||||
echo_i "... using $1"
|
||||
case $1 in
|
||||
xml) path='xml/v3/xfrins' ;;
|
||||
json) path='json/v1/xfrins' ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
file=`$PERL fetch.pl -s 10.53.0.3 -p ${EXTRAPORT1} $path`
|
||||
cp $file $file.$1.$3
|
||||
result=$?
|
||||
return $result
|
||||
}
|
||||
|
||||
# TODO: Move loadkeys_on to conf.sh.common
|
||||
loadkeys_on() {
|
||||
nsidx=$1
|
||||
|
|
@ -655,5 +695,38 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
|||
status=$((status + ret))
|
||||
n=$((n + 1))
|
||||
|
||||
echo_i "Retransfering 'example' from ns1 to ns3 in slow mode ($n)"
|
||||
ret=0
|
||||
i=0
|
||||
# Restart ns1 with '-T transferslowly' to see the xfrins information in ns3's statschannel while it's ongoing
|
||||
stop_server ns1
|
||||
start_server --noclean --restart --port ${PORT} ns1 -- "-D statschannel-ns1 $NS_PARAMS -T transferslowly"
|
||||
# Request a retransfer of the "example" zone
|
||||
nextpart ns3/named.run > /dev/null
|
||||
$RNDCCMD 10.53.0.3 retransfer example | sed "s/^/ns3 /" | cat_i
|
||||
wait_for_log_fast 200 "zone example/IN: Transfer started" ns3/named.run || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
n=$((n + 1))
|
||||
|
||||
# We have now less than one second to catch the zone transfer in process
|
||||
echo_i "Checking zone transfer information in the statistics channel ($n)"
|
||||
ret=0
|
||||
i=0
|
||||
getxfrins xml example x$n || ret=1
|
||||
getxfrins json example j$n || ret=1
|
||||
grep -F '<state>Initial SOA</state>' xfrins.xml.x$n >/dev/null || ret=1
|
||||
grep -F '"state":"Initial SOA"' xfrins.json.j$n >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
n=$((n + 1))
|
||||
|
||||
echo_i "Wait for slow zone transfer to complete ($n)"
|
||||
ret=0
|
||||
wait_for_log 20 "zone example/IN: zone transfer finished: success" ns3/named.run || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
n=$((n + 1))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
|
|
|||
|
|
@ -1932,7 +1932,8 @@ default is used.
|
|||
operations and the number of authoritative answers per query type. The
|
||||
default is ``terse``, providing minimal statistics on zones
|
||||
(including name and current serial number, but not query type
|
||||
counters).
|
||||
counters), and also information about the currently ongoing incoming zone
|
||||
transfers.
|
||||
|
||||
These statistics may be accessed via the ``statistics-channel`` or
|
||||
using :option:`rndc stats`, which dumps them to the file listed in the
|
||||
|
|
@ -5655,6 +5656,7 @@ Broken-out subsets of the statistics can be viewed at
|
|||
http://127.0.0.1:8888/xml/v3/status (server uptime and last
|
||||
reconfiguration time), http://127.0.0.1:8888/xml/v3/server (server and
|
||||
resolver statistics), http://127.0.0.1:8888/xml/v3/zones (zone
|
||||
statistics), http://127.0.0.1:8888/xml/v3/xfrins (incoming zone transfer
|
||||
statistics), http://127.0.0.1:8888/xml/v3/net (network status and socket
|
||||
statistics), http://127.0.0.1:8888/xml/v3/mem (memory manager
|
||||
statistics), and http://127.0.0.1:8888/xml/v3/traffic (traffic sizes).
|
||||
|
|
@ -5664,6 +5666,7 @@ http://127.0.0.1:8888/json, with the broken-out subsets at
|
|||
http://127.0.0.1:8888/json/v1/status (server uptime and last
|
||||
reconfiguration time), http://127.0.0.1:8888/json/v1/server (server and
|
||||
resolver statistics), http://127.0.0.1:8888/json/v1/zones (zone
|
||||
statistics), http://127.0.0.1:8888/json/v1/xfrins (incoming zone transfer
|
||||
statistics), http://127.0.0.1:8888/json/v1/net (network status and
|
||||
socket statistics), http://127.0.0.1:8888/json/v1/mem (memory manager
|
||||
statistics), and http://127.0.0.1:8888/json/v1/traffic (traffic sizes).
|
||||
|
|
@ -7535,6 +7538,146 @@ Outgoing Queries
|
|||
The number of outgoing queries for each RR type sent from the internal
|
||||
resolver, maintained per view.
|
||||
|
||||
Incoming Zone Transfers
|
||||
Information about in-progress incoming zone transfers.
|
||||
|
||||
This section describes the information, which can be seen in the
|
||||
HTML table about in-progress incoming zone transfers. It lists
|
||||
the meaning, units and possible range of values of each column,
|
||||
and the key/attribute/element name (in parentheses) for the JSON
|
||||
and XML output formats.
|
||||
|
||||
``Zone Name`` (``name``)
|
||||
Text string. This is the name of the zone being transferred,
|
||||
as specified in the :any:`zone` declaration on this server.
|
||||
|
||||
``Zone Type`` (``type``)
|
||||
Text string. This is the type of zone being transferred, as
|
||||
specified in the ``zone`` declaration on this server. Possible
|
||||
values are: ``secondary``, ``stub``, ``redirect``, ``mirror``.
|
||||
|
||||
``Local Serial`` (``serial``)
|
||||
32 bit unsigned Integer. This is the current (old) serial
|
||||
number of the zone being transferred. It comes from the SOA
|
||||
record held on the current server.
|
||||
|
||||
``Remote Serial`` (``remoteserial``)
|
||||
32 bit unsigned Integer. This is the new serial number of the
|
||||
zone being transferred. It comes from the SOA record held on
|
||||
the primary server from which the zone is being transferred.
|
||||
|
||||
``IXFR`` (``ixfr``)
|
||||
Boolean. This says whether the transfer is incremental (using
|
||||
IXFR) or full (using AXFR). Possible values are: ``Yes``,
|
||||
``No``.
|
||||
|
||||
``State`` (``state``)
|
||||
Text string. This is the current state of the transfer for
|
||||
this zone. Possible values and their meanings are:
|
||||
|
||||
``Needs Refresh``
|
||||
The zone is flagged for a refresh, but the process
|
||||
hasn't started yet.
|
||||
|
||||
``Pending``
|
||||
The zone is flagged for a refresh, but the process is
|
||||
in waiting state because of rate-limiting, see
|
||||
:any:`serial-query-rate`.
|
||||
|
||||
``Deferred``
|
||||
The zone is going to be refreshed, but the process was
|
||||
deferred due to quota, see :any:`transfers-in` and
|
||||
:any:`transfers-per-ns`.
|
||||
|
||||
``SOA Query``
|
||||
Sending SOA query to get the zone serial number, then
|
||||
follow with a zone transfer, if necessary.
|
||||
|
||||
``Got SOA``
|
||||
An answer for the SOA query from the previous step is
|
||||
received, initiating a transfer.
|
||||
|
||||
``Initial SOA``
|
||||
Waiting for the transfer to start, which is expected
|
||||
to begin with an initial SOA record.
|
||||
|
||||
``First Data``
|
||||
Waiting for the first data record of the transfer.
|
||||
|
||||
``Receiving IXFR Data``
|
||||
Receiving data for an IXFR type incremental zone
|
||||
transfer.
|
||||
|
||||
``Finalizing IXFR``
|
||||
Finalizing an IXFR type incremental zone transfer.
|
||||
|
||||
``Receiving AXFR Data``
|
||||
Receiving data for an AXFR type zone transfer.
|
||||
|
||||
``Finalizing AXFR``
|
||||
Finalizing an AXFR type zone transfer.
|
||||
|
||||
.. note::
|
||||
State names can change between BIND versions.
|
||||
|
||||
``Additional Refresh Queued`` (``refreshqueued``)
|
||||
Boolean. This shows that the zone is flagged for a refresh.
|
||||
This can be set to ``Yes`` either when the zone transfer is
|
||||
still in one of the pending states (see the description of
|
||||
the ``State`` column), or when the transfer is in a running
|
||||
state, but the zone was marked for another refresh again (e.g.
|
||||
because of "notify" request from a primary server). Possible
|
||||
values are: ``Yes``, ``No``.
|
||||
|
||||
``Local Address`` (``localaddr``)
|
||||
IP address - IPv4 or IPv6, as appropriate, and port number.
|
||||
This shows the source address used to establish the connection
|
||||
for the transfer.
|
||||
|
||||
``Remote Address`` (``remoteaddr``)
|
||||
IP address - IPv4 or IPv6, as appropriate, and port number.
|
||||
This shows the destination address used to establish the
|
||||
connection for the transfer.
|
||||
|
||||
``Transport`` (``transport``)
|
||||
Text string. This is the transport protocol in use for the
|
||||
transfer. Possible values are: ``TCP``, ``TLS``.
|
||||
|
||||
``TSIG Key Name`` (``tsigkeyname``)
|
||||
Text string. This is the name of the TSIG key specified for
|
||||
use with this zone in the :any:`zone` declaration (if any).
|
||||
|
||||
``Duration (s)`` (``duration``)
|
||||
64 bit unsigned Integer. This is the time, in seconds, that
|
||||
the transfer has been running so far. The clock starts after
|
||||
the zone transfer process is initialized, and restarts shortly
|
||||
after, when transport connection has been established and the
|
||||
XFR request has been sent.
|
||||
|
||||
``Messages Received`` (``nmsg``)
|
||||
64 bit unsigned Integer. This is the number of DNS messages
|
||||
received. It does not include transport overheads, such as
|
||||
TCP ACK.
|
||||
|
||||
``Records Received`` (``nrecs``)
|
||||
64 bit unsigned Integer. This is the number of individual RRs
|
||||
received so far. If an address record has, for example, five
|
||||
addresses associated with the same name, it counts as five
|
||||
RRs.
|
||||
|
||||
``Bytes Received`` (``nbytes``)
|
||||
64 bit unsigned Integer. This is the number of usable bytes
|
||||
of DNS data. It does not include transport overhead.
|
||||
|
||||
.. note::
|
||||
Depending on the current state of the transfer, some of the
|
||||
values may be empty or set to ``-`` (meaning "not available").
|
||||
Also, in the case of the JSON output format, the corresponding
|
||||
keys can be missing or values can be set to ``NULL``. For
|
||||
example, it isn't known whether a transfer is using AXFR or
|
||||
IXFR until the first data is received (see the description
|
||||
of the ``State`` column).
|
||||
|
||||
Name Server Statistics
|
||||
Statistics counters for incoming request processing.
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ Security Fixes
|
|||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
- The statstics channel now includes information about incoming zone transfers
|
||||
currently in progress. :gl:`#3883`
|
||||
|
||||
- The new :any:`resolver-use-dns64` option enables ``named`` to apply
|
||||
:any:`dns64` rules to IPv4 server addresses when sending recursive
|
||||
|
|
|
|||
|
|
@ -40,23 +40,23 @@ dns_transport_new(const dns_name_t *name, dns_transport_type_t type,
|
|||
*/
|
||||
|
||||
dns_transport_type_t
|
||||
dns_transport_get_type(dns_transport_t *transport);
|
||||
dns_transport_get_type(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_certfile(dns_transport_t *transport);
|
||||
dns_transport_get_certfile(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_keyfile(dns_transport_t *transport);
|
||||
dns_transport_get_keyfile(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_cafile(dns_transport_t *transport);
|
||||
dns_transport_get_cafile(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_remote_hostname(dns_transport_t *transport);
|
||||
dns_transport_get_remote_hostname(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_endpoint(dns_transport_t *transport);
|
||||
dns_transport_get_endpoint(const dns_transport_t *transport);
|
||||
dns_http_mode_t
|
||||
dns_transport_get_mode(dns_transport_t *transport);
|
||||
dns_transport_get_mode(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_ciphers(dns_transport_t *transport);
|
||||
dns_transport_get_ciphers(const dns_transport_t *transport);
|
||||
char *
|
||||
dns_transport_get_tlsname(dns_transport_t *transport);
|
||||
dns_transport_get_tlsname(const dns_transport_t *transport);
|
||||
uint32_t
|
||||
dns_transport_get_tls_versions(const dns_transport_t *transport);
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/sockaddr.h>
|
||||
#include <isc/tls.h>
|
||||
|
||||
#include <dns/transport.h>
|
||||
|
|
@ -82,6 +83,109 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
|
|||
* the zone has a database.
|
||||
*/
|
||||
|
||||
isc_time_t
|
||||
dns_xfrin_getstarttime(const dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
* Get the start time of the xfrin object.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
* Returns:
|
||||
*\li Transfer start time
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
dns_xfrin_getstate(const dns_xfrin_t *xfr, const char **statestr,
|
||||
bool *is_first_data_received, bool *is_ixfr);
|
||||
/*%<
|
||||
* Get the current state of the xfrin object as a character string, and whether
|
||||
* it's currently known to be an IXFR transfer as a boolean value.
|
||||
*
|
||||
* Notes:
|
||||
*\li The 'is_ixfr' value is valid only if 'is_first_data_received' is true.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
dns_xfrin_getendserial(const dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
* Get the 'end_serial' of the xfrin object.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
* Returns:
|
||||
*\li Serial number of the new version zone (if it's already known), or 0.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
dns_xfrin_getstats(dns_xfrin_t *xfr, unsigned int *nmsgp, unsigned int *nrecsp,
|
||||
uint64_t *nbytesp);
|
||||
/*%<
|
||||
* Get various statistics values of the xfrin object: number of the received
|
||||
* messages, number of the received records, number of the received bytes.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
*/
|
||||
|
||||
const isc_sockaddr_t *
|
||||
dns_xfrin_getsourceaddr(const dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
* Get the source socket address of the xfrin object.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
* Returns:
|
||||
*\li const pointer to the zone transfer's source socket address
|
||||
*/
|
||||
|
||||
const isc_sockaddr_t *
|
||||
dns_xfrin_getprimaryaddr(const dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
* Get the socket address of the primary server of the xfrin object.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
* Returns:
|
||||
*\li const pointer to the zone transfer's primary server's socket address
|
||||
*/
|
||||
|
||||
const dns_transport_t *
|
||||
dns_xfrin_gettransport(const dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
* Get the trnasport of the xfrin object.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
* Returns:
|
||||
*\li const pointer to the zone transfer's transport
|
||||
*
|
||||
*/
|
||||
|
||||
const dns_name_t *
|
||||
dns_xfrin_gettsigkeyname(const dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
* Get the name of the xfrin object's TSIG key.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'xfr' is a valid dns_xfrin_t.
|
||||
*
|
||||
* Returns:
|
||||
*\li const pointer to the zone transfer's TSIG key's name or NULL
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
dns_xfrin_shutdown(dns_xfrin_t *xfr);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <dns/rdatastruct.h>
|
||||
#include <dns/rpz.h>
|
||||
#include <dns/types.h>
|
||||
#include <dns/xfrin.h>
|
||||
#include <dns/zt.h>
|
||||
|
||||
/* Define to 1 for detailed reference tracing */
|
||||
|
|
@ -1789,6 +1790,28 @@ dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state);
|
|||
*\li 'state' to be a valid DNS_ZONESTATE_ constant.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_running,
|
||||
bool *is_deferred, bool *is_pending, bool *needs_refresh);
|
||||
/*%<
|
||||
* Returns the xfrin associated with the zone (if any) with the current
|
||||
* transfer states (as booleans). When no longer needed, the returned xfrin
|
||||
* must be detached.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'zone' to be a valid zone.
|
||||
*\li 'xfrp' to be non NULL and '*xfrp' to be NULL.
|
||||
*\li 'is_running' to be non NULL.
|
||||
*\li 'is_deferred' to be non NULL.
|
||||
*\li 'is_pending' to be non NULL.
|
||||
*\li 'needs_refresh' to be non NULL.
|
||||
*
|
||||
* Returns:
|
||||
* ISC_R_SUCCESS xfrin exists and the information was returned.
|
||||
* ISC_R_NOTFOUND no xfrin was found for the zone.
|
||||
* ISC_R_FAILED error while trying to get the xfrin information
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
|
||||
isc_sockaddr_t *local, isc_time_t *now);
|
||||
|
|
|
|||
|
|
@ -94,49 +94,49 @@ list_add(dns_transport_list_t *list, const dns_name_t *name,
|
|||
}
|
||||
|
||||
dns_transport_type_t
|
||||
dns_transport_get_type(dns_transport_t *transport) {
|
||||
dns_transport_get_type(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->type);
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_certfile(dns_transport_t *transport) {
|
||||
dns_transport_get_certfile(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.certfile);
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_keyfile(dns_transport_t *transport) {
|
||||
dns_transport_get_keyfile(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.keyfile);
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_cafile(dns_transport_t *transport) {
|
||||
dns_transport_get_cafile(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.cafile);
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_remote_hostname(dns_transport_t *transport) {
|
||||
dns_transport_get_remote_hostname(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.remote_hostname);
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_endpoint(dns_transport_t *transport) {
|
||||
dns_transport_get_endpoint(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->doh.endpoint);
|
||||
}
|
||||
|
||||
dns_http_mode_t
|
||||
dns_transport_get_mode(dns_transport_t *transport) {
|
||||
dns_transport_get_mode(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->doh.mode);
|
||||
|
|
@ -294,14 +294,14 @@ dns_transport_set_tlsname(dns_transport_t *transport, const char *tlsname) {
|
|||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_ciphers(dns_transport_t *transport) {
|
||||
dns_transport_get_ciphers(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.ciphers);
|
||||
}
|
||||
|
||||
char *
|
||||
dns_transport_get_tlsname(dns_transport_t *transport) {
|
||||
dns_transport_get_tlsname(const dns_transport_t *transport) {
|
||||
REQUIRE(VALID_TRANSPORT(transport));
|
||||
|
||||
return (transport->tls.tlsname);
|
||||
|
|
|
|||
180
lib/dns/xfrin.c
180
lib/dns/xfrin.c
|
|
@ -16,6 +16,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/random.h>
|
||||
#include <isc/result.h>
|
||||
|
|
@ -140,11 +141,14 @@ struct dns_xfrin {
|
|||
dns_diff_t diff; /*%< Pending database changes */
|
||||
int difflen; /*%< Number of pending tuples */
|
||||
|
||||
xfrin_state_t state;
|
||||
_Atomic xfrin_state_t state;
|
||||
uint32_t end_serial;
|
||||
uint32_t expireopt;
|
||||
bool edns, is_ixfr, expireoptset;
|
||||
bool edns, expireoptset;
|
||||
atomic_bool is_ixfr;
|
||||
|
||||
isc_mutex_t statslock;
|
||||
/* Locked by statslock. */
|
||||
unsigned int nmsg; /*%< Number of messages recvd */
|
||||
unsigned int nrecs; /*%< Number of records recvd */
|
||||
uint64_t nbytes; /*%< Number of bytes received */
|
||||
|
|
@ -269,7 +273,7 @@ static isc_result_t
|
|||
axfr_init(dns_xfrin_t *xfr) {
|
||||
isc_result_t result;
|
||||
|
||||
xfr->is_ixfr = false;
|
||||
atomic_store(&xfr->is_ixfr, false);
|
||||
|
||||
if (xfr->db != NULL) {
|
||||
dns_db_detach(&xfr->db);
|
||||
|
|
@ -385,7 +389,7 @@ ixfr_init(dns_xfrin_t *xfr) {
|
|||
return (DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
xfr->is_ixfr = true;
|
||||
atomic_store(&xfr->is_ixfr, true);
|
||||
INSIST(xfr->db != NULL);
|
||||
xfr->difflen = 0;
|
||||
|
||||
|
|
@ -491,7 +495,9 @@ static isc_result_t
|
|||
xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata) {
|
||||
isc_result_t result;
|
||||
|
||||
LOCK(&xfr->statslock);
|
||||
xfr->nrecs++;
|
||||
UNLOCK(&xfr->statslock);
|
||||
|
||||
if (rdata->type == dns_rdatatype_none ||
|
||||
dns_rdatatype_ismeta(rdata->type))
|
||||
|
|
@ -519,7 +525,7 @@ xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata) {
|
|||
}
|
||||
|
||||
redo:
|
||||
switch (xfr->state) {
|
||||
switch (atomic_load(&xfr->state)) {
|
||||
case XFRST_SOAQUERY:
|
||||
if (rdata->type != dns_rdatatype_soa) {
|
||||
xfrin_log(xfr, ISC_LOG_NOTICE,
|
||||
|
|
@ -536,7 +542,7 @@ redo:
|
|||
xfr->ixfr.request_serial, xfr->end_serial);
|
||||
FAIL(DNS_R_UPTODATE);
|
||||
}
|
||||
xfr->state = XFRST_GOTSOA;
|
||||
atomic_store(&xfr->state, XFRST_GOTSOA);
|
||||
break;
|
||||
|
||||
case XFRST_GOTSOA:
|
||||
|
|
@ -578,7 +584,7 @@ redo:
|
|||
xfr->firstsoa_data = isc_mem_allocate(xfr->mctx, rdata->length);
|
||||
memcpy(xfr->firstsoa_data, rdata->data, rdata->length);
|
||||
xfr->firstsoa.data = xfr->firstsoa_data;
|
||||
xfr->state = XFRST_FIRSTDATA;
|
||||
atomic_store(&xfr->state, XFRST_FIRSTDATA);
|
||||
break;
|
||||
|
||||
case XFRST_FIRSTDATA:
|
||||
|
|
@ -593,25 +599,25 @@ redo:
|
|||
xfrin_log(xfr, ISC_LOG_DEBUG(3),
|
||||
"got incremental response");
|
||||
CHECK(ixfr_init(xfr));
|
||||
xfr->state = XFRST_IXFR_DELSOA;
|
||||
atomic_store(&xfr->state, XFRST_IXFR_DELSOA);
|
||||
} else {
|
||||
xfrin_log(xfr, ISC_LOG_DEBUG(3),
|
||||
"got nonincremental response");
|
||||
CHECK(axfr_init(xfr));
|
||||
xfr->state = XFRST_AXFR;
|
||||
atomic_store(&xfr->state, XFRST_AXFR);
|
||||
}
|
||||
goto redo;
|
||||
|
||||
case XFRST_IXFR_DELSOA:
|
||||
INSIST(rdata->type == dns_rdatatype_soa);
|
||||
CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
|
||||
xfr->state = XFRST_IXFR_DEL;
|
||||
atomic_store(&xfr->state, XFRST_IXFR_DEL);
|
||||
break;
|
||||
|
||||
case XFRST_IXFR_DEL:
|
||||
if (rdata->type == dns_rdatatype_soa) {
|
||||
uint32_t soa_serial = dns_soa_getserial(rdata);
|
||||
xfr->state = XFRST_IXFR_ADDSOA;
|
||||
atomic_store(&xfr->state, XFRST_IXFR_ADDSOA);
|
||||
xfr->ixfr.current_serial = soa_serial;
|
||||
goto redo;
|
||||
}
|
||||
|
|
@ -621,7 +627,7 @@ redo:
|
|||
case XFRST_IXFR_ADDSOA:
|
||||
INSIST(rdata->type == dns_rdatatype_soa);
|
||||
CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
|
||||
xfr->state = XFRST_IXFR_ADD;
|
||||
atomic_store(&xfr->state, XFRST_IXFR_ADD);
|
||||
break;
|
||||
|
||||
case XFRST_IXFR_ADD:
|
||||
|
|
@ -629,7 +635,7 @@ redo:
|
|||
uint32_t soa_serial = dns_soa_getserial(rdata);
|
||||
if (soa_serial == xfr->end_serial) {
|
||||
CHECK(ixfr_commit(xfr));
|
||||
xfr->state = XFRST_IXFR_END;
|
||||
atomic_store(&xfr->state, XFRST_IXFR_END);
|
||||
break;
|
||||
} else if (soa_serial != xfr->ixfr.current_serial) {
|
||||
xfrin_log(xfr, ISC_LOG_NOTICE,
|
||||
|
|
@ -639,7 +645,7 @@ redo:
|
|||
FAIL(DNS_R_FORMERR);
|
||||
} else {
|
||||
CHECK(ixfr_commit(xfr));
|
||||
xfr->state = XFRST_IXFR_DELSOA;
|
||||
atomic_store(&xfr->state, XFRST_IXFR_DELSOA);
|
||||
goto redo;
|
||||
}
|
||||
}
|
||||
|
|
@ -674,7 +680,7 @@ redo:
|
|||
FAIL(DNS_R_FORMERR);
|
||||
}
|
||||
CHECK(axfr_commit(xfr));
|
||||
xfr->state = XFRST_AXFR_END;
|
||||
atomic_store(&xfr->state, XFRST_AXFR_END);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -762,6 +768,110 @@ xfrin_idledout(void *xfr) {
|
|||
xfrin_fail(xfr, ISC_R_TIMEDOUT, "maximum idle time exceeded");
|
||||
}
|
||||
|
||||
isc_time_t
|
||||
dns_xfrin_getstarttime(const dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
return (xfr->start);
|
||||
}
|
||||
|
||||
void
|
||||
dns_xfrin_getstate(const dns_xfrin_t *xfr, const char **statestr,
|
||||
bool *is_first_data_received, bool *is_ixfr) {
|
||||
xfrin_state_t state;
|
||||
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
REQUIRE(statestr != NULL && *statestr == NULL);
|
||||
REQUIRE(is_ixfr != NULL);
|
||||
|
||||
state = atomic_load(&xfr->state);
|
||||
*statestr = "";
|
||||
*is_first_data_received = (state > XFRST_FIRSTDATA);
|
||||
*is_ixfr = atomic_load(&xfr->is_ixfr);
|
||||
|
||||
switch (state) {
|
||||
case XFRST_SOAQUERY:
|
||||
*statestr = "SOA Query";
|
||||
break;
|
||||
case XFRST_GOTSOA:
|
||||
*statestr = "Got SOA";
|
||||
break;
|
||||
case XFRST_INITIALSOA:
|
||||
*statestr = "Initial SOA";
|
||||
break;
|
||||
case XFRST_FIRSTDATA:
|
||||
*statestr = "First Data";
|
||||
break;
|
||||
case XFRST_IXFR_DELSOA:
|
||||
case XFRST_IXFR_DEL:
|
||||
case XFRST_IXFR_ADDSOA:
|
||||
case XFRST_IXFR_ADD:
|
||||
*statestr = "Receiving IXFR Data";
|
||||
break;
|
||||
case XFRST_IXFR_END:
|
||||
*statestr = "Finalizing IXFR";
|
||||
break;
|
||||
case XFRST_AXFR:
|
||||
*statestr = "Receiving AXFR Data";
|
||||
break;
|
||||
case XFRST_AXFR_END:
|
||||
*statestr = "Finalizing AXFR";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dns_xfrin_getendserial(const dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
return (xfr->end_serial);
|
||||
}
|
||||
|
||||
void
|
||||
dns_xfrin_getstats(dns_xfrin_t *xfr, unsigned int *nmsgp, unsigned int *nrecsp,
|
||||
uint64_t *nbytesp) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
REQUIRE(nmsgp != NULL && nrecsp != NULL && nbytesp != NULL);
|
||||
|
||||
LOCK(&xfr->statslock);
|
||||
*nmsgp = xfr->nmsg;
|
||||
*nrecsp = xfr->nrecs;
|
||||
*nbytesp = xfr->nbytes;
|
||||
UNLOCK(&xfr->statslock);
|
||||
}
|
||||
|
||||
const isc_sockaddr_t *
|
||||
dns_xfrin_getsourceaddr(const dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
return (&xfr->sourceaddr);
|
||||
}
|
||||
|
||||
const isc_sockaddr_t *
|
||||
dns_xfrin_getprimaryaddr(const dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
return (&xfr->primaryaddr);
|
||||
}
|
||||
|
||||
const dns_transport_t *
|
||||
dns_xfrin_gettransport(const dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
return (xfr->transport);
|
||||
}
|
||||
|
||||
const dns_name_t *
|
||||
dns_xfrin_gettsigkeyname(const dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
if (xfr->tsigkey == NULL || xfr->tsigkey->key == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (dst_key_name(xfr->tsigkey->key));
|
||||
}
|
||||
|
||||
void
|
||||
dns_xfrin_shutdown(dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
|
@ -823,7 +933,7 @@ xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg) {
|
|||
{
|
||||
xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
|
||||
isc_result_totext(result));
|
||||
if (xfr->is_ixfr) {
|
||||
if (atomic_load(&xfr->is_ixfr)) {
|
||||
/*
|
||||
* Pass special result code to force AXFR retry
|
||||
*/
|
||||
|
|
@ -877,7 +987,10 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
|
|||
dns_view_weakattach(dns_zone_getview(zone), &xfr->view);
|
||||
dns_name_init(&xfr->name, NULL);
|
||||
|
||||
isc_mutex_init(&xfr->statslock);
|
||||
|
||||
atomic_init(&xfr->shuttingdown, false);
|
||||
atomic_init(&xfr->is_ixfr, false);
|
||||
|
||||
if (db != NULL) {
|
||||
dns_db_attach(db, &xfr->db);
|
||||
|
|
@ -886,9 +999,9 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db,
|
|||
dns_diff_init(xfr->mctx, &xfr->diff);
|
||||
|
||||
if (reqtype == dns_rdatatype_soa) {
|
||||
xfr->state = XFRST_SOAQUERY;
|
||||
atomic_init(&xfr->state, XFRST_SOAQUERY);
|
||||
} else {
|
||||
xfr->state = XFRST_INITIALSOA;
|
||||
atomic_init(&xfr->state, XFRST_INITIALSOA);
|
||||
}
|
||||
|
||||
xfr->start = isc_time_now();
|
||||
|
|
@ -1261,9 +1374,11 @@ xfrin_send_request(dns_xfrin_t *xfr) {
|
|||
CHECK(add_opt(msg, udpsize, reqnsid, reqexpire));
|
||||
}
|
||||
|
||||
LOCK(&xfr->statslock);
|
||||
xfr->nmsg = 0;
|
||||
xfr->nrecs = 0;
|
||||
xfr->nbytes = 0;
|
||||
UNLOCK(&xfr->statslock);
|
||||
xfr->start = isc_time_now();
|
||||
msg->id = xfr->id;
|
||||
if (xfr->tsigctx != NULL) {
|
||||
|
|
@ -1395,9 +1510,11 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
|
||||
dns_message_setclass(msg, xfr->rdclass);
|
||||
|
||||
LOCK(&xfr->statslock);
|
||||
if (xfr->nmsg > 0) {
|
||||
msg->tcp_continuation = 1;
|
||||
}
|
||||
UNLOCK(&xfr->statslock);
|
||||
|
||||
isc_buffer_init(&buffer, region->base, region->length);
|
||||
isc_buffer_add(&buffer, region->length);
|
||||
|
|
@ -1421,8 +1538,8 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
{
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
msg->rcode == dns_rcode_formerr && xfr->edns &&
|
||||
(xfr->state == XFRST_SOAQUERY ||
|
||||
xfr->state == XFRST_INITIALSOA))
|
||||
(atomic_load(&xfr->state) == XFRST_SOAQUERY ||
|
||||
atomic_load(&xfr->state) == XFRST_INITIALSOA))
|
||||
{
|
||||
xfr->edns = false;
|
||||
dns_message_detach(&msg);
|
||||
|
|
@ -1457,7 +1574,7 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
dns_message_detach(&msg);
|
||||
xfrin_reset(xfr);
|
||||
xfr->reqtype = dns_rdatatype_soa;
|
||||
xfr->state = XFRST_SOAQUERY;
|
||||
atomic_store(&xfr->state, XFRST_SOAQUERY);
|
||||
try_again:
|
||||
result = xfrin_start(xfr);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
|
@ -1481,7 +1598,8 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
goto failure;
|
||||
}
|
||||
|
||||
if ((xfr->state == XFRST_SOAQUERY || xfr->state == XFRST_INITIALSOA) &&
|
||||
if ((atomic_load(&xfr->state) == XFRST_SOAQUERY ||
|
||||
atomic_load(&xfr->state) == XFRST_INITIALSOA) &&
|
||||
msg->counts[DNS_SECTION_QUESTION] != 1)
|
||||
{
|
||||
xfrin_log(xfr, ISC_LOG_NOTICE, "missing question section");
|
||||
|
|
@ -1531,7 +1649,7 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
* if the first RR in the answer section is not a SOA record.
|
||||
*/
|
||||
if (xfr->reqtype == dns_rdatatype_ixfr &&
|
||||
xfr->state == XFRST_INITIALSOA &&
|
||||
atomic_load(&xfr->state) == XFRST_INITIALSOA &&
|
||||
msg->counts[DNS_SECTION_ANSWER] == 0)
|
||||
{
|
||||
xfrin_log(xfr, ISC_LOG_DEBUG(3),
|
||||
|
|
@ -1598,24 +1716,29 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
|
||||
} else if (dns_message_gettsigkey(msg) != NULL) {
|
||||
xfr->sincetsig++;
|
||||
LOCK(&xfr->statslock);
|
||||
if (xfr->sincetsig > 100 || xfr->nmsg == 0 ||
|
||||
xfr->state == XFRST_AXFR_END ||
|
||||
xfr->state == XFRST_IXFR_END)
|
||||
atomic_load(&xfr->state) == XFRST_AXFR_END ||
|
||||
atomic_load(&xfr->state) == XFRST_IXFR_END)
|
||||
{
|
||||
UNLOCK(&xfr->statslock);
|
||||
result = DNS_R_EXPECTEDTSIG;
|
||||
goto failure;
|
||||
}
|
||||
UNLOCK(&xfr->statslock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the number of messages received.
|
||||
*/
|
||||
LOCK(&xfr->statslock);
|
||||
xfr->nmsg++;
|
||||
|
||||
/*
|
||||
* Update the number of bytes received.
|
||||
*/
|
||||
xfr->nbytes += buffer.used;
|
||||
UNLOCK(&xfr->statslock);
|
||||
|
||||
/*
|
||||
* Take the context back.
|
||||
|
|
@ -1628,10 +1751,10 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
get_edns_expire(xfr, msg);
|
||||
}
|
||||
|
||||
switch (xfr->state) {
|
||||
switch (atomic_load(&xfr->state)) {
|
||||
case XFRST_GOTSOA:
|
||||
xfr->reqtype = dns_rdatatype_axfr;
|
||||
xfr->state = XFRST_INITIALSOA;
|
||||
atomic_store(&xfr->state, XFRST_INITIALSOA);
|
||||
CHECK(xfrin_send_request(xfr));
|
||||
break;
|
||||
case XFRST_AXFR_END:
|
||||
|
|
@ -1724,6 +1847,7 @@ xfrin_destroy(dns_xfrin_t *xfr) {
|
|||
if (msecs == 0) {
|
||||
msecs = 1;
|
||||
}
|
||||
LOCK(&xfr->statslock);
|
||||
persec = (xfr->nbytes * 1000) / msecs;
|
||||
xfrin_log(xfr, ISC_LOG_INFO,
|
||||
"Transfer completed: %d messages, %d records, "
|
||||
|
|
@ -1732,6 +1856,8 @@ xfrin_destroy(dns_xfrin_t *xfr) {
|
|||
xfr->nmsg, xfr->nrecs, xfr->nbytes,
|
||||
(unsigned int)(msecs / 1000), (unsigned int)(msecs % 1000),
|
||||
(unsigned int)persec, xfr->end_serial);
|
||||
UNLOCK(&xfr->statslock);
|
||||
isc_mutex_destroy(&xfr->statslock);
|
||||
|
||||
if (xfr->dispentry != NULL) {
|
||||
dns_dispatch_done(&xfr->dispentry);
|
||||
|
|
|
|||
|
|
@ -19164,6 +19164,45 @@ dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
|
|||
return (count);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_running,
|
||||
bool *is_deferred, bool *is_pending, bool *needs_refresh) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(xfrp != NULL && *xfrp == NULL);
|
||||
|
||||
if (zone->zmgr == NULL) {
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
|
||||
LOCK_ZONE(zone);
|
||||
if (zone->xfr != NULL) {
|
||||
dns_xfrin_attach(zone->xfr, xfrp);
|
||||
}
|
||||
if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
|
||||
*is_running = true;
|
||||
*is_deferred = false;
|
||||
*is_pending = false;
|
||||
} else if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
|
||||
*is_running = false;
|
||||
*is_deferred = true;
|
||||
*is_pending = false;
|
||||
} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
|
||||
*is_running = false;
|
||||
*is_deferred = false;
|
||||
*is_pending = true;
|
||||
} else {
|
||||
*is_running = false;
|
||||
*is_deferred = false;
|
||||
*is_pending = false;
|
||||
}
|
||||
*needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
|
||||
UNLOCK_ZONE(zone);
|
||||
RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_lock_keyfiles(dns_zone_t *zone) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
|
|
|||
Loading…
Reference in a new issue