diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index fed032a3d7494a8eef5b1fe14f217bddc1d3c130..ce9ef7aa2773f1e3d2a09d53c7e8d1312cb90cb0 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -3835,6 +3835,10 @@ void ast_channel_macroexten_set(struct ast_channel *chan, const char *value);
 
 char ast_channel_dtmf_digit_to_emulate(const struct ast_channel *chan);
 void ast_channel_dtmf_digit_to_emulate_set(struct ast_channel *chan, char value);
+char ast_channel_sending_dtmf_digit(const struct ast_channel *chan);
+void ast_channel_sending_dtmf_digit_set(struct ast_channel *chan, char value);
+struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan);
+void ast_channel_sending_dtmf_tv_set(struct ast_channel *chan, struct timeval value);
 int ast_channel_amaflags(const struct ast_channel *chan);
 void ast_channel_amaflags_set(struct ast_channel *chan, int value);
 int ast_channel_epfd(const struct ast_channel *chan);
diff --git a/include/asterisk/features.h b/include/asterisk/features.h
index 1619d54c4546e17231240146ea64d0012334f4ed..4f556138138bc8aade90d189a9d5473b6c50adee 100644
--- a/include/asterisk/features.h
+++ b/include/asterisk/features.h
@@ -169,6 +169,18 @@ int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const
 /*! \brief Determine system call pickup extension */
 const char *ast_pickup_ext(void);
 
+/*!
+ * \brief Simulate a DTMF end on a broken bridge channel.
+ *
+ * \param chan Channel sending DTMF that has not ended.
+ * \param digit DTMF digit to stop.
+ * \param start DTMF digit start time.
+ * \param why Reason bridge broken.
+ *
+ * \return Nothing
+ */
+void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why);
+
 /*! \brief Bridge a call, optionally allowing redirection */
 int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config);
 
diff --git a/main/channel.c b/main/channel.c
index b0622fa9c4c6d2ed427d606fe29c41a4186f8a2c..126e44cf639c93738aec441636743e0e5d7f4f04 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -72,6 +72,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/global_datastores.h"
 #include "asterisk/data.h"
 #include "asterisk/channel_internal.h"
+#include "asterisk/features.h"
 
 /*** DOCUMENTATION
  ***/
@@ -4778,6 +4779,11 @@ int ast_senddigit_begin(struct ast_channel *chan, char digit)
 	if (!ast_channel_tech(chan)->send_digit_begin)
 		return 0;
 
+	ast_channel_lock(chan);
+	ast_channel_sending_dtmf_digit_set(chan, digit);
+	ast_channel_sending_dtmf_tv_set(chan, ast_tvnow());
+	ast_channel_unlock(chan);
+
 	if (!ast_channel_tech(chan)->send_digit_begin(chan, digit))
 		return 0;
 
@@ -4804,6 +4810,12 @@ int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duratio
 	if (ast_channel_tech(chan)->send_digit_end)
 		res = ast_channel_tech(chan)->send_digit_end(chan, digit, duration);
 
+	ast_channel_lock(chan);
+	if (ast_channel_sending_dtmf_digit(chan) == digit) {
+		ast_channel_sending_dtmf_digit_set(chan, 0);
+	}
+	ast_channel_unlock(chan);
+
 	if (res && ast_channel_generator(chan))
 		ast_playtones_stop(chan);
 
@@ -6835,6 +6847,8 @@ int ast_do_masquerade(struct ast_channel *original)
 	char orig[AST_CHANNEL_NAME];
 	char masqn[AST_CHANNEL_NAME];
 	char zombn[AST_CHANNEL_NAME];
+	char clone_sending_dtmf_digit;
+	struct timeval clone_sending_dtmf_tv;
 
 	/* XXX This operation is a bit odd.  We're essentially putting the guts of
 	 * the clone channel into the original channel.  Start by killing off the
@@ -6963,6 +6977,10 @@ int ast_do_masquerade(struct ast_channel *original)
 	free_translation(clonechan);
 	free_translation(original);
 
+	/* Save the current DTMF digit being sent if any. */
+	clone_sending_dtmf_digit = ast_channel_sending_dtmf_digit(clonechan);
+	clone_sending_dtmf_tv = ast_channel_sending_dtmf_tv(clonechan);
+
 	/* Save the original name */
 	ast_copy_string(orig, ast_channel_name(original), sizeof(orig));
 	/* Save the new name */
