summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorzuul <zuul@gerrit.asterisk.org>2016-09-14 12:54:24 -0500
committerGerrit Code Review <gerrit2@gerrit.digium.api>2016-09-14 12:54:24 -0500
commita5f7b07579093c22e5b2397451b46c5073d09810 (patch)
treec5fa80d7589604be6455c6e64388764bd4cfff6b /res
parentefba4a7b9cc19ca10b11057da8dd4793355088a3 (diff)
parent30af92e78d36523f8012da5eb9aee16687d8fe61 (diff)
Merge "res_pjsip: Add ignore_uri_user_options option." into 13
Diffstat (limited to 'res')
-rw-r--r--res/res_pjsip.c24
-rw-r--r--res/res_pjsip/config_global.c20
-rw-r--r--res/res_pjsip/pjsip_options.c12
-rw-r--r--res/res_pjsip_caller_id.c18
-rw-r--r--res/res_pjsip_diversion.c25
-rw-r--r--res/res_pjsip_endpoint_identifier_user.c12
-rw-r--r--res/res_pjsip_messaging.c25
-rw-r--r--res/res_pjsip_path.c22
-rw-r--r--res/res_pjsip_pubsub.c18
-rw-r--r--res/res_pjsip_refer.c7
-rw-r--r--res/res_pjsip_registrar.c6
-rw-r--r--res/res_pjsip_session.c13
12 files changed, 185 insertions, 17 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 96c07d501..039495d55 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -1544,6 +1544,30 @@
</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>
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index 281630ae4..fc1227d25 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -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;
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index d87188363..8c8836fd9 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -760,8 +760,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;
}
@@ -778,13 +777,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);
diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c
index 4d9f09237..c3aa338ae 100644
--- a/res/res_pjsip_caller_id.c
+++ b/res/res_pjsip_caller_id.c
@@ -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)) {
diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c
index 99d18da44..b9225de9c 100644
--- a/res/res_pjsip_diversion.c
+++ b/res/res_pjsip_diversion.c
@@ -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)) {
diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c
index e018abd61..30da062ed 100644
--- a/res/res_pjsip_endpoint_identifier_user.c
+++ b/res/res_pjsip_endpoint_identifier_user.c
@@ -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)) {
diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c
index a3cc8afcf..835a38393 100644
--- a/res/res_pjsip_messaging.c
+++ b/res/res_pjsip_messaging.c
@@ -132,6 +132,12 @@ static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri
} else if ((aor_uri = strchr(name, '@'))) {
/* format was 'endpoint@domain' - discard the domain */
*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
@@ -467,6 +473,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);
@@ -547,7 +559,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) {
@@ -572,9 +584,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;
}
diff --git a/res/res_pjsip_path.c b/res/res_pjsip_path.c
index 47d6a7906..20c9d4366 100644
--- a/res/res_pjsip_path.c
+++ b/res/res_pjsip_path.c
@@ -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;
diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c
index 3ac3f342f..2fa7f34e3 100644
--- a/res/res_pjsip_pubsub.c
+++ b/res/res_pjsip_pubsub.c
@@ -1400,6 +1400,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",
@@ -2815,6 +2821,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) {
@@ -3028,6 +3040,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);
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index 8fe4e8477..99295d5f3 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -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);
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index 1e0f5ab72..a13f8f86b 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -634,6 +634,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);
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 050970998..8b8e9d114 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -1980,6 +1980,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");
@@ -3059,6 +3065,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];