From 68c6310ee83078d6ad6af0c9ccddef11b8f8b7c2 Mon Sep 17 00:00:00 2001 From: Garrett D'Amore Date: Sat, 5 Jan 2019 16:09:10 -0800 Subject: fixes #847 Define public TLS API --- src/supplemental/tls/CMakeLists.txt | 9 +- src/supplemental/tls/mbedtls/tls.c | 84 +++--- src/supplemental/tls/tls_api.h | 18 +- src/supplemental/tls/tls_common.c | 560 ++++++++++++++++++++++++++++++++++++ src/transport/tls/tls.c | 470 ++++++++---------------------- 5 files changed, 750 insertions(+), 391 deletions(-) create mode 100644 src/supplemental/tls/tls_common.c (limited to 'src') diff --git a/src/supplemental/tls/CMakeLists.txt b/src/supplemental/tls/CMakeLists.txt index 8fed1df1..8f819ea8 100644 --- a/src/supplemental/tls/CMakeLists.txt +++ b/src/supplemental/tls/CMakeLists.txt @@ -1,6 +1,9 @@ # # Copyright 2018 Capitar IT Group BV # Copyright 2018 Staysail Systems, Inc. +# Copyright 2019 Devolutions +# + # # This software is supplied under the terms of the MIT License, a # copy of which should be located in the distribution where this @@ -8,12 +11,14 @@ # found online at https://opensource.org/licenses/MIT. # +set(_SRCS ${PROJECT_SOURCE_DIR}/include/nng/supplemental/tls/tls.h) + if (NNG_SUPP_TLS) set(NNG_SUPP_TLS_MBEDTLS ON) set(_DEFS -DNNG_SUPP_TLS) -endif() -set(_SRCS ${PROJECT_SOURCE_DIR}/include/nng/supplemental/tls/tls.h) + list(APPEND _SRCS supplemental/tls/tls_common.c) +endif() # For now we only support the ARM mbedTLS library. if (NNG_SUPP_TLS_MBEDTLS) diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c index 29f1873e..9f1e8f83 100644 --- a/src/supplemental/tls/mbedtls/tls.c +++ b/src/supplemental/tls/mbedtls/tls.c @@ -1,7 +1,7 @@ // // Copyright 2018 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV -// Copyright 2018 Devolutions +// Copyright 2019 Devolutions // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -158,32 +158,34 @@ nni_tls_config_fini(nng_tls_config *cfg) { nni_tls_certkey *ck; - nni_mtx_lock(&cfg->lk); - cfg->refcnt--; - if (cfg->refcnt != 0) { + if (cfg != NULL) { + nni_mtx_lock(&cfg->lk); + cfg->refcnt--; + if (cfg->refcnt != 0) { + nni_mtx_unlock(&cfg->lk); + return; + } nni_mtx_unlock(&cfg->lk); - return; - } - nni_mtx_unlock(&cfg->lk); - mbedtls_ssl_config_free(&cfg->cfg_ctx); + mbedtls_ssl_config_free(&cfg->cfg_ctx); #ifdef NNG_TLS_USE_CTR_DRBG - mbedtls_ctr_drbg_free(&cfg->rng_ctx); + mbedtls_ctr_drbg_free(&cfg->rng_ctx); #endif - mbedtls_x509_crt_free(&cfg->ca_certs); - mbedtls_x509_crl_free(&cfg->crl); - if (cfg->server_name) { - nni_strfree(cfg->server_name); - } - while ((ck = nni_list_first(&cfg->certkeys))) { - nni_list_remove(&cfg->certkeys, ck); - mbedtls_x509_crt_free(&ck->crt); - mbedtls_pk_free(&ck->key); + mbedtls_x509_crt_free(&cfg->ca_certs); + mbedtls_x509_crl_free(&cfg->crl); + if (cfg->server_name) { + nni_strfree(cfg->server_name); + } + while ((ck = nni_list_first(&cfg->certkeys))) { + nni_list_remove(&cfg->certkeys, ck); + mbedtls_x509_crt_free(&ck->crt); + mbedtls_pk_free(&ck->key); - NNI_FREE_STRUCT(ck); + NNI_FREE_STRUCT(ck); + } + nni_mtx_fini(&cfg->lk); + NNI_FREE_STRUCT(cfg); } - nni_mtx_fini(&cfg->lk); - NNI_FREE_STRUCT(cfg); } int @@ -254,27 +256,29 @@ void nni_tls_fini(nni_tls *tp) { // Shut it all down first. - if (tp->tcp) { - nni_tcp_conn_close(tp->tcp); - } - nni_aio_stop(tp->tcp_send); - nni_aio_stop(tp->tcp_recv); + if (tp != NULL) { + if (tp->tcp) { + nni_tcp_conn_close(tp->tcp); + } + nni_aio_stop(tp->tcp_send); + nni_aio_stop(tp->tcp_recv); - // And finalize / free everything. - if (tp->tcp) { - nni_tcp_conn_fini(tp->tcp); - } - nni_aio_fini(tp->tcp_send); - nni_aio_fini(tp->tcp_recv); - mbedtls_ssl_free(&tp->ctx); - nni_mtx_fini(&tp->lk); - nni_free(tp->recvbuf, NNG_TLS_MAX_RECV_SIZE); - nni_free(tp->sendbuf, NNG_TLS_MAX_RECV_SIZE); - if (tp->cfg != NULL) { - // release the hold we got on it - nni_tls_config_fini(tp->cfg); + // And finalize / free everything. + if (tp->tcp) { + nni_tcp_conn_fini(tp->tcp); + } + nni_aio_fini(tp->tcp_send); + nni_aio_fini(tp->tcp_recv); + mbedtls_ssl_free(&tp->ctx); + nni_mtx_fini(&tp->lk); + nni_free(tp->recvbuf, NNG_TLS_MAX_RECV_SIZE); + nni_free(tp->sendbuf, NNG_TLS_MAX_RECV_SIZE); + if (tp->cfg != NULL) { + // release the hold we got on it + nni_tls_config_fini(tp->cfg); + } + NNI_FREE_STRUCT(tp); } - NNI_FREE_STRUCT(tp); } // nni_tls_mkerr converts an mbed error to an NNG error. In all cases diff --git a/src/supplemental/tls/tls_api.h b/src/supplemental/tls/tls_api.h index 63424d5e..22dd68a0 100644 --- a/src/supplemental/tls/tls_api.h +++ b/src/supplemental/tls/tls_api.h @@ -1,7 +1,7 @@ // // Copyright 2018 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV -// Copyright 2018 Devolutions +// Copyright 2019 Devolutions // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -44,6 +44,20 @@ extern int nni_tls_setopt( nni_tls *, const char *, const void *, size_t, nni_type); extern int nni_tls_getopt(nni_tls *, const char *, void *, size_t *, nni_type); -// TBD: getting additional peer certificate information... +extern int nni_tls_set( + nng_tls *, const char *, const void *, size_t, nni_type); +extern int nni_tls_get(nng_tls *, const char *, void *, size_t *, nni_type); + +extern int nni_tls_dialer_setopt( + nng_tls_dialer *, const char *, const void *, size_t, nni_type); + +extern int nni_tls_dialer_getopt( + nng_tls_dialer *, const char *, void *, size_t *, nni_type); + +extern int nni_tls_listener_setopt( + nng_tls_listener *, const char *, const void *, size_t, nni_type); + +extern int nni_tls_listener_getopt( + nng_tls_listener *, const char *, void *, size_t *, nni_type); #endif // NNG_SUPPLEMENTAL_TLS_TLS_API_H diff --git a/src/supplemental/tls/tls_common.c b/src/supplemental/tls/tls_common.c new file mode 100644 index 00000000..95466558 --- /dev/null +++ b/src/supplemental/tls/tls_common.c @@ -0,0 +1,560 @@ +// +// Copyright 2018 Staysail Systems, Inc. +// Copyright 2018 Capitar IT Group BV +// Copyright 2019 Devolutions +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#include +#include +#include +#include + +#include "core/nng_impl.h" +#include "supplemental/tls/tls_api.h" + +#include +#include + +// This file contains common code for TLS, and is only compiled if we +// have TLS configured in the system. In particular, this provides the +// parts of TLS support that are invariant relative to different TLS +// libraries, such as dialer and listener support. + +struct nng_tls_s { + nni_tls * c; + nni_aio * aio; // system aio for connect/accept + nni_aio * uaio; // user aio for connect/accept + nng_tls_config *cfg; +}; + +// We use a union and share an "endpoint" for both dialers and listeners. +// This allows us to reuse the bulk of the code for things like option +// handlers for both dialers and listeners. +typedef union tls_tcp_ep_u { + nni_tcp_dialer * d; + nni_tcp_listener *l; +} tls_tcp_ep; + +typedef struct nng_tls_ep_s { + tls_tcp_ep tcp; + nng_tls_config *cfg; + nni_mtx lk; +} tls_ep; + +void +nng_tls_close(nng_tls *tls) +{ + nni_tls_close(tls->c); +} + +void +nng_tls_free(nng_tls *tls) +{ + if (tls != NULL) { + nni_tls_fini(tls->c); + nni_aio_fini(tls->aio); + nng_tls_config_free(tls->cfg); + NNI_FREE_STRUCT(tls); + } +} + +void +nng_tls_send(nng_tls *tls, nng_aio *aio) +{ + nni_tls_send(tls->c, aio); +} + +void +nng_tls_recv(nng_tls *tls, nng_aio *aio) +{ + nni_tls_recv(tls->c, aio); +} + +int +nni_tls_get(nng_tls *tls, const char *name, void *buf, size_t *szp, nni_type t) +{ + return (nni_tls_getopt(tls->c, name, buf, szp, t)); +} + +int +nni_tls_set( + nng_tls *tls, const char *name, const void *buf, size_t sz, nni_type t) +{ + return (nni_tls_setopt(tls->c, name, buf, sz, t)); +} + +int +nng_tls_getopt(nng_tls *tls, const char *name, void *buf, size_t *szp) +{ + return (nni_tls_getopt(tls->c, name, buf, szp, NNI_TYPE_OPAQUE)); +} + +int +nng_tls_setopt(nng_tls *tls, const char *name, const void *buf, size_t sz) +{ + return (nni_tls_setopt(tls->c, name, buf, sz, NNI_TYPE_OPAQUE)); +} + +int +nng_tls_dialer_alloc(nng_tls_dialer **dp) +{ + tls_ep *ep; + int rv; + + if ((rv = nni_init()) != 0) { + return (rv); + } + if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { + return (NNG_ENOMEM); + } + nni_mtx_init(&ep->lk); + + if ((rv = nni_tcp_dialer_init(&ep->tcp.d)) != 0) { + nni_mtx_fini(&ep->lk); + NNI_FREE_STRUCT(ep); + return (rv); + } + if ((rv = nng_tls_config_alloc(&ep->cfg, NNG_TLS_MODE_CLIENT)) != 0) { + nni_tcp_dialer_fini(ep->tcp.d); + nni_mtx_fini(&ep->lk); + NNI_FREE_STRUCT(ep); + return (rv); + } + *dp = (void *) ep; + return (rv); +} + +void +nng_tls_dialer_close(nng_tls_dialer *d) +{ + tls_ep *ep = (void *) d; + nni_tcp_dialer_close(ep->tcp.d); +} + +void +nng_tls_dialer_free(nng_tls_dialer *d) +{ + tls_ep *ep = (void *) d; + if (ep != NULL) { + nni_tcp_dialer_fini(ep->tcp.d); + nng_tls_config_free(ep->cfg); + nni_mtx_fini(&ep->lk); + NNI_FREE_STRUCT(ep); + } +} + +// For dialing, we need to have our own completion callback, instead of +// the user's completion callback. + +static void +tls_conn_cb(void *arg) +{ + nng_tls * tls = arg; + nni_tcp_conn *tcp; + int rv; + + if ((rv = nni_aio_result(tls->aio)) != 0) { + nni_aio_finish_error(tls->uaio, rv); + nng_tls_free(tls); + return; + } + + tcp = nni_aio_get_output(tls->aio, 0); + + rv = nni_tls_init(&tls->c, tls->cfg, tcp); + if (rv != 0) { + nni_aio_finish_error(tls->uaio, rv); + nni_tcp_conn_fini(tcp); + nng_tls_free(tls); + return; + } + + nni_aio_set_output(tls->uaio, 0, tls); + nni_aio_finish(tls->uaio, 0, 0); +} + +// Dialer cancel is called when the user has indicated that they no longer +// want to wait for the connection to establish. +static void +tls_conn_cancel(nni_aio *aio, void *arg, int rv) +{ + nng_tls *tls = arg; + NNI_ASSERT(tls->uaio == aio); + // Just pass this down. If the connection is already done, this + // will have no effect. + nni_aio_abort(tls->aio, rv); +} + +void +nng_tls_dialer_dial(nng_tls_dialer *d, const nng_sockaddr *sa, nng_aio *aio) +{ + int rv; + nng_tls *tls; + tls_ep * ep = (void *) d; + + if (nni_aio_begin(aio) != 0) { + return; + } + if ((tls = NNI_ALLOC_STRUCT(tls)) == NULL) { + nni_aio_finish_error(aio, NNG_ENOMEM); + return; + } + if ((rv = nni_aio_init(&tls->aio, tls_conn_cb, tls)) != 0) { + nni_aio_finish_error(aio, rv); + NNI_FREE_STRUCT(tls); + return; + } + tls->uaio = aio; + + // Save a copy of the TLS configuration. This way we don't have + // to ensure that the dialer outlives the connection, because the + // only shared data is the configuration which is reference counted. + nni_mtx_lock(&ep->lk); + tls->cfg = ep->cfg; + nng_tls_config_hold(tls->cfg); + nni_mtx_unlock(&ep->lk); + + if ((rv = nni_aio_schedule(aio, tls_conn_cancel, tls)) != 0) { + nni_aio_finish_error(aio, rv); + nng_tls_free(tls); + return; + } + + nni_tcp_dialer_dial(ep->tcp.d, sa, tls->aio); +} + +static int +tls_check_string(const void *v, size_t sz, nni_opt_type t) +{ + if ((t != NNI_TYPE_OPAQUE) && (t != NNI_TYPE_STRING)) { + return (NNG_EBADTYPE); + } + if (nni_strnlen(v, sz) >= sz) { + return (NNG_EINVAL); + } + return (0); +} + +static int +tls_ep_set_config(void *arg, const void *buf, size_t sz, nni_type t) +{ + int rv; + nng_tls_config *cfg; + tls_ep * ep; + + if ((rv = nni_copyin_ptr((void **) &cfg, buf, sz, t)) != 0) { + return (rv); + } + if (cfg == NULL) { + return (NNG_EINVAL); + } + if ((ep = arg) != NULL) { + nng_tls_config *old; + + nni_mtx_lock(&ep->lk); + old = ep->cfg; + nng_tls_config_hold(cfg); + ep->cfg = cfg; + nni_mtx_unlock(&ep->lk); + if (old != NULL) { + nng_tls_config_free(old); + } + } + return (0); +} + +static int +tls_ep_get_config(void *arg, void *buf, size_t *szp, nni_type t) +{ + tls_ep * ep = arg; + nng_tls_config *cfg; + int rv; + nni_mtx_lock(&ep->lk); + if ((cfg = ep->cfg) != NULL) { + nng_tls_config_hold(cfg); + } + if ((rv = nni_copyout_ptr(cfg, buf, szp, t)) != 0) { + nng_tls_config_free(cfg); + } + nni_mtx_unlock(&ep->lk); + return (rv); +} + +static int +tls_ep_set_server_name(void *arg, const void *buf, size_t sz, nni_type t) +{ + tls_ep *ep = arg; + int rv; + if ((rv = tls_check_string(buf, sz, t)) != 0) { + return (rv); + } + if ((ep = arg) != NULL) { + nni_mtx_lock(&ep->lk); + rv = nng_tls_config_server_name(ep->cfg, buf); + nni_mtx_unlock(&ep->lk); + } + return (rv); +} + +static int +tls_ep_set_auth_mode(void *arg, const void *buf, size_t sz, nni_type t) +{ + int mode; + int rv; + tls_ep *ep; + + rv = nni_copyin_int(&mode, buf, sz, NNG_TLS_AUTH_MODE_NONE, + NNG_TLS_AUTH_MODE_REQUIRED, t); + if ((rv == 0) && ((ep = arg) != NULL)) { + nni_mtx_lock(&ep->lk); + rv = nng_tls_config_auth_mode(ep->cfg, mode); + nni_mtx_unlock(&ep->lk); + } + return (rv); +} + +static int +tls_ep_set_ca_file(void *arg, const void *buf, size_t sz, nni_opt_type t) +{ + tls_ep *ep; + int rv; + + if (((rv = tls_check_string(buf, sz, t)) == 0) && + ((ep = arg) != NULL)) { + nni_mtx_lock(&ep->lk); + rv = nng_tls_config_ca_file(ep->cfg, buf); + nni_mtx_unlock(&ep->lk); + } + return (rv); +} + +static int +tls_ep_set_cert_key_file(void *arg, const void *buf, size_t sz, nni_opt_type t) +{ + tls_ep *ep; + int rv; + + if (((rv = tls_check_string(buf, sz, t)) == 0) && + ((ep = arg) != NULL)) { + nni_mtx_lock(&ep->lk); + rv = nng_tls_config_cert_key_file(ep->cfg, buf, NULL); + nni_mtx_unlock(&ep->lk); + } + return (rv); +} + +static const nni_option tls_ep_opts[] = { + { + .o_name = NNG_OPT_TLS_CONFIG, + .o_get = tls_ep_get_config, + .o_set = tls_ep_set_config, + }, + { + .o_name = NNG_OPT_TLS_SERVER_NAME, + .o_set = tls_ep_set_server_name, + }, + { + .o_name = NNG_OPT_TLS_CA_FILE, + .o_set = tls_ep_set_ca_file, + }, + { + .o_name = NNG_OPT_TLS_CERT_KEY_FILE, + .o_set = tls_ep_set_cert_key_file, + }, + { + .o_name = NNG_OPT_TLS_AUTH_MODE, + .o_set = tls_ep_set_auth_mode, + }, + { + .o_name = NULL, + }, +}; + +// private version of getopt and setopt take the type +int +nni_tls_dialer_getopt( + nng_tls_dialer *d, const char *name, void *buf, size_t *szp, nni_type t) +{ + int rv; + tls_ep *ep = (void *) d; + + rv = nni_tcp_dialer_getopt(ep->tcp.d, name, buf, szp, t); + if (rv == NNG_ENOTSUP) { + rv = nni_getopt(tls_ep_opts, name, ep, buf, szp, t); + } + return (rv); +} + +int +nni_tls_dialer_setopt(nng_tls_dialer *d, const char *name, const void *buf, + size_t sz, nni_type t) +{ + int rv; + tls_ep *ep = (void *) d; + + rv = nni_tcp_dialer_setopt( + ep != NULL ? ep->tcp.d : NULL, name, buf, sz, t); + if (rv == NNG_ENOTSUP) { + rv = nni_setopt(tls_ep_opts, name, ep, buf, sz, t); + } + return (rv); +} + +// public versions of option handlers here + +int +nng_tls_dialer_getopt( + nng_tls_dialer *d, const char *name, void *buf, size_t *szp) +{ + return (nni_tls_dialer_getopt(d, name, buf, szp, NNI_TYPE_OPAQUE)); +} + +int +nng_tls_dialer_setopt( + nng_tls_dialer *d, const char *name, const void *buf, size_t sz) +{ + return (nni_tls_dialer_setopt(d, name, buf, sz, NNI_TYPE_OPAQUE)); +} + +void +nng_tls_listener_close(nng_tls_listener *l) +{ + tls_ep *ep = (void *) l; + nni_tcp_listener_close(ep->tcp.l); +} + +void +nng_tls_listener_free(nng_tls_listener *l) +{ + tls_ep *ep = (void *) l; + if (ep != NULL) { + nng_tls_listener_close(l); + nng_tls_config_free(ep->cfg); + nni_mtx_fini(&ep->lk); + NNI_FREE_STRUCT(ep); + } +} + +int +nng_tls_listener_alloc(nng_tls_listener **lp) +{ + tls_ep *ep; + int rv; + + if ((rv = nni_init()) != 0) { + return (rv); + } + if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { + return (NNG_ENOMEM); + } + nni_mtx_init(&ep->lk); + + if ((rv = nni_tcp_listener_init(&ep->tcp.l)) != 0) { + nni_mtx_fini(&ep->lk); + NNI_FREE_STRUCT(ep); + return (rv); + } + if ((rv = nng_tls_config_alloc(&ep->cfg, NNG_TLS_MODE_SERVER)) != 0) { + nni_tcp_listener_fini(ep->tcp.l); + nni_mtx_fini(&ep->lk); + NNI_FREE_STRUCT(ep); + return (rv); + } + *lp = (void *) ep; + return (0); +} + +int +nng_tls_listener_listen(nng_tls_listener *l, nng_sockaddr *sa) +{ + tls_ep *ep = (void *) l; + return (nni_tcp_listener_listen(ep->tcp.l, sa)); +} + +void +nng_tls_listener_accept(nng_tls_listener *l, nng_aio *aio) +{ + int rv; + nng_tls *tls; + tls_ep * ep = (void *) l; + + if (nni_aio_begin(aio) != 0) { + return; + } + if ((tls = NNI_ALLOC_STRUCT(tls)) == NULL) { + nni_aio_finish_error(aio, NNG_ENOMEM); + return; + } + if ((rv = nni_aio_init(&tls->aio, tls_conn_cb, tls)) != 0) { + nni_aio_finish_error(aio, rv); + NNI_FREE_STRUCT(tls); + return; + } + tls->uaio = aio; + + // Save a copy of the TLS configuration. This way we don't have + // to ensure that the dialer outlives the connection, because the + // only shared data is the configuration which is reference counted. + nni_mtx_lock(&ep->lk); + tls->cfg = ep->cfg; + nng_tls_config_hold(tls->cfg); + nni_mtx_unlock(&ep->lk); + + if ((rv = nni_aio_schedule(aio, tls_conn_cancel, tls)) != 0) { + nni_aio_finish_error(aio, rv); + nng_tls_free(tls); + return; + } + + nni_tcp_listener_accept(ep->tcp.l, tls->aio); +} + +int +nni_tls_listener_getopt( + nng_tls_listener *l, const char *name, void *buf, size_t *szp, nni_type t) +{ + int rv; + tls_ep *ep = (void *) l; + + rv = nni_tcp_listener_getopt(ep->tcp.l, name, buf, szp, t); + if (rv == NNG_ENOTSUP) { + rv = nni_getopt(tls_ep_opts, name, ep, buf, szp, t); + } + return (rv); +} + +int +nni_tls_listener_setopt(nng_tls_listener *l, const char *name, const void *buf, + size_t sz, nni_type t) +{ + int rv; + tls_ep *ep = (void *) l; + + rv = nni_tcp_listener_setopt( + ep != NULL ? ep->tcp.l : NULL, name, buf, sz, t); + if (rv == NNG_ENOTSUP) { + rv = nni_setopt(tls_ep_opts, name, ep, buf, sz, t); + } + return (rv); +} + +// public versions of option handlers here + +int +nng_tls_listener_getopt( + nng_tls_listener *l, const char *name, void *buf, size_t *szp) +{ + return (nni_tls_listener_getopt(l, name, buf, szp, NNI_TYPE_OPAQUE)); +} + +int +nng_tls_listener_setopt( + nng_tls_listener *l, const char *name, const void *buf, size_t sz) +{ + return (nni_tls_listener_setopt(l, name, buf, sz, NNI_TYPE_OPAQUE)); +} diff --git a/src/transport/tls/tls.c b/src/transport/tls/tls.c index dc198ebf..25bfb0dd 100644 --- a/src/transport/tls/tls.c +++ b/src/transport/tls/tls.c @@ -30,13 +30,11 @@ typedef struct tlstran_pipe tlstran_pipe; // tlstran_pipe is one end of a TLS connection. struct tlstran_pipe { - nni_tls * tls; + nng_tls * tls; nni_pipe * npipe; uint16_t peer; uint16_t proto; size_t rcvmax; - bool nodelay; - bool keepalive; bool closed; nni_list_node node; nni_list sendq; @@ -67,20 +65,16 @@ struct tlstran_ep { uint16_t af; uint16_t proto; size_t rcvmax; - bool nodelay; - bool keepalive; bool fini; int authmode; - nng_tls_config * cfg; nni_url * url; nni_list pipes; nni_reap_item reap; - nni_tcp_dialer * dialer; - nni_tcp_listener *listener; + nng_tls_dialer * dialer; + nng_tls_listener *listener; const char * host; nng_sockaddr src; nng_sockaddr sa; - nng_sockaddr bsa; nni_dialer * ndialer; nni_listener * nlistener; }; @@ -116,7 +110,7 @@ tlstran_pipe_close(void *arg) nni_aio_close(p->connaio); nni_aio_close(p->rslvaio); - nni_tls_close(p->tls); + nng_tls_close(p->tls); } static void @@ -159,9 +153,7 @@ tlstran_pipe_fini(void *arg) nni_aio_fini(p->negoaio); nni_aio_fini(p->connaio); nni_aio_fini(p->rslvaio); - if (p->tls != NULL) { - nni_tls_fini(p->tls); - } + nng_tls_free(p->tls); nni_msg_free(p->rxmsg); NNI_FREE_STRUCT(p); } @@ -190,12 +182,10 @@ tlstran_pipe_alloc(tlstran_pipe **pipep, tlstran_ep *ep) nni_atomic_flag_reset(&p->reaped); nni_list_append(&ep->pipes, p); - p->keepalive = ep->keepalive; - p->nodelay = ep->nodelay; - p->rcvmax = ep->rcvmax; - p->proto = ep->proto; - p->ep = ep; - *pipep = p; + p->rcvmax = ep->rcvmax; + p->proto = ep->proto; + p->ep = ep; + *pipep = p; return (0); } @@ -204,7 +194,7 @@ tlstran_pipe_reap(tlstran_pipe *p) { if (!nni_atomic_flag_test_and_set(&p->reaped)) { if (p->tls != NULL) { - nni_tls_close(p->tls); + nng_tls_close(p->tls); } nni_reap(&p->reap, tlstran_pipe_fini, p); } @@ -250,7 +240,7 @@ tlstran_pipe_rslv_cb(void *arg) tlstran_pipe_reap(p); return; } - nni_tcp_dialer_dial(ep->dialer, &p->sa, p->connaio); + nng_tls_dialer_dial(ep->dialer, &p->sa, p->connaio); nni_mtx_unlock(&ep->mtx); } @@ -262,31 +252,24 @@ tlstran_pipe_conn_cb(void *arg) nni_aio * aio = p->connaio; nni_aio * uaio; nni_iov iov; - nni_tcp_conn *conn; int rv; nni_mtx_lock(&ep->mtx); if ((rv = nni_aio_result(aio)) == 0) { - conn = nni_aio_get_output(aio, 0); + p->tls = nni_aio_get_output(aio, 0); } else { - conn = NULL; + p->tls = NULL; } if ((uaio = p->useraio) == NULL) { - if (conn != NULL) { - nni_tcp_conn_fini(conn); - } nni_mtx_unlock(&ep->mtx); tlstran_pipe_reap(p); return; } - if ((rv != 0) || ((rv = nni_tls_init(&p->tls, ep->cfg, conn)) != 0)) { + if (rv != 0) { p->useraio = NULL; nni_mtx_unlock(&ep->mtx); - if (conn != NULL) { - nni_tcp_conn_fini(conn); - } nni_aio_finish_error(uaio, rv); tlstran_pipe_reap(p); return; @@ -305,7 +288,7 @@ tlstran_pipe_conn_cb(void *arg) iov.iov_len = 8; iov.iov_buf = &p->txlen[0]; nni_aio_set_iov(p->negoaio, 1, &iov); - nni_tls_send(p->tls, p->negoaio); + nng_tls_send(p->tls, p->negoaio); nni_mtx_unlock(&ep->mtx); } @@ -342,7 +325,7 @@ tlstran_pipe_nego_cb(void *arg) iov.iov_buf = &p->txlen[p->gottxhead]; nni_aio_set_iov(aio, 1, &iov); // send it down... - nni_tls_send(p->tls, aio); + nng_tls_send(p->tls, aio); nni_mtx_unlock(&ep->mtx); return; } @@ -351,7 +334,7 @@ tlstran_pipe_nego_cb(void *arg) iov.iov_len = p->wantrxhead - p->gotrxhead; iov.iov_buf = &p->rxlen[p->gotrxhead]; nni_aio_set_iov(aio, 1, &iov); - nni_tls_recv(p->tls, aio); + nng_tls_recv(p->tls, aio); nni_mtx_unlock(&ep->mtx); return; } @@ -368,11 +351,6 @@ tlstran_pipe_nego_cb(void *arg) p->useraio = NULL; nni_mtx_unlock(&ep->mtx); - (void) nni_tls_setopt(p->tls, NNG_OPT_TCP_NODELAY, &p->nodelay, - sizeof(p->nodelay), NNI_TYPE_BOOL); - (void) nni_tls_setopt(p->tls, NNG_OPT_TCP_KEEPALIVE, &p->keepalive, - sizeof(p->keepalive), NNI_TYPE_BOOL); - nni_aio_set_output(uaio, 0, p); nni_aio_finish(uaio, 0, 0); return; @@ -412,7 +390,7 @@ tlstran_pipe_send_cb(void *arg) n = nni_aio_count(txaio); nni_aio_iov_advance(txaio, n); if (nni_aio_iov_count(txaio) > 0) { - nni_tls_send(p->tls, txaio); + nng_tls_send(p->tls, txaio); nni_mtx_unlock(&p->mtx); return; } @@ -448,7 +426,7 @@ tlstran_pipe_recv_cb(void *arg) nni_aio_iov_advance(rxaio, n); if (nni_aio_iov_count(rxaio) > 0) { // Was this a partial read? If so then resubmit for the rest. - nni_tls_recv(p->tls, rxaio); + nng_tls_recv(p->tls, rxaio); nni_mtx_unlock(&p->mtx); return; } @@ -480,7 +458,7 @@ tlstran_pipe_recv_cb(void *arg) iov.iov_len = (size_t) len; nni_aio_set_iov(rxaio, 1, &iov); - nni_tls_recv(p->tls, rxaio); + nng_tls_recv(p->tls, rxaio); nni_mtx_unlock(&p->mtx); return; } @@ -570,7 +548,7 @@ tlstran_pipe_send_start(tlstran_pipe *p) } nni_aio_set_iov(txaio, niov, iov); - nni_tls_send(p->tls, txaio); + nng_tls_send(p->tls, txaio); } static void @@ -631,7 +609,7 @@ tlstran_pipe_recv_start(tlstran_pipe *p) iov.iov_len = sizeof(p->rxlen); nni_aio_set_iov(rxaio, 1, &iov); - nni_tls_recv(p->tls, rxaio); + nng_tls_recv(p->tls, rxaio); } static void @@ -676,17 +654,10 @@ tlstran_ep_fini(void *arg) nni_mtx_unlock(&ep->mtx); return; } - if (ep->dialer != NULL) { - nni_tcp_dialer_fini(ep->dialer); - } - if (ep->listener != NULL) { - nni_tcp_listener_fini(ep->listener); - } + nng_tls_dialer_free(ep->dialer); + nng_tls_listener_free(ep->listener); nni_mtx_unlock(&ep->mtx); - if (ep->cfg != NULL) { - nni_tls_config_fini(ep->cfg); - } nni_mtx_fini(&ep->mtx); NNI_FREE_STRUCT(ep); } @@ -705,14 +676,14 @@ tlstran_ep_close(void *arg) nni_aio_close(p->txaio); nni_aio_close(p->rxaio); if (p->tls != NULL) { - nni_tls_close(p->tls); + nng_tls_close(p->tls); } } if (ep->dialer != NULL) { - nni_tcp_dialer_close(ep->dialer); + nng_tls_dialer_close(ep->dialer); } if (ep->listener != NULL) { - nni_tcp_listener_close(ep->listener); + nng_tls_listener_close(ep->listener); } nni_mtx_unlock(&ep->mtx); } @@ -753,13 +724,11 @@ tlstran_ep_init_dialer(void **dp, nni_url *url, nni_dialer *ndialer) nni_mtx_init(&ep->mtx); NNI_LIST_INIT(&ep->pipes, tlstran_pipe, node); - ep->authmode = NNG_TLS_AUTH_MODE_REQUIRED; - ep->url = url; - ep->af = af; - ep->proto = nni_sock_proto_id(sock); - ep->nodelay = true; - ep->keepalive = false; - ep->ndialer = ndialer; + ep->authmode = NNG_TLS_AUTH_MODE_REQUIRED; + ep->url = url; + ep->af = af; + ep->proto = nni_sock_proto_id(sock); + ep->ndialer = ndialer; // Detect an embedded local interface name in the hostname. This // syntax is only valid with dialers. @@ -798,10 +767,11 @@ tlstran_ep_init_dialer(void **dp, nni_url *url, nni_dialer *ndialer) rv = 0; } - if ((rv != 0) || ((rv = nni_tcp_dialer_init(&ep->dialer)) != 0) || - ((rv = nni_tls_config_init(&ep->cfg, NNG_TLS_MODE_CLIENT)) != 0) || - ((rv = nng_tls_config_auth_mode(ep->cfg, ep->authmode)) != 0) || - ((rv = nng_tls_config_server_name(ep->cfg, ep->host)) != 0)) { + if ((rv != 0) || ((rv = nng_tls_dialer_alloc(&ep->dialer)) != 0) || + ((rv = nng_tls_dialer_setopt(ep->dialer, NNG_OPT_TLS_AUTH_MODE, + &ep->authmode, sizeof(ep->authmode))) != 0) || + ((rv = nng_tls_dialer_setopt(ep->dialer, NNG_OPT_TLS_SERVER_NAME, + ep->host, strlen(ep->host) + 1)) != 0)) { tlstran_ep_fini(ep); return (rv); } @@ -849,8 +819,6 @@ tlstran_ep_init_listener(void **lp, nni_url *url, nni_listener *nlistener) ep->url = url; ep->af = af; ep->proto = nni_sock_proto_id(sock); - ep->nodelay = true; - ep->keepalive = false; ep->nlistener = nlistener; if (strlen(host) == 0) { @@ -873,10 +841,9 @@ tlstran_ep_init_listener(void **lp, nni_url *url, nni_listener *nlistener) rv = nni_aio_result(aio); nni_aio_fini(aio); - ep->bsa = ep->sa; - if (((rv = nni_tcp_listener_init(&ep->listener)) != 0) || - ((rv = nni_tls_config_init(&ep->cfg, NNG_TLS_MODE_SERVER)) != 0) || - ((rv = nng_tls_config_auth_mode(ep->cfg, ep->authmode)) != 0)) { + if ((rv != 0) || ((rv = nng_tls_listener_alloc(&ep->listener)) != 0) || + ((rv = nng_tls_listener_setopt(ep->listener, NNG_OPT_TLS_AUTH_MODE, + &ep->authmode, sizeof(ep->authmode))) != 0)) { tlstran_ep_fini(ep); return (rv); } @@ -921,8 +888,7 @@ tlstran_ep_bind(void *arg) int rv; nni_mtx_lock(&ep->mtx); - ep->bsa = ep->sa; - rv = nni_tcp_listener_listen(ep->listener, &ep->bsa); + rv = nng_tls_listener_listen(ep->listener, &ep->sa); nni_mtx_unlock(&ep->mtx); return (rv); @@ -953,35 +919,10 @@ tlstran_ep_accept(void *arg, nni_aio *aio) } p->useraio = aio; - nni_tcp_listener_accept(ep->listener, p->connaio); + nng_tls_listener_accept(ep->listener, p->connaio); nni_mtx_unlock(&ep->mtx); } -static int -tlstran_ep_set_nodelay(void *arg, const void *v, size_t sz, nni_opt_type t) -{ - tlstran_ep *ep = arg; - bool val; - int rv; - if (((rv = nni_copyin_bool(&val, v, sz, t)) == 0) && (ep != NULL)) { - nni_mtx_lock(&ep->mtx); - ep->nodelay = val; - nni_mtx_unlock(&ep->mtx); - } - return (rv); -} - -static int -tlstran_ep_get_nodelay(void *arg, void *v, size_t *szp, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int rv; - nni_mtx_lock(&ep->mtx); - rv = nni_copyout_bool(ep->nodelay, v, szp, t); - nni_mtx_unlock(&ep->mtx); - return (rv); -} - static int tlstran_ep_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t) { @@ -997,31 +938,6 @@ tlstran_ep_set_recvmaxsz(void *arg, const void *v, size_t sz, nni_opt_type t) return (rv); } -static int -tlstran_ep_set_keepalive(void *arg, const void *v, size_t sz, nni_opt_type t) -{ - tlstran_ep *ep = arg; - bool val; - int rv; - if (((rv = nni_copyin_bool(&val, v, sz, t)) == 0) && (ep != NULL)) { - nni_mtx_lock(&ep->mtx); - ep->keepalive = val; - nni_mtx_unlock(&ep->mtx); - } - return (rv); -} - -static int -tlstran_ep_get_keepalive(void *arg, void *v, size_t *szp, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int rv; - nni_mtx_lock(&ep->mtx); - rv = nni_copyout_bool(ep->keepalive, v, szp, t); - nni_mtx_unlock(&ep->mtx); - return (rv); -} - static int tlstran_ep_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t) { @@ -1036,146 +952,28 @@ tlstran_ep_get_recvmaxsz(void *arg, void *v, size_t *szp, nni_opt_type t) static int tlstran_ep_get_url(void *arg, void *v, size_t *szp, nni_opt_type t) { - tlstran_ep *ep = arg; - char ustr[128]; - char ipstr[48]; // max for IPv6 addresses including [] - char portstr[6]; // max for 16-bit port + tlstran_ep * ep = arg; + char ustr[128]; + char ipstr[48]; // max for IPv6 addresses including [] + char portstr[6]; // max for 16-bit port + nng_sockaddr sa; + size_t sz = sizeof(sa); + int rv; if (ep->dialer != NULL) { return (nni_copyout_str(ep->url->u_rawurl, v, szp, t)); } - nni_mtx_lock(&ep->mtx); - nni_ntop(&ep->bsa, ipstr, portstr); - nni_mtx_unlock(&ep->mtx); - snprintf(ustr, sizeof(ustr), "tls+tcp://%s:%s", ipstr, portstr); - return (nni_copyout_str(ustr, v, szp, t)); -} - -static int -tlstran_ep_get_locaddr(void *arg, void *buf, size_t *szp, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int rv; - - nni_mtx_lock(&ep->mtx); - rv = nni_copyout_sockaddr(&ep->bsa, buf, szp, t); - nni_mtx_unlock(&ep->mtx); - return (rv); -} - -static int -tlstran_ep_set_config(void *arg, const void *data, size_t sz, nni_opt_type t) -{ - tlstran_ep * ep = arg; - nng_tls_config *cfg; - int rv; - - if ((rv = nni_copyin_ptr((void **) &cfg, data, sz, t)) != 0) { + rv = nni_tls_listener_getopt( + ep->listener, NNG_OPT_LOCADDR, &sa, &sz, NNI_TYPE_SOCKADDR); + if (rv != 0) { return (rv); } - if (cfg == NULL) { - return (NNG_EINVAL); - } - if (ep != NULL) { - nng_tls_config *old; - nni_mtx_lock(&ep->mtx); - old = ep->cfg; - nni_tls_config_hold(cfg); - ep->cfg = cfg; - nni_mtx_unlock(&ep->mtx); - if (old != NULL) { - nni_tls_config_fini(old); - } - } - return (0); -} - -static int -tlstran_ep_get_config(void *arg, void *v, size_t *szp, nni_opt_type t) -{ - tlstran_ep * ep = arg; - nng_tls_config *cfg; - int rv; nni_mtx_lock(&ep->mtx); - if ((cfg = ep->cfg) != NULL) { - nni_tls_config_hold(cfg); - } - rv = nni_copyout_ptr(cfg, v, szp, t); + nni_ntop(&sa, ipstr, portstr); nni_mtx_unlock(&ep->mtx); - return (rv); -} - -static int -tlstran_check_string(const void *v, size_t sz, nni_opt_type t) -{ - if ((t != NNI_TYPE_OPAQUE) && (t != NNI_TYPE_STRING)) { - return (NNG_EBADTYPE); - } - if (nni_strnlen(v, sz) >= sz) { - return (NNG_EINVAL); - } - return (0); -} - -static int -tlstran_ep_set_ca_file(void *arg, const void *v, size_t sz, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int rv; - - if (((rv = tlstran_check_string(v, sz, t)) == 0) && (ep != NULL)) { - nni_mtx_lock(&ep->mtx); - rv = nng_tls_config_ca_file(ep->cfg, v); - nni_mtx_unlock(&ep->mtx); - } - return (rv); -} - -static int -tlstran_ep_set_auth_mode(void *arg, const void *v, size_t sz, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int mode; - int rv; - - rv = nni_copyin_int(&mode, v, sz, NNG_TLS_AUTH_MODE_NONE, - NNG_TLS_AUTH_MODE_REQUIRED, t); - if ((rv == 0) && (ep != NULL)) { - nni_mtx_lock(&ep->mtx); - rv = nng_tls_config_auth_mode(ep->cfg, mode); - nni_mtx_unlock(&ep->mtx); - } - return (rv); -} - -static int -tlstran_ep_set_server_name(void *arg, const void *v, size_t sz, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int rv; - - if (((rv = tlstran_check_string(v, sz, t)) == 0) && (ep != NULL)) { - nni_mtx_lock(&ep->mtx); - rv = nng_tls_config_server_name(ep->cfg, v); - nni_mtx_unlock(&ep->mtx); - } - return (rv); -} - -static int -tlstran_ep_set_cert_key_file( - void *arg, const void *v, size_t sz, nni_opt_type t) -{ - tlstran_ep *ep = arg; - int rv; - - if (((rv = tlstran_check_string(v, sz, t)) == 0) && (ep != NULL)) { - nni_mtx_lock(&ep->mtx); - rv = nng_tls_config_cert_key_file(ep->cfg, v, NULL); - nni_mtx_unlock(&ep->mtx); - } - return (rv); + snprintf(ustr, sizeof(ustr), "tls+tcp://%s:%s", ipstr, portstr); + return (nni_copyout_str(ustr, v, szp, t)); } static const nni_option tlstran_pipe_opts[] = { @@ -1192,7 +990,7 @@ tlstran_pipe_getopt( tlstran_pipe *p = arg; int rv; - if ((rv = nni_tls_getopt(p->tls, name, buf, szp, t)) == NNG_ENOTSUP) { + if ((rv = nni_tls_get(p->tls, name, buf, szp, t)) == NNG_ENOTSUP) { rv = nni_getopt(tlstran_pipe_opts, name, p, buf, szp, t); } return (rv); @@ -1209,7 +1007,7 @@ static nni_tran_pipe_ops tlstran_pipe_ops = { .p_getopt = tlstran_pipe_getopt, }; -static nni_option tlstran_dialer_options[] = { +static nni_option tlstran_ep_options[] = { { .o_name = NNG_OPT_RECVMAXSZ, .o_get = tlstran_ep_get_recvmaxsz, @@ -1219,109 +1017,87 @@ static nni_option tlstran_dialer_options[] = { .o_name = NNG_OPT_URL, .o_get = tlstran_ep_get_url, }, - { - .o_name = NNG_OPT_TLS_CONFIG, - .o_get = tlstran_ep_get_config, - .o_set = tlstran_ep_set_config, - }, - { - .o_name = NNG_OPT_TLS_CERT_KEY_FILE, - .o_set = tlstran_ep_set_cert_key_file, - }, - { - .o_name = NNG_OPT_TLS_CA_FILE, - .o_set = tlstran_ep_set_ca_file, - }, - { - .o_name = NNG_OPT_TLS_AUTH_MODE, - .o_set = tlstran_ep_set_auth_mode, - }, - { - .o_name = NNG_OPT_TLS_SERVER_NAME, - .o_set = tlstran_ep_set_server_name, - }, - { - .o_name = NNG_OPT_TCP_NODELAY, - .o_get = tlstran_ep_get_nodelay, - .o_set = tlstran_ep_set_nodelay, - }, - { - .o_name = NNG_OPT_TCP_KEEPALIVE, - .o_get = tlstran_ep_get_keepalive, - .o_set = tlstran_ep_set_keepalive, - }, // terminate list { .o_name = NULL, }, }; -static nni_option tlstran_listener_options[] = { - { - .o_name = NNG_OPT_RECVMAXSZ, - .o_get = tlstran_ep_get_recvmaxsz, - .o_set = tlstran_ep_set_recvmaxsz, - }, - { - .o_name = NNG_OPT_URL, - .o_get = tlstran_ep_get_url, - }, - { - .o_name = NNG_OPT_LOCADDR, - .o_get = tlstran_ep_get_locaddr, - }, - { - .o_name = NNG_OPT_TLS_CONFIG, - .o_get = tlstran_ep_get_config, - .o_set = tlstran_ep_set_config, - }, - { - .o_name = NNG_OPT_TLS_CERT_KEY_FILE, - .o_set = tlstran_ep_set_cert_key_file, - }, - { - .o_name = NNG_OPT_TLS_CA_FILE, - .o_set = tlstran_ep_set_ca_file, - }, - { - .o_name = NNG_OPT_TLS_AUTH_MODE, - .o_set = tlstran_ep_set_auth_mode, - }, - { - .o_name = NNG_OPT_TLS_SERVER_NAME, - .o_set = tlstran_ep_set_server_name, - }, - { - .o_name = NNG_OPT_TCP_NODELAY, - .o_get = tlstran_ep_get_nodelay, - .o_set = tlstran_ep_set_nodelay, - }, - { - .o_name = NNG_OPT_TCP_KEEPALIVE, - .o_get = tlstran_ep_get_keepalive, - .o_set = tlstran_ep_set_keepalive, - }, - // terminate list - { - .o_name = NULL, - }, -}; +static int +tlstran_dialer_getopt( + void *arg, const char *name, void *buf, size_t *szp, nni_type t) +{ + int rv; + tlstran_ep *ep = arg; + + rv = nni_tls_dialer_getopt(ep->dialer, name, buf, szp, t); + if (rv == NNG_ENOTSUP) { + rv = nni_getopt(tlstran_ep_options, name, ep, buf, szp, t); + } + return (rv); +} + +static int +tlstran_dialer_setopt( + void *arg, const char *name, const void *buf, size_t sz, nni_type t) +{ + int rv; + tlstran_ep *ep = arg; + + rv = nni_tls_dialer_setopt( + ep != NULL ? ep->dialer : NULL, name, buf, sz, t); + if (rv == NNG_ENOTSUP) { + rv = nni_setopt(tlstran_ep_options, name, ep, buf, sz, t); + } + return (rv); +} + +static int +tlstran_listener_getopt( + void *arg, const char *name, void *buf, size_t *szp, nni_type t) +{ + int rv; + tlstran_ep *ep = arg; + + rv = nni_tls_listener_getopt(ep->listener, name, buf, szp, t); + if (rv == NNG_ENOTSUP) { + rv = nni_getopt(tlstran_ep_options, name, ep, buf, szp, t); + } + return (rv); +} + +static int +tlstran_listener_setopt( + void *arg, const char *name, const void *buf, size_t sz, nni_type t) +{ + int rv; + tlstran_ep *ep = arg; + + rv = nni_tls_listener_setopt( + ep != NULL ? ep->listener : NULL, name, buf, sz, t); + if (rv == NNG_ENOTSUP) { + rv = nni_setopt(tlstran_ep_options, name, ep, buf, sz, t); + } + return (rv); +} static nni_tran_dialer_ops tlstran_dialer_ops = { .d_init = tlstran_ep_init_dialer, .d_fini = tlstran_ep_fini, .d_connect = tlstran_ep_connect, .d_close = tlstran_ep_close, - .d_options = tlstran_dialer_options, + .d_getopt = tlstran_dialer_getopt, + .d_setopt = tlstran_dialer_setopt, }; static nni_tran_listener_ops tlstran_listener_ops = { - .l_init = tlstran_ep_init_listener, - .l_fini = tlstran_ep_fini, - .l_bind = tlstran_ep_bind, - .l_accept = tlstran_ep_accept, - .l_close = tlstran_ep_close, - .l_options = tlstran_listener_options, + .l_init = tlstran_ep_init_listener, + .l_fini = tlstran_ep_fini, + .l_bind = tlstran_ep_bind, + .l_accept = tlstran_ep_accept, + .l_close = tlstran_ep_close, + .l_getopt = tlstran_listener_getopt, + .l_setopt = tlstran_listener_setopt, }; static nni_tran tls_tran = { -- cgit v1.2.3-70-g09d2