@@ -7207,6 +7225,15 @@ int ast_do_masquerade(struct ast_channel *original)
 	ast_channel_unlock(original);
 	ast_channel_unlock(clonechan);
 
+	if (clone_sending_dtmf_digit) {
+		/*
+		 * The clonechan was sending a DTMF digit that was not completed
+		 * before the masquerade.
+		 */
+		ast_bridge_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv,
+			"masquerade");
+	}
+
 	/*
 	 * If an indication is currently playing, maintain it on the
 	 * channel that is taking the place of original.
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index e3543d8ec26fdbc6c92ecbd9ae1e5b758bb743bc..c7ed84c349ba0fca84b69e96242e626a824acb16 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -193,6 +193,8 @@ struct ast_channel {
 	char macrocontext[AST_MAX_CONTEXT];		/*!< Macro: Current non-macro context. See app_macro.c */
 	char macroexten[AST_MAX_EXTENSION];		/*!< Macro: Current non-macro extension. See app_macro.c */
 	char dtmf_digit_to_emulate;			/*!< Digit being emulated */
+	char sending_dtmf_digit;			/*!< Digit this channel is currently sending out. (zero if not sending) */
+	struct timeval sending_dtmf_tv;		/*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
 };
 
 /* AST_DATA definitions, which will probably have to be re-thought since the channel will be opaque */
@@ -523,6 +525,25 @@ void ast_channel_dtmf_digit_to_emulate_set(struct ast_channel *chan, char value)
 {
 	chan->dtmf_digit_to_emulate = value;
 }
+
+char ast_channel_sending_dtmf_digit(const struct ast_channel *chan)
+{
+	return chan->sending_dtmf_digit;
+}
+void ast_channel_sending_dtmf_digit_set(struct ast_channel *chan, char value)
+{
+	chan->sending_dtmf_digit = value;
+}
+
+struct timeval ast_channel_sending_dtmf_tv(const struct ast_channel *chan)
+{
+	return chan->sending_dtmf_tv;
+}
+void ast_channel_sending_dtmf_tv_set(struct ast_channel *chan, struct timeval value)
+{
+	chan->sending_dtmf_tv = value;
+}
+
 int ast_channel_amaflags(const struct ast_channel *chan)
 {
 	return chan->amaflags;
diff --git a/main/features.c b/main/features.c
index e9f84eae1f761b08050beaebdb268795acf6a53c..847b29ee6116fec6962009bc91f14d044bf82335 100644
--- a/main/features.c
+++ b/main/features.c
@@ -4249,6 +4249,24 @@ static void clear_dialed_interfaces(struct ast_channel *chan)
 	ast_channel_unlock(chan);
 }
 
+void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
+{
+	int dead;
+	long duration;
+
+	ast_channel_lock(chan);
+	dead = ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE) || ast_check_hangup(chan);
+	ast_channel_unlock(chan);
+	if (dead) {
+		return;
+	}
+
+	duration = ast_tvdiff_ms(ast_tvnow(), start);
+	ast_senddigit_end(chan, digit, duration);
+	ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
+		digit, ast_channel_name(chan), why, duration);
+}
+
 /*!
  * \brief bridge the call and set CDR
  *
@@ -4698,6 +4716,15 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a
 	ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, peer);
 
 before_you_go:
+	if (ast_channel_sending_dtmf_digit(chan)) {
+		ast_bridge_end_dtmf(chan, ast_channel_sending_dtmf_digit(chan),
+			ast_channel_sending_dtmf_tv(chan), "bridge end");
+	}
+	if (ast_channel_sending_dtmf_digit(peer)) {
+		ast_bridge_end_dtmf(peer, ast_channel_sending_dtmf_digit(peer),
+			ast_channel_sending_dtmf_tv(peer), "bridge end");
+	}
+
 	/* Just in case something weird happened and we didn't clean up the silence generator... */
 	if (silgen) {
 		ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);