diff --git a/CHANGES b/CHANGES
index 3cc1cd4f59a86fd7fd02e83baaa0f725a568c695..622973c48f0090448ca2c9119d627b9cb6cf4869 100644
--- a/CHANGES
+++ b/CHANGES
@@ -34,6 +34,19 @@ res_pjsip
    preferred codec rather than advertising all joint codec capabilities.
    This limits the other side's codec choice to exactly what we prefer.
 
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 14.1.0 to Asterisk 14.2.0 ----------
+------------------------------------------------------------------------------
+
+res_pjsip
+------------------
+ * Automatic dual stack support is now implemented. Depending on DNS resolution
+   and the transport used for sending a message the SIP signaling and SDP will
+   be updated with the correct IP address and protocol version. This means that
+   the rtp_ipv6 and t38_udptl_ipv6 options no longer have any effect. The
+   res_pjsip_multihomed module has also been moved into core res_pjsip to ensure
+   that messages are updated with the correct address information in all cases.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.0.0 to Asterisk 14.1.0 ----------
 ------------------------------------------------------------------------------
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index c6293b6fbcaaa5dd8a30e46587d9b1be243978f9..3bb9dc5bb72586eb31609a06fde4face3549575d 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -112,9 +112,6 @@
 ; the prefix "external_" will only apply to communication with addresses
 ; outside the range set with "local_net=".
 ;
-; IPv6: For endpoints using IPv6, remember to set "rtp_ipv6=yes" so that the RTP
-; engine will also be able to bind to an IPv6 address.
-;
 ; You can have more than one of any type of transport, as long as it doesn't
 ; use the same resources (bind address, port, etc) as the others.
 
@@ -294,8 +291,6 @@
 ; If using the TLS enabled transport, you may want the "media_encryption=sdes"
 ; option to additionally enable SRTP, though they are not mutually inclusive.
 ;
-; Use the "rtp_ipv6=yes" option if you want to utilize RTP over an ipv6 transport.
-;
 ; If this endpoint were remote, and it was using a transport configured for NAT
 ; then you likely want to use "direct_media=no" to prevent audio issues.
 
@@ -315,7 +310,6 @@
 ;transport=transport-tls
 ;media_encryption=sdes
 ;transport=transport-udp-ipv6
-;rtp_ipv6=yes
 ;transport=transport-udp-nat
 ;direct_media=no
 ;
@@ -646,7 +640,6 @@
                         ; must be provided (default: "")
 ;rewrite_contact=no     ; Allow Contact header to be rewritten with the source
                         ; IP address port (default: "no")
-;rtp_ipv6=no    ; Allow use of IPv6 for RTP traffic (default: "no")
 ;rtp_symmetric=no       ; Enforce that RTP must be symmetric (default: "no")
 ;send_diversion=yes     ; Send the Diversion header conveying the diversion
                         ; information to the called user agent (default: "yes")
@@ -699,8 +692,6 @@
                         ; (default: "0")
 ;t38_udptl_nat=no       ; Whether NAT support is enabled on UDPTL sessions
                         ; (default: "no")
-;t38_udptl_ipv6=no      ; Whether IPv6 is used for UDPTL Sessions (default:
-                        ; "no")
 ;tone_zone=     ; Set which country s indications to use for channels created
                 ; for this endpoint (default: "")
 ;language=      ; Set the default language to use for channels created for this
diff --git a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
index 40e93547d28c80dd4668254d3c572be4255d0157..98a5e9546a0ab5672e3d47a4083f319eef22abbc 100755
--- a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
+++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
@@ -374,7 +374,7 @@ def from_dtlsenable(key, val, section, pjsip, nmapped):
 ###############################################################################
 
 # options in pjsip.conf on an endpoint that have no sip.conf equivalent:
