* sockets with active handles, the socket will be closed.
*/
+void
+isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx);
+/*%<
+ * Asynchronously replace the TLS context within the listener socket object.
+ * The function is intended to be used during reconfiguration.
+ *
+ * Requires:
+ * \li 'listener' is a pointer to a valid network manager listener socket
+ object with TLS support;
+ * \li 'tlsctx' is a valid pointer to a TLS context object.
+ */
+
#ifdef NETMGR_TRACE
#define isc_nmhandle_attach(handle, dest) \
isc__nmhandle_attach(handle, dest, __FILE__, __LINE__, __func__)
return (isc_nm_verify_tls_peer_result_string(session->handle));
}
+void
+isc__nm_http_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
+ REQUIRE(VALID_NMSOCK(listener));
+ REQUIRE(listener->type == isc_nm_httplistener);
+
+ isc_nmsocket_set_tlsctx(listener->outer, tlsctx);
+}
+
static const bool base64url_validation_table[256] = {
false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false,
netievent_task,
+ netievent_settlsctx,
+
/*
* event type values higher than this will be treated
* as high-priority events, which can be processed
isc__nm_put_netievent(nm, ievent); \
}
+typedef struct isc__netievent__tlsctx {
+ NETIEVENT__SOCKET;
+ isc_tlsctx_t *tlsctx;
+} isc__netievent__tlsctx_t;
+
+#define NETIEVENT_SOCKET_TLSCTX_TYPE(type) \
+ typedef isc__netievent__tlsctx_t isc__netievent_##type##_t;
+
+#define NETIEVENT_SOCKET_TLSCTX_DECL(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx); \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+ isc__netievent_##type##_t *ievent);
+
+#define NETIEVENT_SOCKET_TLSCTX_DEF(type) \
+ isc__netievent_##type##_t *isc__nm_get_netievent_##type( \
+ isc_nm_t *nm, isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx) { \
+ isc__netievent_##type##_t *ievent = \
+ isc__nm_get_netievent(nm, netievent_##type); \
+ isc__nmsocket_attach(sock, &ievent->sock); \
+ isc_tlsctx_attach(tlsctx, &ievent->tlsctx); \
+ \
+ return (ievent); \
+ } \
+ \
+ void isc__nm_put_netievent_##type(isc_nm_t *nm, \
+ isc__netievent_##type##_t *ievent) { \
+ isc_tlsctx_free(&ievent->tlsctx); \
+ isc__nmsocket_detach(&ievent->sock); \
+ isc__nm_put_netievent(nm, ievent); \
+ }
+
typedef union {
isc__netievent_t ni;
isc__netievent__socket_t nis;
isc__netievent_udpsend_t nius;
isc__netievent__socket_quota_t nisq;
isc__netievent_tlsconnect_t nitc;
+ isc__netievent__tlsctx_t nitls;
} isc__netievent_storage_t;
/*
isc_tlsctx_t *ctx;
isc_tlsctx_t **listener_tls_ctx; /*%< A context reference per
worker */
+ size_t n_listener_tls_ctx;
isc_nmsocket_t *tlslistener;
atomic_bool result_updated;
enum {
isc__nm_async_tlsdnsshutdown(isc__networker_t *worker, isc__netievent_t *ev0);
void
isc__nm_async_tlsdnsread(isc__networker_t *worker, isc__netievent_t *ev0);
+void
+isc__nm_async_tlsdns_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
+ const int tid);
/*%<
* Callback handlers for asynchronous TLSDNS events.
*/
* Set the keepalive value on the underlying TCP handle.
*/
+void
+isc__nm_async_tls_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
+ const int tid);
+
void
isc__nm_http_stoplistening(isc_nmsocket_t *sock);
void
isc__nm_httpsession_detach(isc_nm_http_session_t **sessionp);
+void
+isc__nm_http_set_tlsctx(isc_nmsocket_t *sock, isc_tlsctx_t *tlsctx);
+
#endif
+void
+isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0);
+
#define isc__nm_uverr2result(x) \
isc___nm_uverr2result(x, true, __FILE__, __LINE__, __func__)
isc_result_t
NETIEVENT_TASK_TYPE(task);
+NETIEVENT_SOCKET_TLSCTX_TYPE(settlsctx);
+
/* Now declared the helper functions */
NETIEVENT_SOCKET_DECL(close);
NETIEVENT_TASK_DECL(task);
+NETIEVENT_SOCKET_TLSCTX_DECL(settlsctx);
+
void
isc__nm_udp_failed_read_cb(isc_nmsocket_t *sock, isc_result_t result);
void
NETIEVENT_CASE(httpsend);
NETIEVENT_CASE(httpclose);
#endif
+ NETIEVENT_CASE(settlsctx);
NETIEVENT_CASE(connectcb);
NETIEVENT_CASE(readcb);
NETIEVENT_TASK_DEF(task);
+NETIEVENT_SOCKET_TLSCTX_DEF(settlsctx);
+
void
isc__nm_maybe_enqueue_ievent(isc__networker_t *worker,
isc__netievent_t *event) {
return (NULL);
}
+void
+isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0) {
+ isc__netievent__tlsctx_t *ev_tlsctx = (isc__netievent__tlsctx_t *)ev0;
+ const int tid = isc_nm_tid();
+ isc_nmsocket_t *listener = ev_tlsctx->sock;
+ isc_tlsctx_t *tlsctx = ev_tlsctx->tlsctx;
+
+ UNUSED(worker);
+
+ switch (listener->type) {
+ case isc_nm_tlsdnslistener:
+ isc__nm_async_tlsdns_set_tlsctx(listener, tlsctx, tid);
+ break;
+#if HAVE_LIBNGHTTP2
+ case isc_nm_tlslistener:
+ isc__nm_async_tls_set_tlsctx(listener, tlsctx, tid);
+ break;
+#endif /* HAVE_LIBNGHTTP2 */
+ default:
+ UNREACHABLE();
+ break;
+ };
+}
+
+static void
+set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
+ /* Update the TLS context reference for every worker thread. */
+ for (size_t i = 0; i < isc_nm_getnworkers(listener->mgr); i++) {
+ isc__netievent__tlsctx_t *ievent =
+ isc__nm_get_netievent_settlsctx(listener->mgr, listener,
+ tlsctx);
+ isc__nm_enqueue_ievent(&listener->mgr->workers[i],
+ (isc__netievent_t *)ievent);
+ }
+}
+
+void
+isc_nmsocket_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
+ REQUIRE(VALID_NMSOCK(listener));
+ REQUIRE(tlsctx != NULL);
+
+ switch (listener->type) {
+#if HAVE_LIBNGHTTP2
+ case isc_nm_httplistener:
+ /*
+ * We handle HTTP listener sockets differently, as they rely
+ * on underlying TLS sockets for networking. The TLS context
+ * will get passed to these underlying sockets via the call to
+ * isc__nm_http_set_tlsctx().
+ */
+ isc__nm_http_set_tlsctx(listener, tlsctx);
+ break;
+ case isc_nm_tlslistener:
+ set_tlsctx_workers(listener, tlsctx);
+ break;
+#endif /* HAVE_LIBNGHTTP2 */
+ case isc_nm_tlsdnslistener:
+ set_tlsctx_workers(listener, tlsctx);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ };
+}
+
#ifdef NETMGR_TRACE
/*
* Dump all active sockets in netmgr. We output to stderr
return (isc_tls_verify_peer_result_string(sock->tls.tls));
}
+void
+isc__nm_async_tlsdns_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
+ const int tid) {
+ REQUIRE(tid >= 0);
+
+ isc_tlsctx_free(&listener->children[tid].tls.ctx);
+ isc_tlsctx_attach(tlsctx, &listener->children[tid].tls.ctx);
+}
void
isc__nm_tlsdns_cleanup_data(isc_nmsocket_t *sock) {
{
isc_tlsctx_free(&sock->tls.ctx);
}
-}
\ No newline at end of file
+}
static void
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
- uint32_t nworkers;
+ size_t nworkers;
REQUIRE(VALID_NM(listener->mgr));
-
- nworkers = isc_nm_getnworkers(listener->mgr);
-
- REQUIRE(nworkers > 0);
REQUIRE(ctx != NULL);
+ nworkers = (size_t)isc_nm_getnworkers(listener->mgr);
+ INSIST(nworkers > 0);
+
listener->tlsstream.listener_tls_ctx = isc_mem_get(
listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
+ listener->tlsstream.n_listener_tls_ctx = nworkers;
for (size_t i = 0; i < nworkers; i++) {
listener->tlsstream.listener_tls_ctx[i] = NULL;
isc_tlsctx_attach(ctx,
static void
tls_cleanup_listener_tlsctx(isc_nmsocket_t *listener) {
- uint32_t nworkers;
-
REQUIRE(VALID_NM(listener->mgr));
- nworkers = isc_nm_getnworkers(listener->mgr);
-
- REQUIRE(nworkers > 0);
if (listener->tlsstream.listener_tls_ctx == NULL) {
return;
}
- for (size_t i = 0; i < nworkers; i++) {
+ for (size_t i = 0; i < listener->tlsstream.n_listener_tls_ctx; i++) {
isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[i]);
}
isc_mem_put(listener->mgr->mctx, listener->tlsstream.listener_tls_ctx,
- sizeof(isc_tlsctx_t *) * nworkers);
+ sizeof(isc_tlsctx_t *) *
+ listener->tlsstream.n_listener_tls_ctx);
+ listener->tlsstream.n_listener_tls_ctx = 0;
}
static isc_tlsctx_t *
return (listener->tlsstream.listener_tls_ctx[tid]);
}
+
+void
+isc__nm_async_tls_set_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx,
+ const int tid) {
+ REQUIRE(tid >= 0);
+
+ isc_tlsctx_free(&listener->tlsstream.listener_tls_ctx[tid]);
+ isc_tlsctx_attach(tlsctx, &listener->tlsstream.listener_tls_ctx[tid]);
+}