isc_boolean_t want_dnssec;
isc_boolean_t want_validation;
isc_boolean_t want_cdflag;
+ isc_boolean_t want_tcp;
/* Locked */
ISC_LINK(struct resctx) link;
unsigned int magic;
isc_mutex_t lock;
dns_client_t *client;
+ isc_boolean_t want_tcp;
/* Locked */
dns_request_t *updatereq;
fopts |= DNS_FETCHOPT_NOCDFLAG;
if (!rctx->want_validation)
fopts |= DNS_FETCHOPT_NOVALIDATE;
+ if (rctx->want_tcp)
+ fopts |= DNS_FETCHOPT_TCP;
result = dns_resolver_createfetch(rctx->view->resolver,
dns_fixedname_name(&rctx->name),
isc_mem_t *mctx;
isc_result_t result;
dns_rdataset_t *rdataset, *sigrdataset;
- isc_boolean_t want_dnssec, want_validation, want_cdflag;
+ isc_boolean_t want_dnssec, want_validation, want_cdflag, want_tcp;
REQUIRE(DNS_CLIENT_VALID(client));
REQUIRE(transp != NULL && *transp == NULL);
want_dnssec = ISC_TF((options & DNS_CLIENTRESOPT_NODNSSEC) == 0);
want_validation = ISC_TF((options & DNS_CLIENTRESOPT_NOVALIDATE) == 0);
want_cdflag = ISC_TF((options & DNS_CLIENTRESOPT_NOCDFLAG) == 0);
+ want_tcp = ISC_TF((options & DNS_CLIENTRESOPT_TCP) != 0);
/*
* Prepare some intermediate resources
rctx->want_dnssec = want_dnssec;
rctx->want_validation = want_validation;
rctx->want_cdflag = want_cdflag;
+ rctx->want_tcp = want_tcp;
ISC_LIST_INIT(rctx->namelist);
rctx->event = event;
dns_clientreqevent_t *event = NULL;
reqctx_t *ctx = NULL;
dns_tsectype_t tsectype = dns_tsectype_none;
-
- UNUSED(options);
+ unsigned int reqoptions;
REQUIRE(DNS_CLIENT_VALID(client));
REQUIRE(qmessage != NULL);
if (result != ISC_R_SUCCESS)
return (result);
+ reqoptions = 0;
+ if ((options & DNS_CLIENTREQOPT_TCP) != 0)
+ reqoptions |= DNS_REQUESTOPT_TCP;
+
clone = NULL;
isc_task_attach(task, &clone);
event = (dns_clientreqevent_t *)
ctx->request = NULL;
result = dns_request_createvia3(view->requestmgr, qmessage, NULL,
- server, options, ctx->tsigkey,
+ server, reqoptions, ctx->tsigkey,
timeout, udptimeout, udpretries,
client->task, request_done, ctx,
&ctx->request);
dns_message_t *answer = NULL;
updatectx_t *uctx = event->ev_arg;
dns_client_t *client;
- unsigned int timeout;
+ unsigned int timeout, reqoptions;
UNUSED(task);
timeout = client->update_timeout / uctx->nservers;
if (timeout < MIN_UPDATE_TIMEOUT)
timeout = MIN_UPDATE_TIMEOUT;
+ reqoptions = 0;
+ if (uctx->want_tcp)
+ reqoptions |= DNS_REQUESTOPT_TCP;
result = dns_request_createvia3(uctx->view->requestmgr,
uctx->updatemsg,
NULL,
- uctx->currentserver, 0,
+ uctx->currentserver,
+ reqoptions,
uctx->tsigkey,
timeout,
client->update_udptimeout,
dns_name_t *name = NULL;
dns_rdataset_t *rdataset = NULL;
dns_client_t *client = uctx->client;
- unsigned int timeout;
+ unsigned int timeout, reqoptions;
REQUIRE(uctx->zonename != NULL && uctx->currentserver != NULL);
timeout = client->update_timeout / uctx->nservers;
if (timeout < MIN_UPDATE_TIMEOUT)
timeout = MIN_UPDATE_TIMEOUT;
+ reqoptions = 0;
+ if (uctx->want_tcp)
+ reqoptions |= DNS_REQUESTOPT_TCP;
result = dns_request_createvia3(uctx->view->requestmgr,
uctx->updatemsg,
- NULL, uctx->currentserver, 0,
- uctx->tsigkey, timeout,
+ NULL, uctx->currentserver,
+ reqoptions, uctx->tsigkey, timeout,
client->update_udptimeout,
client->update_udpretries,
client->task, update_done, uctx,
dns_rdata_t soarr = DNS_RDATA_INIT;
dns_rdata_soa_t soa;
dns_name_t primary;
+ unsigned int resoptions;
result = dns_rdataset_first(soaset);
if (result != ISC_R_SUCCESS)
*/
LOCK(&uctx->lock);
uctx->bp4 = uctx;
+ resoptions = 0;
+ if (uctx->want_tcp)
+ resoptions |= DNS_CLIENTRESOPT_TCP;
result = dns_client_startresolve(uctx->client, &primary,
uctx->rdclass,
dns_rdatatype_a,
- 0, uctx->client->task,
+ resoptions,
+ uctx->client->task,
resolveaddr_done, &uctx->bp4,
&uctx->restrans);
if (result == ISC_R_SUCCESS) {
&primary,
uctx->rdclass,
dns_rdatatype_aaaa,
- 0, uctx->client->task,
+ resoptions,
+ uctx->client->task,
resolveaddr_done,
&uctx->bp6,
&uctx->restrans2);
isc_boolean_t seencname = ISC_FALSE;
isc_boolean_t droplabel = ISC_FALSE;
dns_name_t tname;
- unsigned int nlabels;
+ unsigned int nlabels, reqoptions;
UNUSED(task);
/* Retry SOA request without TSIG */
dns_message_destroy(&rcvmsg);
dns_message_renderreset(uctx->soaquery);
+ reqoptions = 0;
+ if (uctx->want_tcp)
+ reqoptions |= DNS_REQUESTOPT_TCP;
result = dns_request_createvia3(uctx->view->requestmgr,
- uctx->soaquery, NULL, addr, 0,
- NULL,
+ uctx->soaquery, NULL, addr,
+ reqoptions, NULL,
client->find_timeout * 20,
client->find_timeout, 3,
uctx->client->task,
UNLOCK(&uctx->lock);
dns_message_renderreset(soaquery);
dns_message_settsigkey(soaquery, NULL);
+ reqoptions = 0;
+ if (uctx->want_tcp)
+ reqoptions |= DNS_REQUESTOPT_TCP;
result = dns_request_createvia3(uctx->view->requestmgr,
soaquery, NULL,
- uctx->currentserver, 0,
+ uctx->currentserver,
+ reqoptions,
uctx->tsigkey,
client->find_timeout *
20,
dns_message_t *soaquery = uctx->soaquery;
dns_name_t *name = NULL;
dns_rdataset_t *rdataset = NULL;
+ unsigned int reqoptions;
if (soaquery == NULL) {
result = dns_message_create(uctx->client->mctx,
dns_message_addname(soaquery, name, DNS_SECTION_QUESTION);
rdataset = NULL;
name = NULL;
+ reqoptions = 0;
+ if (uctx->want_tcp)
+ reqoptions |= DNS_REQUESTOPT_TCP;
result = dns_request_createvia3(uctx->view->requestmgr,
- soaquery, NULL, uctx->currentserver, 0,
- uctx->tsigkey,
+ soaquery, NULL, uctx->currentserver,
+ reqoptions, uctx->tsigkey,
uctx->client->find_timeout * 20,
uctx->client->find_timeout, 3,
uctx->client->task, receive_soa, uctx,
dns_name_t *name, tname;
dns_rdataset_t *rdataset = NULL;
isc_result_t result = rev->result;
- unsigned int nlabels;
+ unsigned int nlabels, resoptions;
UNUSED(task);
dns_name_getlabelsequence(&uctx->soaqname, 1, nlabels - 1,
&tname);
dns_name_clone(&tname, &uctx->soaqname);
+ resoptions = 0;
+ if (uctx->want_tcp)
+ resoptions |= DNS_CLIENTRESOPT_TCP;
result = dns_client_startresolve(uctx->client, &uctx->soaqname,
uctx->rdclass,
- dns_rdatatype_soa, 0,
+ dns_rdatatype_soa,
+ resoptions,
uctx->client->task,
resolvesoa_done, uctx,
&uctx->restrans);
REQUIRE(DNS_CLIENT_VALID(client));
if ((client->attributes & DNS_CLIENTATTR_OWNCTX) == 0 &&
- (options & DNS_CLIENTRESOPT_ALLOWRUN) == 0) {
+ (options & DNS_CLIENTUPDOPT_ALLOWRUN) == 0) {
/*
* If the client is run under application's control, we need
* to create a new running (sub)environment for this
- * particular resolution.
+ * particular update.
*/
return (ISC_R_NOTIMPLEMENTED); /* XXXTBD */
} else
dns_section_t section = DNS_SECTION_UPDATE;
isc_sockaddr_t *server, *sa = NULL;
dns_tsectype_t tsectype = dns_tsectype_none;
+ isc_boolean_t want_tcp;
+ unsigned int resoptions;
UNUSED(options);
UNLOCK(&client->lock);
if (result != ISC_R_SUCCESS)
return (result);
+ want_tcp = ISC_TF((options & DNS_CLIENTUPDOPT_TCP) != 0);
/* Create a context and prepare some resources */
uctx = isc_mem_get(client->mctx, sizeof(*uctx));
uctx->tsigkey = NULL;
uctx->sig0key = NULL;
uctx->zonename = NULL;
+ uctx->want_tcp = want_tcp;
dns_name_init(&uctx->soaqname, NULL);
ISC_LIST_INIT(uctx->servers);
uctx->nservers = 0;
if (result != ISC_R_SUCCESS)
goto fail;
} else {
+ resoptions = 0;
+ if (want_tcp)
+ resoptions |= DNS_CLIENTRESOPT_TCP;
dns_name_clone(uctx->firstname, &uctx->soaqname);
result = dns_client_startresolve(uctx->client, &uctx->soaqname,
uctx->rdclass,
- dns_rdatatype_soa, 0,
+ dns_rdatatype_soa, resoptions,
client->task, resolvesoa_done,
uctx, &uctx->restrans);
if (result != ISC_R_SUCCESS)
#define DNS_CLIENTRESOPT_NOVALIDATE 0x04
/*%< Don't set the CD flag on upstream queries. */
#define DNS_CLIENTRESOPT_NOCDFLAG 0x08
+/*%< Use TCP transport. */
+#define DNS_CLIENTRESOPT_TCP 0x10
/*%
* Optional flags for dns_client_(start)request.
*/
/*%< Allow running external context. */
#define DNS_CLIENTREQOPT_ALLOWRUN 0x01
+/*%< Use TCP transport. */
+#define DNS_CLIENTREQOPT_TCP 0x02
+
+/*%
+ * Optional flags for dns_client_(start)update.
+ */
+/*%< Allow running external context. */
+#define DNS_CLIENTUPDOPT_ALLOWRUN 0x01
+/*%< Use TCP transport. */
+#define DNS_CLIENTUPDOPT_TCP 0x02
/*%
* A dns_clientresevent_t is sent when name resolution performed by a client
*
* If any trusted keys are configured and the query name is considered to
* belong to a secure zone, these functions also validate the responses
- * using DNSSEC by default. If the DNS_CLIENTRESOPT_NODNSSEC flag is set
+ * using DNSSEC by default. If the DNS_CLIENTRESOPT_NOVALIDATE flag is set
* in 'options', DNSSEC validation is disabled regardless of the configured
- * trusted keys or the query name.
+ * trusted keys or the query name. With DNS_CLIENTRESOPT_NODNSSEC
+ * DNSSEC data is not returned with response. DNS_CLIENTRESOPT_NOCDFLAG
+ * disables the CD flag on queries, DNS_CLIENTRESOPT_TCP switches to
+ * the TCP (vs. UDP) transport.
*
* dns_client_resolve() provides a synchronous service. This function starts
* name resolution internally and blocks until it completes. On success,
* the response message (on success). On return, '*transp' is set to an opaque
* transaction ID so that the caller can cancel this request.
*
+ * DNS_CLIENTREQOPT_TCP switches to the TCP (vs. UDP) transport.
+ *
* Requires:
*
*\li 'client' is a valid client.
* NULL, in which case the library tries the update without any transaction
* authentication.
*
+ * It is typically expected that the client object passed to
+ * dns_client_update() was created via dns_client_create() and has its own
+ * managers and contexts. However, if the DNS_CLIENTUPDOPT_ALLOWRUN flag is
+ * set in 'options', this function performs the synchronous service even if
+ * it does not have its own manager and context structures.
+ *
* dns_client_update() provides a synchronous service. This function blocks
* until the entire update procedure completes, including the additional
* queries when necessary.
* structure. On return, '*transp' is set to an opaque transaction ID so that
* the caller can cancel this update process.
*
- * Notes:
- *\li No options are currently defined.
+ * DNS_CLIENTUPDOPT_TCP switches to the TCP (vs. UDP) transport.
*
* Requires:
*