diff --git a/apps/app_dial.c b/apps/app_dial.c
index 07cbf51ee8d9a671202b977d9e16950561391761..a03dfc0ab03a92aae5dc9ef6e60e28ff3a0be940 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -672,6 +672,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 					if (!peer) {
 						ast_verb(3, "%s answered %s\n", c->name, in->name);
 						peer = c;
+						if (peer->cdr) {
+							peer->cdr->answer = ast_tvnow();
+							peer->cdr->disposition = AST_CDR_ANSWERED;
+						}
 						ast_copy_flags64(peerflags, o,
 							OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
 							OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
diff --git a/include/asterisk/cdr.h b/include/asterisk/cdr.h
index dc14f326e979c9d97a71f0024d2cd2b7cd0fbb21..7ece623791ee63771d6f29c3f4e6a9020f4d5a12 100644
--- a/include/asterisk/cdr.h
+++ b/include/asterisk/cdr.h
@@ -37,7 +37,8 @@
 #define AST_CDR_FLAG_ENABLE			(1 << 7)
 #define AST_CDR_FLAG_ANSLOCKED      (1 << 8)
 #define AST_CDR_FLAG_DONT_TOUCH     (1 << 9)
-#define AST_CDR_FLAG_POST_ENABLE                (1 << 5)
+#define AST_CDR_FLAG_POST_ENABLE    (1 << 10)
+#define AST_CDR_FLAG_DIALED         (1 << 11)
 /*@} */
 
 /*! \name CDR Flags - Disposition */
@@ -111,6 +112,7 @@ struct ast_cdr {
 	struct ast_cdr *next;
 };
 
+int ast_cdr_isset_unanswered(void);
 void ast_cdr_getvar(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int recur, int raw);
 int ast_cdr_setvar(struct ast_cdr *cdr, const char *name, const char *value, int recur);
 int ast_cdr_serialize_variables(struct ast_cdr *cdr, struct ast_str **buf, char delim, char sep, int recur);
diff --git a/main/cdr.c b/main/cdr.c
index f8fc2c634c8db924b7e9437147e300134901e5e4..9402ae674ef4b6473901a455e8bf1aa761d5759c 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -157,6 +157,11 @@ void ast_cdr_unregister(const char *name)
 	AST_RWLIST_UNLOCK(&be_list);
 }
 
+int ast_cdr_isset_unanswered(void)
+{
+	return unanswered;
+}
+
 /*! Duplicate a CDR record 
 	\returns Pointer to new CDR record
 */
diff --git a/main/channel.c b/main/channel.c
index 98a89f0dc0a48d533ce9772e30ba50dc1bac28ca..33bcc055281cad2d849ea3593c902e0caceec485 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1633,7 +1633,10 @@ int ast_hangup(struct ast_channel *chan)
 			ast_cause2str(chan->hangupcause)
 			);
 
-	if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && chan->cdr->disposition != AST_CDR_NULL) {
+	if (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_BRIDGED) && 
+		!ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED) && 
+	    (chan->cdr->disposition != AST_CDR_NULL || ast_test_flag(chan->cdr, AST_CDR_FLAG_DIALED))) {
+			
 		ast_cdr_end(chan->cdr);
 		ast_cdr_detach(chan->cdr);
 	}
@@ -3439,6 +3442,8 @@ int ast_call(struct ast_channel *chan, char *addr, int timeout)
 	/* Stop if we're a zombie or need a soft hangup */
 	ast_channel_lock(chan);
 	if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan)) {
+		if (chan->cdr)
+			ast_set_flag(chan->cdr, AST_CDR_FLAG_DIALED);
 		if (chan->tech->call)
 			res = chan->tech->call(chan, addr, timeout);
 		ast_set_flag(chan, AST_FLAG_OUTGOING);
diff --git a/main/features.c b/main/features.c
index f540c455b2a081acdbf93ae3a888bd8501433689..69bfbe59ed6be8ac1db0accd442de073138552ac 100644
--- a/main/features.c
+++ b/main/features.c
@@ -2140,11 +2140,23 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 				ast_cdr_start(bridge_cdr);
 			}
 		}
-		ast_cdr_answer(bridge_cdr);
-		ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
-		ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
+		ast_log(LOG_NOTICE,"bridge answer set, chan answer set\n");
+		/* peer->cdr->answer will be set when a macro runs on the peer;
+		   in that case, the bridge answer will be delayed while the
+		   macro plays on the peer channel. The peer answered the call
+		   before the macro started playing. To the phone system,
+		   this is billable time for the call, even tho the caller
+		   hears nothing but ringing while the macro does its thing. */
+		if (peer->cdr && !ast_tvzero(peer->cdr->answer)) {
+			bridge_cdr->answer = peer->cdr->answer;
+			chan->cdr->answer = peer->cdr->answer;
+		} else {
+			ast_cdr_answer(bridge_cdr);
+			ast_cdr_answer(chan->cdr); /* for the sake of cli status checks */
+		}
+ 		ast_set_flag(chan->cdr, AST_CDR_FLAG_BRIDGED);
 		if (peer->cdr) {
-			ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
+ 			ast_set_flag(peer->cdr, AST_CDR_FLAG_BRIDGED);
 		}
 	}
 	for (;;) {
@@ -2212,7 +2224,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 		if (res < 0) {
 			if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer))
 				ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name);
-			return -1;
+			goto before_you_go;
 		}
 		
 		if (!f || (f->frametype == AST_FRAME_CONTROL &&
@@ -2308,6 +2320,7 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 			ast_frfree(f);
 
 	}
+   before_you_go:
 	/* obey the NoCDR() wishes. */
 	if (!chan->cdr || (chan->cdr && !ast_test_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED))) {
 		
@@ -2320,14 +2333,24 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 			ast_cdr_specialized_reset(chan->cdr,0);
 		}
 		if (peer->cdr) {
-			if (orig_peer_cdr && peer->cdr != orig_peer_cdr) {
-				/* this can only happen if there was a transfer, methinks */
-				ast_cdr_specialized_reset(orig_peer_cdr,0);
-			} else {
-				ast_cdr_specialized_reset(peer->cdr,0);
+			/* before resetting the peer cdr, throw a copy of it to the 
+			   backend, just in case the cdr.conf file is calling for
+			   unanswered CDR's. */
+			
+			/* When peer->cdr isn't the same addr as orig_peer_cdr,
+			   this can only happen if there was a transfer, methinks;
+			   at any rate, only pay attention to the original*/
+			if (ast_cdr_isset_unanswered()) {
+				struct ast_cdr *dupd = ast_cdr_dup(orig_peer_cdr);
+				if (dupd) {
+					if (ast_tvzero(dupd->end) && ast_cdr_isset_unanswered())
+						ast_cdr_end(dupd);
+					ast_cdr_detach(dupd);
+				}
 			}
+			ast_cdr_specialized_reset(orig_peer_cdr,0);
 		}
-	}
+ 	}
 	return res;
 }