[asterisk-commits] rmudgett: trunk r225357 - in /trunk: ./ channels/ funcs/ include/asterisk/ main/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Oct 22 11:33:27 CDT 2009


Author: rmudgett
Date: Thu Oct 22 11:33:22 2009
New Revision: 225357

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=225357
Log:
Add support for calling and called subaddress.  Partial support for COLP subaddress.

The Telecom Specs in NZ suggests that SUB ADDRESS is always on, so doing
"desk to desk" between offices each with an asterisk box over the ISDN
should then be possible, without a whole load of DDI numbers required.

(closes issue #15604)
Reported by: alecdavis
Patches:
      asterisk_subaddr_trunk.diff11.txt uploaded by alecdavis (license 585)
      Some minor modificatons were made.
Tested by: alecdavis, rmudgett

Review: https://reviewboard.asterisk.org/r/405/

Modified:
    trunk/CHANGES
    trunk/channels/sig_pri.c
    trunk/configure
    trunk/configure.ac
    trunk/funcs/func_callerid.c
    trunk/funcs/func_connectedline.c
    trunk/include/asterisk/autoconfig.h.in
    trunk/include/asterisk/channel.h
    trunk/main/channel.c

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Thu Oct 22 11:33:22 2009
@@ -88,6 +88,8 @@
 ------------------
  * Added new dialplan functions CONNECTEDLINE and REDIRECTING which permits
    setting various connected line and redirecting party information.
+ * CALLERID and CONNECTEDLINE dialplan functions have been extended to
+   support ISDN subaddressing.
  * The CHANNEL() function now supports the "name" option.
  * For DAHDI channels, the CHANNEL() dialplan function now
    supports changing the channel's buffer policy (for the current
@@ -216,6 +218,8 @@
    Number (MSN) list for PTMP CPE interfaces.
  * Added dynamic range compression support for dahdi channels.  It is
    configured via the rxdrc and txdrc parameters in chan_dahdi.conf.
+ * Added support for ISDN calling and called subaddress with partial support
+   for connected line subaddress.
 
 Asterisk Manager Interface
 --------------------------

Modified: trunk/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sig_pri.c?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/channels/sig_pri.c (original)
+++ trunk/channels/sig_pri.c Thu Oct 22 11:33:22 2009
@@ -437,6 +437,168 @@
 	return pri_to_ast_presentation(number_value | number_screening);
 }
 
