]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add ignore_uri_user_options option. 56/3856/2
authorRichard Mudgett <rmudgett@digium.com>
Mon, 29 Aug 2016 23:08:22 +0000 (18:08 -0500)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 9 Sep 2016 22:13:02 +0000 (17:13 -0500)
This implements the chan_sip legacy_useroption_parsing option but with a
better name.

* Made the caller-id number and redirecting number strings obtained from
incoming SIP URI user fields always truncated at the first semicolon.
People don't care about anything after the semicolon showing up on their
displays even though the RFC allows the semicolon.

ASTERISK-26316 #close
Reported by: Kevin Harwell

Change-Id: Ib42b0e940dd34d84c7b14bc2e90d1ba392624f62

16 files changed:
CHANGES
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/config_global.c
res/res_pjsip/pjsip_options.c
res/res_pjsip_caller_id.c
res/res_pjsip_diversion.c
res/res_pjsip_endpoint_identifier_user.c
res/res_pjsip_messaging.c
res/res_pjsip_path.c
res/res_pjsip_pubsub.c
res/res_pjsip_refer.c
res/res_pjsip_registrar.c
res/res_pjsip_session.c

diff --git a/CHANGES b/CHANGES
index bf7bc75de92bcaf6978b8089bfb2b544f327f402..38228e37a23406b2d70be99dabe9d693a40532f8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -79,6 +79,17 @@ res_pjsip
    configure these options then you already had to do a reload after making
    changes.
 
+ * Added "ignore_uri_user_options" global configuration option for
+   compatibility with an ITSP that sends URI user field options.  When enabled
+   the user field is truncated at the first semicolon.
+   Example:
+   URI: "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+   The user field is "1235557890;phone-context=national"
+   Which is truncated to this: "1235557890"
+
+   Note: The caller-id and redirecting number strings obtained from incoming
+   SIP URI user fields are now always truncated at the first semicolon.
+
 app_confbridge
 ------------------
   * Some sounds played into the bridge are played asynchronously. This, for
index e6b32495ba36f5864c41de7d143f24acec8f4725..c6293b6fbcaaa5dd8a30e46587d9b1be243978f9 100644 (file)
                     ; If disabled then unsolicited mwi will start processing
                     ; on the endpoint's next contact update.
 
+;ignore_uri_user_options=no ; Enable/Disable ignoring SIP URI user field options.
+                    ; If you have this option enabled and there are semicolons
+                    ; in the user field of a SIP URI then the field is truncated
+                    ; at the first semicolon.  This effectively makes the semicolon
+                    ; a non-usable character for PJSIP endpoint names, extensions,
+                    ; and AORs.  This can be useful for improving compatability with
+                    ; an ITSP that likes to use user options for whatever reason.
+                    ; Example:
+                    ; URI: "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+                    ; The user field is "1235557890;phone-context=national"
+                    ; Which becomes this: "1235557890"
+                    ;
+                    ; Note: The caller-id and redirecting number strings obtained
+                    ; from incoming SIP URI user fields are always truncated at the
+                    ; first semicolon.
+
 ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
 ;==========================ACL SECTION OPTIONS=========================
 ;[acl]
