summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README-SERIOUSLY.bestpractices.md4
-rw-r--r--README.md7
-rw-r--r--apps/app_voicemail.c252
-rw-r--r--channels/chan_pjsip.c5
-rw-r--r--channels/chan_sip.c92
-rw-r--r--channels/pjsip/dialplan_functions.c50
-rw-r--r--configs/samples/iax.conf.sample12
-rw-r--r--include/asterisk/res_pjsip_session.h2
-rw-r--r--main/asterisk.c38
-rw-r--r--menuselect/Makefile5
-rw-r--r--res/res_pjsip/config_transport.c10
-rw-r--r--res/res_pjsip/pjsip_options.c53
-rw-r--r--res/res_pjsip_dlg_options.c1
-rw-r--r--res/res_pjsip_outbound_publish.c1
-rw-r--r--res/res_pjsip_phoneprov_provider.c1
-rw-r--r--res/res_pjsip_publish_asterisk.c1
-rw-r--r--res/res_pjsip_sdp_rtp.c3
-rw-r--r--res/res_pjsip_session.c15
-rw-r--r--res/res_rtp_asterisk.c8
19 files changed, 382 insertions, 178 deletions
diff --git a/README-SERIOUSLY.bestpractices.md b/README-SERIOUSLY.bestpractices.md
index 7e18c4aa8..ec36fac98 100644
--- a/README-SERIOUSLY.bestpractices.md
+++ b/README-SERIOUSLY.bestpractices.md
@@ -17,7 +17,8 @@ change over time as best practices are defined.
Recognizing potential issues with certain classes of authorization
* [Avoid Privilege Escalations]:
Disable the ability to execute functions that may escalate privileges
-
+* [Important Security Considerations]:
+ More information on the Asterisk Wiki
## Additional Links
@@ -386,3 +387,4 @@ In Asterisk 12 and later, live_dangerously defaults to no.
[Reducing Pattern Match Typos]: #reducing-pattern-match-typos
[Manager Class Authorizations]: #manager-class-authorizations
[Avoid Privilege Escalations]: #avoid-privilege-escalations
+[Important Security Considerations]: https://wiki.asterisk.org/wiki/display/AST/Important+Security+Considerations
diff --git a/README.md b/README.md
index 4ed9b3eec..153c4f3e4 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,7 @@
the security information document before you attempt to configure and run
an Asterisk server.
- If you downloaded Asterisk as a tarball, see the security section in the PDF
-version of the documentation in doc/tex/asterisk.pdf. Alternatively, pull up
-the HTML version of the documentation in doc/tex/asterisk/index.html. The
-source for the security document is available in doc/tex/security.tex.
+See [Important Security Considerations] for more information.
## WHAT IS ASTERISK ?
@@ -269,4 +266,4 @@ Asterisk is a trademark of Digium, Inc.
[CHANGES]: CHANGES
[configs]: configs
[doc]: doc
-
+[Important Security Considerations]: https://wiki.asterisk.org/wiki/display/AST/Important+Security+Considerations
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index d01730101..c155186a2 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -463,6 +463,23 @@
<description>
</description>
</manager>
+ <manager name="VoicemailUserStatus" language="en_US">
+ <synopsis>
+ Show the status of given voicemail user's info.
+ </synopsis>
+ <syntax>
+ <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+ <parameter name="Context" required="true">
+ <para>The context you want to check.</para>
+ </parameter>
+ <parameter name="Mailbox" required="true">
+ <para>The mailbox you want to check.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>Retrieves the status of the given voicemail user.</para>
+ </description>
+ </manager>
<manager name="VoicemailRefresh" language="en_US">
<synopsis>
Tell Asterisk to poll mailboxes for a change
@@ -1105,6 +1122,8 @@ static int write_password_to_file(const char *secretfn, const char *password);
static const char *substitute_escapes(const char *value);
static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu);
static void notify_new_state(struct ast_vm_user *vmu);
+static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char* event_name, const char* actionid);
+
/*!
* Place a message in the indicated folder
@@ -13222,6 +13241,105 @@ static void stop_poll_thread(void)
poll_thread = AST_PTHREADT_NULL;
}
+/*! \brief Append vmu info string into given astman with event_name. */
+static int append_vmu_info_astman(
+ struct mansession *s,
+ struct ast_vm_user *vmu,
+ const char* event_name,
+ const char* actionid
+ )
+{
+ int new;
+ int old;
+
+ if((s == NULL) || (vmu == NULL) || (event_name == NULL) || (actionid == NULL)) {
+ ast_log(LOG_ERROR, "Wrong input parameter.");
+ return 0;
+ }
+
+ /* get mailbox count */
+ inboxcount(vmu->mailbox, &new, &old);
+
+ astman_append(s,
+ "Event: %s\r\n"
+ "%s"
+ "VMContext: %s\r\n"
+ "VoiceMailbox: %s\r\n"
+ "Fullname: %s\r\n"
+ "Email: %s\r\n"
+ "Pager: %s\r\n"
+ "ServerEmail: %s\r\n"
+ "FromString: %s\r\n"
+ "MailCommand: %s\r\n"
+ "Language: %s\r\n"
+ "TimeZone: %s\r\n"
+ "Callback: %s\r\n"
+ "Dialout: %s\r\n"
+ "UniqueID: %s\r\n"
+ "ExitContext: %s\r\n"
+ "SayDurationMinimum: %d\r\n"
+ "SayEnvelope: %s\r\n"
+ "SayCID: %s\r\n"
+ "AttachMessage: %s\r\n"
+ "AttachmentFormat: %s\r\n"
+ "DeleteMessage: %s\r\n"
+ "VolumeGain: %.2f\r\n"
+ "CanReview: %s\r\n"
+ "CallOperator: %s\r\n"
+ "MaxMessageCount: %d\r\n"
+ "MaxMessageLength: %d\r\n"
+ "NewMessageCount: %d\r\n"
+ "OldMessageCount: %d\r\n"
+#ifdef IMAP_STORAGE
+ "IMAPUser: %s\r\n"
+ "IMAPServer: %s\r\n"
+ "IMAPPort: %s\r\n"
+ "IMAPFlags: %s\r\n"
+#endif
+ "\r\n",
+
+ event_name,
+ actionid,
+ vmu->context,
+ vmu->mailbox,
+ vmu->fullname,
+ vmu->email,
+ vmu->pager,
+ ast_strlen_zero(vmu->serveremail) ? serveremail : vmu->serveremail,
+ ast_strlen_zero(vmu->fromstring) ? fromstring : vmu->fromstring,
+ mailcmd,
+ vmu->language,
+ vmu->zonetag,
+ vmu->callback,
+ vmu->dialout,
+ vmu->uniqueid,
+ vmu->exit,
+ vmu->saydurationm,
+ ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
+ ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
+ ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
+ vmu->attachfmt,
+ ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
+ vmu->volgain,
+ ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
+ ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
+ vmu->maxmsg,
+ vmu->maxsecs,
+ new,
+ old
+#ifdef IMAP_STORAGE
+ ,
+ vmu->imapuser,
+ vmu->imapserver,
+ vmu->imapport,
+ vmu->imapflags
+#endif
+ );
+
+ return 1;
+
+}
+
static int manager_voicemail_refresh(struct mansession *s, const struct message *m)
{
const char *context = astman_get_header(m, "Context");
@@ -13258,6 +13376,51 @@ static int manager_voicemail_refresh(struct mansession *s, const struct message
return RESULT_SUCCESS;
}
+static int manager_status_voicemail_user(struct mansession *s, const struct message *m)
+{
+ struct ast_vm_user *vmu = NULL;
+ const char *id = astman_get_header(m, "ActionID");
+ char actionid[128];
+ struct ast_vm_user svm;
+ int ret;
+
+ const char *context = astman_get_header(m, "Context");
+ const char *mailbox = astman_get_header(m, "Mailbox");
+
+ if ((ast_strlen_zero(context) || ast_strlen_zero(mailbox))) {
+ astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters.");
+ return RESULT_SUCCESS;
+ }
+
+ actionid[0] = '\0';
+ if (!ast_strlen_zero(id)) {
+ snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id);
+ }
+
+ /* find user */
+ memset(&svm, 0, sizeof(svm));
+ vmu = find_user(&svm, context, mailbox);
+ if (!vmu) {
+ /* could not find it */
+ astman_send_ack(s, m, "There is no voicemail user of the given info.");
+ return RESULT_SUCCESS;
+ }
+
+ astman_send_listack(s, m, "Voicemail user detail will follow", "start");
+
+ /* append vmu info event */
+ ret = append_vmu_info_astman(s, vmu, "VoicemailUserDetail", actionid);
+ free_user(vmu);
+ if(ret == 0) {
+ ast_log(LOG_ERROR, "Could not append voicemail user info.");
+ }
+
+ astman_send_list_complete_start(s, m, "VoicemailUserDetailComplete", 1);
+ astman_send_list_complete_end(s);
+
+ return RESULT_SUCCESS;
+}
+
/*! \brief Manager list voicemail users command */
static int manager_list_voicemail_users(struct mansession *s, const struct message *m)
{
@@ -13265,6 +13428,7 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa
const char *id = astman_get_header(m, "ActionID");
char actionid[128];
int num_users = 0;
+ int ret;
actionid[0] = '\0';
if (!ast_strlen_zero(id)) {
@@ -13282,86 +13446,14 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa
astman_send_listack(s, m, "Voicemail user list will follow", "start");
AST_LIST_TRAVERSE(&users, vmu, list) {
- char dirname[256];
- int new, old;
- inboxcount(vmu->mailbox, &new, &old);
-
- make_dir(dirname, sizeof(dirname), vmu->context, vmu->mailbox, "INBOX");
- astman_append(s,
- "Event: VoicemailUserEntry\r\n"
- "%s"
- "VMContext: %s\r\n"
- "VoiceMailbox: %s\r\n"
- "Fullname: %s\r\n"
- "Email: %s\r\n"
- "Pager: %s\r\n"
- "ServerEmail: %s\r\n"
- "FromString: %s\r\n"
- "MailCommand: %s\r\n"
- "Language: %s\r\n"
- "TimeZone: %s\r\n"
- "Callback: %s\r\n"
- "Dialout: %s\r\n"
- "UniqueID: %s\r\n"
- "ExitContext: %s\r\n"
- "SayDurationMinimum: %d\r\n"
- "SayEnvelope: %s\r\n"
- "SayCID: %s\r\n"
- "AttachMessage: %s\r\n"
- "AttachmentFormat: %s\r\n"
- "DeleteMessage: %s\r\n"
- "VolumeGain: %.2f\r\n"
- "CanReview: %s\r\n"
- "CallOperator: %s\r\n"
- "MaxMessageCount: %d\r\n"
- "MaxMessageLength: %d\r\n"
- "NewMessageCount: %d\r\n"
- "OldMessageCount: %d\r\n"
-#ifdef IMAP_STORAGE
- "IMAPUser: %s\r\n"
- "IMAPServer: %s\r\n"
- "IMAPPort: %s\r\n"
- "IMAPFlags: %s\r\n"
-#endif
- "\r\n",
- actionid,
- vmu->context,
- vmu->mailbox,
- vmu->fullname,
- vmu->email,
- vmu->pager,
- ast_strlen_zero(vmu->serveremail) ? serveremail : vmu->serveremail,
- ast_strlen_zero(vmu->fromstring) ? fromstring : vmu->fromstring,
- mailcmd,
- vmu->language,
- vmu->zonetag,
- vmu->callback,
- vmu->dialout,
- vmu->uniqueid,
- vmu->exit,
- vmu->saydurationm,
- ast_test_flag(vmu, VM_ENVELOPE) ? "Yes" : "No",
- ast_test_flag(vmu, VM_SAYCID) ? "Yes" : "No",
- ast_test_flag(vmu, VM_ATTACH) ? "Yes" : "No",
- vmu->attachfmt,
- ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No",
- vmu->volgain,
- ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No",
- ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No",
- vmu->maxmsg,
- vmu->maxsecs,
- new,
- old
-#ifdef IMAP_STORAGE
- ,
- vmu->imapuser,
- vmu->imapserver,
- vmu->imapport,
- vmu->imapflags
-#endif
- );
+ /* append vmu info event */
+ ret = append_vmu_info_astman(s, vmu, "VoicemailUserEntry", actionid);
+ if(ret == 0) {
+ ast_log(LOG_ERROR, "Could not append voicemail user info.");
+ continue;
+ }
++num_users;
- }
+ }
astman_send_list_complete_start(s, m, "VoicemailUserEntryComplete", num_users);
astman_send_list_complete_end(s);
@@ -14891,6 +14983,7 @@ static int unload_module(void)
res |= ast_custom_function_unregister(&mailbox_exists_acf);
res |= ast_custom_function_unregister(&vm_info_acf);
res |= ast_manager_unregister("VoicemailUsersList");
+ res |= ast_manager_unregister("VoicemailUserStatus");
res |= ast_manager_unregister("VoicemailRefresh");
#ifdef TEST_FRAMEWORK
res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
@@ -14968,6 +15061,7 @@ static int load_module(void)
res |= ast_custom_function_register(&mailbox_exists_acf);
res |= ast_custom_function_register(&vm_info_acf);
res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users);
+ res |= ast_manager_register_xml("VoicemailUserStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_status_voicemail_user);
res |= ast_manager_register_xml("VoicemailRefresh", EVENT_FLAG_USER, manager_voicemail_refresh);
#ifdef TEST_FRAMEWORK
res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index e4e8fa586..69bcc187f 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -605,6 +605,11 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s
ast_party_id_copy(&ast_channel_caller(chan)->id, &session->id);
ast_party_id_copy(&ast_channel_caller(chan)->ani, &session->id);
+ if (!ast_strlen_zero(exten)) {
+ /* Set provided DNID on the new channel. */
+ ast_channel_dialed(chan)->number.str = ast_strdup(exten);
+ }
+
ast_channel_priority_set(chan, 1);
ast_channel_callgroup_set(chan, session->endpoint->pickup.callgroup);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index a829e2039..2d20442d0 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -593,6 +593,9 @@
<para>At least one variable pair must be specified.
<replaceable>name</replaceable>=<replaceable>value</replaceable></para>
</parameter>
+ <parameter name="Call-ID" required="false">
+ <para>When specified, SIP notity will be sent as a part of an existing dialog.</para>
+ </parameter>
</syntax>
<description>
<para>Sends a SIP Notify event.</para>
@@ -15591,11 +15594,13 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
{
const char *channame = astman_get_header(m, "Channel");
struct ast_variable *vars = astman_get_variables_order(m, ORDER_NATURAL);
+ const char *callid = astman_get_header(m, "Call-ID");
struct sip_pvt *p;
struct ast_variable *header, *var;
if (ast_strlen_zero(channame)) {
astman_send_error(s, m, "SIPNotify requires a channel name");
+ ast_variables_destroy(vars);
return 0;
}
@@ -15603,23 +15608,46 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
channame += 4;
}
- if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, 0))) {
- astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)");
- return 0;
- }
+ /* check if Call-ID header is set */
+ if (!ast_strlen_zero(callid)) {
+ struct sip_pvt tmp_dialog = {
+ .callid = callid,
+ };
- if (create_addr(p, channame, NULL, 0)) {
- /* Maybe they're not registered, etc. */
- dialog_unlink_all(p);
- dialog_unref(p, "unref dialog inside for loop" );
- /* sip_destroy(p); */
- astman_send_error(s, m, "Could not create address");
- return 0;
- }
+ p = ao2_find(dialogs, &tmp_dialog, OBJ_SEARCH_OBJECT);
+ if (!p) {
+ astman_send_error(s, m, "Call-ID not found");
+ ast_variables_destroy(vars);
+ return 0;
+ }
- /* Notify is outgoing call */
- ast_set_flag(&p->flags[0], SIP_OUTGOING);
- sip_notify_alloc(p);
+ if (!(p->notify)) {
+ sip_notify_alloc(p);
+ } else {
+ ast_variables_destroy(p->notify->headers);
+ }
+ } else {
+ if (!(p = sip_alloc(NULL, NULL, 0, SIP_NOTIFY, NULL, 0))) {
+ astman_send_error(s, m, "Unable to build sip pvt data for notify (memory/socket error)");
+ ast_variables_destroy(vars);
+ return 0;
+ }
+
+ if (create_addr(p, channame, NULL, 0)) {
+ /* Maybe they're not registered, etc. */
+ dialog_unlink_all(p);
+ dialog_unref(p, "unref dialog inside for loop" );
+ /* sip_destroy(p); */
+ astman_send_error(s, m, "Could not create address");
+ ast_variables_destroy(vars);
+ return 0;
+ }
+
+ /* Notify is outgoing call */
+ ast_set_flag(&p->flags[0], SIP_OUTGOING);
+ sip_notify_alloc(p);
+
+ }
p->notify->headers = header = ast_variable_new("Subscription-State", "terminated", "");
@@ -15636,14 +15664,19 @@ static int manager_sipnotify(struct mansession *s, const struct message *m)
}
}
- /* Now that we have the peer's address, set our ip and change callid */
- ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
- build_via(p);
+ if (ast_strlen_zero(callid)) {
+ /* Now that we have the peer's address, set our ip and change callid */
+ ast_sip_ouraddrfor(&p->sa, &p->ourip, p);
+ build_via(p);
- change_callid_pvt(p, NULL);
+ change_callid_pvt(p, NULL);
- sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
- transmit_invite(p, SIP_NOTIFY, 0, 2, NULL);
+ sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+ transmit_invite(p, SIP_NOTIFY, 0, 2, NULL);
+ } else {
+ sip_scheddestroy(p, SIP_TRANS_TIMEOUT);
+ transmit_invite(p, SIP_NOTIFY, 0, 1, NULL);
+ }
dialog_unref(p, "bump down the count of p since we're done with it.");
astman_send_ack(s, m, "Notify Sent");
@@ -30286,6 +30319,7 @@ static int sip_send_keepalive(const void *data)
struct sip_peer *peer = (struct sip_peer*) data;
int res = 0;
const char keepalive[] = "\r\n";
+ size_t count = sizeof(keepalive) - 1;
peer->keepalivesend = -1;
@@ -30296,12 +30330,12 @@ static int sip_send_keepalive(const void *data)
/* Send the packet out using the proper method for this peer */
if ((peer->socket.fd != -1) && (peer->socket.type == AST_TRANSPORT_UDP)) {
- res = ast_sendto(peer->socket.fd, keepalive, sizeof(keepalive), 0, &peer->addr);
+ res = ast_sendto(peer->socket.fd, keepalive, count, 0, &peer->addr);
} else if ((peer->socket.type & (AST_TRANSPORT_TCP | AST_TRANSPORT_TLS)) &&
peer->socket.tcptls_session) {
- res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, sizeof(keepalive));
+ res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, count);
} else if (peer->socket.type == AST_TRANSPORT_UDP) {
- res = ast_sendto(sipsock, keepalive, sizeof(keepalive), 0, &peer->addr);
+ res = ast_sendto(sipsock, keepalive, count, 0, &peer->addr);
}
if (res == -1) {
@@ -30315,7 +30349,7 @@ static int sip_send_keepalive(const void *data)
}
}
- if (res != sizeof(keepalive)) {
+ if (res != count) {
ast_log(LOG_WARNING, "sip_send_keepalive to %s returned %d: %s\n", ast_sockaddr_stringify(&peer->addr), res, strerror(errno));
}
@@ -30715,6 +30749,14 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_
}
}
+ /* If stripping the DNID left us with nothing, bail out */
+ if (ast_strlen_zero(tmp)) {
+ dialog_unlink_all(p);
+ dialog_unref(p, "unref dialog p from bad destination");
+ *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
+ return NULL;
+ }
+
/* Divvy up the items separated by slashes */
AST_NONSTANDARD_APP_ARGS(args, tmp, '/');
diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c
index 861edf72d..aa376f892 100644
--- a/channels/pjsip/dialplan_functions.c
+++ b/channels/pjsip/dialplan_functions.c
@@ -388,7 +388,7 @@
</enumlist>
</enum>
<enum name="target_uri">
- <para>The request URI of the <literal>INVITE</literal> request associated with the creation of this channel.</para>
+ <para>The contact URI where requests are sent.</para>
</enum>
<enum name="local_uri">
<para>The local URI.</para>
@@ -402,6 +402,10 @@
<enum name="remote_tag">
<para>Tag in To header</para>
</enum>
+ <enum name="request_uri">
+ <para>The request URI of the incoming <literal>INVITE</literal>
+ associated with the creation of this channel.</para>
+ </enum>
<enum name="t38state">
<para>The current state of any T.38 fax on this channel.</para>
<enumlist>
@@ -656,6 +660,27 @@ static int channel_read_rtcp(struct ast_channel *chan, const char *type, const c
return 0;
}
+static int print_escaped_uri(struct ast_channel *chan, const char *type,
+ pjsip_uri_context_e context, const void *uri, char *buf, size_t size)
+{
+ int res;
+ char *buf_copy;
+
+ res = pjsip_uri_print(context, uri, buf, size);
+ if (res < 0) {
+ ast_log(LOG_ERROR, "Channel %s: Unescaped %s too long for %d byte buffer\n",
+ ast_channel_name(chan), type, (int) size);
+
+ /* Empty buffer that likely is not terminated. */
+ buf[0] = '\0';
+ return -1;
+ }
+
+ buf_copy = ast_strdupa(buf);
+ ast_escape_quoted(buf_copy, buf, size);
+ return 0;
+}
+
/*!
* \internal \brief Handle reading signalling information
*/
@@ -664,6 +689,7 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
char *buf_copy;
pjsip_dialog *dlg;
+ int res = 0;
if (!channel) {
ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan));
@@ -689,25 +715,27 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const
return -1;
#endif
} else if (!strcmp(type, "target_uri")) {
- pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->target, buf, buflen);
- buf_copy = ast_strdupa(buf);
- ast_escape_quoted(buf_copy, buf, buflen);
+ res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI, dlg->target, buf,
+ buflen);
} else if (!strcmp(type, "local_uri")) {
- pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri, buf, buflen);
- buf_copy = ast_strdupa(buf);
- ast_escape_quoted(buf_copy, buf, buflen);
+ res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri,
+ buf, buflen);
} else if (!strcmp(type, "local_tag")) {
ast_copy_pj_str(buf, &dlg->local.info->tag, buflen);
buf_copy = ast_strdupa(buf);
ast_escape_quoted(buf_copy, buf, buflen);
} else if (!strcmp(type, "remote_uri")) {
- pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->remote.info->uri, buf, buflen);
- buf_copy = ast_strdupa(buf);
- ast_escape_quoted(buf_copy, buf, buflen);
+ res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR,
+ dlg->remote.info->uri, buf, buflen);
} else if (!strcmp(type, "remote_tag")) {
ast_copy_pj_str(buf, &dlg->remote.info->tag, buflen);
buf_copy = ast_strdupa(buf);
ast_escape_quoted(buf_copy, buf, buflen);
+ } else if (!strcmp(type, "request_uri")) {
+ if (channel->session->request_uri) {
+ res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI,
+ channel->session->request_uri, buf, buflen);
+ }
} else if (!strcmp(type, "t38state")) {
ast_copy_string(buf, t38state_to_string[channel->session->t38state], buflen);
} else if (!strcmp(type, "local_addr")) {
@@ -743,7 +771,7 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const
return -1;
}
- return 0;
+ return res;
}
/*! \brief Struct used to push function arguments to task processor */
diff --git a/configs/samples/iax.conf.sample b/configs/samples/iax.conf.sample
index ebe4d7fdc..c6da46179 100644
--- a/configs/samples/iax.conf.sample
+++ b/configs/samples/iax.conf.sample
@@ -576,12 +576,12 @@ inkeys=freeworlddialup
;
; Peers may also be specified, with a secret and a remote hostname.
;
-[demo]
-type=peer
-username=asterisk
-secret=supersecret
-host=216.207.245.47
-description=Demo System At Digium ; Description of this peer, as listed by
+;[demo]
+;type=peer
+;username=asterisk
+;secret=supersecret
+;host=192.168.10.10
+;description=My IAX2 Peer ; Description of this peer, as listed by
; 'iax2 show peers'
;sendani=no
;host=asterisk.linux-support.net
diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h
index a0fc9650e..732243f83 100644
--- a/include/asterisk/res_pjsip_session.h
+++ b/include/asterisk/res_pjsip_session.h
@@ -211,6 +211,8 @@ struct ast_sip_session {
unsigned int ended_while_deferred:1;
/*! DTMF mode to use with this session, from endpoint but can change */
enum ast_sip_dtmf_mode dtmf;
+ /*! Initial incoming INVITE Request-URI. NULL otherwise. */
+ pjsip_uri *request_uri;
};
typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);
diff --git a/main/asterisk.c b/main/asterisk.c
index 5c658d007..86f252c18 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -733,6 +733,27 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl
int totalswap = 0;
#if defined(HAVE_SYSINFO)
struct sysinfo sys_info;
+#elif defined(HAVE_SYSCTL)
+ static int pageshift;
+ struct vmtotal vmtotal;
+ struct timeval boottime;
+ time_t now;
+ int mib[2], pagesize, usedswap = 0;
+ size_t len;
+#endif
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show sysinfo";
+ e->usage =
+ "Usage: core show sysinfo\n"
+ " List current system information.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+#if defined(HAVE_SYSINFO)
sysinfo(&sys_info);
uptime = sys_info.uptime / 3600;
physmem = sys_info.totalram * sys_info.mem_unit;
@@ -741,12 +762,6 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl
freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
nprocs = sys_info.procs;
#elif defined(HAVE_SYSCTL)
- static int pageshift;
- struct vmtotal vmtotal;
- struct timeval boottime;
- time_t now;
- int mib[2], pagesize, usedswap = 0;
- size_t len;
/* calculate the uptime by looking at boottime */
time(&now);
mib[0] = CTL_KERN;
@@ -794,17 +809,6 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl
#endif
#endif
- switch (cmd) {
- case CLI_INIT:
- e->command = "core show sysinfo";
- e->usage =
- "Usage: core show sysinfo\n"
- " List current system information.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
ast_cli(a->fd, "\nSystem Statistics\n");
ast_cli(a->fd, "-----------------\n");
ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
diff --git a/menuselect/Makefile b/menuselect/Makefile
index 96c574eb8..c6a6facb6 100644
--- a/menuselect/Makefile
+++ b/menuselect/Makefile
@@ -64,7 +64,10 @@ all: $(ALL_TGTS)
$(OBJS) $(C_OBJS) $(N_OBJS) $(G_OBJS) $(M_OBJS): autoconfig.h menuselect.h
-makeopts autoconfig.h: autoconfig.h.in makeopts.in
+makeopts: makeopts.in
+autoconfig.h: autoconfig.h.in
+
+makeopts autoconfig.h:
@./configure $(CONFIGURE_SILENT)
@echo "****"
@echo "**** The configure script was just executed, so 'make' needs to be"
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index 2f29456ab..a9a90ac92 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -917,6 +917,12 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast
state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD;
} else if (!strcasecmp(var->value, "tlsv1")) {
state->tls.method = PJSIP_TLSV1_METHOD;
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
+ } else if (!strcasecmp(var->value, "tlsv1_1")) {
+ state->tls.method = PJSIP_TLSV1_1_METHOD;
+ } else if (!strcasecmp(var->value, "tlsv1_2")) {
+ state->tls.method = PJSIP_TLSV1_2_METHOD;
+#endif
} else if (!strcasecmp(var->value, "sslv2")) {
state->tls.method = PJSIP_SSLV2_METHOD;
} else if (!strcasecmp(var->value, "sslv3")) {
@@ -933,6 +939,10 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast
static const char *tls_method_map[] = {
[PJSIP_SSL_UNSPECIFIED_METHOD] = "unspecified",
[PJSIP_TLSV1_METHOD] = "tlsv1",
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO
+ [PJSIP_TLSV1_1_METHOD] = "tlsv1_1",
+ [PJSIP_TLSV1_2_METHOD] = "tlsv1_2",
+#endif
[PJSIP_SSLV2_METHOD] = "sslv2",
[PJSIP_SSLV3_METHOD] = "sslv3",
[PJSIP_SSLV23_METHOD] = "sslv23",
diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c
index 662166c89..fbe07d53d 100644
--- a/res/res_pjsip/pjsip_options.c
+++ b/res/res_pjsip/pjsip_options.c
@@ -1147,7 +1147,24 @@ static int qualify_and_schedule_cb_with_aor(void *obj, void *arg, int flags)
static int qualify_and_schedule_cb_without_aor(void *obj, void *arg, int flags)
{
- qualify_and_schedule_contact((struct ast_sip_contact *) obj);
+ /*
+ * These are really dynamic contacts. We need to retrieve the aor associated
+ * with the contact since it's possible some of the aor's fields were updated
+ * since last load.
+ */
+ struct ast_sip_contact *contact = obj;
+ struct ast_sip_aor *aor = ast_sip_location_retrieve_aor(contact->aor);
+
+ if (aor) {
+ qualify_and_schedule_cb_with_aor(obj, aor, flags);
+ ao2_ref(aor, -1);
+ } else {
+ ast_log(LOG_WARNING, "Unable to locate AOR for contact '%s'. Keeping old "
+ "associated settings: frequency=%d, timeout=%f, authenticate=%s\n",
+ contact->uri, contact->qualify_frequency, contact->qualify_timeout,
+ contact->authenticate_qualify ? "yes" : "no");
+ qualify_and_schedule_contact(contact);
+ }
return 0;
}
@@ -1175,32 +1192,21 @@ static int qualify_and_schedule_all_cb(void *obj, void *arg, int flags)
return 0;
}
-/*!
- * \internal
- * \brief Unschedule all existing contacts
- */
-static int unschedule_all_cb(void *obj, void *arg, int flags)
-{
- struct sched_data *data = obj;
-
- AST_SCHED_DEL_UNREF(sched, data->id, ao2_ref(data, -1));
-
- return CMP_MATCH;
-}
-
static void qualify_and_schedule_all(void)
{
- struct ast_variable *var = ast_variable_new("qualify_frequency >", "0", "");
struct ao2_container *aors;
struct ao2_container *contacts;
- if (!var) {
- return;
- }
- aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
- "aor", AST_RETRIEVE_FLAG_MULTIPLE, var);
+ /*
+ * It's possible that the AOR had some of it's fields updated prior to a
+ * reload. For instance qualifying could have been turned on or off by
+ * setting the qualify_frequency. Due to this we have to iterate through
+ * all contacts (static and dynamic), and not just ones where the frequency
+ * is greater than zero, updating any contact fields with the AOR's values.
+ */
- ao2_callback(sched_qualifies, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, unschedule_all_cb, NULL);
+ aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
+ "aor", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
if (aors) {
ao2_callback(aors, OBJ_NODATA, qualify_and_schedule_all_cb, NULL);
@@ -1208,14 +1214,11 @@ static void qualify_and_schedule_all(void)
}
contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
- "contact", AST_RETRIEVE_FLAG_MULTIPLE, var);
+ "contact", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
if (contacts) {
ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_without_aor, NULL);
ao2_ref(contacts, -1);
}
-
- ast_variables_destroy(var);
-
}
int ast_sip_format_contact_ami(void *obj, void *arg, int flags)
diff --git a/res/res_pjsip_dlg_options.c b/res/res_pjsip_dlg_options.c
index e2ed29a2c..de1ac97ef 100644
--- a/res/res_pjsip_dlg_options.c
+++ b/res/res_pjsip_dlg_options.c
@@ -99,6 +99,7 @@ static int unload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SIP OPTIONS in dialog handler",
+ .support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
.load_pri = AST_MODPRI_APP_DEPEND,
diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c
index f1f49d510..e5f12951f 100644
--- a/res/res_pjsip_outbound_publish.c
+++ b/res/res_pjsip_outbound_publish.c
@@ -1697,6 +1697,7 @@ static int reload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJSIP Outbound Publish Support",
+ .support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.reload = reload_module,
.unload = unload_module,
diff --git a/res/res_pjsip_phoneprov_provider.c b/res/res_pjsip_phoneprov_provider.c
index eef3a082f..7e082c4b5 100644
--- a/res/res_pjsip_phoneprov_provider.c
+++ b/res/res_pjsip_phoneprov_provider.c
@@ -413,6 +413,7 @@ static int reload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Phoneprov Provider",
+ .support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.reload = reload_module,
.unload = unload_module,
diff --git a/res/res_pjsip_publish_asterisk.c b/res/res_pjsip_publish_asterisk.c
index 72e1e4d7e..53ee60fe4 100644
--- a/res/res_pjsip_publish_asterisk.c
+++ b/res/res_pjsip_publish_asterisk.c
@@ -929,6 +929,7 @@ static int unload_module(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "PJSIP Asterisk Event PUBLISH Support",
+ .support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.reload = reload_module,
.unload = unload_module,
diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c
index a87758267..854ed1459 100644
--- a/res/res_pjsip_sdp_rtp.c
+++ b/res/res_pjsip_sdp_rtp.c
@@ -1253,7 +1253,8 @@ static int add_crypto_to_stream(struct ast_sip_session *session,
/* If this is an answer we need to use our current state, if it's an offer we need to use
* the configured value.
*/
- if (pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
+ if (session->inv_session->neg
+ && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) {
setup = dtls->get_setup(session_media->rtp);
} else {
setup = session->endpoint->media.rtp.dtls_cfg.default_setup;
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 781d3e4eb..958f2254b 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2818,6 +2818,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s
ast_copy_pj_str(domain, &sip_ruri->host, size);
pbx_builtin_setvar_helper(session->channel, "SIPDOMAIN", domain);
+ /*
+ * Save off the INVITE Request-URI in case it is
+ * needed: CHANNEL(pjsip,request_uri)
+ */
+ session->request_uri = pjsip_uri_clone(session->inv_session->pool, ruri);
+
return SIP_GET_DEST_EXTEN_FOUND;
}
@@ -3872,10 +3878,15 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru
if (!session->pending_media_state->topology || !ast_stream_topology_get_count(session->pending_media_state->topology)) {
/* We've encountered a situation where we have been told to create a local SDP but noone has given us any indication
- * of what kind of stream topology they would like. As a fallback we use the topology from the configured endpoint.
+ * of what kind of stream topology they would like. We try to not alter the current state of the SDP negotiation
+ * by using what is currently negotiated. If this is unavailable we fall back to what is configured on the endpoint.
*/
ast_stream_topology_free(session->pending_media_state->topology);
- session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
+ if (session->active_media_state->topology) {
+ session->pending_media_state->topology = ast_stream_topology_clone(session->active_media_state->topology);
+ } else {
+ session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology);
+ }
if (!session->pending_media_state->topology) {
return NULL;
}
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 16eb7dddf..bdc83301e 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -5169,7 +5169,6 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
unsigned int first_word;
/*! True if we have seen an acceptable SSRC to learn the remote RTCP address */
unsigned int ssrc_seen;
- int report_counter = 0;
struct ast_rtp_rtcp_report_block *report_block;
struct ast_frame *f = &ast_null_frame;
@@ -5413,7 +5412,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
}
return &ast_null_frame;
}
- rtcp_report->report_block[report_counter] = report_block;
+ rtcp_report->report_block[0] = report_block;
report_block->source_ssrc = ntohl(rtcpheader[i]);
report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff;
report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24);
@@ -5450,7 +5449,6 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0);
ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt);
}
- report_counter++;
}
/* If and when we handle more than one report block, this should occur outside
* this loop.
@@ -5475,9 +5473,9 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
/* There's always a single report block stored, here */
struct ast_rtp_rtcp_report *rtcp_report2;
report_block = transport_rtp->f.data.ptr + transport_rtp->f.datalen + sizeof(struct ast_rtp_rtcp_report_block *);
- memcpy(report_block, rtcp_report->report_block[report_counter-1], sizeof(struct ast_rtp_rtcp_report_block));
+ memcpy(report_block, rtcp_report->report_block[0], sizeof(struct ast_rtp_rtcp_report_block));
rtcp_report2 = (struct ast_rtp_rtcp_report *)transport_rtp->f.data.ptr;
- rtcp_report2->report_block[report_counter-1] = report_block;
+ rtcp_report2->report_block[0] = report_block;
transport_rtp->f.datalen += sizeof(struct ast_rtp_rtcp_report_block);
}
transport_rtp->f.offset = AST_FRIENDLY_OFFSET;