Add original party id and reason support.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 20 Apr 2012 00:57:13 +0000 (00:57 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 20 Apr 2012 00:57:13 +0000 (00:57 +0000)
ISDN ETSI PTP and Q.SIG (And SS7 in future) have support for reporting who
was the original redirecting party of a call.

* Added support for the original redirecting party and reason to the
REDIRECTING function and the system core as well as to the stubbed
locations in sig_pri.c.

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

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@362779 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
UPGRADE.txt
channels/sig_pri.c
funcs/func_callerid.c
include/asterisk/channel.h
main/channel.c

diff --git a/CHANGES b/CHANGES
index aa4fe6a..067bd6c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -202,6 +202,8 @@ Dialplan functions
    user information, such as the email address and full name.
    The MAILBOX_EXISTS dialplan function has been deprecated in favour of
    VM_INFO.
+ * The REDIRECTING function now supports the redirecting original party id
+   and reason.
 
 Followme changes
 -------------
index 2890438..adff551 100644 (file)
@@ -39,6 +39,8 @@ Dialplan Functions:
    line purposes use the following variables instead of their macro equivalents:
    REDIRECTING_SEND_SUB, REDIRECTING_SEND_SUB_ARGS,
    CONNECTED_LINE_SEND_SUB, CONNECTED_LINE_SEND_SUB_ARGS.
+ - The REDIRECTING function now supports the redirecting original party id
+   and reason.
 
 
 func_enum:
index e40aa9a..47724a8 100644 (file)
@@ -902,14 +902,16 @@ static void sig_pri_party_id_from_ast(struct pri_party_id *pri_id, const struct
 static void sig_pri_redirecting_update(struct sig_pri_chan *pvt, struct ast_channel *ast)
 {
        struct pri_party_redirecting pri_redirecting;
-
-/*! \todo XXX Original called data can be put in a channel data store that is inherited. */
+       const struct ast_party_redirecting *ast_redirecting;
 
        memset(&pri_redirecting, 0, sizeof(pri_redirecting));
-       sig_pri_party_id_from_ast(&pri_redirecting.from, &ast_channel_redirecting(ast)->from);
-       sig_pri_party_id_from_ast(&pri_redirecting.to, &ast_channel_redirecting(ast)->to);
-       pri_redirecting.count = ast_channel_redirecting(ast)->count;
-       pri_redirecting.reason = ast_to_pri_reason(ast_channel_redirecting(ast)->reason);
+       ast_redirecting = ast_channel_redirecting(ast);
+       sig_pri_party_id_from_ast(&pri_redirecting.from, &ast_redirecting->from);
+       sig_pri_party_id_from_ast(&pri_redirecting.to, &ast_redirecting->to);
+       sig_pri_party_id_from_ast(&pri_redirecting.orig_called, &ast_redirecting->orig);
+       pri_redirecting.count = ast_redirecting->count;
+       pri_redirecting.orig_reason = ast_to_pri_reason(ast_redirecting->orig_reason);
+       pri_redirecting.reason = ast_to_pri_reason(ast_redirecting->reason);
 
        pri_redirecting_update(pvt->pri->pri, pvt->call, &pri_redirecting);
 }
@@ -2115,10 +2117,12 @@ static void sig_pri_redirecting_convert(struct ast_party_redirecting *ast_redire
 {
        ast_party_redirecting_set_init(ast_redirecting, ast_guide);
 
+       sig_pri_party_id_convert(&ast_redirecting->orig, &pri_redirecting->orig_called, pri);
        sig_pri_party_id_convert(&ast_redirecting->from, &pri_redirecting->from, pri);
        sig_pri_party_id_convert(&ast_redirecting->to, &pri_redirecting->to, pri);
        ast_redirecting->count = pri_redirecting->count;
        ast_redirecting->reason = pri_to_ast_reason(pri_redirecting->reason);
+       ast_redirecting->orig_reason = pri_to_ast_reason(pri_redirecting->orig_reason);
 }
 
 /*!
@@ -4185,11 +4189,9 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev
                        if (owner) {
                                sig_pri_redirecting_convert(&ast_redirecting, &subcmd->u.redirecting,
                                        ast_channel_redirecting(owner), pri);
+                               ast_redirecting.orig.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
                                ast_redirecting.from.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
                                ast_redirecting.to.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
-
-/*! \todo XXX Original called data can be put in a channel data store that is inherited. */
-
                                ast_channel_set_redirecting(owner, &ast_redirecting, NULL);
                                if (event_id != PRI_EVENT_RING) {
                                        /* This redirection was not from a SETUP message. */
@@ -4257,6 +4259,7 @@ static void sig_pri_handle_subcmds(struct sig_pri_span *pri, int chanpos, int ev
                                }
                                sig_pri_redirecting_convert(&ast_redirecting, &pri_deflection,
                                        ast_channel_redirecting(owner), pri);
+                               ast_redirecting.orig.tag = ast_strdup(pri->pvts[chanpos]->user_tag);
                                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, NULL);
index 0676283..f15e367 100644 (file)
@@ -69,13 +69,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  * 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(orig-pres), REDIRECTING(from-pres),
+ * or REDIRECTING(to-pres) datatypes.
+ * The name and number now have their own presentation value.  The orig-pres,
+ * 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.
+ * Do not document the REDIRECTING(orig-ton), REDIRECTING(from-ton),
+ * or REDIRECTING(to-ton) datatypes.
+ * They are aliases for orig-num-plan, from-num-plan, and to-num-plan
+ * respectively.
  */
 /*** DOCUMENTATION
        <function name="CALLERID" language="en_US">
@@ -239,6 +242,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                        <parameter name="datatype" required="true">
                                <para>The allowable datatypes are:</para>
                                <enumlist>
+                                       <enum name = "orig-all" />
+                                       <enum name = "orig-name" />
+                                       <enum name = "orig-name-valid" />
+                                       <enum name = "orig-name-charset" />
+                                       <enum name = "orig-name-pres" />
+                                       <enum name = "orig-num" />
+                                       <enum name = "orig-num-valid" />
+                                       <enum name = "orig-num-plan" />
+                                       <enum name = "orig-num-pres" />
+                                       <enum name = "orig-subaddr" />
+                                       <enum name = "orig-subaddr-valid" />
+                                       <enum name = "orig-subaddr-type" />
+                                       <enum name = "orig-subaddr-odd" />
+                                       <enum name = "orig-tag" />
+                                       <enum name = "orig-reason" />
                                        <enum name = "from-all" />
                                        <enum name = "from-name" />
                                        <enum name = "from-name-valid" />
@@ -279,7 +297,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                <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>
+                       and <replaceable>orig-reason</replaceable> fields are the following:</para>
                        <enumlist>
                                <enum name = "unknown"><para>Unknown</para></enum>
                                <enum name = "cfb"><para>Call Forwarding Busy</para></enum>
@@ -1330,6 +1348,7 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat
 {
        struct ast_party_members member;
        char *read_what;
+       const struct ast_party_redirecting *ast_redirecting;
        enum ID_FIELD_STATUS status;
 
        /* Ensure that the buffer is empty */
@@ -1348,9 +1367,26 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat
 
        ast_channel_lock(chan);
 
-       if (!strcasecmp("from", member.argv[0])) {
+       ast_redirecting = ast_channel_redirecting(chan);
+       if (!strcasecmp("orig", member.argv[0])) {
+               if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
+                       ast_copy_string(buf,
+                               ast_redirecting_reason_name(ast_redirecting->orig_reason), len);
+               } else {
+                       status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
+                               &ast_redirecting->orig);
+                       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("from", member.argv[0])) {
                status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
-                       &ast_channel_redirecting(chan)->from);
+                       &ast_redirecting->from);
                switch (status) {
                case ID_FIELD_VALID:
                case ID_FIELD_INVALID:
@@ -1361,7 +1397,7 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat
                }
        } else if (!strcasecmp("to", member.argv[0])) {
                status = party_id_read(buf, len, member.argc - 1, member.argv + 1,
-                       &ast_channel_redirecting(chan)->to);
+                       &ast_redirecting->to);
                switch (status) {
                case ID_FIELD_VALID:
                case ID_FIELD_INVALID:
@@ -1377,11 +1413,11 @@ static int redirecting_read(struct ast_channel *chan, const char *cmd, char *dat
                 */
                ast_copy_string(buf,
                        ast_named_caller_presentation(
-                               ast_party_id_presentation(&ast_channel_redirecting(chan)->from)), len);
+                               ast_party_id_presentation(&ast_redirecting->from)), len);
        } else if (member.argc == 1 && !strcasecmp("reason", member.argv[0])) {
-               ast_copy_string(buf, ast_redirecting_reason_name(ast_channel_redirecting(chan)->reason), len);
+               ast_copy_string(buf, ast_redirecting_reason_name(ast_redirecting->reason), len);
        } else if (member.argc == 1 && !strcasecmp("count", member.argv[0])) {
-               snprintf(buf, len, "%d", ast_channel_redirecting(chan)->count);
+               snprintf(buf, len, "%d", ast_redirecting->count);
        } else {
                ast_log(LOG_ERROR, "Unknown redirecting data type '%s'.\n", data);
        }