+#if defined(HAVE_PRI_SUBADDR)
+/*!
+ * \internal
+ * \brief Fill in the asterisk party subaddress from the given PRI party subaddress.
+ * \since 1.6.3
+ *
+ * \param ast_subaddress Asterisk party subaddress structure.
+ * \param pri_subaddress PRI party subaddress structure.
+ *
+ * \return Nothing
+ *
+ */
+static void sig_pri_set_subaddress(struct ast_party_subaddress *ast_subaddress, const struct pri_party_subaddress *pri_subaddress)
+{
+	char *cnum, *ptr;
+	int x, len;
+
+	if (ast_subaddress->str) {
+		ast_free(ast_subaddress->str);
+	}
+	if (pri_subaddress->length <= 0) {
+		ast_party_subaddress_init(ast_subaddress);
+		return;
+	}
+
+	if (!pri_subaddress->type) {
+		/* NSAP */
+		ast_subaddress->str = ast_strdup((char *) pri_subaddress->data);
+	} else {
+		/* User Specified */
+		if (!(cnum = ast_malloc(2 * pri_subaddress->length + 1))) {
+			ast_party_subaddress_init(ast_subaddress);
+			return;
+		}
+
+		ptr = cnum;
+		len = pri_subaddress->length - 1; /* -1 account for zero based indexing */
+		for (x = 0; x < len; ++x) {
+			ptr += sprintf(ptr, "%02x", pri_subaddress->data[x]);
+		}
+
+		if (pri_subaddress->odd_even_indicator) {
+			/* ODD */
+			sprintf(ptr, "%01x", (pri_subaddress->data[len]) >> 4);
+		} else {
+			/* EVEN */
+			sprintf(ptr, "%02x", pri_subaddress->data[len]);
+		}
+		ast_subaddress->str = cnum;
+	}
+	ast_subaddress->type = pri_subaddress->type;
+	ast_subaddress->odd_even_indicator = pri_subaddress->odd_even_indicator;
+	ast_subaddress->valid = 1;
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
+#if defined(HAVE_PRI_SUBADDR)
+static unsigned char ast_pri_pack_hex_char(char c)
+{
+	unsigned char res;
+
+	if (c < '0') {
+		res = 0;
+	} else if (c < ('9' + 1)) {
+		res = c - '0';
+	} else if (c < 'A') {
+		res = 0;
+	} else if (c < ('F' + 1)) {
+		res = c - 'A' + 10;
+	} else if (c < 'a') {
+		res = 0;
+	} else if (c < ('f' + 1)) {
+		res = c - 'a' + 10;
+	} else {
+		res = 0;
+	}
+	return res;
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
+#if defined(HAVE_PRI_SUBADDR)
+/*!
+ * \internal
+ * \brief Convert a null terminated hexadecimal string to a packed hex byte array.
+ * \details left justified, with 0 padding if odd length.
+ * \since 1.6.3
+ *
+ * \param dst pointer to packed byte array.
+ * \param src pointer to null terminated hexadecimal string.
+ * \param maxlen destination array size.
+ *
+ * \return Length of byte array
+ *
+ * \note The dst is not an ASCIIz string.
+ * \note The src is an ASCIIz hex string.
+ */
+static int ast_pri_pack_hex_string(unsigned char *dst, char *src, int maxlen)
+{
+	int res = 0;
+	int len = strlen(src);
+
+	if (len > (2 * maxlen)) {
+		len = 2 * maxlen;
+	}
+
+	res = len / 2 + len % 2;
+
+	while (len > 1) {
+		*dst = ast_pri_pack_hex_char(*src) << 4;
+		src++;
+		*dst |= ast_pri_pack_hex_char(*src);
+		dst++, src++;
+		len -= 2;
+	}
+	if (len) { /* 1 left */
+		*dst = ast_pri_pack_hex_char(*src) << 4;
+	}
+	return res;
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
+#if defined(HAVE_PRI_SUBADDR)
+/*!
+ * \internal
+ * \brief Fill in the PRI party subaddress from the given asterisk party subaddress.
+ * \since 1.6.3
+ *
+ * \param pri_subaddress PRI party subaddress structure.
+ * \param ast_subaddress Asterisk party subaddress structure.
+ *
+ * \return Nothing
+ *
+ * \note Assumes that pri_subaddress has been previously memset to zero.
+ */
+static void sig_pri_party_subaddress_from_ast(struct pri_party_subaddress *pri_subaddress, const struct ast_party_subaddress *ast_subaddress)
+{
+	if (ast_subaddress->valid && !ast_strlen_zero(ast_subaddress->str)) {
+		pri_subaddress->type = ast_subaddress->type;
+		if (!ast_subaddress->type) {
+			/* 0 = NSAP */
+			ast_copy_string((char *) pri_subaddress->data, ast_subaddress->str,
+				sizeof(pri_subaddress->data));
+			pri_subaddress->length = strlen((char *) pri_subaddress->data);
+			pri_subaddress->odd_even_indicator = 0;
+			pri_subaddress->valid = 1;
+		} else {
+			/* 2 = User Specified */
+			/*
+			 * Copy HexString to packed HexData,
+			 * if odd length then right pad trailing byte with 0
+			 */
+			int length = ast_pri_pack_hex_string(pri_subaddress->data,
+				ast_subaddress->str, sizeof(pri_subaddress->data));
+
+			pri_subaddress->length = length;
+			pri_subaddress->odd_even_indicator = (length & 1);
+			pri_subaddress->valid = 1;
+		}
+	}
+}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
 /*!
  * \internal
  * \brief Fill in the PRI party id from the given asterisk party id.
@@ -466,6 +628,9 @@
 		pri_id->number.plan = ast_id->number_type;
 		ast_copy_string(pri_id->number.str, ast_id->number, sizeof(pri_id->number.str));
 	}
+#if defined(HAVE_PRI_SUBADDR)
+	sig_pri_party_subaddress_from_ast(&pri_id->subaddress, &ast_id->subaddress);
+#endif	/* defined(HAVE_PRI_SUBADDR) */
 }
 
 /*!
@@ -1035,6 +1200,11 @@
 	if (pri_id->name.valid || pri_id->number.valid) {
 		ast_id->number_presentation = overall_ast_presentation(pri_id);
 	}
+#if defined(HAVE_PRI_SUBADDR)
+	if (pri_id->subaddress.valid) {
+		sig_pri_set_subaddress(&ast_id->subaddress, &pri_id->subaddress);
+	}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
 }
 
 /*!
@@ -1189,6 +1359,12 @@
 				}
 				ast_connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
 
+#if defined(HAVE_PRI_SUBADDR)
+				if (ast_connected.id.subaddress.valid) {
+					ast_party_subaddress_set(&owner->cid.subaddress,
+						&ast_connected.id.subaddress);
+				}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
 				if (caller_id_update) {
 					pri->pvts[chanpos]->callingpres =
 						ast_connected.id.number_presentation;
@@ -1796,9 +1972,42 @@
 								e->ring.ctype, pri->pvts[chanpos]->exten, NULL);
 							ast_mutex_lock(&pri->lock);
 							if (c) {
+#if defined(HAVE_PRI_SUBADDR)
+								if (e->ring.calling.subaddress.valid) {
+									/* Set Calling Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.subaddress,
+										&e->ring.calling.subaddress);
+									if (!e->ring.calling.subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.calling.subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
+											(char *) e->ring.calling.subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+								if (e->ring.called_subaddress.valid) {
+									/* Set Called Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.dialed_subaddress,
+										&e->ring.called_subaddress);
+									if (!e->ring.called_subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.called_subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
+											(char *) e->ring.called_subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+#else
 								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
 									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
 								}
+#endif /* !defined(HAVE_PRI_SUBADDR) */
 								if (e->ring.ani2 >= 0) {
 									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
 									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
@@ -1858,9 +2067,42 @@
 								 * will do anything with the channel we have just
 								 * created.
 								 */
+#if defined(HAVE_PRI_SUBADDR)
+								if (e->ring.calling.subaddress.valid) {
+									/* Set Calling Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.subaddress,
+										&e->ring.calling.subaddress);
+									if (!e->ring.calling.subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.calling.subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLINGSUBADDR",
+											(char *) e->ring.calling.subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+								if (e->ring.called_subaddress.valid) {
+									/* Set Called Subaddress */
+									sig_pri_lock_owner(pri, chanpos);
+									sig_pri_set_subaddress(
+										&pri->pvts[chanpos]->owner->cid.dialed_subaddress,
+										&e->ring.called_subaddress);
+									if (!e->ring.called_subaddress.type
+										&& !ast_strlen_zero(
+											(char *) e->ring.called_subaddress.data)) {
+										/* NSAP */
+										pbx_builtin_setvar_helper(c, "CALLEDSUBADDR",
+											(char *) e->ring.called_subaddress.data);
+									}
+									ast_channel_unlock(c);
+								}
+#else
 								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
 									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
 								}
+#endif /* !defined(HAVE_PRI_SUBADDR) */
 								if (e->ring.ani2 >= 0) {
 									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
 									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
@@ -2474,6 +2716,7 @@
 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 */
+	struct ast_party_subaddress dialed_subaddress; /* Called subaddress */
 	struct pri_sr *sr;
 	char *c, *l, *n, *s = NULL;
 #ifdef SUPPORT_USERUSER
@@ -2492,7 +2735,6 @@
 		return -1;
 	}
 
-
 	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
 		ast_log(LOG_WARNING, "sig_pri_call called on %s, neither down nor reserved\n", ast->name);
 		return -1;
@@ -2502,6 +2744,34 @@
 
 	p->dialdest[0] = '\0';
 	p->outgoing = 1;
+
+	/* setup dialed_subaddress if found */
+	ast_party_subaddress_init(&dialed_subaddress);
+	c = strrchr(dest, ':');
+	if (c) {
+		*c = '\0';
+		c++;
+		/* prefix */
+		/* 'n' = NSAP */
+		/* 'U' = odd, 'u'= even */
+		/* Default = NSAP */
+		switch (*c) {
+		case 'U':
+			dialed_subaddress.odd_even_indicator = 1;
+			/* fall through */
+		case 'u':
+			c++;
+			dialed_subaddress.type = 2;
+			break;
+		case 'N':
+		case 'n':
+			c++;
+			/* default already covered with ast_party_subaddress_init */
+			break;
+		}
+		dialed_subaddress.str = c;
+		dialed_subaddress.valid = 1;
+	}
 
 	c = strchr(dest, '/');
 	if (c) {
@@ -2634,6 +2904,16 @@
 	}
 	pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
 
+#if defined(HAVE_PRI_SUBADDR)
+	if (dialed_subaddress.valid) {
+		struct pri_party_subaddress subaddress;
+
+		memset(&subaddress, 0, sizeof(subaddress));
+		sig_pri_party_subaddress_from_ast(&subaddress, &dialed_subaddress);
+		pri_sr_set_called_subaddress(sr, &subaddress);
+	}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
 	ldp_strip = 0;
 	prilocaldialplan = p->pri->localdialplan - 1;
 	if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
@@ -2709,6 +2989,17 @@
 	}
 	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));
