diff --git a/UPGRADE.txt b/UPGRADE.txt
index 61d4ec148c85d874d92ef68ddf644e304c438c31..79c1b958a9540479873d15ec56b468515f3c2b4c 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -18,7 +18,7 @@
 ===
 ===========================================================
 
-From 1.6.2 to 1.6.3:
+From 1.6.2 to 1.8:
 
 * Asterisk-addons no longer exists as an independent package.  Those modules
   now live in the addons directory of the main Asterisk source tree.  They
@@ -53,7 +53,7 @@ From 1.6.2 to 1.6.3:
   the channel name to infer what B channel a call is using and to avoid name
   collisions, the channel name format is changed.
   The new channel naming for PRI channels is:
-  DAHDI/ISDN-<span>-<sequence-number>
+  DAHDI/i<span>/<number>[:<subaddress>]-<sequence-number>
 
 From 1.6.1 to 1.6.2:
 
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 583408e43353a73dbcc08e84ee4c717e7bd3900a..b81c7a8ef51aab08123d0d443d4d600cc5ac2189 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -1039,6 +1039,8 @@ struct dahdi_pvt {
 	int cid_ton;
 	/*! \brief Caller ID name from an incoming call. */
 	char cid_name[AST_MAX_EXTENSION];
+	/*! \brief Caller ID subaddress from an incoming call. */
+	char cid_subaddr[AST_MAX_EXTENSION];
 	char *origcid_num;				/*!< malloced original callerid */
 	char *origcid_name;				/*!< malloced original callerid */
 	/*! \brief Call waiting number. */
@@ -2719,6 +2721,12 @@ static void my_pri_set_callerid(void *pvt, const struct ast_party_caller *caller
 
 	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));
+	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;
 	ast_copy_string(p->cid_ani, S_OR(caller->ani, ""), sizeof(p->cid_ani));
@@ -3073,6 +3081,7 @@ static void dahdi_r2_on_call_init(openr2_chan_t *r2chan)
 	/* better safe than sorry ... */
 	p->cid_name[0] = '\0';
 	p->cid_num[0] = '\0';
+	p->cid_subaddr[0] = '\0';
 	p->rdnis[0] = '\0';
 	p->exten[0] = '\0';
 	p->mfcr2_ani_index = '\0';
@@ -5430,6 +5439,7 @@ static int dahdi_hangup(struct ast_channel *ast)
 	} else {
 		p->cid_num[0] = '\0';
 		p->cid_name[0] = '\0';
+		p->cid_subaddr[0] = '\0';
 	}
 
 	ast_mutex_lock(&p->lock);
@@ -8528,7 +8538,22 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
 #if defined(HAVE_PRI)
 	} else if (i->pri) {
 		ast_mutex_lock(&i->pri->lock);
-		ast_str_set(&chan_name, 0, "ISDN-%d-%d", i->pri->span, ++i->pri->new_chan_seq);
+		y = ++i->pri->new_chan_seq;
+		if (i->outgoing) {
+			/*
+			 * The dnid has been stuffed with the called-number[:subaddress]
+			 * by dahdi_request().
+			 */
+			ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->dnid, y);
+			i->dnid[0] = '\0';
+		} else if (ast_strlen_zero(i->cid_subaddr)) {
+			/* Put in caller-id number only since there is no subaddress. */
+			ast_str_set(&chan_name, 0, "i%d/%s-%x", i->pri->span, i->cid_num, y);
+		} else {
+			/* Put in caller-id number and subaddress. */
+			ast_str_set(&chan_name, 0, "i%d/%s:%s-%x", i->pri->span, i->cid_num,
+				i->cid_subaddr, y);
+		}
 		ast_mutex_unlock(&i->pri->lock);
 #endif	/* defined(HAVE_PRI) */
 	} else {
@@ -11559,6 +11584,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
 			tmp->cid_num[0] = '\0';
 			tmp->cid_name[0] = '\0';
 		}