-# type, rtp_ipv6, 100rel, trust_id_outbound, aggregate_mwi,
+# type, 100rel, trust_id_outbound, aggregate_mwi,
 # connected_line_method
 
 # known sip.conf peer keys that can be mapped to a pjsip.conf section/key
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index fa200be26af97f354418695f5a5e8b027f600b44..39c365aa1acbbdec6b951213f014977f8dd30d0a 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -4332,6 +4332,7 @@ static int unload_pjsip(void *data)
 	 */
 	if (ast_pjsip_endpoint && serializer_pool[0]) {
 		ast_res_pjsip_cleanup_options_handling();
+		ast_res_pjsip_cleanup_message_ip_updater();
 		ast_sip_destroy_distributor();
 		ast_res_pjsip_destroy_configuration();
 		ast_sip_destroy_system();
@@ -4499,6 +4500,12 @@ static int load_module(void)
 	}
 
 	ast_res_pjsip_init_options_handling(0);
+
+	if (ast_res_pjsip_init_message_ip_updater()) {
+		ast_log(LOG_ERROR, "Failed to initialize message IP updating. Aborting load\n");
+		goto error;
+	}
+
 	ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
 
 	AST_TEST_REGISTER(xml_sanitization_end_null);
diff --git a/res/res_pjsip/include/res_pjsip_private.h b/res/res_pjsip/include/res_pjsip_private.h
index b175b5e1194b9773b44189bcfe60693ab3356a95..0bdb63325af1f280bb1f57c2ffb736bf7e509f01 100644
--- a/res/res_pjsip/include/res_pjsip_private.h
+++ b/res/res_pjsip/include/res_pjsip_private.h
@@ -183,6 +183,14 @@ void ast_sip_destroy_global_headers(void);
  */
 int ast_res_pjsip_init_options_handling(int reload);
 
+/*!
+ * \internal Initialize message IP updating handling.
+ *
+ * \retval 0 on success
+ * \retval other on failure
+ */
+int ast_res_pjsip_init_message_ip_updater(void);
+
 /*!
  * \internal
  * \brief Initialize transport storage for contacts.
@@ -234,6 +242,12 @@ int ast_sip_initialize_global(void);
  */
 void ast_res_pjsip_cleanup_options_handling(void);
 
+/*!
+ * \internal
+ * \brief Clean up res_pjsip message ip updating handling
+ */
+void ast_res_pjsip_cleanup_message_ip_updater(void);
+
 /*!
  * \internal
  * \brief Get threadpool options
diff --git a/res/res_pjsip_multihomed.c b/res/res_pjsip/pjsip_message_ip_updater.c
similarity index 60%
rename from res/res_pjsip_multihomed.c
rename to res/res_pjsip/pjsip_message_ip_updater.c
index 5deeb92476802fa0b7eb3928c2628eb1c539ccec..7671ad0a75e1fb5dbb74ab9888d4255d595506f7 100644
--- a/res/res_pjsip_multihomed.c
+++ b/res/res_pjsip/pjsip_message_ip_updater.c
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 2014, Digium, Inc.
+ * Copyright (C) 2014-2016, Digium, Inc.
  *
  * Joshua Colp <jcolp@digium.com>
  *
@@ -16,19 +16,78 @@
  * at the top of the source tree.
  */
 
-/*** MODULEINFO
-	<depend>pjproject</depend>
-	<depend>res_pjsip</depend>
-	<support_level>core</support_level>
- ***/
-
 #include "asterisk.h"
 
 #include <pjsip.h>
 #include <pjsip_ua.h>
 
 #include "asterisk/res_pjsip.h"