+
+#if defined(HAVE_PRI_SUBADDR)
+	if (ast->connected.id.subaddress.valid) {
+		struct pri_party_subaddress subaddress;
+
+		memset(&subaddress, 0, sizeof(subaddress));
+		sig_pri_party_subaddress_from_ast(&subaddress, &ast->connected.id.subaddress);
+		pri_sr_set_caller_subaddress(sr, &subaddress);
+	}
+#endif	/* defined(HAVE_PRI_SUBADDR) */
+
 	sig_pri_redirecting_update(p, ast);
 
 #ifdef SUPPORT_USERUSER

Modified: trunk/configure.ac
URL: http://svnview.digium.com/svn/asterisk/trunk/configure.ac?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Thu Oct 22 11:33:22 2009
@@ -288,11 +288,16 @@
 AST_EXT_LIB_SETUP([POPT], [popt], [popt])
 AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio])
 AST_EXT_LIB_SETUP([PRI], [ISDN PRI], [pri])
+AST_EXT_LIB_SETUP_DEPENDENT([PRI_SUBADDR], [ISDN PRI subaddressing], [PRI], [pri])
+# ------------------------------------v
+# TODO: The code can be changed to always include these features now.
+# These features will always be present if pri_connected_line_update is available.
 AST_EXT_LIB_SETUP_DEPENDENT([PRI_VERSION], [ISDN PRI get_version], [PRI], [pri])
 AST_EXT_LIB_SETUP_DEPENDENT([PRI_INBANDDISCONNECT], [ISDN PRI set_inbanddisconnect], [PRI], [pri])
 AST_EXT_LIB_SETUP_DEPENDENT([PRI_PROG_W_CAUSE], [ISDN progress with cause], [PRI], [pri])
 AST_EXT_LIB_SETUP_DEPENDENT([PRI_SERVICE_MESSAGES], [ISDN service messages], [PRI], [pri])
 AST_EXT_LIB_SETUP_DEPENDENT([PRI_REVERSE_CHARGE], [ISDN reverse charge], [PRI], [pri])
