...
 
Commits (6)
5412. [func] Netmgr server-side TLS layer and internal server-side
DoT support, currently unused. [GL #1840]
5411. [cleanup] Refactoring of TCP accept code to use a single accept()
and pass the accepted socket to child threads for
processing. [GL !3320]
......
......@@ -580,7 +580,7 @@ CRYPTO=OpenSSL
#
# OpenSSL/LibreSSL is mandatory
#
PKG_CHECK_MODULES([OPENSSL], [libcrypto], [],
PKG_CHECK_MODULES([OPENSSL], [libssl libcrypto], [],
[AX_CHECK_OPENSSL([:],[AC_MSG_FAILURE([OpenSSL/LibreSSL not found])])])
AX_SAVE_FLAGS([openssl])
......
......@@ -125,6 +125,7 @@ libisc_la_SOURCES = \
netmgr/netmgr.c \
netmgr/tcp.c \
netmgr/tcpdns.c \
netmgr/tls.c \
netmgr/udp.c \
netmgr/uv-compat.c \
netmgr/uv-compat.h \
......
......@@ -15,6 +15,8 @@
#include <isc/result.h>
#include <isc/types.h>
#include <openssl/ssl.h>
typedef enum {
NMEV_READ,
NMEV_WRITE,
......@@ -255,7 +257,7 @@ isc_result_t
isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
void *cbarg, isc_nm_cb_t accept_cb, void *accept_cbarg,
size_t extrahandlesize, int backlog, isc_quota_t *quota,
isc_nmsocket_t **sockp);
SSL_CTX *sslctx, isc_nmsocket_t **sockp);
/*%<
* Start listening for DNS messages over the TCP interface 'iface', using
* net manager 'mgr'.
......@@ -333,6 +335,11 @@ isc_nm_tcp_gettimeouts(isc_nm_t *mgr, uint32_t *initial, uint32_t *idle,
* \li 'mgr' is a valid netmgr.
*/
isc_result_t
isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t accept_cb,
void *accept_cbarg, size_t extrahandlesize, int backlog,
isc_quota_t *quota, SSL_CTX *sslctx, isc_nmsocket_t **sockp);
void
isc_nm_maxudp(isc_nm_t *mgr, uint32_t maxudp);
/*%<
......
......@@ -88,6 +88,7 @@
#define ISC_R_DISCFULL 67 /*%< disc full */
#define ISC_R_DEFAULT 68 /*%< default */
#define ISC_R_IPV4PREFIX 69 /*%< IPv4 prefix */
#define ISC_R_TLSERROR 70 /*%< TLS error */
/*% Not a result code: the number of results. */
#define ISC_R_NRESULTS 70
......
......@@ -14,6 +14,9 @@
#include <unistd.h>
#include <uv.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <isc/astack.h>
#include <isc/atomic.h>
#include <isc/buffer.h>
......@@ -136,6 +139,9 @@ typedef enum isc__netievent_type {
netievent_tcpaccept,
netievent_tcpstop,
netievent_tcpclose,
netievent_tlsclose,
netievent_tlssend,
netievent_tlsstartread,
netievent_tcpdnsclose,
netievent_closecb,
......@@ -213,6 +219,7 @@ typedef isc__netievent__socket_t isc__netievent_udplisten_t;
typedef isc__netievent__socket_t isc__netievent_udpstop_t;
typedef isc__netievent__socket_t isc__netievent_tcpstop_t;
typedef isc__netievent__socket_t isc__netievent_tcpclose_t;
typedef isc__netievent__socket_t isc__netievent_tlsclose_t;
typedef isc__netievent__socket_t isc__netievent_tcpdnsclose_t;
typedef isc__netievent__socket_t isc__netievent_startread_t;
typedef isc__netievent__socket_t isc__netievent_pauseread_t;
......@@ -336,7 +343,9 @@ typedef enum isc_nmsocket_type {
isc_nm_tcpsocket,
isc_nm_tcplistener,
isc_nm_tcpdnslistener,
isc_nm_tcpdnssocket
isc_nm_tcpdnssocket,
isc_nm_tlslistener,
isc_nm_tlssocket
} isc_nmsocket_type;
/*%
......@@ -372,6 +381,15 @@ struct isc_nmsocket {
/*% Listener socket this connection was accepted on */
isc_nmsocket_t *listener;
/*% TLS stuff */
struct tls {
BIO *app_bio;
SSL *ssl;
SSL_CTX *ctx;
BIO *ssl_bio;
enum { INIT, HANDSHAKE, IO, CLOSING } state;
} tls;
/*%
* quota is the TCP client, attached when a TCP connection
* is established. pquota is a non-attached pointer to the
......@@ -727,6 +745,15 @@ isc__nm_async_tcpclose(isc__networker_t *worker, isc__netievent_t *ev0);
* stoplisten, send, read, pause, close).
*/
void
isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0);
void
isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0);
/*%<
* Callback handlers for asynchronouse TLS events.
*/
isc_result_t
isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region,
isc_nm_cb_t cb, void *cbarg);
......@@ -746,6 +773,37 @@ isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock);
void
isc__nm_async_tcpdnsclose(isc__networker_t *worker, isc__netievent_t *ev0);
isc_result_t
isc__nm_tls_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
void *cbarg);
isc_result_t
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg);
void
isc__nm_tls_close(isc_nmsocket_t *sock);
/*%<
* Close a TLS socket.
*/
isc_result_t
isc__nm_tls_pauseread(isc_nmsocket_t *sock);
/*%<
* Pause reading on this socket, while still remembering the callback.
*/
isc_result_t
isc__nm_tls_resumeread(isc_nmsocket_t *sock);
/*%<
* Resume reading from socket.
*
*/
void
isc__nm_tls_stoplistening(isc_nmsocket_t *sock);
void
isc__nm_async_tls_startread(isc__networker_t *worker, isc__netievent_t *ev0);
#define isc__nm_uverr2result(x) \
isc___nm_uverr2result(x, true, __FILE__, __LINE__)
isc_result_t
......
......@@ -588,6 +588,7 @@ process_queue(isc__networker_t *worker, isc_queue_t *queue) {
uv_stop(&worker->loop);
isc_mempool_put(worker->mgr->evpool, ievent);
return;
case netievent_udplisten:
isc__nm_async_udplisten(worker, ievent);
break;
......@@ -597,6 +598,7 @@ process_queue(isc__networker_t *worker, isc_queue_t *queue) {
case netievent_udpsend:
isc__nm_async_udpsend(worker, ievent);
break;
case netievent_tcpconnect:
isc__nm_async_tcpconnect(worker, ievent);
break;
......@@ -624,9 +626,21 @@ process_queue(isc__networker_t *worker, isc_queue_t *queue) {
case netievent_tcpclose:
isc__nm_async_tcpclose(worker, ievent);
break;
case netievent_tlsstartread:
isc__nm_async_tls_startread(worker, ievent);
break;
case netievent_tlssend:
isc__nm_async_tlssend(worker, ievent);
break;
case netievent_tlsclose:
isc__nm_async_tlsclose(worker, ievent);
break;
case netievent_tcpdnsclose:
isc__nm_async_tcpdnsclose(worker, ievent);
break;
case netievent_closecb:
isc__nm_async_closecb(worker, ievent);
break;
......@@ -863,6 +877,8 @@ isc__nmsocket_prep_destroy(isc_nmsocket_t *sock) {
case isc_nm_tcpdnssocket:
isc__nm_tcpdns_close(sock);
break;
case isc_nm_tlssocket:
isc__nm_tls_close(sock);
default:
break;
}
......@@ -1076,7 +1092,7 @@ isc__nmhandle_get(isc_nmsocket_t *sock, isc_sockaddr_t *peer,
handle->ah_pos = pos;
UNLOCK(&sock->lock);
if (sock->type == isc_nm_tcpsocket) {
if (sock->type == isc_nm_tcpsocket || sock->type == isc_nm_tlssocket) {
INSIST(sock->tcphandle == NULL);
sock->tcphandle = handle;
}
......@@ -1307,6 +1323,8 @@ isc_nm_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
return (isc__nm_tcp_send(handle, region, cb, cbarg));
case isc_nm_tcpdnssocket:
return (isc__nm_tcpdns_send(handle, region, cb, cbarg));
case isc_nm_tlssocket:
return (isc__nm_tls_send(handle, region, cb, cbarg));
default:
INSIST(0);
ISC_UNREACHABLE();
......@@ -1320,6 +1338,8 @@ isc_nm_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
switch (handle->sock->type) {
case isc_nm_tcpsocket:
return (isc__nm_tcp_read(handle, cb, cbarg));
case isc_nm_tlssocket:
return (isc__nm_tls_read(handle, cb, cbarg));
default:
INSIST(0);
ISC_UNREACHABLE();
......@@ -1332,6 +1352,8 @@ isc_nm_pauseread(isc_nmsocket_t *sock) {
switch (sock->type) {
case isc_nm_tcpsocket:
return (isc__nm_tcp_pauseread(sock));
case isc_nm_tlssocket:
return (isc__nm_tls_pauseread(sock));
default:
INSIST(0);
ISC_UNREACHABLE();
......@@ -1344,6 +1366,8 @@ isc_nm_resumeread(isc_nmsocket_t *sock) {
switch (sock->type) {
case isc_nm_tcpsocket:
return (isc__nm_tcp_resumeread(sock));
case isc_nm_tlssocket:
return (isc__nm_tls_resumeread(sock));
default:
INSIST(0);
ISC_UNREACHABLE();
......@@ -1363,6 +1387,9 @@ isc_nm_stoplistening(isc_nmsocket_t *sock) {
case isc_nm_tcplistener:
isc__nm_tcp_stoplistening(sock);
break;
case isc_nm_tlslistener:
isc__nm_tls_stoplistening(sock);
break;
default:
INSIST(0);
ISC_UNREACHABLE();
......
......@@ -285,7 +285,7 @@ isc_result_t
isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
void *cbarg, isc_nm_cb_t accept_cb, void *accept_cbarg,
size_t extrahandlesize, int backlog, isc_quota_t *quota,
isc_nmsocket_t **sockp) {
SSL_CTX *sslctx, isc_nmsocket_t **sockp) {
/* A 'wrapper' socket object with outer set to true TCP socket */
isc_nmsocket_t *dnslistensock = isc_mem_get(mgr->mctx,
sizeof(*dnslistensock));
......@@ -301,9 +301,16 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_recv_cb_t cb,
dnslistensock->extrahandlesize = extrahandlesize;
/* We set dnslistensock->outer to a true listening socket */
result = isc_nm_listentcp(mgr, iface, dnslisten_acceptcb, dnslistensock,
extrahandlesize, backlog, quota,
&dnslistensock->outer);
if (sslctx != NULL) {
result = isc_nm_listentls(mgr, iface, dnslisten_acceptcb,
dnslistensock, extrahandlesize,
backlog, quota, sslctx,
&dnslistensock->outer);
} else {
result = isc_nm_listentcp(
mgr, iface, dnslisten_acceptcb, dnslistensock,
extrahandlesize, backlog, quota, &dnslistensock->outer);
}
if (result == ISC_R_SUCCESS) {
atomic_store(&dnslistensock->listening, true);
*sockp = dnslistensock;
......
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <libgen.h>
#include <unistd.h>
#include <uv.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <isc/atomic.h>
#include <isc/buffer.h>
#include <isc/condition.h>
#include <isc/log.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/netmgr.h>
#include <isc/quota.h>
#include <isc/random.h>
#include <isc/refcount.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/sockaddr.h>
#include <isc/stdtime.h>
#include <isc/thread.h>
#include <isc/util.h>
#include "netmgr-int.h"
#include "uv-compat.h"
#define TLS_CHECK_RV INT_MAX
static void
tls_do_bio(isc_nmsocket_t *sock, int rv);
static void
tls_close_direct(isc_nmsocket_t *sock);
static void
tls_senddone(isc_nmhandle_t *t, isc_result_t res, void *arg) {
(void)res;
(void)t;
isc_nmsocket_t *sock = (isc_nmsocket_t *)arg;
/* if (sock->tls.state != IO) {
int rv = SSL_is_init_finished(sock->tls.ssl);
if (rv != 1) {
}
} */
tls_do_bio(sock, TLS_CHECK_RV);
}
static void
tls_do_bio(isc_nmsocket_t *sock, int rv) {
INSIST(sock->tid == isc_nm_tid());
if (rv == TLS_CHECK_RV) {
char buf[1];
rv = SSL_peek(sock->tls.ssl, buf, 1);
if (rv == 1) {
if (sock->rcb.recv != NULL &&
!atomic_load(&sock->readpaused)) {
isc_region_t region = { malloc(4096), 4096 };
memset(region.base, 0, region.length);
rv = SSL_read(sock->tls.ssl, region.base,
region.length);
isc_region_t dregion =
(isc_region_t){ region.base, rv };
sock->rcb.recv(sock->tcphandle, &dregion,
sock->rcbarg);
free(region.base);
}
}
}
int pending = BIO_pending(sock->tls.app_bio);
if (pending > 0) {
char *p = malloc(pending);
int s;
rv = BIO_read(sock->tls.app_bio, p, pending);
s = isc_nm_send(sock->outer->tcphandle,
&(isc_region_t){ (unsigned char *)p, rv },
tls_senddone, sock);
if (s != rv) {
goto error;
}
}
int err = SSL_get_error(sock->tls.ssl, rv);
if (err == 0) {
return;
} else if (err == SSL_ERROR_WANT_WRITE) {
isc_nm_pauseread(sock->outer);
pending = BIO_pending(sock->tls.app_bio);
if (pending > 0) {
int s;
char *p = malloc(pending);
rv = BIO_read(sock->tls.app_bio, p, pending);
s = isc_nm_send(sock->outer->tcphandle,
&(isc_region_t){ (unsigned char *)p, rv },
tls_senddone, sock);
if (s != rv) {
goto error;
}
}
} else if (err == SSL_ERROR_WANT_READ) {
isc_nm_resumeread(sock->outer);
} else {
goto error;
}
return;
error:
/* XXXWPK TODO log it ! */
if (sock->rcb.recv != NULL) {
sock->rcb.recv(sock->tcphandle, NULL, sock->rcbarg);
} else {
tls_close_direct(sock);
}
}
/*
static int
isc__nm_tls_handshake(isc_nmsocket_t *sock) {
if (sock->tls.state == IO) {
return (1);
}
int rv;
rv = SSL_do_handshake(sock->tls.ssl);
printf("%d %d\n", rv, SSL_get_error(sock->tls.ssl, rv));
sock->tls.state = HANDSHAKE;
if (rv == 1) {
sock->tls.state = IO; */
/* XXXWPK TODO CONNECT callback */
/* }
tls_sendpending(sock);
return (rv);
} */
static void
tls_readcb(isc_nmhandle_t *handle, isc_region_t *region, void *arg) {
isc_nmsocket_t *tlssock = (isc_nmsocket_t *)arg;
int rv;
REQUIRE(VALID_NMSOCK(tlssock));
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(tlssock->tid == isc_nm_tid());
if (region == NULL) {
/* Connection closed */
if (tlssock->rcb.recv != NULL) {
tlssock->rcb.recv(tlssock->tcphandle, region,
tlssock->rcbarg);
}
isc__nm_tls_close(tlssock);
return;
}
rv = BIO_write(tlssock->tls.app_bio, region->base, region->length);
INSIST(rv > 0 && (unsigned int)rv == region->length);
tls_do_bio(tlssock, TLS_CHECK_RV);
if (tlssock->tls.state != IO) {
if (SSL_is_init_finished(tlssock->tls.ssl) == 1) {
tlssock->listener->accept_cb.accept(
tlssock->tcphandle, ISC_R_SUCCESS,
tlssock->listener->accept_cbarg);
tlssock->tls.state = IO;
/* We need to do it again - to flush incoming buffer */
tls_do_bio(tlssock, TLS_CHECK_RV);
}
}
}
static isc_result_t
initialize_tls(isc_nmsocket_t *sock, isc_nmsocket_t *listener, bool srv) {
INSIST(sock->tid == isc_nm_tid());
sock->tls.ctx = listener->tls.ctx;
sock->tls.ssl = SSL_new(sock->tls.ctx);
if (sock->tls.ssl == NULL) {
return (ISC_R_TLSERROR);
}
if (BIO_new_bio_pair(&(sock->tls.ssl_bio), 0, &(sock->tls.app_bio),
0) != 1) {
SSL_free(sock->tls.ssl);
return (ISC_R_TLSERROR);
}
SSL_set_bio(sock->tls.ssl, sock->tls.ssl_bio, sock->tls.ssl_bio);
if (srv) {
SSL_set_accept_state(sock->tls.ssl);
} else {
SSL_set_connect_state(sock->tls.ssl);
}
isc_nm_read(sock->outer->tcphandle, tls_readcb, sock);
tls_do_bio(sock, TLS_CHECK_RV);
return (ISC_R_SUCCESS);
}
static void
tlslisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) {
isc_nmsocket_t *tlslistensock = (isc_nmsocket_t *)cbarg;
isc_nmsocket_t *tlssock = NULL;
REQUIRE(VALID_NMSOCK(tlslistensock));
REQUIRE(tlslistensock->type == isc_nm_tlslistener);
/* If accept() was unsuccessful we can't do anything */
if (result != ISC_R_SUCCESS) {
return;
}
/* We need to create a 'wrapper' tlssocket for this connection */
tlssock = isc_mem_get(handle->sock->mgr->mctx, sizeof(*tlssock));
isc__nmsocket_init(tlssock, handle->sock->mgr, isc_nm_tlssocket,
handle->sock->iface);
tlssock->extrahandlesize = tlslistensock->extrahandlesize;
isc_nmsocket_attach(tlslistensock, &tlssock->listener);
isc_nmsocket_attach(handle->sock, &tlssock->outer);
tlssock->peer = handle->sock->peer;
tlssock->read_timeout = handle->sock->mgr->init;
tlssock->tid = isc_nm_tid();
isc__nmhandle_get(tlssock, NULL, NULL);
uv_timer_init(&tlssock->mgr->workers[isc_nm_tid()].loop,
&tlssock->timer);
tlssock->timer.data = tlssock;
tlssock->timer_initialized = true;
result = initialize_tls(tlssock, tlslistensock, true);
if (result != ISC_R_SUCCESS) {
isc_nmsocket_detach(&tlssock);
abort();
/* TODO log about it! */
return;
}
}
isc_result_t
isc_nm_listentls(isc_nm_t *mgr, isc_nmiface_t *iface, isc_nm_cb_t accept_cb,
void *accept_cbarg, size_t extrahandlesize, int backlog,
isc_quota_t *quota, SSL_CTX *sslctx, isc_nmsocket_t **sockp) {
isc_result_t result;
isc_nmsocket_t *tlssock = isc_mem_get(mgr->mctx, sizeof(*tlssock));
isc__nmsocket_init(tlssock, mgr, isc_nm_tlslistener, iface);
tlssock->accept_cb.accept = accept_cb;
tlssock->accept_cbarg = accept_cbarg;
tlssock->extrahandlesize = extrahandlesize;
tlssock->tls.ctx = sslctx;
/* We set dnslistensock->outer to a true listening socket */
result = isc_nm_listentcp(mgr, iface, tlslisten_acceptcb, tlssock,
extrahandlesize, backlog, quota,
&tlssock->outer);
if (result == ISC_R_SUCCESS) {
atomic_store(&tlssock->listening, true);
*sockp = tlssock;
return (ISC_R_SUCCESS);
} else {
atomic_store(&tlssock->closed, true);
isc_nmsocket_detach(&tlssock);
return (result);
}
}
static isc_result_t
tls_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req);
void
isc__nm_async_tlssend(isc__networker_t *worker, isc__netievent_t *ev0) {
isc_result_t result;
isc__netievent_tcpsend_t *ievent = (isc__netievent_tcpsend_t *)ev0;
REQUIRE(worker->id == ievent->sock->tid);
if (!atomic_load(&ievent->sock->active)) {
return;
}
result = tls_send_direct(ievent->sock, ievent->req);
if (result != ISC_R_SUCCESS) {
ievent->req->cb.send(ievent->req->handle, result,
ievent->req->cbarg);
isc__nm_uvreq_put(&ievent->req, ievent->req->handle->sock);
}
}
static isc_result_t
tls_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(sock->type == isc_nm_tlssocket);
int rv = SSL_write(sock->tls.ssl, req->uvbuf.base, req->uvbuf.len);
if (rv < 0) {
isc__nm_uvreq_put(&req, sock);
return (isc__nm_uverr2result(rv));
}
INSIST((unsigned)rv == req->uvbuf.len);
tls_do_bio(sock, TLS_CHECK_RV);
req->cb.send(sock->tcphandle, ISC_R_SUCCESS, req->cbarg);
isc__nm_uvreq_put(&req, sock);
return (ISC_R_SUCCESS);
}
isc_result_t
isc__nm_tls_send(isc_nmhandle_t *handle, isc_region_t *region, isc_nm_cb_t cb,
void *cbarg) {
isc_nmsocket_t *sock = handle->sock;
isc__netievent_tcpsend_t *ievent = NULL;
isc__nm_uvreq_t *uvreq = NULL;
REQUIRE(sock->type == isc_nm_tlssocket);
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);
uvreq->cb.send = cb;
uvreq->cbarg = cbarg;
if (sock->tid == isc_nm_tid()) {
/*
* If we're in the same thread as the socket we can send the
* data directly
*/
return (tls_send_direct(sock, uvreq));
} else {
/*
* We need to create an event and pass it using async channel
*/
ievent = isc__nm_get_ievent(sock->mgr, netievent_tlssend);
ievent->sock = sock;
ievent->req = uvreq;
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
return (ISC_R_SUCCESS);
}
return (ISC_R_UNEXPECTED);
}
void
isc__nm_async_tls_startread(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_startread_t *ievent = (isc__netievent_startread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock;
REQUIRE(worker->id == isc_nm_tid());
tls_do_bio(sock, TLS_CHECK_RV);
}
isc_result_t
isc__nm_tls_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) {
isc_nmsocket_t *sock = NULL;
isc__netievent_startread_t *ievent = NULL;
REQUIRE(VALID_NMHANDLE(handle));
REQUIRE(VALID_NMSOCK(handle->sock));
sock = handle->sock;
sock->rcb.recv = cb;
sock->rcbarg = cbarg;
ievent = isc__nm_get_ievent(sock->mgr, netievent_tcpstartread);
ievent->sock = sock;
if (sock->tid == isc_nm_tid()) {
isc__nm_async_tls_startread(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
isc__nm_put_ievent(sock->mgr, ievent);
} else {
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
return (ISC_R_SUCCESS);
}
isc_result_t
isc__nm_tls_pauseread(isc_nmsocket_t *sock) {
atomic_store(&sock->readpaused, true);
return (ISC_R_SUCCESS);
}
isc_result_t
isc__nm_tls_resumeread(isc_nmsocket_t *sock) {
atomic_store(&sock->readpaused, false);
return (ISC_R_SUCCESS);
}
static void
timer_close_cb(uv_handle_t *handle) {
isc_nmsocket_t *sock = (isc_nmsocket_t *)uv_handle_get_data(handle);
INSIST(VALID_NMSOCK(sock));
isc_nmsocket_detach(&sock);
}
static void
tls_close_direct(isc_nmsocket_t *sock) {
REQUIRE(sock->tid == isc_nm_tid());
/* We don't need atomics here, it's all in single network thread */
if (sock->timer_initialized) {
/*
* We need to fire the timer callback to clean it up,
* it will then call us again (via detach) so that we
* can finally close the socket.
*/
sock->timer_initialized = false;
uv_timer_stop(&sock->timer);
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
} else {
/*
* At this point we're certain that there are no external
* references, we can close everything.
*/
if (sock->outer != NULL) {
sock->outer->rcb.recv = NULL;
isc_nmsocket_detach(&sock->outer);
}
if (sock->listener != NULL) {
isc_nmsocket_detach(&sock->listener);
}
atomic_store(&sock->closed, true);
}
}
void
isc__nm_tls_close(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tlssocket);
if (sock->tid == isc_nm_tid()) {
tls_close_direct(sock);
} else {
isc__netievent_tlsclose_t *ievent =
isc__nm_get_ievent(sock->mgr, netievent_tlsclose);
ievent->sock = sock;
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
}
void
isc__nm_async_tlsclose(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_tlsclose_t *ievent = (isc__netievent_tlsclose_t *)ev0;
REQUIRE(worker->id == ievent->sock->tid);
tls_close_direct(ievent->sock);
}
void
isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tlslistener);
atomic_store(&sock->listening, false);
atomic_store(&sock->closed, true);
sock->rcb.recv = NULL;
sock->rcbarg = NULL;
if (sock->outer != NULL) {
isc_nm_stoplistening(sock->outer);
isc_nmsocket_detach(&sock->outer);
}
}
\ No newline at end of file
......@@ -468,7 +468,7 @@ ns_interface_listentcp(ns_interface_t *ifp) {
result = isc_nm_listentcpdns(
ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request,
ifp, ns__client_tcpconn, ifp->mgr->sctx, sizeof(ns_client_t),
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota,
ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota, NULL,
&ifp->tcplistensocket);
if (result != ISC_R_SUCCESS) {
isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
......
......@@ -68,7 +68,7 @@ AC_DEFUN([AX_CHECK_OPENSSL], [
AS_IF([test -f "$ssldir/include/openssl/ssl.h"],
[
OPENSSL_CFLAGS="-I$ssldir/include"
OPENSSL_LIBS="-L$ssldir/lib -lcrypto"
OPENSSL_LIBS="-L$ssldir/lib -lcrypto -lssl"
found=true
AC_MSG_RESULT([yes])
break
......