+		tmp->cid_subaddr[0] = '\0';
 		ast_copy_string(tmp->mailbox, conf->chan.mailbox, sizeof(tmp->mailbox));
 		if (channel != CHAN_PSEUDO && !ast_strlen_zero(tmp->mailbox)) {
 			char *mailbox, *context;
@@ -12098,6 +12124,8 @@ static struct ast_channel *dahdi_request(const char *type, int format, const str
 				tmp = analog_request(p->sig_pvt, &callwait, requestor);
 #ifdef HAVE_PRI
 			} else if (dahdi_sig_pri_lib_handles(p->sig)) {
+				sig_pri_extract_called_num_subaddr(p->sig_pvt, data, p->dnid,
+					sizeof(p->dnid));
 				tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW, requestor);
 #endif
 			} else {
@@ -14319,6 +14347,11 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
 			ast_cli(a->fd, "Context: %s\n", tmp->context);
 			ast_cli(a->fd, "Caller ID: %s\n", tmp->cid_num);
 			ast_cli(a->fd, "Calling TON: %d\n", tmp->cid_ton);
+#if defined(HAVE_PRI)
+#if defined(HAVE_PRI_SUBADDR)
+			ast_cli(a->fd, "Caller ID subaddress: %s\n", tmp->cid_subaddr);
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+#endif	/* defined(HAVE_PRI) */
 			ast_cli(a->fd, "Caller ID name: %s\n", tmp->cid_name);
 			ast_cli(a->fd, "Mailbox: %s\n", S_OR(tmp->mailbox, "none"));
 			if (tmp->vars) {
diff --git a/channels/sig_pri.c b/channels/sig_pri.c
index f369fa38105de46e51677c1ab659b9597bab9213..dbbeccf78f20cfdd0da98496ee344757995db83c 100644
--- a/channels/sig_pri.c
+++ b/channels/sig_pri.c
@@ -129,6 +129,12 @@ static void sig_pri_set_caller_id(struct sig_pri_chan *p)
 		ast_party_caller_init(&caller);
 		caller.id.number = p->cid_num;
 		caller.id.name = p->cid_name;
+		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;
@@ -1520,10 +1526,16 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
 				}
 				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_connected.id.subaddress);
+					if (ast_connected.id.subaddress.str) {
+						ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
+							ast_connected.id.subaddress.str,
+							sizeof(pri->pvts[chanpos]->cid_subaddr));
+					}
 				}
 #endif	/* defined(HAVE_PRI_SUBADDR) */
 				if (caller_id_update) {
@@ -2335,6 +2347,22 @@ static void *pri_dchannel(void *vpri)
 							pri->pvts[chanpos]->cid_ani[0] = '\0';
 						}
 #endif
+						pri->pvts[chanpos]->cid_subaddr[0] = '\0';
+#if defined(HAVE_PRI_SUBADDR)
+						if (e->ring.calling.subaddress.valid) {
+							struct ast_party_subaddress calling_subaddress;
+
+							ast_party_subaddress_init(&calling_subaddress);
+							sig_pri_set_subaddress(&calling_subaddress,
+								&e->ring.calling.subaddress);
+							if (calling_subaddress.str) {
+								ast_copy_string(pri->pvts[chanpos]->cid_subaddr,
+									calling_subaddress.str,
+									sizeof(pri->pvts[chanpos]->cid_subaddr));
+							}
+							ast_party_subaddress_free(&calling_subaddress);
+						}
+#endif /* defined(HAVE_PRI_SUBADDR) */
 						ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
 						pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
 						pri->pvts[chanpos]->callingpres = e->ring.callingpres;
@@ -2343,6 +2371,7 @@ static void *pri_dchannel(void *vpri)
 						}
 					} else {
 						pri->pvts[chanpos]->cid_num[0] = '\0';
+						pri->pvts[chanpos]->cid_subaddr[0] = '\0';
 						pri->pvts[chanpos]->cid_ani[0] = '\0';
 						pri->pvts[chanpos]->cid_name[0] = '\0';
 						pri->pvts[chanpos]->cid_ton = 0;
@@ -3170,6 +3199,7 @@ int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast)
 	p->alerting = 0;
 	p->setup_ack = 0;
 	p->cid_num[0] = '\0';
