Compare commits

...

3 Commits

Author SHA1 Message Date
Evan Hunt
bb78bbb27a nonfunctional checkpoint: introduce isc_nm_dnspair() 2022-05-20 12:20:48 -07:00
Evan Hunt
19c4009055 change ns__client_request() to ns_client_request()
in the future we'll want to call this function from outside named,
so change the name to one suitable for external access.
2022-05-20 12:15:48 -07:00
Evan Hunt
d9cd97a9f1 move client setup/resolution from main to separate functions 2022-05-20 12:12:08 -07:00
10 changed files with 252 additions and 65 deletions

View File

@@ -84,6 +84,9 @@ static isc_log_t *lctx = NULL;
/* Configurables */
static char *server = NULL;
static const char *port = "53";
static isc_nm_t *netmgr = NULL;
static isc_taskmgr_t *taskmgr = NULL;
static isc_timermgr_t *timermgr = NULL;
static isc_sockaddr_t *srcaddr4 = NULL, *srcaddr6 = NULL;
static isc_sockaddr_t a4, a6;
static char *curqname = NULL, *qname = NULL;
@@ -1708,20 +1711,97 @@ get_reverse(char *reverse, size_t len, char *value, bool strict) {
}
}
static isc_result_t
setup_client(dns_client_t **clientp) {
isc_result_t result;
dns_client_t *client = NULL;
REQUIRE(clientp != NULL && *clientp == NULL);
/* Create client */
result = dns_client_create(mctx, taskmgr, netmgr, timermgr, 0, &client,
srcaddr4, srcaddr6);
if (result != ISC_R_SUCCESS) {
delv_log(ISC_LOG_ERROR, "dns_client_create: %s",
isc_result_totext(result));
goto cleanup;
}
/* Set the nameserver */
if (server != NULL) {
addserver(client);
} else {
findserver(client);
}
CHECK(setup_dnsseckeys(client));
*clientp = client;
cleanup:
if (result != ISC_R_SUCCESS) {
if (client != NULL) {
dns_client_detach(&client);
}
}
return (result);
}
static isc_result_t
client_resolve(dns_client_t *client, const dns_name_t *query_name,
dns_namelist_t *namelist)
{
isc_result_t result;
unsigned int resopt;
char namestr[DNS_NAME_FORMATSIZE];
/* Set up resolution options */
resopt = DNS_CLIENTRESOPT_NOCDFLAG;
if (no_sigs) {
resopt |= DNS_CLIENTRESOPT_NODNSSEC;
}
if (!root_validation) {
resopt |= DNS_CLIENTRESOPT_NOVALIDATE;
}
if (cdflag) {
resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG;
}
if (use_tcp) {
resopt |= DNS_CLIENTRESOPT_TCP;
}
/* Perform resolution */
result = dns_client_resolve(client, query_name, dns_rdataclass_in,
qtype, resopt, namelist);
if (result != ISC_R_SUCCESS && !yaml) {
delv_log(ISC_LOG_ERROR, "resolution failed: %s",
isc_result_totext(result));
}
if (yaml) {
printf("type: DELV_RESULT\n");
dns_name_format(query_name, namestr, sizeof(namestr));
printf("query_name: %s\n", namestr);
printf("status: %s\n", isc_result_totext(result));
printf("records:\n");
}
return (result);
}
int
main(int argc, char *argv[]) {
dns_client_t *client = NULL;
isc_result_t result;
dns_fixedname_t qfn;
dns_name_t *query_name, *response_name;
char namestr[DNS_NAME_FORMATSIZE];
dns_rdataset_t *rdataset;
dns_namelist_t namelist;
unsigned int resopt;
isc_nm_t *netmgr = NULL;
isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr = NULL;
dns_master_style_t *style = NULL;
struct sigaction sa;
ISC_LIST_INIT(namelist);
progname = argv[0];
preparse_args(argc, argv);
@@ -1744,58 +1824,21 @@ main(int argc, char *argv[]) {
setup_logging(stderr);
/* Create client */
result = dns_client_create(mctx, taskmgr, netmgr, timermgr, 0, &client,
srcaddr4, srcaddr6);
if (result != ISC_R_SUCCESS) {
delv_log(ISC_LOG_ERROR, "dns_client_create: %s",
isc_result_totext(result));
goto cleanup;
/* Unblock SIGINT if it's been blocked by isc_app_ctxstart() */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
if (sigfillset(&sa.sa_mask) != 0 || sigaction(SIGINT, &sa, NULL) < 0) {
fatal("Couldn't set up signal handler");
}
/* Set the nameserver */
if (server != NULL) {
addserver(client);
} else {
findserver(client);
}
CHECK(setup_dnsseckeys(client));
/* Construct QNAME */
CHECK(convert_name(&qfn, &query_name, qname));
/* Set up resolution options */
resopt = DNS_CLIENTRESOPT_NOCDFLAG;
if (no_sigs) {
resopt |= DNS_CLIENTRESOPT_NODNSSEC;
}
if (!root_validation) {
resopt |= DNS_CLIENTRESOPT_NOVALIDATE;
}
if (cdflag) {
resopt &= ~DNS_CLIENTRESOPT_NOCDFLAG;
}
if (use_tcp) {
resopt |= DNS_CLIENTRESOPT_TCP;
}
/* Set up DNS client */
CHECK(setup_client(&client));
/* Perform resolution */
ISC_LIST_INIT(namelist);
result = dns_client_resolve(client, query_name, dns_rdataclass_in,
qtype, resopt, &namelist);
if (result != ISC_R_SUCCESS && !yaml) {
delv_log(ISC_LOG_ERROR, "resolution failed: %s",
isc_result_totext(result));
}
if (yaml) {
printf("type: DELV_RESULT\n");
dns_name_format(query_name, namestr, sizeof(namestr));
printf("query_name: %s\n", namestr);
printf("status: %s\n", isc_result_totext(result));
printf("records:\n");
}
/* Set up and perform DNS client resolution */
CHECK(client_resolve(client, query_name, &namelist));
for (response_name = ISC_LIST_HEAD(namelist); response_name != NULL;
response_name = ISC_LIST_NEXT(response_name, link))

View File

@@ -499,9 +499,11 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
* 'cb'.
*/
void
isc_nm_dnspair(isc_nm_t *mgr, isc_nm_cb_t ccb, void *ccbarg,
isc_nm_recv_cb_t scb, void *scbarg);
/*%<
* Returns 'true' iff 'handle' is associated with a socket of type
* 'isc_nm_tlsdnssocket'.
* FIXME
*/
bool

View File

@@ -295,6 +295,8 @@ typedef enum isc__netievent_type {
netievent_tcpdnsread,
netievent_tcpdnscancel,
netievent_dnspair,
netievent_tlsclose,
netievent_tlssend,
netievent_tlsstartread,
@@ -1573,6 +1575,12 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0);
* Callback handlers for asynchronous TCPDNS events.
*/
void
isc__nm_async_dnspair(isc__networker_t *worker, isc__netievent_t *ev0);
/*%<
* Callback handlers for asynchronous DNS socket pair events.
*/
void
isc__nm_tcpdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
/*
@@ -1956,6 +1964,8 @@ NETIEVENT_SOCKET_REQ_TYPE(tcpdnssend);
NETIEVENT_SOCKET_HANDLE_TYPE(tcpdnscancel);
NETIEVENT_SOCKET_QUOTA_TYPE(tcpdnsaccept);
NETIEVENT_SOCKET_REQ_TYPE(dnspair);
NETIEVENT_SOCKET_TYPE(tlsdnsclose);
NETIEVENT_SOCKET_TYPE(tlsdnsread);
NETIEVENT_SOCKET_TYPE(tlsdnsstop);
@@ -2026,6 +2036,8 @@ NETIEVENT_SOCKET_REQ_DECL(tcpdnssend);
NETIEVENT_SOCKET_HANDLE_DECL(tcpdnscancel);
NETIEVENT_SOCKET_QUOTA_DECL(tcpdnsaccept);
NETIEVENT_SOCKET_REQ_DECL(dnspair);
NETIEVENT_SOCKET_DECL(tlsdnsclose);
NETIEVENT_SOCKET_DECL(tlsdnsread);
NETIEVENT_SOCKET_DECL(tlsdnsstop);

View File

@@ -900,6 +900,8 @@ process_netievent(isc__networker_t *worker, isc__netievent_t *ievent) {
NETIEVENT_CASE(tcpdnsread);
NETIEVENT_CASE(tcpdnsstop);
NETIEVENT_CASE(dnspair);
NETIEVENT_CASE(tlsdnscycle);
NETIEVENT_CASE(tlsdnsaccept);
NETIEVENT_CASE(tlsdnslisten);
@@ -1023,6 +1025,8 @@ NETIEVENT_SOCKET_REQ_DEF(tcpdnssend);
NETIEVENT_SOCKET_HANDLE_DEF(tcpdnscancel);
NETIEVENT_SOCKET_QUOTA_DEF(tcpdnsaccept);
NETIEVENT_SOCKET_REQ_DEF(dnspair);
NETIEVENT_SOCKET_DEF(tlsdnsclose);
NETIEVENT_SOCKET_DEF(tlsdnsread);
NETIEVENT_SOCKET_DEF(tlsdnsstop);

View File

@@ -387,6 +387,7 @@ start_tcpdns_child(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nmsocket_t *sock,
isc__nm_maybe_enqueue_ievent(&mgr->workers[tid],
(isc__netievent_t *)ievent);
}
isc_result_t
isc_nm_listentcpdns(isc_nm_t *mgr, uint32_t workers, isc_sockaddr_t *iface,
isc_nm_recv_cb_t recv_cb, void *recv_cbarg,
@@ -701,7 +702,8 @@ isc__nm_tcpdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
* This MUST be done asynchronously, no matter which thread we're
* in. The callback function for isc_nm_read() often calls
* isc_nm_read() again; if we tried to do that synchronously
* we'd clash in processbuffer() and grow the stack indefinitely.
* we'd clash in isc__nm_tcpdns_processbuffer() and grow the
* stack indefinitely.
*/
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
@@ -1460,3 +1462,127 @@ isc__nm_async_tcpdnscancel(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__nm_failed_read_cb(sock, ISC_R_EOF, false);
}
static isc_result_t
pairdns_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
isc_result_t result = ISC_R_UNSET;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(VALID_UVREQ(req));
REQUIRE(isc__nm_in_netthread());
REQUIRE(sock->tid == isc_nm_tid());
if (isc__nm_closing(sock)) {
result = ISC_R_SHUTTINGDOWN;
goto error;
}
atomic_store(&sock->connected, true);
error:
LOCK(&sock->lock);
sock->result = result;
SIGNAL(&sock->cond);
if (!atomic_load(&sock->active)) {
WAIT(&sock->scond, &sock->lock);
}
INSIST(atomic_load(&sock->active));
UNLOCK(&sock->lock);
return (result);
}
void
isc__nm_async_dnspair(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_dnspair_t *ievent =
(isc__netievent_dnspair_t *)ev0;
isc_nmsocket_t *sock = ievent->sock;
isc__nm_uvreq_t *req = ievent->req;
isc_result_t result = ISC_R_SUCCESS;
UNUSED(worker);
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tcpdnssocket);
REQUIRE(sock->parent == NULL);
REQUIRE(sock->tid == isc_nm_tid());
result = pairdns_direct(sock, req);
if (result != ISC_R_SUCCESS) {
isc__nmsocket_clearcb(sock);
isc__nm_connectcb(sock, req, result, true);
atomic_store(&sock->active, false);
isc__nm_tcpdns_close(sock);
}
/*
* The sock is now attached to the handle.
*/
isc__nmsocket_detach(&sock);
}
void
isc_nm_dnspair(isc_nm_t *mgr, isc_nm_cb_t ccb, void *ccbarg,
isc_nm_recv_cb_t scb, void *scbarg) {
uv_os_sock_t fds[2];
isc_nmsocket_t *csock = NULL, *ssock = NULL;
isc__netievent_tcpdnsconnect_t *cevent = NULL;
isc__netievent_tcpdnslisten_t *sevent = NULL;
isc__nm_uvreq_t *req = NULL;
int r;
REQUIRE(VALID_NM(mgr));
/* XXX: uv_socketpair() was introduced in libuv 1.40 */
r = socketpair(PF_LOCAL, SOCK_STREAM, 0, fds);
RUNTIME_CHECK(r == 0);
/* Set up server socket */
ssock = isc_mem_get(mgr->mctx, sizeof(*ssock));
isc__nmsocket_init(ssock, mgr, isc_nm_tcpdnssocket, NULL);
ssock->recv_cb = scb;
ssock->recv_cbarg = scbarg;
ssock->fd = fds[1];
sevent = isc__nm_get_netievent_tcpdnslisten(mgr, ssock);
/* Set up client socket */
csock = isc_mem_get(mgr->mctx, sizeof(*csock));
isc__nmsocket_init(csock, mgr, isc_nm_tcpdnssocket, NULL);
csock->result = ISC_R_UNSET;
csock->fd = fds[0];
atomic_init(&csock->client, true);
req = isc__nm_uvreq_get(mgr, csock);
req->cb.connect = ccb;
req->cbarg = ccbarg;
req->handle = isc__nmhandle_get(csock, NULL, NULL);
cevent = isc__nm_get_netievent_dnspair(mgr, csock, req);
if (isc__nm_in_netthread()) {
atomic_store(&csock->active, true);
csock->tid = isc_nm_tid();
isc__nm_async_dnspair(&mgr->workers[csock->tid],
(isc__netievent_t *)cevent);
isc__nm_put_netievent_dnspair(mgr, cevent);
} else {
atomic_init(&csock->active, false);
csock->tid = isc_random_uniform(mgr->nworkers);
isc__nm_enqueue_ievent(&mgr->workers[csock->tid],
(isc__netievent_t *)cevent);
}
ssock->tid = isc_random_uniform(mgr->nworkers);
isc__nm_maybe_enqueue_ievent(&mgr->workers[ssock->tid],
(isc__netievent_t *)sevent);
LOCK(&csock->lock);
while (csock->result == ISC_R_UNSET) {
WAIT(&csock->cond, &csock->lock);
}
atomic_store(&csock->active, true);
BROADCAST(&csock->scond);
UNLOCK(&csock->lock);
}

View File

@@ -898,8 +898,8 @@ isc__nm_tlsdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
* This MUST be done asynchronously, no matter which thread
* we're in. The callback function for isc_nm_read() often calls
* isc_nm_read() again; if we tried to do that synchronously
* we'd clash in processbuffer() and grow the stack
* indefinitely.
* we'd clash in isc__nm_tlsdns_processbuffer() and grow the
* stack indefinitely.
*/
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);