diff --git a/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py b/contrib/ast-db-manage/config/versions/a6ef36f1309_ps_globals_add_ignore_uri_user_options.py
new file mode 100644 (file)
index 0000000..1556521
--- /dev/null
@@ -0,0 +1,32 @@
+"""ps_globals add ignore_uri_user_options
+
+Revision ID: a6ef36f1309
+Revises: 7f3e21abe318
+Create Date: 2016-08-31 12:24:22.368956
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a6ef36f1309'
+down_revision = '7f3e21abe318'
+
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects.postgresql import ENUM
+
+YESNO_NAME = 'yesno_values'
+YESNO_VALUES = ['yes', 'no']
+
+def upgrade():
+    ############################# Enums ##############################
+
+    # yesno_values have already been created, so use postgres enum object
+    # type to get around "already created" issue - works okay with mysql
+    yesno_values = ENUM(*YESNO_VALUES, name=YESNO_NAME, create_type=False)
+
+    op.add_column('ps_globals', sa.Column('ignore_uri_user_options', yesno_values))
+
+
+def downgrade():
+    op.drop_column('ps_globals', 'ignore_uri_user_options')
+
index 8a5ad29c59810d9f745320c0199d394ffdce59b8..92bdabb662f772ee4b71482600fba9de3a664cef 100644 (file)
@@ -2446,6 +2446,38 @@ int ast_sip_get_mwi_tps_queue_low(void);
  */
 unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void);
 
+/*!
+ * \brief Retrieve the global setting 'ignore_uri_user_options'.
+ * \since 13.12.0
+ *
+ * \retval non zero if ignore the user field options.
+ */
+unsigned int ast_sip_get_ignore_uri_user_options(void);
+
+/*!
+ * \brief Truncate the URI user field options string if enabled.
+ * \since 13.12.0
+ *
+ * \param str URI user field string to truncate if enabled
+ *
+ * \details
+ * We need to be able to handle URI's looking like
+ * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+ *
+ * Where the URI user field is:
+ * "1235557890;phone-context=national"
+ *
+ * When truncated the string will become:
+ * "1235557890"
+ */
+#define AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(str)                               \
+       do {                                                                                                            \
+               char *__semi = strchr((str), ';');                                              \
+               if (__semi && ast_sip_get_ignore_uri_user_options()) {  \
+                       *__semi = '\0';                                                                         \
+               }                                                                                                               \
+       } while (0)
+
 /*!
  * \brief Retrieve the system debug setting (yes|no|host).
  *
index 7bb10c07f01b59035ebceca2653d6283f1f2181a..d1ebf64e433fb64fd5b5e5cac840708863492c36 100644 (file)
                                                </para>
                                        </description>
                                </configOption>
+                               <configOption name="ignore_uri_user_options">
+                                       <synopsis>Enable/Disable ignoring SIP URI user field options.</synopsis>
+                                       <description>
+                                               <para>If you have this option enabled and there are semicolons
+                                               in the user field of a SIP URI then the field is truncated
+                                               at the first semicolon.  This effectively makes the semicolon
+                                               a non-usable character for PJSIP endpoint names, extensions,
+                                               and AORs.  This can be useful for improving compatability with
+                                               an ITSP that likes to use user options for whatever reason.
+                                               </para>
+                                               <example title="Sample SIP URI">
+                                                       sip:1235557890;phone-context=national@x.x.x.x;user=phone
+                                               </example>
+                                               <example title="Sample SIP URI user field">
+                                                       1235557890;phone-context=national
+                                               </example>
+                                               <example title="Sample SIP URI user field truncated">
+                                                       1235557890
+                                               </example>
+                                               <note><para>The caller-id and redirecting number strings
+                                               obtained from incoming SIP URI user fields are always truncated
+                                               at the first semicolon.</para></note>
+                                       </description>
+                               </configOption>
                        </configObject>
                </configFile>
        </configInfo>
index 281630ae43ac510955c6a445bfcf80566b669294..fc1227d2523305581584b874d3d84c2b5528aa53 100644 (file)
@@ -47,6 +47,7 @@
 #define DEFAULT_MWI_TPS_QUEUE_HIGH AST_TASKPROCESSOR_HIGH_WATER_LEVEL
 #define DEFAULT_MWI_TPS_QUEUE_LOW -1
 #define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0
+#define DEFAULT_IGNORE_URI_USER_OPTIONS 0
 
 /*!
  * \brief Cached global config object
@@ -100,6 +101,8 @@ struct global_config {
                /*! Nonzero to disable sending unsolicited mwi to all endpoints on startup */
                unsigned int disable_initial_unsolicited;
        } mwi;
+       /*! Nonzero if URI user field options are ignored. */
+       unsigned int ignore_uri_user_options;
 };
 
 static void global_destructor(void *obj)
@@ -384,6 +387,20 @@ unsigned int ast_sip_get_mwi_disable_initial_unsolicited(void)
        return disable_initial_unsolicited;
 }
 
+unsigned int ast_sip_get_ignore_uri_user_options(void)
+{
+       unsigned int ignore_uri_user_options;
+       struct global_config *cfg;
+
+       cfg = get_global_cfg();
+       if (!cfg) {
+               return DEFAULT_IGNORE_URI_USER_OPTIONS;
+       }
+
+       ignore_uri_user_options = cfg->ignore_uri_user_options;
+       ao2_ref(cfg, -1);
+       return ignore_uri_user_options;
+}
 
 /*!
  * \internal
@@ -533,6 +550,9 @@ int ast_sip_initialize_sorcery_global(void)
        ast_sorcery_object_field_register(sorcery, "global", "mwi_disable_initial_unsolicited",
                DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED ? "yes" : "no",
                OPT_BOOL_T, 1, FLDSET(struct global_config, mwi.disable_initial_unsolicited));
+       ast_sorcery_object_field_register(sorcery, "global", "ignore_uri_user_options",
+               DEFAULT_IGNORE_URI_USER_OPTIONS ? "yes" : "no",
+               OPT_BOOL_T, 1, FLDSET(struct global_config, ignore_uri_user_options));
 
        if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
                return -1;
index a282224c92fd05111f60f06f808d0c97b18470e5..09fe1559bfb0d8d5de4d18a28aef24a2299443d5 100644 (file)
@@ -750,8 +750,7 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
        pjsip_sip_uri *sip_ruri;
        char exten[AST_MAX_EXTENSION];
 
-       if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method,
-                            &pjsip_options_method)) {
+       if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, &pjsip_options_method)) {
                return PJ_FALSE;
        }
 
@@ -768,13 +767,20 @@ static pj_bool_t options_on_rx_request(pjsip_rx_data *rdata)
        sip_ruri = pjsip_uri_get_uri(ruri);
        ast_copy_pj_str(exten, &sip_ruri->user, sizeof(exten));
 
+       /*
+        * We may want to match in the dialplan without any user
+        * options getting in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
        if (ast_shutting_down()) {
                /*
                 * Not taking any new calls at this time.
                 * Likely a server availability OPTIONS poll.
                 */
                send_options_response(rdata, 503);
-       } else if (!ast_strlen_zero(exten) && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
+       } else if (!ast_strlen_zero(exten)
+               && !ast_exists_extension(NULL, endpoint->context, exten, 1, NULL)) {
                send_options_response(rdata, 404);
        } else {
                send_options_response(rdata, 200);
index 429cb6107832cbe66539d96df18781a7ef1a9c17..16b19ec2ba4cfc645888e1cb2ea6e1fe2870f52a 100644 (file)
@@ -46,11 +46,29 @@ static void set_id_from_hdr(pjsip_fromto_hdr *hdr, struct ast_party_id *id)
        char cid_num[AST_CHANNEL_NAME];
        pjsip_sip_uri *uri;
        pjsip_name_addr *id_name_addr = (pjsip_name_addr *) hdr->uri;
+       char *semi;
 
        uri = pjsip_uri_get_uri(id_name_addr);
        ast_copy_pj_str(cid_name, &id_name_addr->display, sizeof(cid_name));
        ast_copy_pj_str(cid_num, &uri->user, sizeof(cid_num));
 
+       /* Always truncate caller-id number at a semicolon. */
+       semi = strchr(cid_num, ';');
+       if (semi) {
+               /*
+                * We need to be able to handle URI's looking like
+                * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+                *
+                * Where the uri->user field will result in:
+                * "1235557890;phone-context=national"
+                *
+                * People don't care about anything after the semicolon
+                * showing up on their displays even though the RFC
+                * allows the semicolon.
+                */
+               *semi = '\0';
+       }
+
        ast_free(id->name.str);
        id->name.str = ast_strdup(cid_name);
        if (!ast_strlen_zero(cid_name)) {
index 82c3caaed6ea3a40532ee3b99737982a82a46bbe..301d9fc9212cc3f5eed84f4067523c5fd3f608ea 100644 (file)
@@ -148,11 +148,32 @@ static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *
                               struct ast_set_party_id *update)
 {
        pjsip_sip_uri *uri = pjsip_uri_get_uri(name_addr->uri);
+       char *semi;
+       pj_str_t uri_user;
+
+       uri_user = uri->user;
+
+       /* Always truncate redirecting number at a semicolon. */
+       semi = pj_strchr(&uri_user, ';');
+       if (semi) {
+               /*
+                * We need to be able to handle URI's looking like
+                * "sip:1235557890;phone-context=national@x.x.x.x;user=phone"
+                *
+                * Where the uri->user field will result in:
+                * "1235557890;phone-context=national"
+                *
+                * People don't care about anything after the semicolon
+                * showing up on their displays even though the RFC
+                * allows the semicolon.
+                */
+               pj_strset(&uri_user, (char *) pj_strbuf(&uri_user), semi - pj_strbuf(&uri_user));
+       }
 
-       if (pj_strlen(&uri->user)) {
+       if (pj_strlen(&uri_user)) {
                update->number = 1;
                data->number.valid = 1;
-               set_redirecting_value(&data->number.str, &uri->user);
+               set_redirecting_value(&data->number.str, &uri_user);
        }
 
        if (pj_strlen(&name_addr->display)) {
index 6aa2c553206d888e21ba59a5113b2aa4c617caa6..369cb62fc9eb27ef7caf9328fe9b44f4dff11b5e 100644 (file)
@@ -33,6 +33,7 @@ static int get_from_header(pjsip_rx_data *rdata, char *username, size_t username
 {
        pjsip_uri *from = rdata->msg_info.from->uri;
        pjsip_sip_uri *sip_from;
+
        if (!PJSIP_URI_SCHEME_IS_SIP(from) && !PJSIP_URI_SCHEME_IS_SIPS(from)) {
                return -1;
        }
@@ -115,18 +116,25 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi
 
 static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata)
 {
-       char username[64], domain[64];
+       char username[64];
+       char domain[64];
        struct ast_sip_endpoint *endpoint;
 
        if (get_from_header(rdata, username, sizeof(username), domain, sizeof(domain))) {
                return NULL;
        }
+
+       /*
+        * We may want to be matched without any user options getting
+        * in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
+
        ast_debug(3, "Attempting identify by From username '%s' domain '%s'\n", username, domain);
 
        endpoint = find_endpoint(rdata, username, domain);
        if (!endpoint) {
                ast_debug(3, "Endpoint not found for From username '%s' domain '%s'\n", username, domain);
-               ao2_cleanup(endpoint);
                return NULL;
        }
        if (!(endpoint->ident_method & AST_SIP_ENDPOINT_IDENTIFY_BY_USERNAME)) {
index 7efb1a20e6c44574b462f8c7db476bfb685fa9f0..e63c825b58b49ea646dab26b2488bd528c17f704 100644 (file)
@@ -133,6 +133,12 @@ static struct ast_sip_endpoint* get_outbound_endpoint(
        } else if ((aor_uri = strchr(name, '@'))) {
                /* format was 'endpoint@' - don't use the rest */
                *aor_uri = '\0';
+
+               /*
+                * We may want to match without any user options getting
+                * in the way.
+                */
+               AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(name);
        }
 
        /* at this point, if name is not empty then it
@@ -448,6 +454,12 @@ static enum pjsip_status_code rx_data_to_ast_msg(pjsip_rx_data *rdata, struct as
        sip_ruri = pjsip_uri_get_uri(ruri);
        ast_copy_pj_str(exten, &sip_ruri->user, AST_MAX_EXTENSION);
 
+       /*
+        * We may want to match in the dialplan without any user
+        * options getting in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
        endpt = ast_pjsip_rdata_get_endpoint(rdata);
        ast_assert(endpt != NULL);
 
@@ -528,7 +540,7 @@ static void msg_data_destroy(void *obj)
 
 static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *to, const char *from)
 {
-       char *tag;
+       char *uri_params;
        struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy);
 
        if (!mdata) {
@@ -553,9 +565,14 @@ static struct msg_data* msg_data_create(const struct ast_msg *msg, const char *t
                return NULL;
        }
 
-       /* sometimes from can still contain the tag at this point, so remove it */
-       if ((tag = strchr(mdata->from, ';'))) {
-               *tag = '\0';
+       /*
+        * Sometimes from URI can contain URI parameters, so remove them.
+        *
+        * sip:user;user-options@domain;uri-parameters
+        */
+       uri_params = strchr(mdata->from, '@');
+       if (uri_params && (uri_params = strchr(mdata->from, ';'))) {
+               *uri_params = '\0';
        }
        return mdata;
 }
index 2dde7323e61e56780518a9a332385c9300d7976b..e170a750d8d044d6de4aefe7cccd244ff0a22f6b 100644 (file)
@@ -40,7 +40,8 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
        char *configured_aors, *aor_name;
        pjsip_sip_uri *sip_uri;
        char *domain_name;
-       RAII_VAR(struct ast_str *, id, NULL, ast_free);
+       char *username;
+       struct ast_str *id = NULL;
 
        if (ast_strlen_zero(endpoint->aors)) {
                return NULL;
@@ -49,6 +50,14 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
        sip_uri = pjsip_uri_get_uri(uri);
        domain_name = ast_alloca(sip_uri->host.slen + 1);
        ast_copy_pj_str(domain_name, &sip_uri->host, sip_uri->host.slen + 1);
+       username = ast_alloca(sip_uri->user.slen + 1);
+       ast_copy_pj_str(username, &sip_uri->user, sip_uri->user.slen + 1);
+
+       /*
+        * We may want to match without any user options getting
+        * in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
 
        configured_aors = ast_strdupa(endpoint->aors);
 
@@ -60,15 +69,16 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
                        continue;
                }
 
-               if (!pj_strcmp2(&sip_uri->user, aor_name)) {
+               if (!strcmp(username, aor_name)) {
                        break;
                }
 
-               if (!id && !(id = ast_str_create(sip_uri->user.slen + sip_uri->host.slen + 2))) {
-                       return NULL;
+               if (!id && !(id = ast_str_create(strlen(username) + sip_uri->host.slen + 2))) {
+                       aor_name = NULL;
+                       break;
                }
 
-               ast_str_set(&id, 0, "%.*s@", (int)sip_uri->user.slen, sip_uri->user.ptr);
+               ast_str_set(&id, 0, "%s@", username);
                if ((alias = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "domain_alias", domain_name))) {
                        ast_str_append(&id, 0, "%s", alias->domain);
                        ao2_cleanup(alias);
@@ -77,10 +87,10 @@ static struct ast_sip_aor *find_aor(struct ast_sip_endpoint *endpoint, pjsip_uri
                }
 
                if (!strcmp(aor_name, ast_str_buffer(id))) {
-                       ast_free(id);
                        break;
                }
        }
+       ast_free(id);
 
        if (ast_strlen_zero(aor_name)) {
                return NULL;
index fe16c613ab86b408c4707f8ba6467f329f20c223..015ef99c7f3067a06ca09920c48d8be746834afc 100644 (file)
@@ -1378,6 +1378,12 @@ static int sub_persistence_recreate(void *obj)
        resource = ast_alloca(resource_size);
        ast_copy_pj_str(resource, &request_uri->user, resource_size);
 
+       /*
+        * We may want to match without any user options getting
+        * in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource);
+
        handler = subscription_get_handler_from_rdata(rdata);
        if (!handler || !handler->notifier) {
                ast_log(LOG_WARNING, "Failed recreating '%s' subscription: Could not get subscription handler.\n",
@@ -2750,6 +2756,12 @@ static pj_bool_t pubsub_on_rx_subscribe_request(pjsip_rx_data *rdata)
        resource = ast_alloca(resource_size);
        ast_copy_pj_str(resource, &request_uri_sip->user, resource_size);
 
+       /*
+        * We may want to match without any user options getting
+        * in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource);
+
        expires_header = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, rdata->msg_info.msg->hdr.next);
 
        if (expires_header) {
@@ -2963,6 +2975,12 @@ static struct ast_sip_publication *publish_request_initial(struct ast_sip_endpoi
        resource_name = ast_alloca(resource_size);
        ast_copy_pj_str(resource_name, &request_uri_sip->user, resource_size);
 
+       /*
+        * We may want to match without any user options getting
+        * in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(resource_name);
+
        resource = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "inbound-publication", resource_name);
        if (!resource) {
                ast_debug(1, "No 'inbound-publication' defined for resource '%s'\n", resource_name);
index 19367bf3261d5a960558eace8e921136bfd20efd..c1dee8225a095f7863ef4ee2afcd09e0235c57d8 100644 (file)
@@ -814,6 +814,13 @@ static int refer_incoming_blind_request(struct ast_sip_session *session, pjsip_r
 
        /* Using the user portion of the target URI see if it exists as a valid extension in their context */
        ast_copy_pj_str(exten, &target->user, sizeof(exten));
+
+       /*
+        * We may want to match in the dialplan without any user
+        * options getting in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
        if (!ast_exists_extension(NULL, context, exten, 1, NULL)) {
                ast_log(LOG_ERROR, "Channel '%s' from endpoint '%s' attempted blind transfer to '%s@%s' but target does not exist\n",
                        ast_channel_name(session->channel), ast_sorcery_object_get_id(session->endpoint), exten, context);
index fd87ef7bbbdae294da158b8c48070281c666b848..a8d2bdc4c2c160e6a7e5193d40e7a29e0ef244aa 100644 (file)
@@ -626,6 +626,12 @@ static struct ast_sip_aor *find_registrar_aor(struct pjsip_rx_data *rdata, struc
                        username = ast_alloca(uri->user.slen + 1);
                        ast_copy_pj_str(username, &uri->user, uri->user.slen + 1);
 
+                       /*
+                        * We may want to match without any user options getting
+                        * in the way.
+                        */
+                       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(username);
+
                        aor_name = find_aor_name(username, domain_name, endpoint->aors);
                        if (aor_name) {
                                ast_debug(3, "Matched aor '%s' by To username\n", aor_name);
index a26359ffb18c6bef586f6227c4d8562f900d4aa3..7e885c3bddb1047ac8cca51c4bd9ba7da1ae6a7a 100644 (file)
@@ -1982,6 +1982,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s
        sip_ruri = pjsip_uri_get_uri(ruri);
        ast_copy_pj_str(session->exten, &sip_ruri->user, sizeof(session->exten));
 
+       /*
+        * We may want to match in the dialplan without any user
+        * options getting in the way.
+        */
+       AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(session->exten);
+
        pickup_cfg = ast_get_chan_features_pickup_config(session->channel);
        if (!pickup_cfg) {
                ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
@@ -3095,6 +3101,13 @@ static pjsip_redirect_op session_inv_on_redirected(pjsip_inv_session *inv, const
                char exten[AST_MAX_EXTENSION];
 
                ast_copy_pj_str(exten, &uri->user, sizeof(exten));
+
+               /*
+                * We may want to match in the dialplan without any user
+                * options getting in the way.
+                */
+               AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(exten);
+
                ast_channel_call_forward_set(session->channel, exten);
        } else if (session->endpoint->redirect_method == AST_SIP_REDIRECT_URI_CORE) {
                char target_uri[PJSIP_MAX_URL_SIZE];