diff --git a/cdr.c b/cdr.c
index b433902ba0b038888b3d2a52e178c4480cb76afd..32999fd0eefbb7c874fdb93881d0a4982d557b0d 100755
--- a/cdr.c
+++ b/cdr.c
@@ -189,6 +189,29 @@ void ast_cdr_setapp(struct ast_cdr *cdr, char *app, char *data)
 	}
 }
 
+int ast_cdr_setcid(struct ast_cdr *cdr, struct ast_channel *c)
+{
+	char tmp[AST_MAX_EXTENSION] = "";
+	char *num, *name;
+	if (cdr) {
+		/* Grab source from ANI or normal Caller*ID */
+		if (c->ani)
+			strncpy(tmp, c->ani, sizeof(tmp) - 1);
+		else if (c->callerid)
+			strncpy(tmp, c->callerid, sizeof(tmp) - 1);
+		if (c->callerid)
+			strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
+		name = NULL;
+		num = NULL;
+		ast_callerid_parse(tmp, &name, &num);
+		if (num) {
+			ast_shrink_phone_number(num);
+			strncpy(cdr->src, num, sizeof(cdr->src) - 1);
+		}
+	}
+	return 0;
+}
+
 int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *c)
 {
 	char *chan;
@@ -281,6 +304,35 @@ int ast_cdr_setaccount(struct ast_channel *chan, char *account)
 	return 0;
 }
 
+int ast_cdr_update(struct ast_channel *c)
+{
+	struct ast_cdr *cdr = c->cdr;
+	char *name, *num;
+	char tmp[AST_MAX_EXTENSION] = "";
+	/* Grab source from ANI or normal Caller*ID */
+	if (c->ani)
+		strncpy(tmp, c->ani, sizeof(tmp) - 1);
+	else if (c->callerid)
+		strncpy(tmp, c->callerid, sizeof(tmp) - 1);
+	if (c->callerid)
+		strncpy(cdr->clid, c->callerid, sizeof(cdr->clid) - 1);
+	else
+		strcpy(cdr->clid, "");
+	name = NULL;
+	num = NULL;
+	ast_callerid_parse(tmp, &name, &num);
+	if (num) {
+		ast_shrink_phone_number(num);
+		strncpy(cdr->src, num, sizeof(cdr->src) - 1);
+	}
+	/* Copy account code et-al */	
+	strncpy(cdr->accountcode, c->accountcode, sizeof(cdr->accountcode) - 1);
+	/* Destination information */
+	strncpy(cdr->dst, c->exten, sizeof(cdr->dst) - 1);
+	strncpy(cdr->dcontext, c->context, sizeof(cdr->dcontext) - 1);
+	return 0;
+}
+
 int ast_cdr_amaflags2int(char *flag)
 {
 	if (!strcasecmp(flag, "default"))
@@ -321,3 +373,21 @@ void ast_cdr_post(struct ast_cdr *cdr)
 		ast_pthread_mutex_unlock(&cdrlock);
 	}
 }
+
+void ast_cdr_reset(struct ast_cdr *cdr, int post)
+{
+	/* Post if requested */
+	if (post) {
+		ast_cdr_end(cdr);
+		ast_cdr_post(cdr);
+	}
+	/* Reset to initial state */
+	cdr->posted = 0;
+	memset(&cdr->start, 0, sizeof(cdr->start));
+	memset(&cdr->end, 0, sizeof(cdr->end));
+	memset(&cdr->answer, 0, sizeof(cdr->answer));
+	cdr->billsec = 0;
+	cdr->duration = 0;
+	ast_cdr_start(cdr);
+	cdr->disposition = AST_CDR_NOANSWER;
+}