2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00

Improve efficiency of ns_client_t reset

The ns_client_t struct is reset and zero-ed out on every query,
but some fields (query, message, manager) are preserved.

We observe two things:
 - The sendbuf field is going to be overwritten anyway, there's
   no need to zero it out.
 - The fields are copied out when the struct is zero-ed out, and
   then copied back in. For the query field (which is 896 bytes)
   this is very inefficient.

This commit makes the reset more efficient avoiding to unnecessary
zero-ing and copy.
This commit is contained in:
Alessio Podda 2025-05-14 15:32:53 +02:00
parent 0c15da33e8
commit e84704bd55
12 changed files with 833 additions and 769 deletions

View File

@ -98,7 +98,7 @@ typedef struct filter_instance {
/*
* Client attribute tests.
*/
#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
#define WANTDNSSEC(c) (((c)->inner.attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
#define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
/*
@ -439,11 +439,11 @@ typedef struct section_filter {
*/
static bool
is_v4_client(ns_client_t *client) {
if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
if (isc_sockaddr_pf(&client->inner.peeraddr) == AF_INET) {
return true;
}
if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
if (isc_sockaddr_pf(&client->inner.peeraddr) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&client->inner.peeraddr.type.sin6.sin6_addr))
{
return true;
}
@ -455,8 +455,8 @@ is_v4_client(ns_client_t *client) {
*/
static bool
is_v6_client(ns_client_t *client) {
if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
!IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
if (isc_sockaddr_pf(&client->inner.peeraddr) == AF_INET6 &&
!IN6_IS_ADDR_V4MAPPED(&client->inner.peeraddr.type.sin6.sin6_addr))
{
return true;
}
@ -705,7 +705,7 @@ filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
trdataset = ns_client_newrdataset(qctx->client);
result = dns_db_findrdataset(
qctx->db, qctx->node, qctx->version, dns_rdatatype_aaaa,
0, qctx->client->now, trdataset, NULL);
0, qctx->client->inner.now, trdataset, NULL);
if (dns_rdataset_isassociated(trdataset)) {
dns_rdataset_disassociate(trdataset);
}

View File

@ -98,7 +98,7 @@ typedef struct filter_instance {
/*
* Client attribute tests.
*/
#define WANTDNSSEC(c) (((c)->attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
#define WANTDNSSEC(c) (((c)->inner.attributes & NS_CLIENTATTR_WANTDNSSEC) != 0)
#define RECURSIONOK(c) (((c)->query.attributes & NS_QUERYATTR_RECURSIONOK) != 0)
/*
@ -443,11 +443,11 @@ typedef struct section_filter {
*/
static bool
is_v4_client(ns_client_t *client) {
if (isc_sockaddr_pf(&client->peeraddr) == AF_INET) {
if (isc_sockaddr_pf(&client->inner.peeraddr) == AF_INET) {
return true;
}
if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
if (isc_sockaddr_pf(&client->inner.peeraddr) == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&client->inner.peeraddr.type.sin6.sin6_addr))
{
return true;
}
@ -459,8 +459,8 @@ is_v4_client(ns_client_t *client) {
*/
static bool
is_v6_client(ns_client_t *client) {
if (isc_sockaddr_pf(&client->peeraddr) == AF_INET6 &&
!IN6_IS_ADDR_V4MAPPED(&client->peeraddr.type.sin6.sin6_addr))
if (isc_sockaddr_pf(&client->inner.peeraddr) == AF_INET6 &&
!IN6_IS_ADDR_V4MAPPED(&client->inner.peeraddr.type.sin6.sin6_addr))
{
return true;
}
@ -709,7 +709,7 @@ filter_respond_begin(void *arg, void *cbdata, isc_result_t *resp) {
trdataset = ns_client_newrdataset(qctx->client);
result = dns_db_findrdataset(
qctx->db, qctx->node, qctx->version, dns_rdatatype_a, 0,
qctx->client->now, trdataset, NULL);
qctx->client->inner.now, trdataset, NULL);
if (dns_rdataset_isassociated(trdataset)) {
dns_rdataset_disassociate(trdataset);
}

File diff suppressed because it is too large Load Diff

View File

@ -163,81 +163,87 @@ struct ns_clientmgr {
/*% nameserver client structure */
struct ns_client {
unsigned int magic;
ns_clientmgr_t *manager;
ns_clientstate_t state;
bool async;
unsigned int attributes;
dns_view_t *view;
dns_dispatch_t *dispatch;
isc_nmhandle_t *handle; /* Permanent pointer to handle */
isc_nmhandle_t *sendhandle; /* Waiting for send callback */
isc_nmhandle_t *reqhandle; /* Waiting for request callback
(query, update, notify) */
isc_nmhandle_t *updatehandle; /* Waiting for update callback */
isc_nmhandle_t *restarthandle; /* Waiting for restart callback */
unsigned char *tcpbuf;
size_t tcpbuf_size;
unsigned int magic;
struct ns_client_inner {
ns_clientstate_t state;
bool async;
unsigned int attributes;
dns_view_t *view;
dns_dispatch_t *dispatch;
isc_nmhandle_t *handle; /* Permanent pointer to handle */
isc_nmhandle_t *sendhandle; /* Waiting for send callback */
isc_nmhandle_t *reqhandle; /* Waiting for request callback
(query, update, notify) */
isc_nmhandle_t *updatehandle; /* Waiting for update callback */
isc_nmhandle_t *restarthandle; /* Waiting for restart callback
*/
unsigned char *tcpbuf;
size_t tcpbuf_size;
dns_rdataset_t *opt;
uint16_t udpsize;
uint16_t extflags;
int16_t ednsversion; /* -1 noedns */
uint16_t additionaldepth;
void (*cleanup)(ns_client_t *);
isc_time_t requesttime;
isc_stdtime_t now;
isc_time_t tnow;
dns_name_t signername; /*%< [T]SIG key name */
dns_name_t *signer; /*%< NULL if not valid sig */
isc_result_t sigresult;
isc_result_t viewmatchresult;
isc_buffer_t *buffer;
isc_buffer_t tbuffer;
dns_name_t rad; /* Zone rad domain */
isc_sockaddr_t peeraddr;
bool peeraddr_valid;
isc_netaddr_t destaddr;
isc_sockaddr_t destsockaddr;
dns_ecs_t ecs; /*%< EDNS client subnet sent by client */
/*%
* Information about recent FORMERR response(s), for
* FORMERR loop avoidance. This is separate for each
* client object rather than global only to avoid
* the need for locking.
*/
struct {
isc_sockaddr_t addr;
isc_stdtime_t time;
dns_messageid_t id;
} formerrcache;
/*% Callback function to send a response when unit testing */
void (*sendcb)(isc_buffer_t *buf);
ISC_LINK(ns_client_t) rlink;
unsigned char cookie[8];
uint32_t expire;
unsigned char *zoneversion;
uint32_t zoneversionlength;
unsigned char *keytag;
uint16_t keytag_len;
/*%
* Used to override the DNS response code in ns_client_error().
* If set to -1, the rcode is determined from the result code,
* but if set to any other value, the least significant 12
* bits will be used as the rcode in the response message.
*/
int32_t rcode_override;
} inner;
/*
* Fields which will be preserved
*/
ns_clientmgr_t *manager;
dns_message_t *message;
dns_rdataset_t *opt;
dns_edectx_t edectx;
uint16_t udpsize;
uint16_t extflags;
int16_t ednsversion; /* -1 noedns */
uint16_t additionaldepth;
void (*cleanup)(ns_client_t *);
ns_query_t query;
isc_time_t requesttime;
isc_stdtime_t now;
isc_time_t tnow;
dns_name_t signername; /*%< [T]SIG key name */
dns_name_t *signer; /*%< NULL if not valid sig */
isc_result_t sigresult;
isc_result_t viewmatchresult;
isc_buffer_t *buffer;
isc_buffer_t tbuffer;
dns_name_t rad; /* Zone rad domain */
isc_sockaddr_t peeraddr;
bool peeraddr_valid;
isc_netaddr_t destaddr;
isc_sockaddr_t destsockaddr;
dns_ecs_t ecs; /*%< EDNS client subnet sent by client */
/*%
* Information about recent FORMERR response(s), for
* FORMERR loop avoidance. This is separate for each
* client object rather than global only to avoid
* the need for locking.
*/
struct {
isc_sockaddr_t addr;
isc_stdtime_t time;
dns_messageid_t id;
} formerrcache;
/*% Callback function to send a response when unit testing */
void (*sendcb)(isc_buffer_t *buf);
ISC_LINK(ns_client_t) rlink;
unsigned char cookie[8];
uint32_t expire;
unsigned char *zoneversion;
uint32_t zoneversionlength;
unsigned char *keytag;
uint16_t keytag_len;
/*%
* Used to override the DNS response code in ns_client_error().
* If set to -1, the rcode is determined from the result code,
* but if set to any other value, the least significant 12
* bits will be used as the rcode in the response message.
*/
int32_t rcode_override;
uint8_t sendbuf[NS_CLIENT_SEND_BUFFER_SIZE];
ns_query_t query;
uint8_t sendbuf[NS_CLIENT_SEND_BUFFER_SIZE];
};
#define NS_CLIENT_MAGIC ISC_MAGIC('N', 'S', 'C', 'c')

View File

@ -55,7 +55,7 @@ respond(ns_client_t *client, isc_result_t result) {
}
if (msg_result != ISC_R_SUCCESS) {
ns_client_drop(client, msg_result);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
return;
}
message->rcode = rcode;
@ -66,7 +66,7 @@ respond(ns_client_t *client, isc_result_t result) {
}
ns_client_send(client);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
}
void
@ -83,7 +83,7 @@ ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle) {
/*
* Attach to the request handle
*/
isc_nmhandle_attach(handle, &client->reqhandle);
isc_nmhandle_attach(handle, &client->inner.reqhandle);
/*
* Interpret the question section.
@ -142,8 +142,8 @@ ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle) {
}
dns_name_format(zonename, namebuf, sizeof(namebuf));
result = dns_view_findzone(client->view, zonename, DNS_ZTFIND_EXACT,
&zone);
result = dns_view_findzone(client->inner.view, zonename,
DNS_ZTFIND_EXACT, &zone);
if (result == ISC_R_SUCCESS) {
dns_zonetype_t zonetype = dns_zone_gettype(zone);

File diff suppressed because it is too large Load Diff

View File

@ -210,7 +210,8 @@
/*
* Return TRUE if NS_CLIENTATTR_TCP is set in the attributes other FALSE.
*/
#define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0)
#define TCPCLIENT(client) \
(((client)->inner.attributes & NS_CLIENTATTR_TCP) != 0)
/**************************************************************************/
@ -357,7 +358,7 @@ checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename,
int level = update_possible ? ISC_LOG_ERROR : ISC_LOG_INFO;
dns_name_format(zonename, namebuf, sizeof(namebuf));
dns_rdataclass_format(client->view->rdclass, classbuf,
dns_rdataclass_format(client->inner.view->rdclass, classbuf,
sizeof(classbuf));
ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
@ -366,7 +367,7 @@ checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename,
namebuf, classbuf);
} else if (!update_possible) {
dns_name_format(zonename, namebuf, sizeof(namebuf));
dns_rdataclass_format(client->view->rdclass, classbuf,
dns_rdataclass_format(client->inner.view->rdclass, classbuf,
sizeof(classbuf));
result = DNS_R_REFUSED;
@ -415,15 +416,15 @@ checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,
}
}
if (client->signer != NULL) {
dns_name_format(client->signer, namebuf, sizeof(namebuf));
if (client->inner.signer != NULL) {
dns_name_format(client->inner.signer, namebuf, sizeof(namebuf));
ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
NS_LOGMODULE_UPDATE, ISC_LOG_INFO,
"signer \"%s\" %s", namebuf, msg);
}
dns_name_format(zonename, namebuf, sizeof(namebuf));
dns_rdataclass_format(client->view->rdclass, classbuf,
dns_rdataclass_format(client->inner.view->rdclass, classbuf,
sizeof(classbuf));
ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,
@ -1634,7 +1635,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone),
"update", dns_zone_getorigin(zone), false,
false));
} else if (client->signer == NULL && !TCPCLIENT(client)) {
} else if (client->inner.signer == NULL && !TCPCLIENT(client)) {
CHECK(checkupdateacl(client, NULL, "update",
dns_zone_getorigin(zone), false, true));
}
@ -1738,7 +1739,8 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
maxbytype[update] = 0;
isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
isc_netaddr_fromsockaddr(&netaddr,
&client->inner.peeraddr);
if (client->message->tsigkey != NULL) {
tsigkey = client->message->tsigkey->key;
@ -1771,7 +1773,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
ssuinfo.name = name;
ssuinfo.table = ssutable;
ssuinfo.signer = client->signer;
ssuinfo.signer = client->inner.signer;
ssuinfo.addr = &netaddr;
ssuinfo.aclenv = env;
ssuinfo.tcp = TCPCLIENT(client);
@ -1791,9 +1793,10 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
CHECK(rr_exists(db, ver, name, &rdata, &flag));
if (flag &&
!dns_ssutable_checkrules(
ssutable, client->signer, name,
&netaddr, TCPCLIENT(client), env,
rdata.type, target, tsigkey, NULL))
ssutable, client->inner.signer,
name, &netaddr, TCPCLIENT(client),
env, rdata.type, target, tsigkey,
NULL))
{
FAILC(DNS_R_REFUSED,
"rejected by secure update");
@ -1801,9 +1804,9 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
} else if (rdata.type != dns_rdatatype_any) {
const dns_ssurule_t *ssurule = NULL;
if (!dns_ssutable_checkrules(
ssutable, client->signer, name,
&netaddr, TCPCLIENT(client), env,
rdata.type, target, tsigkey,
ssutable, client->inner.signer,
name, &netaddr, TCPCLIENT(client),
env, rdata.type, target, tsigkey,
&ssurule))
{
FAILC(DNS_R_REFUSED,
@ -1813,7 +1816,8 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
rdata.type);
} else {
if (!ssu_checkall(db, ver, name, ssutable,
client->signer, &netaddr, env,
client->inner.signer,
&netaddr, env,
TCPCLIENT(client), tsigkey))
{
FAILC(DNS_R_REFUSED,
@ -1845,7 +1849,7 @@ send_update(ns_client_t *client, dns_zone_t *zone) {
.result = ISC_R_SUCCESS,
};
isc_nmhandle_attach(client->handle, &client->updatehandle);
isc_nmhandle_attach(client->inner.handle, &client->inner.updatehandle);
isc_async_run(dns_zone_getloop(zone), update_action, uev);
maxbytype = NULL;
@ -1877,13 +1881,13 @@ respond(ns_client_t *client, isc_result_t result) {
"could not create update response message: %s",
isc_result_totext(msg_result));
ns_client_drop(client, msg_result);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
return;
}
client->message->rcode = dns_result_torcode(result);
ns_client_send(client);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
}
void
@ -1899,7 +1903,7 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
* Attach to the request handle. This will be held until
* we respond, or drop the request.
*/
isc_nmhandle_attach(handle, &client->reqhandle);
isc_nmhandle_attach(handle, &client->inner.reqhandle);
/*
* Interpret the zone section.
@ -1929,8 +1933,8 @@ ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
"update zone section contains multiple RRs");
}
result = dns_view_findzone(client->view, zonename, DNS_ZTFIND_EXACT,
&zone);
result = dns_view_findzone(client->inner.view, zonename,
DNS_ZTFIND_EXACT, &zone);
if (result != ISC_R_SUCCESS) {
FAILN(DNS_R_NOTAUTH, zonename,
"not authoritative for update zone");
@ -1982,7 +1986,7 @@ failure:
*/
if (result == DNS_R_DROP) {
ns_client_drop(client, result);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
} else {
respond(client, result);
}
@ -3377,7 +3381,7 @@ updatedone_action(void *arg) {
update_t *uev = (update_t *)arg;
ns_client_t *client = uev->client;
REQUIRE(client->updatehandle == client->handle);
REQUIRE(client->inner.updatehandle == client->inner.handle);
switch (uev->result) {
case ISC_R_SUCCESS:
@ -3398,7 +3402,7 @@ updatedone_action(void *arg) {
dns_zone_detach(&uev->zone);
}
isc_mem_put(client->manager->mctx, uev, sizeof(*uev));
isc_nmhandle_detach(&client->updatehandle);
isc_nmhandle_detach(&client->inner.updatehandle);
}
/*%
@ -3413,7 +3417,7 @@ forward_fail(void *arg) {
isc_quota_release(&client->manager->sctx->updquota);
isc_mem_put(client->manager->mctx, uev, sizeof(*uev));
isc_nmhandle_detach(&client->updatehandle);
isc_nmhandle_detach(&client->inner.updatehandle);
}
static void
@ -3445,8 +3449,8 @@ forward_done(void *arg) {
isc_quota_release(&client->manager->sctx->updquota);
isc_mem_put(client->manager->mctx, uev, sizeof(*uev));
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->updatehandle);
isc_nmhandle_detach(&client->inner.reqhandle);
isc_nmhandle_detach(&client->inner.updatehandle);
}
static void
@ -3509,7 +3513,7 @@ send_forward(ns_client_t *client, dns_zone_t *zone) {
LOGLEVEL_PROTOCOL, "forwarding update for zone '%s/%s'",
namebuf, classbuf);
isc_nmhandle_attach(client->handle, &client->updatehandle);
isc_nmhandle_attach(client->inner.handle, &client->inner.updatehandle);
isc_async_run(dns_zone_getloop(zone), forward_action, uev);
return result;

View File

@ -738,7 +738,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
isc_mem_t *mctx = client->manager->mctx;
dns_message_t *request = client->message;
xfrout_ctx_t *xfr = NULL;
dns_transfer_format_t format = client->view->transfer_format;
dns_transfer_format_t format = client->inner.view->transfer_format;
isc_netaddr_t na;
dns_peer_t *peer = NULL;
isc_buffer_t *tsigbuf = NULL;
@ -796,7 +796,7 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
FAILC(DNS_R_FORMERR, "multiple questions");
}
result = dns_view_findzone(client->view, question_name,
result = dns_view_findzone(client->inner.view, question_name,
DNS_ZTFIND_EXACT, &zone);
if (result != ISC_R_SUCCESS || dns_zone_gettype(zone) == dns_zone_dlz) {
/*
@ -804,10 +804,10 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
* marked in the zone table as a DLZ zone. Check the DLZ
* databases for a match.
*/
if (!ISC_LIST_EMPTY(client->view->dlz_searched)) {
result = dns_dlzallowzonexfr(client->view,
question_name,
&client->peeraddr, &db);
if (!ISC_LIST_EMPTY(client->inner.view->dlz_searched)) {
result = dns_dlzallowzonexfr(
client->inner.view, question_name,
&client->inner.peeraddr, &db);
if (result == ISC_R_DEFAULT) {
useviewacl = true;
result = ISC_R_SUCCESS;
@ -913,9 +913,9 @@ got_soa:
dns_acl_t *acl;
ns_client_aclmsg("zone transfer", question_name, reqtype,
client->view->rdclass, msg, sizeof(msg));
client->inner.view->rdclass, msg, sizeof(msg));
if (useviewacl) {
acl = client->view->transferacl;
acl = client->inner.view->transferacl;
} else {
acl = dns_zone_getxfracl(zone);
}
@ -927,7 +927,7 @@ got_soa:
* AXFR over UDP is not possible.
*/
if (reqtype == dns_rdatatype_axfr &&
(client->attributes & NS_CLIENTATTR_TCP) == 0)
(client->inner.attributes & NS_CLIENTATTR_TCP) == 0)
{
FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
}
@ -935,8 +935,8 @@ got_soa:
/*
* Look up the requesting server in the peer table.
*/
isc_netaddr_fromsockaddr(&na, &client->peeraddr);
(void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
isc_netaddr_fromsockaddr(&na, &client->inner.peeraddr);
(void)dns_peerlist_peerbyaddr(client->inner.view->peers, &na, &peer);
/*
* Decide on the transfer format (one-answer or many-answers).
@ -978,7 +978,7 @@ got_soa:
* IXFR over UDP (currently, we always do).
*/
if (DNS_SERIAL_GE(begin_serial, current_serial) ||
(client->attributes & NS_CLIENTATTR_TCP) == 0)
(client->inner.attributes & NS_CLIENTATTR_TCP) == 0)
{
CHECK(soa_rrstream_create(mctx, db, ver, &stream));
is_poll = true;
@ -989,10 +989,10 @@ got_soa:
* Outgoing IXFR may have been disabled for this peer
* or globally.
*/
if ((client->attributes & NS_CLIENTATTR_TCP) != 0) {
if ((client->inner.attributes & NS_CLIENTATTR_TCP) != 0) {
bool provide_ixfr;
provide_ixfr = client->view->provideixfr;
provide_ixfr = client->inner.view->provideixfr;
if (peer != NULL) {
(void)dns_peer_getprovideixfr(peer,
&provide_ixfr);
@ -1121,7 +1121,8 @@ have_stream:
if (zone != NULL) {
dns_zone_getraw(zone, &raw);
mayberaw = (raw != NULL) ? raw : zone;
if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
if ((client->inner.attributes & NS_CLIENTATTR_WANTEXPIRE) !=
0 &&
(dns_zone_gettype(mayberaw) == dns_zone_secondary ||
dns_zone_gettype(mayberaw) == dns_zone_mirror))
{
@ -1129,9 +1130,12 @@ have_stream:
uint32_t secs;
dns_zone_getexpiretime(zone, &expiretime);
secs = isc_time_seconds(&expiretime);
if (secs >= client->now && result == ISC_R_SUCCESS) {
client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
client->expire = secs - client->now;
if (secs >= client->inner.now &&
result == ISC_R_SUCCESS)
{
client->inner.attributes |=
NS_CLIENTATTR_HAVEEXPIRE;
client->inner.expire = secs - client->inner.now;
}
}
if (raw != NULL) {
@ -1192,7 +1196,7 @@ failure:
NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3),
"zone transfer setup failed");
ns_client_error(client, result);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
}
}
@ -1236,11 +1240,11 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
xfr->stats.start = isc_time_now();
isc_nm_timer_create(xfr->client->handle, xfrout_client_timeout, xfr,
&xfr->maxtime_timer);
isc_nm_timer_create(xfr->client->inner.handle, xfrout_client_timeout,
xfr, &xfr->maxtime_timer);
isc_nm_timer_create(xfr->client->handle, xfrout_delayed_timeout, xfr,
&xfr->delayed_send_timer);
isc_nm_timer_create(xfr->client->inner.handle, xfrout_delayed_timeout,
xfr, &xfr->delayed_send_timer);
/*
* Allocate a temporary buffer for the uncompressed response
@ -1277,28 +1281,28 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
static void
xfrout_send(xfrout_ctx_t *xfr) {
const bool is_tcp = ((xfr->client->attributes & NS_CLIENTATTR_TCP) !=
0);
const bool is_tcp =
((xfr->client->inner.attributes & NS_CLIENTATTR_TCP) != 0);
if (is_tcp) {
isc_region_t used;
isc_buffer_usedregion(&xfr->txbuf, &used);
isc_nmhandle_attach(xfr->client->handle,
&xfr->client->sendhandle);
isc_nmhandle_attach(xfr->client->inner.handle,
&xfr->client->inner.sendhandle);
if (xfr->idletime > 0) {
isc_nmhandle_setwritetimeout(xfr->client->sendhandle,
xfr->idletime);
isc_nmhandle_setwritetimeout(
xfr->client->inner.sendhandle, xfr->idletime);
}
isc_nm_send(xfr->client->sendhandle, &used, xfrout_senddone,
xfr);
isc_nm_send(xfr->client->inner.sendhandle, &used,
xfrout_senddone, xfr);
xfr->sends++;
xfr->cbytes = used.length;
} else {
ns_client_send(xfr->client);
xfr->stream->methods->pause(xfr->stream);
isc_nmhandle_detach(&xfr->client->reqhandle);
isc_nmhandle_detach(&xfr->client->inner.reqhandle);
xfrout_ctx_destroy(&xfr);
}
}
@ -1369,7 +1373,7 @@ sendstream(xfrout_ctx_t *xfr) {
isc_buffer_clear(&xfr->buf);
isc_buffer_clear(&xfr->txbuf);
is_tcp = ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0);
is_tcp = ((xfr->client->inner.attributes & NS_CLIENTATTR_TCP) != 0);
if (!is_tcp) {
/*
* In the UDP case, we put the response data directly into
@ -1393,7 +1397,7 @@ sendstream(xfrout_ctx_t *xfr) {
msg->id = xfr->id;
msg->rcode = dns_rcode_noerror;
msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) {
if ((xfr->client->inner.attributes & NS_CLIENTATTR_RA) != 0) {
msg->flags |= DNS_MESSAGEFLAG_RA;
}
CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
@ -1406,7 +1410,9 @@ sendstream(xfrout_ctx_t *xfr) {
/*
* Add a EDNS option to the message?
*/
if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
if ((xfr->client->inner.attributes & NS_CLIENTATTR_WANTOPT) !=
0)
{
dns_rdataset_t *opt = NULL;
CHECK(ns_client_addopt(xfr->client, msg, &opt));
@ -1414,8 +1420,10 @@ sendstream(xfrout_ctx_t *xfr) {
/*
* Add to first message only.
*/
xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
xfr->client->inner.attributes &=
~NS_CLIENTATTR_WANTNSID;
xfr->client->inner.attributes &=
~NS_CLIENTATTR_HAVEEXPIRE;
}
/*
@ -1669,14 +1677,14 @@ static void
xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
xfrout_ctx_t *xfr = (xfrout_ctx_t *)arg;
REQUIRE((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0);
REQUIRE((xfr->client->inner.attributes & NS_CLIENTATTR_TCP) != 0);
INSIST(handle == xfr->client->handle);
INSIST(handle == xfr->client->inner.handle);
xfr->sends--;
INSIST(xfr->sends == 0);
isc_nmhandle_detach(&xfr->client->sendhandle);
isc_nmhandle_detach(&xfr->client->inner.sendhandle);
/*
* Update transfer statistics if sending succeeded, accounting for the
@ -1719,7 +1727,7 @@ xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
* We're done, unreference the handle and destroy the xfr
* context.
*/
isc_nmhandle_detach(&xfr->client->reqhandle);
isc_nmhandle_detach(&xfr->client->inner.reqhandle);
xfrout_ctx_destroy(&xfr);
}
}
@ -1737,7 +1745,7 @@ xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
REQUIRE(xfr->shuttingdown);
ns_client_drop(xfr->client, ISC_R_CANCELED);
isc_nmhandle_detach(&xfr->client->reqhandle);
isc_nmhandle_detach(&xfr->client->inner.reqhandle);
xfrout_ctx_destroy(&xfr);
}

View File

@ -230,7 +230,7 @@ ns_test_getclient(ns_interface_t *ifp0, bool tcp, ns_client_t **clientp) {
atomic_store(&client_refs[i], 2);
atomic_store(&client_addrs[i], (uintptr_t)client);
client->handle = (isc_nmhandle_t *)client; /* Hack */
client->inner.handle = (isc_nmhandle_t *)client; /* Hack */
*clientp = client;
}
@ -389,12 +389,12 @@ create_qctx_for_client(ns_client_t *client, query_ctx_t **qctxp) {
saved_hook_table = ns__hook_table;
ns__hook_table = query_hooks;
ns_query_start(client, client->handle);
ns_query_start(client, client->inner.handle);
ns__hook_table = saved_hook_table;
ns_hooktable_free(mctx, (void **)&query_hooks);
isc_nmhandle_detach(&client->reqhandle);
isc_nmhandle_detach(&client->inner.reqhandle);
return ISC_R_SUCCESS;
}
@ -415,13 +415,13 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
* Allocate and initialize a client structure.
*/
ns_test_getclient(NULL, false, &client);
client->tnow = isc_time_now();
client->inner.tnow = isc_time_now();
/*
* Every client needs to belong to a view.
*/
result = dns_test_makeview("view", false, params->with_cache,
&client->view);
&client->inner.view);
if (result != ISC_R_SUCCESS) {
goto detach_client;
}
@ -441,7 +441,7 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
* set in ns_client_request(), i.e. earlier than the unit tests hook
* into the call chain, just set it manually.
*/
client->attributes |= NS_CLIENTATTR_RA;
client->inner.attributes |= NS_CLIENTATTR_RA;
/*
* Create a query context for a client sending the previously
@ -457,7 +457,7 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
* decrement it in order for it to drop to zero when "qctx" gets
* destroyed.
*/
handle = client->handle;
handle = client->inner.handle;
isc_nmhandle_detach(&handle);
return ISC_R_SUCCESS;
@ -465,9 +465,9 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
detach_query:
dns_message_detach(&client->message);
detach_view:
dns_view_detach(&client->view);
dns_view_detach(&client->inner.view);
detach_client:
isc_nmhandle_detach(&client->handle);
isc_nmhandle_detach(&client->inner.handle);
return result;
}
@ -489,7 +489,7 @@ ns_test_qctx_destroy(query_ctx_t **qctxp) {
dns_db_detach(&qctx->db);
}
if (qctx->client != NULL) {
isc_nmhandle_detach(&qctx->client->handle);
isc_nmhandle_detach(&qctx->client->inner.handle);
}
isc_mem_put(mctx, qctx, sizeof(*qctx));

View File

@ -84,8 +84,8 @@ isc_nmhandle_detach(isc_nmhandle_t **handlep) {
INSIST(i < 32);
if (atomic_fetch_sub(&client_refs[i], 1) == 1) {
dns_view_detach(&client->view);
client->state = 4;
dns_view_detach(&client->inner.view);
client->inner.state = 4;
ns__client_reset_cb(client);
ns__client_put_cb(client);
atomic_store(&client_addrs[i], (uintptr_t)NULL);

View File

@ -71,12 +71,12 @@ ISC_LOOP_TEST_IMPL(notify_start) {
ns_test_getclient(NULL, false, &client);
result = dns_test_makeview("view", false, false, &client->view);
result = dns_test_makeview("view", false, false, &client->inner.view);
assert_int_equal(result, ISC_R_SUCCESS);
result = ns_test_serve_zone("example.com",
TESTS_DIR "/testdata/notify/zone1.db",
client->view);
client->inner.view);
assert_int_equal(result, ISC_R_SUCCESS);
/*
@ -104,16 +104,16 @@ ISC_LOOP_TEST_IMPL(notify_start) {
}
client->message = nmsg;
nmsg = NULL;
client->sendcb = check_response;
ns_notify_start(client, client->handle);
client->inner.sendcb = check_response;
ns_notify_start(client, client->inner.handle);
/*
* Clean up
*/
ns_test_cleanup_zone();
handle = client->handle;
isc_nmhandle_detach(&client->handle);
handle = client->inner.handle;
isc_nmhandle_detach(&client->inner.handle);
isc_nmhandle_detach(&handle);
isc_loop_teardown(mainloop, shutdown_interfacemgr, NULL);

View File

@ -122,8 +122,9 @@ run_sfcache_test(const ns__query_sfcache_test_params_t *test) {
result = isc_time_nowplusinterval(&expire, &hour);
assert_int_equal(result, ISC_R_SUCCESS);
dns_badcache_add(qctx->client->view->failcache, dns_rootname,
dns_rdatatype_ns, test->cache_entry_flags,
dns_badcache_add(qctx->client->inner.view->failcache,
dns_rootname, dns_rdatatype_ns,
test->cache_entry_flags,
isc_time_seconds(&expire));
}
@ -315,7 +316,7 @@ run_start_test(const ns__query_start_test_params_t *test) {
/*
* Enable view->checknames by default, disable if requested.
*/
qctx->client->view->checknames = !test->disable_name_checks;
qctx->client->inner.view->checknames = !test->disable_name_checks;
/*
* Load zone from file and attach it to the client's view, if
@ -324,7 +325,7 @@ run_start_test(const ns__query_start_test_params_t *test) {
if (test->auth_zone_path != NULL) {
result = ns_test_serve_zone(test->auth_zone_origin,
test->auth_zone_path,
qctx->client->view);
qctx->client->inner.view);
assert_int_equal(result, ISC_R_SUCCESS);
}
@ -367,7 +368,8 @@ run_start_test(const ns__query_start_test_params_t *test) {
"query context, but some was",
test->id.description, test->id.lineno);
}
if (qctx->db == NULL || qctx->db != qctx->client->view->cachedb)
if (qctx->db == NULL ||
qctx->db != qctx->client->inner.view->cachedb)
{
fail_msg("# test \"%s\" on line %d: "
"cache database was expected to be "
@ -388,7 +390,7 @@ run_start_test(const ns__query_start_test_params_t *test) {
"context, but it was not",
test->id.description, test->id.lineno);
}
if (qctx->db == qctx->client->view->cachedb) {
if (qctx->db == qctx->client->inner.view->cachedb) {
fail_msg("# test \"%s\" on line %d: "
"cache database was not expected to be "
"attached to query context, but it is",
@ -887,7 +889,7 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) {
};
result = ns_test_qctx_create(&qctx_params, &qctx);
INSIST(result == ISC_R_SUCCESS);
qctx->client->sendcb = send_noop;
qctx->client->inner.sendcb = send_noop;
}
/*
@ -914,15 +916,15 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) {
test->do_cancel)
{
expect_servfail = true;
isc_nmhandle_attach(qctx->client->handle,
&qctx->client->reqhandle);
isc_nmhandle_attach(qctx->client->inner.handle,
&qctx->client->inner.reqhandle);
}
/*
* Emulate query handling from query_start.
* Specified hook should be called.
*/
qctx->client->state = NS_CLIENTSTATE_WORKING;
qctx->client->inner.state = NS_CLIENTSTATE_WORKING;
result = ns__query_start(qctx);
INSIST(result == ISC_R_UNSET);
@ -944,23 +946,23 @@ run_hookasync_test(const ns__query_hookasync_test_params_t *test) {
/* If async event has started, manually invoke the 'done' event. */
if (asdata.async) {
qctx->client->now = 0; /* set to sentinel before resume */
qctx->client->inner.now = 0; /* set to sentinel before resume */
asdata.rev->cb(asdata.rev);
/* Confirm necessary cleanup has been performed. */
INSIST(qctx->client->query.hookactx == NULL);
INSIST(qctx->client->state == NS_CLIENTSTATE_WORKING);
INSIST(qctx->client->inner.state == NS_CLIENTSTATE_WORKING);
INSIST(ns_stats_get_counter(
qctx->client->manager->sctx->nsstats,
ns_statscounter_recursclients) == 0);
INSIST(!ISC_LINK_LINKED(qctx->client, rlink));
INSIST(!ISC_LINK_LINKED(qctx->client, inner.rlink));
if (!test->do_cancel) {
/*
* In the normal case the client's timestamp is updated
* and the query handling has been resumed from the
* expected point.
*/
INSIST(qctx->client->now != 0);
INSIST(qctx->client->inner.now != 0);
INSIST(asdata.lasthookpoint == test->hookpoint2);
}
} else {
@ -1385,21 +1387,22 @@ run_hookasync_e2e_test(const ns__query_hookasync_e2e_test_params_t *test) {
result = ns_test_qctx_create(&qctx_params, &qctx);
INSIST(result == ISC_R_SUCCESS);
qctx->client->sendcb = send_noop;
qctx->client->inner.sendcb = send_noop;
/* Load a zone. it should have ns.foo/A */
result = ns_test_serve_zone("foo", TESTS_DIR "/testdata/query/foo.db",
qctx->client->view);
qctx->client->inner.view);
INSIST(result == ISC_R_SUCCESS);
/*
* We expect to have a response sent all cases, so we need to
* setup reqhandle (which will be detached on the send).
*/
isc_nmhandle_attach(qctx->client->handle, &qctx->client->reqhandle);
isc_nmhandle_attach(qctx->client->inner.handle,
&qctx->client->inner.reqhandle);
/* Handle the query. hook-based async event will be triggered. */
qctx->client->state = NS_CLIENTSTATE_WORKING;
qctx->client->inner.state = NS_CLIENTSTATE_WORKING;
ns__query_start(qctx);
/* If specified cancel the query at this point. */