diff options
-rw-r--r-- | README-SERIOUSLY.bestpractices.md | 4 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | apps/app_voicemail.c | 252 | ||||
-rw-r--r-- | channels/chan_pjsip.c | 5 | ||||
-rw-r--r-- | channels/chan_sip.c | 92 | ||||
-rw-r--r-- | channels/pjsip/dialplan_functions.c | 50 | ||||
-rw-r--r-- | configs/samples/iax.conf.sample | 12 | ||||
-rw-r--r-- | include/asterisk/res_pjsip_session.h | 2 | ||||
-rw-r--r-- | main/asterisk.c | 38 | ||||
-rw-r--r-- | menuselect/Makefile | 5 | ||||
-rw-r--r-- | res/res_pjsip/config_transport.c | 10 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_options.c | 53 | ||||
-rw-r--r-- | res/res_pjsip_dlg_options.c | 1 | ||||
-rw-r--r-- | res/res_pjsip_outbound_publish.c | 1 | ||||
-rw-r--r-- | res/res_pjsip_phoneprov_provider.c | 1 | ||||
-rw-r--r-- | res/res_pjsip_publish_asterisk.c | 1 | ||||
-rw-r--r-- | res/res_pjsip_sdp_rtp.c | 3 | ||||
-rw-r--r-- | res/res_pjsip_session.c | 15 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 8 |
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 @@ -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; |