-#include "asterisk/module.h"
+#include "asterisk/res_pjsip_session.h"
+#include "include/res_pjsip_private.h"
+
+#define MOD_DATA_RESTRICTIONS "restrictions"
+
+static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata);
+
+/*! \brief Outgoing message modification restrictions */
+struct multihomed_message_restrictions {
+	/*! \brief Disallow modification of the From domain */
+	unsigned int disallow_from_domain_modification;
+};
+
+static pjsip_module multihomed_module = {
+	.name = { "Multihomed Routing", 18 },
+	.id = -1,
+	.priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 1,
+	.on_tx_request = multihomed_on_tx_message,
+	.on_tx_response = multihomed_on_tx_message,
+};
+
+/*! \brief Helper function to get (or allocate if not already present) restrictions on a message */
+static struct multihomed_message_restrictions *multihomed_get_restrictions(pjsip_tx_data *tdata)
+{
+	struct multihomed_message_restrictions *restrictions;
+
+	restrictions = ast_sip_mod_data_get(tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS);
+	if (restrictions) {
+		return restrictions;
+	}
+
+	restrictions = PJ_POOL_ALLOC_T(tdata->pool, struct multihomed_message_restrictions);
+	ast_sip_mod_data_set(tdata->pool, tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS, restrictions);
+
+	return restrictions;
+}
+
+/*! \brief Callback invoked on non-session outgoing messages */
+static void multihomed_outgoing_message(struct ast_sip_endpoint *endpoint, struct ast_sip_contact *contact, struct pjsip_tx_data *tdata)
+{
+	struct multihomed_message_restrictions *restrictions = multihomed_get_restrictions(tdata);
+
+	restrictions->disallow_from_domain_modification = !ast_strlen_zero(endpoint->fromdomain);
+}
+
+/*! \brief PJSIP Supplement for tagging messages with restrictions */
+static struct ast_sip_supplement multihomed_supplement = {
+	.priority = AST_SIP_SUPPLEMENT_PRIORITY_FIRST,
+	.outgoing_request = multihomed_outgoing_message,
+	.outgoing_response = multihomed_outgoing_message,
+};
+
+/*! \brief Callback invoked on session outgoing messages */
+static void multihomed_session_outgoing_message(struct ast_sip_session *session, struct pjsip_tx_data *tdata)
+{
+	struct multihomed_message_restrictions *restrictions = multihomed_get_restrictions(tdata);
+
+	restrictions->disallow_from_domain_modification = !ast_strlen_zero(session->endpoint->fromdomain);
+}
+
+/*! \brief PJSIP Session Supplement for tagging messages with restrictions */
+static struct ast_sip_session_supplement multihomed_session_supplement = {
+	.priority = 1,
+	.outgoing_request = multihomed_session_outgoing_message,
+	.outgoing_response = multihomed_session_outgoing_message,
+};
 
 /*! \brief Helper function which returns a UDP transport bound to the given address and port */
 static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port)
@@ -59,6 +118,21 @@ static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port
 	return sip_transport;
 }
 
+/*! \brief Helper function which determines if a transport is bound to any */
+static int multihomed_bound_any(pjsip_transport *transport)
+{
+	pj_uint32_t loop6[4] = {0, 0, 0, 0};
+
+	if ((transport->local_addr.addr.sa_family == pj_AF_INET() &&
+		transport->local_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) ||
+		(transport->local_addr.addr.sa_family == pj_AF_INET6() &&
+		!pj_memcmp(&transport->local_addr.ipv6.sin6_addr, loop6, sizeof(loop6)))) {
+		return 1;
+	}
+
+	return 0;
+}
+
 /*! \brief Helper function which determines if the address within SDP should be rewritten */
 static int multihomed_rewrite_sdp(struct pjmedia_sdp_session *sdp)
 {
@@ -77,26 +151,13 @@ static int multihomed_rewrite_sdp(struct pjmedia_sdp_session *sdp)
 	return 0;
 }
 
-/*! \brief Helper function which determines if a transport is bound to any */
-static int multihomed_bound_any(pjsip_transport *transport)
-{
-	pj_uint32_t loop6[4] = {0, 0, 0, 0};
-
-	if ((transport->local_addr.addr.sa_family == pj_AF_INET() &&
-		transport->local_addr.ipv4.sin_addr.s_addr == PJ_INADDR_ANY) ||
-		(transport->local_addr.addr.sa_family == pj_AF_INET6() &&
-		!pj_memcmp(&transport->local_addr.ipv6.sin6_addr, loop6, sizeof(loop6)))) {
-		return 1;
-	}
-
-	return 0;
-}
-
 static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
 {
+	struct multihomed_message_restrictions *restrictions = ast_sip_mod_data_get(tdata->mod_data, multihomed_module.id, MOD_DATA_RESTRICTIONS);
 	pjsip_tpmgr_fla2_param prm;
 	pjsip_cseq_hdr *cseq;
 	pjsip_via_hdr *via;
+	pjsip_fromto_hdr *from;
 
 	/* Use the destination information to determine what local interface this message will go out on */
 	pjsip_tpmgr_fla2_param_default(&prm);
@@ -153,6 +214,13 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
 			ast_debug(4, "Re-wrote Contact URI host/port to %.*s:%d\n",
 				(int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port);
 
+			if (tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP ||
+				tdata->tp_info.transport->key.type == PJSIP_TRANSPORT_UDP6) {
+				uri->transport_param.slen = 0;
+			} else {
+				pj_strdup2(tdata->pool, &uri->transport_param, pjsip_transport_get_type_name(tdata->tp_info.transport->key.type));
+			}
+
 			pjsip_tx_data_invalidate_msg(tdata);
 		}
 	}
