diff --git a/UPGRADE.txt b/UPGRADE.txt
index ff8d3597a8ce16d97af32a36022d035a99a86db5..1ac0b758ea311acc716cc20b0863a6002cb189d7 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -82,6 +82,9 @@ From 1.6.2 to 1.8:
   of a Mailbox or Password, will, if it exists, jump to the 'a' extension in
   the current dialplan context.
 
+* The CALLERPRES() dialplan function is deprecated in favor of
+  CALLERID(num-pres) and CALLERID(name-pres).
+
 * Environment variables that start with "AST_" are reserved to the system and
   may no longer be set from the dialplan.
 
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 6b8596c5e640ae6830fa932443e4e3431c7f12fc..0375a13f111cce9312347f987b00859b154feff8 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -922,24 +922,23 @@ static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
 	}
 	ast_mutex_lock(&p->lock);
 	ast_set_flag(p, H323_OUTGOING);
-	if (ast->connected.id.number) {
-     		if(p->callerid_num)   free(p->callerid_num);
-		p->callerid_num = strdup(ast->connected.id.number);
-	}
-
-	if (ast->connected.id.name) {
-      		if(p->callerid_name)
-			free(p->callerid_name);
-		p->callerid_name = strdup(ast->connected.id.name);
-	} else if (ast->connected.id.number) {
-      		if(p->callerid_name)
-			free(p->callerid_name);
-		p->callerid_name = strdup(ast->connected.id.number);
+	if (ast->connected.id.number.valid && ast->connected.id.number.str) {
+		free(p->callerid_num);
+		p->callerid_num = strdup(ast->connected.id.number.str);
+	}
+
+	if (ast->connected.id.name.valid && ast->connected.id.name.str) {
+		free(p->callerid_name);
+		p->callerid_name = strdup(ast->connected.id.name.str);
+	} else if (ast->connected.id.number.valid && ast->connected.id.number.str) {
+		free(p->callerid_name);
+		p->callerid_name = strdup(ast->connected.id.number.str);
 	} else {
-		ast->connected.id.name = strdup(gCallerID);
-      		if(p->callerid_name)
-			free(p->callerid_name);
-		p->callerid_name = strdup(ast->connected.id.name);
+		ast->connected.id.name.valid = 1;
+		free(ast->connected.id.name.str);
+		ast->connected.id.name.str = strdup(gCallerID);
+		free(p->callerid_name);
+		p->callerid_name = strdup(ast->connected.id.name.str);
 	}
 
 	/* Retrieve vars */
@@ -1241,13 +1240,15 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
 	case AST_CONTROL_SRCCHANGE:
 		ast_rtp_instance_change_source(p->rtp);
 		break;
-       	case AST_CONTROL_CONNECTED_LINE:
-		if (!ast_strlen_zero(ast->connected.id.name)) {
-			if (gH323Debug)
-				ast_log(LOG_DEBUG, "Sending connected line info for %s (%s)\n",
-				callToken, ast->connected.id.name);
-			ooSetANI(callToken, ast->connected.id.name);
+	case AST_CONTROL_CONNECTED_LINE:
+		if (!ast->connected.id.name.valid
+			|| ast_strlen_zero(ast->connected.id.name.str)) {
+			break;
 		}
+		if (gH323Debug)
+			ast_log(LOG_DEBUG, "Sending connected line info for %s (%s)\n",
+				callToken, ast->connected.id.name.str);
+		ooSetANI(callToken, ast->connected.id.name.str);
 		break;
 
       case AST_CONTROL_T38_PARAMETERS:
@@ -1539,10 +1540,15 @@ int onAlerting(ooCallData *call)
 
 	if (call->remoteDisplayName) {
 		struct ast_party_connected_line connected;
+		struct ast_set_party_connected_line update_connected;
+
+		memset(&update_connected, 0, sizeof(update_connected));
+		update_connected.id.name = 1;
 		ast_party_connected_line_init(&connected);
-		connected.id.name = (char *) call->remoteDisplayName;
+		connected.id.name.valid = 1;
+		connected.id.name.str = (char *) call->remoteDisplayName;
 		connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-		ast_channel_queue_connected_line_update(c, &connected);
+		ast_channel_queue_connected_line_update(c, &connected, &update_connected);
 	}
 	if (c->_state != AST_STATE_UP)
 		ast_setstate(c, AST_STATE_RINGING);
@@ -1590,10 +1596,15 @@ int onProgress(ooCallData *call)
 
 	if (call->remoteDisplayName) {
 		struct ast_party_connected_line connected;
+		struct ast_set_party_connected_line update_connected;
+
+		memset(&update_connected, 0, sizeof(update_connected));
+		update_connected.id.name = 1;
 		ast_party_connected_line_init(&connected);
-		connected.id.name = (char *) call->remoteDisplayName;
+		connected.id.name.valid = 1;
+		connected.id.name.str = (char *) call->remoteDisplayName;
 		connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-		ast_channel_queue_connected_line_update(c, &connected);
+		ast_channel_queue_connected_line_update(c, &connected, &update_connected);
 	}
 	if (c->_state != AST_STATE_UP)
 		ast_setstate(c, AST_STATE_RINGING);
@@ -1983,10 +1994,15 @@ int onCallEstablished(ooCallData *call)
 
 			if (call->remoteDisplayName) {
 				struct ast_party_connected_line connected;
+				struct ast_set_party_connected_line update_connected;
+
+				memset(&update_connected, 0, sizeof(update_connected));
+				update_connected.id.name = 1;
 				ast_party_connected_line_init(&connected);
-				connected.id.name = (char *) call->remoteDisplayName;
+				connected.id.name.valid = 1;
+				connected.id.name.str = (char *) call->remoteDisplayName;
 				connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-				ast_channel_queue_connected_line_update(c, &connected);
+				ast_channel_queue_connected_line_update(c, &connected, &update_connected);
 			}
 
 			ast_queue_control(c, AST_CONTROL_ANSWER);
diff --git a/apps/app_alarmreceiver.c b/apps/app_alarmreceiver.c
index 22dd4af6789f228c7101a2821ba6276c19769dc9..952ef722e01ad154840417435688716aeffacd24 100644
--- a/apps/app_alarmreceiver.c
+++ b/apps/app_alarmreceiver.c
@@ -298,18 +298,22 @@ static int write_metadata( FILE *logfile, char *signalling_type, struct ast_chan
 	int res = 0;
 	struct timeval t;
 	struct ast_tm now;
-	char *cl,*cn;
+	char *cl;
+	char *cn;
 	char workstring[80];
 	char timestamp[80];
 	
 	/* Extract the caller ID location */
-	if (chan->cid.cid_num)
-		ast_copy_string(workstring, chan->cid.cid_num, sizeof(workstring));
-	workstring[sizeof(workstring) - 1] = '\0';
-
-	ast_callerid_parse(workstring, &cn, &cl);
-	if (cl)
-		ast_shrink_phone_number(cl);
+	ast_copy_string(workstring,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
+		sizeof(workstring));
+	ast_shrink_phone_number(workstring);
+	if (ast_strlen_zero(workstring)) {
+		cl = "<unknown>";
+	} else {
+		cl = workstring;
+	}
+	cn = S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>");
 
 	/* Get the current time */
 	t = ast_tvnow();
@@ -319,27 +323,27 @@ static int write_metadata( FILE *logfile, char *signalling_type, struct ast_chan
 	ast_strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
 
 	res = fprintf(logfile, "\n\n[metadata]\n\n");
-
-	if (res >= 0)
+	if (res >= 0) {
 		res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
-
-	if (res >= 0)
-		res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
-
-	if (res >- 0)
-		res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
-
-	if (res >= 0)
+	}
+	if (res >= 0) {
+		res = fprintf(logfile, "CALLINGFROM=%s\n", cl);
+	}
+	if (res >= 0) {
+		res = fprintf(logfile, "CALLERNAME=%s\n", cn);
+	}
+	if (res >= 0) {
 		res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
-
-	if (res >= 0)
+	}
+	if (res >= 0) {
 		res = fprintf(logfile, "[events]\n\n");
-
+	}
 	if (res < 0) {
 		ast_verb(3, "AlarmReceiver: can't write metadata\n");
 		ast_debug(1,"AlarmReceiver: can't write metadata\n");
-	} else
+	} else {
 		res = 0;
+	}
 
 	return res;
 }
diff --git a/apps/app_amd.c b/apps/app_amd.c
index 928afee0b1a75574ad8c0aea4ef162bc8b4827b9..f4eb78470e2d99a48ab828d8cc8c4dee6292f55e 100644
--- a/apps/app_amd.c
+++ b/apps/app_amd.c
@@ -188,8 +188,10 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
 		AST_APP_ARG(argMaximumWordLength);
 	);
 
-	ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", chan->name, chan->cid.cid_ani,
-		chan->redirecting.from.number, ast_getformatname(chan->readformat));
+	ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", chan->name,
+		S_OR(chan->caller.ani, "(N/A)"),
+		S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "(N/A)"),
+		ast_getformatname(chan->readformat));
 
 	/* Lets parse the arguments. */
 	if (!ast_strlen_zero(parse)) {
diff --git a/apps/app_dial.c b/apps/app_dial.c
index 31e64ce4da8386ffe61d76fc8f81b62669c7b160..52ca6bd1d5df76fc54b973c0099b71b5661cb84e 100644
--- a/apps/app_dial.c
+++ b/apps/app_dial.c
@@ -722,13 +722,6 @@ static void handle_cause(int cause, struct cause_args *num)
 	}
 }
 
-/*! \brief free the buffer if allocated, and set the pointer to the second arg */
-#define S_REPLACE(s, new_val) \
-	do {                      \
-		ast_free(s);          \
-		s = (new_val);        \
-	} while (0)
-
 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri)
 {
 	char rexten[2] = { exten, '\0' };
@@ -773,9 +766,11 @@ static void senddialevent(struct ast_channel *src, struct ast_channel *dst, cons
 		"UniqueID: %s\r\n"
 		"DestUniqueID: %s\r\n"
 		"Dialstring: %s\r\n",
-		src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
-		S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
-		dst->uniqueid, dialstring ? dialstring : "");
+		src->name, dst->name,
+		S_COR(src->caller.id.number.valid, src->caller.id.number.str, "<unknown>"),
+		S_COR(src->caller.id.name.valid, src->caller.id.name.str, "<unknown>"),
+		src->uniqueid, dst->uniqueid,
+		dialstring ? dialstring : "");
 }
 
 static void senddialendevent(struct ast_channel *src, const char *dialstatus)
@@ -859,28 +854,34 @@ static void do_forward(struct chanlist *o,
 			ast_rtp_instance_early_bridge_make_compatible(c, in);
 		}
 
-		ast_channel_set_redirecting(c, &original->redirecting);
+		ast_channel_set_redirecting(c, &original->redirecting, NULL);
 		ast_channel_lock(c);
 		while (ast_channel_trylock(in)) {
 			CHANNEL_DEADLOCK_AVOIDANCE(c);
 		}
-		if (ast_strlen_zero(c->redirecting.from.number)) {
+		if (!c->redirecting.from.number.valid
+			|| ast_strlen_zero(c->redirecting.from.number.str)) {
 			/*
 			 * The call was not previously redirected so it is
 			 * now redirected from this number.
 			 */
-			S_REPLACE(c->redirecting.from.number,
-				ast_strdup(S_OR(in->macroexten, in->exten)));
+			ast_party_number_free(&c->redirecting.from.number);
+			ast_party_number_init(&c->redirecting.from.number);
+			c->redirecting.from.number.valid = 1;
+			c->redirecting.from.number.str =
+				ast_strdup(S_OR(in->macroexten, in->exten));
 		}
 
-		c->cid.cid_tns = in->cid.cid_tns;
+		c->dialed.transit_network_select = in->dialed.transit_network_select;
 
 		if (ast_test_flag64(o, OPT_FORCECLID)) {
-			S_REPLACE(c->cid.cid_num, ast_strdup(S_OR(in->macroexten, in->exten)));
-			S_REPLACE(c->cid.cid_name, NULL);
+			ast_party_id_free(&c->caller.id);
+			ast_party_id_init(&c->caller.id);
+			c->caller.id.number.valid = 1;
+			c->caller.id.number.str = ast_strdup(S_OR(in->macroexten, in->exten));
 			ast_string_field_set(c, accountcode, c->accountcode);
 		} else {
-			ast_party_caller_copy(&c->cid, &in->cid);
+			ast_party_caller_copy(&c->caller, &in->caller);
 			ast_string_field_set(c, accountcode, in->accountcode);
 		}
 		ast_party_connected_line_copy(&c->connected, &original->connected);
@@ -897,7 +898,7 @@ static void do_forward(struct chanlist *o,
 			while (ast_channel_trylock(c)) {
 				CHANNEL_DEADLOCK_AVOIDANCE(in);
 			}
-			ast_channel_update_redirecting(in, &c->redirecting);
+			ast_channel_update_redirecting(in, &c->redirecting, NULL);
 			ast_channel_unlock(c);
 		}
 
@@ -985,10 +986,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 
 		if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_CALLERID_ABSENT)) {
 			ast_channel_lock(outgoing->chan);
-			ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->cid);
+			ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->caller);
 			ast_channel_unlock(outgoing->chan);
 			connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-			ast_channel_update_connected_line(in, &connected_caller);
+			ast_channel_update_connected_line(in, &connected_caller, NULL);
 			ast_party_connected_line_free(&connected_caller);
 		}
 	}
@@ -1045,14 +1046,14 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 					if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
 						if (o->pending_connected_update) {
 							if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
-								ast_channel_update_connected_line(in, &o->connected);
+								ast_channel_update_connected_line(in, &o->connected, NULL);
 							}
 						} else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
 							ast_channel_lock(c);
-							ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
+							ast_connected_line_copy_from_caller(&connected_caller, &c->caller);
 							ast_channel_unlock(c);
 							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-							ast_channel_update_connected_line(in, &connected_caller);
+							ast_channel_update_connected_line(in, &connected_caller, NULL);
 							ast_party_connected_line_free(&connected_caller);
 						}
 					}
@@ -1115,14 +1116,14 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 						if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
 							if (o->pending_connected_update) {
 								if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
-									ast_channel_update_connected_line(in, &o->connected);
+									ast_channel_update_connected_line(in, &o->connected, NULL);
 								}
 							} else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
 								ast_channel_lock(c);
-								ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
+								ast_connected_line_copy_from_caller(&connected_caller, &c->caller);
 								ast_channel_unlock(c);
 								connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-								ast_channel_update_connected_line(in, &connected_caller);
+								ast_channel_update_connected_line(in, &connected_caller, NULL);
 								ast_party_connected_line_free(&connected_caller);
 							}
 						}
@@ -1240,7 +1241,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 						ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", c->name, in->name);
 						ast_party_connected_line_set_init(&connected, &o->connected);
 						ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
-						ast_party_connected_line_set(&o->connected, &connected);
+						ast_party_connected_line_set(&o->connected, &connected, NULL);
 						ast_party_connected_line_free(&connected);
 						o->pending_connected_update = 1;
 					} else {
@@ -1617,8 +1618,9 @@ static int setup_privacy_args(struct privacy_args *pa,
 	char *l;
 	int silencethreshold;
 
-	if (!ast_strlen_zero(chan->cid.cid_num)) {
-		l = ast_strdupa(chan->cid.cid_num);
+	if (chan->caller.id.number.valid
+		&& !ast_strlen_zero(chan->caller.id.number.str)) {
+		l = ast_strdupa(chan->caller.id.number.str);
 		ast_shrink_phone_number(l);
 		if (ast_test_flag64(opts, OPT_PRIVACY) ) {
 			ast_verb(3, "Privacy DB is '%s', clid is '%s'\n", opt_args[OPT_ARG_PRIVACY], l);
@@ -2060,11 +2062,16 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
 		memset(&tc->whentohangup, 0, sizeof(tc->whentohangup));
 
 		/* If the new channel has no callerid, try to guess what it should be */
-		if (ast_strlen_zero(tc->cid.cid_num)) {
-			if (!ast_strlen_zero(chan->connected.id.number)) {
-				ast_set_callerid(tc, chan->connected.id.number, chan->connected.id.name, chan->connected.ani);
-			} else if (!ast_strlen_zero(chan->cid.cid_dnid)) {
-				ast_set_callerid(tc, chan->cid.cid_dnid, NULL, NULL);
+		if (!tc->caller.id.number.valid) {
+			if (chan->connected.id.number.valid) {
+				struct ast_party_caller caller;
+
+				ast_party_caller_set_init(&caller, &tc->caller);
+				caller.id = chan->connected.id;
+				caller.ani = chan->connected.ani;
+				ast_channel_set_caller_event(tc, &caller, NULL);
+			} else if (!ast_strlen_zero(chan->dialed.number.str)) {
+				ast_set_callerid(tc, chan->dialed.number.str, NULL, NULL);
 			} else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) {
 				ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL);
 			}
@@ -2076,25 +2083,33 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
 			int pres;
 
 			ast_party_connected_line_set_init(&connected, &tmp->chan->connected);
-			connected.id.number = cid_num;
-			connected.id.name = cid_name;
-			connected.id.tag = cid_tag;
 			if (cid_pres) {
 				pres = ast_parse_caller_presentation(cid_pres);
-				if (pres >= 0) {
-					connected.id.number_presentation = pres;
+				if (pres < 0) {
+					pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
 				}
 			} else {
-				connected.id.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+				pres = AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
+			}
+			if (cid_num) {
+				connected.id.number.valid = 1;
+				connected.id.number.str = cid_num;
+				connected.id.number.presentation = pres;
 			}
-			ast_channel_set_connected_line(tmp->chan, &connected);
+			if (cid_name) {
+				connected.id.name.valid = 1;
+				connected.id.name.str = cid_name;
+				connected.id.name.presentation = pres;
+			}
+			connected.id.tag = cid_tag;
+			ast_channel_set_connected_line(tmp->chan, &connected, NULL);
 		} else {
-			ast_connected_line_copy_from_caller(&tc->connected, &chan->cid);
+			ast_connected_line_copy_from_caller(&tc->connected, &chan->caller);
 		}
 
 		ast_party_redirecting_copy(&tc->redirecting, &chan->redirecting);
 
-		tc->cid.cid_tns = chan->cid.cid_tns;
+		tc->dialed.transit_network_select = chan->dialed.transit_network_select;
 
 		if (!ast_strlen_zero(chan->accountcode)) {
 			ast_string_field_set(tc, peeraccount, chan->accountcode);
@@ -2616,7 +2631,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
 
 		strcpy(peer->context, chan->context);
 
-		if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
+		if (ast_test_flag64(&opts, OPT_PEER_H)
+			&& ast_exists_extension(peer, peer->context, "h", 1,
+				S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL))) {
 			int autoloopflag;
 			int found;
 			int res9;
@@ -2626,8 +2643,12 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
 			autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
 			ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
 
-			while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found, 1)) == 0)
+			while ((res9 = ast_spawn_extension(peer, peer->context, peer->exten,
+				peer->priority,
+				S_COR(peer->caller.id.number.valid, peer->caller.id.number.str, NULL),
+				&found, 1)) == 0) {
 				peer->priority++;
+			}
 
 			if (found && res9) {
 				/* Something bad happened, or a hangup has been requested. */
diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index cb8505b56e4c2060d76fae4d9db3b51f9dd1a44b..bcefb0661547d9c073b5dac65dbc4950fdb1526c 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -111,15 +111,15 @@ static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
 	ast_party_connected_line_copy(&connected_caller, &target->connected);
 	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 	if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
-		ast_channel_update_connected_line(chan, &connected_caller);
+		ast_channel_update_connected_line(chan, &connected_caller, NULL);
 	}
 	ast_party_connected_line_free(&connected_caller);
 
 	ast_channel_lock(chan);
-	ast_connected_line_copy_from_caller(&connected_caller, &chan->cid);
+	ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
 	ast_channel_unlock(chan);
 	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-	ast_channel_queue_connected_line_update(chan, &connected_caller);
+	ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
 	ast_party_connected_line_free(&connected_caller);
 
 	if ((res = ast_answer(chan))) {
diff --git a/apps/app_disa.c b/apps/app_disa.c
index a64d053719f9d9fd6d76201083825ce4c2d0332e..20c9ce48cabda9f118dc5e94b38bc0e4e5e26d3d 100644
--- a/apps/app_disa.c
+++ b/apps/app_disa.c
@@ -308,9 +308,11 @@ static int disa_exec(struct ast_channel *chan, const char *data)
 				}
 			} else {
 				if (j == '#') { /* end of extension .. maybe */
-					if (i == 0 && 
-							(ast_matchmore_extension(chan, args.context, "#", 1, chan->cid.cid_num) ||
-							 ast_exists_extension(chan, args.context, "#", 1, chan->cid.cid_num)) ) {
+					if (i == 0
+						&& (ast_matchmore_extension(chan, args.context, "#", 1,
+							S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+							|| ast_exists_extension(chan, args.context, "#", 1,
+								S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) ) {
 						/* Let the # be the part of, or the entire extension */
 					} else {
 						break;
@@ -340,7 +342,8 @@ static int disa_exec(struct ast_channel *chan, const char *data)
 				}
 
 			/* if can do some more, do it */
-			if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) {
+			if (!ast_matchmore_extension(chan, args.context, exten, 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				break;
 			}
 		}
@@ -352,13 +355,16 @@ static int disa_exec(struct ast_channel *chan, const char *data)
 		int recheck = 0;
 		struct ast_flags cdr_flags = { AST_CDR_FLAG_POSTED };
 
-		if (!ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
+		if (!ast_exists_extension(chan, args.context, exten, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
 			exten[0] = 'i';
 			exten[1] = '\0';
 			recheck = 1;
 		}
-		if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
+		if (!recheck
+			|| ast_exists_extension(chan, args.context, exten, 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			ast_playtones_stop(chan);
 			/* We're authenticated and have a target extension */
 			if (!ast_strlen_zero(args.cid)) {
diff --git a/apps/app_dumpchan.c b/apps/app_dumpchan.c
index d66661db6eb953f5c7d15b4236625a778fe19d9f..feaeda29e7df646d752877dd247bea9e98a62185 100644
--- a/apps/app_dumpchan.c
+++ b/apps/app_dumpchan.c
@@ -116,10 +116,10 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
 			c->name,
 			c->tech->type,
 			c->uniqueid,
-			S_OR(c->cid.cid_num, "(N/A)"),
-			S_OR(c->cid.cid_name, "(N/A)"),
-			S_OR(c->cid.cid_dnid, "(N/A)"),
-			S_OR(c->redirecting.from.number, "(N/A)"),
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, "(N/A)"),
+			S_COR(c->caller.id.name.valid, c->caller.id.name.str, "(N/A)"),
+			S_OR(c->dialed.number.str, "(N/A)"),
+			S_COR(c->redirecting.from.number.valid, c->redirecting.from.number.str, "(N/A)"),
 			c->parkinglot,
 			c->language,
 			ast_state2str(c->_state),
diff --git a/apps/app_fax.c b/apps/app_fax.c
index 9b1972d97a01ec7d67137669d996ed5a1c35dc91..54d22db1695da46d443e5dfa6e9e0f3ed6b259b3 100644
--- a/apps/app_fax.c
+++ b/apps/app_fax.c
@@ -251,25 +251,25 @@ static void phase_e_handler(t30_state_t *f, void *user_data, int result)
 	ast_debug(1, "  Transfer Rate:     %d\n", stat.bit_rate);
 	
 	ast_manager_event(s->chan, EVENT_FLAG_CALL,
-		      s->direction ? "FaxSent" : "FaxReceived", 
-		      "Channel: %s\r\n"
-		      "Exten: %s\r\n"
-		      "CallerID: %s\r\n"
-		      "RemoteStationID: %s\r\n"
-		      "LocalStationID: %s\r\n"
-		      "PagesTransferred: %d\r\n"
-		      "Resolution: %d\r\n"
-		      "TransferRate: %d\r\n"
-		      "FileName: %s\r\n",
-		      s->chan->name,
-		      s->chan->exten,
-		      S_OR(s->chan->cid.cid_num, ""),
-		      far_ident,
-		      local_ident,
-		      pages_transferred,
-		      stat.y_resolution,
-		      stat.bit_rate,
-		      s->file_name);
+		s->direction ? "FaxSent" : "FaxReceived",
+		"Channel: %s\r\n"
+		"Exten: %s\r\n"
+		"CallerID: %s\r\n"
+		"RemoteStationID: %s\r\n"
+		"LocalStationID: %s\r\n"
+		"PagesTransferred: %d\r\n"
+		"Resolution: %d\r\n"
+		"TransferRate: %d\r\n"
+		"FileName: %s\r\n",
+		s->chan->name,
+		s->chan->exten,
+		S_COR(s->chan->caller.id.number.valid, s->chan->caller.id.number.str, ""),
+		far_ident,
+		local_ident,
+		pages_transferred,
+		stat.y_resolution,
+		stat.bit_rate,
+		s->file_name);
 }
 
 /* === Helper functions to configure fax === */
diff --git a/apps/app_followme.c b/apps/app_followme.c
index b6ad76705a3062db8f6593a40650f165b1743b7f..fcab992d390788f95b26fbf00984ec8383f8da1f 100644
--- a/apps/app_followme.c
+++ b/apps/app_followme.c
@@ -838,7 +838,10 @@ static void findmeexec(struct fm_args *tpargs)
 
 			outbound = ast_request("Local", ast_best_codec(caller->nativeformats), caller, dialarg, &dg);
 			if (outbound) {
-				ast_set_callerid(outbound, caller->cid.cid_num, caller->cid.cid_name, caller->cid.cid_num);
+				ast_set_callerid(outbound,
+					S_COR(caller->caller.id.number.valid, caller->caller.id.number.str, NULL),
+					S_COR(caller->caller.id.name.valid, caller->caller.id.name.str, NULL),
+					S_COR(caller->caller.id.number.valid, caller->caller.id.number.str, NULL));
 				ast_channel_inherit_variables(tpargs->chan, outbound);
 				ast_channel_datastore_inherit(tpargs->chan, outbound);
 				ast_string_field_set(outbound, language, tpargs->chan->language);
diff --git a/apps/app_macro.c b/apps/app_macro.c
index f3ff81db58c34c1ccb28d125457205354c343570..e5ab2bc21a5e35cd78aabcc83dc654e4c7bcc670 100644
--- a/apps/app_macro.c
+++ b/apps/app_macro.c
@@ -298,7 +298,8 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
 	}
 
 	snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
-	if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) {
+	if (!ast_exists_extension(chan, fullmacro, "s", 1,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		if (!ast_context_find(fullmacro)) 
 			ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
 		else
@@ -370,7 +371,8 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
 	ast_channel_unlock(chan);
 	autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
 	ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
-	while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
+	while (ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		struct ast_context *c;
 		struct ast_exten *e;
 		int foundx;
@@ -386,7 +388,8 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
 					if (ast_rdlock_context(c)) {
 						ast_log(LOG_WARNING, "Unable to lock context?\n");
 					} else {
-						e = find_matching_priority(c, chan->exten, chan->priority, chan->cid.cid_num);
+						e = find_matching_priority(c, chan->exten, chan->priority,
+							S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
 						if (e) { /* This will only be undefined for pbx_realtime, which is majorly broken. */
 							ast_copy_string(runningapp, ast_get_extension_app(e), sizeof(runningapp));
 							ast_copy_string(runningdata, ast_get_extension_app_data(e), sizeof(runningdata));
@@ -402,7 +405,10 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
 		/* Reset the macro depth, if it was changed in the last iteration */
 		pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
 
-		if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &foundx,1))) {
+		res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+			&foundx, 1);
+		if (res) {
 			/* Something bad happened, or a hangup has been requested. */
 			if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
 		    	(res == '*') || (res == '#')) {
@@ -544,7 +550,9 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
 				/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
 			   	normally if there is any problem */
 				if (sscanf(offsets, "%30d", &offset) == 1) {
-					if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) {
+					if (ast_exists_extension(chan, chan->context, chan->exten,
+						chan->priority + offset + 1,
+						S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 						chan->priority += offset;
 					}
 				}
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index b0b26ae308e615c25739e838f8a5907d9182e600..5ef9718f19eb3b59b2057b0ebb29fb09f541be9e 100644
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -1453,8 +1453,8 @@ static char *meetme_show_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 			if (!concise) {
 				ast_cli(a->fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s %s %02d:%02d:%02d\n",
 					user->user_no,
-					S_OR(user->chan->cid.cid_num, "<unknown>"),
-					S_OR(user->chan->cid.cid_name, "<no name>"),
+					S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"),
+					S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"),
 					user->chan->name,
 					ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "(Admin)" : "",
 					ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "(Listen only)" : "",
@@ -1464,8 +1464,8 @@ static char *meetme_show_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 			} else {
 				ast_cli(a->fd, "%d!%s!%s!%s!%s!%s!%s!%s!%d!%02d:%02d:%02d\n",
 					user->user_no,
-					S_OR(user->chan->cid.cid_num, ""),
-					S_OR(user->chan->cid.cid_name, ""),
+					S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, ""),
+					S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, ""),
 					user->chan->name,
 					ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "1" : "",
 					ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "1" : "",
@@ -2660,17 +2660,17 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc
 
 	if (!sent_event) {
 		ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeJoin",
-			        "Channel: %s\r\n"
-			        "Uniqueid: %s\r\n"
-				"Meetme: %s\r\n"
-				"Usernum: %d\r\n"
-				"CallerIDnum: %s\r\n"
-			      	"CallerIDname: %s\r\n",
-			      	chan->name, chan->uniqueid, conf->confno, 
-				user->user_no,
-				S_OR(user->chan->cid.cid_num, "<unknown>"),
-				S_OR(user->chan->cid.cid_name, "<unknown>")
-				);
+			"Channel: %s\r\n"
+			"Uniqueid: %s\r\n"
+			"Meetme: %s\r\n"
+			"Usernum: %d\r\n"
+			"CallerIDnum: %s\r\n"
+			"CallerIDname: %s\r\n",
+			chan->name, chan->uniqueid, conf->confno,
+			user->user_no,
+			S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"),
+			S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>")
+			);
 		sent_event = 1;
 	}
 
@@ -3697,18 +3697,18 @@ bailoutandtrynormal:
 
 		if (sent_event) {
 			ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeLeave",
-				      "Channel: %s\r\n"
-				      "Uniqueid: %s\r\n"
-				      "Meetme: %s\r\n"
-				      "Usernum: %d\r\n"
-				      "CallerIDNum: %s\r\n"
-				      "CallerIDName: %s\r\n"
-				      "Duration: %ld\r\n",
-				      chan->name, chan->uniqueid, conf->confno, 
-				      user->user_no,
-				      S_OR(user->chan->cid.cid_num, "<unknown>"),
-				      S_OR(user->chan->cid.cid_name, "<unknown>"),
-				      (long)(now.tv_sec - user->jointime));
+				"Channel: %s\r\n"
+				"Uniqueid: %s\r\n"
+				"Meetme: %s\r\n"
+				"Usernum: %d\r\n"
+				"CallerIDNum: %s\r\n"
+				"CallerIDName: %s\r\n"
+				"Duration: %ld\r\n",
+				chan->name, chan->uniqueid, conf->confno,
+				user->user_no,
+				S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"),
+				S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<unknown>"),
+				(long)(now.tv_sec - user->jointime));
 		}
 
 		if (setusercount) {
@@ -4706,30 +4706,30 @@ static int action_meetmelist(struct mansession *s, const struct message *m)
 		while ((user = ao2_iterator_next(&user_iter))) {
 			total++;
 			astman_append(s,
-			"Event: MeetmeList\r\n"
-			"%s"
-			"Conference: %s\r\n"
-			"UserNumber: %d\r\n"
-			"CallerIDNum: %s\r\n"
-			"CallerIDName: %s\r\n"
-			"Channel: %s\r\n"
-			"Admin: %s\r\n"
-			"Role: %s\r\n"
-			"MarkedUser: %s\r\n"
-			"Muted: %s\r\n"
-			"Talking: %s\r\n"
-			"\r\n",
-			idText,
-			cnf->confno,
-			user->user_no,
-			S_OR(user->chan->cid.cid_num, "<unknown>"),
-			S_OR(user->chan->cid.cid_name, "<no name>"),
-			user->chan->name,
-			ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "Yes" : "No",
-			ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "Listen only" : ast_test_flag64(&user->userflags, CONFFLAG_TALKER) ? "Talk only" : "Talk and listen",
-			ast_test_flag64(&user->userflags, CONFFLAG_MARKEDUSER) ? "Yes" : "No",
-			user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No",
-			user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored"); 
+				"Event: MeetmeList\r\n"
+				"%s"
+				"Conference: %s\r\n"
+				"UserNumber: %d\r\n"
+				"CallerIDNum: %s\r\n"
+				"CallerIDName: %s\r\n"
+				"Channel: %s\r\n"
+				"Admin: %s\r\n"
+				"Role: %s\r\n"
+				"MarkedUser: %s\r\n"
+				"Muted: %s\r\n"
+				"Talking: %s\r\n"
+				"\r\n",
+				idText,
+				cnf->confno,
+				user->user_no,
+				S_COR(user->chan->caller.id.number.valid, user->chan->caller.id.number.str, "<unknown>"),
+				S_COR(user->chan->caller.id.name.valid, user->chan->caller.id.name.str, "<no name>"),
+				user->chan->name,
+				ast_test_flag64(&user->userflags, CONFFLAG_ADMIN) ? "Yes" : "No",
+				ast_test_flag64(&user->userflags, CONFFLAG_MONITOR) ? "Listen only" : ast_test_flag64(&user->userflags, CONFFLAG_TALKER) ? "Talk only" : "Talk and listen",
+				ast_test_flag64(&user->userflags, CONFFLAG_MARKEDUSER) ? "Yes" : "No",
+				user->adminflags & ADMINFLAG_MUTED ? "By admin" : user->adminflags & ADMINFLAG_SELFMUTED ? "By self" : "No",
+				user->talking > 0 ? "Yes" : user->talking == 0 ? "No" : "Not monitored");
 			ao2_ref(user, -1);
 		}
 		ao2_iterator_destroy(&user_iter);
@@ -5335,8 +5335,9 @@ static int sla_ring_station(struct sla_ringing_trunk *ringing_trunk, struct sla_
 	char *tech, *tech_data;
 	struct ast_dial *dial;
 	struct sla_ringing_station *ringing_station;
-	const char *cid_name = NULL, *cid_num = NULL;
 	enum ast_dial_result res;
+	int caller_is_saved;
+	struct ast_party_caller caller;
 
 	if (!(dial = ast_dial_create()))
 		return -1;
@@ -5350,23 +5351,21 @@ static int sla_ring_station(struct sla_ringing_trunk *ringing_trunk, struct sla_
 		return -1;
 	}
 
-	if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_name)) {
-		cid_name = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_name);
-		ast_free(ringing_trunk->trunk->chan->cid.cid_name);
-		ringing_trunk->trunk->chan->cid.cid_name = NULL;
-	}
-	if (!sla.attempt_callerid && !ast_strlen_zero(ringing_trunk->trunk->chan->cid.cid_num)) {
-		cid_num = ast_strdupa(ringing_trunk->trunk->chan->cid.cid_num);
-		ast_free(ringing_trunk->trunk->chan->cid.cid_num);
-		ringing_trunk->trunk->chan->cid.cid_num = NULL;
+	/* Do we need to save off the caller ID data? */
+	caller_is_saved = 0;
+	if (!sla.attempt_callerid) {
+		caller_is_saved = 1;
+		caller = ringing_trunk->trunk->chan->caller;
+		ast_party_caller_init(&ringing_trunk->trunk->chan->caller);
 	}
 
 	res = ast_dial_run(dial, ringing_trunk->trunk->chan, 1);
 	
-	if (cid_name)
-		ringing_trunk->trunk->chan->cid.cid_name = ast_strdup(cid_name);
-	if (cid_num)
-		ringing_trunk->trunk->chan->cid.cid_num = ast_strdup(cid_num);
+	/* Restore saved caller ID */
+	if (caller_is_saved) {
+		ast_party_caller_free(&ringing_trunk->trunk->chan->caller);
+		ringing_trunk->trunk->chan->caller = caller;
+	}
 	
 	if (res != AST_DIAL_RESULT_TRYING) {
 		struct sla_failed_station *failed_station;
@@ -5884,7 +5883,8 @@ static void *dial_trunk(void *data)
 	struct ast_conference *conf;
 	struct ast_flags64 conf_flags = { 0 };
 	struct sla_trunk_ref *trunk_ref = args->trunk_ref;
-	const char *cid_name = NULL, *cid_num = NULL;
+	int caller_is_saved;
+	struct ast_party_caller caller;
 
 	if (!(dial = ast_dial_create())) {
 		ast_mutex_lock(args->cond_lock);
@@ -5903,23 +5903,21 @@ static void *dial_trunk(void *data)
 		return NULL;
 	}
 
-	if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_name)) {
-		cid_name = ast_strdupa(trunk_ref->chan->cid.cid_name);
-		ast_free(trunk_ref->chan->cid.cid_name);
-		trunk_ref->chan->cid.cid_name = NULL;
-	}
-	if (!sla.attempt_callerid && !ast_strlen_zero(trunk_ref->chan->cid.cid_num)) {
-		cid_num = ast_strdupa(trunk_ref->chan->cid.cid_num);
-		ast_free(trunk_ref->chan->cid.cid_num);
-		trunk_ref->chan->cid.cid_num = NULL;
+	/* Do we need to save of the caller ID data? */
+	caller_is_saved = 0;
+	if (!sla.attempt_callerid) {
+		caller_is_saved = 1;
+		caller = trunk_ref->chan->caller;
+		ast_party_caller_init(&trunk_ref->chan->caller);
 	}
 
 	dial_res = ast_dial_run(dial, trunk_ref->chan, 1);
 
-	if (cid_name)
-		trunk_ref->chan->cid.cid_name = ast_strdup(cid_name);
-	if (cid_num)
-		trunk_ref->chan->cid.cid_num = ast_strdup(cid_num);
+	/* Restore saved caller ID */
+	if (caller_is_saved) {
+		ast_party_caller_free(&trunk_ref->chan->caller);
+		trunk_ref->chan->caller = caller;
+	}
 
 	if (dial_res != AST_DIAL_RESULT_TRYING) {
 		ast_mutex_lock(args->cond_lock);
diff --git a/apps/app_minivm.c b/apps/app_minivm.c
index b2ab3b82c8f431ea2ec2c6d59c8d71366037304f..55373698cfc7bd5bd11459e2f919f5083d3dbcfc 100644
--- a/apps/app_minivm.c
+++ b/apps/app_minivm.c
@@ -1731,7 +1731,10 @@ static void run_externnotify(struct ast_channel *chan, struct minivm_account *vm
 	snprintf(arguments, sizeof(arguments), "%s %s@%s %s %s&", 
 		ast_strlen_zero(vmu->externnotify) ? global_externnotify : vmu->externnotify, 
 		vmu->username, vmu->domain,
-		chan->cid.cid_name, chan->cid.cid_num);
+		(chan->caller.id.name.valid && chan->caller.id.name.str)
+			? chan->caller.id.name.str : "",
+		(chan->caller.id.number.valid && chan->caller.id.number.str)
+			? chan->caller.id.number.str : "");
 
 	ast_debug(1, "Executing: %s\n", arguments);
 	ast_safe_system(arguments);
@@ -1917,6 +1920,10 @@ static int leave_voicemail(struct ast_channel *chan, char *username, struct leav
 		ast_localtime(&now, &tm, NULL);
 		ast_strftime(timebuf, sizeof(timebuf), "%H:%M:%S", &tm);
 
+		ast_callerid_merge(callerid, sizeof(callerid),
+			S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+			"Unknown");
 		snprintf(logbuf, sizeof(logbuf),
 			/* "Mailbox:domain:macrocontext:exten:priority:callerchan:callerid:origdate:origtime:duration:durationstatus:accountcode" */
 			"%s:%s:%s:%s:%d:%s:%s:%s:%s:%d:%s:%s\n",
@@ -1926,7 +1933,7 @@ static int leave_voicemail(struct ast_channel *chan, char *username, struct leav
 			chan->exten,
 			chan->priority,
 			chan->name,
-			ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
+			callerid,
 			date, 
 			timebuf,
 			duration,
@@ -2118,7 +2125,10 @@ static int minivm_notify_exec(struct ast_channel *chan, const char *data)
 			duration_string = ast_strdupa(duration_string);
 		}
 		ast_channel_unlock(chan);
-		res = notify_new_message(chan, template, vmu, filename, atoi(duration_string), format, chan->cid.cid_num, chan->cid.cid_name);
+		res = notify_new_message(chan, template, vmu, filename, atoi(duration_string),
+			format,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+			S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL));
 	}
 
 	pbx_builtin_setvar_helper(chan, "MVM_NOTIFY_STATUS", res == 0 ? "SUCCESS" : "FAILED");
@@ -2279,26 +2289,35 @@ static int minivm_greet_exec(struct ast_channel *chan, const char *data)
 	/* Check current or macro-calling context for special extensions */
 	if (ast_test_flag(vmu, MVM_OPERATOR)) {
 		if (!ast_strlen_zero(vmu->exit)) {
-			if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
+			if (ast_exists_extension(chan, vmu->exit, "o", 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
 				ouseexten = 1;
 			}
-		} else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
+		} else if (ast_exists_extension(chan, chan->context, "o", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
 			ouseexten = 1;
 		}
-		else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
+		else if (!ast_strlen_zero(chan->macrocontext)
+			&& ast_exists_extension(chan, chan->macrocontext, "o", 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
 			ousemacro = 1;
 		}
 	}
 
 	if (!ast_strlen_zero(vmu->exit)) {
-		if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
+		if (ast_exists_extension(chan, vmu->exit, "a", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
-	} else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
+		}
+	} else if (ast_exists_extension(chan, chan->context, "a", 1,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
-	else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
+	} else if (!ast_strlen_zero(chan->macrocontext)
+		&& ast_exists_extension(chan, chan->macrocontext, "a", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		strncat(ecodes, "*", sizeof(ecodes) -  strlen(ecodes) - 1);
 		ausemacro = 1;
 	}
diff --git a/apps/app_osplookup.c b/apps/app_osplookup.c
index 2ebea0cdf2abce378505c826bfb8b48cea1b4455..ea20cee771407653131a44bc13ee4bf3971816b3 100644
--- a/apps/app_osplookup.c
+++ b/apps/app_osplookup.c
@@ -2257,7 +2257,10 @@ static int ospauth_exec(
 	ast_debug(1, "OSPAuth: source '%s'\n", source);
 	ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
 
-	if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
+	res = osp_auth(provider, &handle, source,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+		chan->exten, token, &timelimit);
+	if (res > 0) {
 		status = AST_OSP_SUCCESS;
 	} else {
 		timelimit = OSP_DEF_TIMELIMIT;
@@ -2453,7 +2456,10 @@ static int osplookup_exec(
 		return OSP_AST_ERROR;
 	}
 
-	if ((res = osp_lookup(provider, callidtypes, actualsrc, srcdev, chan->cid.cid_num, args.exten, snetid, &np, &div, cinfo, &results)) > 0) {
+	res = osp_lookup(provider, callidtypes, actualsrc, srcdev,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+		args.exten, snetid, &np, &div, cinfo, &results);
+	if (res > 0) {
 		status = AST_OSP_SUCCESS;
 	} else {
 		results.tech[0] = '\0';
diff --git a/apps/app_parkandannounce.c b/apps/app_parkandannounce.c
index 4ae525101babf4bf84787c140ad03a3d422ec6d0..5bb8b659465dc3164c727c47480a0681ed2e546f 100644
--- a/apps/app_parkandannounce.c
+++ b/apps/app_parkandannounce.c
@@ -126,10 +126,13 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data)
 		ast_parseable_goto(chan, args.return_context);
 	}
 
-	ast_verb(3, "Return Context: (%s,%s,%d) ID: %s\n", chan->context, chan->exten, chan->priority, chan->cid.cid_num);
-		if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
+	ast_verb(3, "Return Context: (%s,%s,%d) ID: %s\n", chan->context, chan->exten,
+		chan->priority,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
+	if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
-		}
+	}
 
 	/* we are using masq_park here to protect * from touching the channel once we park it.  If the channel comes out of timeout
 	before we are done announcing and the channel is messed with, Kablooeee.  So we use Masq to prevent this.  */
@@ -145,8 +148,11 @@ static int parkandannounce_exec(struct ast_channel *chan, const char *data)
 	snprintf(buf, sizeof(buf), "%d", lot);
 	oh.parent_channel = chan;
 	oh.vars = ast_variable_new("_PARKEDAT", buf, "");
-	dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, chan, args.dial, 30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
-
+	dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, chan, args.dial, 30000,
+		&outstate,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+		&oh);
 	if (dchan) {
 		if (dchan->_state == AST_STATE_UP) {
 			ast_verb(4, "Channel %s was answered.\n", dchan->name);
diff --git a/apps/app_privacy.c b/apps/app_privacy.c
index e0c102d7436de68fb6e9b97b0b5a6ef0be1b8b04..4b8f61c3f5790b391bedff1ed92b7b9280ca58e1 100644
--- a/apps/app_privacy.c
+++ b/apps/app_privacy.c
@@ -96,8 +96,9 @@ static int privacy_exec(struct ast_channel *chan, const char *data)
 		AST_APP_ARG(checkcontext);
 	);
 
-	if (!ast_strlen_zero(chan->cid.cid_num)) {
-		ast_verb(3, "CallerID Present: Skipping\n");
+	if (chan->caller.id.number.valid
+		&& !ast_strlen_zero(chan->caller.id.number.str)) {
+		ast_verb(3, "CallerID number present: Skipping\n");
 	} else {
 		/*Answer the channel if it is not already*/
 		if (chan->_state != AST_STATE_UP) {
@@ -181,14 +182,19 @@ static int privacy_exec(struct ast_channel *chan, const char *data)
 				res = ast_waitstream(chan, "");
 			}
 
-			ast_set_callerid(chan, phone, "Privacy Manager", NULL);
-
-			/* Clear the unavailable presence bit so if it came in on PRI
-			 * the caller id will now be passed out to other channels
+			/*
+			 * This is a caller entered number that is going to be used locally.
+			 * Therefore, the given number presentation is allowed and should
+			 * be passed out to other channels.  This is the point of the
+			 * privacy application.
 			 */
-			chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
+			chan->caller.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+			chan->caller.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+			chan->caller.id.number.plan = 0;/* Unknown */
+
+			ast_set_callerid(chan, phone, "Privacy Manager", NULL);
 
-			ast_verb(3, "Changed Caller*ID to '%s', callerpres to %d\n", phone, chan->cid.cid_pres);
+			ast_verb(3, "Changed Caller*ID number to '%s'\n", phone);
 
 			pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
 		} else {
diff --git a/apps/app_queue.c b/apps/app_queue.c
index e91e13a06e7e477dabd85deaaca732356a6000b1..11de4d903ab9613b9bb2e8ffe285f57cdb845cf1 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -2334,8 +2334,8 @@ static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *
 		ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
 			"Channel: %s\r\nCallerIDNum: %s\r\nCallerIDName: %s\r\nQueue: %s\r\nPosition: %d\r\nCount: %d\r\nUniqueid: %s\r\n",
 			qe->chan->name,
-			S_OR(qe->chan->cid.cid_num, "unknown"), /* XXX somewhere else it is <unknown> */
-			S_OR(qe->chan->cid.cid_name, "unknown"),
+			S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),/* XXX somewhere else it is <unknown> */
+			S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
 			q->name, qe->pos, q->count, qe->chan->uniqueid );
 		ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, qe->chan->name, qe->pos );
 	}
@@ -2391,7 +2391,8 @@ static int valid_exit(struct queue_ent *qe, char digit)
 		return 0;
 
 	/* If the extension is bad, then reset the digits to blank */
-	if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1, qe->chan->cid.cid_num)) {
+	if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
+		S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, NULL))) {
 		qe->digits[0] = '\0';
 		return 0;
 	}
@@ -2893,12 +2894,16 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
 	memset(&tmp->chan->whentohangup, 0, sizeof(tmp->chan->whentohangup));
 
 	/* If the new channel has no callerid, try to guess what it should be */
-	if (ast_strlen_zero(tmp->chan->cid.cid_num)) {
-		if (!ast_strlen_zero(qe->chan->connected.id.number)) {
-			ast_set_callerid(tmp->chan, qe->chan->connected.id.number, qe->chan->connected.id.name, qe->chan->connected.ani);
-			tmp->chan->cid.cid_pres = qe->chan->connected.id.number_presentation;
-		} else if (!ast_strlen_zero(qe->chan->cid.cid_dnid)) {
-			ast_set_callerid(tmp->chan, qe->chan->cid.cid_dnid, NULL, NULL);
+	if (!tmp->chan->caller.id.number.valid) {
+		if (qe->chan->connected.id.number.valid) {
+			struct ast_party_caller caller;
+
+			ast_party_caller_set_init(&caller, &tmp->chan->caller);
+			caller.id = qe->chan->connected.id;
+			caller.ani = qe->chan->connected.ani;
+			ast_channel_set_caller_event(tmp->chan, &caller, NULL);
+		} else if (!ast_strlen_zero(qe->chan->dialed.number.str)) {
+			ast_set_callerid(tmp->chan, qe->chan->dialed.number.str, NULL, NULL);
 		} else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
 			ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL); 
 		}
@@ -2907,9 +2912,9 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
 
 	ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
 
-	tmp->chan->cid.cid_tns = qe->chan->cid.cid_tns;
+	tmp->chan->dialed.transit_network_select = qe->chan->dialed.transit_network_select;
 
-	ast_connected_line_copy_from_caller(&tmp->chan->connected, &qe->chan->cid);
+	ast_connected_line_copy_from_caller(&tmp->chan->connected, &qe->chan->caller);
 
 	/* Inherit specially named variables from parent channel */
 	ast_channel_inherit_variables(qe->chan, tmp->chan);
@@ -2957,23 +2962,23 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
 		char vars[2048];
 
 		manager_event(EVENT_FLAG_AGENT, "AgentCalled",
-					"Queue: %s\r\n"
-					"AgentCalled: %s\r\n"
-					"AgentName: %s\r\n"
-					"ChannelCalling: %s\r\n"
-					"DestinationChannel: %s\r\n"
-					"CallerIDNum: %s\r\n"
-					"CallerIDName: %s\r\n"
-					"Context: %s\r\n"
-					"Extension: %s\r\n"
-					"Priority: %d\r\n"
-					"Uniqueid: %s\r\n"
-					"%s",
-					qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
-					tmp->chan->cid.cid_num ? tmp->chan->cid.cid_num : "unknown",
-					tmp->chan->cid.cid_name ? tmp->chan->cid.cid_name : "unknown",
-					qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
-					qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
+			"Queue: %s\r\n"
+			"AgentCalled: %s\r\n"
+			"AgentName: %s\r\n"
+			"ChannelCalling: %s\r\n"
+			"DestinationChannel: %s\r\n"
+			"CallerIDNum: %s\r\n"
+			"CallerIDName: %s\r\n"
+			"Context: %s\r\n"
+			"Extension: %s\r\n"
+			"Priority: %d\r\n"
+			"Uniqueid: %s\r\n"
+			"%s",
+			qe->parent->name, tmp->interface, tmp->member->membername, qe->chan->name, tmp->chan->name,
+			S_COR(tmp->chan->caller.id.number.valid, tmp->chan->caller.id.number.str, "unknown"),
+			S_COR(tmp->chan->caller.id.name.valid, tmp->chan->caller.id.name.str, "unknown"),
+			qe->chan->context, qe->chan->exten, qe->chan->priority, qe->chan->uniqueid,
+			qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
 		ast_verb(3, "Called %s\n", tmp->interface);
 	}
 	ast_channel_unlock(tmp->chan);
@@ -3332,14 +3337,14 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
 					if (update_connectedline) {
 						if (o->pending_connected_update) {
 							if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
-								ast_channel_update_connected_line(in, &o->connected);
+								ast_channel_update_connected_line(in, &o->connected, NULL);
 							}
 						} else if (!o->dial_callerid_absent) {
 							ast_channel_lock(o->chan);
-							ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
+							ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
 							ast_channel_unlock(o->chan);
 							connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-							ast_channel_update_connected_line(in, &connected_caller);
+							ast_channel_update_connected_line(in, &connected_caller, NULL);
 							ast_party_connected_line_free(&connected_caller);
 						}
 					}
@@ -3400,20 +3405,23 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
 
 						ast_string_field_set(o->chan, accountcode, in->accountcode);
 
-						ast_channel_set_redirecting(o->chan, &original->redirecting);
-						if (ast_strlen_zero(o->chan->redirecting.from.number)) {
+						ast_channel_set_redirecting(o->chan, &original->redirecting, NULL);
+						if (!o->chan->redirecting.from.number.valid
+							|| ast_strlen_zero(o->chan->redirecting.from.number.str)) {
 							/*
 							 * The call was not previously redirected so it is
 							 * now redirected from this number.
 							 */
-							ast_free(o->chan->redirecting.from.number);
-							o->chan->redirecting.from.number =
+							ast_party_number_free(&o->chan->redirecting.from.number);
+							ast_party_number_init(&o->chan->redirecting.from.number);
+							o->chan->redirecting.from.number.valid = 1;
+							o->chan->redirecting.from.number.str =
 								ast_strdup(S_OR(in->macroexten, in->exten));
 						}
 
-						o->chan->cid.cid_tns = in->cid.cid_tns;
+						o->chan->dialed.transit_network_select = in->dialed.transit_network_select;
 
-						ast_party_caller_copy(&o->chan->cid, &in->cid);
+						ast_party_caller_copy(&o->chan->caller, &in->caller);
 						ast_party_connected_line_copy(&o->chan->connected, &original->connected);
 
 						/*
@@ -3429,7 +3437,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
 							CHANNEL_DEADLOCK_AVOIDANCE(in);
 						}
 						if (res) {
-							ast_channel_update_redirecting(in, &o->chan->redirecting);
+							ast_channel_update_redirecting(in, &o->chan->redirecting, NULL);
 						}
 
 						update_connectedline = 1;
@@ -3459,14 +3467,14 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
 								if (update_connectedline) {
 									if (o->pending_connected_update) {
 										if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
-											ast_channel_update_connected_line(in, &o->connected);
+											ast_channel_update_connected_line(in, &o->connected, NULL);
 										}
 									} else if (!o->dial_callerid_absent) {
 										ast_channel_lock(o->chan);
-										ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
+										ast_connected_line_copy_from_caller(&connected_caller, &o->chan->caller);
 										ast_channel_unlock(o->chan);
 										connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-										ast_channel_update_connected_line(in, &connected_caller);
+										ast_channel_update_connected_line(in, &connected_caller, NULL);
 										ast_party_connected_line_free(&connected_caller);
 									}
 								}
@@ -3538,7 +3546,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
 								ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
 								ast_party_connected_line_set_init(&connected, &o->connected);
 								ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
-								ast_party_connected_line_set(&o->connected, &connected);
+								ast_party_connected_line_set(&o->connected, &connected, NULL);
 								ast_party_connected_line_free(&connected);
 								o->pending_connected_update = 1;
 							} else {
@@ -5706,8 +5714,10 @@ static int queue_exec(struct ast_channel *chan, const char *data)
 		set_queue_result(chan, reason);
 		return 0;
 	}
-	ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s|%d", S_OR(args.url, ""),
-		S_OR(chan->cid.cid_num, ""), qe.opos);
+	ast_queue_log(args.queuename, chan->uniqueid, "NONE", "ENTERQUEUE", "%s|%s|%d",
+		S_OR(args.url, ""),
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
+		qe.opos);
 	copy_rules(&qe, args.rule);
 	qe.pr = AST_LIST_FIRST(&qe.qe_rules);
 check_turns:
@@ -7017,8 +7027,8 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
 					"%s"
 					"\r\n",
 					q->name, pos++, qe->chan->name, qe->chan->uniqueid,
-					S_OR(qe->chan->cid.cid_num, "unknown"),
-					S_OR(qe->chan->cid.cid_name, "unknown"),
+					S_COR(qe->chan->caller.id.number.valid, qe->chan->caller.id.number.str, "unknown"),
+					S_COR(qe->chan->caller.id.name.valid, qe->chan->caller.id.name.str, "unknown"),
 					(long) (now - qe->start), idText);
 			}
 		}
diff --git a/apps/app_readexten.c b/apps/app_readexten.c
index f8f4a1bfc4de0177c4c8f894b508a7d54f2dcf07..8049fc94956acbeb6e7818d935facc6f37d4cf77 100644
--- a/apps/app_readexten.c
+++ b/apps/app_readexten.c
@@ -240,8 +240,11 @@ static int readexten_exec(struct ast_channel *chan, const char *data)
 			}
 
 			exten[x] = res;
-			if (!ast_matchmore_extension(chan, arglist.context, exten, 1 /* priority */, chan->cid.cid_num)) {
-				if (!ast_exists_extension(chan, arglist.context, exten, 1, chan->cid.cid_num) && res == '#') {
+			if (!ast_matchmore_extension(chan, arglist.context, exten, 1 /* priority */,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
+				if (!ast_exists_extension(chan, arglist.context, exten, 1,
+					S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+					&& res == '#') {
 					exten[x] = '\0';
 				}
 				break;
@@ -251,7 +254,8 @@ static int readexten_exec(struct ast_channel *chan, const char *data)
 		if (!ast_strlen_zero(status))
 			break;
 
-		if (ast_exists_extension(chan, arglist.context, exten, 1, chan->cid.cid_num)) {
+		if (ast_exists_extension(chan, arglist.context, exten, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			ast_debug(3, "User entered valid extension '%s'\n", exten);
 			pbx_builtin_setvar_helper(chan, arglist.variable, exten);
 			status = "OK";
@@ -296,10 +300,12 @@ static int acf_isexten_exec(struct ast_channel *chan, const char *cmd, char *par
 	else
 		priority_int = atoi(args.priority);
 
-	if (ast_exists_extension(chan, args.context, args.extension, priority_int, chan->cid.cid_num))
+	if (ast_exists_extension(chan, args.context, args.extension, priority_int,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 	    ast_copy_string(buffer, "1", buflen);
-	else
+	} else {
 	    ast_copy_string(buffer, "0", buflen);
+	}
 
 	return 0;
 }
diff --git a/apps/app_rpt.c b/apps/app_rpt.c
index a6be0e19f3506242e509427cbfdee46db904869f..a4d350d32eb3286977055e104d3499578048b421 100644
--- a/apps/app_rpt.c
+++ b/apps/app_rpt.c
@@ -5454,14 +5454,14 @@ struct ast_channel *mychannel,*genchannel;
 		if(instr){
 			ast_callerid_parse(instr, &name, &loc);
 			if(loc){
-				if(mychannel->cid.cid_num)
-					ast_free(mychannel->cid.cid_num);
-				mychannel->cid.cid_num = ast_strdup(loc);
+				mychannel->caller.id.number.valid = 1;
+				ast_free(mychannel->caller.id.number.str);
+				mychannel->caller.id.number.str = ast_strdup(loc);
 			}
 			if(name){
-				if(mychannel->cid.cid_name)
-					ast_free(mychannel->cid.cid_name);
-				mychannel->cid.cid_name = ast_strdup(name);
+				mychannel->caller.id.name.valid = 1;
+				ast_free(mychannel->caller.id.name.str);
+				mychannel->caller.id.name.str = ast_strdup(name);
 			}
 			ast_free(instr);
 		}
@@ -5808,9 +5808,9 @@ static int connect_link(struct rpt *myrpt, char* node, int mode, int perma)
 		if (debug > 3)
 			ast_log(LOG_NOTICE, "rpt (remote) initiating call to %s/%s on %s\n",
 		deststr, tele, l->chan->name);
-		if(l->chan->cid.cid_num)
-			ast_free(l->chan->cid.cid_num);
-		l->chan->cid.cid_num = ast_strdup(myrpt->name);
+		l->chan->caller.id.number.valid = 1;
+		ast_free(l->chan->caller.id.number.str);
+		l->chan->caller.id.number.str = ast_strdup(myrpt->name);
 		ast_call(l->chan,tele,999);
 	}
 	else {
@@ -10388,9 +10388,9 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
 		if (option_verbose > 2)
 			ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
 				deststr, tele, l->chan->name);
-		if(l->chan->cid.cid_num)
-			ast_free(l->chan->cid.cid_num);
-		l->chan->cid.cid_num = ast_strdup(myrpt->name);
+		l->chan->caller.id.number.valid = 1;
+		ast_free(l->chan->caller.id.number.str);
+		l->chan->caller.id.number.str = ast_strdup(myrpt->name);
                 ast_call(l->chan,tele,999); 
 
 	}
@@ -13412,8 +13412,11 @@ static int rpt_exec(struct ast_channel *chan, const char *data)
 		}
 
 		if(option_verbose > 2) {
-			ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
-			if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
+			ast_verbose(VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n",
+				chan->context, chan->exten, chan->priority,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""));
+			if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
 			}
 		}
@@ -13443,7 +13446,8 @@ static int rpt_exec(struct ast_channel *chan, const char *data)
         char hisip[100],nodeip[100],*val, *s, *s1, *s2, *s3, *b,*b1;
 
 		/* look at callerid to see what node this comes from */
-		if (!chan->cid.cid_num) /* if doesn't have caller id */
+		b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
+		if (!b) /* if doesn't have caller id */
 		{
 			ast_log(LOG_WARNING, "Does not have callerid on %s\n",tmp);
 			return -1;
@@ -13467,7 +13471,7 @@ static int rpt_exec(struct ast_channel *chan, const char *data)
 			return -1;
 		}
 		
-		ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+		b1 = ast_strdupa(b);
 		ast_shrink_phone_number(b1);
 		if (!strcmp(myrpt->name,b1))
 		{
@@ -13564,13 +13568,14 @@ static int rpt_exec(struct ast_channel *chan, const char *data)
 			return -1;
 		}
 		/* look at callerid to see what node this comes from */
-		if (!chan->cid.cid_num) /* if doesn't have caller id */
+		b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
+		if (!b) /* if doesn't have caller id */
 		{
 			ast_log(LOG_WARNING, "Doesnt have callerid on %s\n",tmp);
 			return -1;
 		}
 
-		ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+		b1 = ast_strdupa(b);
 		ast_shrink_phone_number(b1);
 		if (!strcmp(myrpt->name,b1))
 		{
@@ -14036,11 +14041,12 @@ static int rpt_exec(struct ast_channel *chan, const char *data)
 				ast_cli_command(nullfd,mycmd);
 		} else ast_cli_command(nullfd,mycmd);
 		/* look at callerid to see what node this comes from */
-		if (!chan->cid.cid_num) /* if doesn't have caller id */
+		b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
+		if (!b) /* if doesn't have caller id */
 		{
 			b1 = "0";
 		} else {
-			ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+			b1 = ast_strdupa(b);
 			ast_shrink_phone_number(b1);
 		}
 		sprintf(mycmd,"CONNECT,%s",b1);
@@ -14546,11 +14552,12 @@ static int rpt_exec(struct ast_channel *chan, const char *data)
 		char mycmd[100],*b,*b1;
 
 		/* look at callerid to see what node this comes from */
-		if (!chan->cid.cid_num) /* if doesn't have caller id */
+		b = S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL);
+		if (!b) /* if doesn't have caller id */
 		{
 			b1 = "0";
 		} else {
-			ast_callerid_parse(chan->cid.cid_num,&b,&b1);
+			b1 = ast_strdupa(b);
 			ast_shrink_phone_number(b1);
 		}
 		sprintf(mycmd,"DISCONNECT,%s",b1);
diff --git a/apps/app_setcallerid.c b/apps/app_setcallerid.c
index 0e2ce485d47ad50641c143b35b4951528e417a7b..666e46ff4e57fa0792294784256ced123c280a3c 100644
--- a/apps/app_setcallerid.c
+++ b/apps/app_setcallerid.c
@@ -105,7 +105,9 @@ static int setcallerid_pres_exec(struct ast_channel *chan, const char *data)
 		return 0;
 	}
 	
-	chan->cid.cid_pres = pres;
+	/* Set the combined caller id presentation. */
+	chan->caller.id.name.presentation = pres;
+	chan->caller.id.number.presentation = pres;
 	return 0;
 }
 
diff --git a/apps/app_sms.c b/apps/app_sms.c
index 6a2b0c03f88ad559e88274b1892a636a07bb3e85..aee2fa6c5a5d8f774036c6595f47372cf8f341d7 100644
--- a/apps/app_sms.c
+++ b/apps/app_sms.c
@@ -1890,8 +1890,9 @@ static int sms_exec(struct ast_channel *chan, const char *data)
 	h.ipc0 = h.ipc1 = 20;                   /* phase for cosine */
 	h.dcs = 0xF1;                           /* default */
 
-	if (chan->cid.cid_num)
-		ast_copy_string(h.cli, chan->cid.cid_num, sizeof(h.cli));
+	ast_copy_string(h.cli,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
+		sizeof(h.cli));
 
 	if (ast_strlen_zero(sms_args.queue)) {
 		ast_log(LOG_ERROR, "Requires queue name\n");
diff --git a/apps/app_stack.c b/apps/app_stack.c
index ebca99490bbb36ed94b0ec3bcf9b1694678400f7..dcf13a00dffc233fe35646bbeb3d62ab0298e914 100644
--- a/apps/app_stack.c
+++ b/apps/app_stack.c
@@ -413,7 +413,9 @@ static int gosub_exec(struct ast_channel *chan, const char *data)
 		return -1;
 	}
 
-	if (!ast_exists_extension(chan, chan->context, chan->exten, ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP) ? chan->priority + 1 : chan->priority, chan->cid.cid_num)) {
+	if (!ast_exists_extension(chan, chan->context, chan->exten,
+		ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP) ? chan->priority + 1 : chan->priority,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		ast_log(LOG_ERROR, "Attempt to reach a non-existent destination for gosub: (Context:%s, Extension:%s, Priority:%d)\n",
 				chan->context, chan->exten, ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP) ? chan->priority + 1 : chan->priority);
 		ast_copy_string(chan->context, newframe->context, sizeof(chan->context));
@@ -588,12 +590,15 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, const char
 
 	if (sscanf(argv[3], "%30d", &priority) != 1 || priority < 1) {
 		/* Lookup the priority label */
-		if ((priority = ast_findlabel_extension(chan, argv[1], argv[2], argv[3], chan->cid.cid_num)) < 0) {
+		priority = ast_findlabel_extension(chan, argv[1], argv[2], argv[3],
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
+		if (priority < 0) {
 			ast_log(LOG_ERROR, "Priority '%s' not found in '%s@%s'\n", argv[3], argv[2], argv[1]);
 			ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
 			return RESULT_FAILURE;
 		}
-	} else if (!ast_exists_extension(chan, argv[1], argv[2], priority, chan->cid.cid_num)) {
+	} else if (!ast_exists_extension(chan, argv[1], argv[2], priority,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
 		return RESULT_FAILURE;
 	}
diff --git a/apps/app_talkdetect.c b/apps/app_talkdetect.c
index 0db0012bc1b6a2499c4af52bb88023398e719214..615929e9430079674421143a75fa1cf5037f12c2 100644
--- a/apps/app_talkdetect.c
+++ b/apps/app_talkdetect.c
@@ -175,7 +175,8 @@ static int background_detect_exec(struct ast_channel *chan, const char *data)
 					char t[2];
 					t[0] = fr->subclass.integer;
 					t[1] = '\0';
-					if (ast_canmatch_extension(chan, chan->context, t, 1, chan->cid.cid_num)) {
+					if (ast_canmatch_extension(chan, chan->context, t, 1,
+						S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 						/* They entered a valid  extension, or might be anyhow */
 						res = fr->subclass.integer;
 						ast_frfree(fr);
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 6e2cc2a45846bb2d7e238e2770ee68c110fdfeb0..32c1760191182760f562d57ff2b8c51ddfaf2b9b 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -2203,7 +2203,10 @@ static int imap_store_file(const char *dir, const char *mailboxuser, const char
 		imap_delete_old_greeting(fn, vms);
 	}
 
-	make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, "INBOX", S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), fn, introfn, fmt, duration, 1, chan, NULL, 1, flag);
+	make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, "INBOX",
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+		fn, introfn, fmt, duration, 1, chan, NULL, 1, flag);
 	/* read mail file to memory */
 	len = ftell(p);
 	rewind(p);
@@ -5185,7 +5188,10 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i
 		res = -1;
 	}
 	ast_unlock_path(todir);
-	notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
+	notify_new_message(chan, recip, NULL, recipmsgnum, duration, fmt,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+		flag);
 	
 	return res;
 }
@@ -5513,25 +5519,34 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
 	/* Check current or macro-calling context for special extensions */
 	if (ast_test_flag(vmu, VM_OPERATOR)) {
 		if (!ast_strlen_zero(vmu->exit)) {
-			if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
+			if (ast_exists_extension(chan, vmu->exit, "o", 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
 				ouseexten = 1;
 			}
-		} else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
+		} else if (ast_exists_extension(chan, chan->context, "o", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
 			ouseexten = 1;
-		} else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
+		} else if (!ast_strlen_zero(chan->macrocontext)
+			&& ast_exists_extension(chan, chan->macrocontext, "o", 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
 			ousemacro = 1;
 		}
 	}
 
 	if (!ast_strlen_zero(vmu->exit)) {
-		if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
+		if (ast_exists_extension(chan, vmu->exit, "a", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
-	} else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
+		}
+	} else if (ast_exists_extension(chan, chan->context, "a", 1,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
-	else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
+	} else if (!ast_strlen_zero(chan->macrocontext)
+		&& ast_exists_extension(chan, chan->macrocontext, "a", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
 		ausemacro = 1;
 	}
@@ -5540,8 +5555,11 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
 		for (code = alldtmf; *code; code++) {
 			char e[2] = "";
 			e[0] = *code;
-			if (strchr(ecodes, e[0]) == NULL && ast_canmatch_extension(chan, chan->context, e, 1, chan->cid.cid_num))
+			if (strchr(ecodes, e[0]) == NULL
+				&& ast_canmatch_extension(chan, chan->context, e, 1,
+					S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				strncat(ecodes, e, sizeof(ecodes) - strlen(ecodes) - 1);
+			}
 		}
 	}
 
@@ -5721,13 +5739,33 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
 			snprintf(priority, sizeof(priority), "%d", chan->priority);
 			snprintf(origtime, sizeof(origtime), "%ld", (long) time(NULL));
 			get_date(date, sizeof(date));
-			ast_store_realtime("voicemail_data", "origmailbox", ext, "context", chan->context, "macrocontext", chan->macrocontext, "exten", chan->exten, "priority", priority, "callerchan", chan->name, "callerid", ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"), "origdate", date, "origtime", origtime, "category", S_OR(category, ""), "filename", tmptxtfile, SENTINEL);
+			ast_callerid_merge(callerid, sizeof(callerid),
+				S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+				"Unknown");
+			ast_store_realtime("voicemail_data",
+				"origmailbox", ext,
+				"context", chan->context,
+				"macrocontext", chan->macrocontext,
+				"exten", chan->exten,
+				"priority", priority,
+				"callerchan", chan->name,
+				"callerid", callerid,
+				"origdate", date,
+				"origtime", origtime,
+				"category", S_OR(category, ""),
+				"filename", tmptxtfile,
+				SENTINEL);
 		}
 
 		/* Store information */
 		txt = fdopen(txtdes, "w+");
 		if (txt) {
 			get_date(date, sizeof(date));
+			ast_callerid_merge(callerid, sizeof(callerid),
+				S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+				"Unknown");
 			fprintf(txt, 
 				";\n"
 				"; Message Information file\n"
@@ -5748,10 +5786,11 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
 				chan->context,
 				chan->macrocontext, 
 				chan->exten,
-				S_OR(chan->redirecting.from.number, "unknown"),
+				S_COR(chan->redirecting.from.number.valid,
+					chan->redirecting.from.number.str, "unknown"),
 				chan->priority,
 				chan->name,
-				ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
+				callerid,
 				date, (long) time(NULL),
 				category ? category : "");
 		} else {
@@ -5865,9 +5904,15 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
 					/* Notification needs to happen after the copy, though. */
 					if (ast_fileexists(fn, NULL, NULL)) {
 #ifdef IMAP_STORAGE
-						notify_new_message(chan, vmu, vms, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
+						notify_new_message(chan, vmu, vms, msgnum, duration, fmt,
+							S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+							S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+							flag);
 #else
-						notify_new_message(chan, vmu, NULL, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), flag);
+						notify_new_message(chan, vmu, NULL, msgnum, duration, fmt,
+							S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+							S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+							flag);
 #endif
 					}
 
@@ -7053,7 +7098,12 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
 					myserveremail = vmtmp->serveremail;
 				attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
 				/* NULL category for IMAP storage */
-				sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, dstvms->curbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, NULL, urgent_str);
+				sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox,
+					dstvms->curbox,
+					S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+					S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL),
+					vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan,
+					NULL, urgent_str);
 #else
 				copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str);
 #endif
@@ -9376,15 +9426,16 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
 			return -1;
 		}
 		if (ast_strlen_zero(mailbox)) {
-			if (chan->cid.cid_num) {
-				ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
+			if (chan->caller.id.number.valid && chan->caller.id.number.str) {
+				ast_copy_string(mailbox, chan->caller.id.number.str, mailbox_size);
 			} else {
 				ast_verb(3, "Username not entered\n");	
 				return -1;
 			}
 		} else if (mailbox[0] == '*') {
 			/* user entered '*' */
-			if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num)) {
+			if (ast_exists_extension(chan, chan->context, "a", 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 				return -1;
 			}
 			mailbox[0] = '\0';
@@ -9415,7 +9466,8 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
 				return -1;
 			} else if (password[0] == '*') {
 				/* user entered '*' */
-				if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num)) {
+				if (ast_exists_extension(chan, chan->context, "a", 1,
+					S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 					mailbox[0] = '*';
 					return -1;
 				}
diff --git a/apps/app_while.c b/apps/app_while.c
index e9a503aadd08188c88597d4e7b11cc4a1308ea84..80359359e19b9871239a47a493822efd3a214455 100644
--- a/apps/app_while.c
+++ b/apps/app_while.c
@@ -163,7 +163,11 @@ static int find_matching_endwhile(struct ast_channel *chan)
 				/* This is the matching context we want */
 				int cur_priority = chan->priority + 1, level=1;
 
-				for (e = find_matching_priority(c, chan->exten, cur_priority, chan->cid.cid_num); e; e = find_matching_priority(c, chan->exten, ++cur_priority, chan->cid.cid_num)) {
+				for (e = find_matching_priority(c, chan->exten, cur_priority,
+					S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
+					e;
+					e = find_matching_priority(c, chan->exten, ++cur_priority,
+						S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 					if (!strcasecmp(ast_get_extension_app(e), "WHILE")) {
 						level++;
 					} else if (!strcasecmp(ast_get_extension_app(e), "ENDWHILE")) {
diff --git a/apps/app_zapateller.c b/apps/app_zapateller.c
index 4be09b59c52053cef7a7ad9d261f026ea864a02e..6af9b963c6b128db085a5db3196f8d29d972275d 100644
--- a/apps/app_zapateller.c
+++ b/apps/app_zapateller.c
@@ -103,8 +103,12 @@ static int zapateller_exec(struct ast_channel *chan, const char *data)
 			res = ast_safe_sleep(chan, 500);
 	}
 
-	if (!ast_strlen_zero(chan->cid.cid_num) && nocallerid)
+	if (nocallerid	/* Zap caller if no caller id. */
+		&& chan->caller.id.number.valid
+		&& !ast_strlen_zero(chan->caller.id.number.str)) {
+		/* We have caller id. */
 		return res;
+	}
 
 	if (!res) 
 		res = ast_tonepair(chan, 950, 0, 330, 0);
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index dfbf2284d6251188d5a6d5e7c66a219d0c5b3bb2..c12900582aea3b58b87eb735a3093e9c5f26265e 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -1510,16 +1510,17 @@ static int action_agents(struct mansession *s, const struct message *m)
 		if (p->chan) {
 			loginChan = ast_strdupa(p->chan->name);
 			if (p->owner && p->owner->_bridge) {
-				talkingto = p->chan->cid.cid_num;
+				talkingto = S_COR(p->chan->caller.id.number.valid,
+					p->chan->caller.id.number.str, "n/a");
 				if (ast_bridged_channel(p->owner))
 					talkingtoChan = ast_strdupa(ast_bridged_channel(p->owner)->name);
 				else
 					talkingtoChan = "n/a";
-        			status = "AGENT_ONCALL";
+				status = "AGENT_ONCALL";
 			} else {
 				talkingto = "n/a";
 				talkingtoChan = "n/a";
-        			status = "AGENT_IDLE";
+				status = "AGENT_IDLE";
 			}
 		} else {
 			loginChan = "n/a";
@@ -2169,10 +2170,12 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, const char *data)
 		if (strchr(data, 'c'))
 			changeoutgoing = 1;
 	}
-	if (chan->cid.cid_num) {
+	if (chan->caller.id.number.valid
+		&& !ast_strlen_zero(chan->caller.id.number.str)) {
 		const char *tmp;
 		char agentvar[AST_MAX_BUF];
-		snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num);
+		snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID,
+			chan->caller.id.number.str);
 		if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) {
 			struct agent_pvt *p;
 			ast_copy_string(agent, tmp, sizeof(agent));
diff --git a/channels/chan_console.c b/channels/chan_console.c
index 9d68e9f5273df18beaef24f198996d75284d4a76..99b673b6c70dba95118cc0dde1b9297863fe7149 100644
--- a/channels/chan_console.c
+++ b/channels/chan_console.c
@@ -566,7 +566,9 @@ static int console_call(struct ast_channel *c, char *dest, int timeout)
 	enum ast_control_frame_type ctrl;
 
 	ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
-		dest, c->cid.cid_name, c->cid.cid_num);
+		dest,
+		S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
+		S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""));
 
 	console_pvt_lock(pvt);
 
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index e035b4bfe85f695a9fc7d41955160884acfc2b8d..e807b957a653cc922c5a8a1330d8a69e9334390e 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -1887,7 +1887,7 @@ static int my_callwait(void *pvt)
 	return 0;
 }
 
-static int my_send_callerid(void *pvt, int cwcid, struct ast_callerid *cid)
+static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *caller)
 {
 	struct dahdi_pvt *p = pvt;
 
@@ -1900,11 +1900,17 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_callerid *cid)
 
 	if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
 		if (cwcid == 0) {
-			p->cidlen = ast_callerid_generate(p->cidspill, cid->cid_name, cid->cid_num, AST_LAW(p));
+			p->cidlen = ast_callerid_generate(p->cidspill,
+				caller->id.name.str,
+				caller->id.number.str,
+				AST_LAW(p));
 		} else {
 			p->callwaitcas = 0;
 			p->cidcwexpire = 0;
-			p->cidlen = ast_callerid_callwaiting_generate(p->cidspill, cid->cid_name, cid->cid_num, AST_LAW(p));
+			p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
+				caller->id.name.str,
+				caller->id.number.str,
+				AST_LAW(p));
 			p->cidlen += READ_SIZE * 4;
 		}
 		p->cidpos = 0;
@@ -2015,7 +2021,8 @@ static void my_handle_dtmfup(void *pvt, struct ast_channel *ast, enum analog_sub
 				 */
 				ast_mutex_unlock(&p->lock);
 				ast_channel_unlock(ast);
-				if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+				if (ast_exists_extension(ast, target_context, "fax", 1,
+					S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
 					ast_channel_lock(ast);
 					ast_mutex_lock(&p->lock);
 					ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
@@ -2910,16 +2917,20 @@ static void my_set_callerid(void *pvt, const struct ast_party_caller *caller)
 {
 	struct dahdi_pvt *p = pvt;
 
-	ast_copy_string(p->cid_num, S_OR(caller->id.number, ""), sizeof(p->cid_num));
-	ast_copy_string(p->cid_name, S_OR(caller->id.name, ""), sizeof(p->cid_name));
+	ast_copy_string(p->cid_num,
+		S_COR(caller->id.number.valid, caller->id.number.str, ""),
+		sizeof(p->cid_num));
+	ast_copy_string(p->cid_name,
+		S_COR(caller->id.name.valid, caller->id.name.str, ""),
+		sizeof(p->cid_name));
 	if (caller->id.subaddress.valid) {
 		ast_copy_string(p->cid_subaddr, S_OR(caller->id.subaddress.str, ""),
 			sizeof(p->cid_subaddr));
 	} else {
 		p->cid_subaddr[0] = '\0';
 	}
-	p->cid_ton = caller->id.number_type;
-	p->callingpres = caller->id.number_presentation;
+	p->cid_ton = caller->id.number.plan;
+	p->callingpres = ast_party_id_presentation(&caller->id);
 	if (caller->id.tag) {
 		ast_copy_string(p->cid_tag, caller->id.tag, sizeof(p->cid_tag));
 	}
@@ -5137,7 +5148,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
 			c = "";
 		}
 		if (!p->hidecallerid) {
-			l = ast->cid.cid_num;
+			l = ast->caller.id.number.valid ? ast->caller.id.number.str : NULL;
 		} else {
 			l = NULL;
 		}
@@ -7386,7 +7397,8 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int idx, struct ast_fra
 				 */
 				ast_mutex_unlock(&p->lock);
 				ast_channel_unlock(ast);
-				if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+				if (ast_exists_extension(ast, target_context, "fax", 1,
+					S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
 					ast_channel_lock(ast);
 					ast_mutex_lock(&p->lock);
 					ast_verb(3, "Redirecting %s to fax extension\n", ast->name);
@@ -8023,10 +8035,16 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
 					cid_num[0] = 0;
 					cid_name[0] = 0;
 					if (p->dahditrcallerid && p->owner) {
-						if (p->owner->cid.cid_num)
-							ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
-						if (p->owner->cid.cid_name)
-							ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
+						if (p->owner->caller.id.number.valid
+							&& p->owner->caller.id.number.str) {
+							ast_copy_string(cid_num, p->owner->caller.id.number.str,
+								sizeof(cid_num));
+						}
+						if (p->owner->caller.id.name.valid
+							&& p->owner->caller.id.name.str) {
+							ast_copy_string(cid_name, p->owner->caller.id.name.str,
+								sizeof(cid_name));
+						}
 					}
 					/* XXX This section needs much more error checking!!! XXX */
 					/* Start a 3-way call if feasible */
@@ -8168,8 +8186,11 @@ winkflashdone:
 		case SIG_FEATDMF_TA:
 			switch (p->whichwink) {
 			case 0:
-				ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
-				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
+				ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
+					S_OR(p->owner->caller.ani, ""));
+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
+					p->owner->caller.ani2,
+					S_OR(p->owner->caller.ani, ""));
 				break;
 			case 1:
 				ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
@@ -9169,25 +9190,29 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
 		tmp->adsicpe = AST_ADSI_UNAVAILABLE;
 	if (!ast_strlen_zero(i->exten))
 		ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
-	if (!ast_strlen_zero(i->rdnis))
-		tmp->redirecting.from.number = ast_strdup(i->rdnis);
-	if (!ast_strlen_zero(i->dnid))
-		tmp->cid.cid_dnid = ast_strdup(i->dnid);
+	if (!ast_strlen_zero(i->rdnis)) {
+		tmp->redirecting.from.number.valid = 1;
+		tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
+	}
+	if (!ast_strlen_zero(i->dnid)) {
+		tmp->dialed.number.str = ast_strdup(i->dnid);
+	}
 
 	/* Don't use ast_set_callerid() here because it will
 	 * generate a needless NewCallerID event */
 #if defined(HAVE_PRI) || defined(HAVE_SS7)
 	if (!ast_strlen_zero(i->cid_ani))
-		tmp->cid.cid_ani = ast_strdup(i->cid_ani);
+		tmp->caller.ani = ast_strdup(i->cid_ani);
 	else
-		tmp->cid.cid_ani = ast_strdup(i->cid_num);
+		tmp->caller.ani = ast_strdup(i->cid_num);
 #else
-	tmp->cid.cid_ani = ast_strdup(i->cid_num);
+	tmp->caller.ani = ast_strdup(i->cid_num);
 #endif	/* defined(HAVE_PRI) || defined(HAVE_SS7) */
-	tmp->cid.cid_pres = i->callingpres;
-	tmp->cid.cid_ton = i->cid_ton;
-	tmp->cid.cid_ani2 = i->cid_ani2;
-	tmp->cid.cid_tag = ast_strdup(i->cid_tag);
+	tmp->caller.id.name.presentation = i->callingpres;
+	tmp->caller.id.number.presentation = i->callingpres;
+	tmp->caller.id.number.plan = i->cid_ton;
+	tmp->caller.ani2 = i->cid_ani2;
+	tmp->caller.id.tag = ast_strdup(i->cid_tag);
 	/* clear the fake event in case we posted one before we had ast_channel */
 	i->fake_event = 0;
 	/* Assure there is no confmute on this channel */
@@ -9576,7 +9601,8 @@ static void *analog_ss_thread(void *data)
 			}
 		}
 
-		if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
+		if (ast_exists_extension(chan, chan->context, exten, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			ast_copy_string(chan->exten, exten, sizeof(chan->exten));
 			if (p->dsp) ast_dsp_digitreset(p->dsp);
 			res = ast_pbx_run(chan);
@@ -9727,12 +9753,10 @@ static void *analog_ss_thread(void *data)
 				ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
 				/* Disable Caller*ID if enabled */
 				p->hidecallerid = 1;
-				if (chan->cid.cid_num)
-					ast_free(chan->cid.cid_num);
-				chan->cid.cid_num = NULL;
-				if (chan->cid.cid_name)
-					ast_free(chan->cid.cid_name);
-				chan->cid.cid_name = NULL;
+				ast_party_number_free(&chan->caller.id.number);
+				ast_party_number_init(&chan->caller.id.number);
+				ast_party_name_free(&chan->caller.id.name);
+				ast_party_name_init(&chan->caller.id.name);
 				res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
 				if (res) {
 					ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
@@ -9782,12 +9806,6 @@ static void *analog_ss_thread(void *data)
 				ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
 				/* Enable Caller*ID if enabled */
 				p->hidecallerid = 0;
-				if (chan->cid.cid_num)
-					ast_free(chan->cid.cid_num);
-				chan->cid.cid_num = NULL;
-				if (chan->cid.cid_name)
-					ast_free(chan->cid.cid_name);
-				chan->cid.cid_name = NULL;
 				ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
 				res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALRECALL);
 				if (res) {
@@ -9833,9 +9851,12 @@ static void *analog_ss_thread(void *data)
 					ast_hangup(chan);
 					goto quit;
 				}
-			} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
-							((exten[0] != '*') || (strlen(exten) > 2))) {
-				ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
+			} else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+				&& ((exten[0] != '*') || (strlen(exten) > 2))) {
+				ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
+					S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
+					chan->context);
 				break;
 			}
 			if (!timeout)
diff --git a/channels/chan_gtalk.c b/channels/chan_gtalk.c
index 1252bde197bd0a19bb46719a9acad014f2398db9..4101d52f960cfe5dfd66af137f6da91d0f82d65b 100644
--- a/channels/chan_gtalk.c
+++ b/channels/chan_gtalk.c
@@ -1051,7 +1051,8 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
 
 	tmp->callgroup = client->callgroup;
 	tmp->pickupgroup = client->pickupgroup;
-	tmp->cid.cid_pres = client->callingpres;
+	tmp->caller.id.name.presentation = client->callingpres;
+	tmp->caller.id.number.presentation = client->callingpres;
 	if (!ast_strlen_zero(client->accountcode))
 		ast_string_field_set(tmp, accountcode, client->accountcode);
 	if (client->amaflags)
@@ -1067,8 +1068,9 @@ static struct ast_channel *gtalk_new(struct gtalk *client, struct gtalk_pvt *i,
 	ast_copy_string(tmp->context, client->context, sizeof(tmp->context));
 	ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
 
-	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
-		tmp->cid.cid_dnid = ast_strdup(i->exten);
+	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
+		tmp->dialed.number.str = ast_strdup(i->exten);
+	}
 	tmp->priority = 1;
 	if (i->rtp)
 		ast_jb_configure(tmp, &global_jbconf);
diff --git a/channels/chan_h323.c b/channels/chan_h323.c
index a8aa9b7d02be9d31f1e713ab887d2e4d3a35673b..1866ce038dc79b3f4ef3026cb30c89833db6a437 100644
--- a/channels/chan_h323.c
+++ b/channels/chan_h323.c
@@ -609,18 +609,20 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
 	/* make sure null terminated */
 	called_addr[sizeof(called_addr) - 1] = '\0';
 
-	if (c->connected.id.number)
-		ast_copy_string(pvt->options.cid_num, c->connected.id.number, sizeof(pvt->options.cid_num));
+	if (c->connected.id.number.valid && c->connected.id.number.str) {
+		ast_copy_string(pvt->options.cid_num, c->connected.id.number.str, sizeof(pvt->options.cid_num));
+	}
 
-	if (c->connected.id.name)
-		ast_copy_string(pvt->options.cid_name, c->connected.id.name, sizeof(pvt->options.cid_name));
+	if (c->connected.id.name.valid && c->connected.id.name.str) {
+		ast_copy_string(pvt->options.cid_name, c->connected.id.name.str, sizeof(pvt->options.cid_name));
+	}
 
-	if (c->redirecting.from.number) {
-		ast_copy_string(pvt->options.cid_rdnis, c->redirecting.from.number, sizeof(pvt->options.cid_rdnis));
+	if (c->redirecting.from.number.valid && c->redirecting.from.number.str) {
+		ast_copy_string(pvt->options.cid_rdnis, c->redirecting.from.number.str, sizeof(pvt->options.cid_rdnis));
 	}
 
-	pvt->options.presentation = c->connected.id.number_presentation;
-	pvt->options.type_of_number = c->connected.id.number_type;
+	pvt->options.presentation = ast_party_id_presentation(c->connected.id);
+	pvt->options.type_of_number = c->connected.id.number.plan;
 
 	if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {
 		if (!strcasecmp(addr, "UNKNOWN"))
@@ -1080,17 +1082,19 @@ static struct ast_channel *__oh323_new(struct oh323_pvt *pvt, int state, const c
 
 		/* Don't use ast_set_callerid() here because it will
 		 * generate a needless NewCallerID event */
-		ch->cid.cid_ani = ast_strdup(cid_num);
+		ch->caller.ani = ast_strdup(cid_num);
 
 		if (pvt->cd.redirect_reason >= 0) {
-			ch->redirecting.from.number = ast_strdup(pvt->cd.redirect_number);
+			ch->redirecting.from.number.valid = 1;
+			ch->redirecting.from.number.str = ast_strdup(pvt->cd.redirect_number);
 			pbx_builtin_setvar_helper(ch, "PRIREDIRECTREASON", redirectingreason2str(pvt->cd.redirect_reason));
 		}
-		ch->cid.cid_pres = pvt->cd.presentation;
-		ch->cid.cid_ton = pvt->cd.type_of_number;
+		ch->caller.id.name.presentation = pvt->cd.presentation;
+		ch->caller.id.number.presentation = pvt->cd.presentation;
+		ch->caller.id.number.plan = pvt->cd.type_of_number;
 
 		if (!ast_strlen_zero(pvt->exten) && strcmp(pvt->exten, "s")) {
-			ch->cid.cid_dnid = ast_strdup(pvt->exten);
+			ch->dialed.number.str = ast_strdup(pvt->exten);
 		}
 		if (pvt->cd.transfer_capability >= 0)
 			ch->transfercapability = pvt->cd.transfer_capability;
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index e6bce413df8c6a572c04f921fa1f34d2e518484b..97752f63adcd83617b8b2308ae9fcbcd20f9d8c0 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -4938,8 +4938,8 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
 	if (pds.port)
 		sin.sin_port = htons(atoi(pds.port));
 
-	l = c->connected.id.number;
-	n = c->connected.id.name;
+	l = c->connected.id.number.valid ? c->connected.id.number.str : NULL;
+	n = c->connected.id.name.valid ? c->connected.id.name.str : NULL;
 
 	/* Now build request */	
 	memset(&ied, 0, sizeof(ied));
@@ -4957,16 +4957,17 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
 
 	if (l) {
 		iax_ie_append_str(&ied, IAX_IE_CALLING_NUMBER, l);
-		iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
+		iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES,
+			ast_party_id_presentation(&c->connected.id));
+	} else if (n) {
+		iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES,
+			ast_party_id_presentation(&c->connected.id));
 	} else {
-		if (n)
-			iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, c->connected.id.number_presentation);
-		else
-			iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
+		iax_ie_append_byte(&ied, IAX_IE_CALLINGPRES, AST_PRES_NUMBER_NOT_AVAILABLE);
 	}
 
-	iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->connected.id.number_type);
-	iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->cid.cid_tns);
+	iax_ie_append_byte(&ied, IAX_IE_CALLINGTON, c->connected.id.number.plan);
+	iax_ie_append_short(&ied, IAX_IE_CALLINGTNS, c->dialed.transit_network_select);
 
 	if (n)
 		iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, n);
@@ -4975,10 +4976,13 @@ static int iax2_call(struct ast_channel *c, char *dest, int timeout)
 
 	if (!ast_strlen_zero(c->language))
 		iax_ie_append_str(&ied, IAX_IE_LANGUAGE, c->language);
-	if (!ast_strlen_zero(c->cid.cid_dnid))
-		iax_ie_append_str(&ied, IAX_IE_DNID, c->cid.cid_dnid);
-	if (!ast_strlen_zero(c->redirecting.from.number))
-		iax_ie_append_str(&ied, IAX_IE_RDNIS, c->redirecting.from.number);
+	if (!ast_strlen_zero(c->dialed.number.str)) {
+		iax_ie_append_str(&ied, IAX_IE_DNID, c->dialed.number.str);
+	}
+	if (c->redirecting.from.number.valid
+		&& !ast_strlen_zero(c->redirecting.from.number.str)) {
+		iax_ie_append_str(&ied, IAX_IE_RDNIS, c->redirecting.from.number.str);
+	}
 
 	if (pds.context)
 		iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, pds.context);
@@ -5599,15 +5603,18 @@ static struct ast_channel *ast_iax2_new(int callno, int state, format_t capabili
 		ast_string_field_set(tmp, parkinglot, i->parkinglot);
 	/* Don't use ast_set_callerid() here because it will
 	 * generate a NewCallerID event before the NewChannel event */
-	if (!ast_strlen_zero(i->ani))
-		tmp->cid.cid_ani = ast_strdup(i->ani);
-	else
-		tmp->cid.cid_ani = ast_strdup(i->cid_num);
-	tmp->cid.cid_dnid = ast_strdup(i->dnid);
-	tmp->redirecting.from.number = ast_strdup(i->rdnis);
-	tmp->cid.cid_pres = i->calling_pres;
-	tmp->cid.cid_ton = i->calling_ton;
-	tmp->cid.cid_tns = i->calling_tns;
+	if (!ast_strlen_zero(i->ani)) {
+		tmp->caller.ani = ast_strdup(i->ani);
+	} else {
+		tmp->caller.ani = ast_strdup(i->cid_num);
+	}
+	tmp->dialed.number.str = ast_strdup(i->dnid);
+	tmp->redirecting.from.number.valid = 1;
+	tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
+	tmp->caller.id.name.presentation = i->calling_pres;
+	tmp->caller.id.number.presentation = i->calling_pres;
+	tmp->caller.id.number.plan = i->calling_ton;
+	tmp->dialed.transit_network_select = i->calling_tns;
 	if (!ast_strlen_zero(i->language))
 		ast_string_field_set(tmp, language, i->language);
 	if (!ast_strlen_zero(i->accountcode))
@@ -11321,16 +11328,21 @@ immediatedial:
 
 		/* Initialize defaults */
 		ast_party_connected_line_init(&connected);
-		connected.id.number_presentation = iaxs[fr->callno]->calling_pres;
+		connected.id.number.presentation = iaxs[fr->callno]->calling_pres;
+		connected.id.name.presentation = iaxs[fr->callno]->calling_pres;
 
 		if (!ast_connected_line_parse_data(f.data.ptr, f.datalen, &connected)) {
-			ast_string_field_set(iaxs[fr->callno], cid_num, connected.id.number);
-			ast_string_field_set(iaxs[fr->callno], cid_name, connected.id.name);
-			iaxs[fr->callno]->calling_pres = connected.id.number_presentation;
+			ast_string_field_set(iaxs[fr->callno], cid_num, connected.id.number.str);
+			ast_string_field_set(iaxs[fr->callno], cid_name, connected.id.name.str);
+			iaxs[fr->callno]->calling_pres = ast_party_id_presentation(&connected.id);
 
 			if (iaxs[fr->callno]->owner) {
-				ast_set_callerid(iaxs[fr->callno]->owner, S_OR(connected.id.number, ""), S_OR(connected.id.name, ""), NULL);
-				iaxs[fr->callno]->owner->cid.cid_pres = connected.id.number_presentation;
+				ast_set_callerid(iaxs[fr->callno]->owner,
+					S_COR(connected.id.number.valid, connected.id.number.str, ""),
+					S_COR(connected.id.name.valid, connected.id.name.str, ""),
+					NULL);
+				iaxs[fr->callno]->owner->caller.id.number.presentation = connected.id.number.presentation;
+				iaxs[fr->callno]->owner->caller.id.name.presentation = connected.id.name.presentation;
 			}
 		}
 		ast_party_connected_line_free(&connected);
diff --git a/channels/chan_jingle.c b/channels/chan_jingle.c
index 560d3ec1744a3cb09003b2814249fd55b31b54c2..d57644cb131344ea91b4213a78ffd3c615fa376f 100644
--- a/channels/chan_jingle.c
+++ b/channels/chan_jingle.c
@@ -853,7 +853,8 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *
 
 	tmp->callgroup = client->callgroup;
 	tmp->pickupgroup = client->pickupgroup;
-	tmp->cid.cid_pres = client->callingpres;
+	tmp->caller.id.name.presentation = client->callingpres;
+	tmp->caller.id.number.presentation = client->callingpres;
 	if (!ast_strlen_zero(client->accountcode))
 		ast_string_field_set(tmp, accountcode, client->accountcode);
 	if (client->amaflags)
@@ -867,9 +868,10 @@ static struct ast_channel *jingle_new(struct jingle *client, struct jingle_pvt *
 	ast_copy_string(tmp->exten, i->exten, sizeof(tmp->exten));
 	/* Don't use ast_set_callerid() here because it will
 	 * generate an unnecessary NewCallerID event  */
-	tmp->cid.cid_ani = ast_strdup(i->cid_num);
-	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
-		tmp->cid.cid_dnid = ast_strdup(i->exten);
+	tmp->caller.ani = ast_strdup(i->cid_num);
+	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
+		tmp->dialed.number.str = ast_strdup(i->exten);
+	}
 	tmp->priority = 1;
 	if (i->rtp)
 		ast_jb_configure(tmp, &global_jbconf);
diff --git a/channels/chan_local.c b/channels/chan_local.c
index c3723947e72ea5f6ad6591860d52e538f2b4e148..36dcc94c9f74d150e77889fac61d93c5a1154c7a 100644
--- a/channels/chan_local.c
+++ b/channels/chan_local.c
@@ -457,11 +457,11 @@ static int local_indicate(struct ast_channel *ast, int condition, const void *da
 			unsigned char frame_data[1024];
 			if (condition == AST_CONTROL_CONNECTED_LINE) {
 				if (isoutbound) {
-					ast_connected_line_copy_to_caller(&the_other_channel->cid, &this_channel->connected);
+					ast_connected_line_copy_to_caller(&the_other_channel->caller, &this_channel->connected);
 				}
-				f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected);
+				f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data), &this_channel->connected, NULL);
 			} else {
-				f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting);
+				f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data), &this_channel->redirecting, NULL);
 			}
 			f.subclass.integer = condition;
 			f.data.ptr = frame_data;
@@ -604,18 +604,10 @@ start_over:
 	 */
 	ast_party_redirecting_copy(&p->chan->redirecting, &p->owner->redirecting);
 
-	ast_free(p->chan->cid.cid_dnid);
-	p->chan->cid.cid_dnid = ast_strdup(p->owner->cid.cid_dnid);
-	if (!p->chan->cid.cid_dnid && p->owner->cid.cid_dnid) {
-		/* Allocation failure */
-		ast_mutex_unlock(&p->lock);
-		ast_channel_unlock(p->chan);
-		return -1;
-	}
-	p->chan->cid.cid_tns = p->owner->cid.cid_tns;
+	ast_party_dialed_copy(&p->chan->dialed, &p->owner->dialed);
 
-	ast_connected_line_copy_to_caller(&p->chan->cid, &p->owner->connected);
-	ast_connected_line_copy_from_caller(&p->chan->connected, &p->owner->cid);
+	ast_connected_line_copy_to_caller(&p->chan->caller, &p->owner->connected);
+	ast_connected_line_copy_from_caller(&p->chan->connected, &p->owner->caller);
 
 	ast_string_field_set(p->chan, language, p->owner->language);
 	ast_string_field_set(p->chan, accountcode, p->owner->accountcode);
@@ -624,7 +616,8 @@ start_over:
 
 	ast_channel_cc_params_init(p->chan, ast_channel_get_cc_config_params(p->owner));
 
-	if (!ast_exists_extension(NULL, p->chan->context, p->chan->exten, 1, p->owner->cid.cid_num)) {
+	if (!ast_exists_extension(NULL, p->chan->context, p->chan->exten, 1,
+		S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL))) {
 		ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n", p->chan->exten, p->chan->context);
 		ast_mutex_unlock(&p->lock);
 		ast_channel_unlock(p->chan);
diff --git a/channels/chan_mgcp.c b/channels/chan_mgcp.c
index 63dcb936d665176047869ba1c9c4041798157cd8..b0bd1cc9740dd323e018b00cfffdc7adc813eadc 100644
--- a/channels/chan_mgcp.c
+++ b/channels/chan_mgcp.c
@@ -898,7 +898,9 @@ static int mgcp_call(struct ast_channel *ast, char *dest, int timeout)
 			transmit_modify_request(sub->next);
 		}
 
-		transmit_notify_request_with_callerid(sub, tone, ast->connected.id.number, ast->connected.id.name);
+		transmit_notify_request_with_callerid(sub, tone,
+			S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
+			S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""));
 		ast_setstate(ast, AST_STATE_RINGING);
 
 		if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {
@@ -918,6 +920,7 @@ static int mgcp_hangup(struct ast_channel *ast)
 {
 	struct mgcp_subchannel *sub = ast->tech_pvt;
 	struct mgcp_endpoint *p = sub->parent;
+	struct ast_channel *bridged;
 
 	ast_debug(1, "mgcp_hangup(%s)\n", ast->name);
 	if (!ast->tech_pvt) {
@@ -967,7 +970,10 @@ static int mgcp_hangup(struct ast_channel *ast)
 		if (p->hookstate == MGCP_OFFHOOK) {
 			if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
 				/* ncs fix! */
-				transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"), ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
+				bridged = ast_bridged_channel(sub->next->owner);
+				transmit_notify_request_with_callerid(p->sub, (p->ncs ? "L/wt1" : "L/wt"),
+					S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
+					S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
 			}
 		} else {
 			/* set our other connection as the primary and swith over to it */
@@ -975,7 +981,10 @@ static int mgcp_hangup(struct ast_channel *ast)
 			p->sub->cxmode = MGCP_CX_RECVONLY;
 			transmit_modify_request(p->sub);
 			if (sub->next->owner && ast_bridged_channel(sub->next->owner)) {
-				transmit_notify_request_with_callerid(p->sub, "L/rg", ast_bridged_channel(sub->next->owner)->cid.cid_num, ast_bridged_channel(sub->next->owner)->cid.cid_name);
+				bridged = ast_bridged_channel(sub->next->owner);
+				transmit_notify_request_with_callerid(p->sub, "L/rg",
+					S_COR(bridged->caller.id.number.valid, bridged->caller.id.number.str, ""),
+					S_COR(bridged->caller.id.name.valid, bridged->caller.id.name.str, ""));
 			}
 		}
 
@@ -1524,7 +1533,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state, cons
 
 		/* Don't use ast_set_callerid() here because it will
 		 * generate a needless NewCallerID event */
-		tmp->cid.cid_ani = ast_strdup(i->cid_num);
+		tmp->caller.ani = ast_strdup(i->cid_num);
 
 		if (!i->adsi) {
 			tmp->adsicpe = AST_ADSI_UNAVAILABLE;
@@ -2988,12 +2997,12 @@ static void *mgcp_ss(void *data)
 					/*res = tone_zone_play_tone(p->subs[index].zfd, -1);*/
 					ast_indicate(chan, -1);
 					ast_copy_string(chan->exten, p->dtmf_buf, sizeof(chan->exten));
-					chan->cid.cid_dnid = ast_strdup(p->dtmf_buf);
+					chan->dialed.number.str = ast_strdup(p->dtmf_buf);
 					memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
 					ast_set_callerid(chan,
 						p->hidecallerid ? "" : p->cid_num,
 						p->hidecallerid ? "" : p->cid_name,
-						chan->cid.cid_ani ? NULL : p->cid_num);
+						chan->caller.ani ? NULL : p->cid_num);
 					ast_setstate(chan, AST_STATE_RING);
 					/*dahdi_enable_ec(p);*/
 					if (p->dtmfmode & MGCP_DTMF_HYBRID) {
@@ -3121,9 +3130,12 @@ static void *mgcp_ss(void *data)
 			len = 0;
 			memset(p->dtmf_buf, 0, sizeof(p->dtmf_buf));
 			timeout = firstdigittimeout;
-		} else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1, chan->cid.cid_num) &&
-				((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
-			ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
+		} else if (!ast_canmatch_extension(chan, chan->context, p->dtmf_buf, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+			&& ((p->dtmf_buf[0] != '*') || (strlen(p->dtmf_buf) > 2))) {
+			ast_debug(1, "Can't match %s from '%s' in context %s\n", p->dtmf_buf,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<Unknown Caller>"),
+				chan->context);
 			break;
 		}
 		if (!timeout)
diff --git a/channels/chan_misdn.c b/channels/chan_misdn.c
index cddfd65cc70cb5728099e2db13ccde53280ff10d..7e1f14af7f6b331fd0e2d85683d069e5ff216245 100644
--- a/channels/chan_misdn.c
+++ b/channels/chan_misdn.c
@@ -4121,8 +4121,10 @@ static void print_bc_info(int fd, struct chan_list *help, struct misdn_bchannel
 		bc->nt ? "NT" : "TE",
 		help->originator == ORG_AST ? "*" : "I",
 		ast ? ast->exten : "",
-		(ast && ast->cid.cid_name) ? ast->cid.cid_name : "",
-		(ast && ast->cid.cid_num) ? ast->cid.cid_num : "",
+		(ast && ast->caller.id.name.valid && ast->caller.id.name.str)
+			? ast->caller.id.name.str : "",
+		(ast && ast->caller.id.number.valid && ast->caller.id.number.str)
+			? ast->caller.id.number.str : "",
 		bc->redirecting.from.name,
 		bc->redirecting.from.number,
 		bc->redirecting.to.name,
@@ -4216,13 +4218,15 @@ static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, st
 					" --> hold_channel: %d\n",
 					help->l3id,
 					ast->exten,
-					ast->cid.cid_name ? ast->cid.cid_name : "",
-					ast->cid.cid_num ? ast->cid.cid_num : "",
+					S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
+					S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
 					help->hold.port,
 					help->hold.channel
 					);
 			} else {
-				ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n", ast->exten, ast->cid.cid_num);
+				ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
+					ast->exten,
+					S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""));
 			}
 		}
 	}
@@ -5706,12 +5710,12 @@ static void update_config(struct chan_list *ch)
 	chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
 
 	if (pres < 0 || screen < 0) {
-		chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number_presentation);
+		chan_misdn_log(2, port, " --> pres: %x\n", ast->connected.id.number.presentation);
 
-		bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
+		bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number.presentation);
 		chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
 
-		bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
+		bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number.presentation);
 		chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
 	} else {
 		bc->caller.screening = screen;
@@ -6014,16 +6018,20 @@ static int read_config(struct chan_list *ch)
 static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
 {
 	struct ast_party_connected_line connected;
+	struct ast_set_party_connected_line update_connected;
 
 	ast_party_connected_line_init(&connected);
-	connected.id.number = (char *) id->number;
-	connected.id.number_type = misdn_to_ast_ton(id->number_type)
+	memset(&update_connected, 0, sizeof(update_connected));
+	update_connected.id.number = 1;
+	connected.id.number.valid = 1;
+	connected.id.number.str = (char *) id->number;
+	connected.id.number.plan = misdn_to_ast_ton(id->number_type)
 		| misdn_to_ast_plan(id->number_plan);
-	connected.id.number_presentation = misdn_to_ast_pres(id->presentation)
+	connected.id.number.presentation = misdn_to_ast_pres(id->presentation)
 		| misdn_to_ast_screen(id->screening);
 	connected.id.tag = cid_tag;
 	connected.source = source;
-	ast_channel_queue_connected_line_update(ast, &connected);
+	ast_channel_queue_connected_line_update(ast, &connected, &update_connected);
 }
 
 /*!
@@ -6043,16 +6051,26 @@ static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchan
 	if (originator == ORG_MISDN) {
 		/* ORIGINATOR MISDN (incoming call) */
 
-		ast_copy_string(bc->connected.name, S_OR(ast->connected.id.name, ""), sizeof(bc->connected.name));
-		ast_copy_string(bc->connected.number, S_OR(ast->connected.id.number, ""), sizeof(bc->connected.number));
-		bc->connected.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
-		bc->connected.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
+		ast_copy_string(bc->connected.name,
+			S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+			sizeof(bc->connected.name));
+		if (ast->connected.id.number.valid) {
+			ast_copy_string(bc->connected.number, S_OR(ast->connected.id.number.str, ""),
+				sizeof(bc->connected.number));
+			bc->connected.presentation = ast_to_misdn_pres(ast->connected.id.number.presentation);
+			bc->connected.screening = ast_to_misdn_screen(ast->connected.id.number.presentation);
+			bc->connected.number_type = ast_to_misdn_ton(ast->connected.id.number.plan);
+			bc->connected.number_plan = ast_to_misdn_plan(ast->connected.id.number.plan);
+		} else {
+			bc->connected.number[0] = '\0';
+			bc->connected.presentation = 0;/* Allowed */
+			bc->connected.screening = 0;/* Unscreened */
+			bc->connected.number_type = NUMTYPE_UNKNOWN;
+			bc->connected.number_plan = NUMPLAN_UNKNOWN;
+		}
 
 		misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
-		if (number_type < 0) {
-			bc->connected.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
-			bc->connected.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
-		} else {
+		if (0 <= number_type) {
 			/* Force us to send in CONNECT message */
 			bc->connected.number_type = number_type;
 			bc->connected.number_plan = NUMPLAN_ISDN;
@@ -6061,16 +6079,26 @@ static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchan
 	} else {
 		/* ORIGINATOR Asterisk (outgoing call) */
 
-		ast_copy_string(bc->caller.name, S_OR(ast->connected.id.name, ""), sizeof(bc->caller.name));
-		ast_copy_string(bc->caller.number, S_OR(ast->connected.id.number, ""), sizeof(bc->caller.number));
-		bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number_presentation);
-		bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number_presentation);
+		ast_copy_string(bc->caller.name,
+			S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+			sizeof(bc->caller.name));
+		if (ast->connected.id.number.valid) {
+			ast_copy_string(bc->caller.number, S_OR(ast->connected.id.number.str, ""),
+				sizeof(bc->caller.number));
+			bc->caller.presentation = ast_to_misdn_pres(ast->connected.id.number.presentation);
+			bc->caller.screening = ast_to_misdn_screen(ast->connected.id.number.presentation);
+			bc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number.plan);
+			bc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number.plan);
+		} else {
+			bc->caller.number[0] = '\0';
+			bc->caller.presentation = 0;/* Allowed */
+			bc->caller.screening = 0;/* Unscreened */
+			bc->caller.number_type = NUMTYPE_UNKNOWN;
+			bc->caller.number_plan = NUMPLAN_UNKNOWN;
+		}
 
 		misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
-		if (number_type < 0) {
-			bc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
-			bc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
-		} else {
+		if (0 <= number_type) {
 			/* Force us to send in SETUP message */
 			bc->caller.number_type = number_type;
 			bc->caller.number_plan = NUMPLAN_ISDN;
@@ -6150,19 +6178,41 @@ static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bc
  */
 static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
 {
-	ast_copy_string(bc->redirecting.from.name, S_OR(ast->redirecting.from.name, ""), sizeof(bc->redirecting.from.name));
-	ast_copy_string(bc->redirecting.from.number, S_OR(ast->redirecting.from.number, ""), sizeof(bc->redirecting.from.number));
-	bc->redirecting.from.presentation = ast_to_misdn_pres(ast->redirecting.from.number_presentation);
-	bc->redirecting.from.screening = ast_to_misdn_screen(ast->redirecting.from.number_presentation);
-	bc->redirecting.from.number_type = ast_to_misdn_ton(ast->redirecting.from.number_type);
-	bc->redirecting.from.number_plan = ast_to_misdn_plan(ast->redirecting.from.number_type);
-
-	ast_copy_string(bc->redirecting.to.name, S_OR(ast->redirecting.to.name, ""), sizeof(bc->redirecting.to.name));
-	ast_copy_string(bc->redirecting.to.number, S_OR(ast->redirecting.to.number, ""), sizeof(bc->redirecting.to.number));
-	bc->redirecting.to.presentation = ast_to_misdn_pres(ast->redirecting.to.number_presentation);
-	bc->redirecting.to.screening = ast_to_misdn_screen(ast->redirecting.to.number_presentation);
-	bc->redirecting.to.number_type = ast_to_misdn_ton(ast->redirecting.to.number_type);
-	bc->redirecting.to.number_plan = ast_to_misdn_plan(ast->redirecting.to.number_type);
+	ast_copy_string(bc->redirecting.from.name,
+		S_COR(ast->redirecting.from.name.valid, ast->redirecting.from.name.str, ""),
+		sizeof(bc->redirecting.from.name));
+	if (ast->redirecting.from.number.valid) {
+		ast_copy_string(bc->redirecting.from.number, S_OR(ast->redirecting.from.number.str, ""),
+			sizeof(bc->redirecting.from.number));
+		bc->redirecting.from.presentation = ast_to_misdn_pres(ast->redirecting.from.number.presentation);
+		bc->redirecting.from.screening = ast_to_misdn_screen(ast->redirecting.from.number.presentation);
+		bc->redirecting.from.number_type = ast_to_misdn_ton(ast->redirecting.from.number.plan);
+		bc->redirecting.from.number_plan = ast_to_misdn_plan(ast->redirecting.from.number.plan);
+	} else {
+		bc->redirecting.from.number[0] = '\0';
+		bc->redirecting.from.presentation = 0;/* Allowed */
+		bc->redirecting.from.screening = 0;/* Unscreened */
+		bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
+		bc->redirecting.from.number_plan = NUMPLAN_UNKNOWN;
+	}
+
+	ast_copy_string(bc->redirecting.to.name,
+		S_COR(ast->redirecting.to.name.valid, ast->redirecting.to.name.str, ""),
+		sizeof(bc->redirecting.to.name));
+	if (ast->redirecting.to.number.valid) {
+		ast_copy_string(bc->redirecting.to.number, S_OR(ast->redirecting.to.number.str, ""),
+			sizeof(bc->redirecting.to.number));
+		bc->redirecting.to.presentation = ast_to_misdn_pres(ast->redirecting.to.number.presentation);
+		bc->redirecting.to.screening = ast_to_misdn_screen(ast->redirecting.to.number.presentation);
+		bc->redirecting.to.number_type = ast_to_misdn_ton(ast->redirecting.to.number.plan);
+		bc->redirecting.to.number_plan = ast_to_misdn_plan(ast->redirecting.to.number.plan);
+	} else {
+		bc->redirecting.to.number[0] = '\0';
+		bc->redirecting.to.presentation = 0;/* Allowed */
+		bc->redirecting.to.screening = 0;/* Unscreened */
+		bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
+		bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
+	}
 
 	bc->redirecting.reason = ast_to_misdn_reason(ast->redirecting.reason);
 	bc->redirecting.count = ast->redirecting.count;
@@ -6181,23 +6231,29 @@ static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct as
 static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
 {
 	struct ast_party_redirecting redirecting;
+	struct ast_set_party_redirecting update_redirecting;
 
 	ast_party_redirecting_set_init(&redirecting, &ast->redirecting);
+	memset(&update_redirecting, 0, sizeof(update_redirecting));
 
-	redirecting.from.number = (char *) redirect->from.number;
-	redirecting.from.number_type =
+	update_redirecting.from.number = 1;
+	redirecting.from.number.valid = 1;
+	redirecting.from.number.str = (char *) redirect->from.number;
+	redirecting.from.number.plan =
 		misdn_to_ast_ton(redirect->from.number_type)
 		| misdn_to_ast_plan(redirect->from.number_plan);
-	redirecting.from.number_presentation =
+	redirecting.from.number.presentation =
 		misdn_to_ast_pres(redirect->from.presentation)
 		| misdn_to_ast_screen(redirect->from.screening);
 	redirecting.from.tag = tag;
 
-	redirecting.to.number = (char *) redirect->to.number;
-	redirecting.to.number_type =
+	update_redirecting.to.number = 1;
+	redirecting.to.number.valid = 1;
+	redirecting.to.number.str = (char *) redirect->to.number;
+	redirecting.to.number.plan =
 		misdn_to_ast_ton(redirect->to.number_type)
 		| misdn_to_ast_plan(redirect->to.number_plan);
-	redirecting.to.number_presentation =
+	redirecting.to.number.presentation =
 		misdn_to_ast_pres(redirect->to.presentation)
 		| misdn_to_ast_screen(redirect->to.screening);
 	redirecting.to.tag = tag;
@@ -6205,7 +6261,7 @@ static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct
 	redirecting.reason = misdn_to_ast_reason(redirect->reason);
 	redirecting.count = redirect->count;
 
-	ast_channel_set_redirecting(ast, &redirecting);
+	ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
 }
 
 /*!
@@ -6393,12 +6449,16 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
 		ast_copy_string(ast->exten, args.ext, sizeof(ast->exten));
 		ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
 
-		if (ast_strlen_zero(newbc->caller.name)	&& !ast_strlen_zero(ast->connected.id.name)) {
-			ast_copy_string(newbc->caller.name, ast->connected.id.name, sizeof(newbc->caller.name));
+		if (ast_strlen_zero(newbc->caller.name)
+			&& ast->connected.id.name.valid
+			&& !ast_strlen_zero(ast->connected.id.name.str)) {
+			ast_copy_string(newbc->caller.name, ast->connected.id.name.str, sizeof(newbc->caller.name));
 			chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
 		}
-		if (ast_strlen_zero(newbc->caller.number) && !ast_strlen_zero(ast->connected.id.number)) {
-			ast_copy_string(newbc->caller.number, ast->connected.id.number, sizeof(newbc->caller.number));
+		if (ast_strlen_zero(newbc->caller.number)
+			&& ast->connected.id.number.valid
+			&& !ast_strlen_zero(ast->connected.id.number.str)) {
+			ast_copy_string(newbc->caller.number, ast->connected.id.number.str, sizeof(newbc->caller.number));
 			chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
 		}
 
@@ -6408,12 +6468,17 @@ static int misdn_call(struct ast_channel *ast, char *dest, int timeout)
 			strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
 		}
 
-		ast->cid.cid_tag = ast_strdup(newbc->incoming_cid_tag);
+		ast->caller.id.tag = ast_strdup(newbc->incoming_cid_tag);
 
 		misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
 		if (number_type < 0) {
-			newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number_type);
-			newbc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number_type);
+			if (ast->connected.id.number.valid) {
+				newbc->caller.number_type = ast_to_misdn_ton(ast->connected.id.number.plan);
+				newbc->caller.number_plan = ast_to_misdn_plan(ast->connected.id.number.plan);
+			} else {
+				newbc->caller.number_type = NUMTYPE_UNKNOWN;
+				newbc->caller.number_plan = NUMPLAN_ISDN;
+			}
 		} else {
 			/* Force us to send in SETUP message */
 			newbc->caller.number_type = number_type;
@@ -6921,8 +6986,10 @@ static int misdn_hangup(struct ast_channel *ast)
 		bc->pid,
 		ast->context,
 		ast->exten,
-		ast->cid.cid_name ? ast->cid.cid_name : "",
-		ast->cid.cid_num ? ast->cid.cid_num : "",
+		(ast->caller.id.name.valid && ast->caller.id.name.str)
+			? ast->caller.id.name.str : "",
+		(ast->caller.id.number.valid && ast->caller.id.number.str)
+			? ast->caller.id.number.str : "",
 		misdn_get_ch_state(p));
 	chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
 	chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
@@ -7056,7 +7123,8 @@ static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame
  					char context_tmp[BUFFERSIZE];
  					misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
  					context = ast_strlen_zero(context_tmp) ? (ast_strlen_zero(ast->macrocontext) ? ast->context : ast->macrocontext) : context_tmp;
- 					if (ast_exists_extension(ast, context, "fax", 1, ast->cid.cid_num)) {
+					if (ast_exists_extension(ast, context, "fax", 1,
+						S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
  						ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast->name, context);
   						/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
   						pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast->exten);
@@ -7256,7 +7324,9 @@ static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
 		if (!ch->dropped_frame_cnt) {
 			chan_misdn_log(5, ch->bc->port,
 				"BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
-				frame->samples, ch->bc->addr, ast->exten, ast->cid.cid_num, misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
+				frame->samples, ch->bc->addr, ast->exten,
+				S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
+				misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
 		}
 
 		if (++ch->dropped_frame_cnt > 100) {
@@ -7871,7 +7941,7 @@ static struct ast_channel *misdn_new(struct chan_list *chlist, int state,  char
 		if (callerid) {
 			/* Don't use ast_set_callerid() here because it will
 			 * generate a needless NewCallerID event */
-			tmp->cid.cid_ani = ast_strdup(cid_num);
+			tmp->caller.ani = ast_strdup(cid_num);
 		}
 
 		if (pipe(chlist->pipe) < 0) {
@@ -8162,8 +8232,10 @@ static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
 			bc->pid,
 			ast->context,
 			ast->exten,
-			ast->cid.cid_name ? ast->cid.cid_name : "",
-			ast->cid.cid_num ? ast->cid.cid_num : "");
+			(ast->caller.id.name.valid && ast->caller.id.name.str)
+				? ast->caller.id.name.str : "",
+			(ast->caller.id.number.valid && ast->caller.id.number.str)
+				? ast->caller.id.number.str : "");
 
 		if (ast->_state != AST_STATE_RESERVED) {
 			chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
@@ -8313,8 +8385,10 @@ static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch,
 		"* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
 		ast->context,
 		ast->exten,
-		ast->cid.cid_name ? ast->cid.cid_name : "",
-		ast->cid.cid_num ? ast->cid.cid_num : "");
+		(ast->caller.id.name.valid && ast->caller.id.name.str)
+			? ast->caller.id.name.str : "",
+		(ast->caller.id.number.valid && ast->caller.id.number.str)
+			? ast->caller.id.number.str : "");
 
 	strcpy(ast->exten, "s");
 
@@ -8596,10 +8670,8 @@ static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *no
 		return;
 	}
 	chan->priority = notify->priority;
-	if (chan->cid.cid_dnid) {
-		ast_free(chan->cid.cid_dnid);
-	}
-	chan->cid.cid_dnid = ast_strdup(notify->exten);
+	ast_free(chan->dialed.number.str);
+	chan->dialed.number.str = ast_strdup(notify->exten);
 
 	if (ast_pbx_start(chan)) {
 		ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", chan->name);
@@ -8933,11 +9005,11 @@ static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel
 			bc->div_leg_3_rx_wanted = 0;
 
 			if (ch && ch->ast) {
-				ch->ast->redirecting.to.number_presentation =
+				ch->ast->redirecting.to.number.presentation =
 					bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
 					? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED
 					: AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
-				ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+				ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting, NULL);
 			}
 		}
 		break;
@@ -9790,12 +9862,12 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 		/* Update asterisk channel caller information */
 		chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
 		chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
-		chan->cid.cid_ton = misdn_to_ast_ton(bc->caller.number_type)
+		chan->caller.id.number.plan = misdn_to_ast_ton(bc->caller.number_type)
 			| misdn_to_ast_plan(bc->caller.number_plan);
 
 		chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
 		chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
-		chan->cid.cid_pres = misdn_to_ast_pres(bc->caller.presentation)
+		chan->caller.id.number.presentation = misdn_to_ast_pres(bc->caller.presentation)
 			| misdn_to_ast_screen(bc->caller.screening);
 
 		ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
@@ -9807,7 +9879,7 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 		}
 
 		ast_channel_lock(chan);
-		chan->cid.cid_tag = ast_strdup(bc->incoming_cid_tag);
+		chan->caller.id.tag = ast_strdup(bc->incoming_cid_tag);
 		ast_channel_unlock(chan);
 
 		if (!ast_strlen_zero(bc->redirecting.from.number)) {
@@ -10108,9 +10180,9 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 			bc->div_leg_3_rx_wanted = 0;
 
 			if (ch->ast) {
-				ch->ast->redirecting.to.number_presentation =
+				ch->ast->redirecting.to.number.presentation =
 					AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
-				ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+				ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting, NULL);
 			}
 		}
 #endif	/* defined(AST_MISDN_ENHANCEMENTS) */
@@ -10544,7 +10616,8 @@ cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
 						break;
 					}
 					misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
-					ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting);
+					ast_channel_queue_redirecting_update(ch->ast, &ch->ast->redirecting,
+						NULL);
 				}
 			}
 			break;
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index aea48730f62687e9a02686548e0d8e372b331a1a..b2776850db84192fadbfbaa40cdf5c66a1e51bfc 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -602,7 +602,11 @@ static int oss_call(struct ast_channel *c, char *dest, int timeout)
 	AST_NONSTANDARD_APP_ARGS(args, parse, '/');
 
 	ast_verbose(" << Call to device '%s' dnid '%s' rdnis '%s' on console from '%s' <%s> >>\n",
-		dest, c->cid.cid_dnid, c->redirecting.from.number, c->cid.cid_name, c->cid.cid_num);
+		dest,
+		S_OR(c->dialed.number.str, ""),
+		S_COR(c->redirecting.from.number.valid, c->redirecting.from.number.str, ""),
+		S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
+		S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""));
 	if (!ast_strlen_zero(args.flags) && strcasecmp(args.flags, "answer") == 0) {
 		f.subclass.integer = AST_CONTROL_ANSWER;
 		ast_queue_frame(c, &f);
@@ -803,9 +807,10 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
 		ast_string_field_set(c, language, o->language);
 	/* Don't use ast_set_callerid() here because it will
 	 * generate a needless NewCallerID event */
-	c->cid.cid_ani = ast_strdup(o->cid_num);
-	if (!ast_strlen_zero(ext))
-		c->cid.cid_dnid = ast_strdup(ext);
+	c->caller.ani = ast_strdup(o->cid_num);
+	if (!ast_strlen_zero(ext)) {
+		c->dialed.number.str = ast_strdup(ext);
+	}
 
 	o->owner = c;
 	ast_module_ref(ast_module_info->self);
@@ -1181,9 +1186,10 @@ static char *console_transfer(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 	tmp = ast_ext_ctx(a->argv[2], &ext, &ctx);
 	if (ctx == NULL)			/* supply default context if needed */
 		ctx = o->owner->context;
-	if (!ast_exists_extension(b, ctx, ext, 1, b->cid.cid_num))
+	if (!ast_exists_extension(b, ctx, ext, 1,
+		S_COR(b->caller.id.number.valid, b->caller.id.number.str, NULL))) {
 		ast_cli(a->fd, "No such extension exists\n");
-	else {
+	} else {
 		ast_cli(a->fd, "Whee, transferring %s to %s@%s.\n", b->name, ext, ctx);
 		if (ast_async_goto(b, ctx, ext, 1))
 			ast_cli(a->fd, "Failed to transfer :(\n");
diff --git a/channels/chan_phone.c b/channels/chan_phone.c
index 389f30401415e83869b8b0e0e083d5af760b4c66..18eaf8fa1df35501eee5b1c92c8a70974de79065 100644
--- a/channels/chan_phone.c
+++ b/channels/chan_phone.c
@@ -303,13 +303,16 @@ static int phone_call(struct ast_channel *ast, char *dest, int timeout)
 		snprintf(cid.min, sizeof(cid.min),     "%02d", tm.tm_min);
 	}
 	/* the standard format of ast->callerid is:  "name" <number>, but not always complete */
-	if (ast_strlen_zero(ast->connected.id.name))
+	if (!ast->connected.id.name.valid
+		|| ast_strlen_zero(ast->connected.id.name.str)) {
 		strcpy(cid.name, DEFAULT_CALLER_ID);
-	else
-		ast_copy_string(cid.name, ast->connected.id.name, sizeof(cid.name));
+	} else {
+		ast_copy_string(cid.name, ast->connected.id.name.str, sizeof(cid.name));
+	}
 
-	if (ast->connected.id.number) 
-		ast_copy_string(cid.number, ast->connected.id.number, sizeof(cid.number));
+	if (ast->connected.id.number.valid && ast->connected.id.number.str) {
+		ast_copy_string(cid.number, ast->connected.id.number.str, sizeof(cid.number));
+	}
 
 	p = ast->tech_pvt;
 
@@ -885,7 +888,7 @@ static struct ast_channel *phone_new(struct phone_pvt *i, int state, char *cntx,
 
 		/* Don't use ast_set_callerid() here because it will
 		 * generate a NewCallerID event before the NewChannel event */
-		tmp->cid.cid_ani = ast_strdup(i->cid_num);
+		tmp->caller.ani = ast_strdup(i->cid_num);
 
 		i->owner = tmp;
 		ast_module_ref(ast_module_info->self);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 5d6d2f1989ba30bc9772e0b2b76835992b949db4..8dc4c5dbe14ca64810d4481a9c483f70d09b90f4 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -1457,7 +1457,6 @@ static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewl
 static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout);
 static void update_connectedline(struct sip_pvt *p, const void *data, size_t datalen);
 static void update_redirecting(struct sip_pvt *p, const void *data, size_t datalen);
-static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward);
 static int get_domain(const char *str, char *domain, int len);
 static void get_realm(struct sip_pvt *p, const struct sip_request *req);
 
@@ -5073,7 +5072,7 @@ static int sip_call(struct ast_channel *ast, char *dest, int timeout)
 		ast->hangupcause = AST_CAUSE_USER_BUSY;
 		return res;
 	}
-	p->callingpres = ast->cid.cid_pres;
+	p->callingpres = ast_party_id_presentation(&ast->caller.id);
 	p->jointcapability = ast_rtp_instance_available_formats(p->rtp, p->capability, p->prefcodec);
 	p->jointnoncodeccapability = p->noncodeccapability;
 
@@ -6390,7 +6389,7 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
 	ast_channel_lock(tmp);
 	sip_pvt_lock(i);
 	ast_channel_cc_params_init(tmp, i->cc_params);
-	tmp->cid.cid_tag = ast_strdup(i->cid_tag);
+	tmp->caller.id.tag = ast_strdup(i->cid_tag);
 	ast_channel_unlock(tmp);
 
 	tmp->tech = ( ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INFO || ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_SHORTINFO) ?  &sip_tech_info : &sip_tech;
@@ -6491,7 +6490,8 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
 
 	tmp->callgroup = i->callgroup;
 	tmp->pickupgroup = i->pickupgroup;
-	tmp->cid.cid_pres = i->callingpres;
+	tmp->caller.id.name.presentation = i->callingpres;
+	tmp->caller.id.number.presentation = i->callingpres;
 	if (!ast_strlen_zero(i->parkinglot))
 		ast_string_field_set(tmp, parkinglot, i->parkinglot);
 	if (!ast_strlen_zero(i->accountcode))
@@ -6513,12 +6513,15 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
 
 	/* Don't use ast_set_callerid() here because it will
 	 * generate an unnecessary NewCallerID event  */
-	tmp->cid.cid_ani = ast_strdup(i->cid_num);
-	if (!ast_strlen_zero(i->rdnis))
-		tmp->redirecting.from.number = ast_strdup(i->rdnis);
-	
-	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s"))
-		tmp->cid.cid_dnid = ast_strdup(i->exten);
+	tmp->caller.ani = ast_strdup(i->cid_num);
+	if (!ast_strlen_zero(i->rdnis)) {
+		tmp->redirecting.from.number.valid = 1;
+		tmp->redirecting.from.number.str = ast_strdup(i->rdnis);
+	}
+
+	if (!ast_strlen_zero(i->exten) && strcmp(i->exten, "s")) {
+		tmp->dialed.number.str = ast_strdup(i->exten);
+	}
 
 	tmp->priority = 1;
 	if (!ast_strlen_zero(i->uri))
@@ -6817,7 +6820,8 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
 		if (strcmp(ast->exten, "fax")) {
 			const char *target_context = S_OR(ast->macrocontext, ast->context);
 			ast_channel_unlock(ast);
-			if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+			if (ast_exists_extension(ast, target_context, "fax", 1,
+				S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, NULL))) {
 				ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to CNG detection\n", ast->name);
 				pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
 				if (ast_async_goto(ast, target_context, "fax", 1)) {
@@ -6826,11 +6830,11 @@ static struct ast_frame *sip_read(struct ast_channel *ast)
 				fr = &ast_null_frame;
 			} else {
 				ast_log(LOG_NOTICE, "FAX CNG detected but no fax extension\n");
-                        }
+			}
 		} else {
 			ast_channel_unlock(ast);
-                }
-        }
+		}
+	}
 
 	/* Only allow audio through if they sent progress with SDP, or if the channel is actually answered */
 	if (fr && fr->frametype == AST_FRAME_VOICE && p->invitestate != INV_EARLY_MEDIA && ast->_state != AST_STATE_UP) {
@@ -8228,7 +8232,8 @@ static int process_sdp(struct sip_pvt *p, struct sip_request *req, int t38action
 					if (strcmp(p->owner->exten, "fax")) {
 						const char *target_context = S_OR(p->owner->macrocontext, p->owner->context);
 						ast_channel_unlock(p->owner);
-						if (ast_exists_extension(p->owner, target_context, "fax", 1, p->owner->cid.cid_num)) {
+						if (ast_exists_extension(p->owner, target_context, "fax", 1,
+							S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL))) {
 							ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to peer T.38 re-INVITE\n", p->owner->name);
 							pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten);
 							if (ast_async_goto(p->owner, target_context, "fax", 1)) {
@@ -9691,11 +9696,15 @@ static int add_rpid(struct sip_request *req, struct sip_pvt *p)
 		return 0;
 	}
 
-	if (p->owner && p->owner->connected.id.number)
-		lid_num = p->owner->connected.id.number;
-	if (p->owner && p->owner->connected.id.name)
-		lid_name = p->owner->connected.id.name;
-	lid_pres = (p->owner) ? p->owner->connected.id.number_presentation : AST_PRES_NUMBER_NOT_AVAILABLE;
+	if (p->owner && p->owner->connected.id.number.valid
+		&& p->owner->connected.id.number.str) {
+		lid_num = p->owner->connected.id.number.str;
+	}
+	if (p->owner && p->owner->connected.id.name.valid
+		&& p->owner->connected.id.name.str) {
+		lid_name = p->owner->connected.id.name.str;
+	}
+	lid_pres = (p->owner) ? ast_party_id_presentation(&p->owner->connected.id) : AST_PRES_NUMBER_NOT_AVAILABLE;
 
 	if (ast_strlen_zero(lid_num))
 		return 0;
@@ -10700,14 +10709,16 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
 	snprintf(p->lastmsg, sizeof(p->lastmsg), "Init: %s", sip_methods[sipmethod].text);
 
 	d = S_OR(p->fromdomain, ast_sockaddr_stringify_host(&p->ourip));
-	if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
-		l = p->owner->connected.id.number;
-		n = p->owner->connected.id.name;
-	} else if (p->owner && (p->owner->connected.id.number_presentation & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED && (!ast_test_flag(&p->flags[0], SIP_SENDRPID))) {
-		/* if we are not sending RPID and user wants his callerid restricted */		
-		l = CALLERID_UNKNOWN;
-		n = l;
-		d = FROMDOMAIN_INVALID;
+	if (p->owner) {
+		if ((ast_party_id_presentation(&p->owner->connected.id) & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
+			l = p->owner->connected.id.number.valid ? p->owner->connected.id.number.str : NULL;
+			n = p->owner->connected.id.name.valid ? p->owner->connected.id.name.str : NULL;
+		} else if (!ast_test_flag(&p->flags[0], SIP_SENDRPID)) {
+			/* if we are not sending RPID and user wants his callerid restricted */		
+			l = CALLERID_UNKNOWN;
+			n = l;
+			d = FROMDOMAIN_INVALID;
+		}
 	}
 
 	/* Hey, it's a NOTIFY! See if they've configured a mwi_from.
@@ -10845,16 +10856,18 @@ static void add_diversion_header(struct sip_request *req, struct sip_pvt *pvt)
 		return;
 	}
 
-	diverting_number = pvt->owner->redirecting.from.number;
-	diverting_name = pvt->owner->redirecting.from.name;
-	reason = sip_reason_code_to_str(pvt->owner->redirecting.reason);
-
-	if (ast_strlen_zero(diverting_number)) {
+	diverting_number = pvt->owner->redirecting.from.number.str;
+	if (!pvt->owner->redirecting.from.number.valid
+		|| ast_strlen_zero(diverting_number)) {
 		return;
 	}
 
+	reason = sip_reason_code_to_str(pvt->owner->redirecting.reason);
+
 	/* We at least have a number to place in the Diversion header, which is enough */
-	if (ast_strlen_zero(diverting_name)) {
+	diverting_name = pvt->owner->redirecting.from.name.str;
+	if (!pvt->owner->redirecting.from.name.valid
+		|| ast_strlen_zero(diverting_name)) {
 		snprintf(header_text, sizeof(header_text), "<sip:%s@%s>;reason=%s", diverting_number,
 				ast_sockaddr_stringify_host(&pvt->ourip), reason);
 	} else {
@@ -11291,11 +11304,17 @@ static void state_notify_build_xml(int state, int full, const char *exten, const
 				struct ast_channel *caller;
 
 				if ((caller = ast_channel_callback(find_calling_channel, NULL, p, 0))) {
-					int need = strlen(caller->cid.cid_num) + strlen(p->fromdomain) + sizeof("sip:@");
-					local_target = alloca(need);
+					char *cid_num;
+					int need;
+
 					ast_channel_lock(caller);
-					snprintf(local_target, need, "sip:%s@%s", caller->cid.cid_num, p->fromdomain);
-					local_display = ast_strdupa(caller->cid.cid_name);
+					cid_num = S_COR(caller->caller.id.number.valid,
+						caller->caller.id.number.str, "");
+					need = strlen(cid_num) + strlen(p->fromdomain) + sizeof("sip:@");
+					local_target = alloca(need);
+					snprintf(local_target, need, "sip:%s@%s", cid_num, p->fromdomain);
+					local_display = ast_strdupa(S_COR(caller->caller.id.name.valid,
+						caller->caller.id.name.str, ""));
 					ast_channel_unlock(caller);
 					caller = ast_channel_unref(caller);
 				}
@@ -11599,10 +11618,15 @@ static void update_connectedline(struct sip_pvt *p, const void *data, size_t dat
 
 	if (!ast_test_flag(&p->flags[0], SIP_SENDRPID))
 		return;
-	if (ast_strlen_zero(p->owner->connected.id.number))
+	if (!p->owner->connected.id.number.valid
+		|| ast_strlen_zero(p->owner->connected.id.number.str)) {
 		return;
+	}
 
-	append_history(p, "ConnectedLine", "%s party is now %s <%s>", ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called", p->owner->connected.id.name, p->owner->connected.id.number);
+	append_history(p, "ConnectedLine", "%s party is now %s <%s>",
+		ast_test_flag(&p->flags[0], SIP_OUTGOING) ? "Calling" : "Called",
+		S_COR(p->owner->connected.id.name.valid, p->owner->connected.id.name.str, ""),
+		S_COR(p->owner->connected.id.number.valid, p->owner->connected.id.number.str, ""));
 
 	if (p->owner->_state == AST_STATE_UP || ast_test_flag(&p->flags[0], SIP_OUTGOING)) {
 		struct sip_request req;
@@ -13551,7 +13575,8 @@ static int get_pai(struct sip_pvt *p, struct sip_request *req)
 
 	if (p->owner) {
 		ast_set_callerid(p->owner, cid_num, cid_name, NULL);
-		p->owner->cid.cid_pres = callingpres;
+		p->owner->caller.id.name.presentation = callingpres;
+		p->owner->caller.id.number.presentation = callingpres;
 	}
 
 	return 1;
@@ -13650,7 +13675,8 @@ static int get_rpid(struct sip_pvt *p, struct sip_request *oreq)
 
 	if (p->owner) {
 		ast_set_callerid(p->owner, cid_num, cid_name, NULL);
-		p->owner->cid.cid_pres = callingpres;
+		p->owner->caller.id.name.presentation = callingpres;
+		p->owner->caller.id.number.presentation = callingpres;
 	}
 
 	return 1;
@@ -17811,7 +17837,9 @@ static struct ast_custom_function sipchaninfo_function = {
 /*! \brief update redirecting information for a channel based on headers
  *
  */
-static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req, struct ast_party_redirecting *redirecting, int set_call_forward)
+static void change_redirecting_information(struct sip_pvt *p, struct sip_request *req,
+	struct ast_party_redirecting *redirecting,
+	struct ast_set_party_redirecting *update_redirecting, int set_call_forward)
 {
 	char *redirecting_from_name = NULL;
 	char *redirecting_from_number = NULL;
@@ -17841,42 +17869,38 @@ static void change_redirecting_information(struct sip_pvt *p, struct sip_request
 	}
 
 	if (!ast_strlen_zero(redirecting_from_number)) {
-		if (redirecting->from.number) {
-			ast_free(redirecting->from.number);
-		}
 		ast_debug(3, "Got redirecting from number %s\n", redirecting_from_number);
-		redirecting->from.number = redirecting_from_number;
+		update_redirecting->from.number = 1;
+		redirecting->from.number.valid = 1;
+		ast_free(redirecting->from.number.str);
+		redirecting->from.number.str = redirecting_from_number;
 	}
 	if (!ast_strlen_zero(redirecting_from_name)) {
-		if (redirecting->from.name) {
-			ast_free(redirecting->from.name);
-		}
 		ast_debug(3, "Got redirecting from name %s\n", redirecting_from_name);
-		redirecting->from.name = redirecting_from_name;
+		update_redirecting->from.name = 1;
+		redirecting->from.name.valid = 1;
+		ast_free(redirecting->from.name.str);
+		redirecting->from.name.str = redirecting_from_name;
 	}
 	if (!ast_strlen_zero(p->cid_tag)) {
-		if (redirecting->from.tag) {
-			ast_free(redirecting->from.tag);
-		}
+		ast_free(redirecting->from.tag);
 		redirecting->from.tag = ast_strdup(p->cid_tag);
-		if (redirecting->to.tag) {
-			ast_free(redirecting->to.tag);
-		}
+		ast_free(redirecting->to.tag);
 		redirecting->to.tag = ast_strdup(p->cid_tag);
 	}
 	if (!ast_strlen_zero(redirecting_to_number)) {
-		if (redirecting->to.number) {
-			ast_free(redirecting->to.number);
-		}
 		ast_debug(3, "Got redirecting to number %s\n", redirecting_to_number);
-		redirecting->to.number = redirecting_to_number;
+		update_redirecting->to.number = 1;
+		redirecting->to.number.valid = 1;
+		ast_free(redirecting->to.number.str);
+		redirecting->to.number.str = redirecting_to_number;
 	}
 	if (!ast_strlen_zero(redirecting_to_name)) {
-		if (redirecting->to.name) {
-			ast_free(redirecting->to.name);
-		}
 		ast_debug(3, "Got redirecting to name %s\n", redirecting_from_number);
-		redirecting->to.name = redirecting_to_name;
+		update_redirecting->to.name = 1;
+		redirecting->to.name.valid = 1;
+		ast_free(redirecting->to.name.str);
+		redirecting->to.name.str = redirecting_to_name;
 	}
 	redirecting->reason = reason;
 }
@@ -18169,6 +18193,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
 	char *p_hdrval;
 	int rtn;
 	struct ast_party_connected_line connected;
+	struct ast_set_party_connected_line update_connected;
 
 	if (reinvite)
 		ast_debug(4, "SIP response %d to RE-invite on %s call %s\n", resp, outgoing ? "outgoing" : "incoming", p->callid);
@@ -18224,12 +18249,23 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
 		if (!req->ignore && p->owner) {
 			if (get_rpid(p, req)) {
 				ast_party_connected_line_init(&connected);
-				connected.id.number = (char *) p->cid_num;
-				connected.id.name = (char *) p->cid_name;
+				memset(&update_connected, 0, sizeof(update_connected));
+				if (p->cid_num) {
+					update_connected.id.number = 1;
+					connected.id.number.valid = 1;
+					connected.id.number.str = (char *) p->cid_num;
+					connected.id.number.presentation = p->callingpres;
+				}
+				if (p->cid_name) {
+					update_connected.id.name = 1;
+					connected.id.name.valid = 1;
+					connected.id.name.str = (char *) p->cid_name;
+					connected.id.name.presentation = p->callingpres;
+				}
 				connected.id.tag = (char *) p->cid_tag;
-				connected.id.number_presentation = p->callingpres;
 				connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-				ast_channel_queue_connected_line_update(p->owner, &connected);
+				ast_channel_queue_connected_line_update(p->owner, &connected,
+					&update_connected);
 			}
 			sip_handle_cc(p, req, AST_CC_CCNR);
 			ast_queue_control(p->owner, AST_CONTROL_RINGING);
@@ -18254,9 +18290,15 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
 		if (!req->ignore && (p->invitestate != INV_CANCELLED) && sip_cancel_destroy(p))
 			ast_log(LOG_WARNING, "Unable to cancel SIP destruction.  Expect bad things.\n");
 		if (!req->ignore && p->owner) {
-			struct ast_party_redirecting redirecting = {{0,},};
-			change_redirecting_information(p, req, &redirecting, FALSE);
-			ast_channel_queue_redirecting_update(p->owner, &redirecting);
+			struct ast_party_redirecting redirecting;
+			struct ast_set_party_redirecting update_redirecting;
+
+			ast_party_redirecting_init(&redirecting);
+			memset(&update_redirecting, 0, sizeof(update_redirecting));
+			change_redirecting_information(p, req, &redirecting, &update_redirecting,
+				FALSE);
+			ast_channel_queue_redirecting_update(p->owner, &redirecting,
+				&update_redirecting);
 			ast_party_redirecting_free(&redirecting);
 			sip_handle_cc(p, req, AST_CC_CCNR);
 		}
@@ -18270,12 +18312,23 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
 			if (get_rpid(p, req)) {
 				/* Queue a connected line update */
 				ast_party_connected_line_init(&connected);
-				connected.id.number = (char *) p->cid_num;
-				connected.id.name = (char *) p->cid_name;
+				memset(&update_connected, 0, sizeof(update_connected));
+				if (p->cid_num) {
+					update_connected.id.number = 1;
+					connected.id.number.valid = 1;
+					connected.id.number.str = (char *) p->cid_num;
+					connected.id.number.presentation = p->callingpres;
+				}
+				if (p->cid_name) {
+					update_connected.id.name = 1;
+					connected.id.name.valid = 1;
+					connected.id.name.str = (char *) p->cid_name;
+					connected.id.name.presentation = p->callingpres;
+				}
 				connected.id.tag = (char *) p->cid_tag;
-				connected.id.number_presentation = p->callingpres;
 				connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-				ast_channel_queue_connected_line_update(p->owner, &connected);
+				ast_channel_queue_connected_line_update(p->owner, &connected,
+					&update_connected);
 			}
 			sip_handle_cc(p, req, AST_CC_CCNR);
 		}
@@ -18316,12 +18369,23 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
 		if (!req->ignore && p->owner && (get_rpid(p, req) || !reinvite)) {
 			/* Queue a connected line update */
 			ast_party_connected_line_init(&connected);
-			connected.id.number = (char *) p->cid_num;
-			connected.id.name = (char *) p->cid_name;
+			memset(&update_connected, 0, sizeof(update_connected));
+			if (p->cid_num) {
+				update_connected.id.number = 1;
+				connected.id.number.valid = 1;
+				connected.id.number.str = (char *) p->cid_num;
+				connected.id.number.presentation = p->callingpres;
+			}
+			if (p->cid_name) {
+				update_connected.id.name = 1;
+				connected.id.name.valid = 1;
+				connected.id.name.str = (char *) p->cid_name;
+				connected.id.name.presentation = p->callingpres;
+			}
 			connected.id.tag = (char *) p->cid_tag;
-			connected.id.number_presentation = p->callingpres;
 			connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-			ast_channel_queue_connected_line_update(p->owner, &connected);
+			ast_channel_queue_connected_line_update(p->owner, &connected,
+				&update_connected);
 		}
 
 		/* Parse contact header for continued conversation */
@@ -19234,9 +19298,14 @@ static void handle_response(struct sip_pvt *p, int resp, const char *rest, struc
 				case 302: /* Moved temporarily */
 				case 305: /* Use Proxy */
 				if (p->owner) {
-					struct ast_party_redirecting redirecting = {{0,},};
-					change_redirecting_information(p, req, &redirecting, TRUE);
-					ast_channel_set_redirecting(p->owner, &redirecting);
+					struct ast_party_redirecting redirecting;
+					struct ast_set_party_redirecting update_redirecting;
+
+					ast_party_redirecting_init(&redirecting);
+					change_redirecting_information(p, req, &redirecting,
+						&update_redirecting, TRUE);
+					ast_channel_set_redirecting(p->owner, &redirecting,
+						&update_redirecting);
 					ast_party_redirecting_free(&redirecting);
 				}
 					/* Fall through */
@@ -20454,13 +20523,24 @@ static int handle_request_update(struct sip_pvt *p, struct sip_request *req)
 	}
 	if (get_rpid(p, req)) {
 		struct ast_party_connected_line connected;
+		struct ast_set_party_connected_line update_connected;
 		ast_party_connected_line_init(&connected);
-		connected.id.number = (char *) p->cid_num;
-		connected.id.name = (char *) p->cid_name;
+		memset(&update_connected, 0, sizeof(update_connected));
+		if (p->cid_num) {
+			update_connected.id.number = 1;
+			connected.id.number.valid = 1;
+			connected.id.number.str = (char *) p->cid_num;
+			connected.id.number.presentation = p->callingpres;
+		}
+		if (p->cid_name) {
+			update_connected.id.name = 1;
+			connected.id.name.valid = 1;
+			connected.id.name.str = (char *) p->cid_name;
+			connected.id.name.presentation = p->callingpres;
+		}
 		connected.id.tag = (char *) p->cid_tag;
-		connected.id.number_presentation = p->callingpres;
 		connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-		ast_channel_queue_connected_line_update(p->owner, &connected);
+		ast_channel_queue_connected_line_update(p->owner, &connected, &update_connected);
 	}
 	transmit_response(p, "200 OK", req);
 	return 0;
@@ -20486,6 +20566,8 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 	struct sip_peer *authpeer = NULL;	/* Matching Peer */
 	int reinvite = 0;
 	int rtn;
+	struct ast_party_redirecting redirecting;
+	struct ast_set_party_redirecting update_redirecting;
 
 	const char *p_uac_se_hdr;       /* UAC's Session-Expires header string                      */
 	const char *p_uac_min_se;       /* UAC's requested Min-SE interval (char string)            */
@@ -20783,14 +20865,26 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 			ast_clear_flag(&p->flags[0], SIP_OUTGOING);	/* This is now an inbound dialog */
 			if (get_rpid(p, req)) {
 				struct ast_party_connected_line connected;
+				struct ast_set_party_connected_line update_connected;
 
 				ast_party_connected_line_init(&connected);
-				connected.id.number = (char *) p->cid_num;
-				connected.id.name = (char *) p->cid_name;
+				memset(&update_connected, 0, sizeof(update_connected));
+				if (p->cid_num) {
+					update_connected.id.number = 1;
+					connected.id.number.valid = 1;
+					connected.id.number.str = (char *) p->cid_num;
+					connected.id.number.presentation = p->callingpres;
+				}
+				if (p->cid_name) {
+					update_connected.id.name = 1;
+					connected.id.name.valid = 1;
+					connected.id.name.str = (char *) p->cid_name;
+					connected.id.name.presentation = p->callingpres;
+				}
 				connected.id.tag = (char *) p->cid_tag;
-				connected.id.number_presentation = p->callingpres;
 				connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-				ast_channel_queue_connected_line_update(p->owner, &connected);
+				ast_channel_queue_connected_line_update(p->owner, &connected,
+					&update_connected);
 			}
 			/* Handle SDP here if we already have an owner */
 			if (find_sdp(req)) {
@@ -20958,16 +21052,19 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 			build_route(p, req, 0);
 
 			if (c) {
-				struct ast_party_redirecting redirecting = { { 0, }, };
+				ast_party_redirecting_init(&redirecting);
+				memset(&update_redirecting, 0, sizeof(update_redirecting));
 				/* Pre-lock the call */
 				ast_channel_lock(c);
-				change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
-				ast_channel_set_redirecting(c, &redirecting);
+				change_redirecting_information(p, req, &redirecting, &update_redirecting,
+					FALSE); /*Will return immediately if no Diversion header is present */
+				ast_channel_set_redirecting(c, &redirecting, &update_redirecting);
 				ast_party_redirecting_free(&redirecting);
 			}
 		}
 	} else {
-		struct ast_party_redirecting redirecting = {{0,},};
+		ast_party_redirecting_init(&redirecting);
+		memset(&update_redirecting, 0, sizeof(update_redirecting));
 		if (sipdebug) {
 			if (!req->ignore)
 				ast_debug(2, "Got a SIP re-invite for call %s\n", p->callid);
@@ -20977,9 +21074,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 		if (!req->ignore)
 			reinvite = 1;
 		c = p->owner;
-		change_redirecting_information(p, req, &redirecting, FALSE); /*Will return immediately if no Diversion header is present */
+		change_redirecting_information(p, req, &redirecting, &update_redirecting, FALSE); /*Will return immediately if no Diversion header is present */
 		if (c) {
-			ast_channel_set_redirecting(c, &redirecting);
+			ast_channel_set_redirecting(c, &redirecting, &update_redirecting);
 		}
 		ast_party_redirecting_free(&redirecting);
 	}
@@ -21448,8 +21545,8 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
 		ast_indicate(target.chan1, AST_CONTROL_UNHOLD);
 
 		if (target.chan2) {
-			ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee);
-			ast_channel_queue_connected_line_update(target.chan2, &connected_to_target);
+			ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee, NULL);
+			ast_channel_queue_connected_line_update(target.chan2, &connected_to_target, NULL);
 		} else {
 			/* Since target.chan1 isn't actually connected to another channel, there is no way for us
 			 * to queue a frame so that its connected line status will be updated.
@@ -21462,7 +21559,8 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
 			int payload_size;
 			int frame_size;
 			unsigned char connected_line_data[1024];
-			payload_size = ast_connected_line_build_data(connected_line_data, sizeof(connected_line_data), &connected_to_target);
+			payload_size = ast_connected_line_build_data(connected_line_data,
+				sizeof(connected_line_data), &connected_to_target, NULL);
 			frame_size = payload_size + sizeof(*frame_payload);
 			if (payload_size != -1 && (frame_payload = alloca(frame_size))) {
 				frame_payload->payload_size = payload_size;
@@ -21474,7 +21572,7 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual *
 			 * will be updated, we also are going to queue a plain old connected line update on target.chan1. This
 			 * way, either Dial or Queue can apply this connected line update to the outgoing ringing channel.
 			 */
-			ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee);
+			ast_channel_queue_connected_line_update(target.chan1, &connected_to_transferee, NULL);
 
 		}
 		ast_channel_unref(current->chan1);
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 6ddc3f0cf767280af78f74ee102e08e6dd893b6d..3a99fbbcd3585b8c195bdc1f1cbda26ec421e815 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -2674,21 +2674,33 @@ static void update_connectedline(struct skinny_subchannel *sub, const void *data
 	struct skinny_line *l = sub->parent;
 	struct skinny_device *d = l->device;
 
-	if (ast_strlen_zero(c->cid.cid_num) || ast_strlen_zero(c->connected.id.number))
+	if (!c->caller.id.number.valid
+		|| ast_strlen_zero(c->caller.id.number.str)
+		|| !c->connected.id.number.valid
+		|| ast_strlen_zero(c->connected.id.number.str))
 		return;
 
 	if (sub->owner->_state == AST_STATE_UP) {
 		transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
 		transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
 		if (sub->outgoing)
-			transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+			transmit_callinfo(d,
+				S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
+				c->connected.id.number.str,
+				l->cid_name, l->cid_num, l->instance, sub->callid, 1);
 		else
-			transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
+			transmit_callinfo(d, l->cid_name, l->cid_num,
+				S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
+				c->connected.id.number.str,
+				l->instance, sub->callid, 2);
 	} else {
 		if (sub->outgoing) {
 			transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
 			transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
-			transmit_callinfo(d, c->connected.id.name, c->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+			transmit_callinfo(d,
+				S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
+				c->connected.id.number.str,
+				l->cid_name, l->cid_num, l->instance, sub->callid, 1);
 		} else {
 			if (!sub->ringing) {
 				transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGOUT);
@@ -2700,7 +2712,10 @@ static void update_connectedline(struct skinny_subchannel *sub, const void *data
 				sub->progress = 1;
 			}
 
-			transmit_callinfo(d, l->cid_name, l->cid_num, c->connected.id.name, c->connected.id.number, l->instance, sub->callid, 2);
+			transmit_callinfo(d, l->cid_name, l->cid_num,
+				S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
+				c->connected.id.number.str,
+				l->instance, sub->callid, 2);
 		}
 	}
 }
@@ -3759,9 +3774,15 @@ static void *skinny_newcall(void *data)
 	ast_set_callerid(c,
 		l->hidecallerid ? "" : l->cid_num,
 		l->hidecallerid ? "" : l->cid_name,
-		c->cid.cid_ani ? NULL : l->cid_num);
-	c->connected.id.number = ast_strdup(c->exten);
-	c->connected.id.name = NULL;
+		c->caller.ani ? NULL : l->cid_num);
+#if 1	/* XXX This code is probably not necessary */
+	ast_party_number_free(&c->connected.id.number);
+	ast_party_number_init(&c->connected.id.number);
+	c->connected.id.number.valid = 1;
+	c->connected.id.number.str = ast_strdup(c->exten);
+	ast_party_name_free(&c->connected.id.name);
+	ast_party_name_init(&c->connected.id.name);
+#endif
 	ast_setstate(c, AST_STATE_RING);
 	if (!sub->rtp) {
 		start_rtp(sub);
@@ -3852,9 +3873,12 @@ static void *skinny_ss(void *data)
 				ast_hangup(c);
 			}
 			return NULL;
-		} else if (!ast_canmatch_extension(c, c->context, d->exten, 1, c->cid.cid_num) &&
-			   ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
-			ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten, c->cid.cid_num ? c->cid.cid_num : "<Unknown Caller>", c->context);
+		} else if (!ast_canmatch_extension(c, c->context, d->exten, 1,
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))
+			&& ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
+			ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten,
+				S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<Unknown Caller>"),
+				c->context);
 			memset(d->exten, 0, sizeof(d->exten));
 			if (l->hookstate == SKINNY_OFFHOOK) {
 				transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
@@ -3925,7 +3949,10 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
 	transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_RINGIN);
 	transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
 	transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
-	transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
+	transmit_callinfo(d,
+		S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+		S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
+		l->cid_name, l->cid_num, l->instance, sub->callid, 1);
 	transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
 	transmit_ringer_mode(d, SKINNY_RING_INSIDE);
 
@@ -4058,7 +4085,10 @@ static int skinny_answer(struct ast_channel *ast)
 	/* order matters here...
 	   for some reason, transmit_callinfo must be before transmit_callstate,
 	   or you won't get keypad messages in some situations. */
-	transmit_callinfo(d, ast->connected.id.name, ast->connected.id.number, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
+	transmit_callinfo(d,
+		S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+		S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
+		l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
 	transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
 	transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
 	transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
@@ -4368,7 +4398,12 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
 				transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_RINGOUT);
 				transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
 				transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
-				transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+				transmit_callinfo(d,
+					S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
+					S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
+					S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, l->lastnumberdialed),
+					S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, l->lastnumberdialed),
+					l->instance, sub->callid, 2); /* 2 = outgoing from phone */
 				sub->ringing = 1;
 				if (!d->earlyrtp) {
 					break;
@@ -4409,7 +4444,12 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
 			}
 			transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_PROGRESS);
 			transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
-			transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, S_OR(ast->connected.id.name, l->lastnumberdialed), S_OR(ast->connected.id.number, l->lastnumberdialed), l->instance, sub->callid, 2); /* 2 = outgoing from phone */
+			transmit_callinfo(d,
+				S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
+				S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
+				S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, l->lastnumberdialed),
+				S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, l->lastnumberdialed),
+				l->instance, sub->callid, 2); /* 2 = outgoing from phone */
 			sub->progress = 1;
 			if (!d->earlyrtp) {
 				break;
@@ -4533,7 +4573,7 @@ static struct ast_channel *skinny_new(struct skinny_line *l, int state, const ch
 
 		/* Don't use ast_set_callerid() here because it will
 		 * generate a needless NewCallerID event */
-		tmp->cid.cid_ani = ast_strdup(l->cid_num);
+		tmp->caller.ani = ast_strdup(l->cid_num);
 
 		tmp->priority = 1;
 		tmp->adsicpe = AST_ADSI_UNAVAILABLE;
diff --git a/channels/chan_unistim.c b/channels/chan_unistim.c
index fdc969d86f3e0b626a89c1e43c49cdfa4673651f..3c307a6820a091aae32b041ca362504de626068e 100644
--- a/channels/chan_unistim.c
+++ b/channels/chan_unistim.c
@@ -2313,7 +2313,6 @@ static void handle_dial_page(struct unistimsession *pte)
 			send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
 		}
 		send_text_status(pte, "Call   Redial BackSpcErase");
-
 	}
 
 	if (pte->device->height == 1) {
@@ -2792,7 +2791,6 @@ static void key_dial_page(struct unistimsession *pte, char keycode)
 				send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
 			}
 			send_text_status(pte, "Hangup Transf");
-
 		} else
 			show_main_page(pte);
 		break;
@@ -3736,13 +3734,14 @@ static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
 	Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
 
 	if (sub->owner) {
-		if (sub->owner->connected.id.number) {
+		if (sub->owner->connected.id.number.valid
+			&& sub->owner->connected.id.number.str) {
 			if (session->device->height == 1) {
-				send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.number);
+				send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
 			} else {
-				send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number);
+				send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
 			}
-			change_callerid(session, 0, sub->owner->connected.id.number);
+			change_callerid(session, 0, sub->owner->connected.id.number.str);
 		} else {
 			if (session->device->height == 1) {
 				send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERID);
@@ -3751,15 +3750,15 @@ static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
 			}
 			change_callerid(session, 0, DEFAULTCALLERID);
 		}
-		if (sub->owner->connected.id.name) {
-			send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name);
-			change_callerid(session, 1, sub->owner->connected.id.name);
+		if (sub->owner->connected.id.name.valid
+			&& sub->owner->connected.id.name.str) {
+			send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name.str);
+			change_callerid(session, 1, sub->owner->connected.id.name.str);
 		} else {
 			send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
 			change_callerid(session, 1, DEFAULTCALLERNAME);
 		}
 	}
-
 	send_text(TEXT_LINE2, TEXT_NORMAL, session, "is calling you.");
 	send_text_status(session, "Accept              Ignore");
 
@@ -4567,8 +4566,12 @@ static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state
 		instr = ast_strdup(l->cid_num);
 		if (instr) {
 			ast_callerid_parse(instr, &name, &loc);
-			tmp->cid.cid_num = ast_strdup(loc);
-			tmp->cid.cid_name = ast_strdup(name);
+			tmp->caller.id.number.valid = 1;
+			ast_free(tmp->caller.id.number.str);
+			tmp->caller.id.number.str = ast_strdup(loc);
+			tmp->caller.id.name.valid = 1;
+			ast_free(tmp->caller.id.name.str);
+			tmp->caller.id.name.str = ast_strdup(name);
 			ast_free(instr);
 		}
 	}
diff --git a/channels/chan_usbradio.c b/channels/chan_usbradio.c
index 81c1afe55b869c9c00fe10812c7f8728c2dcad3a..f64a2cb1075265ba6dc17fa75482bb755d5d9865 100644
--- a/channels/chan_usbradio.c
+++ b/channels/chan_usbradio.c
@@ -2201,11 +2201,10 @@ static struct ast_channel *usbradio_new(struct chan_usbradio_pvt *o, char *ext,
 		ast_string_field_set(c, language, o->language);
 	/* Don't use ast_set_callerid() here because it will
 	 * generate a needless NewCallerID event */
-	c->cid.cid_num = ast_strdup(o->cid_num);
-	c->cid.cid_ani = ast_strdup(o->cid_num);
-	c->cid.cid_name = ast_strdup(o->cid_name);
-	if (!ast_strlen_zero(ext))
-		c->cid.cid_dnid = ast_strdup(ext);
+	c->caller.ani = ast_strdup(o->cid_num);
+	if (!ast_strlen_zero(ext)) {
+		c->dialed.number.str = ast_strdup(ext);
+	}
 
 	o->owner = c;
 	ast_module_ref(ast_module_info->self);
diff --git a/channels/chan_vpb.cc b/channels/chan_vpb.cc
index f6a3ae6a511806b0a2a679cc333e6ad570e966da..9914c59c30f0dcfc6b0048a5c3a7ddf1cafdb07e 100644
--- a/channels/chan_vpb.cc
+++ b/channels/chan_vpb.cc
@@ -693,7 +693,9 @@ static void get_callerid(struct vpb_pvt *p)
 					strcpy(p->cid_num, cli_struct->cldn);
 					strcpy(p->cid_name, cli_struct->cn);
 				}
-				ast_verb(4, "CID record - got [%s] [%s]\n", owner->cid.cid_num, owner->cid.cid_name);
+				ast_verb(4, "CID record - got [%s] [%s]\n",
+					S_COR(owner->caller.id.number.valid, owner->caller.id.number.str, ""),
+					S_COR(owner->caller.id.name.valid, owner->caller.id.name.str, ""));
 				snprintf(p->callerid, sizeof(p->callerid), "%s %s", cli_struct->cldn, cli_struct->cn);
 			} else {
 				ast_log(LOG_ERROR, "CID record - No caller id avalable on %s \n", p->dev);
@@ -778,19 +780,15 @@ static void get_callerid_ast(struct vpb_pvt *p)
 	} else {
 		ast_log(LOG_ERROR, "%s: Failed to create Caller ID struct\n", p->dev);
 	}
-	if (owner->cid.cid_num) {
-		ast_free(owner->cid.cid_num);
-		owner->cid.cid_num = NULL;
-	}
-	if (owner->cid.cid_name) {
-		ast_free(owner->cid.cid_name);
-		owner->cid.cid_name = NULL;
-	}
+	ast_party_number_free(&owner->caller.id.number);
+	ast_party_number_init(&owner->caller.id.number);
+	ast_party_name_free(&owner->caller.id.name);
+	ast_party_name_init(&owner->caller.id.name);
 	if (number)
 		ast_shrink_phone_number(number);
 	ast_set_callerid(owner,
 		number, name,
-		owner->cid.cid_ani ? NULL : number);
+		owner->caller.ani ? NULL : number);
 	if (!ast_strlen_zero(name)){
 		snprintf(p->callerid, sizeof(p->callerid), "%s %s", number, name);
 	} else {
@@ -901,7 +899,8 @@ static inline int monitor_handle_owned(struct vpb_pvt *p, VPB_EVENT *e)
 				if (strcmp(p->owner->exten, "fax")) {
 					const char *target_context = S_OR(p->owner->macrocontext, p->owner->context);
 
-					if (ast_exists_extension(p->owner, target_context, "fax", 1, p->owner->cid.cid_num)) {
+					if (ast_exists_extension(p->owner, target_context, "fax", 1,
+						S_COR(p->owner->caller.id.number.valid, p->owner->caller.id.number.str, NULL))) {
 						ast_verb(3, "Redirecting %s to fax extension\n", p->owner->name);
 						/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
 						pbx_builtin_setvar_helper(p->owner, "FAXEXTEN", p->owner->exten);
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 1f92d24d9cd0f753effb12be36049d41346763fd..feb0d5fdb34e3021c7138b590581f90a7ef46620 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -351,16 +351,18 @@ static int analog_unalloc_sub(struct analog_pvt *p, enum analog_sub x)
 	return 0;
 }
 
-static int analog_send_callerid(struct analog_pvt *p, int cwcid, struct ast_callerid *cid)
+static int analog_send_callerid(struct analog_pvt *p, int cwcid, struct ast_party_caller *caller)
 {
-	ast_debug(1, "Sending callerid.  CID_NAME: '%s' CID_NUM: '%s'\n", cid->cid_name, cid->cid_num);
+	ast_debug(1, "Sending callerid.  CID_NAME: '%s' CID_NUM: '%s'\n",
+		caller->id.name.str,
+		caller->id.number.str);
 
 	if (cwcid) {
 		p->callwaitcas = 0;
 	}
 
 	if (p->calls->send_callerid) {
-		return p->calls->send_callerid(p->chan_pvt, cwcid, cid);
+		return p->calls->send_callerid(p->chan_pvt, cwcid, caller);
 	}
 	return 0;
 }
@@ -860,7 +862,9 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 	char *c, *n, *l;
 	char dest[256]; /* must be same length as p->dialdest */
 
-	ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n", ast->connected.id.name, ast->connected.id.number);
+	ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n",
+		S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+		S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
 
 	ast_copy_string(dest, rdest, sizeof(dest));
 	ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
@@ -916,13 +920,13 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 			}
 			analog_set_dialing(p, 1);
 		} else {
-			if (ast->connected.id.number) {
-				ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
+			if (ast->connected.id.number.valid && ast->connected.id.number.str) {
+				ast_copy_string(p->callwait_num, ast->connected.id.number.str, sizeof(p->callwait_num));
 			} else {
 				p->callwait_num[0] = '\0';
 			}
-			if (ast->connected.id.name) {
-				ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
+			if (ast->connected.id.name.valid && ast->connected.id.name.str) {
+				ast_copy_string(p->callwait_name, ast->connected.id.name.str, sizeof(p->callwait_name));
 			} else {
 				p->callwait_name[0] = '\0';
 			}
@@ -937,8 +941,8 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 			}
 
 		}
-		n = ast->connected.id.name;
-		l = ast->connected.id.number;
+		n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
+		l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
 		if (l) {
 			ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
 		} else {
@@ -951,8 +955,8 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 		}
 
 		if (p->use_callerid) {
-			p->cid.cid_name = p->lastcid_name;
-			p->cid.cid_num = p->lastcid_num;
+			p->caller.id.name.str = p->lastcid_name;
+			p->caller.id.number.str = p->lastcid_num;
 		}
 
 		ast_setstate(ast, AST_STATE_RINGING);
@@ -1025,7 +1029,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 
 		switch (mysig) {
 		case ANALOG_SIG_FEATD:
-			l = ast->connected.id.number;
+			l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
 			if (l) {
 				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
 			} else {
@@ -1033,7 +1037,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, char *rdest, int
 			}
 			break;
 		case ANALOG_SIG_FEATDMF:
-			l = ast->connected.id.number;
+			l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
 			if (l) {
 				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
 			} else {
@@ -1408,9 +1412,9 @@ void analog_handle_dtmfup(struct analog_pvt *p, struct ast_channel *ast, enum an
 	if (p->callwaitcas) {
 		if ((f->subclass.integer == 'A') || (f->subclass.integer == 'D')) {
 			ast_debug(1, "Got some DTMF, but it's for the CAS\n");
-			p->cid.cid_name = p->callwait_name;
-			p->cid.cid_num = p->callwait_num;
-			analog_send_callerid(p, 1, &p->cid);
+			p->caller.id.name.str = p->callwait_name;
+			p->caller.id.number.str = p->callwait_num;
+			analog_send_callerid(p, 1, &p->caller);
 		}
 		if (analog_handles_digit(f))
 			p->callwaitcas = 0;
@@ -1820,7 +1824,8 @@ static void *__analog_ss_thread(void *data)
 
 		analog_dsp_set_digitmode(p, ANALOG_DIGITMODE_DTMF);
 
-		if (ast_exists_extension(chan, chan->context, exten, 1, chan->cid.cid_num)) {
+		if (ast_exists_extension(chan, chan->context, exten, 1,
+			chan->caller.id.number.valid ? chan->caller.id.number.str : NULL)) {
 			ast_copy_string(chan->exten, exten, sizeof(chan->exten));
 			analog_dsp_reset_and_flush_digits(p);
 			res = ast_pbx_run(chan);
@@ -1976,14 +1981,10 @@ static void *__analog_ss_thread(void *data)
 				ast_verb(3, "Disabling Caller*ID on %s\n", chan->name);
 				/* Disable Caller*ID if enabled */
 				p->hidecallerid = 1;
-				if (chan->cid.cid_num) {
-					free(chan->cid.cid_num);
-				}
-				chan->cid.cid_num = NULL;
-				if (chan->cid.cid_name) {
-					free(chan->cid.cid_name);
-				}
-				chan->cid.cid_name = NULL;
+				ast_party_number_free(&chan->caller.id.number);
+				ast_party_number_init(&chan->caller.id.number);
+				ast_party_name_free(&chan->caller.id.name);
+				ast_party_name_init(&chan->caller.id.name);
 				res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
 				if (res) {
 					ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
@@ -2055,14 +2056,6 @@ static void *__analog_ss_thread(void *data)
 				ast_verb(3, "Enabling Caller*ID on %s\n", chan->name);
 				/* Enable Caller*ID if enabled */
 				p->hidecallerid = 0;
-				if (chan->cid.cid_num) {
-					free(chan->cid.cid_num);
-				}
-				chan->cid.cid_num = NULL;
-				if (chan->cid.cid_name) {
-					free(chan->cid.cid_name);
-				}
-				chan->cid.cid_name = NULL;
 				ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
 				res = analog_play_tone(p, index, ANALOG_TONE_DIALRECALL);
 				if (res) {
@@ -2108,9 +2101,13 @@ static void *__analog_ss_thread(void *data)
 					ast_hangup(chan);
 					goto quit;
 				}
-			} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
-							((exten[0] != '*') || (strlen(exten) > 2))) {
-				ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
+			} else if (!ast_canmatch_extension(chan, chan->context, exten, 1,
+				chan->caller.id.number.valid ? chan->caller.id.number.str : NULL)
+				&& ((exten[0] != '*') || (strlen(exten) > 2))) {
+				ast_debug(1, "Can't match %s from '%s' in context %s\n", exten,
+					chan->caller.id.number.valid && chan->caller.id.number.str
+						? chan->caller.id.number.str : "<Unknown Caller>",
+					chan->context);
 				break;
 			}
 			if (!timeout) {
@@ -2799,7 +2796,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 		if (p->inalarm) break;
 		ast->rings++;
 		if (ast->rings == p->cidrings) {
-			analog_send_callerid(p, 0, &p->cid);
+			analog_send_callerid(p, 0, &p->caller);
 		}
 
 		if (ast->rings > p->cidrings) {
@@ -2869,20 +2866,26 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 				}
 				ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
 			} else if (!p->subs[ANALOG_SUB_THREEWAY].owner) {
-				char cid_num[256];
-				char cid_name[256];
-
 				if (!p->threewaycalling) {
 					/* Just send a flash if no 3-way calling */
 					ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_FLASH);
 					goto winkflashdone;
 				} else if (!analog_check_for_conference(p)) {
+					char cid_num[256];
+					char cid_name[256];
+
+					cid_num[0] = '\0';
+					cid_name[0] = '\0';
 					if (p->dahditrcallerid && p->owner) {
-						if (p->owner->cid.cid_num) {
-							ast_copy_string(cid_num, p->owner->cid.cid_num, sizeof(cid_num));
+						if (p->owner->caller.id.number.valid
+							&& p->owner->caller.id.number.str) {
+							ast_copy_string(cid_num, p->owner->caller.id.number.str,
+								sizeof(cid_num));
 						}
-						if (p->owner->cid.cid_name) {
-							ast_copy_string(cid_name, p->owner->cid.cid_name, sizeof(cid_name));
+						if (p->owner->caller.id.name.valid
+							&& p->owner->caller.id.name.str) {
+							ast_copy_string(cid_name, p->owner->caller.id.name.str,
+								sizeof(cid_name));
 						}
 					}
 					/* XXX This section needs much more error checking!!! XXX */
@@ -3035,8 +3038,11 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
 		case ANALOG_SIG_FEATDMF_TA:
 			switch (p->whichwink) {
 			case 0:
-				ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
-				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
+				ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->caller.ani2,
+					S_OR(p->owner->caller.ani, ""));
+				snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#",
+					p->owner->caller.ani2,
+					S_OR(p->owner->caller.ani, ""));
 				break;
 			case 1:
 				ast_copy_string(p->dop.dialstr, p->finaldial, sizeof(p->dop.dialstr));
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index bc9f9260d90f82380f8c87b626bb06b612cf090d..3f75e5827de2e7cf19d92bc1a6549fd1dfb9e893 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -156,7 +156,7 @@ struct analog_callback {
 	int (* const train_echocanceller)(void *pvt);
 	int (* const dsp_set_digitmode)(void *pvt, enum analog_dsp_digitmode mode);
 	int (* const dsp_reset_and_flush_digits)(void *pvt);
-	int (* const send_callerid)(void *pvt, int cwcid, struct ast_callerid *cid);
+	int (* const send_callerid)(void *pvt, int cwcid, struct ast_party_caller *caller);
 	/* Returns 0 if CID received.  Returns 1 if event received, and -1 if error.  name and num are size ANALOG_MAX_CID */
 	int (* const get_callerid)(void *pvt, char *name, char *num, enum analog_event *ev, size_t timeout);
 	/* Start CID detection */
@@ -298,7 +298,7 @@ struct analog_pvt {
 	char callwait_name[AST_MAX_EXTENSION];
 	char lastcid_num[AST_MAX_EXTENSION];
 	char lastcid_name[AST_MAX_EXTENSION];
-	struct ast_callerid cid;
+	struct ast_party_caller caller;
 	int cidrings;					/*!< Which ring to deliver CID on */
 	char echorest[20];
 	int polarity;
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index e7b059fa7de30b962aecebcd17c9fa3f3cf9c33c..6b6a25e6d16675575d171f296b94f0f362ff5f39 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -206,16 +206,22 @@ static void sig_pri_set_caller_id(struct sig_pri_chan *p)
 
 	if (p->calls->set_callerid) {
 		ast_party_caller_init(&caller);
-		caller.id.number = p->cid_num;
-		caller.id.name = p->cid_name;
+
+		caller.id.name.str = p->cid_name;
+		caller.id.name.presentation = p->callingpres;
+		caller.id.name.valid = 1;
+
+		caller.id.number.str = p->cid_num;
+		caller.id.number.plan = p->cid_ton;
+		caller.id.number.presentation = p->callingpres;
+		caller.id.number.valid = 1;
+
 		if (!ast_strlen_zero(p->cid_subaddr)) {
 			caller.id.subaddress.valid = 1;
 			//caller.id.subaddress.type = 0;/* nsap */
 			//caller.id.subaddress.odd_even_indicator = 0;
 			caller.id.subaddress.str = p->cid_subaddr;
 		}
-		caller.id.number_type = p->cid_ton;
-		caller.id.number_presentation = p->callingpres;
 		caller.id.tag = p->user_tag;
 		caller.ani = p->cid_ani;
 		caller.ani2 = p->cid_ani2;
@@ -454,76 +460,102 @@ static int ast_to_pri_presentation(int ast_presentation)
 
 /*!
  * \internal
- * \brief Determine the overall presentation value for the given party.
+ * \brief Convert PRI name char_set to asterisk version.
  * \since 1.8
  *
- * \param id Party to determine the overall presentation value.
+ * \param pri_char_set PRI name char_set.
  *
- * \return Overall presentation value for the given party converted to ast values.
+ * \return Equivalent asterisk name char_set value.
  */
-static int overall_ast_presentation(const struct pri_party_id *id)
-{
-	int number_priority;
-	int number_value;
-	int number_screening;
-	int name_priority;
-	int name_value;
-
-	/* Determine name presentation priority. */
-	if (!id->name.valid) {
-		name_value = PRI_PRES_UNAVAILABLE;
-		name_priority = 3;
-	} else {
-		name_value = id->name.presentation & PRI_PRES_RESTRICTION;
-		switch (name_value) {
-		case PRI_PRES_RESTRICTED:
-			name_priority = 0;
-			break;
-		case PRI_PRES_ALLOWED:
-			name_priority = 1;
-			break;
-		case PRI_PRES_UNAVAILABLE:
-			name_priority = 2;
-			break;
-		default:
-			name_value = PRI_PRES_UNAVAILABLE;
-			name_priority = 3;
-			break;
-		}
-	}
+static enum AST_PARTY_CHAR_SET pri_to_ast_char_set(int pri_char_set)
+{
+	enum AST_PARTY_CHAR_SET ast_char_set;
 
-	/* Determine number presentation priority. */
-	if (!id->number.valid) {
-		number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
-		number_value = PRI_PRES_UNAVAILABLE;
-		number_priority = 3;
-	} else {
-		number_screening = id->number.presentation & PRI_PRES_NUMBER_TYPE;
-		number_value = id->number.presentation & PRI_PRES_RESTRICTION;
-		switch (number_value) {
-		case PRI_PRES_RESTRICTED:
-			number_priority = 0;
-			break;
-		case PRI_PRES_ALLOWED:
-			number_priority = 1;
-			break;
-		case PRI_PRES_UNAVAILABLE:
-			number_priority = 2;
-			break;
-		default:
-			number_screening = PRI_PRES_USER_NUMBER_UNSCREENED;
-			number_value = PRI_PRES_UNAVAILABLE;
-			number_priority = 3;
-			break;
-		}
+	switch (pri_char_set) {
+	default:
+	case PRI_CHAR_SET_UNKNOWN:
+		ast_char_set = AST_PARTY_CHAR_SET_UNKNOWN;
+		break;
+	case PRI_CHAR_SET_ISO8859_1:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO8859_1;
+		break;
+	case PRI_CHAR_SET_WITHDRAWN:
+		ast_char_set = AST_PARTY_CHAR_SET_WITHDRAWN;
+		break;
+	case PRI_CHAR_SET_ISO8859_2:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO8859_2;
+		break;
+	case PRI_CHAR_SET_ISO8859_3:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO8859_3;
+		break;
+	case PRI_CHAR_SET_ISO8859_4:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO8859_4;
+		break;
+	case PRI_CHAR_SET_ISO8859_5:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO8859_5;
+		break;
+	case PRI_CHAR_SET_ISO8859_7:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO8859_7;
+		break;
+	case PRI_CHAR_SET_ISO10646_BMPSTRING:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO10646_BMPSTRING;
+		break;
+	case PRI_CHAR_SET_ISO10646_UTF_8STRING:
+		ast_char_set = AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING;
+		break;
 	}
 
-	/* Select the wining presentation value. */
-	if (name_priority < number_priority) {
-		number_value = name_value;
+	return ast_char_set;
+}
+
+/*!
+ * \internal
+ * \brief Convert asterisk name char_set to PRI version.
+ * \since 1.8
+ *
+ * \param ast_char_set Asterisk name char_set.
+ *
+ * \return Equivalent PRI name char_set value.
+ */
+static int ast_to_pri_char_set(enum AST_PARTY_CHAR_SET ast_char_set)
+{
+	int pri_char_set;
+
+	switch (ast_char_set) {
+	default:
+	case AST_PARTY_CHAR_SET_UNKNOWN:
+		pri_char_set = PRI_CHAR_SET_UNKNOWN;
+		break;
+	case AST_PARTY_CHAR_SET_ISO8859_1:
+		pri_char_set = PRI_CHAR_SET_ISO8859_1;
+		break;
+	case AST_PARTY_CHAR_SET_WITHDRAWN:
+		pri_char_set = PRI_CHAR_SET_WITHDRAWN;
+		break;
+	case AST_PARTY_CHAR_SET_ISO8859_2:
+		pri_char_set = PRI_CHAR_SET_ISO8859_2;
+		break;
+	case AST_PARTY_CHAR_SET_ISO8859_3:
+		pri_char_set = PRI_CHAR_SET_ISO8859_3;
+		break;
+	case AST_PARTY_CHAR_SET_ISO8859_4:
+		pri_char_set = PRI_CHAR_SET_ISO8859_4;
+		break;
+	case AST_PARTY_CHAR_SET_ISO8859_5:
+		pri_char_set = PRI_CHAR_SET_ISO8859_5;
+		break;
+	case AST_PARTY_CHAR_SET_ISO8859_7:
+		pri_char_set = PRI_CHAR_SET_ISO8859_7;
+		break;
+	case AST_PARTY_CHAR_SET_ISO10646_BMPSTRING:
+		pri_char_set = PRI_CHAR_SET_ISO10646_BMPSTRING;
+		break;
+	case AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING:
+		pri_char_set = PRI_CHAR_SET_ISO10646_UTF_8STRING;
+		break;
 	}
 
-	return pri_to_ast_presentation(number_value | number_screening);
+	return pri_char_set;
 }
 
 #if defined(HAVE_PRI_SUBADDR)
@@ -688,6 +720,56 @@ static void sig_pri_party_subaddress_from_ast(struct pri_party_subaddress *pri_s
 }
 #endif	/* defined(HAVE_PRI_SUBADDR) */
 
+/*!
+ * \internal
+ * \brief Fill in the PRI party name from the given asterisk party name.
+ * \since 1.8
+ *
+ * \param pri_name PRI party name structure.
+ * \param ast_name Asterisk party name structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes that pri_name has been previously memset to zero.
+ */
+static void sig_pri_party_name_from_ast(struct pri_party_name *pri_name, const struct ast_party_name *ast_name)
+{
+	if (!ast_name->valid) {
+		return;
+	}
+	pri_name->valid = 1;
+	pri_name->presentation = ast_to_pri_presentation(ast_name->presentation);
+	pri_name->char_set = ast_to_pri_char_set(ast_name->char_set);
+	if (!ast_strlen_zero(ast_name->str)) {
+		ast_copy_string(pri_name->str, ast_name->str, sizeof(pri_name->str));
+	}
+}
+
+/*!
+ * \internal
+ * \brief Fill in the PRI party number from the given asterisk party number.
+ * \since 1.8
+ *
+ * \param pri_number PRI party number structure.
+ * \param ast_number Asterisk party number structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes that pri_number has been previously memset to zero.
+ */
+static void sig_pri_party_number_from_ast(struct pri_party_number *pri_number, const struct ast_party_number *ast_number)
+{
+	if (!ast_number->valid) {
+		return;
+	}
+	pri_number->valid = 1;
+	pri_number->presentation = ast_to_pri_presentation(ast_number->presentation);
+	pri_number->plan = ast_number->plan;
+	if (!ast_strlen_zero(ast_number->str)) {
+		ast_copy_string(pri_number->str, ast_number->str, sizeof(pri_number->str));
+	}
+}
+
 /*!
  * \internal
  * \brief Fill in the PRI party id from the given asterisk party id.
@@ -702,21 +784,8 @@ static void sig_pri_party_subaddress_from_ast(struct pri_party_subaddress *pri_s
  */
 static void sig_pri_party_id_from_ast(struct pri_party_id *pri_id, const struct ast_party_id *ast_id)
 {
-	int presentation;
-
-	presentation = ast_to_pri_presentation(ast_id->number_presentation);
-	if (!ast_strlen_zero(ast_id->name)) {
-		pri_id->name.valid = 1;
-		pri_id->name.presentation = presentation;
-		pri_id->name.char_set = PRI_CHAR_SET_ISO8859_1;
-		ast_copy_string(pri_id->name.str, ast_id->name, sizeof(pri_id->name.str));
-	}
-	if (!ast_strlen_zero(ast_id->number)) {
-		pri_id->number.valid = 1;
-		pri_id->number.presentation = presentation;
-		pri_id->number.plan = ast_id->number_type;
-		ast_copy_string(pri_id->number.str, ast_id->number, sizeof(pri_id->number.str));
-	}
+	sig_pri_party_name_from_ast(&pri_id->name, &ast_id->name);
+	sig_pri_party_number_from_ast(&pri_id->number, &ast_id->number);
 #if defined(HAVE_PRI_SUBADDR)
 	sig_pri_party_subaddress_from_ast(&pri_id->subaddress, &ast_id->subaddress);
 #endif	/* defined(HAVE_PRI_SUBADDR) */
@@ -1488,10 +1557,8 @@ static void *pri_ss_thread(void *data)
 		exten[0] = 's';
 		exten[1] = '\0';
 	} else {
-		if (chan->cid.cid_dnid) {
-			ast_free(chan->cid.cid_dnid);
-		}
-		chan->cid.cid_dnid = ast_strdup(exten);
+		ast_free(chan->dialed.number.str);
+		chan->dialed.number.str = ast_strdup(exten);
 
 		if (p->pri->append_msn_to_user_tag && p->pri->nodetype != PRI_NETWORK) {
 			/*
@@ -1500,8 +1567,8 @@ static void *pri_ss_thread(void *data)
 			 */
 			snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
 				exten);
-			ast_free(chan->cid.cid_tag);
-			chan->cid.cid_tag = ast_strdup(p->user_tag);
+			ast_free(chan->caller.id.tag);
+			chan->caller.id.tag = ast_strdup(p->user_tag);
 		}
 	}
 	sig_pri_play_tone(p, -1);
@@ -1554,6 +1621,52 @@ void pri_event_noalarm(struct sig_pri_pri *pri, int index, int before_start_pri)
 		pri_restart(pri->dchans[index]);
 }
 
+/*!
+ * \internal
+ * \brief Convert libpri party name into asterisk party name.
+ * \since 1.8
+ *
+ * \param ast_name Asterisk party name structure to fill.  Must already be set initialized.
+ * \param pri_name libpri party name structure containing source information.
+ *
+ * \note The filled in ast_name structure needs to be destroyed by
+ * ast_party_name_free() when it is no longer needed.
+ *
+ * \return Nothing
+ */
+static void sig_pri_party_name_convert(struct ast_party_name *ast_name, const struct pri_party_name *pri_name)
+{
+	ast_name->str = ast_strdup(pri_name->str);
+	ast_name->char_set = pri_to_ast_char_set(pri_name->char_set);
+	ast_name->presentation = pri_to_ast_presentation(pri_name->presentation);
+	ast_name->valid = 1;
+}
+
+/*!
+ * \internal
+ * \brief Convert libpri party number into asterisk party number.
+ * \since 1.8
+ *
+ * \param ast_number Asterisk party number structure to fill.  Must already be set initialized.
+ * \param pri_number libpri party number structure containing source information.
+ * \param pri Span controlling structure.
+ *
+ * \note The filled in ast_number structure needs to be destroyed by
+ * ast_party_number_free() when it is no longer needed.
+ *
+ * \return Nothing
+ */
+static void sig_pri_party_number_convert(struct ast_party_number *ast_number, const struct pri_party_number *pri_number, struct sig_pri_pri *pri)
+{
+	char number[AST_MAX_EXTENSION];
+
+	apply_plan_to_number(number, sizeof(number), pri, pri_number->str, pri_number->plan);
+	ast_number->str = ast_strdup(number);
+	ast_number->plan = pri_number->plan;
+	ast_number->presentation = pri_to_ast_presentation(pri_number->presentation);
+	ast_number->valid = 1;
+}
+
 /*!
  * \internal
  * \brief Convert libpri party id into asterisk party id.
@@ -1568,22 +1681,13 @@ void pri_event_noalarm(struct sig_pri_pri *pri, int index, int before_start_pri)
  *
  * \return Nothing
  */
-static void sig_pri_party_id_convert(struct ast_party_id *ast_id,
-	const struct pri_party_id *pri_id, struct sig_pri_pri *pri)
+static void sig_pri_party_id_convert(struct ast_party_id *ast_id, const struct pri_party_id *pri_id, struct sig_pri_pri *pri)
 {
-	char number[AST_MAX_EXTENSION];
-
 	if (pri_id->name.valid) {
-		ast_id->name = ast_strdup(pri_id->name.str);
+		sig_pri_party_name_convert(&ast_id->name, &pri_id->name);
 	}
 	if (pri_id->number.valid) {
-		apply_plan_to_number(number, sizeof(number), pri, pri_id->number.str,
-			pri_id->number.plan);
-		ast_id->number = ast_strdup(number);
-		ast_id->number_type = pri_id->number.plan;
-	}
-	if (pri_id->name.valid || pri_id->number.valid) {
-		ast_id->number_presentation = overall_ast_presentation(pri_id);
+		sig_pri_party_number_convert(&ast_id->number, &pri_id->number, pri);
 	}
 #if defined(HAVE_PRI_SUBADDR)
 	if (pri_id->subaddress.valid) {
@@ -1667,13 +1771,41 @@ static int sig_pri_msn_match(const char *msn_patterns, const char *exten)
  */
 static void sig_pri_event_party_id(struct ast_str **msg, const char *prefix, struct ast_party_id *party)
 {
-	ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix,
-		party->number_presentation,
-		ast_describe_caller_presentation(party->number_presentation));
-	ast_str_append(msg, 0, "%sNum: %s\r\n", prefix, S_OR(party->number, ""));
-	ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number_type);
-	ast_str_append(msg, 0, "%sName: %s\r\n", prefix, S_OR(party->name, ""));
+	int pres;
+
+	/* Combined party presentation */
+	pres = ast_party_id_presentation(party);
+	ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, pres,
+		ast_describe_caller_presentation(pres));
+
+	/* Party number */
+	ast_str_append(msg, 0, "%sNumValid: %d\r\n", prefix,
+		(unsigned) party->number.valid);
+	ast_str_append(msg, 0, "%sNum: %s\r\n", prefix,
+		S_COR(party->number.valid, party->number.str, ""));
+	ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number.plan);
+	if (party->number.valid) {
+		ast_str_append(msg, 0, "%sNumPlan: %d\r\n", prefix, party->number.plan);
+		ast_str_append(msg, 0, "%sNumPres: %d (%s)\r\n", prefix,
+			party->number.presentation,
+			ast_describe_caller_presentation(party->number.presentation));
+	}
+
+	/* Party name */
+	ast_str_append(msg, 0, "%sNameValid: %d\r\n", prefix,
+		(unsigned) party->name.valid);
+	ast_str_append(msg, 0, "%sName: %s\r\n", prefix,
+		S_COR(party->name.valid, party->name.str, ""));
+	if (party->name.valid) {
+		ast_str_append(msg, 0, "%sNameCharSet: %s\r\n", prefix,
+			ast_party_name_charset_describe(party->name.char_set));
+		ast_str_append(msg, 0, "%sNamePres: %d (%s)\r\n", prefix,
+			party->name.presentation,
+			ast_describe_caller_presentation(party->name.presentation));
+	}
+
 #if defined(HAVE_PRI_SUBADDR)
+	/* Party subaddress */
 	if (party->subaddress.valid) {
 		static const char subaddress[] = "Subaddr";
 
@@ -3479,27 +3611,28 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
 				ast_connected.id.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
 
 				caller_id_update = 0;
-				if (ast_connected.id.name) {
+				if (ast_connected.id.name.str) {
 					/* Save name for Caller-ID update */
 					ast_copy_string(pri->pvts[chanpos]->cid_name,
-						ast_connected.id.name, sizeof(pri->pvts[chanpos]->cid_name));
+						ast_connected.id.name.str, sizeof(pri->pvts[chanpos]->cid_name));
 					caller_id_update = 1;
 				}
-				if (ast_connected.id.number) {
+				if (ast_connected.id.number.str) {
 					/* Save number for Caller-ID update */
-					ast_copy_string(pri->pvts[chanpos]->cid_num, ast_connected.id.number,
-						sizeof(pri->pvts[chanpos]->cid_num));
-					pri->pvts[chanpos]->cid_ton = ast_connected.id.number_type;
+					ast_copy_string(pri->pvts[chanpos]->cid_num,
+						ast_connected.id.number.str, sizeof(pri->pvts[chanpos]->cid_num));
+					pri->pvts[chanpos]->cid_ton = ast_connected.id.number.plan;
 					caller_id_update = 1;
 				} else {
-					ast_connected.id.number = ast_strdup("");
+					ast_connected.id.number.valid = 1;
+					ast_connected.id.number.str = ast_strdup("");
 				}
 				ast_connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 
 				pri->pvts[chanpos]->cid_subaddr[0] = '\0';
 #if defined(HAVE_PRI_SUBADDR)
 				if (ast_connected.id.subaddress.valid) {
-					ast_party_subaddress_set(&owner->cid.subaddress,
+					ast_party_subaddress_set(&owner->caller.id.subaddress,
 						&ast_connected.id.subaddress);
 					if (ast_connected.id.subaddress.str) {
 						ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
@@ -3510,17 +3643,17 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
 #endif	/* defined(HAVE_PRI_SUBADDR) */
 				if (caller_id_update) {
 					pri->pvts[chanpos]->callingpres =
-						ast_connected.id.number_presentation;
+						ast_party_id_presentation(&ast_connected.id);
 					sig_pri_set_caller_id(pri->pvts[chanpos]);
-					ast_set_callerid(owner, S_OR(ast_connected.id.number, NULL),
-						S_OR(ast_connected.id.name, NULL),
-						S_OR(ast_connected.id.number, NULL));
+					ast_set_callerid(owner, S_OR(ast_connected.id.number.str, NULL),
+						S_OR(ast_connected.id.name.str, NULL),
+						S_OR(ast_connected.id.number.str, NULL));
 				}
 
 				/* Update the connected line information on the other channel */
 				if (event_id != PRI_EVENT_RING) {
 					/* This connected_line update was not from a SETUP message. */
-					ast_channel_queue_connected_line_update(owner, &ast_connected);
+					ast_channel_queue_connected_line_update(owner, &ast_connected, NULL);
 				}
 
 				ast_party_connected_line_free(&ast_connected);
@@ -3538,10 +3671,10 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
 
 /*! \todo XXX Original called data can be put in a channel data store that is inherited. */
 
-				ast_channel_set_redirecting(owner, &ast_redirecting);
+				ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
 				if (event_id != PRI_EVENT_RING) {
 					/* This redirection was not from a SETUP message. */
-					ast_channel_queue_redirecting_update(owner, &ast_redirecting);
+					ast_channel_queue_redirecting_update(owner, &ast_redirecting, NULL);
 				}
 				ast_party_redirecting_free(&ast_redirecting);
 
@@ -3588,7 +3721,7 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
 					&owner->redirecting, pri);
 				ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
 				ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
-				ast_channel_set_redirecting(owner, &ast_redirecting);
+				ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
 				ast_party_redirecting_free(&ast_redirecting);
 
 				/*
@@ -4549,7 +4682,7 @@ static void *pri_dchannel(void *vpri)
 									/* Set Calling Subaddress */
 									sig_pri_lock_owner(pri, chanpos);
 									sig_pri_set_subaddress(
-										&pri->pvts[chanpos]->owner->cid.subaddress,
+										&pri->pvts[chanpos]->owner->caller.id.subaddress,
 										&e->ring.calling.subaddress);
 									if (!e->ring.calling.subaddress.type
 										&& !ast_strlen_zero(
@@ -4564,7 +4697,7 @@ static void *pri_dchannel(void *vpri)
 									/* Set Called Subaddress */
 									sig_pri_lock_owner(pri, chanpos);
 									sig_pri_set_subaddress(
-										&pri->pvts[chanpos]->owner->cid.dialed_subaddress,
+										&pri->pvts[chanpos]->owner->dialed.subaddress,
 										&e->ring.called_subaddress);
 									if (!e->ring.called_subaddress.type
 										&& !ast_strlen_zero(
@@ -4650,7 +4783,7 @@ static void *pri_dchannel(void *vpri)
 									/* Set Calling Subaddress */
 									sig_pri_lock_owner(pri, chanpos);
 									sig_pri_set_subaddress(
-										&pri->pvts[chanpos]->owner->cid.subaddress,
+										&pri->pvts[chanpos]->owner->caller.id.subaddress,
 										&e->ring.calling.subaddress);
 									if (!e->ring.calling.subaddress.type
 										&& !ast_strlen_zero(
@@ -4665,7 +4798,7 @@ static void *pri_dchannel(void *vpri)
 									/* Set Called Subaddress */
 									sig_pri_lock_owner(pri, chanpos);
 									sig_pri_set_subaddress(
-										&pri->pvts[chanpos]->owner->cid.dialed_subaddress,
+										&pri->pvts[chanpos]->owner->dialed.subaddress,
 										&e->ring.called_subaddress);
 									if (!e->ring.called_subaddress.type
 										&& !ast_strlen_zero(
@@ -5705,7 +5838,9 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 	struct ast_flags opts;
 	char *opt_args[OPT_ARG_ARRAY_SIZE];
 
-	ast_log(LOG_DEBUG, "CALLING CID_NAME: %s CID_NUM:: %s\n", ast->cid.cid_name, ast->cid.cid_num);
+	ast_log(LOG_DEBUG, "CALLER NAME: %s NUM: %s\n",
+		S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+		S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
 
 	if (!p->pri) {
 		ast_log(LOG_ERROR, "Could not find pri on channel %d\n", p->channel);
@@ -5764,9 +5899,9 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 	l = NULL;
 	n = NULL;
 	if (!p->hidecallerid) {
-		l = ast->connected.id.number;
+		l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
 		if (!p->hidecalleridname) {
-			n = ast->connected.id.name;
+			n = ast->connected.id.name.valid ? ast->connected.id.name.str : NULL;
 		}
 	}
 
@@ -5938,7 +6073,8 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 		snprintf(p->user_tag, sizeof(p->user_tag), "%s_%s", p->pri->initial_user_tag,
 			p->pri->nodetype == PRI_NETWORK
 				? c + p->stripmsd + dp_strip
-				: S_OR(ast->connected.id.number, ""));
+				: S_COR(ast->connected.id.number.valid,
+					ast->connected.id.number.str, ""));
 	} else {
 		ast_copy_string(p->user_tag, p->pri->initial_user_tag, sizeof(p->user_tag));
 	}
@@ -5947,8 +6083,8 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 	 * Replace the caller id tag from the channel creation
 	 * with the actual tag value.
 	 */
-	ast_free(ast->cid.cid_tag);
-	ast->cid.cid_tag = ast_strdup(p->user_tag);
+	ast_free(ast->caller.id.tag);
+	ast->caller.id.tag = ast_strdup(p->user_tag);
 
 	ldp_strip = 0;
 	prilocaldialplan = p->pri->localdialplan - 1;
@@ -6024,7 +6160,7 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
 		}
 	}
 	pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
-		p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
+		p->use_callingpres ? ast->connected.id.number.presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
 
 #if defined(HAVE_PRI_SUBADDR)
 	if (ast->connected.id.subaddress.valid) {
diff --git a/channels/sig_ss7.c b/channels/sig_ss7.c
index e3c0278ef13a5775e6108ef185a7d13e1efaebbf..7325b874b984b7e4dc1ee4df4fc13516b5ef647c 100644
--- a/channels/sig_ss7.c
+++ b/channels/sig_ss7.c
@@ -124,16 +124,22 @@ static void sig_ss7_set_caller_id(struct sig_ss7_chan *p)
 
 	if (p->calls->set_callerid) {
 		ast_party_caller_init(&caller);
-		caller.id.number = p->cid_num;
-		caller.id.name = p->cid_name;
+
+		caller.id.name.str = p->cid_name;
+		caller.id.name.presentation = p->callingpres;
+		caller.id.name.valid = 1;
+
+		caller.id.number.str = p->cid_num;
+		caller.id.number.plan = p->cid_ton;
+		caller.id.number.presentation = p->callingpres;
+		caller.id.number.valid = 1;
+
 		if (!ast_strlen_zero(p->cid_subaddr)) {
 			caller.id.subaddress.valid = 1;
 			//caller.id.subaddress.type = 0;/* nsap */
 			//caller.id.subaddress.odd_even_indicator = 0;
 			caller.id.subaddress.str = p->cid_subaddr;
 		}
-		caller.id.number_type = p->cid_ton;
-		caller.id.number_presentation = p->callingpres;
 		caller.ani = p->cid_ani;
 		caller.ani2 = p->cid_ani2;
 		p->calls->set_callerid(p->chan_pvt, &caller);
@@ -1255,7 +1261,7 @@ int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
 	}
 
 	if (!p->hidecallerid) {
-		l = ast->connected.id.number;
+		l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
 	} else {
 		l = NULL;
 	}
@@ -1301,8 +1307,8 @@ int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
 		}
 	}
 	isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
-		p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number_presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
-		p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number_presentation) : SS7_SCREENING_USER_PROVIDED );
+		p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number.presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
+		p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number.presentation) : SS7_SCREENING_USER_PROVIDED);
 
 	isup_set_oli(p->ss7call, ast->connected.ani2);
 	isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
diff --git a/funcs/func_blacklist.c b/funcs/func_blacklist.c
index a765242d4ff963b2c4a661b561c931a97286c0f2..b940b5891be801cc64261444081df4375b23bed0 100644
--- a/funcs/func_blacklist.c
+++ b/funcs/func_blacklist.c
@@ -57,12 +57,12 @@ static int blacklist_read(struct ast_channel *chan, const char *cmd, char *data,
 	char blacklist[1];
 	int bl = 0;
 
-	if (chan->cid.cid_num) {
-		if (!ast_db_get("blacklist", chan->cid.cid_num, blacklist, sizeof (blacklist)))
+	if (chan->caller.id.number.valid && chan->caller.id.number.str) {
+		if (!ast_db_get("blacklist", chan->caller.id.number.str, blacklist, sizeof (blacklist)))
 			bl = 1;
 	}
-	if (chan->cid.cid_name) {
-		if (!ast_db_get("blacklist", chan->cid.cid_name, blacklist, sizeof (blacklist)))
+	if (chan->caller.id.name.valid && chan->caller.id.name.str) {
+		if (!ast_db_get("blacklist", chan->caller.id.name.str, blacklist, sizeof (blacklist)))
 			bl = 1;
 	}
 
diff --git a/funcs/func_callerid.c b/funcs/func_callerid.c
index 357055c8c2df5aed3429e5e3866daf7b6226c744..98d58d07b55395e3435ad2166755b7ae6be5bd27 100644
--- a/funcs/func_callerid.c
+++ b/funcs/func_callerid.c
@@ -1,7 +1,7 @@
 /*
  * Asterisk -- An open source telephony toolkit.
  *
- * Copyright (C) 1999-2006, Digium, Inc.
+ * Copyright (C) 1999-2010, Digium, Inc.
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -16,9 +16,12 @@
 
 /*! \file
  *
- * \brief Caller ID related dialplan functions
+ * \brief Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)
  *
  * \ingroup functions
+ *
+ * See Also:
+ * \arg \ref AstCREDITS
  */
 
 #include "asterisk.h"
@@ -32,6 +35,41 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/callerid.h"
 
+/*
+ * Do not document the CALLERID(pres) datatype.
+ * The name and number now have their own presentation value.  The pres
+ * option will simply live on as a historical relic with as best
+ * as can be managed backward compatible meaning.
+ *
+ * Do not document the CALLERID(ton) datatype.
+ * It is an alias for num-plan.
+ *
+ * Do not document the CONNECTEDLINE(source) datatype.
+ * It has turned out to not be needed.  The source value is really
+ * only useful as a possible tracing aid.
+ *
+ * Do not document the CONNECTEDLINE(pres) datatype.
+ * The name and number now have their own presentation value.  The pres
+ * option will simply live on as a historical relic with as best
+ * as can be managed backward compatible meaning.
+ *
+ * Do not document the CONNECTEDLINE(ton) datatype.
+ * It is an alias for num-plan.
+ *
+ * Do not document the REDIRECTING(pres) datatype.
+ * It has turned out that the from-pres and to-pres values must be kept
+ * separate.  They represent two different parties and there is a case when
+ * they are active at the same time.  The plain pres option will simply
+ * live on as a historical relic.
+ *
+ * Do not document the REDIRECTING(from-pres) or REDIRECTING(to-pres) datatypes.
+ * The name and number now have their own presentation value.  The from-pres
+ * and to-pres options will simply live on as a historical relic with as best
+ * as can be managed backward compatible meaning.
+ *
+ * Do not document the REDIRECTING(from-ton) or REDIRECTING(to-ton) datatypes.
+ * They are aliases for from-num-plan and to-num-plan respectively.
+ */
 /*** DOCUMENTATION
 	<function name="CALLERID" language="en_US">
 		<synopsis>
@@ -41,21 +79,28 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 			<parameter name="datatype" required="true">
 				<para>The allowable datatypes are:</para>
 				<enumlist>
-					<enum name="all" />
-					<enum name="num" />
-					<enum name="name" />
-					<enum name="tag" />
-					<enum name="ANI" />
-					<enum name="DNID" />
-					<enum name="RDNIS" />
-					<enum name="pres" />
-					<enum name="ton" />
-					<enum name="subaddr[-valid]|[-type]|[-odd]">
-						<para>ISDN Calling Subaddress</para>
-					</enum>
-					<enum name="dnid-subaddr[-valid]|[-type]|[-odd]">
-						<para>ISDN Called Subaddress</para>
-					</enum>
+					<enum name = "all" />
+					<enum name = "name" />
+					<enum name = "name-valid" />
+					<enum name = "name-charset" />
+					<enum name = "name-pres" />
+					<enum name = "num" />
+					<enum name = "num-valid" />
+					<enum name = "num-plan" />
+					<enum name = "num-pres" />
+					<enum name = "subaddr" />
+					<enum name = "subaddr-valid" />
+					<enum name = "subaddr-type" />
+					<enum name = "subaddr-odd" />
+					<enum name = "tag" />
+					<enum name = "ANI" />
+					<enum name = "RDNIS" />
+					<enum name = "DNID" />
+					<enum name = "dnid-num-plan" />
+					<enum name = "dnid-subaddr" />
+					<enum name = "dnid-subaddr-valid" />
+					<enum name = "dnid-subaddr-type" />
+					<enum name = "dnid-subaddr-odd" />
 				</enumlist>
 			</parameter>
 			<parameter name="CID">
@@ -63,8 +108,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 			</parameter>
 		</syntax>
 		<description>
-			<para>Gets or sets Caller*ID data on the channel. Uses channel callerid by default or optional
-			callerid, if specified.</para>
+			<para>Gets or sets Caller*ID data on the channel. Uses channel callerid by
+			default or optional callerid, if specified.</para>
+			<para>The allowable values for the <replaceable>name-charset</replaceable>
+			field are the following:</para>
+			<enumlist>
+				<enum name = "unknown"><para>Unknown</para></enum>
+				<enum name = "iso8859-1"><para>ISO8859-1</para></enum>
+				<enum name = "withdrawn"><para>Withdrawn</para></enum>
+				<enum name = "iso8859-2"><para>ISO8859-2</para></enum>
+				<enum name = "iso8859-3"><para>ISO8859-3</para></enum>
+				<enum name = "iso8859-4"><para>ISO8859-4</para></enum>
+				<enum name = "iso8859-5"><para>ISO8859-5</para></enum>
+				<enum name = "iso8859-7"><para>ISO8859-7</para></enum>
+				<enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
+				<enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
+			</enumlist>
 		</description>
 	</function>
 	<function name="CALLERPRES" language="en_US">
@@ -73,8 +132,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 		</synopsis>
 		<syntax />
 		<description>
-			<para>Gets or sets Caller*ID presentation on the channel. The following values
-			are valid:</para>
+			<para>Gets or sets Caller*ID presentation on the channel.
+			This function is deprecated in favor of CALLERID(num-pres)
+			and CALLERID(name-pres).
+			The following values are valid:</para>
 			<enumlist>
 				<enum name="allowed_not_screened">
 					<para>Presentation Allowed, Not Screened.</para>
@@ -106,47 +167,731 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 			</enumlist>
 		</description>
 	</function>
+	<function name="CONNECTEDLINE" language="en_US">
+		<synopsis>
+			Gets or sets Connected Line data on the channel.
+		</synopsis>
+		<syntax>
+			<parameter name="datatype" required="true">
+				<para>The allowable datatypes are:</para>
+				<enumlist>
+					<enum name = "all" />
+					<enum name = "name" />
+					<enum name = "name-valid" />
+					<enum name = "name-charset" />
+					<enum name = "name-pres" />
+					<enum name = "num" />
+					<enum name = "num-valid" />
+					<enum name = "num-plan" />
+					<enum name = "num-pres" />
+					<enum name = "subaddr" />
+					<enum name = "subaddr-valid" />
+					<enum name = "subaddr-type" />
+					<enum name = "subaddr-odd" />
+					<enum name = "tag" />
+				</enumlist>
+			</parameter>
+			<parameter name="i">
+				<para>If set, this will prevent the channel from sending out protocol
+				messages because of the value being set</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Gets or sets Connected Line data on the channel.</para>
+			<para>The allowable values for the <replaceable>name-charset</replaceable>
+			field are the following:</para>
+			<enumlist>
+				<enum name = "unknown"><para>Unknown</para></enum>
+				<enum name = "iso8859-1"><para>ISO8859-1</para></enum>
+				<enum name = "withdrawn"><para>Withdrawn</para></enum>
+				<enum name = "iso8859-2"><para>ISO8859-2</para></enum>
+				<enum name = "iso8859-3"><para>ISO8859-3</para></enum>
+				<enum name = "iso8859-4"><para>ISO8859-4</para></enum>
+				<enum name = "iso8859-5"><para>ISO8859-5</para></enum>
+				<enum name = "iso8859-7"><para>ISO8859-7</para></enum>
+				<enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
+				<enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
+			</enumlist>
+		</description>
+	</function>
+	<function name="REDIRECTING" language="en_US">
+		<synopsis>
+			Gets or sets Redirecting data on the channel.
+		</synopsis>
+		<syntax>
+			<parameter name="datatype" required="true">
+				<para>The allowable datatypes are:</para>
+				<enumlist>
+					<enum name = "from-all" />
+					<enum name = "from-name" />
+					<enum name = "from-name-valid" />
+					<enum name = "from-name-charset" />
+					<enum name = "from-name-pres" />
+					<enum name = "from-num" />
+					<enum name = "from-num-valid" />
+					<enum name = "from-num-plan" />
+					<enum name = "from-num-pres" />
+					<enum name = "from-subaddr" />
+					<enum name = "from-subaddr-valid" />
+					<enum name = "from-subaddr-type" />
+					<enum name = "from-subaddr-odd" />
+					<enum name = "from-tag" />
+					<enum name = "to-all" />
+					<enum name = "to-name" />
+					<enum name = "to-name-valid" />
+					<enum name = "to-name-charset" />
+					<enum name = "to-name-pres" />
+					<enum name = "to-num" />
+					<enum name = "to-num-valid" />
+					<enum name = "to-num-plan" />
+					<enum name = "to-num-pres" />
+					<enum name = "to-subaddr" />
+					<enum name = "to-subaddr-valid" />
+					<enum name = "to-subaddr-type" />
+					<enum name = "to-subaddr-odd" />
+					<enum name = "to-tag" />
+					<enum name = "reason" />
+					<enum name = "count" />
+				</enumlist>
+			</parameter>
+			<parameter name="i">
+				<para>If set, this will prevent the channel from sending out protocol
+				messages because of the value being set</para>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Gets or sets Redirecting data on the channel.</para>
+			<para>The allowable values for the <replaceable>reason</replaceable>
+			field are the following:</para>
+			<enumlist>
+				<enum name = "unknown"><para>Unknown</para></enum>
+				<enum name = "cfb"><para>Call Forwarding Busy</para></enum>
+				<enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
+				<enum name = "unavailable"><para>Callee is Unavailable</para></enum>
+				<enum name = "time_of_day"><para>Time of Day</para></enum>
+				<enum name = "dnd"><para>Do Not Disturb</para></enum>
+				<enum name = "deflection"><para>Call Deflection</para></enum>
+				<enum name = "follow_me"><para>Follow Me</para></enum>
+				<enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
+				<enum name = "away"><para>Callee is Away</para></enum>
+				<enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
+				<enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
+			</enumlist>
+			<para>The allowable values for the <replaceable>xxx-name-charset</replaceable>
+			field are the following:</para>
+			<enumlist>
+				<enum name = "unknown"><para>Unknown</para></enum>
+				<enum name = "iso8859-1"><para>ISO8859-1</para></enum>
+				<enum name = "withdrawn"><para>Withdrawn</para></enum>
+				<enum name = "iso8859-2"><para>ISO8859-2</para></enum>
+				<enum name = "iso8859-3"><para>ISO8859-3</para></enum>
+				<enum name = "iso8859-4"><para>ISO8859-4</para></enum>
+				<enum name = "iso8859-5"><para>ISO8859-5</para></enum>
+				<enum name = "iso8859-7"><para>ISO8859-7</para></enum>
+				<enum name = "bmp"><para>ISO10646 Bmp String</para></enum>
+				<enum name = "utf8"><para>ISO10646 UTF-8 String</para></enum>
+			</enumlist>
+		</description>
+	</function>
  ***/
 
+enum ID_FIELD_STATUS {
+	ID_FIELD_VALID,
+	ID_FIELD_INVALID,
+	ID_FIELD_UNKNOWN
+};
+
+AST_DEFINE_APP_ARGS_TYPE(ast_party_func_args,
+	AST_APP_ARG(member);	/*!< Member name */
+	AST_APP_ARG(opts);		/*!< Options token */
+	AST_APP_ARG(other);		/*!< Any remining unused arguments */
+	);
+
+AST_DEFINE_APP_ARGS_TYPE(ast_party_members,
+	AST_APP_ARG(subnames[10]);	/*!< Option member subnames */
+	);
+
+enum CONNECTED_LINE_OPT_FLAGS {
+	CONNECTED_LINE_OPT_INHIBIT = (1 << 0),
+};
+enum CONNECTED_LINE_OPT_ARGS {
+	CONNECTED_LINE_OPT_DUMMY,	/*!< Delete this if CONNECTED_LINE ever gets an option with parameters. */
+
+	/*! \note This entry _MUST_ be the last one in the enum */
+	CONNECTED_LINE_OPT_ARG_ARRAY_SIZE
+};
+
+AST_APP_OPTIONS(connectedline_opts, BEGIN_OPTIONS
+	AST_APP_OPTION('i', CONNECTED_LINE_OPT_INHIBIT),
+END_OPTIONS);
+
+enum REDIRECTING_OPT_FLAGS {
+	REDIRECTING_OPT_INHIBIT = (1 << 0),
+};
+enum REDIRECTING_OPT_ARGS {
+	REDIRECTING_OPT_DUMMY,	/*!< Delete this if REDIRECTING ever gets an option with parameters. */
+
+	/*! \note This entry _MUST_ be the last one in the enum */
+	REDIRECTING_OPT_ARG_ARRAY_SIZE
+};
+
+AST_APP_OPTIONS(redirecting_opts, BEGIN_OPTIONS
+	AST_APP_OPTION('i', REDIRECTING_OPT_INHIBIT),
+END_OPTIONS);
+
+/*!
+ * \internal
+ * \brief Read values from the party name struct.
+ * \since 1.8
+ *
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer.
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param name Party name to get values from.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_name_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_name *name)
+{
+	enum ID_FIELD_STATUS status;
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 0) {
+		/* We want the name string */
+		if (name->valid && name->str) {
+			ast_copy_string(buf, name->str, len);
+		}
+	} else if (argc == 1 && !strcasecmp("valid", argv[0])) {
+		snprintf(buf, len, "%d", name->valid);
+	} else if (argc == 1 && !strcasecmp("charset", argv[0])) {
+		ast_copy_string(buf, ast_party_name_charset_str(name->char_set), len);
+	} else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
+		/* Accept pres[entation] */
+		ast_copy_string(buf, ast_named_caller_presentation(name->presentation), len);
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Read values from the party number struct.
+ * \since 1.8
+ *
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer.
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param number Party number to get values from.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_number_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_number *number)
+{
+	enum ID_FIELD_STATUS status;
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 0) {
+		/* We want the number string */
+		if (number->valid && number->str) {
+			ast_copy_string(buf, number->str, len);
+		}
+	} else if (argc == 1 && !strcasecmp("valid", argv[0])) {
+		snprintf(buf, len, "%d", number->valid);
+	} else if (argc == 1 && !strcasecmp("plan", argv[0])) {
+		snprintf(buf, len, "%d", number->plan);
+	} else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
+		/* Accept pres[entation] */
+		ast_copy_string(buf, ast_named_caller_presentation(number->presentation), len);
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Read values from the party subaddress struct.
+ * \since 1.8
+ *
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer.
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param subaddress Party subaddress to get values from.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_subaddress_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_subaddress *subaddress)
+{
+	enum ID_FIELD_STATUS status;
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 0) {
+		/* We want the subaddress string */
+		if (subaddress->str) {
+			ast_copy_string(buf, subaddress->str, len);
+		}
+	} else if (argc == 1 && !strcasecmp("valid", argv[0])) {
+		snprintf(buf, len, "%d", subaddress->valid);
+	} else if (argc == 1 && !strcasecmp("type", argv[0])) {
+		snprintf(buf, len, "%d", subaddress->type);
+	} else if (argc == 1 && !strcasecmp("odd", argv[0])) {
+		snprintf(buf, len, "%d", subaddress->odd_even_indicator);
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Read values from the party id struct.
+ * \since 1.8
+ *
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer.
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param id Party id to get values from.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_id_read(char *buf, size_t len, int argc, char *argv[], const struct ast_party_id *id)
+{
+	enum ID_FIELD_STATUS status;
+
+	if (argc == 0) {
+		/* Must have at least one subname. */
+		return ID_FIELD_UNKNOWN;
+	}
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 1 && !strcasecmp("all", argv[0])) {
+		snprintf(buf, len, "\"%s\" <%s>",
+			 S_COR(id->name.valid, id->name.str, ""),
+			 S_COR(id->number.valid, id->number.str, ""));
+	} else if (!strcasecmp("name", argv[0])) {
+		status = party_name_read(buf, len, argc - 1, argv + 1, &id->name);
+	} else if (!strncasecmp("num", argv[0], 3)) {
+		/* Accept num[ber] */
+		status = party_number_read(buf, len, argc - 1, argv + 1, &id->number);
+	} else if (!strncasecmp("subaddr", argv[0], 7)) {
+		/* Accept subaddr[ess] */
+		status = party_subaddress_read(buf, len, argc - 1, argv + 1, &id->subaddress);
+	} else if (argc == 1 && !strcasecmp("tag", argv[0])) {
+		if (id->tag) {
+			ast_copy_string(buf, id->tag, len);
+		}
+	} else if (argc == 1 && !strcasecmp("ton", argv[0])) {
+		/* ton is an alias for num-plan */
+		snprintf(buf, len, "%d", id->number.plan);
+	} else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
+		/*
+		 * Accept pres[entation]
+		 * This is the combined name/number presentation.
+		 */
+		ast_copy_string(buf,
+			ast_named_caller_presentation(ast_party_id_presentation(id)), len);
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Write new values to the party name struct
+ * \since 1.8
+ *
+ * \param name Party name struct to write values
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param value Value to assign to the party name.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_INVALID on error with field value.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_name_write(struct ast_party_name *name, int argc, char *argv[], const char *value)
+{
+	char *val;
+	enum ID_FIELD_STATUS status;
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 0) {
+		/* We are setting the name string */
+		name->valid = 1;
+		name->str = ast_strdup(value);
+		ast_trim_blanks(name->str);
+	} else if (argc == 1 && !strcasecmp("valid", argv[0])) {
+		name->valid = atoi(value) ? 1 : 0;
+	} else if (argc == 1 && !strcasecmp("charset", argv[0])) {
+		int char_set;
+
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			char_set = atoi(val);
+		} else {
+			char_set = ast_party_name_charset_parse(val);
+		}
+
+		if (char_set < 0) {
+			ast_log(LOG_ERROR,
+				"Unknown name char-set '%s', value unchanged\n", val);
+			status = ID_FIELD_INVALID;
+		} else {
+			name->char_set = char_set;
+		}
+	} else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
+		int pres;
+
+		/* Accept pres[entation] */
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			pres = atoi(val);
+		} else {
+			pres = ast_parse_caller_presentation(val);
+		}
+
+		if (pres < 0) {
+			ast_log(LOG_ERROR,
+				"Unknown name presentation '%s', value unchanged\n", val);
+			status = ID_FIELD_INVALID;
+		} else {
+			name->presentation = pres;
+		}
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Write new values to the party number struct
+ * \since 1.8
+ *
+ * \param number Party number struct to write values
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param value Value to assign to the party number.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_INVALID on error with field value.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_number_write(struct ast_party_number *number, int argc, char *argv[], const char *value)
+{
+	char *val;
+	enum ID_FIELD_STATUS status;
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 0) {
+		/* We are setting the number string */
+		number->valid = 1;
+		number->str = ast_strdup(value);
+		ast_trim_blanks(number->str);
+	} else if (argc == 1 && !strcasecmp("valid", argv[0])) {
+		number->valid = atoi(value) ? 1 : 0;
+	} else if (argc == 1 && !strcasecmp("plan", argv[0])) {
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			number->plan = atoi(val);
+		} else {
+			ast_log(LOG_ERROR,
+				"Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
+			status = ID_FIELD_INVALID;
+		}
+	} else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
+		int pres;
+
+		/* Accept pres[entation] */
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			pres = atoi(val);
+		} else {
+			pres = ast_parse_caller_presentation(val);
+		}
+
+		if (pres < 0) {
+			ast_log(LOG_ERROR,
+				"Unknown number presentation '%s', value unchanged\n", val);
+			status = ID_FIELD_INVALID;
+		} else {
+			number->presentation = pres;
+		}
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Write new values to the party subaddress struct
+ * \since 1.8
+ *
+ * \param subaddress Party subaddress struct to write values
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param value Value to assign to the party subaddress.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_INVALID on error with field value.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_subaddress_write(struct ast_party_subaddress *subaddress, int argc, char *argv[], const char *value)
+{
+	enum ID_FIELD_STATUS status;
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 0) {
+		/* We are setting the subaddress string */
+		subaddress->str = ast_strdup(value);
+		ast_trim_blanks(subaddress->str);
+	} else if (argc == 1 && !strcasecmp("valid", argv[0])) {
+		subaddress->valid = atoi(value) ? 1 : 0;
+	} else if (argc == 1 && !strcasecmp("type", argv[0])) {
+		subaddress->type = atoi(value) ? 2 : 0;
+	} else if (argc == 1 && !strcasecmp("odd", argv[0])) {
+		subaddress->odd_even_indicator = atoi(value) ? 1 : 0;
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*!
+ * \internal
+ * \brief Write new values to the party id struct
+ * \since 1.8
+ *
+ * \param id Party ID struct to write values
+ * \param argc Number of party member subnames.
+ * \param argv Party member subnames given.
+ * \param value Value to assign to the party id.
+ *
+ * \retval ID_FIELD_VALID on success.
+ * \retval ID_FIELD_INVALID on error with field value.
+ * \retval ID_FIELD_UNKNOWN on unknown field name.
+ */
+static enum ID_FIELD_STATUS party_id_write(struct ast_party_id *id, int argc, char *argv[], const char *value)
+{
+	char *val;
+	enum ID_FIELD_STATUS status;
+
+	if (argc == 0) {
+		/* Must have at least one subname. */
+		return ID_FIELD_UNKNOWN;
+	}
+
+	status = ID_FIELD_VALID;
+
+	if (argc == 1 && !strcasecmp("all", argv[0])) {
+		char name[256];
+		char num[256];
+
+		ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
+		id->name.valid = 1;
+		id->name.str = ast_strdup(name);
+		if (!id->name.str) {
+			return ID_FIELD_INVALID;
+		}
+		id->number.valid = 1;
+		id->number.str = ast_strdup(num);
+		if (!id->number.str) {
+			return ID_FIELD_INVALID;
+		}
+	} else if (!strcasecmp("name", argv[0])) {
+		status = party_name_write(&id->name, argc - 1, argv + 1, value);
+	} else if (!strncasecmp("num", argv[0], 3)) {
+		/* Accept num[ber] */
+		status = party_number_write(&id->number, argc - 1, argv + 1, value);
+	} else if (!strncasecmp("subaddr", argv[0], 7)) {
+		/* Accept subaddr[ess] */
+		status = party_subaddress_write(&id->subaddress, argc - 1, argv + 1, value);
+	} else if (argc == 1 && !strcasecmp("tag", argv[0])) {
+		id->tag = ast_strdup(value);
+		ast_trim_blanks(id->tag);
+	} else if (argc == 1 && !strcasecmp("ton", argv[0])) {
+		/* ton is an alias for num-plan */
+		argv[0] = "plan";
+		status = party_number_write(&id->number, argc, argv, value);
+	} else if (argc == 1 && !strncasecmp("pres", argv[0], 4)) {
+		int pres;
+
+		/*
+		 * Accept pres[entation]
+		 * This is the combined name/number presentation.
+		 */
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			pres = atoi(val);
+		} else {
+			pres = ast_parse_caller_presentation(val);
+		}
+
+		if (pres < 0) {
+			ast_log(LOG_ERROR,
+				"Unknown combined presentation '%s', value unchanged\n", val);
+			status = ID_FIELD_INVALID;
+		} else {
+			id->name.presentation = pres;
+			id->number.presentation = pres;
+		}
+	} else {
+		status = ID_FIELD_UNKNOWN;
+	}
+
+	return status;
+}
+
+/*! TRUE if we have already notified about CALLERPRES being deprecated. */
+static int callerpres_deprecate_notify;
+
+/*!
+ * \internal
+ * \brief Read values from the caller-id presentation information struct.
+ *
+ * \param chan Asterisk channel to read
+ * \param cmd Not used
+ * \param data Caller-id presentation function datatype string
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
 static int callerpres_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
-	ast_copy_string(buf, ast_named_caller_presentation(chan->cid.cid_pres), len);
+	if (!callerpres_deprecate_notify) {
+		callerpres_deprecate_notify = 1;
+		ast_log(LOG_WARNING, "CALLERPRES is deprecated."
+			"  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
+	}
+	ast_copy_string(buf,
+		ast_named_caller_presentation(ast_party_id_presentation(&chan->caller.id)), len);
 	return 0;
 }
 
+/*!
+ * \internal
+ * \brief Write new values to the caller-id presentation information struct.
+ *
+ * \param chan Asterisk channel to update
+ * \param cmd Not used
+ * \param data Caller-id presentation function datatype string
+ * \param value Value to assign to the caller-id presentation information struct.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
 static int callerpres_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
 {
-	int pres = ast_parse_caller_presentation(value);
-	if (pres < 0)
+	int pres;
+
+	if (!callerpres_deprecate_notify) {
+		callerpres_deprecate_notify = 1;
+		ast_log(LOG_WARNING, "CALLERPRES is deprecated."
+			"  Use CALLERID(name-pres) or CALLERID(num-pres) instead.\n");
+	}
+
+	pres = ast_parse_caller_presentation(value);
+	if (pres < 0) {
 		ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show function CALLERPRES')\n", value);
-	else
-		chan->cid.cid_pres = pres;
+	} else {
+		chan->caller.id.name.presentation = pres;
+		chan->caller.id.number.presentation = pres;
+	}
 	return 0;
 }
 
-static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
-			 char *buf, size_t len)
+/*!
+ * \internal
+ * \brief Read values from the caller-id information struct.
+ *
+ * \param chan Asterisk channel to read
+ * \param cmd Not used
+ * \param data Caller-id function datatype string
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int callerid_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 {
-	char *opt = data;
+	enum ID_FIELD_STATUS status;
+	char *parms;
+	struct ast_party_members member;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(member);	/*!< Member name */
+		AST_APP_ARG(cid);		/*!< Optional caller id to parse instead of from the channel. */
+		);
 
 	/* Ensure that the buffer is empty */
 	*buf = 0;
 
-	if (!chan)
+	if (!chan) {
 		return -1;
+	}
 
-	if (strchr(opt, ',')) {
-		char name[80], num[80];
+	parms = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parms);
+	if (args.argc == 0) {
+		/* Must have at least one argument. */
+		return -1;
+	}
+
+	AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
+	if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
+		/* Too few or too many subnames */
+		return -1;
+	}
 
-		data = strsep(&opt, ",");
-		ast_callerid_split(opt, name, sizeof(name), num, sizeof(num));
+	if (args.argc == 2) {
+		char name[80];
+		char num[80];
 
-		if (!strncasecmp("all", data, 3)) {
+		ast_callerid_split(args.cid, name, sizeof(name), num, sizeof(num));
+
+		if (member.argc == 1 && !strcasecmp("all", member.argv[0])) {
 			snprintf(buf, len, "\"%s\" <%s>", name, num);
-		} else if (!strncasecmp("name", data, 4)) {
+		} else if (member.argc == 1 && !strcasecmp("name", member.argv[0])) {
 			ast_copy_string(buf, name, len);
-		} else if (!strncasecmp("num", data, 3)) {
-			/* also matches "number" */
+		} else if (member.argc == 1 && !strncasecmp("num", member.argv[0], 3)) {
+			/* Accept num[ber] */
 			ast_copy_string(buf, num, len);
 		} else {
 			ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
@@ -154,75 +899,67 @@ static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
 	} else {
 		ast_channel_lock(chan);
 
-		if (!strncasecmp("all", data, 3)) {
-			snprintf(buf, len, "\"%s\" <%s>",
-				S_OR(chan->cid.cid_name, ""),
-				S_OR(chan->cid.cid_num, ""));
-		} else if (!strncasecmp("name", data, 4)) {
-			if (chan->cid.cid_name) {
-				ast_copy_string(buf, chan->cid.cid_name, len);
-			}
-		} else if (!strncasecmp("tag", data, 3)) {
-			if (chan->cid.cid_tag) {
-				ast_copy_string(buf, chan->cid.cid_tag, len);
+		if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
+			if (chan->redirecting.from.number.valid
+				&& chan->redirecting.from.number.str) {
+				ast_copy_string(buf, chan->redirecting.from.number.str, len);
 			}
-		} else if (!strncasecmp("num", data, 3)) {
-			/* also matches "number" */
-			if (chan->cid.cid_num) {
-				ast_copy_string(buf, chan->cid.cid_num, len);
+		} else if (!strcasecmp("dnid", member.argv[0])) {
+			if (member.argc == 1) {
+				/* Setup as if user had given dnid-num instead. */
+				member.argc = 2;
+				member.argv[1] = "num";
 			}
-		} else if (!strncasecmp("ani", data, 3)) {
-			if (!strncasecmp(data + 3, "2", 1)) {
-				snprintf(buf, len, "%d", chan->cid.cid_ani2);
-			} else if (chan->cid.cid_ani) {
-				ast_copy_string(buf, chan->cid.cid_ani, len);
-			}
-		} else if (!strncasecmp("dnid", data, 4)) {
-			/* Called parties info */
-
-			/* also matches dnid-subaddr-valid, dnid-subaddr-type, dnid-subaddr-odd, dnid-subaddr */
-			if (!strncasecmp(data + 4 ,"-subaddr", 8)) {
-				if (!strncasecmp(data + 12 ,"-valid", 6)) {		/* dnid-subaddr-valid */
-					snprintf(buf, len, "%d", chan->cid.dialed_subaddress.valid);
-				} else if (!strncasecmp(data + 12 ,"-type", 5)) {	/* dnid-subaddr-type */
-					snprintf(buf, len, "%d", chan->cid.dialed_subaddress.type);
-				} else if (!strncasecmp(data + 12 ,"-odd", 4)) {	/* dnid-subaddr-odd */
-					snprintf(buf, len, "%d", chan->cid.dialed_subaddress.odd_even_indicator);
-				} else {						/* dnid-subaddr */
-					if (chan->cid.dialed_subaddress.str) {
-						ast_copy_string(buf, chan->cid.dialed_subaddress.str, len);
+			if (!strncasecmp("num", member.argv[1], 3)) {
+				/*
+				 * Accept num[ber]
+				 * dnid-num...
+				 */
+				if (member.argc == 2) {
+					/* dnid-num */
+					if (chan->dialed.number.str) {
+						ast_copy_string(buf, chan->dialed.number.str, len);
 					}
+				} else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
+					/* dnid-num-plan */
+					snprintf(buf, len, "%d", chan->dialed.number.plan);
+				} else {
+					ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
 				}
-			} else {							/* dnid */
-				if (chan->cid.cid_dnid) {
-					ast_copy_string(buf, chan->cid.cid_dnid, len);
+			} else if (!strncasecmp("subaddr", member.argv[1], 7)) {
+				/*
+				 * Accept subaddr[ess]
+				 * dnid-subaddr...
+				 */
+				status = party_subaddress_read(buf, len, member.argc - 2, member.argv + 2,
+					&chan->dialed.subaddress);
+				switch (status) {
+				case ID_FIELD_VALID:
+				case ID_FIELD_INVALID:
+					break;
+				default:
+					ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+					break;
 				}
+			} else {
+				ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
 			}
-		} else if (!strncasecmp("subaddr", data, 7)) {
-			/* Calling parties info */
-
-			/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
-			if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
-				snprintf(buf, len, "%d", chan->cid.subaddress.valid);
-			} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
-				snprintf(buf, len, "%d", chan->cid.subaddress.type);
-			} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
-				snprintf(buf, len, "%d", chan->cid.subaddress.odd_even_indicator);
-			} else {						/* subaddr */
-				if (chan->cid.subaddress.str) {
-					ast_copy_string(buf, chan->cid.subaddress.str, len);
-				}
+		} else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
+			snprintf(buf, len, "%d", chan->caller.ani2);
+		} else if (member.argc == 1 && !strcasecmp("ani", member.argv[0])) {
+			if (chan->caller.ani) {
+				ast_copy_string(buf, chan->caller.ani, len);
 			}
-		} else if (!strncasecmp("rdnis", data, 5)) {
-			if (chan->redirecting.from.number) {
-				ast_copy_string(buf, chan->redirecting.from.number, len);
-			}
-		} else if (!strncasecmp("pres", data, 4)) {
-			ast_copy_string(buf, ast_named_caller_presentation(chan->cid.cid_pres), len);
-		} else if (!strncasecmp("ton", data, 3)) {
-			snprintf(buf, len, "%d", chan->cid.cid_ton);
 		} else {
-			ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+			status = party_id_read(buf, len, member.argc, member.argv, &chan->caller.id);
+			switch (status) {
+			case ID_FIELD_VALID:
+			case ID_FIELD_INVALID:
+				break;
+			default:
+				ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+				break;
+			}
 		}
 
 		ast_channel_unlock(chan);
@@ -231,126 +968,525 @@ static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
 	return 0;
 }
 
-static int callerid_write(struct ast_channel *chan, const char *cmd, char *data,
-			  const char *value)
+/*!
+ * \internal
+ * \brief Write new values to the caller-id information struct.
+ *
+ * \param chan Asterisk channel to update
+ * \param cmd Not used
+ * \param data Caller-id function datatype string
+ * \param value Value to assign to the caller-id information struct.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int callerid_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
 {
-	if (!value || !chan)
+	struct ast_party_caller caller;
+	struct ast_party_dialed dialed;
+	enum ID_FIELD_STATUS status;
+	char *val;
+	char *parms;
+	struct ast_party_func_args args;
+	struct ast_party_members member;
+
+	if (!value || !chan) {
 		return -1;
+	}
 
-	value = ast_skip_blanks(value);
+	parms = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parms);
+	if (args.argc == 0) {
+		/* Must have at least one argument. */
+		return -1;
+	}
 
-	if (!strncasecmp("all", data, 3)) {
-		char name[256];
-		char num[256];
+	AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
+	if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
+		/* Too few or too many subnames */
+		return -1;
+	}
 
-		ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
-		ast_set_callerid(chan, num, name, num);
-		if (chan->cdr) {
-			ast_cdr_setcid(chan->cdr, chan);
-		}
-	} else if (!strncasecmp("name", data, 4)) {
-		ast_set_callerid(chan, NULL, value, NULL);
+	value = ast_skip_blanks(value);
+
+	ast_channel_lock(chan);
+	if (member.argc == 1 && !strcasecmp("rdnis", member.argv[0])) {
+		chan->redirecting.from.number.valid = 1;
+		ast_free(chan->redirecting.from.number.str);
+		chan->redirecting.from.number.str = ast_strdup(value);
 		if (chan->cdr) {
 			ast_cdr_setcid(chan->cdr, chan);
 		}
-	} else if (!strncasecmp("num", data, 3)) {
-		/* also matches "number" */
-		ast_set_callerid(chan, value, NULL, NULL);
-		if (chan->cdr) {
-			ast_cdr_setcid(chan->cdr, chan);
+	} else if (!strcasecmp("dnid", member.argv[0])) {
+		ast_party_dialed_set_init(&dialed, &chan->dialed);
+		if (member.argc == 1) {
+			/* Setup as if user had given dnid-num instead. */
+			member.argc = 2;
+			member.argv[1] = "num";
 		}
-	} else if (!strncasecmp("tag", data, 3)) {
-		ast_channel_lock(chan);
-		if (chan->cid.cid_tag) {
-			ast_free(chan->cid.cid_tag);
+		if (!strncasecmp("num", member.argv[1], 3)) {
+			/*
+			 * Accept num[ber]
+			 * dnid-num...
+			 */
+			if (member.argc == 2) {
+				/* dnid-num */
+				dialed.number.str = ast_strdup(value);
+				ast_trim_blanks(dialed.number.str);
+				ast_party_dialed_set(&chan->dialed, &dialed);
+				if (chan->cdr) {
+					ast_cdr_setcid(chan->cdr, chan);
+				}
+			} else if (member.argc == 3 && !strcasecmp("plan", member.argv[2])) {
+				/* dnid-num-plan */
+				val = ast_strdupa(value);
+				ast_trim_blanks(val);
+
+				if (('0' <= val[0]) && (val[0] <= '9')) {
+					chan->dialed.number.plan = atoi(val);
+					if (chan->cdr) {
+						ast_cdr_setcid(chan->cdr, chan);
+					}
+				} else {
+					ast_log(LOG_ERROR,
+						"Unknown type-of-number/numbering-plan '%s', value unchanged\n", val);
+				}
+			} else {
+				ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+			}
+		} else if (!strncasecmp("subaddr", member.argv[1], 7)) {
+			/*
+			 * Accept subaddr[ess]
+			 * dnid-subaddr...
+			 */
+			status = party_subaddress_write(&dialed.subaddress, member.argc - 2,
+				member.argv + 2, value);
+			switch (status) {
+			case ID_FIELD_VALID:
+				ast_party_dialed_set(&chan->dialed, &dialed);
+				if (chan->cdr) {
+					ast_cdr_setcid(chan->cdr, chan);
+				}
+				break;
+			case ID_FIELD_INVALID:
+				break;
+			default:
+				ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+				break;
+			}
+		} else {
+			ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
 		}
-		chan->cid.cid_tag = ast_strdup(value);
-		ast_channel_unlock(chan);
-	} else if (!strncasecmp("ani", data, 3)) {
-		if (!strncasecmp(data + 3, "2", 1)) {
-			chan->cid.cid_ani2 = atoi(value);
+		ast_party_dialed_free(&dialed);
+	} else if (member.argc == 1 && !strcasecmp("ani2", member.argv[0])) {
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			chan->caller.ani2 = atoi(val);
+			if (chan->cdr) {
+				ast_cdr_setcid(chan->cdr, chan);
+			}
 		} else {
-			ast_set_callerid(chan, NULL, NULL, value);
+			ast_log(LOG_ERROR, "Unknown callerid ani2 '%s', value unchanged\n", val);
 		}
+	} else if (member.argc == 1 && !strcasecmp("ani", member.argv[0])) {
+		ast_party_caller_set_init(&caller, &chan->caller);
+		caller.ani = ast_strdup(value);
+		ast_trim_blanks(caller.ani);
+		ast_party_caller_set(&chan->caller, &caller, NULL);
 		if (chan->cdr) {
 			ast_cdr_setcid(chan->cdr, chan);
 		}
-	} else if (!strncasecmp("dnid", data, 4)) {
-		ast_channel_lock(chan);
-		/* also matches dnid-subaddr-valid, dnid-subaddr-type, dnid-subaddr-odd, dnid-subaddr */
-		if (!strncasecmp(data + 4 ,"-subaddr", 8)) {
-			if (!strncasecmp(data + 12 ,"-valid", 6)) {		/* dnid-subaddr-valid */
-				chan->cid.dialed_subaddress.valid = atoi(value) ? 1 : 0;
-			} else if (!strncasecmp(data + 12 ,"-type", 5)) {	/* dnid-subaddr-type */
-				chan->cid.dialed_subaddress.type = atoi(value) ? 2 : 0;
-			} else if (!strncasecmp(data + 12 ,"-odd", 4)) {	/* dnid-subaddr-odd */
-				chan->cid.dialed_subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
-			} else {						/* dnid-subaddr */
-				if (chan->cid.dialed_subaddress.str) {
-					ast_free(chan->cid.dialed_subaddress.str);
-				}
-				chan->cid.dialed_subaddress.str = ast_strdup(value);
-			}
-		} else {							/* dnid */
-			if (chan->cid.cid_dnid) {
-				ast_free(chan->cid.cid_dnid);
+		ast_party_caller_free(&caller);
+	} else {
+		ast_party_caller_set_init(&caller, &chan->caller);
+		status = party_id_write(&caller.id, member.argc, member.argv, value);
+		switch (status) {
+		case ID_FIELD_VALID:
+			ast_channel_set_caller_event(chan, &caller, NULL);
+			if (chan->cdr) {
+				ast_cdr_setcid(chan->cdr, chan);
 			}
-			chan->cid.cid_dnid = ast_strdup(value);
+			break;
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+			break;
 		}
+		ast_party_caller_free(&caller);
+	}
+	ast_channel_unlock(chan);
 
-		if (chan->cdr) {
-			ast_cdr_setcid(chan->cdr, chan);
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Read values from the connected line information struct.
+ *
+ * \param chan Asterisk channel to read
+ * \param cmd Not used
+ * \param data Connected line function datatype string
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+	struct ast_party_members member;
+	char *read_what;
+	enum ID_FIELD_STATUS status;
+
+	/* Ensure that the buffer is empty */
+	*buf = 0;
+
+	if (!chan) {
+		return -1;
+	}
+
+	read_what = ast_strdupa(data);
+	AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
+	if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
+		/* Too few or too many subnames */
+		return -1;
+	}
+
+	ast_channel_lock(chan);
+
+	if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
+		ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
+	} else {
+		status = party_id_read(buf, len, member.argc, member.argv, &chan->connected.id);
+		switch (status) {
+		case ID_FIELD_VALID:
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
+			break;
 		}
-		ast_channel_unlock(chan);
-	} else if (!strncasecmp("subaddr", data, 7)) {
-		ast_channel_lock(chan);
-		/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
-		if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
-			chan->cid.subaddress.valid = atoi(value) ? 1 : 0;
-		} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
-			chan->cid.subaddress.type = atoi(value) ? 2 : 0;
-		} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
-			chan->cid.subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
-		} else {						/* subaddr */
-			if (chan->cid.subaddress.str) {
-				ast_free(chan->cid.subaddress.str);
-			}
-			chan->cid.subaddress.str = ast_strdup(value);
+	}
+
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Write new values to the connected line information struct.
+ *
+ * \param chan Asterisk channel to update
+ * \param cmd Not used
+ * \param data Connected line function datatype string
+ * \param value Value to assign to the connected line information struct.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+	struct ast_party_connected_line connected;
+	enum ID_FIELD_STATUS status;
+	char *val;
+	char *parms;
+	void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
+	struct ast_party_func_args args;
+	struct ast_party_members member;
+	struct ast_flags opts;
+	char *opt_args[CONNECTED_LINE_OPT_ARG_ARRAY_SIZE];
+
+	if (!value || !chan) {
+		return -1;
+	}
+
+	parms = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parms);
+	if (args.argc == 0) {
+		/* Must have at least one argument. */
+		return -1;
+	}
+
+	AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
+	if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
+		/* Too few or too many subnames */
+		return -1;
+	}
+
+	if (ast_app_parse_options(connectedline_opts, &opts, opt_args, args.opts)) {
+		/* General invalid option syntax. */
+		return -1;
+	}
+
+	/* Determine if the update indication inhibit option is present */
+	if (ast_test_flag(&opts, CONNECTED_LINE_OPT_INHIBIT)) {
+		set_it = ast_channel_set_connected_line;
+	} else {
+		set_it = ast_channel_update_connected_line;
+	}
+
+	ast_channel_lock(chan);
+	ast_party_connected_line_set_init(&connected, &chan->connected);
+	ast_channel_unlock(chan);
+
+	value = ast_skip_blanks(value);
+
+	if (member.argc == 1 && !strcasecmp("source", member.argv[0])) {
+		int source;
+
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			source = atoi(val);
+		} else {
+			source = ast_connected_line_source_parse(val);
 		}
-		if (chan->cdr) {
-			ast_cdr_setcid(chan->cdr, chan);
+
+		if (source < 0) {
+			ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
+		} else {
+			connected.source = source;
+			set_it(chan, &connected, NULL);
 		}
-		ast_channel_unlock(chan);
-	} else if (!strncasecmp("rdnis", data, 5)) {
-		ast_channel_lock(chan);
-		ast_free(chan->redirecting.from.number);
-		chan->redirecting.from.number = ast_strdup(value);
-		if (chan->cdr) {
-			ast_cdr_setcid(chan->cdr, chan);
+	} else {
+		status = party_id_write(&connected.id, member.argc, member.argv, value);
+		switch (status) {
+		case ID_FIELD_VALID:
+			set_it(chan, &connected, NULL);
+			break;
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
+			break;
 		}
-		ast_channel_unlock(chan);
-	} else if (!strncasecmp("pres", data, 4)) {
-		int i;
-		char *val;
+		ast_party_connected_line_free(&connected);
+	}
+
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Read values from the redirecting information struct.
+ *
+ * \param chan Asterisk channel to read
+ * \param cmd Not used
+ * \param data Redirecting function datatype string
+ * \param buf Buffer to fill with read value.
+ * \param len Length of the buffer
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+{
+	struct ast_party_members member;
+	char *read_what;
+	enum ID_FIELD_STATUS status;
+
+	/* Ensure that the buffer is empty */
+	*buf = 0;
+
+	if (!chan) {
+		return -1;
+	}
+
+	read_what = ast_strdupa(data);
+	AST_NONSTANDARD_APP_ARGS(member, read_what, '-');
+	if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
+		/* Too few or too many subnames */
+		return -1;
+	}
+
+	ast_channel_lock(chan);
+
+	if (!strcasecmp("from", member.argv[0])) {
+		status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
+			&chan->redirecting.from);
+		switch (status) {
+		case ID_FIELD_VALID:
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
+			break;
+		}
+	} else if (!strcasecmp("to", member.argv[0])) {
+		status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
+			&chan->redirecting.to);
+		switch (status) {
+		case ID_FIELD_VALID:
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
+			break;
+		}
+	} else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
+		/*
+		 * Accept pres[entation]
+		 * This is the combined from name/number presentation.
+		 */
+		ast_copy_string(buf,
+			ast_named_caller_presentation(
+				ast_party_id_presentation(&chan->redirecting.from)), len);
+	} else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
+		ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
+	} else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
+		snprintf(buf, len, "%d", chan->redirecting.count);
+	} else {
+		ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
+	}
+
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
+/*!
+ * \internal
+ * \brief Write new values to the redirecting information struct.
+ *
+ * \param chan Asterisk channel to update
+ * \param cmd Not used
+ * \param data Redirecting function datatype string
+ * \param value Value to assign to the redirecting information struct.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
+{
+	struct ast_party_redirecting redirecting;
+	enum ID_FIELD_STATUS status;
+	char *val;
+	char *parms;
+	void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
+	struct ast_party_func_args args;
+	struct ast_party_members member;
+	struct ast_flags opts;
+	char *opt_args[REDIRECTING_OPT_ARG_ARRAY_SIZE];
+
+	if (!value || !chan) {
+		return -1;
+	}
+
+	parms = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parms);
+	if (args.argc == 0) {
+		/* Must have at least one argument. */
+		return -1;
+	}
+
+	AST_NONSTANDARD_APP_ARGS(member, args.member, '-');
+	if (member.argc == 0 || ARRAY_LEN(member.subnames) <= member.argc) {
+		/* Too few or too many subnames */
+		return -1;
+	}
+
+	if (ast_app_parse_options(redirecting_opts, &opts, opt_args, args.opts)) {
+		/* General invalid option syntax. */
+		return -1;
+	}
+
+	/* Determine if the update indication inhibit option is present */
+	if (ast_test_flag(&opts, REDIRECTING_OPT_INHIBIT)) {
+		set_it = ast_channel_set_redirecting;
+	} else {
+		set_it = ast_channel_update_redirecting;
+	}
+
+	ast_channel_lock(chan);
+	ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
+	ast_channel_unlock(chan);
+
+	value = ast_skip_blanks(value);
+
+	if (!strcasecmp("from", member.argv[0])) {
+		status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
+			value);
+		switch (status) {
+		case ID_FIELD_VALID:
+			set_it(chan, &redirecting, NULL);
+			break;
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
+			break;
+		}
+		ast_party_redirecting_free(&redirecting);
+	} else if (!strcasecmp("to", member.argv[0])) {
+		status = party_id_write(&redirecting.to, member.argc - 1, member.argv + 1, value);
+		switch (status) {
+		case ID_FIELD_VALID:
+			set_it(chan, &redirecting, NULL);
+			break;
+		case ID_FIELD_INVALID:
+			break;
+		default:
+			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
+			break;
+		}
+		ast_party_redirecting_free(&redirecting);
+	} else if (member.argc == 1 && !strncasecmp("pres", member.argv[0], 4)) {
+		int pres;
 
 		val = ast_strdupa(value);
 		ast_trim_blanks(val);
 
-		if ((val[0] >= '0') && (val[0] <= '9')) {
-			i = atoi(val);
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			pres = atoi(val);
+		} else {
+			pres = ast_parse_caller_presentation(val);
+		}
+
+		if (pres < 0) {
+			ast_log(LOG_ERROR,
+				"Unknown redirecting combined presentation '%s', value unchanged\n", val);
+		} else {
+			redirecting.from.name.presentation = pres;
+			redirecting.from.number.presentation = pres;
+			redirecting.to.name.presentation = pres;
+			redirecting.to.number.presentation = pres;
+			set_it(chan, &redirecting, NULL);
+		}
+	} else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
+		int reason;
+
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
+
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			reason = atoi(val);
+		} else {
+			reason = ast_redirecting_reason_parse(val);
+		}
+
+		if (reason < 0) {
+			ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
 		} else {
-			i = ast_parse_caller_presentation(val);
+			redirecting.reason = reason;
+			set_it(chan, &redirecting, NULL);
 		}
+	} else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
+		val = ast_strdupa(value);
+		ast_trim_blanks(val);
 
-		if (i < 0) {
-			ast_log(LOG_ERROR, "Unknown calling number presentation '%s', value unchanged\n", val);
+		if (('0' <= val[0]) && (val[0] <= '9')) {
+			redirecting.count = atoi(val);
+			set_it(chan, &redirecting, NULL);
 		} else {
-			chan->cid.cid_pres = i;
+			ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
 		}
-	} else if (!strncasecmp("ton", data, 3)) {
-		chan->cid.cid_ton = atoi(value);
 	} else {
-		ast_log(LOG_ERROR, "Unknown callerid data type '%s'.\n", data);
+		ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
 	}
 
 	return 0;
@@ -370,18 +1506,53 @@ static struct ast_custom_function callerpres_function = {
 	.write = callerpres_write,
 };
 
+static struct ast_custom_function connectedline_function = {
+	.name = "CONNECTEDLINE",
+	.read = connectedline_read,
+	.write = connectedline_write,
+};
+
+static struct ast_custom_function redirecting_function = {
+	.name = "REDIRECTING",
+	.read = redirecting_read,
+	.write = redirecting_write,
+};
+
+/*!
+ * \internal
+ * \brief Unload the function module
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
 static int unload_module(void)
 {
-	int res = ast_custom_function_unregister(&callerpres_function);
+	int res;
+
+	res = ast_custom_function_unregister(&callerpres_function);
 	res |= ast_custom_function_unregister(&callerid_function);
+	res |= ast_custom_function_unregister(&connectedline_function);
+	res |= ast_custom_function_unregister(&redirecting_function);
 	return res;
 }
 
+/*!
+ * \internal
+ * \brief Load and initialize the function module.
+ *
+ * \retval AST_MODULE_LOAD_SUCCESS on success.
+ * \retval AST_MODULE_LOAD_DECLINE on error.
+ */
 static int load_module(void)
 {
-	int res = ast_custom_function_register(&callerpres_function);
+	int res;
+
+	res = ast_custom_function_register(&callerpres_function);
 	res |= ast_custom_function_register(&callerid_function);
-	return res;
+	res |= ast_custom_function_register(&connectedline_function);
+	res |= ast_custom_function_register(&redirecting_function);
+	return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
 }
 
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Caller ID related dialplan functions");
+/* Do not wrap the following line. */
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Party ID related dialplan functions (Caller-ID, Connected-line, Redirecting)");
diff --git a/funcs/func_connectedline.c b/funcs/func_connectedline.c
deleted file mode 100644
index 95bcb23af36ebf408c262f972cc93fe2d0fd3da9..0000000000000000000000000000000000000000
--- a/funcs/func_connectedline.c
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2007, Gareth Palmer
- *
- * Gareth Palmer <gareth@acsdata.co.nz>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*! \file
- *
- * \brief Connected Line dialplan function
- *
- * \ingroup functions
- */
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "asterisk/module.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/logger.h"
-#include "asterisk/utils.h"
-#include "asterisk/app.h"
-#include "asterisk/options.h"
-#include "asterisk/callerid.h"
-
-/*
- * Do not document the CONNECTEDLINE(source) datatype.
- * It has turned out to not be needed.  The source value is really
- * only useful as a possible tracing aid.
- */
-/*** DOCUMENTATION
-	<function name="CONNECTEDLINE" language="en_US">
-		<synopsis>
-			Gets or sets Connected Line data on the channel.
-		</synopsis>
-		<syntax>
-			<parameter name="datatype" required="true">
-				<para>The allowable datatypes are:</para>
-				<enumlist>
-					<enum name = "all" />
-					<enum name = "num" />
-					<enum name = "name" />
-					<enum name = "tag" />
-					<enum name = "ton" />
-					<enum name = "pres" />
-					<enum name = "subaddr[-valid]|[-type]|[-odd]">
-						<para>ISDN Connected line subaddress</para>
-					</enum>
-				</enumlist>
-			</parameter>
-			<parameter name="i">
-				<para>If set, this will prevent the channel from sending out protocol
-				messages because of the value being set</para>
-			</parameter>
-		</syntax>
-		<description>
-			<para>Gets or sets Connected Line data on the channel.</para>
-		</description>
-	</function>
- ***/
-
-static int connectedline_read(struct ast_channel *chan, const char *cmd, char *data,
-			      char *buf, size_t len)
-{
-	/* Ensure that the buffer is empty */
-	*buf = 0;
-
-	if (!chan)
-		return -1;
-
-	ast_channel_lock(chan);
-
-	if (!strncasecmp("all", data, 3)) {
-		snprintf(buf, len, "\"%s\" <%s>",
-			 S_OR(chan->connected.id.name, ""),
-			 S_OR(chan->connected.id.number, ""));
-	} else if (!strncasecmp("name", data, 4)) {
-		if (chan->connected.id.name) {
-			ast_copy_string(buf, chan->connected.id.name, len);
-		}
-	} else if (!strncasecmp("num", data, 3)) {
-		if (chan->connected.id.number) {
-			ast_copy_string(buf, chan->connected.id.number, len);
-		}
-	} else if (!strncasecmp("tag", data, 3)) {
-		if (chan->connected.id.tag) {
-			ast_copy_string(buf, chan->connected.id.tag, len);
-		}
-	} else if (!strncasecmp("ton", data, 3)) {
-		snprintf(buf, len, "%d", chan->connected.id.number_type);
-	} else if (!strncasecmp("pres", data, 4)) {
-		ast_copy_string(buf, ast_named_caller_presentation(chan->connected.id.number_presentation), len);
-	} else if (!strncasecmp("source", data, 6)) {
-		ast_copy_string(buf, ast_connected_line_source_name(chan->connected.source), len);
-	} else if (!strncasecmp("subaddr", data, 7)) {
-		/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
-		if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
-			snprintf(buf, len, "%d", chan->connected.id.subaddress.valid);
-		} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
-			snprintf(buf, len, "%d", chan->connected.id.subaddress.type);
-		} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
-			snprintf(buf, len, "%d", chan->connected.id.subaddress.odd_even_indicator);
-		} else {						/* subaddr */
-			if (chan->connected.id.subaddress.str) {
-				ast_copy_string(buf, chan->connected.id.subaddress.str, len);
-			}
-		}
-	} else {
-		ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
-	}
-
-	ast_channel_unlock(chan);
-
-	return 0;
-}
-
-static int connectedline_write(struct ast_channel *chan, const char *cmd, char *data,
-			       const char *value)
-{
-	struct ast_party_connected_line connected;
-	char *val;
-	char *option;
-	void (*set_it)(struct ast_channel *chan, const struct ast_party_connected_line *connected);
-
-	if (!value || !chan) {
-		return -1;
-	}
-
-	/* Determine if the update indication inhibit option is present */
-	option = strchr(data, ',');
-	if (option) {
-		option = ast_skip_blanks(option + 1);
-		switch (*option) {
-		case 'i':
-			set_it = ast_channel_set_connected_line;
-			break;
-
-		default:
-			ast_log(LOG_ERROR, "Unknown connectedline option '%s'.\n", option);
-			return 0;
-		}
-	}
-	else {
-		set_it = ast_channel_update_connected_line;
-	}
-
-	ast_channel_lock(chan);
-	ast_party_connected_line_set_init(&connected, &chan->connected);
-	ast_channel_unlock(chan);
-
-	value = ast_skip_blanks(value);
-
-	if (!strncasecmp("all", data, 3)) {
-		char name[256];
-		char num[256];
-
-		ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
-		connected.id.name = name;
-		connected.id.number = num;
-		set_it(chan, &connected);
-	} else if (!strncasecmp("name", data, 4)) {
-		connected.id.name = ast_strdupa(value);
-		ast_trim_blanks(connected.id.name);
-		set_it(chan, &connected);
-	} else if (!strncasecmp("num", data, 3)) {
-		connected.id.number = ast_strdupa(value);
-		ast_trim_blanks(connected.id.number);
-		set_it(chan, &connected);
-	} else if (!strncasecmp("tag", data, 3)) {
-		connected.id.tag = ast_strdupa(value);
-		ast_trim_blanks(connected.id.tag);
-		set_it(chan, &connected);
-	} else if (!strncasecmp("ton", data, 3)) {
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			connected.id.number_type = atoi(val);
-			set_it(chan, &connected);
-		} else {
-			ast_log(LOG_ERROR, "Unknown connectedline type of number '%s', value unchanged\n", val);
-		}
-	} else if (!strncasecmp("pres", data, 4)) {
-		int pres;
-
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			pres = atoi(val);
-		} else {
-			pres = ast_parse_caller_presentation(val);
-		}
-
-		if (pres < 0) {
-			ast_log(LOG_ERROR, "Unknown connectedline number presentation '%s', value unchanged\n", val);
-		} else {
-			connected.id.number_presentation = pres;
-			set_it(chan, &connected);
-		}
-	} else if (!strncasecmp("source", data, 6)) {
-		int source;
-
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			source = atoi(val);
-		} else {
-			source = ast_connected_line_source_parse(val);
-		}
-
-		if (source < 0) {
-			ast_log(LOG_ERROR, "Unknown connectedline source '%s', value unchanged\n", val);
-		} else {
-			connected.source = source;
-			set_it(chan, &connected);
-		}
-	} else if (!strncasecmp("subaddr", data, 7)) { /* outbound: set calling subaddress */
-		/* also matches subaddr-valid, subaddr-type, subaddr-odd, subaddr */
-		if (!strncasecmp(data + 7 ,"-valid", 6)) {		/* subaddr-valid */
-			connected.id.subaddress.valid = atoi(value) ? 1 : 0;
-		} else if (!strncasecmp(data + 7 ,"-type", 5)) {	/* subaddr-type */
-			connected.id.subaddress.type = atoi(value) ? 2 : 0;
-		} else if (!strncasecmp(data + 7 ,"-odd", 4)) {		/* subaddr-odd */
-			connected.id.subaddress.odd_even_indicator = atoi(value) ? 1 : 0;
-		} else {						/* subaddr */
-			connected.id.subaddress.str = ast_strdupa(value);
-			ast_trim_blanks(connected.id.subaddress.str);
-		}
-		set_it(chan, &connected);
-	} else {
-		ast_log(LOG_ERROR, "Unknown connectedline data type '%s'.\n", data);
-	}
-
-	return 0;
-}
-
-static struct ast_custom_function connectedline_function = {
-	.name = "CONNECTEDLINE",
-	.read = connectedline_read,
-	.write = connectedline_write,
-};
-
-static int unload_module(void)
-{
-	return ast_custom_function_unregister(&connectedline_function);
-}
-
-static int load_module(void)
-{
-	return ast_custom_function_register(&connectedline_function)
-		? AST_MODULE_LOAD_DECLINE
-		: AST_MODULE_LOAD_SUCCESS;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Connected Line dialplan function");
diff --git a/funcs/func_dialplan.c b/funcs/func_dialplan.c
index 6ad9c1c9ba7403fd9e9f193d6d0efb52c7e14792..4e1ab3bed4558d0cd1cb980810b3da97300c218f 100644
--- a/funcs/func_dialplan.c
+++ b/funcs/func_dialplan.c
@@ -75,20 +75,20 @@ static int isexten_function_read(struct ast_channel *chan, const char *cmd, char
 		if (sscanf(args.priority, "%30d", &priority_num) == 1 && priority_num > 0) {
 			int res;
 			res = ast_exists_extension(chan, args.context, args.exten, priority_num, 
-				chan->cid.cid_num);
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
 			if (res)
 				strcpy(buf, "1");
 		} else {
 			int res;
-			res = ast_findlabel_extension(chan, args.context, args.exten, 
-				args.priority, chan->cid.cid_num);
+			res = ast_findlabel_extension(chan, args.context, args.exten, args.priority,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
 			if (res > 0)
 				strcpy(buf, "1");
 		}
 	} else if (!ast_strlen_zero(args.exten)) {
 		int res;
 		res = ast_exists_extension(chan, args.context, args.exten, 1, 
-			chan->cid.cid_num);
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
 		if (res)
 			strcpy(buf, "1");
 	} else if (!ast_strlen_zero(args.context)) {
diff --git a/funcs/func_redirecting.c b/funcs/func_redirecting.c
deleted file mode 100644
index 2f38c2f3b6e4b70f752f5966de2363a06b7c7122..0000000000000000000000000000000000000000
--- a/funcs/func_redirecting.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 2008 Digium, Inc.
- *
- * Richard Mudgett <rmudgett@digium.com>
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- * \brief Redirecting data dialplan function
- * \ingroup functions
- *
- * \author Richard Mudgett <rmudgett@digium.com>
- *
- * See Also:
- * \arg \ref AstCREDITS
- */
-
-
-#include "asterisk.h"
-
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-/* ------------------------------------------------------------------- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "asterisk/module.h"
-#include "asterisk/channel.h"
-#include "asterisk/pbx.h"
-#include "asterisk/logger.h"
-#include "asterisk/utils.h"
-#include "asterisk/app.h"
-#include "asterisk/options.h"
-#include "asterisk/callerid.h"
-
-/*
- * Do not document the REDIRECTING(pres) datatype.
- * It has turned out that the from-pres and to-pres values must be kept
- * separate.  They represent two different parties and there is a case when
- * they are active at the same time.  The plain pres option will simply
- * live on as a historical relic.
- */
-/*** DOCUMENTATION
-	<function name="REDIRECTING" language="en_US">
-		<synopsis>
-			Gets or sets Redirecting data on the channel.
-		</synopsis>
-		<syntax>
-			<parameter name="datatype" required="true">
-				<para>The allowable datatypes are:</para>
-				<enumlist>
-					<enum name = "from-all" />
-					<enum name = "from-num" />
-					<enum name = "from-name" />
-					<enum name = "from-tag" />
-					<enum name = "from-ton" />
-					<enum name = "from-pres" />
-					<enum name = "to-all" />
-					<enum name = "to-num" />
-					<enum name = "to-name" />
-					<enum name = "to-tag" />
-					<enum name = "to-ton" />
-					<enum name = "to-pres" />
-					<enum name = "reason" />
-					<enum name = "count" />
-				</enumlist>
-			</parameter>
-			<parameter name="i">
-				<para>If set, this will prevent the channel from sending out protocol
-				messages because of the value being set</para>
-			</parameter>
-		</syntax>
-		<description>
-			<para>Gets or sets Redirecting data on the channel. The allowable values
-			for the <replaceable>reason</replaceable> field are the following:</para>
-			<enumlist>
-				<enum name = "unknown"><para>Unknown</para></enum>
-				<enum name = "cfb"><para>Call Forwarding Busy</para></enum>
-				<enum name = "cfnr"><para>Call Forwarding No Reply</para></enum>
-				<enum name = "unavailable"><para>Callee is Unavailable</para></enum>
-				<enum name = "time_of_day"><para>Time of Day</para></enum>
-				<enum name = "dnd"><para>Do Not Disturb</para></enum>
-				<enum name = "deflection"><para>Call Deflection</para></enum>
-				<enum name = "follow_me"><para>Follow Me</para></enum>
-				<enum name = "out_of_order"><para>Called DTE Out-Of-Order</para></enum>
-				<enum name = "away"><para>Callee is Away</para></enum>
-				<enum name = "cf_dte"><para>Call Forwarding By The Called DTE</para></enum>
-				<enum name = "cfu"><para>Call Forwarding Unconditional</para></enum>
-			</enumlist>
-		</description>
-	</function>
- ***/
-
-enum ID_FIELD_STATUS {
-	ID_FIELD_VALID,
-	ID_FIELD_INVALID,
-	ID_FIELD_UNKNOWN
-};
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Read values from the party id struct.
- *
- * \param buf Buffer to fill with read value.
- * \param len Length of the buffer
- * \param data Remaining function datatype string
- *
- * \retval ID_FIELD_VALID on success.
- * \retval ID_FIELD_UNKNOWN on unknown field name.
- */
-static enum ID_FIELD_STATUS redirecting_id_read(char *buf, size_t len, char *data, const struct ast_party_id *id)
-{
-	enum ID_FIELD_STATUS status;
-
-	status = ID_FIELD_VALID;
-
-	if (!strncasecmp("all", data, 3)) {
-		snprintf(buf, len, "\"%s\" <%s>",
-			 S_OR(id->name, ""),
-			 S_OR(id->number, ""));
-	} else if (!strncasecmp("name", data, 4)) {
-		if (id->name) {
-			ast_copy_string(buf, id->name, len);
-		}
-	} else if (!strncasecmp("num", data, 3)) {
-		if (id->number) {
-			ast_copy_string(buf, id->number, len);
-		}
-	} else if (!strncasecmp("tag", data, 3)) {
-		if (id->tag) {
-			ast_copy_string(buf, id->tag, len);
-		}
-	} else if (!strncasecmp("ton", data, 3)) {
-		snprintf(buf, len, "%d", id->number_type);
-	} else if (!strncasecmp("pres", data, 4)) {
-		ast_copy_string(buf, ast_named_caller_presentation(id->number_presentation), len);
-	} else {
-		status = ID_FIELD_UNKNOWN;
-	}
-
-	return status;
-}
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Read values from the redirecting information struct.
- *
- * \param chan Asterisk channel to read
- * \param cmd Not used
- * \param data Redirecting function datatype string
- * \param buf Buffer to fill with read value.
- * \param len Length of the buffer
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int redirecting_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
-{
-	/* Ensure that the buffer is empty */
-	*buf = 0;
-
-	if (!chan)
-		return -1;
-
-	ast_channel_lock(chan);
-
-	if (!strncasecmp("from-", data, 5)) {
-		switch (redirecting_id_read(buf, len, data + 5, &chan->redirecting.from)) {
-		case ID_FIELD_VALID:
-		case ID_FIELD_INVALID:
-			break;
-
-		default:
-			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-			break;
-		}
-	} else if (!strncasecmp("to-", data, 3)) {
-		switch (redirecting_id_read(buf, len, data + 3, &chan->redirecting.to)) {
-		case ID_FIELD_VALID:
-		case ID_FIELD_INVALID:
-			break;
-
-		default:
-			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-			break;
-		}
-	} else if (!strncasecmp("pres", data, 4)) {
-		ast_copy_string(buf, ast_named_caller_presentation(chan->redirecting.from.number_presentation), len);
-	} else if (!strncasecmp("reason", data, 6)) {
-		ast_copy_string(buf, ast_redirecting_reason_name(chan->redirecting.reason), len);
-	} else if (!strncasecmp("count", data, 5)) {
-		snprintf(buf, len, "%d", chan->redirecting.count);
-	} else {
-		ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-	}
-
-	ast_channel_unlock(chan);
-
-	return 0;
-}
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Write new values to the party id struct
- *
- * \param id Party ID struct to write values
- * \param data Remaining function datatype string
- * \param value Value to assign to the party id.
- *
- * \retval ID_FIELD_VALID on success.
- * \retval ID_FIELD_INVALID on error with field value.
- * \retval ID_FIELD_UNKNOWN on unknown field name.
- */
-static enum ID_FIELD_STATUS redirecting_id_write(struct ast_party_id *id, char *data, const char *value)
-{
-	char *val;
-	enum ID_FIELD_STATUS status;
-
-	status = ID_FIELD_VALID;
-
-	if (!strncasecmp("all", data, 3)) {
-		char name[256];
-		char num[256];
-
-		ast_callerid_split(value, name, sizeof(name), num, sizeof(num));
-		if (!(id->name = ast_strdup(name))) {
-			return ID_FIELD_INVALID;
-		}
-		if (!(id->number = ast_strdup(num))) {
-			return ID_FIELD_INVALID;
-		}
-	} else if (!strncasecmp("name", data, 4)) {
-		id->name = ast_strdup(value);
-		ast_trim_blanks(id->name);
-	} else if (!strncasecmp("num", data, 3)) {
-		id->number = ast_strdup(value);
-		ast_trim_blanks(id->number);
-	} else if (!strncasecmp("tag", data, 3)) {
-		id->tag = ast_strdup(value);
-		ast_trim_blanks(id->tag);
-	} else if (!strncasecmp("ton", data, 3)) {
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			id->number_type = atoi(val);
-		} else {
-			ast_log(LOG_ERROR, "Unknown redirecting type of number '%s', value unchanged\n", val);
-			status = ID_FIELD_INVALID;
-		}
-	} else if (!strncasecmp("pres", data, 4)) {
-		int pres;
-
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			pres = atoi(val);
-		} else {
-			pres = ast_parse_caller_presentation(val);
-		}
-
-		if (pres < 0) {
-			ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val);
-			status = ID_FIELD_INVALID;
-		} else {
-			id->number_presentation = pres;
-		}
-	} else {
-		status = ID_FIELD_UNKNOWN;
-	}
-
-	return status;
-}
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Write new values to the redirecting information struct.
- *
- * \param chan Asterisk channel to update
- * \param cmd Not used
- * \param data Redirecting function datatype string
- * \param value Value to assign to the redirecting information struct.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int redirecting_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
-{
-	struct ast_party_redirecting redirecting;
-	char *val;
-	char *option;
-	void (*set_it)(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
-
-	if (!value || !chan) {
-		return -1;
-	}
-
-	/* Determine if the update indication inhibit option is present */
-	option = strchr(data, ',');
-	if (option) {
-		option = ast_skip_blanks(option + 1);
-		switch (*option) {
-		case 'i':
-			set_it = ast_channel_set_redirecting;
-			break;
-
-		default:
-			ast_log(LOG_ERROR, "Unknown redirecting option '%s'.\n", option);
-			return 0;
-		}
-	}
-	else {
-		set_it = ast_channel_update_redirecting;
-	}
-
-	ast_channel_lock(chan);
-	ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
-	ast_channel_unlock(chan);
-
-	value = ast_skip_blanks(value);
-
-	if (!strncasecmp("from-", data, 5)) {
-		switch (redirecting_id_write(&redirecting.from, data + 5, value)) {
-		case ID_FIELD_VALID:
-			set_it(chan, &redirecting);
-			break;
-
-		case ID_FIELD_INVALID:
-			break;
-
-		default:
-			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-			break;
-		}
-		ast_party_redirecting_free(&redirecting);
-	} else if (!strncasecmp("to-", data, 3)) {
-		switch (redirecting_id_write(&redirecting.to, data + 3, value)) {
-		case ID_FIELD_VALID:
-			set_it(chan, &redirecting);
-			break;
-
-		case ID_FIELD_INVALID:
-			break;
-
-		default:
-			ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-			break;
-		}
-		ast_party_redirecting_free(&redirecting);
-	} else if (!strncasecmp("pres", data, 4)) {
-		int pres;
-
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			pres = atoi(val);
-		} else {
-			pres = ast_parse_caller_presentation(val);
-		}
-
-		if (pres < 0) {
-			ast_log(LOG_ERROR, "Unknown redirecting number presentation '%s', value unchanged\n", val);
-		} else {
-			redirecting.from.number_presentation = pres;
-			redirecting.to.number_presentation = pres;
-			set_it(chan, &redirecting);
-		}
-	} else if (!strncasecmp("reason", data, 6)) {
-		int reason;
-
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			reason = atoi(val);
-		} else {
-			reason = ast_redirecting_reason_parse(val);
-		}
-
-		if (reason < 0) {
-			ast_log(LOG_ERROR, "Unknown redirecting reason '%s', value unchanged\n", val);
-		} else {
-			redirecting.reason = reason;
-			set_it(chan, &redirecting);
-		}
-	} else if (!strncasecmp("count", data, 5)) {
-		val = ast_strdupa(value);
-		ast_trim_blanks(val);
-
-		if (('0' <= val[0]) && (val[0] <= '9')) {
-			redirecting.count = atoi(val);
-			set_it(chan, &redirecting);
-		} else {
-			ast_log(LOG_ERROR, "Unknown redirecting count '%s', value unchanged\n", val);
-		}
-	} else {
-		ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
-	}
-
-	return 0;
-}
-
-
-
-
-static struct ast_custom_function redirecting_function = {
-	.name = "REDIRECTING",
-	.read = redirecting_read,
-	.write = redirecting_write,
-};
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Unload the function module
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int unload_module(void)
-{
-	return ast_custom_function_unregister(&redirecting_function);
-}
-
-
-
-
-/* ******************************************************************* */
-/*!
- * \internal
- * \brief Load and initialize the function module.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-static int load_module(void)
-{
-	return ast_custom_function_register(&redirecting_function)
-		? AST_MODULE_LOAD_DECLINE
-		: AST_MODULE_LOAD_SUCCESS;
-}
-
-
-
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Redirecting data dialplan function");
-
-
-/* ------------------------------------------------------------------- */
-/* end func_redirecting.c */
diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h
index 9428fcaa4eaa67c56c546abb73b22cc9df78dd6d..e052f64781625a5a511d43cb06e3088747dedff9 100644
--- a/include/asterisk/callerid.h
+++ b/include/asterisk/callerid.h
@@ -480,5 +480,36 @@ const char *ast_connected_line_source_describe(int data);
  */
 const char *ast_connected_line_source_name(int data);
 
+/*!
+ * \since 1.8
+ * \brief Convert ast_party_name.char_set text code to value (used in config file parsing)
+ *
+ * \param data text string from config file
+ *
+ * \retval AST_PARTY_CHAR_SET from channel.h
+ * \retval -1 if not in table
+ */
+int ast_party_name_charset_parse(const char *data);
+
+/*!
+ * \since 1.8
+ * \brief Convert ast_party_name.char_set value to explanatory string
+ *
+ * \param data AST_PARTY_CHAR_SET from channel.h
+ *
+ * \return string for human presentation
+ */
+const char *ast_party_name_charset_describe(int data);
+
+/*!
+ * \since 1.8
+ * \brief Convert ast_party_name.char_set value to text code
+ *
+ * \param data AST_PARTY_CHAR_SET from channel.h
+ *
+ * \return string for config file
+ */
+const char *ast_party_name_charset_str(int data);
+
 
 #endif /* _ASTERISK_CALLERID_H */
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index c61513065b9c348c67f5032e9100db33e39784f6..46d6c7476404802a8cf9832f1aff07918eded697 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -187,6 +187,65 @@ struct ast_generator {
 	void (*digit)(struct ast_channel *chan, char digit);
 };
 
+/*! Party name character set enumeration values (values from Q.SIG) */
+enum AST_PARTY_CHAR_SET {
+	AST_PARTY_CHAR_SET_UNKNOWN = 0,
+	AST_PARTY_CHAR_SET_ISO8859_1 = 1,
+	AST_PARTY_CHAR_SET_WITHDRAWN = 2,/* ITU withdrew this enum value. */
+	AST_PARTY_CHAR_SET_ISO8859_2 = 3,
+	AST_PARTY_CHAR_SET_ISO8859_3 = 4,
+	AST_PARTY_CHAR_SET_ISO8859_4 = 5,
+	AST_PARTY_CHAR_SET_ISO8859_5 = 6,
+	AST_PARTY_CHAR_SET_ISO8859_7 = 7,
+	AST_PARTY_CHAR_SET_ISO10646_BMPSTRING = 8,
+	AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING = 9,
+};
+
+/*!
+ * \since 1.8
+ * \brief Information needed to specify a name in a call.
+ * \note All string fields here are malloc'ed, so they need to be
+ * freed when the structure is deleted.
+ * \note NULL and "" must be considered equivalent.
+ */
+struct ast_party_name {
+	/*! \brief Subscriber name (Malloced) */
+	char *str;
+	/*!
+	 * \brief Character set the name is using.
+	 * \see enum AST_PARTY_CHAR_SET
+	 * \note
+	 * Set to AST_PARTY_CHAR_SET_ISO8859_1 if unsure what to use.
+	 * \todo Start using the party name character set value.  Not currently used.
+	 */
+	int char_set;
+	/*!
+	 * \brief Q.931 encoded presentation-indicator encoded field
+	 * \note Must tolerate the Q.931 screening-indicator field values being present.
+	 */
+	int presentation;
+	/*! \brief TRUE if the name information is valid/present */
+	unsigned char valid;
+};
+
+/*!
+ * \since 1.8
+ * \brief Information needed to specify a number in a call.
+ * \note All string fields here are malloc'ed, so they need to be
+ * freed when the structure is deleted.
+ * \note NULL and "" must be considered equivalent.
+ */
+struct ast_party_number {
+	/*! \brief Subscriber phone number (Malloced) */
+	char *str;
+	/*! \brief Q.931 Type-Of-Number and Numbering-Plan encoded fields */
+	int plan;
+	/*! \brief Q.931 presentation-indicator and screening-indicator encoded fields */
+	int presentation;
+	/*! \brief TRUE if the number information is valid/present */
+	unsigned char valid;
+};
+
 /*!
  * \since 1.8
  * \brief Information needed to specify a subaddress in a call.
@@ -219,123 +278,72 @@ struct ast_party_subaddress {
 };
 
 /*!
- * \brief Structure for all kinds of caller ID identifications.
+ * \since 1.8
+ * \brief Information needed to identify an endpoint in a call.
  * \note All string fields here are malloc'ed, so they need to be
  * freed when the structure is deleted.
- * Also, NULL and "" must be considered equivalent.
- *
- * \note SIP and IAX2 has utf8 encoded Unicode caller ID names.
- * In some cases, we also have an alternative (RPID) E.164 number that can be used
- * as caller ID on numeric E.164 phone networks (DAHDI or SIP/IAX2 to PSTN gateway).
- *
- * \todo Implement settings for transliteration between UTF8 caller ID names in
- *       to Ascii Caller ID's (DAHDI). Östen Åsklund might be transliterated into
- *       Osten Asklund or Oesten Aasklund depending upon language and person...
- *       We need automatic routines for incoming calls and static settings for
- *       our own accounts.
+ * \note NULL and "" must be considered equivalent.
  */
-struct ast_callerid {
-	/*!
-	 * \brief Malloc'd Dialed Number Identifier
-	 * (Field will eventually move to struct ast_channel.dialed.number)
-	 */
-	char *cid_dnid;
-
-	/*!
-	 * \brief Malloc'd Caller Number
-	 * (Field will eventually move to struct ast_channel.caller.id.number)
-	 */
-	char *cid_num;
-
-	/*!
-	 * \brief Malloc'd Caller Name (ASCII)
-	 * (Field will eventually move to struct ast_channel.caller.id.name)
-	 */
-	char *cid_name;
-
-	/*!
-	 * \brief Malloc'd Automatic Number Identification (ANI)
-	 * (Field will eventually move to struct ast_channel.caller.ani)
-	 */
-	char *cid_ani;
-
-	/*!
-	 * \brief Callerid Q.931 encoded number presentation/screening fields
-	 * (Field will eventually move to struct ast_channel.caller.id.number_presentation)
-	 */
-	int cid_pres;
-
-	/*!
-	 * \brief Callerid ANI 2 (Info digits)
-	 * (Field will eventually move to struct ast_channel.caller.ani2)
-	 */
-	int cid_ani2;
-
-	/*!
-	 * \brief Callerid Q.931 encoded type-of-number/numbering-plan fields
-	 * \note Currently this value is mostly just passed around the system.
-	 * The H.323 interfaces set the value from received messages and uses the value for sent messages.
-	 * The DAHDI PRI interfaces set the value from received messages but does not use it for sent messages.
-	 * You can read it and set it but only H.323 uses it.
-	 * (Field will eventually move to struct ast_channel.caller.id.number_type)
-	 */
-	int cid_ton;
-
-	/*!
-	 * \brief Callerid Transit Network Select
-	 * \note Currently this value is just passed around the system.
-	 * You can read it and set it but it is never used for anything.
-	 * (Field will eventually move to struct ast_channel.dialed.transit_network_select)
-	 */
-	int cid_tns;
+struct ast_party_id {
+	/*! \brief Subscriber name */
+	struct ast_party_name name;
+	/*! \brief Subscriber phone number */
+	struct ast_party_number number;
+	/*! \brief Subscriber subaddress. */
+	struct ast_party_subaddress subaddress;
 
 	/*!
-	 * \brief Callerid "Tag"
+	 * \brief User-set "tag"
+	 * \details
 	 * A user-settable field used to help associate some extrinsic information
-	 * about the channel or user of the channel to the caller ID. This information
-	 * is not transmitted over the wire and so is only useful within an Asterisk
-	 * environment.
-	 * (Field will eventually move to struct ast_channel.caller.id.tag)
+	 * about the channel or user of the channel to the party ID.  This information
+	 * is normally not transmitted over the wire and so is only useful within an
+	 * Asterisk environment.
 	 */
-	char *cid_tag;
+	char *tag;
+};
 
-	/*!
-	 * \brief Caller id subaddress.
-	 * (Field will eventually move to struct ast_channel.caller.id.subaddress)
-	 */
-	struct ast_party_subaddress subaddress;
-	/*!
-	 * \brief Dialed/Called subaddress.
-	 * (Field will eventually move to struct ast_channel.dialed.subaddress)
-	 */
-	struct ast_party_subaddress dialed_subaddress;
+/*!
+ * \since 1.8
+ * \brief Indicate what information in ast_party_id should be set.
+ */
+struct ast_set_party_id {
+	/*! TRUE if the ast_party_name information should be set. */
+	unsigned char name;
+	/*! TRUE if the ast_party_number information should be set. */
+	unsigned char number;
+	/*! TRUE if the ast_party_subaddress information should be set. */
+	unsigned char subaddress;
 };
 
 /*!
  * \since 1.8
- * \brief Information needed to identify an endpoint in a call.
+ * \brief Dialed/Called Party information.
+ * \note Dialed Number Identifier (DNID)
  * \note All string fields here are malloc'ed, so they need to be
  * freed when the structure is deleted.
  * \note NULL and "" must be considered equivalent.
  */
-struct ast_party_id {
-	/*! \brief Subscriber phone number (Malloced) */
-	char *number;
-
-	/*! \brief Subscriber name (Malloced) */
-	char *name;
-
-	/*! \brief User-set "tag" */
-	char *tag;
-
-	/*! \brief Subscriber subaddress. */
+struct ast_party_dialed {
+	/*!
+	 * \brief Dialed/Called number
+	 * \note Done this way in case we ever really need to use ast_party_number.
+	 * We currently do not need all of the ast_party_number fields.
+	 */
+	struct {
+		/*! \brief Subscriber phone number (Malloced) */
+		char *str;
+		/*! \brief Q.931 Type-Of-Number and Numbering-Plan encoded fields */
+		int plan;
+	} number;
+	/*! \brief Dialed/Called subaddress */
 	struct ast_party_subaddress subaddress;
-
-	/*! \brief Q.931 encoded type-of-number/numbering-plan fields */
-	int number_type;
-
-	/*! \brief Q.931 encoded number presentation/screening fields */
-	int number_presentation;
+	/*!
+	 * \brief Transit Network Select
+	 * \note Currently this value is just passed around the system.
+	 * You can read it and set it but it is never used for anything.
+	 */
+	int transit_network_select;
 };
 
 /*!
@@ -344,17 +352,41 @@ struct ast_party_id {
  * \note All string fields here are malloc'ed, so they need to be
  * freed when the structure is deleted.
  * \note NULL and "" must be considered equivalent.
+ *
+ * \note SIP and IAX2 has UTF8 encoded Unicode Caller ID names.
+ * In some cases, we also have an alternative (RPID) E.164 number that can
+ * be used as Caller ID on numeric E.164 phone networks (DAHDI or SIP/IAX2 to
+ * PSTN gateway).
+ *
+ * \todo Implement settings for transliteration between UTF8 Caller ID names in
+ *       to ASCII Caller ID's (DAHDI). Östen Åsklund might be transliterated into
+ *       Osten Asklund or Oesten Aasklund depending upon language and person...
+ *       We need automatic routines for incoming calls and static settings for
+ *       our own accounts.
  */
 struct ast_party_caller {
-	struct ast_party_id id;		/*! \brief Caller party ID */
+	/*! \brief Caller party ID */
+	struct ast_party_id id;
 
-	/*! \brief Automatic Number Identification (ANI) (Malloced) */
+	/*!
+	 * \brief Automatic Number Identification (ANI) (Malloced)
+	 * \todo BUGBUG This should be made an ast_party_id.
+	 */
 	char *ani;
 
 	/*! \brief Automatic Number Identification 2 (Info Digits) */
 	int ani2;
 };
 
+/*!
+ * \since 1.8
+ * \brief Indicate what information in ast_party_caller should be set.
+ */
+struct ast_set_party_caller {
+	/*! What caller id information to set. */
+	struct ast_set_party_id id;
+};
+
 /*!
  * \since 1.8
  * \brief Connected Line/Party information.
@@ -363,12 +395,14 @@ struct ast_party_caller {
  * \note NULL and "" must be considered equivalent.
  */
 struct ast_party_connected_line {
-	struct ast_party_id id;		/*! \brief Connected party ID */
+	/*! \brief Connected party ID */
+	struct ast_party_id id;
 
 	/*!
 	 * \brief Automatic Number Identification (ANI) (Malloced)
 	 * \note Not really part of connected line data but needed to
 	 * save the corresponding caller id value.
+	 * \todo BUGBUG This should be made an ast_party_id.
 	 */
 	char *ani;
 
@@ -387,6 +421,15 @@ struct ast_party_connected_line {
 	int source;
 };
 
+/*!
+ * \since 1.8
+ * \brief Indicate what information in ast_party_connected_line should be set.
+ */
+struct ast_set_party_connected_line {
+	/*! What connected line id information to set. */
+	struct ast_set_party_id id;
+};
+
 /*!
  * \since 1.8
  * \brief Redirecting Line information.
@@ -410,6 +453,17 @@ struct ast_party_redirecting {
 	int reason;
 };
 
+/*!
+ * \since 1.8
+ * \brief Indicate what information in ast_party_redirecting should be set.
+ */
+struct ast_set_party_redirecting {
+	/*! What redirecting-from id information to set. */
+	struct ast_set_party_id from;
+	/*! What redirecting-to id information to set. */
+	struct ast_set_party_id to;
+};
+
 /*!
  * \brief
  * Structure to describe a channel "technology", ie a channel driver
@@ -699,12 +753,19 @@ struct ast_channel {
 	struct timeval whentohangup;        		/*!< Non-zero, set to actual time when channel is to be hung up */
 	pthread_t blocker;				/*!< If anyone is blocking, this is them */
 
+	/*!
+	 * \brief Dialed/Called information.
+	 * \note Set on incoming channels to indicate the originally dialed party.
+	 * \note Dialed Number Identifier (DNID)
+	 */
+	struct ast_party_dialed dialed;
+
 	/*!
 	 * \brief Channel Caller ID information.
 	 * \note The caller id information is the caller id of this
 	 * channel when it is used to initiate a call.
 	 */
-	struct ast_callerid cid;
+	struct ast_party_caller caller;
 
 	/*!
 	 * \brief Channel Connected Line ID information.
@@ -1903,12 +1964,42 @@ int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen,
 void ast_deactivate_generator(struct ast_channel *chan);
 
 /*!
- * \brief Set caller ID number, name and ANI
+ * \brief Set caller ID number, name and ANI and generate AMI event.
  *
+ * \note Use ast_channel_set_caller() and ast_channel_set_caller_event() instead.
  * \note The channel does not need to be locked before calling this function.
  */
 void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani);
 
+/*!
+ * \brief Set the caller id information in the Asterisk channel
+ * \since 1.8
+ *
+ * \param chan Asterisk channel to set caller id information
+ * \param caller Caller id information
+ * \param update What caller information to update.  NULL if all.
+ *
+ * \return Nothing
+ *
+ * \note The channel does not need to be locked before calling this function.
+ */
+void ast_channel_set_caller(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update);
+
+/*!
+ * \brief Set the caller id information in the Asterisk channel and generate an AMI event
+ * if the caller id name or number changed.
+ * \since 1.8
+ *
+ * \param chan Asterisk channel to set caller id information
+ * \param caller Caller id information
+ * \param update What caller information to update.  NULL if all.
+ *
+ * \return Nothing
+ *
+ * \note The channel does not need to be locked before calling this function.
+ */
+void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update);
+
 /*! Set the file descriptor on the channel */
 void ast_channel_set_fd(struct ast_channel *chan, int which, int fd);
 
@@ -2408,6 +2499,128 @@ struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *cont
 void ast_channel_set_linkgroup(struct ast_channel *chan, struct ast_channel *peer);
 
 
+/*!
+ * \brief Initialize the given name structure.
+ * \since 1.8
+ *
+ * \param init Name structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_name_init(struct ast_party_name *init);
+
+/*!
+ * \brief Copy the source party name information to the destination party name.
+ * \since 1.8
+ *
+ * \param dest Destination party name
+ * \param src Source party name
+ *
+ * \return Nothing
+ */
+void ast_party_name_copy(struct ast_party_name *dest, const struct ast_party_name *src);
+
+/*!
+ * \brief Initialize the given party name structure using the given guide
+ * for a set update operation.
+ * \since 1.8
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated.  Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Party name structure to initialize.
+ * \param guide Source party name to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_name_set_init(struct ast_party_name *init, const struct ast_party_name *guide);
+
+/*!
+ * \brief Set the source party name information into the destination party name.
+ * \since 1.8
+ *
+ * \param dest The name one wishes to update
+ * \param src The new name values to update the dest
+ *
+ * \return Nothing
+ */
+void ast_party_name_set(struct ast_party_name *dest, const struct ast_party_name *src);
+
+/*!
+ * \brief Destroy the party name contents
+ * \since 1.8
+ *
+ * \param doomed The party name to destroy.
+ *
+ * \return Nothing
+ */
+void ast_party_name_free(struct ast_party_name *doomed);
+
+/*!
+ * \brief Initialize the given number structure.
+ * \since 1.8
+ *
+ * \param init Number structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_number_init(struct ast_party_number *init);
+
+/*!
+ * \brief Copy the source party number information to the destination party number.
+ * \since 1.8
+ *
+ * \param dest Destination party number
+ * \param src Source party number
+ *
+ * \return Nothing
+ */
+void ast_party_number_copy(struct ast_party_number *dest, const struct ast_party_number *src);
+
+/*!
+ * \brief Initialize the given party number structure using the given guide
+ * for a set update operation.
+ * \since 1.8
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated.  Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Party number structure to initialize.
+ * \param guide Source party number to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_number_set_init(struct ast_party_number *init, const struct ast_party_number *guide);
+
+/*!
+ * \brief Set the source party number information into the destination party number.
+ * \since 1.8
+ *
+ * \param dest The number one wishes to update
+ * \param src The new number values to update the dest
+ *
+ * \return Nothing
+ */
+void ast_party_number_set(struct ast_party_number *dest, const struct ast_party_number *src);
+
+/*!
+ * \brief Destroy the party number contents
+ * \since 1.8
+ *
+ * \param doomed The party number to destroy.
+ *
+ * \return Nothing
+ */
+void ast_party_number_free(struct ast_party_number *doomed);
+
 /*!
  * \since 1.8
  * \brief Initialize the given subaddress structure.
@@ -2431,7 +2644,7 @@ void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct a
 
 /*!
  * \since 1.8
- * \brief Initialize the given party subadress structure using the given guide
+ * \brief Initialize the given party subaddress structure using the given guide
  * for a set update operation.
  *
  * \details
@@ -2441,7 +2654,7 @@ void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct a
  * String values are simply set to NULL pointers if they are not going
  * to be updated.
  *
- * \param init Party Subaddress structure to initialize.
+ * \param init Party subaddress structure to initialize.
  * \param guide Source party subaddress to use as a guide in initializing.
  *
  * \return Nothing
@@ -2452,8 +2665,8 @@ void ast_party_subaddress_set_init(struct ast_party_subaddress *init, const stru
  * \since 1.8
  * \brief Set the source party subaddress information into the destination party subaddress.
  *
- * \param dest Destination party subaddress
- * \param src Source party subaddress
+ * \param dest The subaddress one wishes to update
+ * \param src The new subaddress values to update the dest
  *
  * \return Nothing
  */
@@ -2479,6 +2692,48 @@ void ast_party_subaddress_free(struct ast_party_subaddress *doomed);
  */
 void ast_party_id_init(struct ast_party_id *init);
 
+/*!
+ * \brief Copy the source party id information to the destination party id.
+ * \since 1.8
+ *
+ * \param dest Destination party id
+ * \param src Source party id
+ *
+ * \return Nothing
+ */
+void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src);
+
+/*!
+ * \brief Initialize the given party id structure using the given guide
+ * for a set update operation.
+ * \since 1.8
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated.  Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Party id structure to initialize.
+ * \param guide Source party id to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_id_set_init(struct ast_party_id *init, const struct ast_party_id *guide);
+
+/*!
+ * \brief Set the source party id information into the destination party id.
+ * \since 1.8
+ *
+ * \param dest The id one wishes to update
+ * \param src The new id values to update the dest
+ * \param update What id information to update.  NULL if all.
+ *
+ * \return Nothing
+ */
+void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_id *src, const struct ast_set_party_id *update);
+
 /*!
  * \brief Destroy the party id contents
  * \since 1.8
@@ -2489,6 +2744,80 @@ void ast_party_id_init(struct ast_party_id *init);
  */
 void ast_party_id_free(struct ast_party_id *doomed);
 
+/*!
+ * \brief Determine the overall presentation value for the given party.
+ * \since 1.8
+ *
+ * \param id Party to determine the overall presentation value.
+ *
+ * \return Overall presentation value for the given party.
+ */
+int ast_party_id_presentation(const struct ast_party_id *id);
+
+/*!
+ * \brief Initialize the given dialed structure.
+ * \since 1.8
+ *
+ * \param init Dialed structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_dialed_init(struct ast_party_dialed *init);
+
+/*!
+ * \brief Copy the source dialed party information to the destination dialed party.
+ * \since 1.8
+ *
+ * \param dest Destination dialed party
+ * \param src Source dialed party
+ *
+ * \return Nothing
+ */
+void ast_party_dialed_copy(struct ast_party_dialed *dest, const struct ast_party_dialed *src);
+
+/*!
+ * \brief Initialize the given dialed structure using the given
+ * guide for a set update operation.
+ * \since 1.8
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated.  Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Caller structure to initialize.
+ * \param guide Source dialed to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_dialed_set_init(struct ast_party_dialed *init, const struct ast_party_dialed *guide);
+
+/*!
+ * \brief Set the dialed information based on another dialed source
+ * \since 1.8
+ *
+ * This is similar to ast_party_dialed_copy, except that NULL values for
+ * strings in the src parameter indicate not to update the corresponding dest values.
+ *
+ * \param dest The dialed one wishes to update
+ * \param src The new dialed values to update the dest
+ *
+ * \return Nada
+ */
+void ast_party_dialed_set(struct ast_party_dialed *dest, const struct ast_party_dialed *src);
+
+/*!
+ * \brief Destroy the dialed party contents
+ * \since 1.8
+ *
+ * \param doomed The dialed party to destroy.
+ *
+ * \return Nothing
+ */
+void ast_party_dialed_free(struct ast_party_dialed *doomed);
+
 /*!
  * \since 1.8
  * \brief Initialize the given caller structure.
@@ -2508,7 +2837,51 @@ void ast_party_caller_init(struct ast_party_caller *init);
  *
  * \return Nothing
  */
-void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid *src);
+void ast_party_caller_copy(struct ast_party_caller *dest, const struct ast_party_caller *src);
+
+/*!
+ * \brief Initialize the given caller structure using the given
+ * guide for a set update operation.
+ * \since 1.8
+ *
+ * \details
+ * The initialization is needed to allow a set operation to know if a
+ * value needs to be updated.  Simple integers need the guide's original
+ * value in case the set operation is not trying to set a new value.
+ * String values are simply set to NULL pointers if they are not going
+ * to be updated.
+ *
+ * \param init Caller structure to initialize.
+ * \param guide Source caller to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide);
+
+/*!
+ * \brief Set the caller information based on another caller source
+ * \since 1.8
+ *
+ * This is similar to ast_party_caller_copy, except that NULL values for
+ * strings in the src parameter indicate not to update the corresponding dest values.
+ *
+ * \param dest The caller one wishes to update
+ * \param src The new caller values to update the dest
+ * \param update What caller information to update.  NULL if all.
+ *
+ * \return Nada
+ */
+void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update);
+
+/*!
+ * \brief Destroy the caller party contents
+ * \since 1.8
+ *
+ * \param doomed The caller party to destroy.
+ *
+ * \return Nothing
+ */
+void ast_party_caller_free(struct ast_party_caller *doomed);
 
 /*!
  * \since 1.8
@@ -2557,19 +2930,20 @@ void ast_party_connected_line_set_init(struct ast_party_connected_line *init, co
  * This is similar to ast_party_connected_line_copy, except that NULL values for
  * strings in the src parameter indicate not to update the corresponding dest values.
  *
- * \param src The source connected line to use as a guide to set the dest
  * \param dest The connected line one wishes to update
+ * \param src The new connected line values to update the dest
+ * \param update What connected line information to update.  NULL if all.
  *
- * \return Nada
+ * \return Nothing
  */
-void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src);
+void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update);
 
 /*!
  * \since 1.8
  * \brief Collect the caller party information into a connected line structure.
  *
  * \param connected Collected caller information for the connected line
- * \param cid Caller information.
+ * \param caller Caller information.
  *
  * \return Nothing
  *
@@ -2577,7 +2951,7 @@ void ast_party_connected_line_set(struct ast_party_connected_line *dest, const s
  * \warning DO NOT call ast_party_connected_line_free() on the filled in
  * connected line structure!
  */
-void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_callerid *cid);
+void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_party_caller *caller);
 
 /*!
  * \since 1.8
@@ -2589,6 +2963,16 @@ void ast_party_connected_line_collect_caller(struct ast_party_connected_line *co
  */
 void ast_party_connected_line_free(struct ast_party_connected_line *doomed);
 
+/*!
+ * \brief Initialize the given redirecting structure.
+ * \since 1.8
+ *
+ * \param init Redirecting structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_init(struct ast_party_redirecting *init);
+
 /*!
  * \since 1.8
  * \brief Copy the source redirecting information to the destination redirecting.
@@ -2619,6 +3003,21 @@ void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct
  */
 void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide);
 
+/*!
+ * \brief Set the redirecting information based on another redirecting source
+ * \since 1.8
+ *
+ * This is similar to ast_party_redirecting_copy, except that NULL values for
+ * strings in the src parameter indicate not to update the corresponding dest values.
+ *
+ * \param dest The redirecting one wishes to update
+ * \param src The new redirecting values to update the dest
+ * \param update What redirecting information to update.  NULL if all.
+ *
+ * \return Nothing
+ */
+void ast_party_redirecting_set(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src, const struct ast_set_party_redirecting *update);
+
 /*!
  * \since 1.8
  * \brief Destroy the redirecting information contents
@@ -2640,7 +3039,7 @@ void ast_party_redirecting_free(struct ast_party_redirecting *doomed);
  *
  * \note Assumes locks are already acquired
  */
-void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_callerid *src);
+void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src);
 
 /*!
  * \since 1.8
@@ -2653,7 +3052,7 @@ void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest,
  *
  * \note Assumes locks are already acquired
  */
-void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct ast_party_connected_line *src);
+void ast_connected_line_copy_to_caller(struct ast_party_caller *dest, const struct ast_party_connected_line *src);
 
 /*!
  * \since 1.8
@@ -2661,12 +3060,13 @@ void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct a
  *
  * \param chan Asterisk channel to set connected line information
  * \param connected Connected line information
+ * \param update What connected line information to update.  NULL if all.
  *
  * \return Nothing
  *
  * \note The channel does not need to be locked before calling this function.
  */
-void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected);
+void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
 
 /*!
  * \since 1.8
@@ -2675,11 +3075,12 @@ void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_p
  * \param data Buffer to fill with the frame data
  * \param datalen Size of the buffer to fill
  * \param connected Connected line information
+ * \param update What connected line information to build.  NULL if all.
  *
  * \retval -1 if error
  * \retval Amount of data buffer used
  */
-int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected);
+int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
 
 /*!
  * \since 1.8
@@ -2706,10 +3107,11 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str
  *
  * \param chan Asterisk channel to indicate connected line information
  * \param connected Connected line information
+ * \param update What connected line information to update.  NULL if all.
  *
  * \return Nothing
  */
-void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected);
+void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
 
 /*!
  * \since 1.8
@@ -2717,10 +3119,11 @@ void ast_channel_update_connected_line(struct ast_channel *chan, const struct as
  *
  * \param chan Asterisk channel to indicate connected line information
  * \param connected Connected line information
+ * \param update What connected line information to update.  NULL if all.
  *
  * \return Nothing
  */
-void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected);
+void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update);
 
 /*!
  * \since 1.8
@@ -2728,12 +3131,13 @@ void ast_channel_queue_connected_line_update(struct ast_channel *chan, const str
  *
  * \param chan Asterisk channel to set redirecting id information
  * \param redirecting Redirecting id information
+ * \param update What redirecting information to update.  NULL if all.
  *
  * \return Nothing
  *
  * \note The channel does not need to be locked before calling this function.
  */
-void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
+void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
 
 /*!
  * \since 1.8
@@ -2742,11 +3146,12 @@ void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_part
  * \param data Buffer to fill with the frame data
  * \param datalen Size of the buffer to fill
  * \param redirecting Redirecting id information
+ * \param update What redirecting information to build.  NULL if all.
  *
  * \retval -1 if error
  * \retval Amount of data buffer used
  */
-int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting);
+int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
 
 /*!
  * \since 1.8
@@ -2772,10 +3177,11 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
  *
  * \param chan Asterisk channel to indicate redirecting id information
  * \param redirecting Redirecting id information
+ * \param update What redirecting information to update.  NULL if all.
  *
  * \return Nothing
  */
-void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
+void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
 
 /*!
  * \since 1.8
@@ -2783,10 +3189,11 @@ void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_p
  *
  * \param chan Asterisk channel to indicate redirecting id information
  * \param redirecting Redirecting id information
+ * \param update What redirecting information to update.  NULL if all.
  *
  * \return Nothing
  */
-void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting);
+void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update);
 
 /*!
  * \since 1.8
diff --git a/main/app.c b/main/app.c
index 050c4e2389924d533d74298d1557231839da786e..e6ca51483e76917bc9c1f845c33fe34e23744ddc 100644
--- a/main/app.c
+++ b/main/app.c
@@ -105,13 +105,15 @@ int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect,
 			break;
 		}
 		collect[x++] = res;
-		if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num)) {
+		if (!ast_matchmore_extension(chan, context, collect, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			break;
 		}
 	}
 
 	if (res >= 0) {
-		res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0;
+		res = ast_exists_extension(chan, context, collect, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)) ? 1 : 0;
 	}
 
 	return res;
diff --git a/main/callerid.c b/main/callerid.c
index 17d265ed133df921db4043d35b8ce3178bc90f86..ac8fbde8b17541efde2620ec54d028e09ca845be 100644
--- a/main/callerid.c
+++ b/main/callerid.c
@@ -1282,3 +1282,58 @@ const char *ast_connected_line_source_name(int data)
 
 	return "not-known";
 }
+
+/*! \brief Translation table for ast_party_name char-set settings */
+static const struct ast_value_translation party_name_charset_tbl[] = {
+/* *INDENT-OFF* */
+	{ AST_PARTY_CHAR_SET_UNKNOWN,               "unknown",      "Unknown" },
+	{ AST_PARTY_CHAR_SET_ISO8859_1,             "iso8859-1",    "ISO8859-1" },
+	{ AST_PARTY_CHAR_SET_WITHDRAWN,             "withdrawn",    "Withdrawn" },
+	{ AST_PARTY_CHAR_SET_ISO8859_2,             "iso8859-2",    "ISO8859-2" },
+	{ AST_PARTY_CHAR_SET_ISO8859_3,             "iso8859-3",    "ISO8859-3" },
+	{ AST_PARTY_CHAR_SET_ISO8859_4,             "iso8859-4",    "ISO8859-4" },
+	{ AST_PARTY_CHAR_SET_ISO8859_5,             "iso8859-5",    "ISO8859-5" },
+	{ AST_PARTY_CHAR_SET_ISO8859_7,             "iso8859-7",    "ISO8859-7" },
+	{ AST_PARTY_CHAR_SET_ISO10646_BMPSTRING,    "bmp",          "ISO10646 Bmp String" },
+	{ AST_PARTY_CHAR_SET_ISO10646_UTF_8STRING,  "utf8",         "ISO10646 UTF-8 String" },
+/* *INDENT-ON* */
+};
+
+int ast_party_name_charset_parse(const char *data)
+{
+	int index;
+
+	for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
+		if (!strcasecmp(party_name_charset_tbl[index].name, data)) {
+			return party_name_charset_tbl[index].value;
+		}
+	}
+
+	return -1;
+}
+
+const char *ast_party_name_charset_describe(int data)
+{
+	int index;
+
+	for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
+		if (party_name_charset_tbl[index].value == data) {
+			return party_name_charset_tbl[index].description;
+		}
+	}
+
+	return "not-known";
+}
+
+const char *ast_party_name_charset_str(int data)
+{
+	int index;
+
+	for (index = 0; index < ARRAY_LEN(party_name_charset_tbl); ++index) {
+		if (party_name_charset_tbl[index].value == data) {
+			return party_name_charset_tbl[index].name;
+		}
+	}
+
+	return "not-known";
+}
diff --git a/main/ccss.c b/main/ccss.c
index efdcbb17fdb271c5d40692118ebe7a7694609a67..2cf8284704570631872593d239e8cf26f608c575 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -2339,11 +2339,11 @@ static int cc_generic_agent_init(struct ast_cc_agent *agent, struct ast_channel
 	}
 
 	generic_pvt->offer_timer_id = -1;
-	if (chan->cid.cid_num) {
-		ast_copy_string(generic_pvt->cid_num, chan->cid.cid_num, sizeof(generic_pvt->cid_num));
+	if (chan->caller.id.number.valid && chan->caller.id.number.str) {
+		ast_copy_string(generic_pvt->cid_num, chan->caller.id.number.str, sizeof(generic_pvt->cid_num));
 	}
-	if (chan->cid.cid_name) {
-		ast_copy_string(generic_pvt->cid_name, chan->cid.cid_name, sizeof(generic_pvt->cid_name));
+	if (chan->caller.id.name.valid && chan->caller.id.name.str) {
+		ast_copy_string(generic_pvt->cid_name, chan->caller.id.name.str, sizeof(generic_pvt->cid_name));
 	}
 	ast_copy_string(generic_pvt->exten, S_OR(chan->macroexten, chan->exten), sizeof(generic_pvt->exten));
 	ast_copy_string(generic_pvt->context, S_OR(chan->macrocontext, chan->context), sizeof(generic_pvt->context));
diff --git a/main/cdr.c b/main/cdr.c
index f14af2cb98af8643a40bced4c9aceecabb28d46d..9dca74ff330d8b4f4104f640ba7b0bd6cfa3a5ea 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -846,28 +846,25 @@ void ast_cdr_setdisposition(struct ast_cdr *cdr, long int disposition)
 /* set cid info for one record */
 static void set_one_cid(struct ast_cdr *cdr, struct ast_channel *c)
 {
-	/* Grab source from ANI or normal Caller*ID */
-	const char *num = S_OR(c->cid.cid_ani, c->cid.cid_num);
-	if (!cdr)
+	const char *num;
+
+	if (!cdr) {
 		return;
-	if (!ast_strlen_zero(c->cid.cid_name)) {
-		if (!ast_strlen_zero(num))	/* both name and number */
-			snprintf(cdr->clid, sizeof(cdr->clid), "\"%s\" <%s>", c->cid.cid_name, num);
-		else				/* only name */
-			ast_copy_string(cdr->clid, c->cid.cid_name, sizeof(cdr->clid));
-	} else if (!ast_strlen_zero(num)) {	/* only number */
-		ast_copy_string(cdr->clid, num, sizeof(cdr->clid));
-	} else {				/* nothing known */
-		cdr->clid[0] = '\0';
 	}
+
+	/* Grab source from ANI or normal Caller*ID */
+	num = S_OR(c->caller.ani,
+		S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL));
+	ast_callerid_merge(cdr->clid, sizeof(cdr->clid),
+		S_COR(c->caller.id.name.valid, c->caller.id.name.str, NULL), num, "");
 	ast_copy_string(cdr->src, S_OR(num, ""), sizeof(cdr->src));
-	ast_cdr_setvar(cdr, "dnid", S_OR(c->cid.cid_dnid, ""), 0);
+	ast_cdr_setvar(cdr, "dnid", S_OR(c->dialed.number.str, ""), 0);
 
-	if (c->cid.subaddress.valid) {
-		ast_cdr_setvar(cdr, "callingsubaddr", S_OR(c->cid.subaddress.str, ""), 0);
+	if (c->caller.id.subaddress.valid) {
+		ast_cdr_setvar(cdr, "callingsubaddr", S_OR(c->caller.id.subaddress.str, ""), 0);
 	}
-	if (c->cid.dialed_subaddress.valid) {
-		ast_cdr_setvar(cdr, "calledsubaddr", S_OR(c->cid.dialed_subaddress.str, ""), 0);
+	if (c->dialed.subaddress.valid) {
+		ast_cdr_setvar(cdr, "calledsubaddr", S_OR(c->dialed.subaddress.str, ""), 0);
 	}
 }
 
diff --git a/main/cel.c b/main/cel.c
index 2c6dd9b27d1d1d41d38efe27dcc655a3c951d8bf..52c62f6b894cddf83ddb141a55d6e17ba735021b 100644
--- a/main/cel.c
+++ b/main/cel.c
@@ -437,11 +437,14 @@ struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event
 		AST_LIST_INSERT_HEAD(headp, newvariable, entries);
 	}
 
-	tchan->cid.cid_name = ast_strdup(record.caller_id_name);
-	tchan->cid.cid_num = ast_strdup(record.caller_id_num);
-	tchan->cid.cid_ani = ast_strdup(record.caller_id_ani);
-	tchan->redirecting.from.number = ast_strdup(record.caller_id_rdnis);
-	tchan->cid.cid_dnid = ast_strdup(record.caller_id_dnid);
+	tchan->caller.id.name.valid = 1;
+	tchan->caller.id.name.str = ast_strdup(record.caller_id_name);
+	tchan->caller.id.number.valid = 1;
+	tchan->caller.id.number.str = ast_strdup(record.caller_id_num);
+	tchan->caller.ani = ast_strdup(record.caller_id_ani);
+	tchan->redirecting.from.number.valid = 1;
+	tchan->redirecting.from.number.str = ast_strdup(record.caller_id_rdnis);
+	tchan->dialed.number.str = ast_strdup(record.caller_id_dnid);
 
 	ast_copy_string(tchan->exten, record.extension, sizeof(tchan->exten));
 	ast_copy_string(tchan->context, record.context, sizeof(tchan->context));
@@ -526,29 +529,34 @@ int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event
 	ast_channel_lock(chan);
 
 	ev = ast_event_new(AST_EVENT_CEL,
-			AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
-			AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
-			AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
-			AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname,
-			AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_name, ""),
-			AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_num, ""),
-			AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_ani, ""),
-			AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->redirecting.from.number, ""),
-			AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_dnid, ""),
-			AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, chan->exten,
-			AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, chan->context,
-			AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, chan->name,
-			AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->appl, ""),
-			AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->data, ""),
-			AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, chan->amaflags,
-			AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, chan->accountcode,
-			AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, chan->peeraccount,
-			AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, chan->uniqueid,
-			AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, chan->linkedid,
-			AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, chan->userfield,
-			AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra,
-			AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername,
-			AST_EVENT_IE_END);
+		AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
+		AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
+		AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
+		AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname,
+		AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR,
+			S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""),
+		AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
+		AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR,
+			S_OR(chan->caller.ani, ""),
+		AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR,
+			S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, ""),
+		AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR,
+			S_OR(chan->dialed.number.str, ""),
+		AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, chan->exten,
+		AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, chan->context,
+		AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, chan->name,
+		AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->appl, ""),
+		AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->data, ""),
+		AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, chan->amaflags,
+		AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, chan->accountcode,
+		AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, chan->peeraccount,
+		AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, chan->uniqueid,
+		AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, chan->linkedid,
+		AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, chan->userfield,
+		AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra,
+		AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername,
+		AST_EVENT_IE_END);
 
 	ast_channel_unlock(chan);
 
diff --git a/main/channel.c b/main/channel.c
index ba420fbb9da6621d77851938a53c57d9cce74cc0..51cbd553bfa0e1219cbedc32a57af9e5195d9e6f 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -72,9 +72,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <sys/epoll.h>
 #endif
 
+#if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED)
 #if defined(HAVE_PRI)
 #include "libpri.h"
 #endif	/* defined(HAVE_PRI) */
+#endif	/* defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED) */
 
 struct ast_epoll_data {
 	struct ast_channel *chan;
@@ -139,6 +141,7 @@ static AST_RWLIST_HEAD_STATIC(backends, chanlist);
 #define NUM_CHANNEL_BUCKETS 1567
 #endif
 
+#if 0	/* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */
 #define DATA_EXPORT_CALLERID(MEMBER)				\
 	MEMBER(ast_callerid, cid_dnid, AST_DATA_STRING)		\
 	MEMBER(ast_callerid, cid_num, AST_DATA_STRING)		\
@@ -149,6 +152,7 @@ static AST_RWLIST_HEAD_STATIC(backends, chanlist);
 	MEMBER(ast_callerid, cid_tag, AST_DATA_STRING)
 
 AST_DATA_STRUCTURE(ast_callerid, DATA_EXPORT_CALLERID);
+#endif
 
 #define DATA_EXPORT_CHANNEL(MEMBER)						\
 	MEMBER(ast_channel, blockproc, AST_DATA_STRING)				\
@@ -283,6 +287,7 @@ static void channel_data_add_flags(struct ast_data *tree,
 	ast_data_add_bool(tree, "DISABLE_WORKAROUNDS", ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS));
 }
 
+#if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED)
 static const char *party_number_ton2str(int ton)
 {
 #if defined(HAVE_PRI)
@@ -306,7 +311,9 @@ static const char *party_number_ton2str(int ton)
 #endif	/* defined(HAVE_PRI) */
 	return "Unknown";
 }
+#endif	/* defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED) */
 
+#if defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED)
 static const char *party_number_plan2str(int plan)
 {
 #if defined(HAVE_PRI)
@@ -330,14 +337,22 @@ static const char *party_number_plan2str(int plan)
 #endif	/* defined(HAVE_PRI) */
 	return "Unknown";
 }
+#endif	/* defined(KEEP_TILL_CHANNEL_PARTY_NUMBER_INFO_NEEDED) */
 
 int ast_channel_data_add_structure(struct ast_data *tree,
 	struct ast_channel *chan, int add_bridged)
 {
 	struct ast_channel *bc;
-	struct ast_data *data_bridged, *data_cdr, *data_flags, *data_zones;
-	struct ast_data *data_callerid, *enum_node, *data_softhangup;
+	struct ast_data *data_bridged;
+	struct ast_data *data_cdr;
+	struct ast_data *data_flags;
+	struct ast_data *data_zones;
+	struct ast_data *enum_node;
+	struct ast_data *data_softhangup;
+#if 0	/* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */
+	struct ast_data *data_callerid;
 	char value_str[100];
+#endif
 
 	if (!tree) {
 		return -1;
@@ -417,6 +432,7 @@ int ast_channel_data_add_structure(struct ast_data *tree,
 
 	ast_data_add_uint(tree, "timetohangup", chan->whentohangup.tv_sec);
 
+#if 0	/* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */
 	/* callerid */
 	data_callerid = ast_data_add_node(tree, "callerid");
 	if (!data_callerid) {
@@ -433,6 +449,7 @@ int ast_channel_data_add_structure(struct ast_data *tree,
 		party_number_ton2str(chan->cid.cid_ton),
 		party_number_plan2str(chan->cid.cid_ton));
 	ast_data_add_str(enum_node, "text", value_str);
+#endif
 
 	/* tone zone */
 	if (chan->zone) {
@@ -1090,13 +1107,22 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
 		return ast_channel_unref(tmp);
 	}
 	
+	ast_party_dialed_init(&tmp->dialed);
+	ast_party_caller_init(&tmp->caller);
+	ast_party_connected_line_init(&tmp->connected);
+	ast_party_redirecting_init(&tmp->redirecting);
+
 	if (cid_name) {
-		if (!(tmp->cid.cid_name = ast_strdup(cid_name))) {
+		tmp->caller.id.name.valid = 1;
+		tmp->caller.id.name.str = ast_strdup(cid_name);
+		if (!tmp->caller.id.name.str) {
 			return ast_channel_unref(tmp);
 		}
 	}
 	if (cid_num) {
-		if (!(tmp->cid.cid_num = ast_strdup(cid_num))) {
+		tmp->caller.id.number.valid = 1;
+		tmp->caller.id.number.str = ast_strdup(cid_num);
+		if (!tmp->caller.id.number.str) {
 			return ast_channel_unref(tmp);
 		}
 	}
@@ -1762,23 +1788,6 @@ int ast_safe_sleep(struct ast_channel *chan, int ms)
 	return ast_safe_sleep_conditional(chan, ms, NULL, NULL);
 }
 
-static void free_cid(struct ast_callerid *cid)
-{
-	if (cid->cid_dnid)
-		ast_free(cid->cid_dnid);
-	if (cid->cid_num)
-		ast_free(cid->cid_num);	
-	if (cid->cid_name)
-		ast_free(cid->cid_name);	
-	if (cid->cid_ani)
-		ast_free(cid->cid_ani);
-	if (cid->cid_tag)
-		ast_free(cid->cid_tag);
-	cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = NULL;
-	ast_party_subaddress_free(&cid->subaddress);
-	ast_party_subaddress_free(&cid->dialed_subaddress);
-}
-
 struct ast_channel *ast_channel_release(struct ast_channel *chan)
 {
 	/* Safe, even if already unlinked. */
@@ -1786,6 +1795,112 @@ struct ast_channel *ast_channel_release(struct ast_channel *chan)
 	return ast_channel_unref(chan);
 }
 
+void ast_party_name_init(struct ast_party_name *init)
+{
+	init->str = NULL;
+	init->char_set = AST_PARTY_CHAR_SET_ISO8859_1;
+	init->presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	init->valid = 0;
+}
+
+void ast_party_name_copy(struct ast_party_name *dest, const struct ast_party_name *src)
+{
+	if (dest == src) {
+		/* Don't copy to self */
+		return;
+	}
+
+	ast_free(dest->str);
+	dest->str = ast_strdup(src->str);
+	dest->char_set = src->char_set;
+	dest->presentation = src->presentation;
+	dest->valid = src->valid;
+}
+
+void ast_party_name_set_init(struct ast_party_name *init, const struct ast_party_name *guide)
+{
+	init->str = NULL;
+	init->char_set = guide->char_set;
+	init->presentation = guide->presentation;
+	init->valid = guide->valid;
+}
+
+void ast_party_name_set(struct ast_party_name *dest, const struct ast_party_name *src)
+{
+	if (dest == src) {
+		/* Don't set to self */
+		return;
+	}
+
+	if (src->str && src->str != dest->str) {
+		ast_free(dest->str);
+		dest->str = ast_strdup(src->str);
+	}
+
+	dest->char_set = src->char_set;
+	dest->presentation = src->presentation;
+	dest->valid = src->valid;
+}
+
+void ast_party_name_free(struct ast_party_name *doomed)
+{
+	ast_free(doomed->str);
+	doomed->str = NULL;
+}
+
+void ast_party_number_init(struct ast_party_number *init)
+{
+	init->str = NULL;
+	init->plan = 0;/* Unknown */
+	init->presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	init->valid = 0;
+}
+
+void ast_party_number_copy(struct ast_party_number *dest, const struct ast_party_number *src)
+{
+	if (dest == src) {
+		/* Don't copy to self */
+		return;
+	}
+
+	ast_free(dest->str);
+	dest->str = ast_strdup(src->str);
+	dest->plan = src->plan;
+	dest->presentation = src->presentation;
+	dest->valid = src->valid;
+}
+
+void ast_party_number_set_init(struct ast_party_number *init, const struct ast_party_number *guide)
+{
+	init->str = NULL;
+	init->plan = guide->plan;
+	init->presentation = guide->presentation;
+	init->valid = guide->valid;
+}
+
+void ast_party_number_set(struct ast_party_number *dest, const struct ast_party_number *src)
+{
+	if (dest == src) {
+		/* Don't set to self */
+		return;
+	}
+
+	if (src->str && src->str != dest->str) {
+		ast_free(dest->str);
+		dest->str = ast_strdup(src->str);
+	}
+
+	dest->plan = src->plan;
+	dest->presentation = src->presentation;
+	dest->valid = src->valid;
+}
+
+void ast_party_number_free(struct ast_party_number *doomed)
+{
+	ast_free(doomed->str);
+	doomed->str = NULL;
+}
+
 void ast_party_subaddress_init(struct ast_party_subaddress *init)
 {
 	init->str = NULL;
@@ -1801,9 +1916,7 @@ void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct a
 		return;
 	}
 
-	if (dest->str) {
-		ast_free(dest->str);
-	}
+	ast_free(dest->str);
 	dest->str = ast_strdup(src->str);
 	dest->type = src->type;
 	dest->odd_even_indicator = src->odd_even_indicator;
@@ -1826,9 +1939,7 @@ void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct as
 	}
 
 	if (src->str && src->str != dest->str) {
-		if (dest->str) {
-			ast_free(dest->str);
-		}
+		ast_free(dest->str);
 		dest->str = ast_strdup(src->str);
 	}
 
@@ -1839,207 +1950,236 @@ void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct as
 
 void ast_party_subaddress_free(struct ast_party_subaddress *doomed)
 {
-	if (doomed->str) {
-		ast_free(doomed->str);
-		doomed->str = NULL;
-	}
+	ast_free(doomed->str);
+	doomed->str = NULL;
 }
 
 void ast_party_id_init(struct ast_party_id *init)
 {
-	init->number = NULL;
-	init->name = NULL;
-	init->tag = NULL;
-	init->number_type = 0;	/* Unknown */
-	init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	ast_party_name_init(&init->name);
+	ast_party_number_init(&init->number);
 	ast_party_subaddress_init(&init->subaddress);
+	init->tag = NULL;
 }
 
-/*!
- * \internal
- * \brief Copy the source party id information to the destination party id.
- *
- * \param dest Destination party id
- * \param src Source party id
- *
- * \return Nothing
- */
-static void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
+void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
 {
 	if (dest == src) {
 		/* Don't copy to self */
 		return;
 	}
 
-	if (dest->number) {
-		ast_free(dest->number);
-	}
-	dest->number = ast_strdup(src->number);
-
-	if (dest->name) {
-		ast_free(dest->name);
-	}
-	dest->name = ast_strdup(src->name);
+	ast_party_name_copy(&dest->name, &src->name);
+	ast_party_number_copy(&dest->number, &src->number);
+	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
 
-	if (dest->tag) {
-		ast_free(dest->tag);
-	}
+	ast_free(dest->tag);
 	dest->tag = ast_strdup(src->tag);
-
-	dest->number_type = src->number_type;
-	dest->number_presentation = src->number_presentation;
-	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
 }
 
-/*!
- * \internal
- * \brief Initialize the given party id structure using the given guide
- * for a set update operation.
- *
- * \details
- * The initialization is needed to allow a set operation to know if a
- * value needs to be updated.  Simple integers need the guide's original
- * value in case the set operation is not trying to set a new value.
- * String values are simply set to NULL pointers if they are not going
- * to be updated.
- *
- * \param init Party id structure to initialize.
- * \param guide Source party id to use as a guide in initializing.
- *
- * \return Nothing
- */
-static void ast_party_id_set_init(struct ast_party_id *init, const struct ast_party_id *guide)
+void ast_party_id_set_init(struct ast_party_id *init, const struct ast_party_id *guide)
 {
-	init->number = NULL;
-	init->name = NULL;
-	init->tag = NULL;
-	init->number_type = guide->number_type;
-	init->number_presentation = guide->number_presentation;
+	ast_party_name_set_init(&init->name, &guide->name);
+	ast_party_number_set_init(&init->number, &guide->number);
 	ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
+	init->tag = NULL;
 }
 
-/*!
- * \internal
- * \brief Set the source party id information into the destination party id.
- *
- * \param dest Destination party id
- * \param src Source party id
- *
- * \return Nothing
- */
-static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_id *src)
+void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_id *src, const struct ast_set_party_id *update)
 {
 	if (dest == src) {
 		/* Don't set to self */
 		return;
 	}
 
-	if (src->name && src->name != dest->name) {
-		if (dest->name) {
-			ast_free(dest->name);
-		}
-		dest->name = ast_strdup(src->name);
+	if (!update || update->name) {
+		ast_party_name_set(&dest->name, &src->name);
 	}
-
-	if (src->number && src->number != dest->number) {
-		if (dest->number) {
-			ast_free(dest->number);
-		}
-		dest->number = ast_strdup(src->number);
+	if (!update || update->number) {
+		ast_party_number_set(&dest->number, &src->number);
+	}
+	if (!update || update->subaddress) {
+		ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
 	}
 
 	if (src->tag && src->tag != dest->tag) {
-		if (dest->tag) {
-			ast_free(dest->tag);
-		}
+		ast_free(dest->tag);
 		dest->tag = ast_strdup(src->tag);
 	}
-
-	dest->number_type = src->number_type;
-	dest->number_presentation = src->number_presentation;
-	ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
 }
 
 void ast_party_id_free(struct ast_party_id *doomed)
 {
-	if (doomed->number) {
-		ast_free(doomed->number);
-		doomed->number = NULL;
+	ast_party_name_free(&doomed->name);
+	ast_party_number_free(&doomed->number);
+	ast_party_subaddress_free(&doomed->subaddress);
+
+	ast_free(doomed->tag);
+	doomed->tag = NULL;
+}
+
+int ast_party_id_presentation(const struct ast_party_id *id)
+{
+	int number_priority;
+	int number_value;
+	int number_screening;
+	int name_priority;
+	int name_value;
+
+	/* Determine name presentation priority. */
+	if (!id->name.valid) {
+		name_value = AST_PRES_UNAVAILABLE;
+		name_priority = 3;
+	} else {
+		name_value = id->name.presentation & AST_PRES_RESTRICTION;
+		switch (name_value) {
+		case AST_PRES_RESTRICTED:
+			name_priority = 0;
+			break;
+		case AST_PRES_ALLOWED:
+			name_priority = 1;
+			break;
+		case AST_PRES_UNAVAILABLE:
+			name_priority = 2;
+			break;
+		default:
+			name_value = AST_PRES_UNAVAILABLE;
+			name_priority = 3;
+			break;
+		}
 	}
 
-	if (doomed->name) {
-		ast_free(doomed->name);
-		doomed->name = NULL;
+	/* Determine number presentation priority. */
+	if (!id->number.valid) {
+		number_screening = AST_PRES_USER_NUMBER_UNSCREENED;
+		number_value = AST_PRES_UNAVAILABLE;
+		number_priority = 3;
+	} else {
+		number_screening = id->number.presentation & AST_PRES_NUMBER_TYPE;
+		number_value = id->number.presentation & AST_PRES_RESTRICTION;
+		switch (number_value) {
+		case AST_PRES_RESTRICTED:
+			number_priority = 0;
+			break;
+		case AST_PRES_ALLOWED:
+			number_priority = 1;
+			break;
+		case AST_PRES_UNAVAILABLE:
+			number_priority = 2;
+			break;
+		default:
+			number_screening = AST_PRES_USER_NUMBER_UNSCREENED;
+			number_value = AST_PRES_UNAVAILABLE;
+			number_priority = 3;
+			break;
+		}
 	}
 
-	if (doomed->tag) {
-		ast_free(doomed->tag);
-		doomed->tag = NULL;
+	/* Select the wining presentation value. */
+	if (name_priority < number_priority) {
+		number_value = name_value;
 	}
-	ast_party_subaddress_free(&doomed->subaddress);
+
+	return number_value | number_screening;
 }
 
-void ast_party_caller_init(struct ast_party_caller *init)
+void ast_party_dialed_init(struct ast_party_dialed *init)
 {
-	ast_party_id_init(&init->id);
-	init->ani = NULL;
-	init->ani2 = 0;
+	init->number.str = NULL;
+	init->number.plan = 0;/* Unknown */
+	ast_party_subaddress_init(&init->subaddress);
+	init->transit_network_select = 0;
 }
 
-void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid *src)
+void ast_party_dialed_copy(struct ast_party_dialed *dest, const struct ast_party_dialed *src)
 {
 	if (dest == src) {
 		/* Don't copy to self */
 		return;
 	}
 
-#if 1
-	/* Copy caller-id specific information ONLY from struct ast_callerid */
-	if (dest->cid_num)
-	{
-		ast_free(dest->cid_num);
-	}
-	dest->cid_num = ast_strdup(src->cid_num);
+	ast_free(dest->number.str);
+	dest->number.str = ast_strdup(src->number.str);
+	dest->number.plan = src->number.plan;
+	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
+	dest->transit_network_select = src->transit_network_select;
+}
 
-	if (dest->cid_name)
-	{
-		ast_free(dest->cid_name);
-	}
-	dest->cid_name = ast_strdup(src->cid_name);
+void ast_party_dialed_set_init(struct ast_party_dialed *init, const struct ast_party_dialed *guide)
+{
+	init->number.str = NULL;
+	init->number.plan = guide->number.plan;
+	ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
+	init->transit_network_select = guide->transit_network_select;
+}
 
-	if (dest->cid_tag) {
-		ast_free(dest->cid_tag);
+void ast_party_dialed_set(struct ast_party_dialed *dest, const struct ast_party_dialed *src)
+{
+	if (src->number.str && src->number.str != dest->number.str) {
+		ast_free(dest->number.str);
+		dest->number.str = ast_strdup(src->number.str);
 	}
-	dest->cid_tag = ast_strdup(src->cid_tag);
+	dest->number.plan = src->number.plan;
+
+	ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
 
-	dest->cid_ton = src->cid_ton;
-	dest->cid_pres = src->cid_pres;
+	dest->transit_network_select = src->transit_network_select;
+}
 
+void ast_party_dialed_free(struct ast_party_dialed *doomed)
+{
+	ast_free(doomed->number.str);
+	doomed->number.str = NULL;
+	ast_party_subaddress_free(&doomed->subaddress);
+}
 
-	if (dest->cid_ani)
-	{
-		ast_free(dest->cid_ani);
+void ast_party_caller_init(struct ast_party_caller *init)
+{
+	ast_party_id_init(&init->id);
+	init->ani = NULL;
+	init->ani2 = 0;
+}
+
+void ast_party_caller_copy(struct ast_party_caller *dest, const struct ast_party_caller *src)
+{
+	if (dest == src) {
+		/* Don't copy to self */
+		return;
 	}
-	dest->cid_ani = ast_strdup(src->cid_ani);
 
-	dest->cid_ani2 = src->cid_ani2;
+	ast_party_id_copy(&dest->id, &src->id);
 
-	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
+	ast_free(dest->ani);
+	dest->ani = ast_strdup(src->ani);
 
-#else
+	dest->ani2 = src->ani2;
+}
 
-	/* The src and dest parameter types will become struct ast_party_caller ptrs. */
-	/* This is future code */
+void ast_party_caller_set_init(struct ast_party_caller *init, const struct ast_party_caller *guide)
+{
+	ast_party_id_set_init(&init->id, &guide->id);
+	init->ani = NULL;
+	init->ani2 = guide->ani2;
+}
 
-	ast_party_id_copy(&dest->id, &src->id);
+void ast_party_caller_set(struct ast_party_caller *dest, const struct ast_party_caller *src, const struct ast_set_party_caller *update)
+{
+	ast_party_id_set(&dest->id, &src->id, update ? &update->id : NULL);
 
-	if (dest->ani) {
+	if (src->ani && src->ani != dest->ani) {
 		ast_free(dest->ani);
+		dest->ani = ast_strdup(src->ani);
 	}
-	dest->ani = ast_strdup(src->ani);
 
 	dest->ani2 = src->ani2;
-#endif
+}
+
+void ast_party_caller_free(struct ast_party_caller *doomed)
+{
+	ast_party_id_free(&doomed->id);
+
+	ast_free(doomed->ani);
+	doomed->ani = NULL;
 }
 
 void ast_party_connected_line_init(struct ast_party_connected_line *init)
@@ -2059,9 +2199,7 @@ void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const
 
 	ast_party_id_copy(&dest->id, &src->id);
 
-	if (dest->ani) {
-		ast_free(dest->ani);
-	}
+	ast_free(dest->ani);
 	dest->ani = ast_strdup(src->ani);
 
 	dest->ani2 = src->ani2;
@@ -2076,14 +2214,12 @@ void ast_party_connected_line_set_init(struct ast_party_connected_line *init, co
 	init->source = guide->source;
 }
 
-void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
+void ast_party_connected_line_set(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src, const struct ast_set_party_connected_line *update)
 {
-	ast_party_id_set(&dest->id, &src->id);
+	ast_party_id_set(&dest->id, &src->id, update ? &update->id : NULL);
 
 	if (src->ani && src->ani != dest->ani) {
-		if (dest->ani) {
-			ast_free(dest->ani);
-		}
+		ast_free(dest->ani);
 		dest->ani = ast_strdup(src->ani);
 	}
 
@@ -2091,17 +2227,11 @@ void ast_party_connected_line_set(struct ast_party_connected_line *dest, const s
 	dest->source = src->source;
 }
 
-void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_callerid *cid)
+void ast_party_connected_line_collect_caller(struct ast_party_connected_line *connected, struct ast_party_caller *caller)
 {
-	connected->id.number = cid->cid_num;
-	connected->id.name = cid->cid_name;
-	connected->id.number_type = cid->cid_ton;
-	connected->id.number_presentation = cid->cid_pres;
-	connected->id.tag = cid->cid_tag;
-	connected->id.subaddress = cid->subaddress;
-
-	connected->ani = cid->cid_ani;
-	connected->ani2 = cid->cid_ani2;
+	connected->id = caller->id;
+	connected->ani = caller->ani;
+	connected->ani2 = caller->ani2;
 	connected->source = AST_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN;
 }
 
@@ -2109,10 +2239,16 @@ void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
 {
 	ast_party_id_free(&doomed->id);
 
-	if (doomed->ani) {
-		ast_free(doomed->ani);
-		doomed->ani = NULL;
-	}
+	ast_free(doomed->ani);
+	doomed->ani = NULL;
+}
+
+void ast_party_redirecting_init(struct ast_party_redirecting *init)
+{
+	ast_party_id_init(&init->from);
+	ast_party_id_init(&init->to);
+	init->count = 0;
+	init->reason = AST_REDIRECTING_REASON_UNKNOWN;
 }
 
 void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
@@ -2136,6 +2272,14 @@ void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const st
 	init->reason = guide->reason;
 }
 
+void ast_party_redirecting_set(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src, const struct ast_set_party_redirecting *update)
+{
+	ast_party_id_set(&dest->from, &src->from, update ? &update->from : NULL);
+	ast_party_id_set(&dest->to, &src->to, update ? &update->to : NULL);
+	dest->reason = src->reason;
+	dest->count = src->count;
+}
+
 void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
 {
 	ast_party_id_free(&doomed->from);
@@ -2210,7 +2354,8 @@ static void ast_channel_destructor(void *obj)
 	if (chan->pbx)
 		ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
 
-	free_cid(&chan->cid);
+	ast_party_dialed_free(&chan->dialed);
+	ast_party_caller_free(&chan->caller);
 	ast_party_connected_line_free(&chan->connected);
 	ast_party_redirecting_free(&chan->redirecting);
 
@@ -2275,7 +2420,10 @@ static void ast_dummy_channel_destructor(void *obj)
 
 	headp = &chan->varshead;
 
-	free_cid(&chan->cid);
+	ast_party_dialed_free(&chan->dialed);
+	ast_party_caller_free(&chan->caller);
+	ast_party_connected_line_free(&chan->connected);
+	ast_party_redirecting_free(&chan->redirecting);
 
 	/* loop over the variables list, freeing all data and deleting list items */
 	/* no need to lock the list, as the channel is already locked */
@@ -2574,19 +2722,19 @@ int ast_hangup(struct ast_channel *chan)
 	ast_channel_unlock(chan);
 	ast_cc_offer(chan);
 	ast_manager_event(chan, EVENT_FLAG_CALL, "Hangup",
-			"Channel: %s\r\n"
-			"Uniqueid: %s\r\n"
-			"CallerIDNum: %s\r\n"
-			"CallerIDName: %s\r\n"
-			"Cause: %d\r\n"
-			"Cause-txt: %s\r\n",
-			chan->name,
-			chan->uniqueid,
-			S_OR(chan->cid.cid_num, "<unknown>"),
-			S_OR(chan->cid.cid_name, "<unknown>"),
-			chan->hangupcause,
-			ast_cause2str(chan->hangupcause)
-			);
+		"Channel: %s\r\n"
+		"Uniqueid: %s\r\n"
+		"CallerIDNum: %s\r\n"
+		"CallerIDName: %s\r\n"
+		"Cause: %d\r\n"
+		"Cause-txt: %s\r\n",
+		chan->name,
+		chan->uniqueid,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"),
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>"),
+		chan->hangupcause,
+		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) && 
@@ -4012,7 +4160,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
 			ast_party_connected_line_set_init(&connected, &chan->connected);
 			res = ast_connected_line_parse_data(data, datalen, &connected);
 			if (!res) {
-				ast_channel_set_connected_line(chan, &connected);
+				ast_channel_set_connected_line(chan, &connected, NULL);
 			}
 			ast_party_connected_line_free(&connected);
 		}
@@ -4025,7 +4173,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
 			ast_party_redirecting_set_init(&redirecting, &chan->redirecting);
 			res = ast_redirecting_parse_data(data, datalen, &redirecting);
 			if (!res) {
-				ast_channel_set_redirecting(chan, &redirecting);
+				ast_channel_set_redirecting(chan, &redirecting, NULL);
 			}
 			ast_party_redirecting_free(&redirecting);
 		}
@@ -4810,7 +4958,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
 		return NULL;
 	}
 
-	ast_channel_set_redirecting(new, apr);
+	ast_channel_set_redirecting(new, apr, NULL);
 
 	/* Copy/inherit important information into new channel */
 	if (oh) {
@@ -4821,7 +4969,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
 			ast_set_callerid(new, oh->cid_num, oh->cid_name, oh->cid_num);
 		}
 		if (oh->parent_channel) {
-			ast_channel_update_redirecting(oh->parent_channel, apr);
+			ast_channel_update_redirecting(oh->parent_channel, apr, NULL);
 			ast_channel_inherit_variables(oh->parent_channel, new);
 			ast_channel_datastore_inherit(oh->parent_channel, new);
 		}
@@ -4829,7 +4977,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
 			ast_cdr_setaccount(new, oh->account);
 		}
 	} else if (caller) { /* no outgoing helper so use caller if avaliable */
-		ast_channel_update_redirecting(caller, apr);
+		ast_channel_update_redirecting(caller, apr, NULL);
 		ast_channel_inherit_variables(caller, new);
 		ast_channel_datastore_inherit(caller, new);
 	}
@@ -4840,7 +4988,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
 	}
 	ast_copy_flags(new->cdr, orig->cdr, AST_CDR_FLAG_ORIGINATED);
 	ast_string_field_set(new, accountcode, orig->accountcode);
-	ast_party_caller_copy(&new->cid, &orig->cid);
+	ast_party_caller_copy(&new->caller, &orig->caller);
 	ast_party_connected_line_copy(&new->connected, &orig->connected);
 	ast_channel_unlock(new);
 	ast_channel_unlock(orig);
@@ -4895,10 +5043,17 @@ struct ast_channel *__ast_request_and_dial(const char *type, format_t format, co
 	ast_set_callerid(chan, cid_num, cid_name, cid_num);
 	ast_set_flag(chan->cdr, AST_CDR_FLAG_ORIGINATED);
 	ast_party_connected_line_set_init(&connected, &chan->connected);
-	connected.id.number = (char *) cid_num;
-	connected.id.name = (char *) cid_name;
-	connected.id.number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-	ast_channel_set_connected_line(chan, &connected);
+	if (cid_num) {
+		connected.id.number.valid = 1;
+		connected.id.number.str = (char *) cid_num;
+		connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	}
+	if (cid_name) {
+		connected.id.name.valid = 1;
+		connected.id.name.str = (char *) cid_name;
+		connected.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	}
+	ast_channel_set_connected_line(chan, &connected, NULL);
 
 	if (ast_call(chan, data, 0)) {	/* ast_call failed... */
 		ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
@@ -5658,19 +5813,22 @@ static void ast_set_owners_and_peers(struct ast_channel *chan1,
  */
 static void report_new_callerid(struct ast_channel *chan)
 {
+	int pres;
+
+	pres = ast_party_id_presentation(&chan->caller.id);
 	ast_manager_event(chan, EVENT_FLAG_CALL, "NewCallerid",
-				"Channel: %s\r\n"
-				"CallerIDNum: %s\r\n"
-				"CallerIDName: %s\r\n"
-				"Uniqueid: %s\r\n"
-				"CID-CallingPres: %d (%s)\r\n",
-				chan->name,
-				S_OR(chan->cid.cid_num, ""),
-				S_OR(chan->cid.cid_name, ""),
-				chan->uniqueid,
-				chan->cid.cid_pres,
-				ast_describe_caller_presentation(chan->cid.cid_pres)
-				);
+		"Channel: %s\r\n"
+		"CallerIDNum: %s\r\n"
+		"CallerIDName: %s\r\n"
+		"Uniqueid: %s\r\n"
+		"CID-CallingPres: %d (%s)\r\n",
+		chan->name,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""),
+		chan->uniqueid,
+		pres,
+		ast_describe_caller_presentation(pres)
+		);
 }
 
 /*!
@@ -5690,7 +5848,8 @@ int ast_do_masquerade(struct ast_channel *original)
 	const struct ast_channel_tech *t;
 	void *t_pvt;
 	union {
-		struct ast_callerid cid;
+		struct ast_party_dialed dialed;
+		struct ast_party_caller caller;
 		struct ast_party_connected_line connected;
 		struct ast_party_redirecting redirecting;
 	} exchange;
@@ -5917,18 +6076,24 @@ int ast_do_masquerade(struct ast_channel *original)
 	 * Just swap the whole structures, nevermind the allocations,
 	 * they'll work themselves out.
 	 */
-	exchange.cid = original->cid;
-	original->cid = clonechan->cid;
-	clonechan->cid = exchange.cid;
-	report_new_callerid(original);
+	exchange.dialed = original->dialed;
+	original->dialed = clonechan->dialed;
+	clonechan->dialed = exchange.dialed;
+
+	exchange.caller = original->caller;
+	original->caller = clonechan->caller;
+	clonechan->caller = exchange.caller;
 
 	exchange.connected = original->connected;
 	original->connected = clonechan->connected;
 	clonechan->connected = exchange.connected;
+
 	exchange.redirecting = original->redirecting;
 	original->redirecting = clonechan->redirecting;
 	clonechan->redirecting = exchange.redirecting;
 
+	report_new_callerid(original);
+
 	/* Restore original timing file descriptor */
 	ast_channel_set_fd(original, AST_TIMING_FD, original->timingfd);
 
@@ -6030,19 +6195,18 @@ void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char
 	ast_channel_lock(chan);
 
 	if (cid_num) {
-		if (chan->cid.cid_num)
-			ast_free(chan->cid.cid_num);
-		chan->cid.cid_num = ast_strdup(cid_num);
+		chan->caller.id.number.valid = 1;
+		ast_free(chan->caller.id.number.str);
+		chan->caller.id.number.str = ast_strdup(cid_num);
 	}
 	if (cid_name) {
-		if (chan->cid.cid_name)
-			ast_free(chan->cid.cid_name);
-		chan->cid.cid_name = ast_strdup(cid_name);
+		chan->caller.id.name.valid = 1;
+		ast_free(chan->caller.id.name.str);
+		chan->caller.id.name.str = ast_strdup(cid_name);
 	}
 	if (cid_ani) {
-		if (chan->cid.cid_ani)
-			ast_free(chan->cid.cid_ani);
-		chan->cid.cid_ani = ast_strdup(cid_ani);
+		ast_free(chan->caller.ani);
+		chan->caller.ani = ast_strdup(cid_ani);
 	}
 
 	report_new_callerid(chan);
@@ -6050,6 +6214,40 @@ void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char
 	ast_channel_unlock(chan);
 }
 
+void ast_channel_set_caller(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
+{
+	if (&chan->caller == caller) {
+		/* Don't set to self */
+		return;
+	}
+
+	ast_channel_lock(chan);
+	ast_party_caller_set(&chan->caller, caller, update);
+	ast_channel_unlock(chan);
+}
+
+void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_party_caller *caller, const struct ast_set_party_caller *update)
+{
+	struct ast_party_caller pre_set;
+
+	if (&chan->caller == caller) {
+		/* Don't set to self */
+		return;
+	}
+
+	ast_channel_lock(chan);
+	pre_set = chan->caller;
+	ast_party_caller_set(&chan->caller, caller, update);
+	if (S_COR(pre_set.id.number.valid, pre_set.id.number.str, NULL)
+			!= S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)
+		|| S_COR(pre_set.id.name.valid, pre_set.id.name.str, NULL)
+			!= S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, NULL)) {
+		/* The caller id name or number changed. */
+		report_new_callerid(chan);
+	}
+	ast_channel_unlock(chan);
+}
+
 int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
 {
 	int oldstate = chan->_state;
@@ -6072,16 +6270,16 @@ int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
 
 	/* setstate used to conditionally report Newchannel; this is no more */
 	ast_manager_event(chan, EVENT_FLAG_CALL, "Newstate",
-		      "Channel: %s\r\n"
-		      "ChannelState: %d\r\n"
-		      "ChannelStateDesc: %s\r\n"
-		      "CallerIDNum: %s\r\n"
-		      "CallerIDName: %s\r\n"
-		      "Uniqueid: %s\r\n",
-		      chan->name, chan->_state, ast_state2str(chan->_state),
-		      S_OR(chan->cid.cid_num, ""),
-		      S_OR(chan->cid.cid_name, ""),
-		      chan->uniqueid);
+		"Channel: %s\r\n"
+		"ChannelState: %d\r\n"
+		"ChannelStateDesc: %s\r\n"
+		"CallerIDNum: %s\r\n"
+		"CallerIDName: %s\r\n"
+		"Uniqueid: %s\r\n",
+		chan->name, chan->_state, ast_state2str(chan->_state),
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""),
+		chan->uniqueid);
 
 	return 0;
 }
@@ -6346,19 +6544,20 @@ static void manager_bridge_event(int onoff, int type, struct ast_channel *c0, st
 {
 	struct ast_channel *chans[2] = { c0, c1 };
 	ast_manager_event_multichan(EVENT_FLAG_CALL, "Bridge", 2, chans,
-			"Bridgestate: %s\r\n"
-			"Bridgetype: %s\r\n"
-			"Channel1: %s\r\n"
-			"Channel2: %s\r\n"
-			"Uniqueid1: %s\r\n"
-			"Uniqueid2: %s\r\n"
-			"CallerID1: %s\r\n"
-			"CallerID2: %s\r\n",
-			onoff ? "Link" : "Unlink",
-			type == 1 ? "core" : "native",
-			c0->name, c1->name, c0->uniqueid, c1->uniqueid, 
-			S_OR(c0->cid.cid_num, ""), 
-			S_OR(c1->cid.cid_num, ""));
+		"Bridgestate: %s\r\n"
+		"Bridgetype: %s\r\n"
+		"Channel1: %s\r\n"
+		"Channel2: %s\r\n"
+		"Uniqueid1: %s\r\n"
+		"Uniqueid2: %s\r\n"
+		"CallerID1: %s\r\n"
+		"CallerID2: %s\r\n",
+		onoff ? "Link" : "Unlink",
+		type == 1 ? "core" : "native",
+		c0->name, c1->name,
+		c0->uniqueid, c1->uniqueid,
+		S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, ""),
+		S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, ""));
 }
 
 static void update_bridge_vars(struct ast_channel *c0, struct ast_channel *c1)
@@ -6606,13 +6805,16 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
 			ast_set_flag(c1, AST_FLAG_NBRIDGE);
 			if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, timeoutms)) == AST_BRIDGE_COMPLETE) {
 				ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans,
-					      "Channel1: %s\r\n"
-					      "Channel2: %s\r\n"
-					      "Uniqueid1: %s\r\n"
-					      "Uniqueid2: %s\r\n"
-					      "CallerID1: %s\r\n"
-					      "CallerID2: %s\r\n",
-					      c0->name, c1->name, c0->uniqueid, c1->uniqueid, S_OR(c0->cid.cid_num, "<unknown>"), S_OR(c1->cid.cid_num, "<unknown>"));
+					"Channel1: %s\r\n"
+					"Channel2: %s\r\n"
+					"Uniqueid1: %s\r\n"
+					"Uniqueid2: %s\r\n"
+					"CallerID1: %s\r\n"
+					"CallerID2: %s\r\n",
+					c0->name, c1->name,
+					c0->uniqueid, c1->uniqueid,
+					S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, "<unknown>"),
+					S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>"));
 
 				ast_debug(1, "Returning from native bridge, channels: %s, %s\n", c0->name, c1->name);
 
@@ -6677,13 +6879,16 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
 	c1->_bridge = NULL;
 
 	ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans,
-		      "Channel1: %s\r\n"
-		      "Channel2: %s\r\n"
-		      "Uniqueid1: %s\r\n"
-		      "Uniqueid2: %s\r\n"
-		      "CallerID1: %s\r\n"
-		      "CallerID2: %s\r\n",
-		      c0->name, c1->name, c0->uniqueid, c1->uniqueid, S_OR(c0->cid.cid_num, "<unknown>"), S_OR(c1->cid.cid_num, "<unknown>"));
+		"Channel1: %s\r\n"
+		"Channel2: %s\r\n"
+		"Uniqueid1: %s\r\n"
+		"Uniqueid2: %s\r\n"
+		"CallerID1: %s\r\n"
+		"CallerID2: %s\r\n",
+		c0->name, c1->name,
+		c0->uniqueid, c1->uniqueid,
+		S_COR(c0->caller.id.number.valid, c0->caller.id.number.str, "<unknown>"),
+		S_COR(c1->caller.id.number.valid, c1->caller.id.number.str, "<unknown>"));
 	ast_debug(1, "Bridge stops bridging channels %s and %s\n", c0->name, c1->name);
 
 	return res;
@@ -7289,101 +7494,27 @@ int ast_say_digits_full(struct ast_channel *chan, int num,
 	return ast_say_digit_str_full(chan, buf, ints, lang, audiofd, ctrlfd);
 }
 
-void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_callerid *src)
+void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
 {
-#if 1
-	/* Must manually fill in struct ast_party_id until struct ast_callerid goes away */
-	if (dest->id.number) {
-		ast_free(dest->id.number);
-	}
-	dest->id.number = ast_strdup(src->cid_num);
+	ast_party_id_copy(&dest->id, &src->id);
 
-	if (dest->id.name) {
-		ast_free(dest->id.name);
-	}
-	dest->id.name = ast_strdup(src->cid_name);
-
-	if (dest->id.tag) {
-		ast_free(dest->id.tag);
-	}
-	dest->id.tag = ast_strdup(src->cid_tag);
-
-	dest->id.number_type = src->cid_ton;
-	dest->id.number_presentation = src->cid_pres;
-
-
-	if (dest->ani) {
-		ast_free(dest->ani);
-	}
-	dest->ani = ast_strdup(src->cid_ani);
-
-	dest->ani2 = src->cid_ani2;
-	ast_party_subaddress_copy(&dest->id.subaddress, &src->subaddress);
-
-#else
-
-	/* The src parameter type will become a struct ast_party_caller ptr. */
-	/* This is future code */
-
-	ast_party_id_copy(&dest->id, &src->id);
-
-	if (dest->ani) {
-		ast_free(dest->ani);
-	}
-	dest->ani = ast_strdup(src->ani);
+	ast_free(dest->ani);
+	dest->ani = ast_strdup(src->ani);
 
 	dest->ani2 = src->ani2;
-#endif
 }
 
-void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct ast_party_connected_line *src)
+void ast_connected_line_copy_to_caller(struct ast_party_caller *dest, const struct ast_party_connected_line *src)
 {
-#if 1
-	/* Must manually extract from struct ast_party_id until struct ast_callerid goes away */
-	if (dest->cid_num) {
-		ast_free(dest->cid_num);
-	}
-	dest->cid_num = ast_strdup(src->id.number);
-
-	if (dest->cid_name) {
-		ast_free(dest->cid_name);
-	}
-	dest->cid_name = ast_strdup(src->id.name);
-
-	if (dest->cid_tag) {
-		ast_free(dest->cid_tag);
-	}
-	dest->cid_tag = ast_strdup(src->id.tag);
-
-	dest->cid_ton = src->id.number_type;
-	dest->cid_pres = src->id.number_presentation;
-
-
-	if (dest->cid_ani) {
-		ast_free(dest->cid_ani);
-	}
-	dest->cid_ani = ast_strdup(src->ani);
-
-	dest->cid_ani2 = src->ani2;
-	ast_party_subaddress_copy(&dest->subaddress, &src->id.subaddress);
-
-#else
-
-	/* The dest parameter type will become a struct ast_party_caller ptr. */
-	/* This is future code */
-
 	ast_party_id_copy(&dest->id, &src->id);
 
-	if (dest->ani) {
-		ast_free(dest->ani);
-	}
+	ast_free(dest->ani);
 	dest->ani = ast_strdup(src->ani);
 
 	dest->ani2 = src->ani2;
-#endif
 }
 
-void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected)
+void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
 {
 	if (&chan->connected == connected) {
 		/* Don't set to self */
@@ -7391,30 +7522,38 @@ void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_p
 	}
 
 	ast_channel_lock(chan);
-	ast_party_connected_line_set(&chan->connected, connected);
+	ast_party_connected_line_set(&chan->connected, connected, update);
 	ast_channel_unlock(chan);
 }
 
-/*!
- * \brief Element identifiers for connected line indication frame data
- * \note Only add to the end of this enum.
- */
-enum {
-	AST_CONNECTED_LINE_NUMBER,
-	AST_CONNECTED_LINE_NAME,
-	AST_CONNECTED_LINE_NUMBER_TYPE,
-	AST_CONNECTED_LINE_NUMBER_PRESENTATION,
-	AST_CONNECTED_LINE_SOURCE,
-	AST_CONNECTED_LINE_SUBADDRESS,
-	AST_CONNECTED_LINE_SUBADDRESS_TYPE,
-	AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN,
-	AST_CONNECTED_LINE_SUBADDRESS_VALID,
-	AST_CONNECTED_LINE_TAG,
+/*! \note Should follow struct ast_party_name */
+struct ast_party_name_ies {
+	/*! \brief Subscriber name ie */
+	int str;
+	/*! \brief Character set ie. */
+	int char_set;
+	/*! \brief presentation-indicator ie */
+	int presentation;
+	/*! \brief valid/present ie */
+	int valid;
 };
 
-int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected)
+/*!
+ * \internal
+ * \since 1.8
+ * \brief Build a party name information data frame component.
+ *
+ * \param data Buffer to fill with the frame data
+ * \param datalen Size of the buffer to fill
+ * \param name Party name information
+ * \param label Name of particular party name
+ * \param ies Data frame ie values for the party name components
+ *
+ * \retval -1 if error
+ * \retval Amount of data buffer used
+ */
+static int party_name_build_data(unsigned char *data, size_t datalen, const struct ast_party_name *name, const char *label, const struct ast_party_name_ies *ies)
 {
-	int32_t value;
 	size_t length;
 	size_t pos = 0;
 
@@ -7422,110 +7561,383 @@ int ast_connected_line_build_data(unsigned char *data, size_t datalen, const str
 	 * The size of integer values must be fixed in case the frame is
 	 * shipped to another machine.
 	 */
-
-	/* *************** Connected line party id *************** */
-	if (connected->id.number) {
-		length = strlen(connected->id.number);
+	if (name->str) {
+		length = strlen(name->str);
 		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for connected line number\n");
+			ast_log(LOG_WARNING, "No space left for %s name\n", label);
 			return -1;
 		}
-		data[pos++] = AST_CONNECTED_LINE_NUMBER;
+		data[pos++] = ies->str;
 		data[pos++] = length;
-		memcpy(data + pos, connected->id.number, length);
+		memcpy(data + pos, name->str, length);
 		pos += length;
 	}
 
-	if (connected->id.name) {
-		length = strlen(connected->id.name);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for connected line name\n");
-			return -1;
-		}
-		data[pos++] = AST_CONNECTED_LINE_NAME;
-		data[pos++] = length;
-		memcpy(data + pos, connected->id.name, length);
-		pos += length;
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for %s name char set\n", label);
+		return -1;
 	}
+	data[pos++] = ies->char_set;
+	data[pos++] = 1;
+	data[pos++] = name->char_set;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for %s name presentation\n", label);
+		return -1;
+	}
+	data[pos++] = ies->presentation;
+	data[pos++] = 1;
+	data[pos++] = name->presentation;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for %s name valid\n", label);
+		return -1;
+	}
+	data[pos++] = ies->valid;
+	data[pos++] = 1;
+	data[pos++] = name->valid;
+
+	return pos;
+}
+
+/*! \note Should follow struct ast_party_number */
+struct ast_party_number_ies {
+	/*! \brief Subscriber phone number ie */
+	int str;
+	/*! \brief Type-Of-Number and Numbering-Plan ie */
+	int plan;
+	/*! \brief presentation-indicator ie */
+	int presentation;
+	/*! \brief valid/present ie */
+	int valid;
+};
 
-	if (connected->id.tag) {
-		length = strlen(connected->id.tag);
+/*!
+ * \internal
+ * \since 1.8
+ * \brief Build a party number information data frame component.
+ *
+ * \param data Buffer to fill with the frame data
+ * \param datalen Size of the buffer to fill
+ * \param number Party number information
+ * \param label Name of particular party number
+ * \param ies Data frame ie values for the party number components
+ *
+ * \retval -1 if error
+ * \retval Amount of data buffer used
+ */
+static int party_number_build_data(unsigned char *data, size_t datalen, const struct ast_party_number *number, const char *label, const struct ast_party_number_ies *ies)
+{
+	size_t length;
+	size_t pos = 0;
+
+	/*
+	 * The size of integer values must be fixed in case the frame is
+	 * shipped to another machine.
+	 */
+	if (number->str) {
+		length = strlen(number->str);
 		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for connected line tag\n");
+			ast_log(LOG_WARNING, "No space left for %s number\n", label);
 			return -1;
 		}
-		data[pos++] = AST_CONNECTED_LINE_TAG;
+		data[pos++] = ies->str;
 		data[pos++] = length;
-		memcpy(data + pos, connected->id.tag, length);
+		memcpy(data + pos, number->str, length);
 		pos += length;
 	}
 
 	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for connected line type of number\n");
+		ast_log(LOG_WARNING, "No space left for %s numbering plan\n", label);
 		return -1;
 	}
-	data[pos++] = AST_CONNECTED_LINE_NUMBER_TYPE;
+	data[pos++] = ies->plan;
 	data[pos++] = 1;
-	data[pos++] = connected->id.number_type;
+	data[pos++] = number->plan;
 
 	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for connected line presentation\n");
+		ast_log(LOG_WARNING, "No space left for %s number presentation\n", label);
 		return -1;
 	}
-	data[pos++] = AST_CONNECTED_LINE_NUMBER_PRESENTATION;
+	data[pos++] = ies->presentation;
 	data[pos++] = 1;
-	data[pos++] = connected->id.number_presentation;
+	data[pos++] = number->presentation;
 
-	/* Connected line source */
-	if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
-		ast_log(LOG_WARNING, "No space left for connected line source\n");
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for %s number valid\n", label);
 		return -1;
 	}
-	data[pos++] = AST_CONNECTED_LINE_SOURCE;
-	data[pos++] = sizeof(value);
-	value = htonl(connected->source);
-	memcpy(data + pos, &value, sizeof(value));
-	pos += sizeof(value);
+	data[pos++] = ies->valid;
+	data[pos++] = 1;
+	data[pos++] = number->valid;
 
-	/* Connected line Subaddress */
-	if (connected->id.subaddress.str) {
-		length = strlen(connected->id.subaddress.str);
+	return pos;
+}
+
+/*! \note Should follow struct ast_party_subaddress */
+struct ast_party_subaddress_ies {
+	/*! \brief subaddress ie. */
+	int str;
+	/*! \brief subaddress type ie */
+	int type;
+	/*! \brief odd/even indicator ie */
+	int odd_even_indicator;
+	/*! \brief valid/present ie */
+	int valid;
+};
+
+/*!
+ * \internal
+ * \since 1.8
+ * \brief Build a party subaddress information data frame component.
+ *
+ * \param data Buffer to fill with the frame data
+ * \param datalen Size of the buffer to fill
+ * \param subaddress Party subaddress information
+ * \param label Name of particular party subaddress
+ * \param ies Data frame ie values for the party subaddress components
+ *
+ * \retval -1 if error
+ * \retval Amount of data buffer used
+ */
+static int party_subaddress_build_data(unsigned char *data, size_t datalen, const struct ast_party_subaddress *subaddress, const char *label, const struct ast_party_subaddress_ies *ies)
+{
+	size_t length;
+	size_t pos = 0;
+
+	/*
+	 * The size of integer values must be fixed in case the frame is
+	 * shipped to another machine.
+	 */
+	if (subaddress->str) {
+		length = strlen(subaddress->str);
 		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for connected line subaddress\n");
+			ast_log(LOG_WARNING, "No space left for %s subaddress\n", label);
 			return -1;
 		}
-		data[pos++] = AST_CONNECTED_LINE_SUBADDRESS;
+		data[pos++] = ies->str;
 		data[pos++] = length;
-		memcpy(data + pos, connected->id.subaddress.str, length);
+		memcpy(data + pos, subaddress->str, length);
 		pos += length;
 	}
-	/* Connected line Subaddress Type */
+
 	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for connected line type of subaddress\n");
+		ast_log(LOG_WARNING, "No space left for %s type of subaddress\n", label);
 		return -1;
 	}
-	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_TYPE;
+	data[pos++] = ies->type;
 	data[pos++] = 1;
-	data[pos++] = connected->id.subaddress.type;
+	data[pos++] = subaddress->type;
 
-	/* Connected line Subaddress Odd/Even indicator */
 	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
 		ast_log(LOG_WARNING,
-			"No space left for connected line subaddress odd-even indicator\n");
+			"No space left for %s subaddress odd-even indicator\n", label);
+		return -1;
+	}
+	data[pos++] = ies->odd_even_indicator;
+	data[pos++] = 1;
+	data[pos++] = subaddress->odd_even_indicator;
+
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for %s subaddress valid\n", label);
 		return -1;
 	}
-	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN;
+	data[pos++] = ies->valid;
 	data[pos++] = 1;
-	data[pos++] = connected->id.subaddress.odd_even_indicator;
+	data[pos++] = subaddress->valid;
+
+	return pos;
+}
+
+/*! \note Should follow struct ast_party_id */
+struct ast_party_id_ies {
+	/*! \brief Subscriber name ies */
+	struct ast_party_name_ies name;
+	/*! \brief Subscriber phone number ies */
+	struct ast_party_number_ies number;
+	/*! \brief Subscriber subaddress ies. */
+	struct ast_party_subaddress_ies subaddress;
+	/*! \brief User party id tag ie. */
+	int tag;
+	/*! \brief Combined name and number presentation ie. */
+	int combined_presentation;
+};
+
+/*!
+ * \internal
+ * \since 1.8
+ * \brief Build a party id information data frame component.
+ *
+ * \param data Buffer to fill with the frame data
+ * \param datalen Size of the buffer to fill
+ * \param id Party id information
+ * \param label Name of particular party id
+ * \param ies Data frame ie values for the party id components
+ * \param update What id information to build.  NULL if all.
+ *
+ * \retval -1 if error
+ * \retval Amount of data buffer used
+ */
+static int party_id_build_data(unsigned char *data, size_t datalen,
+	const struct ast_party_id *id, const char *label, const struct ast_party_id_ies *ies,
+	const struct ast_set_party_id *update)
+{
+	size_t length;
+	size_t pos = 0;
+	int res;
 
-	/* Connected line Subaddress Valid */
+	/*
+	 * The size of integer values must be fixed in case the frame is
+	 * shipped to another machine.
+	 */
+
+	if (!update || update->name) {
+		res = party_name_build_data(data + pos, datalen - pos, &id->name, label,
+			&ies->name);
+		if (res < 0) {
+			return -1;
+		}
+		pos += res;
+	}
+
+	if (!update || update->number) {
+		res = party_number_build_data(data + pos, datalen - pos, &id->number, label,
+			&ies->number);
+		if (res < 0) {
+			return -1;
+		}
+		pos += res;
+	}
+
+	if (!update || update->subaddress) {
+		res = party_subaddress_build_data(data + pos, datalen - pos, &id->subaddress,
+			label, &ies->subaddress);
+		if (res < 0) {
+			return -1;
+		}
+		pos += res;
+	}
+
+	/* *************** Party id user tag **************************** */
+	if (id->tag) {
+		length = strlen(id->tag);
+		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+			ast_log(LOG_WARNING, "No space left for %s tag\n", label);
+			return -1;
+		}
+		data[pos++] = ies->tag;
+		data[pos++] = length;
+		memcpy(data + pos, id->tag, length);
+		pos += length;
+	}
+
+	/* *************** Party id combined presentation *************** */
+	if (!update || update->number) {
+		int presentation;
+
+		if (!update || update->name) {
+			presentation = ast_party_id_presentation(id);
+		} else {
+			/*
+			 * We must compromise because not all the information is available
+			 * to determine a combined presentation value.
+			 * We will only send the number presentation instead.
+			 */
+			presentation = id->number.presentation;
+		}
+
+		if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+			ast_log(LOG_WARNING, "No space left for %s combined presentation\n", label);
+			return -1;
+		}
+		data[pos++] = ies->combined_presentation;
+		data[pos++] = 1;
+		data[pos++] = presentation;
+	}
+
+	return pos;
+}
+
+/*!
+ * \brief Element identifiers for connected line indication frame data
+ * \note Only add to the end of this enum.
+ */
+enum {
+	AST_CONNECTED_LINE_NUMBER,
+	AST_CONNECTED_LINE_NAME,
+	AST_CONNECTED_LINE_NUMBER_PLAN,
+	AST_CONNECTED_LINE_ID_PRESENTATION,/* Combined number and name presentation. */
+	AST_CONNECTED_LINE_SOURCE,
+	AST_CONNECTED_LINE_SUBADDRESS,
+	AST_CONNECTED_LINE_SUBADDRESS_TYPE,
+	AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN,
+	AST_CONNECTED_LINE_SUBADDRESS_VALID,
+	AST_CONNECTED_LINE_TAG,
+	AST_CONNECTED_LINE_VERSION,
+	AST_CONNECTED_LINE_NAME_VALID,
+	AST_CONNECTED_LINE_NAME_CHAR_SET,
+	AST_CONNECTED_LINE_NAME_PRESENTATION,
+	AST_CONNECTED_LINE_NUMBER_VALID,
+	AST_CONNECTED_LINE_NUMBER_PRESENTATION,
+};
+
+int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
+{
+	int32_t value;
+	size_t pos = 0;
+	int res;
+
+	static const struct ast_party_id_ies ies = {
+		.name.str = AST_CONNECTED_LINE_NAME,
+		.name.char_set = AST_CONNECTED_LINE_NAME_CHAR_SET,
+		.name.presentation = AST_CONNECTED_LINE_NAME_PRESENTATION,
+		.name.valid = AST_CONNECTED_LINE_NAME_VALID,
+
+		.number.str = AST_CONNECTED_LINE_NUMBER,
+		.number.plan = AST_CONNECTED_LINE_NUMBER_PLAN,
+		.number.presentation = AST_CONNECTED_LINE_NUMBER_PRESENTATION,
+		.number.valid = AST_CONNECTED_LINE_NUMBER_VALID,
+
+		.subaddress.str = AST_CONNECTED_LINE_SUBADDRESS,
+		.subaddress.type = AST_CONNECTED_LINE_SUBADDRESS_TYPE,
+		.subaddress.odd_even_indicator = AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN,
+		.subaddress.valid = AST_CONNECTED_LINE_SUBADDRESS_VALID,
+
+		.tag = AST_CONNECTED_LINE_TAG,
+		.combined_presentation = AST_CONNECTED_LINE_ID_PRESENTATION,
+	};
+
+	/*
+	 * The size of integer values must be fixed in case the frame is
+	 * shipped to another machine.
+	 */
+
+	/* Connected line frame version */
 	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for connected line subaddress valid\n");
+		ast_log(LOG_WARNING, "No space left for connected line frame version\n");
 		return -1;
 	}
-	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_VALID;
+	data[pos++] = AST_CONNECTED_LINE_VERSION;
 	data[pos++] = 1;
-	data[pos++] = connected->id.subaddress.valid;
+	data[pos++] = 2;/* Version 1 did not have a version ie */
+
+	res = party_id_build_data(data + pos, datalen - pos, &connected->id,
+		"connected line", &ies, update ? &update->id : NULL);
+	if (res < 0) {
+		return -1;
+	}
+	pos += res;
+
+	/* Connected line source */
+	if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
+		ast_log(LOG_WARNING, "No space left for connected line source\n");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SOURCE;
+	data[pos++] = sizeof(value);
+	value = htonl(connected->source);
+	memcpy(data + pos, &value, sizeof(value));
+	pos += sizeof(value);
 
 	return pos;
 }
@@ -7536,6 +7948,9 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str
 	unsigned char ie_len;
 	unsigned char ie_id;
 	int32_t value;
+	int frame_version = 1;
+	int combined_presentation = 0;
+	int got_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */
 
 	for (pos = 0; pos < datalen; pos += ie_len) {
 		if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) {
@@ -7550,62 +7965,94 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str
 		}
 
 		switch (ie_id) {
-		case AST_CONNECTED_LINE_NUMBER:
-			if (connected->id.number) {
-				ast_free(connected->id.number);
-			}
-			connected->id.number = ast_malloc(ie_len + 1);
-			if (connected->id.number) {
-				memcpy(connected->id.number, data + pos, ie_len);
-				connected->id.number[ie_len] = 0;
+/* Connected line party frame version */
+		case AST_CONNECTED_LINE_VERSION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line frame version (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			frame_version = data[pos];
 			break;
+/* Connected line party id name */
 		case AST_CONNECTED_LINE_NAME:
-			if (connected->id.name) {
-				ast_free(connected->id.name);
+			ast_free(connected->id.name.str);
+			connected->id.name.str = ast_malloc(ie_len + 1);
+			if (connected->id.name.str) {
+				memcpy(connected->id.name.str, data + pos, ie_len);
+				connected->id.name.str[ie_len] = 0;
 			}
-			connected->id.name = ast_malloc(ie_len + 1);
-			if (connected->id.name) {
-				memcpy(connected->id.name, data + pos, ie_len);
-				connected->id.name[ie_len] = 0;
+			break;
+		case AST_CONNECTED_LINE_NAME_CHAR_SET:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line name char set (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			connected->id.name.char_set = data[pos];
 			break;
-		case AST_CONNECTED_LINE_TAG:
-			if (connected->id.tag) {
-				ast_free(connected->id.tag);
+		case AST_CONNECTED_LINE_NAME_PRESENTATION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line name presentation (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
-			connected->id.tag = ast_malloc(ie_len + 1);
-			if (connected->id.tag) {
-				memcpy(connected->id.tag, data + pos, ie_len);
-				connected->id.tag[ie_len] = 0;
+			connected->id.name.presentation = data[pos];
+			break;
+		case AST_CONNECTED_LINE_NAME_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line name valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.name.valid = data[pos];
+			break;
+/* Connected line party id number */
+		case AST_CONNECTED_LINE_NUMBER:
+			ast_free(connected->id.number.str);
+			connected->id.number.str = ast_malloc(ie_len + 1);
+			if (connected->id.number.str) {
+				memcpy(connected->id.number.str, data + pos, ie_len);
+				connected->id.number.str[ie_len] = 0;
 			}
 			break;
-		case AST_CONNECTED_LINE_NUMBER_TYPE:
+		case AST_CONNECTED_LINE_NUMBER_PLAN:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid connected line type of number (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid connected line numbering plan (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			connected->id.number_type = data[pos];
+			connected->id.number.plan = data[pos];
 			break;
 		case AST_CONNECTED_LINE_NUMBER_PRESENTATION:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid connected line presentation (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid connected line number presentation (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			connected->id.number_presentation = data[pos];
+			connected->id.number.presentation = data[pos];
 			break;
-		case AST_CONNECTED_LINE_SOURCE:
-			if (ie_len != sizeof(value)) {
-				ast_log(LOG_WARNING, "Invalid connected line source (%u)\n", (unsigned) ie_len);
+		case AST_CONNECTED_LINE_NUMBER_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line number valid (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			memcpy(&value, data + pos, sizeof(value));
-			connected->source = ntohl(value);
+			connected->id.number.valid = data[pos];
 			break;
-		case AST_CONNECTED_LINE_SUBADDRESS:
-			if (connected->id.subaddress.str) {
-				ast_free(connected->id.subaddress.str);
+/* Connected line party id combined presentation */
+		case AST_CONNECTED_LINE_ID_PRESENTATION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line combined presentation (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			combined_presentation = data[pos];
+			got_combined_presentation = 1;
+			break;
+/* Connected line party id subaddress */
+		case AST_CONNECTED_LINE_SUBADDRESS:
+			ast_free(connected->id.subaddress.str);
 			connected->id.subaddress.str = ast_malloc(ie_len + 1);
 			if (connected->id.subaddress.str) {
 				memcpy(connected->id.subaddress.str, data + pos, ie_len);
@@ -7637,21 +8084,69 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str
 			}
 			connected->id.subaddress.valid = data[pos];
 			break;
+/* Connected line party tag */
+		case AST_CONNECTED_LINE_TAG:
+			ast_free(connected->id.tag);
+			connected->id.tag = ast_malloc(ie_len + 1);
+			if (connected->id.tag) {
+				memcpy(connected->id.tag, data + pos, ie_len);
+				connected->id.tag[ie_len] = 0;
+			}
+			break;
+/* Connected line party source */
+		case AST_CONNECTED_LINE_SOURCE:
+			if (ie_len != sizeof(value)) {
+				ast_log(LOG_WARNING, "Invalid connected line source (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			memcpy(&value, data + pos, sizeof(value));
+			connected->source = ntohl(value);
+			break;
+/* Connected line party unknown element */
 		default:
-			ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
+			ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n",
+				(unsigned) ie_id, (unsigned) ie_len);
 			break;
 		}
 	}
 
+	switch (frame_version) {
+	case 1:
+		/*
+		 * The other end is an earlier version that we need to adjust
+		 * for compatibility.
+		 */
+		connected->id.name.valid = 1;
+		connected->id.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1;
+		connected->id.number.valid = 1;
+		if (got_combined_presentation) {
+			connected->id.name.presentation = combined_presentation;
+			connected->id.number.presentation = combined_presentation;
+		}
+		break;
+	case 2:
+		/* The other end is at the same level as we are. */
+		break;
+	default:
+		/*
+		 * The other end is newer than we are.
+		 * We need to assume that they are compatible with us.
+		 */
+		ast_log(LOG_DEBUG, "Connected line frame has newer version: %u\n",
+			(unsigned) frame_version);
+		break;
+	}
+
 	return 0;
 }
 
-void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected)
+void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
 {
 	unsigned char data[1024];	/* This should be large enough */
 	size_t datalen;
 
-	datalen = ast_connected_line_build_data(data, sizeof(data), connected);
+	datalen = ast_connected_line_build_data(data, sizeof(data), connected, update);
 	if (datalen == (size_t) -1) {
 		return;
 	}
@@ -7659,12 +8154,12 @@ void ast_channel_update_connected_line(struct ast_channel *chan, const struct as
 	ast_indicate_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen);
 }
 
-void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected)
+void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
 {
 	unsigned char data[1024];	/* This should be large enough */
 	size_t datalen;
 
-	datalen = ast_connected_line_build_data(data, sizeof(data), connected);
+	datalen = ast_connected_line_build_data(data, sizeof(data), connected, update);
 	if (datalen == (size_t) -1) {
 		return;
 	}
@@ -7672,7 +8167,7 @@ void ast_channel_queue_connected_line_update(struct ast_channel *chan, const str
 	ast_queue_control_data(chan, AST_CONTROL_CONNECTED_LINE, data, datalen);
 }
 
-void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
+void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
 {
 	if (&chan->redirecting == redirecting) {
 		/* Don't set to self */
@@ -7680,12 +8175,7 @@ void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_part
 	}
 
 	ast_channel_lock(chan);
-
-	ast_party_id_set(&chan->redirecting.from, &redirecting->from);
-	ast_party_id_set(&chan->redirecting.to, &redirecting->to);
-	chan->redirecting.reason = redirecting->reason;
-	chan->redirecting.count = redirecting->count;
-
+	ast_party_redirecting_set(&chan->redirecting, redirecting, update);
 	ast_channel_unlock(chan);
 }
 
@@ -7696,12 +8186,12 @@ void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_part
 enum {
 	AST_REDIRECTING_FROM_NUMBER,
 	AST_REDIRECTING_FROM_NAME,
-	AST_REDIRECTING_FROM_NUMBER_TYPE,
-	AST_REDIRECTING_FROM_NUMBER_PRESENTATION,
+	AST_REDIRECTING_FROM_NUMBER_PLAN,
+	AST_REDIRECTING_FROM_ID_PRESENTATION,
 	AST_REDIRECTING_TO_NUMBER,
 	AST_REDIRECTING_TO_NAME,
-	AST_REDIRECTING_TO_NUMBER_TYPE,
-	AST_REDIRECTING_TO_NUMBER_PRESENTATION,
+	AST_REDIRECTING_TO_NUMBER_PLAN,
+	AST_REDIRECTING_TO_ID_PRESENTATION,
 	AST_REDIRECTING_REASON,
 	AST_REDIRECTING_COUNT,
 	AST_REDIRECTING_FROM_SUBADDRESS,
@@ -7714,200 +8204,86 @@ enum {
 	AST_REDIRECTING_TO_SUBADDRESS_VALID,
 	AST_REDIRECTING_FROM_TAG,
 	AST_REDIRECTING_TO_TAG,
+	AST_REDIRECTING_VERSION,
+	AST_REDIRECTING_FROM_NAME_VALID,
+	AST_REDIRECTING_FROM_NAME_CHAR_SET,
+	AST_REDIRECTING_FROM_NAME_PRESENTATION,
+	AST_REDIRECTING_FROM_NUMBER_VALID,
+	AST_REDIRECTING_FROM_NUMBER_PRESENTATION,
+	AST_REDIRECTING_TO_NAME_VALID,
+	AST_REDIRECTING_TO_NAME_CHAR_SET,
+	AST_REDIRECTING_TO_NAME_PRESENTATION,
+	AST_REDIRECTING_TO_NUMBER_VALID,
+	AST_REDIRECTING_TO_NUMBER_PRESENTATION,
 };
 
-int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting)
+int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
 {
 	int32_t value;
-	size_t length;
 	size_t pos = 0;
+	int res;
 
-	/*
-	 * The size of integer values must be fixed in case the frame is
-	 * shipped to another machine.
-	 */
-
-	/* *************** Redirecting from party id *************** */
-	if (redirecting->from.number) {
-		length = strlen(redirecting->from.number);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting from number\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_FROM_NUMBER;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->from.number, length);
-		pos += length;
-	}
-
-	if (redirecting->from.name) {
-		length = strlen(redirecting->from.name);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting from name\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_FROM_NAME;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->from.name, length);
-		pos += length;
-	}
-
-	if (redirecting->from.tag) {
-		length = strlen(redirecting->from.tag);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting from name\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_FROM_TAG;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->from.tag, length);
-		pos += length;
-	}
-
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting from type of number\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_FROM_NUMBER_TYPE;
-	data[pos++] = 1;
-	data[pos++] = redirecting->from.number_type;
-
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting from presentation\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_FROM_NUMBER_PRESENTATION;
-	data[pos++] = 1;
-	data[pos++] = redirecting->from.number_presentation;
-
-	/* subaddress */
-	if (redirecting->from.subaddress.str) {
-		length = strlen(redirecting->from.subaddress.str);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting-from subaddress\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->from.subaddress.str, length);
-		pos += length;
-	}
-
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting-from type of subaddress\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS_TYPE;
-	data[pos++] = 1;
-	data[pos++] = redirecting->from.subaddress.type;
-
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING,
-			"No space left for redirecting-from subaddress odd-even indicator\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN;
-	data[pos++] = 1;
-	data[pos++] = redirecting->from.subaddress.odd_even_indicator;
-
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting-from subaddress valid\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_FROM_SUBADDRESS_VALID;
-	data[pos++] = 1;
-	data[pos++] = redirecting->from.subaddress.valid;
-
-	/* *************** Redirecting to party id *************** */
-	if (redirecting->to.number) {
-		length = strlen(redirecting->to.number);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting to number\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_TO_NUMBER;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->to.number, length);
-		pos += length;
-	}
-
-	if (redirecting->to.name) {
-		length = strlen(redirecting->to.name);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting to name\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_TO_NAME;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->to.name, length);
-		pos += length;
-	}
-
-	if (redirecting->to.tag) {
-		length = strlen(redirecting->to.tag);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting to name\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_TO_TAG;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->to.tag, length);
-		pos += length;
-	}
+	static const struct ast_party_id_ies from_ies = {
+		.name.str = AST_REDIRECTING_FROM_NAME,
+		.name.char_set = AST_REDIRECTING_FROM_NAME_CHAR_SET,
+		.name.presentation = AST_REDIRECTING_FROM_NAME_PRESENTATION,
+		.name.valid = AST_REDIRECTING_FROM_NAME_VALID,
 
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting to type of number\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_TO_NUMBER_TYPE;
-	data[pos++] = 1;
-	data[pos++] = redirecting->to.number_type;
+		.number.str = AST_REDIRECTING_FROM_NUMBER,
+		.number.plan = AST_REDIRECTING_FROM_NUMBER_PLAN,
+		.number.presentation = AST_REDIRECTING_FROM_NUMBER_PRESENTATION,
+		.number.valid = AST_REDIRECTING_FROM_NUMBER_VALID,
 
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting to presentation\n");
-		return -1;
-	}
-	data[pos++] = AST_REDIRECTING_TO_NUMBER_PRESENTATION;
-	data[pos++] = 1;
-	data[pos++] = redirecting->to.number_presentation;
+		.subaddress.str = AST_REDIRECTING_FROM_SUBADDRESS,
+		.subaddress.type = AST_REDIRECTING_FROM_SUBADDRESS_TYPE,
+		.subaddress.odd_even_indicator = AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN,
+		.subaddress.valid = AST_REDIRECTING_FROM_SUBADDRESS_VALID,
 
-	/* subaddress */
-	if (redirecting->to.subaddress.str) {
-		length = strlen(redirecting->to.subaddress.str);
-		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
-			ast_log(LOG_WARNING, "No space left for redirecting-to subaddress\n");
-			return -1;
-		}
-		data[pos++] = AST_REDIRECTING_TO_SUBADDRESS;
-		data[pos++] = length;
-		memcpy(data + pos, redirecting->to.subaddress.str, length);
-		pos += length;
-	}
+		.tag = AST_REDIRECTING_FROM_TAG,
+		.combined_presentation = AST_REDIRECTING_FROM_ID_PRESENTATION,
+	};
+	static const struct ast_party_id_ies to_ies = {
+		.name.str = AST_REDIRECTING_TO_NAME,
+		.name.char_set = AST_REDIRECTING_TO_NAME_CHAR_SET,
+		.name.presentation = AST_REDIRECTING_TO_NAME_PRESENTATION,
+		.name.valid = AST_REDIRECTING_TO_NAME_VALID,
+
+		.number.str = AST_REDIRECTING_TO_NUMBER,
+		.number.plan = AST_REDIRECTING_TO_NUMBER_PLAN,
+		.number.presentation = AST_REDIRECTING_TO_NUMBER_PRESENTATION,
+		.number.valid = AST_REDIRECTING_TO_NUMBER_VALID,
+
+		.subaddress.str = AST_REDIRECTING_TO_SUBADDRESS,
+		.subaddress.type = AST_REDIRECTING_TO_SUBADDRESS_TYPE,
+		.subaddress.odd_even_indicator = AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN,
+		.subaddress.valid = AST_REDIRECTING_TO_SUBADDRESS_VALID,
+
+		.tag = AST_REDIRECTING_TO_TAG,
+		.combined_presentation = AST_REDIRECTING_TO_ID_PRESENTATION,
+	};
 
+	/* Redirecting frame version */
 	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting-to type of subaddress\n");
+		ast_log(LOG_WARNING, "No space left for redirecting frame version\n");
 		return -1;
 	}
-	data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_TYPE;
+	data[pos++] = AST_REDIRECTING_VERSION;
 	data[pos++] = 1;
-	data[pos++] = redirecting->to.subaddress.type;
+	data[pos++] = 2;/* Version 1 did not have a version ie */
 
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING,
-			"No space left for redirecting-to subaddress odd-even indicator\n");
+	res = party_id_build_data(data + pos, datalen - pos, &redirecting->from,
+		"redirecting-from", &from_ies, update ? &update->from : NULL);
+	if (res < 0) {
 		return -1;
 	}
-	data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN;
-	data[pos++] = 1;
-	data[pos++] = redirecting->to.subaddress.odd_even_indicator;
+	pos += res;
 
-	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
-		ast_log(LOG_WARNING, "No space left for redirecting-to subaddress valid\n");
+	res = party_id_build_data(data + pos, datalen - pos, &redirecting->to,
+		"redirecting-to", &to_ies, update ? &update->to : NULL);
+	if (res < 0) {
 		return -1;
 	}
-	data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_VALID;
-	data[pos++] = 1;
-	data[pos++] = redirecting->to.subaddress.valid;
+	pos += res;
 
 	/* Redirecting reason */
 	if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
@@ -7940,6 +8316,11 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 	unsigned char ie_len;
 	unsigned char ie_id;
 	int32_t value;
+	int frame_version = 1;
+	int from_combined_presentation = 0;
+	int got_from_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */
+	int to_combined_presentation = 0;
+	int got_to_combined_presentation = 0;/* TRUE if got a combined name and number presentation value. */
 
 	for (pos = 0; pos < datalen; pos += ie_len) {
 		if (datalen < pos + sizeof(ie_id) + sizeof(ie_len)) {
@@ -7954,54 +8335,94 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 		}
 
 		switch (ie_id) {
-		case AST_REDIRECTING_FROM_NUMBER:
-			if (redirecting->from.number) {
-				ast_free(redirecting->from.number);
-			}
-			redirecting->from.number = ast_malloc(ie_len + 1);
-			if (redirecting->from.number) {
-				memcpy(redirecting->from.number, data + pos, ie_len);
-				redirecting->from.number[ie_len] = 0;
+/* Redirecting frame version */
+		case AST_REDIRECTING_VERSION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting frame version (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			frame_version = data[pos];
 			break;
+/* Redirecting-from party id name */
 		case AST_REDIRECTING_FROM_NAME:
-			if (redirecting->from.name) {
-				ast_free(redirecting->from.name);
+			ast_free(redirecting->from.name.str);
+			redirecting->from.name.str = ast_malloc(ie_len + 1);
+			if (redirecting->from.name.str) {
+				memcpy(redirecting->from.name.str, data + pos, ie_len);
+				redirecting->from.name.str[ie_len] = 0;
 			}
-			redirecting->from.name = ast_malloc(ie_len + 1);
-			if (redirecting->from.name) {
-				memcpy(redirecting->from.name, data + pos, ie_len);
-				redirecting->from.name[ie_len] = 0;
+			break;
+		case AST_REDIRECTING_FROM_NAME_CHAR_SET:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-from name char set (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			redirecting->from.name.char_set = data[pos];
 			break;
-		case AST_REDIRECTING_FROM_TAG:
-			if (redirecting->from.tag) {
-				ast_free(redirecting->from.tag);
+		case AST_REDIRECTING_FROM_NAME_PRESENTATION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-from name presentation (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
-			redirecting->from.tag = ast_malloc(ie_len + 1);
-			if (redirecting->from.tag) {
-				memcpy(redirecting->from.tag, data + pos, ie_len);
-				redirecting->from.tag[ie_len] = 0;
+			redirecting->from.name.presentation = data[pos];
+			break;
+		case AST_REDIRECTING_FROM_NAME_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-from name valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->from.name.valid = data[pos];
+			break;
+/* Redirecting-from party id number */
+		case AST_REDIRECTING_FROM_NUMBER:
+			ast_free(redirecting->from.number.str);
+			redirecting->from.number.str = ast_malloc(ie_len + 1);
+			if (redirecting->from.number.str) {
+				memcpy(redirecting->from.number.str, data + pos, ie_len);
+				redirecting->from.number.str[ie_len] = 0;
 			}
 			break;
-		case AST_REDIRECTING_FROM_NUMBER_TYPE:
+		case AST_REDIRECTING_FROM_NUMBER_PLAN:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting from type of number (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid redirecting-from numbering plan (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			redirecting->from.number_type = data[pos];
+			redirecting->from.number.plan = data[pos];
 			break;
 		case AST_REDIRECTING_FROM_NUMBER_PRESENTATION:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting from presentation (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid redirecting-from number presentation (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			redirecting->from.number_presentation = data[pos];
+			redirecting->from.number.presentation = data[pos];
 			break;
-		case AST_REDIRECTING_FROM_SUBADDRESS:
-			if (redirecting->from.subaddress.str) {
-				ast_free(redirecting->from.subaddress.str);
+		case AST_REDIRECTING_FROM_NUMBER_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-from number valid (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			redirecting->from.number.valid = data[pos];
+			break;
+/* Redirecting-from party id combined presentation */
+		case AST_REDIRECTING_FROM_ID_PRESENTATION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-from combined presentation (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			from_combined_presentation = data[pos];
+			got_from_combined_presentation = 1;
+			break;
+/* Redirecting-from party id subaddress */
+		case AST_REDIRECTING_FROM_SUBADDRESS:
+			ast_free(redirecting->from.subaddress.str);
 			redirecting->from.subaddress.str = ast_malloc(ie_len + 1);
 			if (redirecting->from.subaddress.str) {
 				memcpy(redirecting->from.subaddress.str, data + pos, ie_len);
@@ -8010,7 +8431,7 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 			break;
 		case AST_REDIRECTING_FROM_SUBADDRESS_TYPE:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting from type of subaddress (%u)\n",
+				ast_log(LOG_WARNING, "Invalid redirecting-from type of subaddress (%u)\n",
 					(unsigned) ie_len);
 				break;
 			}
@@ -8019,7 +8440,7 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 		case AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN:
 			if (ie_len != 1) {
 				ast_log(LOG_WARNING,
-					"Invalid redirecting from subaddress odd-even indicator (%u)\n",
+					"Invalid redirecting-from subaddress odd-even indicator (%u)\n",
 					(unsigned) ie_len);
 				break;
 			}
@@ -8027,60 +8448,100 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 			break;
 		case AST_REDIRECTING_FROM_SUBADDRESS_VALID:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting from subaddress valid (%u)\n",
+				ast_log(LOG_WARNING, "Invalid redirecting-from subaddress valid (%u)\n",
 					(unsigned) ie_len);
 				break;
 			}
 			redirecting->from.subaddress.valid = data[pos];
 			break;
-		case AST_REDIRECTING_TO_NUMBER:
-			if (redirecting->to.number) {
-				ast_free(redirecting->to.number);
-			}
-			redirecting->to.number = ast_malloc(ie_len + 1);
-			if (redirecting->to.number) {
-				memcpy(redirecting->to.number, data + pos, ie_len);
-				redirecting->to.number[ie_len] = 0;
+/* Redirecting-from party id tag */
+		case AST_REDIRECTING_FROM_TAG:
+			ast_free(redirecting->from.tag);
+			redirecting->from.tag = ast_malloc(ie_len + 1);
+			if (redirecting->from.tag) {
+				memcpy(redirecting->from.tag, data + pos, ie_len);
+				redirecting->from.tag[ie_len] = 0;
 			}
 			break;
+/* Redirecting-to party id name */
 		case AST_REDIRECTING_TO_NAME:
-			if (redirecting->to.name) {
-				ast_free(redirecting->to.name);
+			ast_free(redirecting->to.name.str);
+			redirecting->to.name.str = ast_malloc(ie_len + 1);
+			if (redirecting->to.name.str) {
+				memcpy(redirecting->to.name.str, data + pos, ie_len);
+				redirecting->to.name.str[ie_len] = 0;
 			}
-			redirecting->to.name = ast_malloc(ie_len + 1);
-			if (redirecting->to.name) {
-				memcpy(redirecting->to.name, data + pos, ie_len);
-				redirecting->to.name[ie_len] = 0;
+			break;
+		case AST_REDIRECTING_TO_NAME_CHAR_SET:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-to name char set (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			redirecting->to.name.char_set = data[pos];
 			break;
-		case AST_REDIRECTING_TO_TAG:
-			if (redirecting->to.tag) {
-				ast_free(redirecting->to.tag);
+		case AST_REDIRECTING_TO_NAME_PRESENTATION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-to name presentation (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
-			redirecting->to.tag = ast_malloc(ie_len + 1);
-			if (redirecting->to.tag) {
-				memcpy(redirecting->to.tag, data + pos, ie_len);
-				redirecting->to.tag[ie_len] = 0;
+			redirecting->to.name.presentation = data[pos];
+			break;
+		case AST_REDIRECTING_TO_NAME_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-to name valid (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			redirecting->to.name.valid = data[pos];
 			break;
-		case AST_REDIRECTING_TO_NUMBER_TYPE:
+/* Redirecting-to party id number */
+		case AST_REDIRECTING_TO_NUMBER:
+			ast_free(redirecting->to.number.str);
+			redirecting->to.number.str = ast_malloc(ie_len + 1);
+			if (redirecting->to.number.str) {
+				memcpy(redirecting->to.number.str, data + pos, ie_len);
+				redirecting->to.number.str[ie_len] = 0;
+			}
+			break;
+		case AST_REDIRECTING_TO_NUMBER_PLAN:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting to type of number (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid redirecting-to numbering plan (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			redirecting->to.number_type = data[pos];
+			redirecting->to.number.plan = data[pos];
 			break;
 		case AST_REDIRECTING_TO_NUMBER_PRESENTATION:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting to presentation (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid redirecting-to number presentation (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
-			redirecting->to.number_presentation = data[pos];
+			redirecting->to.number.presentation = data[pos];
 			break;
-		case AST_REDIRECTING_TO_SUBADDRESS:
-			if (redirecting->to.subaddress.str) {
-				ast_free(redirecting->to.subaddress.str);
+		case AST_REDIRECTING_TO_NUMBER_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-to number valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			redirecting->to.number.valid = data[pos];
+			break;
+/* Redirecting-to party id combined presentation */
+		case AST_REDIRECTING_TO_ID_PRESENTATION:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid redirecting-to combined presentation (%u)\n",
+					(unsigned) ie_len);
+				break;
 			}
+			to_combined_presentation = data[pos];
+			got_to_combined_presentation = 1;
+			break;
+/* Redirecting-to party id subaddress */
+		case AST_REDIRECTING_TO_SUBADDRESS:
+			ast_free(redirecting->to.subaddress.str);
 			redirecting->to.subaddress.str = ast_malloc(ie_len + 1);
 			if (redirecting->to.subaddress.str) {
 				memcpy(redirecting->to.subaddress.str, data + pos, ie_len);
@@ -8089,7 +8550,7 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 			break;
 		case AST_REDIRECTING_TO_SUBADDRESS_TYPE:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting to type of subaddress (%u)\n",
+				ast_log(LOG_WARNING, "Invalid redirecting-to type of subaddress (%u)\n",
 					(unsigned) ie_len);
 				break;
 			}
@@ -8098,7 +8559,7 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 		case AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN:
 			if (ie_len != 1) {
 				ast_log(LOG_WARNING,
-					"Invalid redirecting to subaddress odd-even indicator (%u)\n",
+					"Invalid redirecting-to subaddress odd-even indicator (%u)\n",
 					(unsigned) ie_len);
 				break;
 			}
@@ -8106,43 +8567,93 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
 			break;
 		case AST_REDIRECTING_TO_SUBADDRESS_VALID:
 			if (ie_len != 1) {
-				ast_log(LOG_WARNING, "Invalid redirecting to subaddress valid (%u)\n",
+				ast_log(LOG_WARNING, "Invalid redirecting-to subaddress valid (%u)\n",
 					(unsigned) ie_len);
 				break;
 			}
 			redirecting->to.subaddress.valid = data[pos];
 			break;
+/* Redirecting-to party id tag */
+		case AST_REDIRECTING_TO_TAG:
+			ast_free(redirecting->to.tag);
+			redirecting->to.tag = ast_malloc(ie_len + 1);
+			if (redirecting->to.tag) {
+				memcpy(redirecting->to.tag, data + pos, ie_len);
+				redirecting->to.tag[ie_len] = 0;
+			}
+			break;
+/* Redirecting reason */
 		case AST_REDIRECTING_REASON:
 			if (ie_len != sizeof(value)) {
-				ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
 			memcpy(&value, data + pos, sizeof(value));
 			redirecting->reason = ntohl(value);
 			break;
+/* Redirecting count */
 		case AST_REDIRECTING_COUNT:
 			if (ie_len != sizeof(value)) {
-				ast_log(LOG_WARNING, "Invalid redirecting count (%u)\n", (unsigned) ie_len);
+				ast_log(LOG_WARNING, "Invalid redirecting count (%u)\n",
+					(unsigned) ie_len);
 				break;
 			}
 			memcpy(&value, data + pos, sizeof(value));
 			redirecting->count = ntohl(value);
 			break;
+/* Redirecting unknown element */
 		default:
-			ast_log(LOG_DEBUG, "Unknown redirecting element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
+			ast_log(LOG_DEBUG, "Unknown redirecting element: %u (%u)\n",
+				(unsigned) ie_id, (unsigned) ie_len);
 			break;
 		}
 	}
 
+	switch (frame_version) {
+	case 1:
+		/*
+		 * The other end is an earlier version that we need to adjust
+		 * for compatibility.
+		 */
+		redirecting->from.name.valid = 1;
+		redirecting->from.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1;
+		redirecting->from.number.valid = 1;
+		if (got_from_combined_presentation) {
+			redirecting->from.name.presentation = from_combined_presentation;
+			redirecting->from.number.presentation = from_combined_presentation;
+		}
+
+		redirecting->to.name.valid = 1;
+		redirecting->to.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1;
+		redirecting->to.number.valid = 1;
+		if (got_to_combined_presentation) {
+			redirecting->to.name.presentation = to_combined_presentation;
+			redirecting->to.number.presentation = to_combined_presentation;
+		}
+		break;
+	case 2:
+		/* The other end is at the same level as we are. */
+		break;
+	default:
+		/*
+		 * The other end is newer than we are.
+		 * We need to assume that they are compatible with us.
+		 */
+		ast_log(LOG_DEBUG, "Redirecting frame has newer version: %u\n",
+			(unsigned) frame_version);
+		break;
+	}
+
 	return 0;
 }
 
-void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
+void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
 {
 	unsigned char data[1024];	/* This should be large enough */
 	size_t datalen;
 
-	datalen = ast_redirecting_build_data(data, sizeof(data), redirecting);
+	datalen = ast_redirecting_build_data(data, sizeof(data), redirecting, update);
 	if (datalen == (size_t) -1) {
 		return;
 	}
@@ -8150,12 +8661,12 @@ void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_p
 	ast_indicate_data(chan, AST_CONTROL_REDIRECTING, data, datalen);
 }
 
-void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting)
+void ast_channel_queue_redirecting_update(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
 {
 	unsigned char data[1024];	/* This should be large enough */
 	size_t datalen;
 
-	datalen = ast_redirecting_build_data(data, sizeof(data), redirecting);
+	datalen = ast_redirecting_build_data(data, sizeof(data), redirecting, update);
 	if (datalen == (size_t) -1) {
 		return;
 	}
@@ -8193,7 +8704,7 @@ int ast_channel_connected_line_macro(struct ast_channel *autoservice_chan, struc
 	}
 
 	if (!(retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args))) {
-		ast_channel_update_connected_line(macro_chan, &macro_chan->connected);
+		ast_channel_update_connected_line(macro_chan, &macro_chan->connected, NULL);
 	}
 
 	return retval;
@@ -8230,7 +8741,7 @@ int ast_channel_redirecting_macro(struct ast_channel *autoservice_chan, struct a
 
 	retval = ast_app_run_macro(autoservice_chan, macro_chan, macro, macro_args);
 	if (!retval) {
-		ast_channel_update_redirecting(macro_chan, &macro_chan->redirecting);
+		ast_channel_update_redirecting(macro_chan, &macro_chan->redirecting, NULL);
 	}
 
 	return retval;
diff --git a/main/cli.c b/main/cli.c
index 0b58c346151b9380bb1e870b6c0940afca77a8b9..c9dbc6d02ece87751280e1844955801ddf577be4 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -872,7 +872,7 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 				ast_cli(a->fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
 					c->appl ? c->appl : "(None)",
 					S_OR(c->data, ""),	/* XXX different from verbose ? */
-					S_OR(c->cid.cid_num, ""),
+					S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
 					S_OR(c->accountcode, ""),
 					S_OR(c->peeraccount, ""),
 					c->amaflags, 
@@ -883,7 +883,7 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 				ast_cli(a->fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
 					c->appl ? c->appl : "(None)",
 					c->data ? S_OR(c->data, "(Empty)" ): "(None)",
-					S_OR(c->cid.cid_num, ""),
+					S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
 					durbuf,
 					S_OR(c->accountcode, ""),
 					S_OR(c->peeraccount, ""),
@@ -1417,9 +1417,9 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 		"           Data: %s\n"
 		"    Blocking in: %s\n",
 		c->name, c->tech->type, c->uniqueid, c->linkedid,
-		S_OR(c->cid.cid_num, "(N/A)"),
-		S_OR(c->cid.cid_name, "(N/A)"),
-		S_OR(c->cid.cid_dnid, "(N/A)"), 
+		S_COR(c->caller.id.number.valid, c->caller.id.number.str, "(N/A)"),
+		S_COR(c->caller.id.name.valid, c->caller.id.name.str, "(N/A)"),
+		S_OR(c->dialed.number.str, "(N/A)"),
 		c->language,	
 		ast_state2str(c->_state), c->_state, c->rings, 
 		ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats), 
diff --git a/main/dial.c b/main/dial.c
index bfd0c44a40f1daa1909e230965f5018b76a98d08..ba1a2bb53cf3d2c54c54dd5b0b7f9422b5bb74a8 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -268,9 +268,9 @@ static int begin_dial_channel(struct ast_dial_channel *channel, struct ast_chann
 		/* Copy over callerid information */
 		ast_party_redirecting_copy(&channel->owner->redirecting, &chan->redirecting);
 
-		channel->owner->cid.cid_tns = chan->cid.cid_tns;
+		channel->owner->dialed.transit_network_select = chan->dialed.transit_network_select;
 
-		ast_connected_line_copy_from_caller(&channel->owner->connected, &chan->cid);
+		ast_connected_line_copy_from_caller(&channel->owner->connected, &chan->caller);
 
 		ast_string_field_set(channel->owner, language, chan->language);
 		ast_string_field_set(channel->owner, accountcode, chan->accountcode);
diff --git a/main/features.c b/main/features.c
index a107b4b7acc470d8c0975edb629df6efde232534..d5fc289f29f66e5421f39db52e726cb0062add5e 100644
--- a/main/features.c
+++ b/main/features.c
@@ -961,8 +961,8 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
 		"Uniqueid: %s\r\n",
 		pu->parkingexten, pu->chan->name, pu->parkinglot->name, event_from ? event_from : "",
 		(long)pu->start.tv_sec + (long)(pu->parkingtime/1000) - (long)time(NULL),
-		S_OR(pu->chan->cid.cid_num, "<unknown>"),
-		S_OR(pu->chan->cid.cid_name, "<unknown>"),
+		S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
+		S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
 		pu->chan->uniqueid
 		);
 
@@ -1417,8 +1417,10 @@ static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *pee
 			snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
 			snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
 		} else {
-			caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
-			callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
+			caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
+				caller_chan->caller.id.number.str, caller_chan->name));
+			callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
+				callee_chan->caller.id.number.str, callee_chan->name));
 			len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
 			args = alloca(len);
 			touch_filename = alloca(len);
@@ -1530,8 +1532,10 @@ static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *
 			snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
 			snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
 		} else {
-			caller_chan_id = ast_strdupa(S_OR(caller_chan->cid.cid_num, caller_chan->name));
-			callee_chan_id = ast_strdupa(S_OR(callee_chan->cid.cid_num, callee_chan->name));
+			caller_chan_id = ast_strdupa(S_COR(caller_chan->caller.id.number.valid,
+				caller_chan->caller.id.number.str, caller_chan->name));
+			callee_chan_id = ast_strdupa(S_COR(callee_chan->caller.id.number.valid,
+				callee_chan->caller.id.number.str, callee_chan->name));
 			len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
 			args = alloca(len);
 			touch_filename = alloca(len);
@@ -1653,7 +1657,8 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
 			ast_log(LOG_WARNING, "Unable to park call %s, parkstatus = %d\n", transferee->name, parkstatus);
 		}
 		/*! \todo XXX Maybe we should have another message here instead of invalid extension XXX */
-	} else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
+	} else if (ast_exists_extension(transferee, transferer_real_context, xferto, 1,
+		S_COR(transferer->caller.id.number.valid, transferer->caller.id.number.str, NULL))) {
 		ast_cel_report_event(transferer, AST_CEL_BLINDTRANSFER, NULL, xferto, transferee);
 		pbx_builtin_setvar_helper(transferer, "BLINDTRANSFER", transferee->name);
 		pbx_builtin_setvar_helper(transferee, "BLINDTRANSFER", transferer->name);
@@ -1688,7 +1693,7 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
 			ast_set_flag(transferee, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
 			ast_log(LOG_DEBUG,"ABOUT TO AST_ASYNC_GOTO, have a pbx... set HANGUP_DONT on chan=%s\n", transferee->name);
 			if (ast_channel_connected_line_macro(transferee, transferer, &transferer->connected, 1, 0)) {
-				ast_channel_update_connected_line(transferee, &transferer->connected);
+				ast_channel_update_connected_line(transferee, &transferer->connected, NULL);
 			}
 			set_c_e_p(transferee, transferer_real_context, xferto, 0);
 		}
@@ -1792,7 +1797,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
 	}
 
 	/* valid extension, res == 1 */
-	if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
+	if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1,
+		S_COR(transferer->caller.id.number.valid, transferer->caller.id.number.str, NULL))) {
 		ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
 		finishup(transferee);
 		if (ast_stream_and_wait(transferer, "beeperr", ""))
@@ -1824,8 +1830,12 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
 		}
 	}
 
-	newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
-		xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
+	newchan = feature_request_and_dial(transferer, transferee, "Local",
+		ast_best_codec(transferer->nativeformats),
+		xferto, atxfernoanswertimeout, &outstate,
+		transferer->caller.id.number.valid ? transferer->caller.id.number.str : NULL,
+		transferer->caller.id.name.valid ? transferer->caller.id.name.str : NULL,
+		1, transferer->language);
 
 	ast_party_connected_line_init(&connected_line);
 	if (!ast_check_hangup(transferer)) {
@@ -1979,14 +1989,14 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
 		 */
 		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
 		if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
-			ast_channel_update_connected_line(xferchan, &connected_line);
+			ast_channel_update_connected_line(xferchan, &connected_line, NULL);
 		}
 		ast_channel_lock(xferchan);
-		ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
+		ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
 		ast_channel_unlock(xferchan);
 		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
 		if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
-			ast_channel_update_connected_line(newchan, &connected_line);
+			ast_channel_update_connected_line(newchan, &connected_line, NULL);
 		}
 		ast_party_connected_line_free(&connected_line);
 
@@ -2016,15 +2026,23 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
 			}
 
 			ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
-			newchan = feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
-				transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+			newchan = feature_request_and_dial(transferee, NULL, transferer_tech,
+				ast_best_codec(transferee->nativeformats),
+				transferer_name, atxfernoanswertimeout, &outstate,
+				transferee->caller.id.number.valid ? transferee->caller.id.number.str : NULL,
+				transferee->caller.id.name.valid ? transferee->caller.id.name.str : NULL,
+				0, transferer->language);
 			while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
 				/* Trying to transfer again */
 				ast_autoservice_start(transferee);
 				ast_indicate(transferee, AST_CONTROL_HOLD);
 
-				newchan = feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
-					xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
+				newchan = feature_request_and_dial(transferer, transferee, "Local",
+					ast_best_codec(transferer->nativeformats),
+					xferto, atxfernoanswertimeout, &outstate,
+					transferer->caller.id.number.valid ? transferer->caller.id.number.str : NULL,
+					transferer->caller.id.name.valid ? transferer->caller.id.name.str : NULL,
+					1, transferer->language);
 				if (ast_autoservice_stop(transferee) < 0) {
 					if (newchan)
 						ast_hangup(newchan);
@@ -2035,8 +2053,12 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
 					ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
 					ast_safe_sleep(transferee, atxferloopdelay);
 					ast_debug(1, "Trying to callback...\n");
-					newchan = feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
-						transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+					newchan = feature_request_and_dial(transferee, NULL, transferer_tech,
+						ast_best_codec(transferee->nativeformats),
+						transferer_name, atxfernoanswertimeout, &outstate,
+						transferee->caller.id.number.valid ? transferee->caller.id.number.str : NULL,
+						transferee->caller.id.name.valid ? transferee->caller.id.name.str : NULL,
+						0, transferer->language);
 				}
 				tries++;
 			}
@@ -2094,18 +2116,18 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
 		}
 
 		ast_channel_lock(newchan);
-		ast_connected_line_copy_from_caller(&connected_line, &newchan->cid);
+		ast_connected_line_copy_from_caller(&connected_line, &newchan->caller);
 		ast_channel_unlock(newchan);
 		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
 		if (ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
-			ast_channel_update_connected_line(xferchan, &connected_line);
+			ast_channel_update_connected_line(xferchan, &connected_line, NULL);
 		}
 		ast_channel_lock(xferchan);
-		ast_connected_line_copy_from_caller(&connected_line, &xferchan->cid);
+		ast_connected_line_copy_from_caller(&connected_line, &xferchan->caller);
 		ast_channel_unlock(xferchan);
 		connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
 		if (ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
-			ast_channel_update_connected_line(newchan, &connected_line);
+			ast_channel_update_connected_line(newchan, &connected_line, NULL);
 		}
 
 		ast_party_connected_line_free(&connected_line);
@@ -2676,7 +2698,7 @@ static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
 	pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
 		
 	ast_channel_lock(chan);
-	ast_connected_line_copy_from_caller(&chan->connected, &caller->cid);
+	ast_connected_line_copy_from_caller(&chan->connected, &caller->caller);
 	ast_channel_unlock(chan);
 	
 	if (ast_call(chan, data, timeout)) {
@@ -3328,8 +3350,9 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 	 * if it were, then chan belongs to a different thread now, and might have been hung up long
      * ago.
 	 */
-	if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) &&
-		ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) {
+	if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN)
+		&& ast_exists_extension(chan, chan->context, "h", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		struct ast_cdr *swapper = NULL;
 		char savelastapp[AST_MAX_EXTENSION];
 		char savelastdata[AST_MAX_EXTENSION];
@@ -3357,10 +3380,16 @@ int ast_bridge_call(struct ast_channel *chan,struct ast_channel *peer,struct ast
 		ast_copy_string(chan->exten, "h", sizeof(chan->exten));
 		chan->priority = 1;
 		ast_channel_unlock(chan);
-		while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &found, 1)) == 0) {
+		while ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten,
+			chan->priority,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL),
+			&found, 1)) == 0) {
 			chan->priority++;
 		}
-		if (spawn_error && (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num) || ast_check_hangup(chan))) {
+		if (spawn_error
+			&& (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority,
+				S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+				|| ast_check_hangup(chan))) {
 			/* if the extension doesn't exist or a hangup occurred, this isn't really a spawn error */
 			spawn_error = 0;
 		}
@@ -3503,8 +3532,8 @@ static void post_manager_event(const char *s, struct parkeduser *pu)
 		pu->parkingexten, 
 		pu->chan->name,
 		pu->parkinglot->name,
-		S_OR(pu->chan->cid.cid_num, "<unknown>"),
-		S_OR(pu->chan->cid.cid_name, "<unknown>"),
+		S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
+		S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>"),
 		pu->chan->uniqueid
 		);
 }
@@ -3952,8 +3981,8 @@ static int park_exec_full(struct ast_channel *chan, const char *data, struct ast
 			"CallerIDNum: %s\r\n"
 			"CallerIDName: %s\r\n",
 			pu->parkingexten, pu->chan->name, chan->name,
-			S_OR(pu->chan->cid.cid_num, "<unknown>"),
-			S_OR(pu->chan->cid.cid_name, "<unknown>")
+			S_COR(pu->chan->caller.id.number.valid, pu->chan->caller.id.number.str, "<unknown>"),
+			S_COR(pu->chan->caller.id.name.valid, pu->chan->caller.id.name.str, "<unknown>")
 			);
 
 		ast_free(pu);
@@ -4998,8 +5027,8 @@ static int manager_parking_status(struct mansession *s, const struct message *m)
 				"\r\n",
 				cur->parkingnum, cur->chan->name, cur->peername,
 				(long) cur->start.tv_sec + (long) (cur->parkingtime / 1000) - (long) time(NULL),
-				S_OR(cur->chan->cid.cid_num, ""),	/* XXX in other places it is <unknown> */
-				S_OR(cur->chan->cid.cid_name, ""),
+				S_COR(cur->chan->caller.id.number.valid, cur->chan->caller.id.number.str, ""),	/* XXX in other places it is <unknown> */
+				S_COR(cur->chan->caller.id.name.valid, cur->chan->caller.id.name.str, ""),
 				idText);
 		}
 		AST_LIST_UNLOCK(&curlot->parkings);
@@ -5135,12 +5164,12 @@ int ast_pickup_call(struct ast_channel *chan)
 	connected_caller = cur->connected;
 	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 	if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
-		ast_channel_update_connected_line(chan, &connected_caller);
+		ast_channel_update_connected_line(chan, &connected_caller, NULL);
 	}
 
-	ast_party_connected_line_collect_caller(&connected_caller, &chan->cid);
+	ast_party_connected_line_collect_caller(&connected_caller, &chan->caller);
 	connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
-	ast_channel_queue_connected_line_update(chan, &connected_caller);
+	ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
 
 	ast_channel_unlock(cur);
 	ast_channel_unlock(chan);
diff --git a/main/file.c b/main/file.c
index 6f3794338883ced8cb3a37fc9dd070ac1da90008..726a72b64abf7d5c71fa6c9166d16f1879004921 100644
--- a/main/file.c
+++ b/main/file.c
@@ -1236,7 +1236,8 @@ static int waitstream_core(struct ast_channel *c, const char *breakon,
 			case AST_FRAME_DTMF_END:
 				if (context) {
 					const char exten[2] = { fr->subclass.integer, '\0' };
-					if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) {
+					if (ast_exists_extension(c, context, exten, 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 						res = fr->subclass.integer;
 						ast_frfree(fr);
 						ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
diff --git a/main/manager.c b/main/manager.c
index 5c8f893af7f742e169e196116b22b87b362b92d8..6203614522e7d4498c25663bb7d3c1a7153084e3 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -3165,8 +3165,8 @@ static int action_status(struct mansession *s, const struct message *m)
 			"%s"
 			"\r\n",
 			c->name,
-			S_OR(c->cid.cid_num, ""),
-			S_OR(c->cid.cid_name, ""),
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
+			S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
 			c->accountcode,
 			c->_state,
 			ast_state2str(c->_state), c->context,
@@ -3186,8 +3186,8 @@ static int action_status(struct mansession *s, const struct message *m)
 				"%s"
 				"\r\n",
 				c->name,
-				S_OR(c->cid.cid_num, "<unknown>"),
-				S_OR(c->cid.cid_name, "<unknown>"),
+				S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<unknown>"),
+				S_COR(c->caller.id.name.valid, c->caller.id.name.str, "<unknown>"),
 				c->accountcode,
 				ast_state2str(c->_state), bridge, c->uniqueid,
 				ast_str_buffer(str), idText);
@@ -4276,7 +4276,8 @@ static int action_coreshowchannels(struct mansession *s, const struct message *m
 			"BridgedUniqueID: %s\r\n"
 			"\r\n", idText, c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state,
 			ast_state2str(c->_state), c->appl ? c->appl : "", c->data ? S_OR(c->data, "") : "",
-			S_OR(c->cid.cid_num, ""), durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""),
+			durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
 
 		ast_channel_unlock(c);
 
diff --git a/main/pbx.c b/main/pbx.c
index dbc4db49749350ad88208e37731c6557ea0408f1..3de94174076345d68128f7f663ed5fe84bb2bd79 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -3011,16 +3011,17 @@ const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, stru
 		if (!strncmp(var, "CALL", 4)) {
 			if (!strncmp(var + 4, "ING", 3)) {
 				if (!strcmp(var + 7, "PRES")) {			/* CALLINGPRES */
-					ast_str_set(str, maxlen, "%d", c->cid.cid_pres);
+					ast_str_set(str, maxlen, "%d",
+						ast_party_id_presentation(&c->caller.id));
 					s = ast_str_buffer(*str);
 				} else if (!strcmp(var + 7, "ANI2")) {		/* CALLINGANI2 */
-					ast_str_set(str, maxlen, "%d", c->cid.cid_ani2);
+					ast_str_set(str, maxlen, "%d", c->caller.ani2);
 					s = ast_str_buffer(*str);
 				} else if (!strcmp(var + 7, "TON")) {		/* CALLINGTON */
-					ast_str_set(str, maxlen, "%d", c->cid.cid_ton);
+					ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
 					s = ast_str_buffer(*str);
 				} else if (!strcmp(var + 7, "TNS")) {		/* CALLINGTNS */
-					ast_str_set(str, maxlen, "%d", c->cid.cid_tns);
+					ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
 					s = ast_str_buffer(*str);
 				}
 			}
@@ -4581,7 +4582,8 @@ static int collect_digits(struct ast_channel *c, int waittime, char *buf, int bu
 	int digit;
 
 	buf[pos] = '\0';	/* make sure it is properly terminated */
-	while (ast_matchmore_extension(c, c->context, buf, 1, c->cid.cid_num)) {
+	while (ast_matchmore_extension(c, c->context, buf, 1,
+		S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 		/* As long as we're willing to wait, and as long as it's not defined,
 		   keep reading digits until we can't possibly get a right answer anymore.  */
 		digit = ast_waitfordigit(c, waittime);
@@ -4626,7 +4628,8 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 	ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
 
 	/* Start by trying whatever the channel is set to */
-	if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
+	if (!ast_exists_extension(c, c->context, c->exten, c->priority,
+		S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 		/* If not successful fall back to 's' */
 		ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
 		/* XXX the original code used the existing priority in the call to
@@ -4634,7 +4637,8 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 		 * I believe the correct thing is to set it to 1 immediately.
 		 */
 		set_ext_pri(c, "s", 1);
-		if (!ast_exists_extension(c, c->context, c->exten, c->priority, c->cid.cid_num)) {
+		if (!ast_exists_extension(c, c->context, c->exten, c->priority,
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 			/* JK02: And finally back to default if everything else failed */
 			ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
 			ast_copy_string(c->context, "default", sizeof(c->context));
@@ -4652,13 +4656,19 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 		int timeout = 0;
 
 		/* loop on priorities in this context/exten */
-		while ( !(res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found,1))) {
-			if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
+		while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
+			&found, 1))) {
+			if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT
+				&& ast_exists_extension(c, c->context, "T", 1,
+					S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 				set_ext_pri(c, "T", 0); /* 0 will become 1 with the c->priority++; at the end */
 				/* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
 				memset(&c->whentohangup, 0, sizeof(c->whentohangup));
 				c->_softhangup &= ~AST_SOFTHANGUP_TIMEOUT;
-			} else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
+			} else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT
+				&& ast_exists_extension(c, c->context, "e", 1,
+					S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 				pbx_builtin_raise_exception(c, "ABSOLUTETIMEOUT");
 				/* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
 				memset(&c->whentohangup, 0, sizeof(c->whentohangup));
@@ -4686,7 +4696,8 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 				ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
 
 				/* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
-				if (!ast_matchmore_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
+				if (!ast_matchmore_extension(c, c->context, c->exten, 1,
+					S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 					invalid = 1;
 				} else {
 					ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
@@ -4697,7 +4708,9 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 				ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
 				ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
 
-				if ((res == AST_PBX_ERROR) && ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
+				if ((res == AST_PBX_ERROR)
+					&& ast_exists_extension(c, c->context, "e", 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 					/* if we are already on the 'e' exten, don't jump to it again */
 					if (!strcmp(c->exten, "e")) {
 						ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
@@ -4711,7 +4724,9 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 				if (c->_softhangup == AST_SOFTHANGUP_ASYNCGOTO) {
 					c->_softhangup = 0;
 					continue;
-				} else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT && ast_exists_extension(c, c->context, "T", 1, c->cid.cid_num)) {
+				} else if (c->_softhangup == AST_SOFTHANGUP_TIMEOUT
+					&& ast_exists_extension(c, c->context, "T", 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 					set_ext_pri(c, "T", 1);
 					/* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
 					memset(&c->whentohangup, 0, sizeof(c->whentohangup));
@@ -4733,17 +4748,21 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 		 * hangup.  We have options, here.  We can either catch the failure
 		 * and continue, or we can drop out entirely. */
 
-		if (invalid || !ast_exists_extension(c, c->context, c->exten, 1, c->cid.cid_num)) {
+		if (invalid
+			|| !ast_exists_extension(c, c->context, c->exten, 1,
+				S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 			/*!\note
 			 * If there is no match at priority 1, it is not a valid extension anymore.
 			 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
 			 * neither exist.
 			 */
-			if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
+			if (ast_exists_extension(c, c->context, "i", 1,
+				S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 				ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
 				pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
 				set_ext_pri(c, "i", 1);
-			} else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
+			} else if (ast_exists_extension(c, c->context, "e", 1,
+				S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 				pbx_builtin_raise_exception(c, "INVALID");
 			} else {
 				ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
@@ -4779,17 +4798,21 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 				break;
 			if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
 				timeout = 1;
-			if (!timeout && ast_exists_extension(c, c->context, dst_exten, 1, c->cid.cid_num)) /* Prepare the next cycle */
+			if (!timeout
+				&& ast_exists_extension(c, c->context, dst_exten, 1,
+					S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
 				set_ext_pri(c, dst_exten, 1);
-			else {
+			} else {
 				/* No such extension */
 				if (!timeout && !ast_strlen_zero(dst_exten)) {
 					/* An invalid extension */
-					if (ast_exists_extension(c, c->context, "i", 1, c->cid.cid_num)) {
+					if (ast_exists_extension(c, c->context, "i", 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 						ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
 						pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
 						set_ext_pri(c, "i", 1);
-					} else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
+					} else if (ast_exists_extension(c, c->context, "e", 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 						pbx_builtin_raise_exception(c, "INVALID");
 					} else {
 						ast_log(LOG_WARNING, "Invalid extension '%s', but no rule 'i' in context '%s'\n", dst_exten, c->context);
@@ -4798,10 +4821,12 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 					}
 				} else {
 					/* A simple timeout */
-					if (ast_exists_extension(c, c->context, "t", 1, c->cid.cid_num)) {
+					if (ast_exists_extension(c, c->context, "t", 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 						ast_verb(3, "Timeout on %s\n", c->name);
 						set_ext_pri(c, "t", 1);
-					} else if (ast_exists_extension(c, c->context, "e", 1, c->cid.cid_num)) {
+					} else if (ast_exists_extension(c, c->context, "e", 1,
+						S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 						pbx_builtin_raise_exception(c, "RESPONSETIMEOUT");
 					} else {
 						ast_log(LOG_WARNING, "Timeout, but no rule 't' in context '%s'\n", c->context);
@@ -4825,14 +4850,17 @@ static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
 		ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
 	}
 
-	if ((!args || !args->no_hangup_chan) &&
-			!ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN) &&
-			ast_exists_extension(c, c->context, "h", 1, c->cid.cid_num)) {
+	if ((!args || !args->no_hangup_chan)
+		&& !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
+		&& ast_exists_extension(c, c->context, "h", 1,
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
 		set_ext_pri(c, "h", 1);
 		if (c->cdr && ast_opt_end_cdr_before_h_exten) {
 			ast_cdr_end(c->cdr);
 		}
-		while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority, c->cid.cid_num, &found, 1)) == 0) {
+		while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
+			S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
+			&found, 1)) == 0) {
 			c->priority++;
 		}
 		if (found && res) {
@@ -9188,12 +9216,14 @@ static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
 
 	res = ast_waitfordigit(chan, ms);
 	if (!res) {
-		if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) {
+		if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			ast_verb(3, "Timeout on %s, continuing...\n", chan->name);
 		} else if (chan->_softhangup == AST_SOFTHANGUP_TIMEOUT) {
 			ast_verb(3, "Call timeout on %s, checking for 'T'\n", chan->name);
 			res = -1;
-		} else if (ast_exists_extension(chan, chan->context, "t", 1, chan->cid.cid_num)) {
+		} else if (ast_exists_extension(chan, chan->context, "t", 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 			ast_verb(3, "Timeout on %s, going to 't'\n", chan->name);
 			set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
 		} else {
@@ -9309,10 +9339,12 @@ static int pbx_builtin_background(struct ast_channel *chan, const char *data)
 	 * users can EXEC Background and reasonably expect that the DTMF code will
 	 * be returned (see #16434).
 	 */
-	if (!ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS) &&
-			(exten[0] = res) &&
-			ast_canmatch_extension(chan, args.context, exten, 1, chan->cid.cid_num) &&
-			!ast_matchmore_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
+	if (!ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS)
+		&& (exten[0] = res)
+		&& ast_canmatch_extension(chan, args.context, exten, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
+		&& !ast_matchmore_extension(chan, args.context, exten, 1,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
 		snprintf(chan->exten, sizeof(chan->exten), "%c", res);
 		ast_copy_string(chan->context, args.context, sizeof(chan->context));
 		chan->priority = 0;
@@ -10032,7 +10064,8 @@ static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, c
 		exten = chan->exten;
 
 	goto_func = (async) ? ast_async_goto : ast_explicit_goto;
-	if (ast_exists_extension(chan, context, exten, priority, chan->cid.cid_num))
+	if (ast_exists_extension(chan, context, exten, priority,
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
 		return goto_func(chan, context, exten, priority);
 	else {
 		return AST_PBX_GOTO_FAILED;
@@ -10081,8 +10114,10 @@ static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string,
 		pri++;
 	}
 	if (sscanf(pri, "%30d", &ipri) != 1) {
-		if ((ipri = ast_findlabel_extension(chan, context ? context : chan->context, exten ? exten : chan->exten,
-			pri, chan->cid.cid_num)) < 1) {
+		ipri = ast_findlabel_extension(chan, context ? context : chan->context,
+			exten ? exten : chan->exten, pri,
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
+		if (ipri < 1) {
 			ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
 			return -1;
 		} else
diff --git a/res/res_agi.c b/res/res_agi.c
index 4150fe1a918ff735112d3c01112786fd30a330c7..bd8ad4bfd36f599d3b8e0565080fa31b72b90226 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -1626,14 +1626,18 @@ static void setup_env(struct ast_channel *chan, char *request, int fd, int enhan
 	ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
 
 	/* ANI/DNIS */
-	ast_agi_send(fd, chan, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
-	ast_agi_send(fd, chan, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
-	ast_agi_send(fd, chan, "agi_callingpres: %d\n", chan->cid.cid_pres);
-	ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->cid.cid_ani2);
-	ast_agi_send(fd, chan, "agi_callington: %d\n", chan->cid.cid_ton);
-	ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->cid.cid_tns);
-	ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
-	ast_agi_send(fd, chan, "agi_rdnis: %s\n", S_OR(chan->redirecting.from.number, "unknown"));
+	ast_agi_send(fd, chan, "agi_callerid: %s\n",
+		S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "unknown"));
+	ast_agi_send(fd, chan, "agi_calleridname: %s\n",
+		S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "unknown"));
+	ast_agi_send(fd, chan, "agi_callingpres: %d\n",
+		ast_party_id_presentation(&chan->caller.id));
+	ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->caller.ani2);
+	ast_agi_send(fd, chan, "agi_callington: %d\n", chan->caller.id.number.plan);
+	ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->dialed.transit_network_select);
+	ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->dialed.number.str, "unknown"));
+	ast_agi_send(fd, chan, "agi_rdnis: %s\n",
+		S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, "unknown"));
 
 	/* Context information */
 	ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
@@ -2116,7 +2120,9 @@ static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, cons
 		return RESULT_SHOWUSAGE;
 
 	if (sscanf(argv[2], "%30d", &pri) != 1) {
-		if ((pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2], chan->cid.cid_num)) < 1)
+		pri = ast_findlabel_extension(chan, chan->context, chan->exten, argv[2],
+			S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
+		if (pri < 1)
 			return RESULT_SHOWUSAGE;
 	}
 
diff --git a/res/snmp/agent.c b/res/snmp/agent.c
index b902affcc25b0fbd71ce237605121f83bfae0436..439bd17e7280cf17129b38d42794290bcd9fa222 100644
--- a/res/snmp/agent.c
+++ b/res/snmp/agent.c
@@ -419,59 +419,59 @@ static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *le
 		ret = (u_char *)&long_ret;
 		break;
 	case ASTCHANCIDDNID:
-		if (chan->cid.cid_dnid) {
-			strncpy(string_ret, chan->cid.cid_dnid, sizeof(string_ret));
+		if (chan->dialed.number.str) {
+			strncpy(string_ret, chan->dialed.number.str, sizeof(string_ret));
 			string_ret[sizeof(string_ret) - 1] = '\0';
 			*var_len = strlen(string_ret);
 			ret = (u_char *)string_ret;
 		}
 		break;
 	case ASTCHANCIDNUM:
-		if (chan->cid.cid_num) {
-			strncpy(string_ret, chan->cid.cid_num, sizeof(string_ret));
+		if (chan->caller.id.number.valid && chan->caller.id.number.str) {
+			strncpy(string_ret, chan->caller.id.number.str, sizeof(string_ret));
 			string_ret[sizeof(string_ret) - 1] = '\0';
 			*var_len = strlen(string_ret);
 			ret = (u_char *)string_ret;
 		}
 		break;
 	case ASTCHANCIDNAME:
-		if (chan->cid.cid_name) {
-			strncpy(string_ret, chan->cid.cid_name, sizeof(string_ret));
+		if (chan->caller.id.name.valid && chan->caller.id.name.str) {
+			strncpy(string_ret, chan->caller.id.name.str, sizeof(string_ret));
 			string_ret[sizeof(string_ret) - 1] = '\0';
 			*var_len = strlen(string_ret);
 			ret = (u_char *)string_ret;
 		}
 		break;
 	case ASTCHANCIDANI:
-		if (chan->cid.cid_ani) {
-			strncpy(string_ret, chan->cid.cid_ani, sizeof(string_ret));
+		if (chan->caller.ani) {
+			strncpy(string_ret, chan->caller.ani, sizeof(string_ret));
 			string_ret[sizeof(string_ret) - 1] = '\0';
 			*var_len = strlen(string_ret);
 			ret = (u_char *)string_ret;
 		}
 		break;
 	case ASTCHANCIDRDNIS:
-		if (chan->redirecting.from.number) {
-			strncpy(string_ret, chan->redirecting.from.number, sizeof(string_ret));
+		if (chan->redirecting.from.number.valid && chan->redirecting.from.number.str) {
+			strncpy(string_ret, chan->redirecting.from.number.str, sizeof(string_ret));
 			string_ret[sizeof(string_ret) - 1] = '\0';
 			*var_len = strlen(string_ret);
 			ret = (u_char *)string_ret;
 		}
 		break;
 	case ASTCHANCIDPRES:
-		long_ret = chan->cid.cid_pres;
+		long_ret = ast_party_id_presentation(chan->caller.id);
 		ret = (u_char *)&long_ret;
 		break;
 	case ASTCHANCIDANI2:
-		long_ret = chan->cid.cid_ani2;
+		long_ret = chan->caller.ani2;
 		ret = (u_char *)&long_ret;
 		break;
 	case ASTCHANCIDTON:
-		long_ret = chan->cid.cid_ton;
+		long_ret = chan->caller.id.number.plan;
 		ret = (u_char *)&long_ret;
 		break;
 	case ASTCHANCIDTNS:
-		long_ret = chan->cid.cid_tns;
+		long_ret = chan->dialed.transit_network_select;
 		ret = (u_char *)&long_ret;
 		break;
 	case ASTCHANAMAFLAGS:
diff --git a/tests/test_substitution.c b/tests/test_substitution.c
index 412b6f4bbabbaf2dd4fb1b4687449edef8e4c5a8..aa7d14f914e046cc47ea5cb1474e3c7005f7fa70 100644
--- a/tests/test_substitution.c
+++ b/tests/test_substitution.c
@@ -220,10 +220,17 @@ AST_TEST_DEFINE(test_substitution)
 	c = ast_channel_alloc(0, 0, "", "", "", "", "", "", 0, "Test/substitution");
 
 #define TEST(t) if (t == AST_TEST_FAIL) { res = AST_TEST_FAIL; }
-	TEST(test_chan_integer(test, c, &c->cid.cid_pres, "${CALLINGPRES}"));
-	TEST(test_chan_integer(test, c, &c->cid.cid_ani2, "${CALLINGANI2}"));
-	TEST(test_chan_integer(test, c, &c->cid.cid_ton, "${CALLINGTON}"));
-	TEST(test_chan_integer(test, c, &c->cid.cid_tns, "${CALLINGTNS}"));
+#if 0
+	/*
+	 * We can no longer test the CALLINGPRES value this way because it is now
+	 * a calculated value from the name and number presentation information to
+	 * get a combined presentation value.
+	 */
+	TEST(test_chan_integer(test, c, &c->caller.id.number.presentation, "${CALLINGPRES}"));
+#endif
+	TEST(test_chan_integer(test, c, &c->caller.ani2, "${CALLINGANI2}"));
+	TEST(test_chan_integer(test, c, &c->caller.id.number.plan, "${CALLINGTON}"));
+	TEST(test_chan_integer(test, c, &c->dialed.transit_network_select, "${CALLINGTNS}"));
 	TEST(test_chan_integer(test, c, &c->hangupcause, "${HANGUPCAUSE}"));
 	TEST(test_chan_integer(test, c, &c->priority, "${PRIORITY}"));
 	TEST(test_chan_string(test, c, c->context, sizeof(c->context), "${CONTEXT}"));