Index: include/asterisk/cdr.h
===================================================================
--- include/asterisk/cdr.h	(revision 212843)
+++ include/asterisk/cdr.h	(working copy)
@@ -38,6 +38,7 @@
 #define AST_CDR_FLAG_DONT_TOUCH     (1 << 9)
 #define AST_CDR_FLAG_DIALED         (1 << 10)
 #define AST_CDR_FLAG_ORIGINATED		(1 << 11)
+#define AST_CDR_FLAG_SPLIT_ON_GOTO	(1 << 12)
 
 /*! Disposition */
 #define AST_CDR_NULL                0
@@ -317,6 +318,14 @@
  */
 void ast_cdr_specialized_reset(struct ast_cdr *cdr, struct ast_flags *flags);
 
+/*! Split a cdr record */
+/*!
+ * \param chan the channel to operate on
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_cdr_split(struct ast_channel* chan);
+
 /*! Flags to a string */
 /*!
  * \param flags binary flag
@@ -347,6 +356,13 @@
 
 extern char ast_default_accountcode[AST_MAX_ACCOUNT_CODE];
 
+/*! Get the last CDR record in the chain. */
+/*!
+ * \param cdr which cdr to act upon
+ * \return the last cdr record in the chain or NULl if cdr is NULL
+ */
+struct ast_cdr *ast_cdr_tail(struct ast_cdr *cdr);
+
 struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr);
 
 /*! Reload the configuration file cdr.conf and start/stop CDR scheduling thread */
Index: main/cdr.c
===================================================================
--- main/cdr.c	(revision 212843)
+++ main/cdr.c	(working copy)
@@ -1126,6 +1126,38 @@
 	cdr->disposition = AST_CDR_NULL;
 }
 
+int ast_cdr_split(struct ast_channel *chan)
+{
+	struct ast_cdr *newcdr, *cdr;
+
+	if (!chan || !chan->cdr)
+		return -1;
+
+	cdr = ast_cdr_tail(chan->cdr);
+
+	if (!(newcdr = ast_cdr_dup(cdr)))
+		return -1;
+
+	ast_cdr_reset(newcdr, NULL);
+	ast_cdr_init(newcdr, chan);
+
+	ast_cdr_end(cdr);
+	ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH | AST_CDR_FLAG_LOCKED);
+	ast_cdr_append(cdr, newcdr);
+	return 0;
+}
+
+struct ast_cdr *ast_cdr_tail(struct ast_cdr *cdr)
+{
+	if (!cdr)
+		return cdr;
+
+	while (cdr->next)
+		cdr = cdr->next;
+
+	return cdr;
+}
+
 struct ast_cdr *ast_cdr_append(struct ast_cdr *cdr, struct ast_cdr *newcdr) 
 {
 	struct ast_cdr *ret;
Index: main/manager.c
===================================================================
--- main/manager.c	(revision 212843)
+++ main/manager.c	(working copy)
@@ -1717,20 +1717,36 @@
 		ast_channel_unlock(chan2);
 		return 0;
 	}
-	if (chan->pbx) {
-		ast_channel_lock(chan);
-		ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
-		ast_channel_unlock(chan);
-	}
+	/* don't let the after-bridge code run the h-exten */
+	if (chan->pbx)
+		ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_DONT);
+
+	/* Mark the cdr record to be split. The reasoning here is as follows:
+	 * because this is an asynchronous redirect, we want to preserve any
+	 * existing CDR records on our channel and create a new one for the
+	 * next leg of the call.
+	 */
+	ast_set_flag(ast_cdr_tail(chan->cdr), AST_CDR_FLAG_SPLIT_ON_GOTO);
+
+	ast_clear_flag(chan, AST_FLAG_OUTGOING);
+
 	res = ast_async_goto(chan, context, exten, pi);
 	if (!res) {
 		if (!ast_strlen_zero(name2)) {
 			if (chan2) {
-				if (chan2->pbx) {
-					ast_channel_lock(chan2);
-					ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
-					ast_channel_unlock(chan2);
-				}
+				/* don't let the after-bridge code run the h-exten */
+				if (chan2->pbx)
+					ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT);
+
+				/* Mark the cdr record to be split. The reasoning here is as follows:
+				 * because this is an asynchronous redirect, we want to preserve any
+				 * existing CDR records on our channel and create a new one for the
+				 * next leg of the call.
+				 */
+				ast_set_flag(ast_cdr_tail(chan2->cdr), AST_CDR_FLAG_SPLIT_ON_GOTO);
+
+				ast_clear_flag(chan2, AST_FLAG_OUTGOING);
+
 				res = ast_async_goto(chan2, context, exten, pi);
 			} else {
 				res = -1;
Index: main/pbx.c
===================================================================
--- main/pbx.c	(revision 212843)
+++ main/pbx.c	(working copy)
@@ -4600,9 +4600,16 @@
 
 int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
 {
-	int res = 0;
+	int res = 0, cdr_split = 0;
 
 	ast_channel_lock(chan);
+	if (chan->cdr && ast_test_flag(ast_cdr_tail(chan->cdr), AST_CDR_FLAG_SPLIT_ON_GOTO)) {
+		if (ast_cdr_split(chan)) {
+			ast_channel_unlock(chan);
+			return -1;
+		}
+		cdr_split = 1;
+	}
 
 	if (chan->pbx) { /* This channel is currently in the PBX */
 		ast_explicit_goto(chan, context, exten, priority);
@@ -4616,8 +4623,12 @@
 			res = -1;
 		} else {
 			if (chan->cdr) {
-				ast_cdr_discard(tmpchan->cdr);
-				tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
+				if (cdr_split) {
+					ast_set_flag(tmpchan->cdr, AST_CDR_FLAG_POST_DISABLED);
+				} else {
+					ast_cdr_discard(tmpchan->cdr);
+					tmpchan->cdr = ast_cdr_dup(chan->cdr);  /* share the love */
+				}
 			}
 			/* Make formats okay */
 			tmpchan->readformat = chan->readformat;