@@ -164,17 +232,38 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
 		pjsip_tx_data_invalidate_msg(tdata);
 	}
 
+	if (tdata->msg->type == PJSIP_REQUEST_MSG && (from = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_FROM, NULL)) &&
+		(restrictions && !restrictions->disallow_from_domain_modification)) {
+		pjsip_name_addr *id_name_addr = (pjsip_name_addr *)from->uri;
+		pjsip_sip_uri *uri = pjsip_uri_get_uri(id_name_addr);
+		pj_sockaddr ip;
+
+		if (pj_strcmp2(&uri->host, "localhost") && pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &uri->host, &ip) == PJ_SUCCESS) {
+			pj_strassign(&uri->host, &prm.ret_addr);
+			pjsip_tx_data_invalidate_msg(tdata);
+		}
+	}
+
 	/* Update the SDP if it is present */
 	if (tdata->msg->body && ast_sip_is_content_type(&tdata->msg->body->content_type, "application", "sdp") &&
 		multihomed_rewrite_sdp(tdata->msg->body->data)) {
 		struct pjmedia_sdp_session *sdp = tdata->msg->body->data;
+		static const pj_str_t STR_IP4 = { "IP4", 3 };
+		static const pj_str_t STR_IP6 = { "IP6", 3 };
+		pj_str_t STR_IP;
 		int stream;
 
+		STR_IP = tdata->tp_info.transport->key.type & PJSIP_TRANSPORT_IPV6 ? STR_IP6 : STR_IP4;
+
+		pj_strassign(&sdp->origin.addr, &prm.ret_addr);
+		sdp->origin.addr_type = STR_IP;
 		pj_strassign(&sdp->conn->addr, &prm.ret_addr);
+		sdp->conn->addr_type = STR_IP;
 
 		for (stream = 0; stream < sdp->media_count; ++stream) {
 			if (sdp->media[stream]->conn) {
 				pj_strassign(&sdp->media[stream]->conn->addr, &prm.ret_addr);
+				sdp->media[stream]->conn->addr_type = STR_IP;
 			}
 		}
 
@@ -184,42 +273,31 @@ static pj_status_t multihomed_on_tx_message(pjsip_tx_data *tdata)
 	return PJ_SUCCESS;
 }
 
-static pjsip_module multihomed_module = {
-	.name = { "Multihomed Routing", 18 },
-	.id = -1,
-	.priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 1,
-	.on_tx_request = multihomed_on_tx_message,
-	.on_tx_response = multihomed_on_tx_message,
-};
-
-static int unload_module(void)
+void ast_res_pjsip_cleanup_message_ip_updater(void)
 {
 	ast_sip_unregister_service(&multihomed_module);
-	return 0;
+	ast_sip_unregister_supplement(&multihomed_supplement);
+	ast_sip_session_unregister_supplement(&multihomed_session_supplement);
 }
 
