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/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@225357 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
Richard Mudgett 16 years ago
parent 3acfd4933c
commit 1174a61612

@ -88,6 +88,8 @@ Dialplan Functions
------------------
* 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 @@ libpri channel driver (chan_dahdi) DAHDI changes
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
--------------------------

@ -437,6 +437,168 @@ static int overall_ast_presentation(const struct pri_party_id *id)
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 @@ static void sig_pri_party_id_from_ast(struct pri_party_id *pri_id, const struct
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 @@ static void sig_pri_party_id_convert(struct ast_party_id *ast_id,
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 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve
}
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 @@ static void *pri_dchannel(void *vpri)
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 @@ static void *pri_dchannel(void *vpri)
* 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 @@ exit:
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 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
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;
@ -2503,6 +2745,34 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
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) {
c++;
@ -2634,6 +2904,16 @@ int sig_pri_call(struct sig_pri_chan *p, struct ast_channel *ast, char *rdest, i
}
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 @@ 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));
#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

20276
configure vendored

File diff suppressed because it is too large Load Diff

@ -288,11 +288,16 @@ AST_EXT_LIB_SETUP([PGSQL], [PostgreSQL], [postgres])
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([POPT], [popt], [poptStrerror], [popt.h])
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.

@ -49,6 +49,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<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 @@ static int callerid_read(struct ast_channel *chan, const char *cmd, char *data,
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 @@ static int callerid_write(struct ast_channel *chan, const char *cmd, char *data,
}
} else if (!strncasecmp("dnid", data, 4)) {
ast_channel_lock(chan);
if (chan->cid.cid_dnid) {
ast_free(chan->cid.cid_dnid);
/* 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);
}
chan->cid.cid_dnid = ast_strdup(value);
if (chan->cdr) {
ast_cdr_setcid(chan->cdr, chan);
}

@ -43,7 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/*
* 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 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<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 @@ static int connectedline_read(struct ast_channel *chan, const char *cmd, char *d
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 @@ static int connectedline_write(struct ast_channel *chan, const char *cmd, char *
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);
}

@ -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
@ -1272,11 +1272,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
@ -1328,20 +1333,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

@ -184,6 +184,37 @@ struct ast_generator {
void (*digit)(struct ast_channel *chan, char digit);
};
/*!
* \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
@ -260,6 +291,16 @@ struct ast_callerid {
* (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;
};
/*!
@ -276,6 +317,9 @@ struct ast_party_id {
/*! \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;
@ -2340,6 +2384,67 @@ 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);
/*!
* \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.

@ -1449,6 +1449,8 @@ static void free_cid(struct ast_callerid *cid)
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)
@ -1458,6 +1460,65 @@ struct ast_channel *ast_channel_release(struct ast_channel *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;
}
}
/*!
* \internal
* \brief Initialize the given party id structure.
@ -1472,6 +1533,7 @@ static void ast_party_id_init(struct ast_party_id *init)
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 @@ static void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_
dest->number_type = src->number_type;
dest->number_presentation = src->number_presentation;
ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
}
/*!
@ -1527,6 +1590,7 @@ static void ast_party_id_set_init(struct ast_party_id *init, const struct ast_pa
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 @@ static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_i
dest->number_type = src->number_type;
dest->number_presentation = src->number_presentation;
ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
}
/*!
@ -1582,6 +1647,7 @@ static void ast_party_id_free(struct ast_party_id *doomed)
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 @@ void ast_party_caller_copy(struct ast_callerid *dest, const struct ast_callerid
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 @@ void ast_party_connected_line_collect_caller(struct ast_party_connected_line *co
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 @@ void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest,
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 @@ void ast_connected_line_copy_to_caller(struct ast_callerid *dest, const struct a
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 @@ enum {
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 @@ int ast_connected_line_build_data(unsigned char *data, size_t datalen, const str
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;
}
@ -6721,6 +6836,41 @@ int ast_connected_line_parse_data(const unsigned char *data, size_t datalen, str
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);
break;
@ -6799,7 +6949,15 @@ enum {
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 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
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 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
data[pos++] = 1;
data[pos++] = redirecting->to.number_presentation;
/* 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;
}
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
ast_log(LOG_WARNING, "No space left for redirecting-to type of subaddress\n");
return -1;
}
data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_TYPE;
data[pos++] = 1;
data[pos++] = redirecting->to.subaddress.type;
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
ast_log(LOG_WARNING,
"No space left for redirecting-to subaddress odd-even indicator\n");
return -1;
}
data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN;
data[pos++] = 1;
data[pos++] = redirecting->to.subaddress.odd_even_indicator;
if (datalen < pos + (sizeof(data[0]) * 2) + 1) {
ast_log(LOG_WARNING, "No space left for redirecting-to subaddress valid\n");
return -1;
}
data[pos++] = AST_REDIRECTING_TO_SUBADDRESS_VALID;
data[pos++] = 1;
data[pos++] = redirecting->to.subaddress.valid;
/* Redirecting reason */
if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
ast_log(LOG_WARNING, "No space left for redirecting reason\n");
@ -6974,6 +7208,41 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
}
redirecting->from.number_presentation = data[pos];
break;
case AST_REDIRECTING_FROM_SUBADDRESS:
if (redirecting->from.subaddress.str) {
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);
redirecting->from.subaddress.str[ie_len] = 0;
}
break;
case AST_REDIRECTING_FROM_SUBADDRESS_TYPE:
if (ie_len != 1) {
ast_log(LOG_WARNING, "Invalid redirecting from type of subaddress (%u)\n",
(unsigned) ie_len);
break;
}
redirecting->from.subaddress.type = data[pos];
break;
case AST_REDIRECTING_FROM_SUBADDRESS_ODD_EVEN:
if (ie_len != 1) {
ast_log(LOG_WARNING,
"Invalid redirecting from subaddress odd-even indicator (%u)\n",
(unsigned) ie_len);
break;
}
redirecting->from.subaddress.odd_even_indicator = data[pos];
break;
case AST_REDIRECTING_FROM_SUBADDRESS_VALID:
if (ie_len != 1) {
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);
@ -7008,6 +7277,41 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
}
redirecting->to.number_presentation = data[pos];
break;
case AST_REDIRECTING_TO_SUBADDRESS:
if (redirecting->to.subaddress.str) {
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);
redirecting->to.subaddress.str[ie_len] = 0;
}
break;
case AST_REDIRECTING_TO_SUBADDRESS_TYPE:
if (ie_len != 1) {
ast_log(LOG_WARNING, "Invalid redirecting to type of subaddress (%u)\n",
(unsigned) ie_len);
break;
}
redirecting->to.subaddress.type = data[pos];
break;
case AST_REDIRECTING_TO_SUBADDRESS_ODD_EVEN:
if (ie_len != 1) {
ast_log(LOG_WARNING,
"Invalid redirecting to subaddress odd-even indicator (%u)\n",
(unsigned) ie_len);
break;
}
redirecting->to.subaddress.odd_even_indicator = data[pos];
break;
case AST_REDIRECTING_TO_SUBADDRESS_VALID:
if (ie_len != 1) {
ast_log(LOG_WARNING, "Invalid redirecting to subaddress valid (%u)\n",
(unsigned) ie_len);
break;
}
redirecting->to.subaddress.valid = data[pos];
break;
case AST_REDIRECTING_REASON:
if (ie_len != sizeof(value)) {
ast_log(LOG_WARNING, "Invalid redirecting reason (%u)\n", (unsigned) ie_len);

Loading…
Cancel
Save