View File

@@ -1698,8 +1698,8 @@ ns__client_put_cb(void *client0) {
* or tcpmsg (TCP case).
*/
void
ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg) {
ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg) {
ns_client_t *client = NULL;
isc_result_t result;
isc_result_t sigresult = ISC_R_SUCCESS;

View File

@@ -454,8 +454,8 @@ ns_client_addopt(ns_client_t *client, dns_message_t *message,
*/
void
ns__client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg);
ns_client_request(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *arg);
/*%<
* Handle client requests.

View File

@@ -487,7 +487,7 @@ ns_interface_listenudp(ns_interface_t *ifp) {
/* Reserve space for an ns_client_t with the netmgr handle */
result = isc_nm_listenudp(ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr,
ns__client_request, ifp,
ns_client_request, ifp,
&ifp->udplistensocket);
return (result);
}
@@ -497,7 +497,7 @@ ns_interface_listentcp(ns_interface_t *ifp) {
isc_result_t result;
result = isc_nm_listentcpdns(
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns__client_request,
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request,
ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog,
&ifp->mgr->sctx->tcpquota, &ifp->tcplistensocket);
if (result != ISC_R_SUCCESS) {
@@ -537,7 +537,7 @@ ns_interface_listentls(ns_interface_t *ifp, isc_tlsctx_t *sslctx) {
isc_result_t result;
result = isc_nm_listentlsdns(
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns__client_request,
ifp->mgr->nm, ISC_NM_LISTEN_ALL, &ifp->addr, ns_client_request,
ifp, ns__client_tcpconn, ifp, ifp->mgr->backlog,
&ifp->mgr->sctx->tcpquota, sslctx, &ifp->tcplistensocket);
@@ -576,7 +576,7 @@ ns_interface_listenhttp(ns_interface_t *ifp, isc_tlsctx_t *sslctx, char **eps,
for (size_t i = 0; i < neps; i++) {
result = isc_nm_http_endpoints_add(epset, eps[i],
ns__client_request, ifp);
ns_client_request, ifp);
if (result != ISC_R_SUCCESS) {
break;
}

View File

@@ -793,7 +793,7 @@ ns_test_qctx_create(const ns_test_qctx_create_params_t *params,
/*
* Allow recursion for the client. As NS_CLIENTATTR_RA normally gets
* set in ns__client_request(), i.e. earlier than the unit tests hook
* 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;