+	p->cid_subaddr[0] = '\0';
 	p->cid_name[0] = '\0';
 	p->exten[0] = '\0';
 	sig_pri_set_dialing(p, 0);
@@ -3219,6 +3249,95 @@ exit:
 	return res;
 }
 
+/*!
+ * \brief Extract the called number and subaddress from the dial string.
+ * \since 1.6.3
+ *
+ * \param p sig_pri channel structure.
+ * \param rdest Dial string buffer to extract called number and subaddress.
+ * \param called Buffer to fill with extracted <number>[:<subaddress>]
+ * \param called_buff_size Size of buffer to fill.
+ *
+ * \note Parsing must remain in sync with sig_pri_call().
+ *
+ * \return Nothing
+ */
+void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size)
+{
+	char *dial;
+	char *number;
+	char *subaddr;
+
+	/* Get private copy of dial string. */
+	dial = ast_strdupa(rdest);
+
+	/* Skip channel selection section. */
+	number = strchr(dial, '/');
+	if (number) {
+		++number;
+	} else {
+		number = "";
+	}
+
+#if defined(HAVE_PRI_SETUP_KEYPAD)
+	/*
+	 *  v--- number points here
+	 * /[K<keypad-digits>/]extension
+	 */
+	if (number[0] == 'K') {
+		/* Skip the keypad facility digits. */
+		number = strchr(number + 1, '/');
+		if (number) {
+			++number;
+		} else {
+			number = "";
+		}
+	}
+	/*
+	 *  v--- number points here
+	 * /extension
+	 */
+#endif	/* defined(HAVE_PRI_SETUP_KEYPAD) */
+
+	/* Find and extract dialed_subaddress */
+	subaddr = strchr(number, ':');
+	if (subaddr) {
+		*subaddr++ = '\0';
+
+		/* Skip subaddress type prefix. */
+		switch (*subaddr) {
+		case 'U':
+		case 'u':
+		case 'N':
+		case 'n':
+			++subaddr;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* Skip type-of-number/dial-plan prefix characters. */
+	if (strlen(number) < p->stripmsd) {
+		number = "";
+	} else {
+		number += p->stripmsd;
+		while (isalpha(*number)) {
+			++number;
+		}
+	}
+
+	/* Fill buffer with extracted number and subaddress. */
+	if (ast_strlen_zero(subaddr)) {
+		/* Put in called number only since there is no subaddress. */
+		snprintf(called, called_buff_size, "%s", number);
+	} else {
+		/* Put in called number and subaddress. */
+		snprintf(called, called_buff_size, "%s:%s", number, subaddr);
+	}
+}
+
+/*! \note Parsing must remain in sync with sig_pri_extract_called_num_subaddr(). */
 int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1)
 {
 	char dest[256]; /* must be same length as p->dialdest */
diff --git a/channels/sig_pri.h b/channels/sig_pri.h
index d04ffeb95fe42954c86f0706bb7bf635f1e81aeb..fa2767500ff0b130f7aad5c32609b275bb0b17d9 100644
--- a/channels/sig_pri.h
+++ b/channels/sig_pri.h
@@ -138,6 +138,7 @@ struct sig_pri_chan {
 	int cid_ton;					/*!< Type Of Number (TON) */
 	int callingpres;				/*!< The value of calling presentation that we're going to use when placing a PRI call */
 	char cid_num[AST_MAX_EXTENSION];
+	char cid_subaddr[AST_MAX_EXTENSION];
 	char cid_name[AST_MAX_EXTENSION];
 	char cid_ani[AST_MAX_EXTENSION];
 	char exten[AST_MAX_EXTENSION];
@@ -246,6 +247,7 @@ struct sig_pri_pri {
 	struct sig_pri_callback *calls;
 };
 
+void sig_pri_extract_called_num_subaddr(struct sig_pri_chan *p, const char *rdest, char *called, size_t called_buff_size);
 int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, int timeout, int layer1);
 
 int sig_pri_hangup(struct sig_pri_chan *p, struct ast_channel *ast);