diff --git a/apps/app_dial.c b/apps/app_dial.c
index b0a21fb8584bfc8e7f99409bebe6b64998519767..3a963f9f3e74f6116c163c9c2c5b1e5ebfc6fe1b 100755
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -122,12 +122,14 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
 
 #define AST_MAX_WATCHERS 256
 
-static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, int *sentringing)
+static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, int *sentringing, char *status)
 {
 	struct localuser *o;
 	int found;
 	int numlines;
-	int numbusies = 0;
+	int numbusy = 0;
+	int numcongestion = 0;
+	int numnochan = 0;
 	int orig = *to;
 	struct ast_frame *f;
 	struct ast_channel *peer = NULL;
@@ -162,9 +164,15 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
 			numlines++;
 		}
 		if (found < 0) {
-			if (numlines == numbusies) {
+			if (numlines == (numbusy + numcongestion + numnochan)) {
 				if (option_verbose > 2)
-					ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
+					ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
+				if (numbusy)
+					strcpy(status, "BUSY");
+				else if (numcongestion)
+					strcpy(status, "CONGESTION");
+				else if (numnochan)
+					strcpy(status, "CHANUNAVAIL");
 				/* See if there is a special busy message */
 				if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) 
 					in->priority+=100;
@@ -211,7 +219,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
 					if (!o->chan) {
 						ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
 						o->stillgoing = 0;
-						numbusies++;
+						numnochan++;
 					} else {
 						if (o->chan->callerid)
 							free(o->chan->callerid);
@@ -255,7 +263,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
 							o->stillgoing = 0;
 							ast_hangup(o->chan);
 							o->chan = NULL;
-							numbusies++;
+							numnochan++;
 						}
 					}
 					continue;
@@ -284,7 +292,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
 							o->stillgoing = 0;
 							if (in->cdr)
 								ast_cdr_busy(in->cdr);
-							numbusies++;
+							numbusy++;
 							break;
 						case AST_CONTROL_CONGESTION:
 							if (option_verbose > 2)
@@ -295,7 +303,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
 							o->stillgoing = 0;
 							if (in->cdr)
 								ast_cdr_busy(in->cdr);
-							numbusies++;
+							numcongestion++;
 							break;
 						case AST_CONTROL_RINGING:
 							if (option_verbose > 2)
@@ -418,6 +426,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
 	char *sdtmfptr;
 	char sdtmfdata[256] = "";
 	char *stack,*var;
+	char status[256];
 	int play_to_caller=0,play_to_callee=0;
 	int playargs=0, sentringing=0, moh=0;
 	int digit = 0;
@@ -816,6 +825,8 @@ static int dial_exec(struct ast_channel *chan, void *data)
 		to = -1;
 
 	if (outgoing) {
+		/* Our status will at least be NOANSWER */
+		strcpy(status, "NOANSWER");
 		if (outgoing->musiconhold) {
 			moh=1;
 			ast_moh_start(chan, NULL);
@@ -823,9 +834,10 @@ static int dial_exec(struct ast_channel *chan, void *data)
 			ast_indicate(chan, AST_CONTROL_RINGING);
 			sentringing++;
 		}
-	}
+	} else
+		strcpy(status, "CHANUNAVAIL");
 
-	peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &sentringing);
+	peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &sentringing, status);
 
 	if (!peer) {
 		if (to) 
@@ -838,6 +850,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
 		goto out;
 	}
 	if (peer) {
+		strcpy(status, "ANSWER");
 		/* Ah ha!  Someone answered within the desired timeframe.  Of course after this
 		   we will always return with -1 so that it is hung up properly after the 
 		   conversation.  */
@@ -929,6 +942,8 @@ out:
 		ast_indicate(chan, -1);
 	}
 	hanguptree(outgoing, NULL);
+	pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
+	
 	LOCAL_USER_REMOVE(u);
 	
 	if((go_on>0) && (!chan->_softhangup))
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 4682617ea3693e1e1fd422892abadd267a9b6cd7..0125adee476d3fea4f1e76aeb5d1925f001e6b50 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -1448,6 +1448,14 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
 	ast_mutex_lock(&p->lock);
 	strncpy(dest, rdest, sizeof(dest) - 1);
 	strncpy(p->dialdest, rdest, sizeof(dest) - 1);
