mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-03 08:05:21 +00:00
Add NS records to the authority section when answering from a zone.
Do not put a name into a section more than once. Make restarts part of query state. We were leaking the old qname after a CNAME/DNAME restart. Update A6 follower calls to conform with interface changes.
This commit is contained in:
@@ -117,6 +117,7 @@ query_reset(ns_client_t *client, isc_boolean_t everything) {
|
|||||||
|
|
||||||
client->query.attributes = (NS_QUERYATTR_RECURSIONOK|
|
client->query.attributes = (NS_QUERYATTR_RECURSIONOK|
|
||||||
NS_QUERYATTR_CACHEOK);
|
NS_QUERYATTR_CACHEOK);
|
||||||
|
client->query.restarts = 0;
|
||||||
client->query.qname = NULL;
|
client->query.qname = NULL;
|
||||||
client->query.origqname = NULL;
|
client->query.origqname = NULL;
|
||||||
client->query.dboptions = 0;
|
client->query.dboptions = 0;
|
||||||
@@ -487,25 +488,42 @@ query_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type,
|
|||||||
|
|
||||||
static inline isc_boolean_t
|
static inline isc_boolean_t
|
||||||
query_isduplicate(ns_client_t *client, dns_name_t *name,
|
query_isduplicate(ns_client_t *client, dns_name_t *name,
|
||||||
dns_rdatatype_t type)
|
dns_rdatatype_t type, dns_name_t **mnamep)
|
||||||
{
|
{
|
||||||
dns_section_t section;
|
dns_section_t section;
|
||||||
dns_name_t *mname;
|
dns_name_t *mname = NULL;
|
||||||
|
dns_result_t result;
|
||||||
|
|
||||||
for (section = DNS_SECTION_ANSWER;
|
for (section = DNS_SECTION_ANSWER;
|
||||||
section <= DNS_SECTION_ADDITIONAL;
|
section <= DNS_SECTION_ADDITIONAL;
|
||||||
section++) {
|
section++) {
|
||||||
mname = NULL;
|
result = dns_message_findname(client->message, section,
|
||||||
if (dns_message_findname(client->message, section,
|
name, type, 0, &mname, NULL);
|
||||||
name, type, 0, &mname, NULL) ==
|
if (result == ISC_R_SUCCESS) {
|
||||||
ISC_R_SUCCESS) {
|
|
||||||
/*
|
/*
|
||||||
* We've already got this RRset in the response.
|
* We've already got this RRset in the response.
|
||||||
*/
|
*/
|
||||||
return (ISC_TRUE);
|
return (ISC_TRUE);
|
||||||
}
|
} else if (result == DNS_R_NXRDATASET) {
|
||||||
|
/*
|
||||||
|
* The name exists, but the rdataset does not.
|
||||||
|
*/
|
||||||
|
if (section == DNS_SECTION_ADDITIONAL)
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
RUNTIME_CHECK(result == DNS_R_NXDOMAIN);
|
||||||
|
mname = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the dns_name_t we're lookup up is already in the message,
|
||||||
|
* we don't want to trigger the caller's name replacement logic.
|
||||||
|
*/
|
||||||
|
if (name == mname)
|
||||||
|
mname = NULL;
|
||||||
|
|
||||||
|
*mnamep = mname;
|
||||||
|
|
||||||
return (ISC_FALSE);
|
return (ISC_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,14 +533,14 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
isc_result_t result, eresult;
|
isc_result_t result, eresult;
|
||||||
dns_dbnode_t *node, *znode;
|
dns_dbnode_t *node, *znode;
|
||||||
dns_db_t *db, *zdb;
|
dns_db_t *db, *zdb;
|
||||||
dns_name_t *fname, *zfname;
|
dns_name_t *fname, *zfname, *mname;
|
||||||
dns_rdataset_t *rdataset, *sigrdataset, *a6rdataset;
|
dns_rdataset_t *rdataset, *sigrdataset, *a6rdataset;
|
||||||
dns_rdataset_t *zrdataset, *zsigrdataset;
|
dns_rdataset_t *zrdataset, *zsigrdataset;
|
||||||
isc_buffer_t *dbuf;
|
isc_buffer_t *dbuf;
|
||||||
isc_buffer_t b;
|
isc_buffer_t b;
|
||||||
dns_dbversion_t *version, *zversion;
|
dns_dbversion_t *version, *zversion;
|
||||||
unsigned int dboptions;
|
unsigned int dboptions;
|
||||||
isc_boolean_t is_zone, nxglue, added_something;
|
isc_boolean_t is_zone, nxglue, added_something, need_addname;
|
||||||
|
|
||||||
REQUIRE(NS_CLIENT_VALID(client));
|
REQUIRE(NS_CLIENT_VALID(client));
|
||||||
REQUIRE(type != dns_rdatatype_any);
|
REQUIRE(type != dns_rdatatype_any);
|
||||||
@@ -547,6 +565,7 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
znode = NULL;
|
znode = NULL;
|
||||||
nxglue = ISC_FALSE;
|
nxglue = ISC_FALSE;
|
||||||
added_something = ISC_FALSE;
|
added_something = ISC_FALSE;
|
||||||
|
need_addname = ISC_FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a database to answer the query.
|
* Find a database to answer the query.
|
||||||
@@ -671,8 +690,14 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
if (dbuf != NULL)
|
if (dbuf != NULL)
|
||||||
query_keepname(client, fname, dbuf);
|
query_keepname(client, fname, dbuf);
|
||||||
|
|
||||||
|
mname = NULL;
|
||||||
if (rdataset->methods != NULL &&
|
if (rdataset->methods != NULL &&
|
||||||
!query_isduplicate(client, fname, type)) {
|
!query_isduplicate(client, fname, type, &mname)) {
|
||||||
|
if (mname != NULL) {
|
||||||
|
query_releasename(client, &fname);
|
||||||
|
fname = mname;
|
||||||
|
} else
|
||||||
|
need_addname = ISC_TRUE;
|
||||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||||
rdataset = NULL;
|
rdataset = NULL;
|
||||||
added_something = ISC_TRUE;
|
added_something = ISC_TRUE;
|
||||||
@@ -729,8 +754,14 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
sigrdataset);
|
sigrdataset);
|
||||||
}
|
}
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
mname = NULL;
|
||||||
if (!query_isduplicate(client, fname,
|
if (!query_isduplicate(client, fname,
|
||||||
dns_rdatatype_a6)) {
|
dns_rdatatype_a6, &mname)) {
|
||||||
|
if (mname != NULL) {
|
||||||
|
query_releasename(client, &fname);
|
||||||
|
fname = mname;
|
||||||
|
} else
|
||||||
|
need_addname = ISC_TRUE;
|
||||||
a6rdataset = rdataset;
|
a6rdataset = rdataset;
|
||||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||||
added_something = ISC_TRUE;
|
added_something = ISC_TRUE;
|
||||||
@@ -762,8 +793,14 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
sigrdataset);
|
sigrdataset);
|
||||||
}
|
}
|
||||||
if (result == ISC_R_SUCCESS) {
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
mname = NULL;
|
||||||
if (!query_isduplicate(client, fname,
|
if (!query_isduplicate(client, fname,
|
||||||
dns_rdatatype_aaaa)) {
|
dns_rdatatype_aaaa, &mname)) {
|
||||||
|
if (mname != NULL) {
|
||||||
|
query_releasename(client, &fname);
|
||||||
|
fname = mname;
|
||||||
|
} else
|
||||||
|
need_addname = ISC_TRUE;
|
||||||
ISC_LIST_APPEND(fname->list, rdataset, link);
|
ISC_LIST_APPEND(fname->list, rdataset, link);
|
||||||
added_something = ISC_TRUE;
|
added_something = ISC_TRUE;
|
||||||
if (sigrdataset->methods != NULL) {
|
if (sigrdataset->methods != NULL) {
|
||||||
@@ -784,10 +821,13 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally! Add the name and the rdatasets we found to the additional
|
* We may have added our rdatasets to an existing name, if so, then
|
||||||
* data section.
|
* need_addname will be ISC_FALSE. Whether we used an existing name
|
||||||
|
* or a new one, we must set fname to NULL to prevent cleanup.
|
||||||
*/
|
*/
|
||||||
dns_message_addname(client->message, fname, DNS_SECTION_ADDITIONAL);
|
if (need_addname)
|
||||||
|
dns_message_addname(client->message, fname,
|
||||||
|
DNS_SECTION_ADDITIONAL);
|
||||||
fname = NULL;
|
fname = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -828,8 +868,10 @@ query_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t type) {
|
|||||||
* know about the A6 chains. We wait until now to do this so that
|
* know about the A6 chains. We wait until now to do this so that
|
||||||
* they'll come after any additional data added above.
|
* they'll come after any additional data added above.
|
||||||
*/
|
*/
|
||||||
if (a6rdataset != NULL)
|
if (a6rdataset != NULL) {
|
||||||
|
dns_a6_reset(&client->query.a6ctx);
|
||||||
dns_a6_foreach(&client->query.a6ctx, a6rdataset);
|
dns_a6_foreach(&client->query.a6ctx, a6rdataset);
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
query_putrdataset(client, &rdataset);
|
query_putrdataset(client, &rdataset);
|
||||||
@@ -860,7 +902,7 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset,
|
|||||||
ns_client_t *client = arg;
|
ns_client_t *client = arg;
|
||||||
dns_rdataset_t *crdataset, *csigrdataset;
|
dns_rdataset_t *crdataset, *csigrdataset;
|
||||||
isc_buffer_t b, *dbuf;
|
isc_buffer_t b, *dbuf;
|
||||||
dns_name_t *fname;
|
dns_name_t *fname, *mname;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add an rrset to the additional data section.
|
* Add an rrset to the additional data section.
|
||||||
@@ -890,9 +932,18 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset,
|
|||||||
if (sigrdataset->methods != NULL)
|
if (sigrdataset->methods != NULL)
|
||||||
dns_rdataset_clone(sigrdataset, csigrdataset);
|
dns_rdataset_clone(sigrdataset, csigrdataset);
|
||||||
|
|
||||||
if (query_isduplicate(client, fname, crdataset->type))
|
mname = NULL;
|
||||||
|
if (query_isduplicate(client, fname, crdataset->type, &mname))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
query_keepname(client, fname, dbuf);
|
if (mname != NULL) {
|
||||||
|
query_releasename(client, &fname);
|
||||||
|
fname = mname;
|
||||||
|
} else {
|
||||||
|
query_keepname(client, fname, dbuf);
|
||||||
|
dns_message_addname(client->message, fname,
|
||||||
|
DNS_SECTION_ADDITIONAL);
|
||||||
|
}
|
||||||
|
|
||||||
ISC_LIST_APPEND(fname->list, crdataset, link);
|
ISC_LIST_APPEND(fname->list, crdataset, link);
|
||||||
crdataset = NULL;
|
crdataset = NULL;
|
||||||
/*
|
/*
|
||||||
@@ -905,7 +956,6 @@ query_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset,
|
|||||||
csigrdataset = NULL;
|
csigrdataset = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dns_message_addname(client->message, fname, DNS_SECTION_ADDITIONAL);
|
|
||||||
fname = NULL;
|
fname = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -933,9 +983,10 @@ query_addrdataset(ns_client_t *client, dns_name_t *fname,
|
|||||||
* We don't care if dns_a6_foreach or dns_rdataset_additionaldata()
|
* We don't care if dns_a6_foreach or dns_rdataset_additionaldata()
|
||||||
* fail.
|
* fail.
|
||||||
*/
|
*/
|
||||||
if (type == dns_rdatatype_a6)
|
if (type == dns_rdatatype_a6) {
|
||||||
|
dns_a6_reset(&client->query.a6ctx);
|
||||||
(void)dns_a6_foreach(&client->query.a6ctx, rdataset);
|
(void)dns_a6_foreach(&client->query.a6ctx, rdataset);
|
||||||
else
|
} else
|
||||||
(void)dns_rdataset_additionaldata(rdataset,
|
(void)dns_rdataset_additionaldata(rdataset,
|
||||||
query_addadditional, client);
|
query_addadditional, client);
|
||||||
/*
|
/*
|
||||||
@@ -1073,6 +1124,66 @@ query_addsoa(ns_client_t *client, dns_db_t *db) {
|
|||||||
return (eresult);
|
return (eresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline isc_result_t
|
||||||
|
query_addns(ns_client_t *client, dns_db_t *db) {
|
||||||
|
dns_name_t *name, *fname;
|
||||||
|
dns_dbnode_t *node;
|
||||||
|
isc_result_t result, eresult;
|
||||||
|
dns_fixedname_t foundname;
|
||||||
|
dns_rdataset_t *rdataset, *sigrdataset;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization.
|
||||||
|
*/
|
||||||
|
eresult = ISC_R_SUCCESS;
|
||||||
|
name = NULL;
|
||||||
|
rdataset = NULL;
|
||||||
|
node = NULL;
|
||||||
|
dns_fixedname_init(&foundname);
|
||||||
|
fname = dns_fixedname_name(&foundname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get resources and make 'name' be the database origin.
|
||||||
|
*/
|
||||||
|
result = dns_message_gettempname(client->message, &name);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
return (result);
|
||||||
|
dns_name_init(name, NULL);
|
||||||
|
dns_name_clone(dns_db_origin(db), name);
|
||||||
|
rdataset = query_newrdataset(client);
|
||||||
|
sigrdataset = query_newrdataset(client);
|
||||||
|
if (rdataset == NULL || sigrdataset == NULL) {
|
||||||
|
eresult = DNS_R_SERVFAIL;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the NS rdataset.
|
||||||
|
*/
|
||||||
|
result = dns_db_find(db, name, NULL, dns_rdatatype_ns, 0, 0, &node,
|
||||||
|
fname, rdataset, sigrdataset);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
/*
|
||||||
|
* This is bad. We tried to get the NS rdataset at the zone
|
||||||
|
* top and it didn't work!
|
||||||
|
*/
|
||||||
|
eresult = DNS_R_SERVFAIL;
|
||||||
|
} else {
|
||||||
|
query_addrrset(client, &name, &rdataset, &sigrdataset, NULL,
|
||||||
|
DNS_SECTION_AUTHORITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
query_putrdataset(client, &rdataset);
|
||||||
|
query_putrdataset(client, &sigrdataset);
|
||||||
|
if (name != NULL)
|
||||||
|
query_releasename(client, &name);
|
||||||
|
if (node != NULL)
|
||||||
|
dns_db_detachnode(db, &node);
|
||||||
|
|
||||||
|
return (eresult);
|
||||||
|
}
|
||||||
|
|
||||||
static inline isc_result_t
|
static inline isc_result_t
|
||||||
query_checktype(dns_rdatatype_t type) {
|
query_checktype(dns_rdatatype_t type) {
|
||||||
|
|
||||||
@@ -1171,7 +1282,7 @@ query_find(ns_client_t *client) {
|
|||||||
dns_rdata_t rdata;
|
dns_rdata_t rdata;
|
||||||
dns_rdatasetiter_t *rdsiter;
|
dns_rdatasetiter_t *rdsiter;
|
||||||
isc_boolean_t want_restart, auth, is_zone, clear_fname;
|
isc_boolean_t want_restart, auth, is_zone, clear_fname;
|
||||||
unsigned int restarts, qcount, n, nlabels, nbits;
|
unsigned int qcount, n, nlabels, nbits;
|
||||||
dns_namereln_t namereln;
|
dns_namereln_t namereln;
|
||||||
int order;
|
int order;
|
||||||
isc_buffer_t *dbuf;
|
isc_buffer_t *dbuf;
|
||||||
@@ -1189,7 +1300,6 @@ query_find(ns_client_t *client) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
eresult = ISC_R_SUCCESS;
|
eresult = ISC_R_SUCCESS;
|
||||||
restarts = 0;
|
|
||||||
fname = NULL;
|
fname = NULL;
|
||||||
zfname = NULL;
|
zfname = NULL;
|
||||||
rdataset = NULL;
|
rdataset = NULL;
|
||||||
@@ -1467,7 +1577,7 @@ query_find(ns_client_t *client) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
case DNS_R_NXDOMAIN:
|
case DNS_R_NXDOMAIN:
|
||||||
INSIST(is_zone);
|
INSIST(is_zone);
|
||||||
if (restarts > 0) {
|
if (client->query.restarts > 0) {
|
||||||
/*
|
/*
|
||||||
* We hit a dead end following a CNAME or DNAME.
|
* We hit a dead end following a CNAME or DNAME.
|
||||||
*/
|
*/
|
||||||
@@ -1553,9 +1663,17 @@ query_find(ns_client_t *client) {
|
|||||||
r.length = rdata.length;
|
r.length = rdata.length;
|
||||||
dns_name_init(tname, NULL);
|
dns_name_init(tname, NULL);
|
||||||
dns_name_fromregion(tname, &r);
|
dns_name_fromregion(tname, &r);
|
||||||
|
if (client->query.restarts > 0) {
|
||||||
|
/*
|
||||||
|
* client->query.qname was dynamically allocated.
|
||||||
|
* We must free it before we set it.
|
||||||
|
*/
|
||||||
|
dns_message_puttempname(client->message,
|
||||||
|
&client->query.qname);
|
||||||
|
}
|
||||||
client->query.qname = tname;
|
client->query.qname = tname;
|
||||||
want_restart = ISC_TRUE;
|
want_restart = ISC_TRUE;
|
||||||
goto cleanup;
|
goto addauth;
|
||||||
case DNS_R_DNAME:
|
case DNS_R_DNAME:
|
||||||
/*
|
/*
|
||||||
* Compare the current qname to the found name. We need
|
* Compare the current qname to the found name. We need
|
||||||
@@ -1626,10 +1744,18 @@ query_find(ns_client_t *client) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
query_keepname(client, fname, dbuf);
|
query_keepname(client, fname, dbuf);
|
||||||
|
if (client->query.restarts > 0) {
|
||||||
|
/*
|
||||||
|
* client->query.qname was dynamically allocated.
|
||||||
|
* We must free it before we set it.
|
||||||
|
*/
|
||||||
|
dns_message_puttempname(client->message,
|
||||||
|
&client->query.qname);
|
||||||
|
}
|
||||||
client->query.qname = fname;
|
client->query.qname = fname;
|
||||||
fname = NULL;
|
fname = NULL;
|
||||||
want_restart = ISC_TRUE;
|
want_restart = ISC_TRUE;
|
||||||
goto cleanup;
|
goto addauth;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* Something has gone wrong.
|
* Something has gone wrong.
|
||||||
@@ -1774,7 +1900,21 @@ query_find(ns_client_t *client) {
|
|||||||
* OK) launch queries for any types we don't have answers to.
|
* OK) launch queries for any types we don't have answers to.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
addauth:
|
||||||
|
/*
|
||||||
|
* Add NS records for the zone to the authority section (if we
|
||||||
|
* haven't already added them to the answer section).
|
||||||
|
*/
|
||||||
|
if (client->query.restarts == 0 &&
|
||||||
|
is_zone &&
|
||||||
|
!(qtype == dns_rdatatype_ns &&
|
||||||
|
dns_name_equal(client->query.qname, dns_db_origin(db))))
|
||||||
|
query_addns(client, db);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
/*
|
||||||
|
* General cleanup.
|
||||||
|
*/
|
||||||
query_putrdataset(client, &rdataset);
|
query_putrdataset(client, &rdataset);
|
||||||
query_putrdataset(client, &sigrdataset);
|
query_putrdataset(client, &sigrdataset);
|
||||||
if (fname != NULL)
|
if (fname != NULL)
|
||||||
@@ -1791,7 +1931,10 @@ query_find(ns_client_t *client) {
|
|||||||
dns_db_detach(&zdb);
|
dns_db_detach(&zdb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restarts == 0 && !auth) {
|
/*
|
||||||
|
* AA bit.
|
||||||
|
*/
|
||||||
|
if (client->query.restarts == 0 && !auth) {
|
||||||
/*
|
/*
|
||||||
* We're not authoritative, so we must ensure the AA bit
|
* We're not authoritative, so we must ensure the AA bit
|
||||||
* isn't set.
|
* isn't set.
|
||||||
@@ -1799,11 +1942,25 @@ query_find(ns_client_t *client) {
|
|||||||
client->message->flags &= ~DNS_MESSAGEFLAG_AA;
|
client->message->flags &= ~DNS_MESSAGEFLAG_AA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_restart && restarts < MAX_RESTARTS) {
|
/*
|
||||||
restarts++;
|
* Restart the query?
|
||||||
|
*/
|
||||||
|
if (want_restart && client->query.restarts < MAX_RESTARTS) {
|
||||||
|
client->query.restarts++;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cleanup qname?
|
||||||
|
*/
|
||||||
|
if (client->query.restarts > 0) {
|
||||||
|
/*
|
||||||
|
* client->query.qname was dynamically allocated.
|
||||||
|
* We must free it.
|
||||||
|
*/
|
||||||
|
dns_message_puttempname(client->message, &client->query.qname);
|
||||||
|
}
|
||||||
|
|
||||||
if (eresult != ISC_R_SUCCESS && !PARTIALANSWER(client))
|
if (eresult != ISC_R_SUCCESS && !PARTIALANSWER(client))
|
||||||
ns_client_error(client, eresult);
|
ns_client_error(client, eresult);
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user