diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample index a2664e41a1..a94707e596 100644 --- a/configs/samples/rtp.conf.sample +++ b/configs/samples/rtp.conf.sample @@ -102,6 +102,10 @@ rtpend=20000 ; ; ice_blacklist = ; +; The MTU to use for DTLS packet fragmentation. This option is set to 1200 +; by default. The minimum MTU is 256. +; dtls_mtu = 1200 +; [ice_host_candidates] ; ; When Asterisk is behind a static one-to-one NAT and ICE is in use, ICE will diff --git a/configure b/configure index 2a704b544e..92143a47b5 100755 --- a/configure +++ b/configure @@ -1152,6 +1152,10 @@ PBX_DAHDI DAHDI_DIR DAHDI_INCLUDE DAHDI_LIB +PBX_OPENSSL_BIO_METHOD +OPENSSL_BIO_METHOD_DIR +OPENSSL_BIO_METHOD_INCLUDE +OPENSSL_BIO_METHOD_LIB PBX_OPENSSL_SRTP OPENSSL_SRTP_DIR OPENSSL_SRTP_INCLUDE @@ -9827,6 +9831,18 @@ PBX_OPENSSL_SRTP=0 +OPENSSL_BIO_METHOD_DESCRIP="OpenSSL BIO Method Support" +OPENSSL_BIO_METHOD_OPTION=crypto +OPENSSL_BIO_METHOD_DIR=${CRYPTO_DIR} + +PBX_OPENSSL_BIO_METHOD=0 + + + + + + + DAHDI_DESCRIP="DAHDI" DAHDI_OPTION="dahdi" PBX_DAHDI=0 @@ -31149,6 +31165,102 @@ _ACEOF fi + +if test "x${PBX_OPENSSL_BIO_METHOD}" != "x1" -a "${USE_OPENSSL_BIO_METHOD}" != "no"; then + pbxlibdir="" + # if --with-OPENSSL_BIO_METHOD=DIR has been specified, use it. + if test "x${OPENSSL_BIO_METHOD_DIR}" != "x"; then + if test -d ${OPENSSL_BIO_METHOD_DIR}/lib; then + pbxlibdir="-L${OPENSSL_BIO_METHOD_DIR}/lib" + else + pbxlibdir="-L${OPENSSL_BIO_METHOD_DIR}" + fi + fi + + ast_ext_lib_check_save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} " + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_meth_new in -lssl" >&5 +$as_echo_n "checking for BIO_meth_new in -lssl... " >&6; } +if ${ac_cv_lib_ssl_BIO_meth_new+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl ${pbxlibdir} -lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BIO_meth_new (); +int +main () +{ +return BIO_meth_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ssl_BIO_meth_new=yes +else + ac_cv_lib_ssl_BIO_meth_new=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_BIO_meth_new" >&5 +$as_echo "$ac_cv_lib_ssl_BIO_meth_new" >&6; } +if test "x$ac_cv_lib_ssl_BIO_meth_new" = xyes; then : + AST_OPENSSL_BIO_METHOD_FOUND=yes +else + AST_OPENSSL_BIO_METHOD_FOUND=no +fi + + CFLAGS="${ast_ext_lib_check_save_CFLAGS}" + + + # now check for the header. + if test "${AST_OPENSSL_BIO_METHOD_FOUND}" = "yes"; then + OPENSSL_BIO_METHOD_LIB="${pbxlibdir} -lssl -lcrypto" + # if --with-OPENSSL_BIO_METHOD=DIR has been specified, use it. + if test "x${OPENSSL_BIO_METHOD_DIR}" != "x"; then + OPENSSL_BIO_METHOD_INCLUDE="-I${OPENSSL_BIO_METHOD_DIR}/include" + fi + OPENSSL_BIO_METHOD_INCLUDE="${OPENSSL_BIO_METHOD_INCLUDE} " + + # check for the header + ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${OPENSSL_BIO_METHOD_INCLUDE}" + ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : + OPENSSL_BIO_METHOD_HEADER_FOUND=1 +else + OPENSSL_BIO_METHOD_HEADER_FOUND=0 +fi + + + CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}" + + if test "x${OPENSSL_BIO_METHOD_HEADER_FOUND}" = "x0" ; then + OPENSSL_BIO_METHOD_LIB="" + OPENSSL_BIO_METHOD_INCLUDE="" + else + + PBX_OPENSSL_BIO_METHOD=1 + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_BIO_METHOD 1 +_ACEOF + + fi + fi +fi + + fi if test "$PBX_OPENSSL" = "1"; diff --git a/configure.ac b/configure.ac index e65f159803..b2fcb85308 100644 --- a/configure.ac +++ b/configure.ac @@ -480,6 +480,7 @@ AST_EXT_LIB_SETUP_OPTIONAL([COROSYNC_CFG_STATE_TRACK], [A callback only in coros AST_EXT_LIB_SETUP([CRYPT], [password and data encryption], [crypt]) AST_EXT_LIB_SETUP([CRYPTO], [OpenSSL Cryptography], [crypto]) AST_EXT_LIB_SETUP_OPTIONAL([OPENSSL_SRTP], [OpenSSL SRTP Extension Support], [CRYPTO], [crypto]) +AST_EXT_LIB_SETUP_OPTIONAL([OPENSSL_BIO_METHOD], [OpenSSL BIO Method Support], [CRYPTO], [crypto]) AST_EXT_LIB_SETUP([DAHDI], [DAHDI], [dahdi]) AST_EXT_LIB_SETUP([FFMPEG], [Ffmpeg and avcodec], [avcodec]) AST_EXT_LIB_SETUP([GSM], [External GSM], [gsm], [, use 'internal' GSM otherwise]) @@ -2588,6 +2589,7 @@ AST_EXT_LIB_CHECK([CRYPTO], [crypto], [AES_encrypt], [openssl/aes.h]) if test "$PBX_CRYPTO" = "1"; then AST_EXT_LIB_CHECK([OPENSSL], [ssl], [SSL_connect], [openssl/ssl.h], [-lcrypto]) + AST_EXT_LIB_CHECK([OPENSSL_BIO_METHOD], [ssl], [BIO_meth_new], [openssl/ssl.h], [-lcrypto]) fi if test "$PBX_OPENSSL" = "1"; diff --git a/doc/CHANGES-staging/res_rtp_asterisk_dtls_fragmentation.txt b/doc/CHANGES-staging/res_rtp_asterisk_dtls_fragmentation.txt new file mode 100644 index 0000000000..dfc5984d6f --- /dev/null +++ b/doc/CHANGES-staging/res_rtp_asterisk_dtls_fragmentation.txt @@ -0,0 +1,5 @@ +Subject: res_rtp_asterisk + +DTLS packets will now be fragmented according to the MTU as set in rtp.conf. This +allows larger certificates to be used for the DTLS negotiation. By default this value +is 1200. diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index 71df798c12..8f7aaa1360 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -582,6 +582,9 @@ /* Define to 1 if you have the OpenSSL Secure Sockets Layer library. */ #undef HAVE_OPENSSL +/* Define to 1 if CRYPTO has the OpenSSL BIO Method Support feature. */ +#undef HAVE_OPENSSL_BIO_METHOD + /* Define to 1 if CRYPTO has the OpenSSL SRTP Extension Support feature. */ #undef HAVE_OPENSSL_SRTP diff --git a/menuselect/configure b/menuselect/configure index 8efb6372e8..fd7d24b87b 100755 --- a/menuselect/configure +++ b/menuselect/configure @@ -692,6 +692,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -772,6 +773,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' @@ -1024,6 +1026,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1161,7 +1172,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1314,6 +1325,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 335a329c69..b55a7d511e 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -174,6 +174,7 @@ enum strict_rtp_mode { #define DEFAULT_STRICT_RTP STRICT_RTP_YES /*!< Enabled by default */ #define DEFAULT_ICESUPPORT 1 +#define DEFAULT_DTLS_MTU 1200 extern struct ast_srtp_res *res_srtp; extern struct ast_srtp_policy_res *res_srtp_policy; @@ -203,6 +204,9 @@ static pj_str_t turnaddr; static int turnport = DEFAULT_TURN_PORT; static pj_str_t turnusername; static pj_str_t turnpassword; +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) +static int dtls_mtu = DEFAULT_DTLS_MTU; +#endif static struct ast_ha *ice_blacklist = NULL; /*!< Blacklisted ICE networks */ static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE; @@ -593,13 +597,101 @@ static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instanc #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) static int ast_rtp_activate(struct ast_rtp_instance *instance); -static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp); static void dtls_srtp_start_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp); static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp); +static int dtls_bio_write(BIO *bio, const char *buf, int len); +static long dtls_bio_ctrl(BIO *bio, int cmd, long arg1, void *arg2); +static int dtls_bio_new(BIO *bio); +static int dtls_bio_free(BIO *bio); + +#ifndef HAVE_OPENSSL_BIO_METHOD +static BIO_METHOD dtls_bio_methods = { + .type = BIO_TYPE_BIO, + .name = "rtp write", + .bwrite = dtls_bio_write, + .ctrl = dtls_bio_ctrl, + .create = dtls_bio_new, + .destroy = dtls_bio_free, +}; +#else +static BIO_METHOD *dtls_bio_methods; +#endif #endif static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *via_ice, int use_srtp); +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) +static int dtls_bio_new(BIO *bio) +{ +#ifdef HAVE_OPENSSL_BIO_METHOD + BIO_set_init(bio, 1); + BIO_set_data(bio, NULL); + BIO_set_shutdown(bio, 0); +#else + bio->init = 1; + bio->ptr = NULL; + bio->flags = 0; +#endif + return 1; +} + +static int dtls_bio_free(BIO *bio) +{ + /* The pointer on the BIO is that of the RTP instance. It is not reference counted as the BIO + * lifetime is tied to the instance, and actions on the BIO are taken by the thread handling + * the RTP instance - not another thread. + */ +#ifdef HAVE_OPENSSL_BIO_METHOD + BIO_set_data(bio, NULL); +#else + bio->ptr = NULL; +#endif + return 1; +} + +static int dtls_bio_write(BIO *bio, const char *buf, int len) +{ +#ifdef HAVE_OPENSSL_BIO_METHOD + struct ast_rtp_instance *instance = BIO_get_data(bio); +#else + struct ast_rtp_instance *instance = bio->ptr; +#endif + struct ast_rtp *rtp = ast_rtp_instance_get_data(instance); + int rtcp = 0; + struct ast_sockaddr remote_address = { {0, } }; + int ice; + + if (rtp->rtcp && rtp->rtcp->dtls.write_bio == bio) { + rtcp = 1; + ast_sockaddr_copy(&remote_address, &rtp->rtcp->them); + } else { + ast_rtp_instance_get_remote_address(instance, &remote_address); + } + + if (ast_sockaddr_isnull(&remote_address)) { + return 0; + } + + return __rtp_sendto(instance, (char *)buf, len, 0, &remote_address, rtcp, &ice, 0); +} + +static long dtls_bio_ctrl(BIO *bio, int cmd, long arg1, void *arg2) +{ + switch (cmd) { + case BIO_CTRL_FLUSH: + return 1; + case BIO_CTRL_DGRAM_QUERY_MTU: + return dtls_mtu; + case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: + return 0L; + default: + return 0; + } +} + +#endif + #ifdef HAVE_PJPROJECT /*! \brief Helper function which clears the ICE host candidate mapping */ static void host_candidate_overrides_clear(void) @@ -1630,7 +1722,7 @@ static int dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) } static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx, - enum ast_rtp_dtls_setup setup) + enum ast_rtp_dtls_setup setup, struct ast_rtp_instance *instance) { dtls->dtls_setup = setup; @@ -1645,12 +1737,20 @@ static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx, } BIO_set_mem_eof_return(dtls->read_bio, -1); - if (!(dtls->write_bio = BIO_new(BIO_s_mem()))) { +#ifdef HAVE_OPENSSL_BIO_METHOD + if (!(dtls->write_bio = BIO_new(dtls_bio_methods))) { ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n"); goto error; } - BIO_set_mem_eof_return(dtls->write_bio, -1); + BIO_set_data(dtls->write_bio, instance); +#else + if (!(dtls->write_bio = BIO_new(&dtls_bio_methods))) { + ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n"); + goto error; + } + dtls->write_bio->ptr = instance; +#endif SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio); if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) { @@ -1688,7 +1788,7 @@ static int dtls_setup_rtcp(struct ast_rtp_instance *instance) return 0; } - return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup); + return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup, instance); } static const SSL_METHOD *get_dtls_method(void) @@ -2081,7 +2181,7 @@ static int ast_rtp_dtls_set_configuration(struct ast_rtp_instance *instance, con rtp->rekey = dtls_cfg->rekey; rtp->suite = dtls_cfg->suite; - res = dtls_details_initialize(&rtp->dtls, rtp->ssl_ctx, dtls_cfg->default_setup); + res = dtls_details_initialize(&rtp->dtls, rtp->ssl_ctx, dtls_cfg->default_setup, instance); if (!res) { dtls_setup_rtcp(instance); } @@ -2337,12 +2437,6 @@ static void dtls_perform_handshake(struct ast_rtp_instance *instance, struct dtl * timer before we have a chance to even start it. */ dtls_srtp_start_timeout_timer(instance, rtp, rtcp); - - /* - * We must call dtls_srtp_check_pending() after starting the timer. - * Otherwise we won't prevent the race condition. - */ - dtls_srtp_check_pending(instance, rtp, rtcp); } #endif @@ -2533,7 +2627,6 @@ static int dtls_srtp_handle_timeout(struct ast_rtp_instance *instance, int rtcp) struct timeval dtls_timeout; DTLSv1_handle_timeout(dtls->ssl); - dtls_srtp_check_pending(instance, rtp, rtcp); /* If a timeout can't be retrieved then this recurring scheduled item must stop */ if (!DTLSv1_get_timeout(dtls->ssl, &dtls_timeout)) { @@ -2604,40 +2697,6 @@ static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, stru AST_SCHED_DEL_UNREF(rtp->sched, dtls->timeout_timer, ao2_ref(instance, -1)); } -/*! \pre instance is locked */ -static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp) -{ - struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls; - size_t pending; - - if (!dtls->ssl || !dtls->write_bio) { - return; - } - - pending = BIO_ctrl_pending(dtls->write_bio); - - if (pending > 0) { - char outgoing[pending]; - size_t out; - struct ast_sockaddr remote_address = { {0, } }; - int ice; - - if (!rtcp) { - ast_rtp_instance_get_remote_address(instance, &remote_address); - } else { - ast_sockaddr_copy(&remote_address, &rtp->rtcp->them); - } - - /* If we do not yet know an address to send this to defer it until we do */ - if (ast_sockaddr_isnull(&remote_address)) { - return; - } - - out = BIO_read(dtls->write_bio, outgoing, sizeof(outgoing)); - __rtp_sendto(instance, outgoing, out, 0, &remote_address, rtcp, &ice, 0); - } -} - /* Scheduler callback */ static int dtls_srtp_renegotiate(const void *data) { @@ -2648,12 +2707,10 @@ static int dtls_srtp_renegotiate(const void *data) SSL_renegotiate(rtp->dtls.ssl); SSL_do_handshake(rtp->dtls.ssl); - dtls_srtp_check_pending(instance, rtp, 0); if (rtp->rtcp && rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) { SSL_renegotiate(rtp->rtcp->dtls.ssl); SSL_do_handshake(rtp->rtcp->dtls.ssl); - dtls_srtp_check_pending(instance, rtp, 1); } rtp->rekeyid = -1; @@ -2904,8 +2961,6 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s SSL_set_accept_state(dtls->ssl); } - dtls_srtp_check_pending(instance, rtp, rtcp); - BIO_write(dtls->read_bio, buf, len); len = SSL_read(dtls->ssl, buf, len); @@ -2917,8 +2972,6 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s return -1; } - dtls_srtp_check_pending(instance, rtp, rtcp); - if (SSL_is_init_finished(dtls->ssl)) { /* Any further connections will be existing since this is now established */ dtls->connection = AST_RTP_DTLS_CONNECTION_EXISTING; @@ -8559,6 +8612,10 @@ static int rtp_reload(int reload) blacklist_clear(&stun_blacklist_lock, &stun_blacklist); #endif +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) + dtls_mtu = DEFAULT_DTLS_MTU; +#endif + if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) { rtpstart = atoi(s); if (rtpstart < MINIMUM_RTP_PORT) @@ -8692,6 +8749,15 @@ static int rtp_reload(int reload) /* Read STUN blacklist configuration lines */ blacklist_config_load(cfg, "stun_blacklist", &stun_blacklist_lock, &stun_blacklist); #endif +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) + if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) { + if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) { + ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n", + DEFAULT_DTLS_MTU); + dtls_mtu = DEFAULT_DTLS_MTU; + } + } +#endif ast_config_destroy(cfg); @@ -8769,7 +8835,24 @@ static int load_module(void) #endif +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD) + dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write"); + if (!dtls_bio_methods) { +#ifdef HAVE_PJPROJECT + rtp_terminate_pjproject(); +#endif + return AST_MODULE_LOAD_DECLINE; + } + BIO_meth_set_write(dtls_bio_methods, dtls_bio_write); + BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl); + BIO_meth_set_create(dtls_bio_methods, dtls_bio_new); + BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free); +#endif + if (ast_rtp_engine_register(&asterisk_rtp_engine)) { +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD) + BIO_meth_free(dtls_bio_methods); +#endif #ifdef HAVE_PJPROJECT rtp_terminate_pjproject(); #endif @@ -8777,6 +8860,9 @@ static int load_module(void) } if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) { +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD) + BIO_meth_free(dtls_bio_methods); +#endif #ifdef HAVE_PJPROJECT ast_rtp_engine_unregister(&asterisk_rtp_engine); rtp_terminate_pjproject(); @@ -8794,6 +8880,12 @@ static int unload_module(void) ast_rtp_engine_unregister(&asterisk_rtp_engine); ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp)); +#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD) + if (dtls_bio_methods) { + BIO_meth_free(dtls_bio_methods); + } +#endif + #ifdef HAVE_PJPROJECT host_candidate_overrides_clear(); pj_thread_register_check();