+# ------------------------------------^
 AST_EXT_LIB_SETUP([RESAMPLE], [LIBRESAMPLE], [resample])
 AST_EXT_LIB_SETUP([SPANDSP], [SPANDSP], [spandsp])
 AST_EXT_LIB_SETUP([SS7], [ISDN SS7], [ss7])
@@ -1437,6 +1442,7 @@
 AST_EXT_LIB_CHECK([PORTAUDIO], [portaudio], [Pa_GetDeviceCount], [portaudio.h])
 
 AST_EXT_LIB_CHECK([PRI], [pri], [pri_connected_line_update], [libpri.h])
+AST_EXT_LIB_CHECK([PRI_SUBADDR], [pri], [pri_sr_set_called_subaddress], [libpri.h])
 
 # ------------------------------------v
 # TODO: The code can be changed to always include these features now.

Modified: trunk/funcs/func_callerid.c
URL: http://svnview.digium.com/svn/asterisk/trunk/funcs/func_callerid.c?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/funcs/func_callerid.c (original)
+++ trunk/funcs/func_callerid.c Thu Oct 22 11:33:22 2009
@@ -49,6 +49,12 @@
 					<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>
 				</enumlist>
 			</parameter>
 			<parameter name="CID">
@@ -167,8 +173,40 @@
 				ast_copy_string(buf, chan->cid.cid_ani, len);
 			}
 		} else if (!strncasecmp("dnid", data, 4)) {
-			if (chan->cid.cid_dnid) {
-				ast_copy_string(buf, chan->cid.cid_dnid, len);
+			/* 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);
+					}
+				}
+			} else {							/* dnid */
+				if (chan->cid.cid_dnid) {
+					ast_copy_string(buf, chan->cid.cid_dnid, len);
+				}
+			}
+		} 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 (!strncasecmp("rdnis", data, 5)) {
 			if (chan->cid.cid_rdnis) {
@@ -227,10 +265,46 @@
 		}
 	} else if (!strncasecmp("dnid", data, 4)) {
 		ast_channel_lock(chan);
-		if (chan->cid.cid_dnid) {
-			ast_free(chan->cid.cid_dnid);
-		}
-		chan->cid.cid_dnid = ast_strdup(value);
+		/* 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);
+			}
+			chan->cid.cid_dnid = ast_strdup(value);
+		}
+
+		if (chan->cdr) {
+			ast_cdr_setcid(chan->cdr, chan);
+		}
+		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);
+		}
 		if (chan->cdr) {
 			ast_cdr_setcid(chan->cdr, chan);
 		}

Modified: trunk/funcs/func_connectedline.c
URL: http://svnview.digium.com/svn/asterisk/trunk/funcs/func_connectedline.c?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/funcs/func_connectedline.c (original)
+++ trunk/funcs/func_connectedline.c Thu Oct 22 11:33:22 2009
@@ -43,7 +43,7 @@
 
 /*
  * Do not document the CONNECTEDLINE(source) datatype.
- * It has turned out to not be needed.  The source value is really                                      .
+ * It has turned out to not be needed.  The source value is really
  * only useful as a possible tracing aid.
  */
 /*** DOCUMENTATION
@@ -60,6 +60,9 @@
 					<enum name = "name" />
 					<enum name = "ton" />
 					<enum name = "pres" />
+					<enum name = "subaddr[-valid]|[-type]|[-odd]">
+						<para>ISDN Connected line subaddress</para>
+					</enum>
 				</enumlist>
 			</parameter>
 			<parameter name="i">
@@ -102,6 +105,19 @@
 		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);
 	}
@@ -209,6 +225,19 @@
 			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);
 	}

Modified: trunk/include/asterisk/autoconfig.h.in
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/autoconfig.h.in?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/include/asterisk/autoconfig.h.in (original)
+++ trunk/include/asterisk/autoconfig.h.in Thu Oct 22 11:33:22 2009
@@ -668,6 +668,9 @@
 /* Define to 1 if you have the ISDN service messages library. */
 #undef HAVE_PRI_SERVICE_MESSAGES
 
+/* Define to 1 if you have the ISDN PRI subaddressing library. */
+#undef HAVE_PRI_SUBADDR
+
 /* Define to 1 if you have the ISDN PRI get_version library. */
 #undef HAVE_PRI_VERSION
 
@@ -1253,9 +1256,6 @@
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* Define to 1 if the C compiler supports function prototypes. */
-#undef PROTOTYPES
-
 /* Define to necessary symbol if this constant uses a non-standard name on
    your system. */
 #undef PTHREAD_CREATE_JOINABLE
@@ -1271,11 +1271,6 @@
 
 /* Define to the type of arg 5 for `select'. */
 #undef SELECT_TYPE_ARG5
-
-/* Define to 1 if the `setvbuf' function takes the buffering type as its
-   second argument and the buffer pointer as the third, as on System V before
-   release 3. */
-#undef SETVBUF_REVERSED
 
 /* The size of `int', as computed by sizeof. */
 #undef SIZEOF_INT
@@ -1297,20 +1292,30 @@
 /* Define to 1 if your <sys/time.h> declares `struct tm'. */
 #undef TM_IN_SYS_TIME
 
-/* Define to 1 if on AIX 3.
-   System headers sometimes define this.
-   We just want to avoid a redefinition error message.  */
+/* Enable extensions on AIX 3, Interix.  */
 #ifndef _ALL_SOURCE
 # undef _ALL_SOURCE
 #endif
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
 /* Enable GNU extensions on systems that have them.  */
 #ifndef _GNU_SOURCE
 # undef _GNU_SOURCE
 #endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
 
 /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
 #undef _LARGEFILE_SOURCE
@@ -1327,20 +1332,6 @@
 
 /* Define to 1 if you need to in order for `stat' and other things to work. */
 #undef _POSIX_SOURCE
-
-/* Enable extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif
-
-/* Define like PROTOTYPES; this can be used by system headers. */
-#undef __PROTOTYPES
 
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const

Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Thu Oct 22 11:33:22 2009
@@ -185,6 +185,37 @@
 };
 
 /*!
+ * \since 1.6.3
+ * \brief Information needed to specify a subaddress 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_subaddress {
+	/*!
+	 * \brief Malloced subaddress string.
+	 * \note If the subaddress type is user specified then the subaddress is
+	 * a string of ASCII hex because the actual subaddress is likely BCD encoded.
+	 */
+	char *str;
+	/*!
+	 * \brief Q.931 subaddress type.
+	 * \details
+	 * nsap(0),
+	 * user_specified(2)
+	 */
+	int type;
+	/*!
+	 * \brief TRUE if odd number of address signals
+	 * \note The odd/even indicator is used when the type of subaddress is
+	 * user_specified and the coding is BCD.
+	 */
+	unsigned char odd_even_indicator;
+	/*! \brief TRUE if the subaddress information is valid/present */
+	unsigned char valid;
+};
+
+/*!
  * \brief Structure for all kinds of caller ID identifications.
  * \note All string fields here are malloc'ed, so they need to be
  * freed when the structure is deleted.
@@ -260,6 +291,16 @@
 	 * (Field will eventually move to struct ast_channel.dialed.transit_network_select)
 	 */
 	int cid_tns;
