/* Serial number */
result = dns_zone_getserial(mayberaw, &serial);
- /* XXXWPK TODO this is to mirror old behavior with dns_zone_getserial */
+
+ /* This is to mirror old behavior with dns_zone_getserial */
if (result != ISC_R_SUCCESS) {
serial = 0;
}
+
snprintf(serbuf, sizeof(serbuf), "%u", serial);
if (hasraw) {
result = dns_zone_getserial(zone, &signed_serial);
- /* XXXWPK TODO ut supra */
if (result != ISC_R_SUCCESS) {
serial = 0;
}
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
recursion yes;
+ dnssec-validation yes;
};
view normal {
*/
void
-isc_nmhandle_ref(isc_nmhandle_t *handle);
+isc_nmhandle_attach(isc_nmhandle_t *handle, isc_nmhandle_t **dest);
void
-isc_nmhandle_unref(isc_nmhandle_t *handle);
+isc_nmhandle_detach(isc_nmhandle_t **handlep);
/*%<
* Increment/decrement the reference counter in a netmgr handle,
* but (unlike the attach/detach functions) do not change the pointer
sock->statichandle = NULL;
if (sock->outerhandle != NULL) {
- isc_nmhandle_unref(sock->outerhandle);
- sock->outerhandle = NULL;
+ isc_nmhandle_detach(&sock->outerhandle);
}
if (sock->outer != NULL) {
(sock->type == isc_nm_udpsocket && atomic_load(&sock->client)))
{
INSIST(sock->statichandle == NULL);
+
+ /*
+ * statichandle must be assigned, not attached;
+ * otherwise, if a handle was detached elsewhere
+ * it could never reach 0 references, and the
+ * handle and socket would never be freed.
+ */
sock->statichandle = handle;
}
}
void
-isc_nmhandle_ref(isc_nmhandle_t *handle) {
+isc_nmhandle_attach(isc_nmhandle_t *handle, isc_nmhandle_t **handlep) {
REQUIRE(VALID_NMHANDLE(handle));
+ REQUIRE(handlep != NULL && *handlep == NULL);
isc_refcount_increment(&handle->references);
+ *handlep = handle;
}
bool
}
void
-isc_nmhandle_unref(isc_nmhandle_t *handle) {
+isc_nmhandle_detach(isc_nmhandle_t **handlep) {
isc_nmsocket_t *sock = NULL;
+ isc_nmhandle_t *handle = NULL;
- REQUIRE(VALID_NMHANDLE(handle));
+ REQUIRE(handlep != NULL);
+ REQUIRE(VALID_NMHANDLE(*handlep));
+
+ handle = *handlep;
+ *handlep = NULL;
if (isc_refcount_decrement(&handle->references) > 1) {
return;
}
+
/* We need an acquire memory barrier here */
(void)isc_refcount_current(&handle->references);
}
if (handle == sock->statichandle) {
+ /* statichandle is assigned, not attached. */
sock->statichandle = NULL;
}
}
if (handle != NULL) {
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&handle);
}
isc__nmsocket_detach(&sock);
isc__nmsocket_detach(&sock);
/*
- * If the connect callback wants to hold on to the handle,
- * it needs to attach to it.
+ * The connect callback should have attached to the handle.
+ * If it didn't, the socket will be closed now.
*/
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&handle);
}
isc_result_t
isc__nmsocket_detach(&csock);
/*
- * If the accept callback wants to hold on to the handle,
- * it needs to attach to it.
+ * The accept callback should have attached to the handle.
+ * If it didn't, the socket will be closed now.
*/
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&handle);
return;
error:
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
uvreq->uvbuf.base = (char *)region->base;
uvreq->uvbuf.len = region->length;
- uvreq->handle = handle;
- isc_nmhandle_ref(uvreq->handle);
+ isc_nmhandle_attach(handle, &uvreq->handle);
uvreq->cb.send = cb;
uvreq->cbarg = cbarg;
uvreq->cb.send(uvreq->handle, result, uvreq->cbarg);
sock = uvreq->handle->sock;
- isc_nmhandle_unref(uvreq->handle);
isc__nm_uvreq_put(&uvreq, sock);
}
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_tcpsocket);
-
- isc_nmhandle_ref(req->handle);
r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, &req->uvbuf,
1, tcp_send_cb);
if (r < 0) {
sock = handle->sock;
+ REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tcpsocket);
if (atomic_load(&sock->client) && sock->rcb.recv != NULL) {
REQUIRE(sock->tid == isc_nm_tid());
/* Close the TCP connection; its closure should fire ours. */
- isc_nmhandle_unref(sock->outerhandle);
- sock->outerhandle = NULL;
+ isc_nmhandle_detach(&sock->outerhandle);
}
/*
dnslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
isc_nmsocket_t *dnslistensock = (isc_nmsocket_t *)cbarg;
isc_nmsocket_t *dnssock = NULL;
+ isc_nmhandle_t *readhandle = NULL;
REQUIRE(VALID_NMSOCK(dnslistensock));
REQUIRE(dnslistensock->type == isc_nm_tcpdnslistener);
isc__nmsocket_attach(dnssock, &dnssock->self);
- dnssock->outerhandle = handle;
- isc_nmhandle_ref(dnssock->outerhandle);
+ isc_nmhandle_attach(handle, &dnssock->outerhandle);
dnssock->peer = handle->sock->peer;
dnssock->read_timeout = handle->sock->mgr->init;
uv_timer_start(&dnssock->timer, dnstcp_readtimeout,
dnssock->read_timeout, 0);
- isc_nmhandle_ref(handle);
- result = isc_nm_read(handle, dnslisten_readcb, dnssock);
+ /*
+ * Add a reference to handle to keep it from being freed by
+ * the caller. It will be detached in dnslisted_readcb() when
+ * the connection is closed or there is no more data to be read.
+ */
+ isc_nmhandle_attach(handle, &readhandle);
+ result = isc_nm_read(readhandle, dnslisten_readcb, dnssock);
if (result != ISC_R_SUCCESS) {
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&readhandle);
}
isc__nmsocket_detach(&dnssock);
*/
len = dnslen(dnssock->buf);
if (len <= dnssock->buf_len - 2) {
- isc_nmhandle_t *dnshandle;
+ isc_nmhandle_t *dnshandle = NULL;
+ isc_nmsocket_t *listener = NULL;
+
if (atomic_load(&dnssock->client) &&
dnssock->statichandle != NULL) {
- dnshandle = dnssock->statichandle;
- isc_nmhandle_ref(dnshandle);
+ isc_nmhandle_attach(dnssock->statichandle, &dnshandle);
} else {
dnshandle = isc__nmhandle_get(dnssock, NULL, NULL);
}
- isc_nmsocket_t *listener = dnssock->listener;
-
+ listener = dnssock->listener;
if (listener != NULL && listener->rcb.recv != NULL) {
listener->rcb.recv(
dnshandle, ISC_R_SUCCESS,
}
/*
- * We've got a read on our underlying socket, need to check if we have
- * a complete DNS packet and, if so - call the callback
+ * We've got a read on our underlying socket. Check whether
+ * we have a complete DNS packet and, if so, call the callback.
*/
static void
dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
if (region == NULL || eresult != ISC_R_SUCCESS) {
/* Connection closed */
- if (eresult != ISC_R_CANCELED) {
- isc_nmhandle_unref(handle);
- }
dnssock->result = eresult;
if (dnssock->self != NULL) {
isc__nmsocket_detach(&dnssock->self);
}
isc__nmsocket_clearcb(dnssock);
if (dnssock->outerhandle != NULL) {
- isc_nmhandle_unref(dnssock->outerhandle);
- dnssock->outerhandle = NULL;
+ isc_nmhandle_detach(&dnssock->outerhandle);
}
+ isc_nmhandle_detach(&handle);
return;
}
if (atomic_load(&dnssock->sequential) ||
dnssock->rcb.recv == NULL) {
/*
- * Two reasons we might want to pause here:
- * - If we're in sequential mode and we've received
+ * There are two reasons we might want to pause here:
+ * - We're in sequential mode and we've received
* a whole packet, so we're done until it's been
- * processed;
- * - If we no longer have a read callback.
+ * processed; or
+ * - We no longer have a read callback.
*/
isc_nm_pauseread(dnssock->outerhandle);
done = true;
}
}
- isc_nmhandle_unref(dnshandle);
+ isc_nmhandle_detach(&dnshandle);
} while (!done);
}
if (sock->timer_initialized) {
uv_timer_stop(&sock->timer);
}
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&handle);
} else if (sock->outerhandle != NULL) {
result = isc_nm_resumeread(sock->outerhandle);
if (result != ISC_R_SUCCESS) {
- isc_nmhandle_unref(sock->outerhandle);
- sock->outerhandle = NULL;
+ isc_nmhandle_detach(&sock->outerhandle);
}
}
uv_timer_stop(&sock->timer);
}
atomic_store(&sock->outerhandle->sock->processing, true);
- isc_nmhandle_unref(dnshandle);
+ isc_nmhandle_detach(&dnshandle);
} while (atomic_load(&sock->ah) < TCPDNS_CLIENTS_PER_CONN);
}
req->cb.send(req->handle, result, req->cbarg);
isc_mem_put(req->sock->mgr->mctx, req->uvbuf.base, req->uvbuf.len);
isc__nm_uvreq_put(&req, req->handle->sock);
+ isc_nmhandle_detach(&handle);
}
void
result = ISC_R_NOTCONNECTED;
if (atomic_load(&sock->active) && sock->outerhandle != NULL) {
+ isc_nmhandle_t *sendhandle = NULL;
isc_region_t r;
r.base = (unsigned char *)req->uvbuf.base;
r.length = req->uvbuf.len;
- result = isc_nm_send(sock->outerhandle, &r, tcpdnssend_cb, req);
+ isc_nmhandle_attach(sock->outerhandle, &sendhandle);
+ result = isc_nm_send(sendhandle, &r, tcpdnssend_cb, req);
+ if (result != ISC_R_SUCCESS) {
+ isc_nmhandle_detach(&sendhandle);
+ }
}
if (result != ISC_R_SUCCESS) {
REQUIRE(sock->type == isc_nm_tcpdnssocket);
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
- uvreq->handle = handle;
- isc_nmhandle_ref(uvreq->handle);
+ isc_nmhandle_attach(handle, &uvreq->handle);
uvreq->cb.send = cb;
uvreq->cbarg = cbarg;
memmove(uvreq->uvbuf.base + 2, region->base, region->length);
if (sock->tid == isc_nm_tid()) {
+ isc_result_t result;
+ isc_nmhandle_t *sendhandle = NULL;
isc_region_t r;
r.base = (unsigned char *)uvreq->uvbuf.base;
r.length = uvreq->uvbuf.len;
- return (isc_nm_send(sock->outerhandle, &r, tcpdnssend_cb,
- uvreq));
+ isc_nmhandle_attach(sock->outerhandle, &sendhandle);
+ result = isc_nm_send(sock->outerhandle, &r, tcpdnssend_cb,
+ uvreq);
+ if (result != ISC_R_SUCCESS) {
+ isc_nmhandle_detach(&sendhandle);
+ }
+ return (result);
} else {
isc__netievent_tcpdnssend_t *ievent = NULL;
*/
if (sock->outerhandle != NULL) {
isc__nmsocket_clearcb(sock->outerhandle->sock);
- isc_nmhandle_unref(sock->outerhandle);
- sock->outerhandle = NULL;
+ isc_nmhandle_detach(&sock->outerhandle);
}
if (sock->listener != NULL) {
isc__nmsocket_detach(&sock->listener);
}
/*
- * handle 'udplisten' async call - start listening on a socket.
+ * Asynchronous 'udplisten' call handler: start listening on a UDP socket.
*/
void
isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
}
/*
- * handle 'udpstop' async call - stop listening on a socket.
+ * Asynchronous 'udpstop' call handler: stop listening on a UDP socket.
*/
void
isc__nm_async_udpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
#endif
/*
- * Three reasons to return now without processing:
- * - If addr == NULL that's the end of stream - we can
- * free the buffer and bail.
+ * Three possible reasons to return now without processing:
+ * - If addr == NULL, in which case it's the end of stream;
+ * we can free the buffer and bail.
* - If we're simulating a firewall blocking UDP packets
* bigger than 'maxudp' bytes for testing purposes.
* - If the socket is no longer active.
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
- if (!atomic_load(&sock->connected)) {
- nmhandle = isc__nmhandle_get(sock, &sockaddr, NULL);
- } else {
- nmhandle = sock->statichandle;
- }
+ nmhandle = isc__nmhandle_get(sock, &sockaddr, NULL);
region.base = (unsigned char *)buf->base;
region.length = nrecv;
* If the recv callback wants to hold on to the handle,
* it needs to attach to it.
*/
- isc_nmhandle_unref(nmhandle);
+ isc_nmhandle_detach(&nmhandle);
}
/*
- * isc__nm_udp_send sends buf to a peer on a socket.
- * It tries to find a proper sibling/child socket so that we won't have
- * to jump to another thread.
+ * Send the data in 'region' to a peer via a UDP socket. We try to find
+ * a proper sibling/child socket so that we won't have to jump to another
+ * thread.
*/
isc_result_t
isc__nm_udp_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
* we need to do so here.
*/
if (maxudp != 0 && region->length > maxudp) {
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&handle);
return (ISC_R_SUCCESS);
}
uvreq->uvbuf.base = (char *)region->base;
uvreq->uvbuf.len = region->length;
- uvreq->handle = handle;
- isc_nmhandle_ref(uvreq->handle);
+ isc_nmhandle_attach(handle, &uvreq->handle);
uvreq->cb.send = cb;
uvreq->cbarg = cbarg;
}
/*
- * handle 'udpsend' async event - send a packet on the socket
+ * Asynchronous 'udpsend' event handler: send a packet on a UDP socket.
*/
void
isc__nm_async_udpsend(isc__networker_t *worker, isc__netievent_t *ev0) {
}
}
-/*
- * udp_send_cb - callback
- */
static void
udp_send_cb(uv_udp_send_t *req, int status) {
isc_result_t result = ISC_R_SUCCESS;
}
uvreq->cb.send(uvreq->handle, result, uvreq->cbarg);
- isc_nmhandle_unref(uvreq->handle);
isc__nm_uvreq_put(&uvreq, uvreq->sock);
}
return (ISC_R_CANCELED);
}
- isc_nmhandle_ref(req->handle);
sa = atomic_load(&sock->connected) ? NULL : &peer->type.sa;
rv = uv_udp_send(&req->uv_req.udp_send, &sock->uv_handle.udp,
&req->uvbuf, 1, sa, udp_send_cb);
isc_netaddr_totext
isc_netaddr_unspec
isc_netscope_pton
+isc_nmhandle_attach
+isc_nmhandle_detach
isc_nmhandle_getdata
isc_nmhandle_getextra
isc_nmhandle_is_stream
isc_nmhandle_netmgr
isc_nmhandle_localaddr
isc_nmhandle_peeraddr
-isc_nmhandle_ref
isc_nmhandle_setdata
-isc_nmhandle_unref
isc_nm_cancelread
isc_nm_closedown
isc_nm_destroy
client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
ns_client_t *client = cbarg;
- REQUIRE(client->handle == handle);
+ REQUIRE(client->sendhandle == handle);
CTRACE("senddone");
if (result != ISC_R_SUCCESS) {
"send failed: %s", isc_result_totext(result));
}
- isc_nmhandle_unref(handle);
+ isc_nmhandle_detach(&client->sendhandle);
}
static void
static isc_result_t
client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {
+ isc_result_t result;
isc_region_t r;
- isc_buffer_usedregion(buffer, &r);
-
- INSIST(client->handle != NULL);
+ REQUIRE(client->sendhandle == NULL);
- return (isc_nm_send(client->handle, &r, client_senddone, client));
+ isc_buffer_usedregion(buffer, &r);
+ isc_nmhandle_attach(client->handle, &client->sendhandle);
+ result = isc_nm_send(client->handle, &r, client_senddone, client);
+ if (result != ISC_R_SUCCESS) {
+ isc_nmhandle_detach(&client->sendhandle);
+ }
+ return (result);
}
void
}
ns_client_drop(client, result);
- isc_nmhandle_unref(client->handle);
}
void
isc_region_t zr;
#endif /* HAVE_DNSTAP */
+ REQUIRE(NS_CLIENT_VALID(client));
+
/*
* XXXWPK TODO
* Delay the response according to the -T delay option
*/
- REQUIRE(NS_CLIENT_VALID(client));
- /*
- * We need to do it to make sure the client and handle
- * won't disappear from under us with client_senddone.
- */
-
env = ns_interfacemgr_getaclenv(client->manager->interface->mgr);
CTRACE("send");
respsize = isc_buffer_usedlength(&buffer);
- isc_nmhandle_ref(client->handle);
result = client_sendpkg(client, &buffer);
- if (result != ISC_R_SUCCESS) {
- /* We won't get a callback to clean it up */
- isc_nmhandle_unref(client->handle);
- }
switch (isc_sockaddr_pf(&client->peeraddr)) {
case AF_INET:
respsize = isc_buffer_usedlength(&buffer);
- isc_nmhandle_ref(client->handle);
result = client_sendpkg(client, &buffer);
- if (result != ISC_R_SUCCESS) {
- /* We won't get a callback to clean it up */
- isc_nmhandle_unref(client->handle);
- }
switch (isc_sockaddr_pf(&client->peeraddr)) {
case AF_INET:
ns__client_put_cb);
client->handle = handle;
}
+
if (isc_nmhandle_is_stream(handle)) {
client->attributes |= NS_CLIENTATTR_TCP;
}
isc_buffer_add(&tbuffer, region->length);
buffer = &tbuffer;
- client->peeraddr = isc_nmhandle_peeraddr(client->handle);
-
+ client->peeraddr = isc_nmhandle_peeraddr(handle);
client->peeraddr_valid = true;
reqsize = isc_buffer_usedlength(buffer);
isc_netaddr_fromsockaddr(&client->destaddr,
&client->manager->interface->addr);
} else {
- isc_sockaddr_t sockaddr =
- isc_nmhandle_localaddr(client->handle);
+ isc_sockaddr_t sockaddr = isc_nmhandle_localaddr(handle);
isc_netaddr_fromsockaddr(&client->destaddr, &sockaddr);
}
&client->requesttime, NULL, buffer);
#endif /* HAVE_DNSTAP */
- isc_nmhandle_ref(client->handle);
- ns_query_start(client);
+ ns_query_start(client, handle);
break;
case dns_opcode_update:
CTRACE("update");
&client->requesttime, NULL, buffer);
#endif /* HAVE_DNSTAP */
ns_client_settimeout(client, 60);
- isc_nmhandle_ref(client->handle);
- ns_update_start(client, sigresult);
+ ns_update_start(client, handle, sigresult);
break;
case dns_opcode_notify:
CTRACE("notify");
ns_client_settimeout(client, 60);
- isc_nmhandle_ref(client->handle);
- ns_notify_start(client);
+ ns_notify_start(client, handle);
break;
case dns_opcode_iquery:
CTRACE("iquery");
isc_task_t * task;
dns_view_t * view;
dns_dispatch_t * dispatch;
- isc_nmhandle_t * handle;
- unsigned char * tcpbuf;
- dns_message_t * message;
- unsigned char * sendbuf;
- dns_rdataset_t * opt;
- uint16_t udpsize;
- uint16_t extflags;
- int16_t ednsversion; /* -1 noedns */
+ 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 *fetchhandle; /* Waiting for recursive fetch */
+ isc_nmhandle_t *updatehandle; /* Waiting for update callback */
+ unsigned char * tcpbuf;
+ dns_message_t * message;
+ unsigned char * sendbuf;
+ dns_rdataset_t *opt;
+ uint16_t udpsize;
+ uint16_t extflags;
+ int16_t ednsversion; /* -1 noedns */
void (*cleanup)(ns_client_t *);
void (*shutdown)(void *arg, isc_result_t result);
void * shutdown_arg;
***/
void
-ns_notify_start(ns_client_t *client);
+ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle);
/*%<
* Examines the incoming message to determine appropriate zone.
ns_query_free(ns_client_t *client);
void
-ns_query_start(ns_client_t *client);
+ns_query_start(ns_client_t *client, isc_nmhandle_t *handle);
void
ns_query_cancel(ns_client_t *client);
***/
void
-ns_update_start(ns_client_t *client, isc_result_t sigresult);
+ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
+ isc_result_t sigresult);
#endif /* NS_UPDATE_H */
}
if (msg_result != ISC_R_SUCCESS) {
ns_client_drop(client, msg_result);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
return;
}
message->rcode = rcode;
}
ns_client_send(client);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
}
void
-ns_notify_start(ns_client_t *client) {
+ns_notify_start(ns_client_t *client, isc_nmhandle_t *handle) {
dns_message_t *request = client->message;
isc_result_t result;
dns_name_t *zonename;
char tsigbuf[DNS_NAME_FORMATSIZE * 2 + sizeof(": TSIG '' ()")];
dns_tsigkey_t *tsigkey;
+ /*
+ * Attach to the request handle
+ */
+ isc_nmhandle_attach(handle, &client->reqhandle);
+
/*
* Interpret the question section.
*/
inc_stats(client, counter);
ns_client_send(client);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
}
static void
log_queryerror(client, result, line, loglevel);
ns_client_error(client, result);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
}
static void
inc_stats(client, ns_statscounter_failure);
}
ns_client_drop(client, result);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
}
static inline void
}
free_devent(client, &event, &devent);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->fetchhandle);
}
static void
peeraddr = NULL;
}
- isc_nmhandle_ref(client->handle);
+ isc_nmhandle_attach(client->handle, &client->fetchhandle);
options = client->query.fetchoptions | DNS_FETCHOPT_PREFETCH;
result = dns_resolver_createfetch(
client->view->resolver, qname, rdataset->type, NULL, NULL, NULL,
&client->query.prefetch);
if (result != ISC_R_SUCCESS) {
ns_client_putrdataset(client, &tmprdataset);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->fetchhandle);
}
dns_rdataset_clearprefetch(rdataset);
}
options = client->query.fetchoptions;
- isc_nmhandle_ref(client->handle);
+ isc_nmhandle_attach(client->handle, &client->fetchhandle);
result = dns_resolver_createfetch(
client->view->resolver, qname, type, NULL, NULL, NULL, peeraddr,
client->message->id, options, 0, NULL, client->task,
&client->query.prefetch);
if (result != ISC_R_SUCCESS) {
ns_client_putrdataset(client, &tmprdataset);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->fetchhandle);
}
}
}
UNLOCK(&client->manager->reclock);
+ isc_nmhandle_detach(&client->fetchhandle);
+
client->query.attributes &= ~NS_QUERYATTR_RECURSING;
client->state = NS_CLIENTSTATE_WORKING;
}
dns_resolver_destroyfetch(&fetch);
- isc_nmhandle_unref(client->handle);
}
/*%
peeraddr = &client->peeraddr;
}
- isc_nmhandle_ref(client->handle);
+ isc_nmhandle_attach(client->handle, &client->fetchhandle);
result = dns_resolver_createfetch(
client->view->resolver, qname, qtype, qdomain, nameservers,
NULL, peeraddr, client->message->id, client->query.fetchoptions,
0, NULL, client->task, fetch_callback, client, rdataset,
sigrdataset, &client->query.fetch);
if (result != ISC_R_SUCCESS) {
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->fetchhandle);
ns_client_putrdataset(client, &rdataset);
if (sigrdataset != NULL) {
ns_client_putrdataset(client, &sigrdataset);
}
void
-ns_query_start(ns_client_t *client) {
+ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
isc_result_t result;
dns_message_t *message;
dns_rdataset_t *rdataset;
REQUIRE(NS_CLIENT_VALID(client));
+ /*
+ * Attach to the request handle
+ */
+ isc_nmhandle_attach(handle, &client->reqhandle);
+
message = client->message;
saved_extflags = client->extflags;
saved_flags = client->message->flags;
@BIND9_MAKE_INCLUDES@
-WRAP_OPTIONS = -Wl,--wrap=isc_nmhandle_unref
+WRAP_OPTIONS = -Wl,--wrap=isc_nmhandle_detach -Wl,--wrap=isc_nmhandle_attach
CINCLUDES = -I. -Iinclude ${NS_INCLUDES} ${DNS_INCLUDES} ${ISC_INCLUDES} \
${OPENSSL_CFLAGS} \
notify_start(void **state) {
isc_result_t result;
ns_client_t *client = NULL;
+ isc_nmhandle_t *handle = NULL;
dns_message_t *nmsg = NULL;
unsigned char ndata[4096];
isc_buffer_t nbuf;
client->message = nmsg;
nmsg = NULL;
client->sendcb = check_response;
- ns_notify_start(client);
+ ns_notify_start(client, client->handle);
/*
* Clean up
*/
ns_test_cleanup_zone();
- isc_nmhandle_unref(client->handle);
+
+ handle = client->handle;
+ isc_nmhandle_detach(&client->handle);
+ isc_nmhandle_detach(&handle);
}
#endif /* if defined(USE_LIBTOOL) || LD_WRAP */
atomic_uintptr_t client_addrs[32];
void
-__wrap_isc_nmhandle_unref(isc_nmhandle_t *handle);
+__wrap_isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp);
+void
+__wrap_isc_nmhandle_detach(isc_nmhandle_t **handlep);
+
+void
+__wrap_isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp) {
+ ns_client_t *client = (ns_client_t *)source;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ if (atomic_load(&client_addrs[i]) == (uintptr_t)client) {
+ break;
+ }
+ }
+ INSIST(i < 32);
+ INSIST(atomic_load(&client_refs[i]) > 0);
+
+ atomic_fetch_add(&client_refs[i], 1);
+
+ *targetp = source;
+ return;
+}
void
-__wrap_isc_nmhandle_unref(isc_nmhandle_t *handle) {
+__wrap_isc_nmhandle_detach(isc_nmhandle_t **handlep) {
+ isc_nmhandle_t *handle = *handlep;
ns_client_t *client = (ns_client_t *)handle;
int i;
+ *handlep = NULL;
+
for (i = 0; i < 32; i++) {
if (atomic_load(&client_addrs[i]) == (uintptr_t)client) {
break;
}
}
- REQUIRE(i < 32);
+ INSIST(i < 32);
if (atomic_fetch_sub(&client_refs[i], 1) == 1) {
dns_view_detach(&client->view);
ns__client_put_cb(client);
isc_mem_put(mctx, client, sizeof(ns_client_t));
}
+
return;
}
#ifdef USE_LIBTOOL
void
-isc_nmhandle_unref(isc_nmhandle_t *handle) {
- __wrap_isc_nmhandle_unref(handle);
+isc_nmhandle_attach(isc_nmhandle_t *source, isc_nmhandle_t **targetp) {
+ __wrap_isc_nmhandle_attach(source, targetp);
+}
+void
+isc_nmhandle_detach(isc_nmhandle_t **handle) {
+ __wrap_isc_nmhandle_detach(handle);
}
#endif /* USE_LIBTOOL */
saved_hook_table = ns__hook_table;
ns__hook_table = query_hooks;
- ns_query_start(client);
+ ns_query_start(client, client->handle);
ns__hook_table = saved_hook_table;
ns_hooktable_free(mctx, (void **)&query_hooks);
+ isc_nmhandle_detach(&client->reqhandle);
+
if (*qctxp == NULL) {
return (ISC_R_NOMEMORY);
} else {
query_ctx_t **qctxp) {
ns_client_t *client = NULL;
isc_result_t result;
+ isc_nmhandle_t *handle = NULL;
REQUIRE(params != NULL);
REQUIRE(params->qname != NULL);
}
/*
- * Reference count for "client" is now at 2, so decrement it in order
- * for it to drop to zero when "qctx" gets destroyed.
+ * The reference count for "client" is now at 2, so we need to
+ * decrement it in order for it to drop to zero when "qctx" gets
+ * destroyed.
*/
- isc_nmhandle_unref(client->handle);
+ handle = client->handle;
+ isc_nmhandle_detach(&handle);
return (ISC_R_SUCCESS);
detach_view:
dns_view_detach(&client->view);
detach_client:
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->handle);
return (result);
}
dns_db_detach(&qctx->db);
}
if (qctx->client != NULL) {
- isc_nmhandle_unref(qctx->client->handle);
+ isc_nmhandle_detach(&qctx->client->handle);
}
isc_mem_put(mctx, qctx, sizeof(*qctx));
client->nupdates++;
event->ev_arg = client;
- isc_nmhandle_ref(client->handle);
+ isc_nmhandle_attach(client->handle, &client->updatehandle);
dns_zone_gettask(zone, &zonetask);
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
client->message->rcode = dns_result_torcode(result);
ns_client_send(client);
- isc_nmhandle_unref(client->handle);
return;
msg_failure:
"could not create update response message: %s",
isc_result_totext(msg_result));
ns_client_drop(client, msg_result);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
}
void
-ns_update_start(ns_client_t *client, isc_result_t sigresult) {
+ns_update_start(ns_client_t *client, isc_nmhandle_t *handle,
+ isc_result_t sigresult) {
dns_message_t *request = client->message;
isc_result_t result;
dns_name_t *zonename;
dns_rdataset_t *zone_rdataset;
dns_zone_t *zone = NULL, *raw = NULL;
+ /*
+ * Attach to the request handle
+ */
+ isc_nmhandle_attach(handle, &client->reqhandle);
+
/*
* Interpret the zone section.
*/
default:
FAILC(DNS_R_NOTAUTH, "not authoritative for update zone");
}
+
+ isc_nmhandle_detach(&client->reqhandle);
return;
failure:
if (zone != NULL) {
dns_zone_detach(&zone);
}
+ isc_nmhandle_detach(&client->reqhandle);
}
/*%
}
uev->ev_type = DNS_EVENT_UPDATEDONE;
uev->ev_action = updatedone_action;
+
isc_task_send(client->task, &event);
INSIST(ver == NULL);
UNUSED(task);
- INSIST(event->ev_type == DNS_EVENT_UPDATEDONE);
- INSIST(task == client->task);
+ REQUIRE(event->ev_type == DNS_EVENT_UPDATEDONE);
+ REQUIRE(task == client->task);
+ REQUIRE(client->updatehandle == client->handle);
INSIST(client->nupdates > 0);
switch (uev->result) {
if (uev->zone != NULL) {
dns_zone_detach(&uev->zone);
}
+
client->nupdates--;
+
respond(client, uev->result);
+
isc_event_free(&event);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->updatehandle);
}
/*%
* Update forwarding support.
*/
-
static void
forward_fail(isc_task_t *task, isc_event_t *event) {
ns_client_t *client = (ns_client_t *)event->ev_arg;
client->nupdates--;
respond(client, DNS_R_SERVFAIL);
isc_event_free(&event);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->updatehandle);
}
static void
uev->answer = answer;
inc_stats(client, zone, ns_statscounter_updaterespfwd);
}
+
isc_task_send(client->task, ISC_EVENT_PTR(&uev));
dns_zone_detach(&zone);
}
ns_client_sendraw(client, uev->answer);
dns_message_detach(&uev->answer);
isc_event_free(&event);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->updatehandle);
}
static void
namebuf, classbuf);
dns_zone_gettask(zone, &zonetask);
- isc_nmhandle_ref(client->handle);
+ isc_nmhandle_attach(client->handle, &client->updatehandle);
isc_task_send(zonetask, ISC_EVENT_PTR(&event));
if (event != NULL) {
#include <isc/mem.h>
#include <isc/print.h>
#include <isc/stats.h>
-#include <isc/timer.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/rriterator.h>
#include <dns/soa.h>
#include <dns/stats.h>
-#include <dns/timer.h>
#include <dns/tsig.h>
#include <dns/view.h>
#include <dns/zone.h>
NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3),
"zone transfer setup failed");
ns_client_error(client, result);
- isc_nmhandle_unref(client->handle);
+ isc_nmhandle_detach(&client->reqhandle);
}
}
xfr->txmem = mem;
xfr->txmemlen = len;
-#if 0
- CHECK(dns_timer_setidle(xfr->client->timer,
- maxtime,idletime,false));
-#endif /* if 0 */
-
/*
* Register a shutdown callback with the client, so that we
* can stop the transfer immediately when the client task
xfrout_log(xfr, ISC_LOG_DEBUG(8),
"sending TCP message of %d bytes", used.length);
- CHECK(isc_nm_send(xfr->client->handle, &used, xfrout_senddone,
- xfr));
+ isc_nmhandle_attach(xfr->client->handle,
+ &xfr->client->sendhandle);
+ CHECK(isc_nm_send(xfr->client->sendhandle, &used,
+ xfrout_senddone, xfr));
xfr->sends++;
xfr->cbytes = used.length;
} else {
xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
ns_client_send(xfr->client);
xfr->stream->methods->pause(xfr->stream);
- isc_nmhandle_unref(xfr->client->handle);
+ isc_nmhandle_detach(&xfr->client->reqhandle);
xfrout_ctx_destroy(&xfr);
return;
}
return;
}
+ if (xfr->client->sendhandle != NULL) {
+ isc_nmhandle_detach(&xfr->client->sendhandle);
+ }
+
xfrout_fail(xfr, result, "sending zone data");
}
xfr->sends--;
INSIST(xfr->sends == 0);
+ isc_nmhandle_detach(&xfr->client->sendhandle);
+
/*
* Update transfer statistics if sending succeeded, accounting for the
* two-byte TCP length prefix included in the number of bytes sent.
xfr->stats.nbytes += xfr->cbytes;
}
-#if 0
- (void)isc_timer_touch(xfr->client->timer);
-#endif /* if 0 */
-
if (xfr->shuttingdown) {
xfrout_maybe_destroy(xfr);
} else if (result != ISC_R_SUCCESS) {
xfr->stats.nbytes, (unsigned int)(msecs / 1000),
(unsigned int)(msecs % 1000), (unsigned int)persec);
+ /*
+ * We're done, unreference the handle and destroy the xfr
+ * context.
+ */
+ isc_nmhandle_detach(&xfr->client->reqhandle);
xfrout_ctx_destroy(&xfr);
- /* We're done, unreference the handle */
- isc_nmhandle_unref(handle);
}
}
static void
xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
- INSIST(xfr->shuttingdown);
-#if 0
- if (xfr->sends > 0) {
- /*
- * If we are currently sending, cancel it and wait for
- * cancel event before destroying the context.
- */
- isc_socket_cancel(xfr->client->tcpsocket,xfr->client->task,
- ISC_SOCKCANCEL_SEND);
- } else {
-#endif /* if 0 */
+ REQUIRE(xfr->shuttingdown);
+
ns_client_drop(xfr->client, ISC_R_CANCELED);
- isc_nmhandle_unref(xfr->client->handle);
+ isc_nmhandle_detach(&xfr->client->reqhandle);
xfrout_ctx_destroy(&xfr);
-#if 0
-}
-#endif /* if 0 */
}
static void