-static int load_module(void)
+int ast_res_pjsip_init_message_ip_updater(void)
 {
-	char hostname[MAXHOSTNAMELEN] = "";
-
-	CHECK_PJSIP_MODULE_LOADED();
+	if (ast_sip_session_register_supplement(&multihomed_session_supplement)) {
+		ast_log(LOG_ERROR, "Could not register multihomed session supplement for outgoing requests\n");
+		return -1;
+	}
 
-	if (!gethostname(hostname, sizeof(hostname) - 1)) {
-		ast_verb(2, "Performing DNS resolution of local hostname '%s' to get local IPv4 and IPv6 address\n",
-			hostname);
+	if (ast_sip_register_supplement(&multihomed_supplement)) {
+		ast_log(LOG_ERROR, "Could not register multihomed supplement for outgoing requests\n");
+		ast_res_pjsip_cleanup_message_ip_updater();
+		return -1;
 	}
 
 	if (ast_sip_register_service(&multihomed_module)) {
 		ast_log(LOG_ERROR, "Could not register multihomed module for incoming and outgoing requests\n");
-		return AST_MODULE_LOAD_FAILURE;
+		ast_res_pjsip_cleanup_message_ip_updater();
+		return -1;
 	}
 
-	return AST_MODULE_LOAD_SUCCESS;
+	return 0;
 }
-
-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Multihomed Routing Support",
-	.support_level = AST_MODULE_SUPPORT_CORE,
-	.load = load_module,
-	.unload = unload_module,
-	.load_pri = AST_MODPRI_APP_DEPEND,
-);
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index 68d5fdb56389211bcd1cc4d6b8e8a37087a4d882..a69aa1a74383a8ae713cb3b53c13a9c1884a151e 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -59,11 +59,8 @@ ASTERISK_REGISTER_FILE()
 /*! \brief Scheduler for RTCP purposes */
 static struct ast_sched_context *sched;
 
-/*! \brief Address for IPv4 RTP */
-static struct ast_sockaddr address_ipv4;
-
-/*! \brief Address for IPv6 RTP */
-static struct ast_sockaddr address_ipv6;
+/*! \brief Address for RTP */
+static struct ast_sockaddr address_rtp;
 
 static const char STR_AUDIO[] = "audio";
 static const int FD_AUDIO = 0;
@@ -173,11 +170,11 @@ static int rtp_check_timeout(const void *data)
 }
 
 /*! \brief Internal function which creates an RTP instance */
-static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media, unsigned int ipv6)
+static int create_rtp(struct ast_sip_session *session, struct ast_sip_session_media *session_media)
 {
 	struct ast_rtp_engine_ice *ice;
 	struct ast_sockaddr temp_media_address;
-	struct ast_sockaddr *media_address =  ipv6 ? &address_ipv6 : &address_ipv4;
+	struct ast_sockaddr *media_address =  &address_rtp;
 
 	if (session->endpoint->media.bind_rtp_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) {
 		ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0);
@@ -903,7 +900,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session, struct
 	}
 
 	/* Using the connection information create an appropriate RTP instance */
-	if (!session_media->rtp && create_rtp(session, session_media, ast_sockaddr_is_ipv6(addrs))) {
+	if (!session_media->rtp && create_rtp(session, session_media)) {
 		return -1;
 	}
 
@@ -1055,7 +1052,6 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
 	pj_pool_t *pool = session->inv_session->pool_prov;
 	static const pj_str_t STR_IN = { "IN", 2 };
 	static const pj_str_t STR_IP4 = { "IP4", 3};
-	static const pj_str_t STR_IP6 = { "IP6", 3};
 	static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
 	static const pj_str_t STR_SENDONLY = { "sendonly", 8 };
 	pjmedia_sdp_media *media;
@@ -1079,7 +1075,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
 	    (!use_override_prefs && !ast_format_cap_has_type(session->endpoint->media.codecs, media_type))) {
 		/* If no type formats are configured don't add a stream */
 		return 0;
-	} else if (!session_media->rtp && create_rtp(session, session_media, session->endpoint->media.rtp.ipv6)) {
+	} else if (!session_media->rtp && create_rtp(session, session_media)) {
 		return -1;
 	}
 
@@ -1120,7 +1116,8 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
 	}
 
 	media->conn->net_type = STR_IN;
-	media->conn->addr_type = session->endpoint->media.rtp.ipv6 ? STR_IP6 : STR_IP4;
+	/* Connection information will be updated by the multihomed module */
+	media->conn->addr_type = STR_IP4;
 	pj_strdup2(pool, &media->conn->addr, hostip);
 	ast_rtp_instance_get_local_address(session_media->rtp, &addr);
 	media->desc.port = direct_media_enabled ? ast_sockaddr_port(&session_media->direct_media_addr) : (pj_uint16_t) ast_sockaddr_port(&addr);