+	/*!
+	 * \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;
 };
 
 /*!
@@ -275,6 +316,9 @@
 
 	/*! \brief Subscriber name (Malloced) */
 	char *name;
+
+	/*! \brief Subscriber subaddress. */
+	struct ast_party_subaddress subaddress;
 
 	/*! \brief Q.931 encoded type-of-number/numbering-plan fields */
 	int number_type;
@@ -2342,6 +2386,67 @@
 
 /*!
  * \since 1.6.3
+ * \brief Initialize the given subaddress structure.
+ *
+ * \param init Subaddress structure to initialize.
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_init(struct ast_party_subaddress *init);
+
+/*!
+ * \since 1.6.3
+ * \brief Copy the source party subaddress information to the destination party subaddress.
+ *
+ * \param dest Destination party subaddress
+ * \param src Source party subaddress
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src);
+
+/*!
+ * \since 1.6.3
+ * \brief Initialize the given party subadress 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 Subaddress structure to initialize.
+ * \param guide Source party subaddress to use as a guide in initializing.
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_set_init(struct ast_party_subaddress *init, const struct ast_party_subaddress *guide);
+
+/*!
+ * \since 1.6.3
+ * \brief Set the source party subaddress information into the destination party subaddress.
+ *
+ * \param dest Destination party subaddress
+ * \param src Source party subaddress
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src);
+
+/*!
+ * \since 1.6.3
+ * \brief Destroy the party subaddress contents
+ *
+ * \param doomed The party subaddress to destroy.
+ *
+ * \return Nothing
+ */
+void ast_party_subaddress_free(struct ast_party_subaddress *doomed);
+
+/*!
+ * \since 1.6.3
  * \brief Initialize the given caller structure.
  *
  * \param init Caller structure to initialize.

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=225357&r1=225356&r2=225357
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Thu Oct 22 11:33:22 2009
@@ -1449,6 +1449,8 @@
 	if (cid->cid_rdnis)
 		ast_free(cid->cid_rdnis);
 	cid->cid_dnid = cid->cid_num = cid->cid_name = cid->cid_ani = cid->cid_rdnis = NULL;
+	ast_party_subaddress_free(&cid->subaddress);
+	ast_party_subaddress_free(&cid->dialed_subaddress);
 }
 
 struct ast_channel *ast_channel_release(struct ast_channel *chan)
@@ -1456,6 +1458,65 @@
 	/* Safe, even if already unlinked. */
 	ao2_unlink(channels, chan);
 	return ast_channel_unref(chan);