@@ -1450,7 +1486,42 @@ static int redirecting_write(struct ast_channel *chan, const char *cmd, char *da
 
        value = ast_skip_blanks(value);
 
-       if (!strcasecmp("from", member.argv[0])) {
+       if (!strcasecmp("orig", member.argv[0])) {
+               if (member.argc == 2 && !strcasecmp("reason", member.argv[1])) {
+                       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 orig reason '%s', value unchanged\n", val);
+                       } else {
+                               redirecting.orig_reason = reason;
+                               set_it(chan, &redirecting, NULL);
+                       }
+               } else {
+                       status = party_id_write(&redirecting.orig, 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("from", member.argv[0])) {
                status = party_id_write(&redirecting.from, member.argc - 1, member.argv + 1,
                        value);
                switch (status) {
index 54faa1d..ab6c736 100644 (file)
@@ -449,6 +449,9 @@ struct ast_set_party_connected_line {
  * \note NULL and "" must be considered equivalent.
  */
 struct ast_party_redirecting {
+       /*! \brief Who originally redirected the call (Sent to the party the call is redirected toward) */
+       struct ast_party_id orig;
+
        /*! \brief Who is redirecting the call (Sent to the party the call is redirected toward) */
        struct ast_party_id from;
 
@@ -460,6 +463,9 @@ struct ast_party_redirecting {
 
        /*! \brief enum AST_REDIRECTING_REASON value for redirection */
        int reason;
+
+       /*! \brief enum AST_REDIRECTING_REASON value for redirection by original party */
+       int orig_reason;
 };
 
 /*!
@@ -467,6 +473,8 @@ struct ast_party_redirecting {
  * \brief Indicate what information in ast_party_redirecting should be set.
  */
 struct ast_set_party_redirecting {
+       /*! What redirecting-orig id information to set. */
+       struct ast_set_party_id orig;
        /*! What redirecting-from id information to set. */
        struct ast_set_party_id from;
        /*! What redirecting-to id information to set. */
index 5f549f3..13ebdad 100644 (file)
@@ -2118,10 +2118,12 @@ void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
 
 void ast_party_redirecting_init(struct ast_party_redirecting *init)
 {
+       ast_party_id_init(&init->orig);
        ast_party_id_init(&init->from);
        ast_party_id_init(&init->to);
        init->count = 0;
        init->reason = AST_REDIRECTING_REASON_UNKNOWN;
+       init->orig_reason = AST_REDIRECTING_REASON_UNKNOWN;
 }
 
 void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct ast_party_redirecting *src)
@@ -2131,30 +2133,37 @@ void ast_party_redirecting_copy(struct ast_party_redirecting *dest, const struct
                return;
        }
 
+       ast_party_id_copy(&dest->orig, &src->orig);
        ast_party_id_copy(&dest->from, &src->from);
        ast_party_id_copy(&dest->to, &src->to);
        dest->count = src->count;
        dest->reason = src->reason;
+       dest->orig_reason = src->orig_reason;
 }
 
 void ast_party_redirecting_set_init(struct ast_party_redirecting *init, const struct ast_party_redirecting *guide)
 {
+       ast_party_id_set_init(&init->orig, &guide->orig);
        ast_party_id_set_init(&init->from, &guide->from);
        ast_party_id_set_init(&init->to, &guide->to);
        init->count = guide->count;
        init->reason = guide->reason;
+       init->orig_reason = guide->orig_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->orig, &src->orig, update ? &update->orig : NULL);
        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;
+       dest->reason = src->reason;
+       dest->orig_reason = src->orig_reason;
 }
 
 void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
 {
+       ast_party_id_free(&doomed->orig);
        ast_party_id_free(&doomed->from);
        ast_party_id_free(&doomed->to);
 }
@@ -8436,7 +8445,10 @@ struct ast_party_id_ies {
        struct ast_party_subaddress_ies subaddress;
        /*! \brief User party id tag ie. */
        int tag;
-       /*! \brief Combined name and number presentation ie. */
+       /*!
+        * \brief Combined name and number presentation ie.
+        * \note Not sent if value is zero.
+        */
        int combined_presentation;
 };
 
@@ -8509,7 +8521,7 @@ static int party_id_build_data(unsigned char *data, size_t datalen,
        }
 
        /* *************** Party id combined presentation *************** */
-       if (!update || update->number) {
+       if (ies->combined_presentation && (!update || update->number)) {
                int presentation;
 
                if (!update || update->name) {
@@ -8551,6 +8563,10 @@ enum {
        AST_CONNECTED_LINE_SUBADDRESS_VALID,
        AST_CONNECTED_LINE_TAG,
        AST_CONNECTED_LINE_VERSION,
+       /*
+        * No more party id combined number and name presentation values
+        * need to be created.
+        */
        AST_CONNECTED_LINE_NAME_VALID,
        AST_CONNECTED_LINE_NAME_CHAR_SET,
        AST_CONNECTED_LINE_NAME_PRESENTATION,
@@ -8864,11 +8880,11 @@ enum {
        AST_REDIRECTING_FROM_NUMBER,
        AST_REDIRECTING_FROM_NAME,
        AST_REDIRECTING_FROM_NUMBER_PLAN,
-       AST_REDIRECTING_FROM_ID_PRESENTATION,
+       AST_REDIRECTING_FROM_ID_PRESENTATION,/* Combined number and name presentation. */
        AST_REDIRECTING_TO_NUMBER,
        AST_REDIRECTING_TO_NAME,
        AST_REDIRECTING_TO_NUMBER_PLAN,
-       AST_REDIRECTING_TO_ID_PRESENTATION,
+       AST_REDIRECTING_TO_ID_PRESENTATION,/* Combined number and name presentation. */
        AST_REDIRECTING_REASON,
        AST_REDIRECTING_COUNT,
        AST_REDIRECTING_FROM_SUBADDRESS,
@@ -8882,6 +8898,10 @@ enum {
        AST_REDIRECTING_FROM_TAG,
        AST_REDIRECTING_TO_TAG,
        AST_REDIRECTING_VERSION,
+       /*
+        * No more party id combined number and name presentation values
+        * need to be created.
+        */
        AST_REDIRECTING_FROM_NAME_VALID,
        AST_REDIRECTING_FROM_NAME_CHAR_SET,
        AST_REDIRECTING_FROM_NAME_PRESENTATION,
@@ -8892,6 +8912,20 @@ enum {
        AST_REDIRECTING_TO_NAME_PRESENTATION,
        AST_REDIRECTING_TO_NUMBER_VALID,
        AST_REDIRECTING_TO_NUMBER_PRESENTATION,
+       AST_REDIRECTING_ORIG_NUMBER,
+       AST_REDIRECTING_ORIG_NUMBER_VALID,
+       AST_REDIRECTING_ORIG_NUMBER_PLAN,
+       AST_REDIRECTING_ORIG_NUMBER_PRESENTATION,
+       AST_REDIRECTING_ORIG_NAME,
+       AST_REDIRECTING_ORIG_NAME_VALID,
+       AST_REDIRECTING_ORIG_NAME_CHAR_SET,
+       AST_REDIRECTING_ORIG_NAME_PRESENTATION,
+       AST_REDIRECTING_ORIG_SUBADDRESS,
+       AST_REDIRECTING_ORIG_SUBADDRESS_TYPE,
+       AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN,
+       AST_REDIRECTING_ORIG_SUBADDRESS_VALID,
+       AST_REDIRECTING_ORIG_TAG,
+       AST_REDIRECTING_ORIG_REASON,
 };
 
 int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
@@ -8900,6 +8934,25 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
        size_t pos = 0;
        int res;
 
+       static const struct ast_party_id_ies orig_ies = {
+               .name.str = AST_REDIRECTING_ORIG_NAME,
+               .name.char_set = AST_REDIRECTING_ORIG_NAME_CHAR_SET,
+               .name.presentation = AST_REDIRECTING_ORIG_NAME_PRESENTATION,
+               .name.valid = AST_REDIRECTING_ORIG_NAME_VALID,
+
+               .number.str = AST_REDIRECTING_ORIG_NUMBER,
+               .number.plan = AST_REDIRECTING_ORIG_NUMBER_PLAN,
+               .number.presentation = AST_REDIRECTING_ORIG_NUMBER_PRESENTATION,
+               .number.valid = AST_REDIRECTING_ORIG_NUMBER_VALID,
+
+               .subaddress.str = AST_REDIRECTING_ORIG_SUBADDRESS,
+               .subaddress.type = AST_REDIRECTING_ORIG_SUBADDRESS_TYPE,
+               .subaddress.odd_even_indicator = AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN,
+               .subaddress.valid = AST_REDIRECTING_ORIG_SUBADDRESS_VALID,
+
+               .tag = AST_REDIRECTING_ORIG_TAG,
+               .combined_presentation = 0,/* Not sent. */
+       };
        static const struct ast_party_id_ies from_ies = {
                .name.str = AST_REDIRECTING_FROM_NAME,
                .name.char_set = AST_REDIRECTING_FROM_NAME_CHAR_SET,
@@ -8948,6 +9001,13 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
        data[pos++] = 1;
        data[pos++] = 2;/* Version 1 did not have a version ie */
 
+       res = party_id_build_data(data + pos, datalen - pos, &redirecting->orig,
+               "redirecting-orig", &orig_ies, update ? &update->orig : NULL);
+       if (res < 0) {
+               return -1;
+       }
+       pos += res;
+
        res = party_id_build_data(data + pos, datalen - pos, &redirecting->from,
                "redirecting-from", &from_ies, update ? &update->from : NULL);
        if (res < 0) {
@@ -8973,6 +9033,17 @@ int ast_redirecting_build_data(unsigned char *data, size_t datalen, const struct
        memcpy(data + pos, &value, sizeof(value));
        pos += sizeof(value);
 
+       /* Redirecting original reason */
+       if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
+               ast_log(LOG_WARNING, "No space left for redirecting original reason\n");
+               return -1;
+       }
+       data[pos++] = AST_REDIRECTING_ORIG_REASON;
+       data[pos++] = sizeof(value);
+       value = htonl(redirecting->orig_reason);
+       memcpy(data + pos, &value, sizeof(value));
+       pos += sizeof(value);
+
        /* Redirecting count */
        if (datalen < pos + (sizeof(data[0]) * 2) + sizeof(value)) {
                ast_log(LOG_WARNING, "No space left for redirecting count\n");
@@ -9021,6 +9092,115 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
                        }
                        frame_version = data[pos];
                        break;
+/* Redirecting-orig party id name */
+               case AST_REDIRECTING_ORIG_NAME:
+                       ast_free(redirecting->orig.name.str);
+                       redirecting->orig.name.str = ast_malloc(ie_len + 1);
+                       if (redirecting->orig.name.str) {
+                               memcpy(redirecting->orig.name.str, data + pos, ie_len);
+                               redirecting->orig.name.str[ie_len] = 0;
+                       }
+                       break;
+               case AST_REDIRECTING_ORIG_NAME_CHAR_SET:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig name char set (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.name.char_set = data[pos];
+                       break;
+               case AST_REDIRECTING_ORIG_NAME_PRESENTATION:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig name presentation (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.name.presentation = data[pos];
+                       break;
+               case AST_REDIRECTING_ORIG_NAME_VALID:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig name valid (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.name.valid = data[pos];
+                       break;
+/* Redirecting-orig party id number */
+               case AST_REDIRECTING_ORIG_NUMBER:
+                       ast_free(redirecting->orig.number.str);
+                       redirecting->orig.number.str = ast_malloc(ie_len + 1);
+                       if (redirecting->orig.number.str) {
+                               memcpy(redirecting->orig.number.str, data + pos, ie_len);
+                               redirecting->orig.number.str[ie_len] = 0;
+                       }
+                       break;
+               case AST_REDIRECTING_ORIG_NUMBER_PLAN:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig numbering plan (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.number.plan = data[pos];
+                       break;
+               case AST_REDIRECTING_ORIG_NUMBER_PRESENTATION:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig number presentation (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.number.presentation = data[pos];
+                       break;
+               case AST_REDIRECTING_ORIG_NUMBER_VALID:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig number valid (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.number.valid = data[pos];
+                       break;
+/* Redirecting-orig party id subaddress */
+               case AST_REDIRECTING_ORIG_SUBADDRESS:
+                       ast_free(redirecting->orig.subaddress.str);
+                       redirecting->orig.subaddress.str = ast_malloc(ie_len + 1);
+                       if (redirecting->orig.subaddress.str) {
+                               memcpy(redirecting->orig.subaddress.str, data + pos, ie_len);
+                               redirecting->orig.subaddress.str[ie_len] = 0;
+                       }
+                       break;
+               case AST_REDIRECTING_ORIG_SUBADDRESS_TYPE:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig type of subaddress (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.subaddress.type = data[pos];
+                       break;
+               case AST_REDIRECTING_ORIG_SUBADDRESS_ODD_EVEN:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING,
+                                       "Invalid redirecting-orig subaddress odd-even indicator (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.subaddress.odd_even_indicator = data[pos];
+                       break;
+               case AST_REDIRECTING_ORIG_SUBADDRESS_VALID:
+                       if (ie_len != 1) {
+                               ast_log(LOG_WARNING, "Invalid redirecting-orig subaddress valid (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       redirecting->orig.subaddress.valid = data[pos];
+                       break;
+/* Redirecting-orig party id tag */
+               case AST_REDIRECTING_ORIG_TAG:
+                       ast_free(redirecting->orig.tag);
+                       redirecting->orig.tag = ast_malloc(ie_len + 1);
+                       if (redirecting->orig.tag) {
+                               memcpy(redirecting->orig.tag, data + pos, ie_len);
+                               redirecting->orig.tag[ie_len] = 0;
+                       }
+                       break;
 /* Redirecting-from party id name */
                case AST_REDIRECTING_FROM_NAME:
                        ast_free(redirecting->from.name.str);
@@ -9269,6 +9449,16 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
                        memcpy(&value, data + pos, sizeof(value));
                        redirecting->reason = ntohl(value);
                        break;
+/* Redirecting orig-reason */
+               case AST_REDIRECTING_ORIG_REASON:
+                       if (ie_len != sizeof(value)) {
+                               ast_log(LOG_WARNING, "Invalid redirecting original reason (%u)\n",
+                                       (unsigned) ie_len);
+                               break;
+                       }
+                       memcpy(&value, data + pos, sizeof(value));
+                       redirecting->orig_reason = ntohl(value);
+                       break;
 /* Redirecting count */
                case AST_REDIRECTING_COUNT:
                        if (ie_len != sizeof(value)) {
@@ -9292,6 +9482,9 @@ int ast_redirecting_parse_data(const unsigned char *data, size_t datalen, struct
                /*
                 * The other end is an earlier version that we need to adjust
                 * for compatibility.
+                *
+                * The earlier version did not have the orig party id or
+                * orig_reason value.
                 */
                redirecting->from.name.valid = 1;
                redirecting->from.name.char_set = AST_PARTY_CHAR_SET_ISO8859_1;