@@ -1257,7 +1254,7 @@ static int apply_negotiated_sdp_stream(struct ast_sip_session *session, struct a
 	}
 
 	/* Create an RTP instance if need be */
-	if (!session_media->rtp && create_rtp(session, session_media, session->endpoint->media.rtp.ipv6)) {
+	if (!session_media->rtp && create_rtp(session, session_media)) {
 		return -1;
 	}
 
@@ -1493,8 +1490,7 @@ static int load_module(void)
 {
 	CHECK_PJSIP_SESSION_MODULE_LOADED();
 
-	ast_sockaddr_parse(&address_ipv4, "0.0.0.0", 0);
-	ast_sockaddr_parse(&address_ipv6, "::", 0);
+	ast_sockaddr_parse(&address_rtp, "::", 0);
 
 	if (!(sched = ast_sched_context_create())) {
 		ast_log(LOG_ERROR, "Unable to create scheduler context.\n");
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 150336a085d2a6025e0843eff9e2e2d9c4cb82c6..b052cc428cbdf9ea8e3c89e000e5db1d2bb1ed15 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -51,11 +51,8 @@ ASTERISK_REGISTER_FILE()
 /*! \brief The number of seconds after receiving a T.38 re-invite before automatically rejecting it */
 #define T38_AUTOMATIC_REJECTION_SECONDS 5
 
-/*! \brief Address for IPv4 UDPTL */
-static struct ast_sockaddr address_ipv4;
-
-/*! \brief Address for IPv6 UDPTL */
-static struct ast_sockaddr address_ipv6;
+/*! \brief Address for UDPTL */
+static struct ast_sockaddr address;
 
 /*! \brief T.38 state information */
 struct t38_state {
@@ -259,8 +256,7 @@ static int t38_initialize_session(struct ast_sip_session *session, struct ast_si
 		return 0;
 	}
 
-	if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0,
-		session->endpoint->media.t38.ipv6 ? &address_ipv6 : &address_ipv4))) {
+	if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, &address))) {
 		return -1;
 	}
 
@@ -922,8 +918,7 @@ static int load_module(void)
 {
 	CHECK_PJSIP_SESSION_MODULE_LOADED();
 
-	ast_sockaddr_parse(&address_ipv4, "0.0.0.0", 0);
-	ast_sockaddr_parse(&address_ipv6, "::", 0);
+	ast_sockaddr_parse(&address, "::", 0);
 
 	if (ast_sip_session_register_supplement(&t38_supplement)) {
 		ast_log(LOG_ERROR, "Unable to register T.38 session supplement\n");
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 4bf625260f2daac90bbbc010de4979302a020fcd..cdf0c560d0a9cbb216ceb3c9254cf0a7cd0fbc9b 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -4971,6 +4971,15 @@ static int ast_rtp_fd(struct ast_rtp_instance *instance, int rtcp)
 static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct ast_sockaddr *addr)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	struct ast_sockaddr local, us;
+
+	if (!ast_sockaddr_isnull(addr)) {
+		/* Update the local RTP address with what is being used */
+		ast_ouraddrfor(addr, &us);
+		ast_rtp_instance_get_local_address(instance, &local);
+		ast_sockaddr_set_port(&us, ast_sockaddr_port(&local));
+		ast_rtp_instance_set_local_address(instance, &us);
+	}
 
 	if (rtp->rtcp) {
 		ast_debug(1, "Setting RTCP address on RTP instance '%p'\n", instance);
@@ -4979,6 +4988,15 @@ static void ast_rtp_remote_address_set(struct ast_rtp_instance *instance, struct
 			ast_sockaddr_set_port(&rtp->rtcp->them,
 					      ast_sockaddr_port(addr) + 1);
 		}
+
+		if (!ast_sockaddr_isnull(addr)) {
+			/* Update the local RTCP address with what is being used */
+			ast_sockaddr_set_port(&us, ast_sockaddr_port(&local) + 1);
+			ast_sockaddr_copy(&rtp->rtcp->us, &us);
+
+			ast_free(rtp->rtcp->local_addr_str);
+			rtp->rtcp->local_addr_str = ast_strdup(ast_sockaddr_stringify(&us));
+		}
 	}
 
 	rtp->rxseqno = 0;