+}
+
+void ast_party_subaddress_init(struct ast_party_subaddress *init)
+{
+	init->str = NULL;
+	init->type = 0;
+	init->odd_even_indicator = 0;
+	init->valid = 0;
+}
+
+void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src)
+{
+	if (dest == src) {
+		/* Don't copy to self */
+		return;
+	}
+
+	if (dest->str) {
+		ast_free(dest->str);
+	}
+	dest->str = ast_strdup(src->str);
+	dest->type = src->type;
+	dest->odd_even_indicator = src->odd_even_indicator;
+	dest->valid = src->valid;
+}
+
+void ast_party_subaddress_set_init(struct ast_party_subaddress *init, const struct ast_party_subaddress *guide)
+{
+	init->str = NULL;
+	init->type = guide->type;
+	init->odd_even_indicator = guide->odd_even_indicator;
+	init->valid = guide->valid;
+}
+
+void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src)
+{
+	if (dest == src) {
+		/* Don't set to self */
+		return;
+	}
+
+	if (src->str && src->str != dest->str) {
+		if (dest->str) {
+			ast_free(dest->str);
+		}
+		dest->str = ast_strdup(src->str);
+	}
+
+	dest->type = src->type;
+	dest->odd_even_indicator = src->odd_even_indicator;
+	dest->valid = src->valid;
+}
+
+void ast_party_subaddress_free(struct ast_party_subaddress *doomed)
+{
+	if (doomed->str) {
+		ast_free(doomed->str);
+		doomed->str = NULL;
+	}
 }
 
 /*!
@@ -1472,6 +1533,7 @@
 	init->name = NULL;
 	init->number_type = 0;	/* Unknown */
 	init->number_presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
