diff -Naur asterisk-18.5.0-original/include/asterisk/res_pjsip.h asterisk-18.5.0/include/asterisk/res_pjsip.h --- asterisk-18.5.0-original/include/asterisk/res_pjsip.h 2021-06-24 06:50:57.000000000 -0600 +++ asterisk-18.5.0/include/asterisk/res_pjsip.h 2021-07-14 07:30:17.911381000 -0600 @@ -758,6 +758,8 @@ unsigned int nat; /*! Whether to use IPv6 for UDPTL or not */ unsigned int ipv6; + /*! Bind the UDPTL instance to the media_address */ + unsigned int bind_udptl_to_media_address; }; /*! diff -Naur asterisk-18.5.0-original/res/res_pjsip/pjsip_configuration.c asterisk-18.5.0/res/res_pjsip/pjsip_configuration.c --- asterisk-18.5.0-original/res/res_pjsip/pjsip_configuration.c 2021-06-24 06:50:57.000000000 -0600 +++ asterisk-18.5.0/res/res_pjsip/pjsip_configuration.c 2021-07-14 07:30:37.697424000 -0600 @@ -2077,6 +2077,7 @@ ast_sorcery_object_field_register(sip_sorcery, "endpoint", "fax_detect_timeout", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_endpoint, faxdetect_timeout)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_nat", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.nat)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_udptl_ipv6", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.ipv6)); + ast_sorcery_object_field_register(sip_sorcery, "endpoint", "t38_bind_udptl_to_media_address", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, media.t38.bind_udptl_to_media_address)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "tone_zone", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, zone)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "language", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, language)); ast_sorcery_object_field_register(sip_sorcery, "endpoint", "record_on_feature", "automixmon", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_endpoint, info.recording.onfeature)); diff -Naur asterisk-18.5.0-original/res/res_pjsip_t38.c asterisk-18.5.0/res/res_pjsip_t38.c --- asterisk-18.5.0-original/res/res_pjsip_t38.c 2021-06-24 06:50:57.000000000 -0600 +++ asterisk-18.5.0/res/res_pjsip_t38.c 2021-07-14 07:30:46.170753000 -0600 @@ -255,11 +255,53 @@ /*! \brief Initializes UDPTL support on a session, only done when actually needed */ static int t38_initialize_session(struct ast_sip_session *session, struct ast_sip_session_media *session_media) { + struct ast_sockaddr temp_media_address; + struct ast_sockaddr *media_address = &address; + if (session_media->udptl) { return 0; } + + if (session->endpoint->media.t38.bind_udptl_to_media_address && !ast_strlen_zero(session->endpoint->media.address)) { + if (ast_sockaddr_parse(&temp_media_address, session->endpoint->media.address, 0)) { + ast_debug(5, "Endpoint %s: Binding UDPTL media to %s\n", + ast_sorcery_object_get_id(session->endpoint), + session->endpoint->media.address); + media_address = &temp_media_address; + } else { + ast_debug(5, "Endpoint %s: UDPTL media address invalid: %s\n", + ast_sorcery_object_get_id(session->endpoint), + session->endpoint->media.address); + } + + } else { + struct ast_sip_transport *transport; + + transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", + session->endpoint->transport); + if (transport) { + struct ast_sip_transport_state *trans_state; + + trans_state = ast_sip_get_transport_state(ast_sorcery_object_get_id(transport)); + if (trans_state) { + char hoststr[PJ_INET6_ADDRSTRLEN]; + + pj_sockaddr_print(&trans_state->host, hoststr, sizeof(hoststr), 0); + if (ast_sockaddr_parse(&temp_media_address, hoststr, 0)) { + ast_debug(5, "Transport %s bound to %s: Using it for UDPTL media.\n", + session->endpoint->transport, hoststr); + media_address = &temp_media_address; + } else { + ast_debug(5, "Transport %s bound to %s: Invalid for UDPTL media.\n", + session->endpoint->transport, hoststr); + } + ao2_ref(trans_state, -1); + } + ao2_ref(transport, -1); + } + } - if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, &address))) { + if (!(session_media->udptl = ast_udptl_new_with_bindaddr(NULL, NULL, 0, media_address))) { return -1; }