+	if ((ast->_state == AST_STATE_BUSY)) {
+		struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_BUSY };
+		/* If this is a placeholder frame for a busy channel,
+		   return busy state immediately */
+		zap_queue_frame(p, &f);
+		ast_mutex_unlock(&p->lock);
+		return 0;
+	}
 	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 		ast_log(LOG_WARNING, "zt_call called on %s, neither down nor reserved\n", ast->name);
 		ast_mutex_unlock(&p->lock);
@@ -6136,7 +6144,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p
 	return tmp;
 }
 
-static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch)
+static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch, int *busy)
 {
 	int res;
 	ZT_PARAMS par;
@@ -6146,6 +6154,11 @@ static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch)
 	/* Check to see if we have a channel match */
 	if ((channelmatch > 0) && (p->channel != channelmatch))
 		return 0;
+	/* We're at least busy at this point */
+	if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) {
+		if (busy)
+			*busy = 1;
+	}
 	/* If do not distrub, definitely not */
 	if (p->dnd)
 		return 0;
@@ -6293,6 +6306,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data)
 	int channelmatch = -1;
 	int roundrobin = 0;
 	int callwait = 0;
+	int busy = 0;
 	struct zt_pvt *p;
 	struct ast_channel *tmp = NULL;
 	char *dest=NULL;
@@ -6405,7 +6419,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data)
 #if 0 
 		ast_verbose("name = %s, %d\n",p->owner->name,p->channel);
 #endif
-		if (p && available(p, channelmatch, groupmatch)) {
+		if (p && available(p, channelmatch, groupmatch, &busy)) {
 			if (option_debug)
 				ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
 				if (p->inalarm)
@@ -6483,6 +6497,19 @@ next:
 	}
 	ast_mutex_unlock(lock);
 	restart_monitor();
+	if (!tmp) {
+		if (busy) {
+			tmp = zt_request("Zap", format, "pseudo");
+			if (tmp) {
+				char newname[80];
+				ast_mutex_lock(&tmp->lock);
+				snprintf(newname, sizeof(newname), "Zap/%s-busy-%d", (char *)data, rand());
+				ast_change_name(tmp, newname);
+				ast_setstate(tmp, AST_STATE_BUSY);
+				ast_mutex_unlock(&tmp->lock);
+			}
+		}
+	}
 	return tmp;
 }
 
diff --git a/configs/extensions.conf.sample b/configs/extensions.conf.sample
index b500f0252edcd3c8283daa64c9adadaa479e06fb..3fcf312629d20e884c7e42c044dc6b0932928f5e 100755
--- a/configs/extensions.conf.sample
+++ b/configs/extensions.conf.sample
@@ -181,10 +181,16 @@ include => iaxprovider
 ;   ${ARG2} - Device(s) to ring
 ;
 exten => s,1,Dial(${ARG2},20)					; Ring the interface, 20 seconds maximum
-exten => s,2,Voicemail(u${ARG1})				; If unavailable, send to voicemail w/ unavail announce
-exten => s,3,Goto(default,s,1)					; If they press #, return to start
-exten => s,102,Voicemail(b${ARG1})				; If busy, send to voicemail w/ busy announce
-exten => s,103,Goto(default,s,1)				; If they press #, return to start
+exten => s,2,Goto(s-${DIALSTATUS})				; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER)
+
+exten => s-NOANSWER,1,Voicemail(u${ARG1})		; If unavailable, send to voicemail w/ unavail announce
+exten => s-NOANSWER,2,Goto(default,s,1)			; If they press #, return to start
+
+exten => s-BUSY,1,Voicemail(b${ARG1})			; If busy, send to voicemail w/ busy announce
+exten => s-BUSY,2,Goto(default,s,1)				; If they press #, return to start
+
+exten => s-.,1,Goto(s-NOANSWER,1)				; Treat anything else as no answer
+
 exten => a,1,VoicemailMain(${ARG1})				; If they press *, send the user into VoicemailMain
 
 [demo]