+	ast_party_subaddress_init(&init->subaddress);
 }
 
 /*!
@@ -1502,6 +1564,7 @@
 
 	dest->number_type = src->number_type;
 	dest->number_presentation = src->number_presentation;
+	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
 }
 
 /*!
@@ -1527,6 +1590,7 @@
 	init->name = NULL;
 	init->number_type = guide->number_type;
 	init->number_presentation = guide->number_presentation;
+	ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
 }
 
 /*!
@@ -1561,6 +1625,7 @@
 
 	dest->number_type = src->number_type;
 	dest->number_presentation = src->number_presentation;
+	ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
 }
 
 /*!
@@ -1582,6 +1647,7 @@
 		ast_free(doomed->name);
 		doomed->name = NULL;
 	}
+	ast_party_subaddress_free(&doomed->subaddress);
 }
 
 void ast_party_caller_init(struct ast_party_caller *init)
@@ -1624,6 +1690,8 @@
 
 	dest->cid_ani2 = src->cid_ani2;
 
+	ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
+
 #else
 
 	/* The src and dest parameter types will become struct ast_party_caller ptrs. */
@@ -1695,6 +1763,7 @@
 	connected->id.name = cid->cid_name;
 	connected->id.number_type = cid->cid_ton;
 	connected->id.number_presentation = cid->cid_pres;
+	connected->id.subaddress = cid->subaddress;
 
 	connected->ani = cid->cid_ani;
 	connected->ani2 = cid->cid_ani2;
@@ -6511,6 +6580,7 @@
 	dest->ani = ast_strdup(src->cid_ani);
 
 	dest->ani2 = src->cid_ani2;
+	ast_party_subaddress_copy(&dest->id.subaddress, &src->subaddress);
 
 #else
 
