diff --git a/CHANGES b/CHANGES
index 443f1acb02092c8c2165e39065846ce16341bb41..10c179fba9d65d28c943f9f23ac05dd105af0837 100644
--- a/CHANGES
+++ b/CHANGES
@@ -73,6 +73,11 @@ Chan_local changes
  * Added a manager event "LocalBridge" for local channel call bridges between
    the two pseudo-channels created.
 
+Chan_dahdi changes
+------------------
+ * Added dialtone_detect option for analog ports to disconnect incoming
+   calls when dialtone is detected.
+
 Codec changes
 -------------
  * Codec lists may now be modified by the '!' character, to allow succinct
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 21214bd88b6e1bdb2399409efc62bf24dbd9618c..d65bb122ef257613575f95bd9cf211b25a7d8945 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -532,6 +532,7 @@ static inline int dahdi_wait_event(int fd)
 #define CIDCW_EXPIRE_SAMPLES			((500 * 8) / READ_SIZE) /*!< 500 ms */
 #define MIN_MS_SINCE_FLASH				((2000) )	/*!< 2000 ms */
 #define DEFAULT_RINGT 					((8000 * 8) / READ_SIZE) /*!< 8,000 ms */
+#define DEFAULT_DIALTONE_DETECT_TIMEOUT ((10000 * 8) / READ_SIZE) /*!< 10,000 ms */
 
 struct dahdi_pvt;
 
@@ -1167,6 +1168,12 @@ struct dahdi_pvt {
 	 * \note Set from the "waitfordialtone" value read in from chan_dahdi.conf
 	 */
 	int waitfordialtone;
+	/*!
+	 * \brief Number of frames to watch for dialtone in incoming calls
+	 * \note Set from the "dialtone_detect" value read in from chan_dahdi.conf
+	 */
+	int dialtone_detect;
+	int dialtone_scanning_time_elapsed;	/*!< Amount of audio scanned for dialtone, in frames */
 	struct timeval waitingfordt;			/*!< Time we started waiting for dialtone */
 	struct timeval flashtime;			/*!< Last flash-hook time */
 	/*! \brief Opaque DSP configuration structure. */
@@ -9250,7 +9257,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
 		p->subs[idx].f.data.ptr = NULL;
 		p->subs[idx].f.datalen= 0;
 	}
-	if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec) && !idx) {
+	if (p->dsp && (!p->ignoredtmf || p->callwaitcas || p->busydetect || p->callprogress || p->waitingfordt.tv_sec || p->dialtone_detect) && !idx) {
 		/* Perform busy detection etc on the dahdi line */
 		int mute;
 
@@ -9264,10 +9271,24 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
 		}
 
 		if (f) {
+			if ((p->dsp_features & DSP_FEATURE_WAITDIALTONE) && (p->dialtone_detect > 0)
+				&& !p->outgoing && ast_channel_state(ast) == AST_STATE_UP) {
+				if (++p->dialtone_scanning_time_elapsed >= p->dialtone_detect) {
+					p->dsp_features &= ~DSP_FEATURE_WAITDIALTONE;
+					ast_dsp_set_features(p->dsp, p->dsp_features);
+				}
+			}
 			if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_BUSY)) {
 				if ((ast_channel_state(ast) == AST_STATE_UP) && !p->outgoing) {
-					/* Treat this as a "hangup" instead of a "busy" on the assumption that
-					   a busy */
+					/*
+					 * Treat this as a "hangup" instead of a "busy" on the
+					 * assumption that a busy means the incoming call went away.
+					 */
+					f = NULL;
+				}
+			} else if (p->dialtone_detect && !p->outgoing && f->frametype == AST_FRAME_VOICE) {
+				if ((ast_dsp_get_tstate(p->dsp) == DSP_TONE_STATE_DIALTONE) && (ast_dsp_get_tcount(p->dsp) > 9)) {
+					/* Dialtone detected on inbound call; hangup the channel */
 					f = NULL;
 				}
 			} else if (f->frametype == AST_FRAME_DTMF_BEGIN
@@ -9691,7 +9712,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
 			features |= DSP_FEATURE_BUSY_DETECT;
 		if ((i->callprogress & CALLPROGRESS_PROGRESS) && CANPROGRESSDETECT(i))
 			features |= DSP_FEATURE_CALL_PROGRESS;
-		if ((i->waitfordialtone) && CANPROGRESSDETECT(i))
+		if ((i->waitfordialtone || i->dialtone_detect) && CANPROGRESSDETECT(i))
 			features |= DSP_FEATURE_WAITDIALTONE;
 		if ((!i->outgoing && (i->callprogress & CALLPROGRESS_FAX_INCOMING)) ||
 			(i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
@@ -9737,6 +9758,8 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
 		}
 	}
 
+	i->dialtone_scanning_time_elapsed = 0;
+
 	if (state == AST_STATE_RING)
 		ast_channel_rings_set(tmp, 1);
 	ast_channel_tech_pvt_set(tmp, i);
@@ -12873,6 +12896,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
 		tmp->busy_cadence = conf->chan.busy_cadence;
 		tmp->callprogress = conf->chan.callprogress;
 		tmp->waitfordialtone = conf->chan.waitfordialtone;
+		tmp->dialtone_detect = conf->chan.dialtone_detect;
 		tmp->cancallforward = conf->chan.cancallforward;
 		tmp->dtmfrelax = conf->chan.dtmfrelax;
 		tmp->callwaiting = tmp->permcallwaiting;
@@ -17281,6 +17305,16 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
 				confp->chan.callprogress |= CALLPROGRESS_PROGRESS;
 		} else if (!strcasecmp(v->name, "waitfordialtone")) {
 			confp->chan.waitfordialtone = atoi(v->value);
+		} else if (!strcasecmp(v->name, "dialtone_detect")) {
+			if (!strcasecmp(v->value, "always")) {
+				confp->chan.dialtone_detect = -1;
+			} else if (ast_true(v->value)) {
+				confp->chan.dialtone_detect = DEFAULT_DIALTONE_DETECT_TIMEOUT;
+			} else if (ast_false(v->value)) {
+				confp->chan.dialtone_detect = 0;
+			} else {
+				confp->chan.dialtone_detect = ast_strlen_zero(v->value) ? 0 : (8 * atoi(v->value)) / READ_SIZE;
+			}
 		} else if (!strcasecmp(v->name, "faxdetect")) {
 			confp->chan.callprogress &= ~CALLPROGRESS_FAX;
 			if (!strcasecmp(v->value, "incoming")) {
diff --git a/configs/chan_dahdi.conf.sample b/configs/chan_dahdi.conf.sample
index 10c55ca7564aa17a82c887b23bc58131be44ae1e..d83bba8d9b38a88166051c0f0a1f987af3c82297 100644
--- a/configs/chan_dahdi.conf.sample
+++ b/configs/chan_dahdi.conf.sample
@@ -551,6 +551,17 @@ usecallerid=yes
 ; marking the line as once again available for use with outgoing calls.
 ;waitfordialtone=yes
 ;
+; For analog lines, enables Asterisk to use dialtone detection per channel
+; if an incoming call was hung up before it was answered.  If dialtone is
+; detected, the call is hung up.
+; no:       Disabled. (Default)
+; yes:      Look for dialtone for 10000 ms after answer.
+; <number>: Look for dialtone for the specified number of ms after answer.
+; always:   Look for dialtone for the entire call.  Dialtone may return
+;           if the far end hangs up first.
+;
+;dialtone_detect=no
+;
 ; The following option enables receiving MWI on FXO lines.  The default
 ; value is no.
 ; 	The mwimonitor can take the following values