@@ -6552,6 +6622,7 @@
 	dest->cid_ani = ast_strdup(src->ani);
 
 	dest->cid_ani2 = src->ani2;
+	ast_party_subaddress_copy(&dest->subaddress, &src->id.subaddress);
 
 #else
 
@@ -6590,7 +6661,11 @@
 	AST_CONNECTED_LINE_NAME,
 	AST_CONNECTED_LINE_NUMBER_TYPE,
 	AST_CONNECTED_LINE_NUMBER_PRESENTATION,
-	AST_CONNECTED_LINE_SOURCE
+	AST_CONNECTED_LINE_SOURCE,
+	AST_CONNECTED_LINE_SUBADDRESS,
+	AST_CONNECTED_LINE_SUBADDRESS_TYPE,
+	AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN,
+	AST_CONNECTED_LINE_SUBADDRESS_VALID
 };
 
 int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected)
@@ -6656,6 +6731,46 @@
 	memcpy(data + pos, &value, sizeof(value));
 	pos += sizeof(value);
 
+	/* Connected line Subaddress */
+	if (connected->id.subaddress.str) {
+		length = strlen(connected->id.subaddress.str);
+		if (datalen < pos + (sizeof(data[0]) * 2) + length) {
+			ast_log(LOG_WARNING, "No space left for connected line subaddress\n");
+			return -1;
+		}
+		data[pos++] = AST_CONNECTED_LINE_SUBADDRESS;
+		data[pos++] = length;
+		memcpy(data + pos, connected->id.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");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_TYPE;
+	data[pos++] = 1;
+	data[pos++] = connected->id.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");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN;
+	data[pos++] = 1;
+	data[pos++] = connected->id.subaddress.odd_even_indicator;
+
+	/* Connected line Subaddress Valid */
+	if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
+		ast_log(LOG_WARNING, "No space left for connected line subaddress valid\n");
+		return -1;
+	}
+	data[pos++] = AST_CONNECTED_LINE_SUBADDRESS_VALID;
+	data[pos++] = 1;
+	data[pos++] = connected->id.subaddress.valid;
+
 	return pos;
 }
 
@@ -6720,6 +6835,41 @@
 			}
 			memcpy(&value, data + pos, sizeof(value));
 			connected->source = ntohl(value);
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS:
+			if (connected->id.subaddress.str) {
+				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);
+				connected->id.subaddress.str[ie_len] = 0;
+			}
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS_TYPE:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line type of subaddress (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.subaddress.type = data[pos];
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS_ODD_EVEN:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING,
+					"Invalid connected line subaddress odd-even indicator (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.subaddress.odd_even_indicator = data[pos];
+			break;
+		case AST_CONNECTED_LINE_SUBADDRESS_VALID:
+			if (ie_len != 1) {
+				ast_log(LOG_WARNING, "Invalid connected line subaddress valid (%u)\n",
+					(unsigned) ie_len);
+				break;
+			}
+			connected->id.subaddress.valid = data[pos];
 			break;
 		default:
 			ast_log(LOG_DEBUG, "Unknown connected line element: %u (%u)\n", (unsigned) ie_id, (unsigned) ie_len);
@@ -6799,7 +6949,15 @@
 	AST_REDIRECTING_TO_NUMBER_TYPE,
 	AST_REDIRECTING_TO_NUMBER_PRESENTATION,
 	AST_REDIRECTING_REASON,
-	AST_REDIRECTING_COUNT
+	AST_REDIRECTING_COUNT,
+	AST_REDIRECTING_FROM_SUBADDRESS,
+	AST_REDIRECTING_FROM_SUBADDRESS_TYPE,
+	AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN,
+	AST_REDIRECTING_FROM_SUBADDRESS_VALID,
+	AST_REDIRECTING_TO_SUBADDRESS,
+	AST_REDIRECTING_TO_SUBADDRESS_TYPE,
+	AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN,
+	AST_REDIRECTING_TO_SUBADDRESS_VALID
 };
 
 int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting)
@@ -6854,6 +7012,44 @@
 	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);
@@ -6895,6 +7091,44 @@
 	data[pos++] = 1;

[... 128 lines stripped ...]



More information about the asterisk-commits mailing list