Newer
Older
Kevin P. Fleming
committed
/*
* Asterisk -- An open source telephony toolkit.
* Copyright (C) 1999 - 2012, Digium, Inc.
* Mark Spencer <markster@digium.com>
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Implementation of Session Initiation Protocol
*
* \author Mark Spencer <markster@digium.com>
*
* See Also:
* \arg \ref AstCREDITS
*
* Implementation of RFC 3261 - without S/MIME, and experimental TCP and TLS support
* Configuration file \link Config_sip sip.conf \endlink
* ********** IMPORTANT *
* \note TCP/TLS support is EXPERIMENTAL and WILL CHANGE. This applies to configuration
* settings, dialplan commands and dialplans apps/functions
Olle Johansson
committed
* See \ref sip_tcp_tls
* ******** General TODO:s
* \todo Better support of forking
* \todo VIA branch tag transaction checking
* \todo Transaction support
Olle Johansson
committed
* ******** Wishlist: Improvements
* - Support of SIP domains for devices, so that we match on username\@domain in the From: header
Olle Johansson
committed
* - Connect registrations with a specific device on the incoming call. It's not done
*
* \ingroup channel_drivers
Olle Johansson
committed
*
* \par Overview of the handling of SIP sessions
* The SIP channel handles several types of SIP sessions, or dialogs,
* not all of them being "telephone calls".
* - Incoming calls that will be sent to the PBX core
* - Outgoing calls, generated by the PBX
* - SIP subscriptions and notifications of states and voicemail messages
* - SIP registrations, both inbound and outbound
* - SIP peer management (peerpoke, OPTIONS)
* - SIP text messages
*
* In the SIP channel, there's a list of active SIP dialogs, which includes
* all of these when they are active. "sip show channels" in the CLI will
* show most of these, excluding subscriptions which are shown by
* "sip show subscriptions"
*
* \par incoming packets
* Incoming packets are received in the monitoring thread, then handled by
* sipsock_read() for udp only. In tcp, packets are read by the tcp_helper thread.
* sipsock_read() function parses the packet and matches an existing
* sipsock_read sends the packet to handle_incoming(), that parses a bit more.
* If it is a response to an outbound request, the packet is sent to handle_response().
* If it is a request, handle_incoming() sends it to one of a list of functions
* depending on the request type - INVITE, OPTIONS, REFER, BYE, CANCEL etc
* sipsock_read locks the ast_channel if it exists (an active call) and
* unlocks it after we have processed the SIP message.
*
* A new INVITE is sent to handle_request_invite(), that will end up
* starting a new channel in the PBX, the new channel after that executing
* in a separate channel thread. This is an incoming "call".
* When the call is answered, either by a bridged channel or the PBX itself
* the sip_answer() function is called.
*
* The actual media - Video or Audio - is mostly handled by the RTP subsystem
* \par Outbound calls
* Outbound calls are set up by the PBX through the sip_request_call()
* function. After that, they are activated by sip_call().
* \par Hanging up
* The PBX issues a hangup on both incoming and outgoing calls through
* the sip_hangup() function
/*! \li \ref chan_sip.c uses configuration files \ref sip.conf and \ref sip_notify.conf
* \addtogroup configuration_file
*/
/*! \page sip.conf sip.conf
* \verbinclude sip.conf.sample
*/
/*! \page sip_notify.conf sip_notify.conf
* \verbinclude sip_notify.conf.sample
*/
* \page sip_tcp_tls SIP TCP and TLS support
Olle Johansson
committed
* \par tcpfixes TCP implementation changes needed
* \todo Fix TCP/TLS handling in dialplan, SRV records, transfers and much more
* \todo Save TCP/TLS sessions in registry
* If someone registers a SIPS uri, this forces us to set up a TLS connection back.
* \todo Add TCP/TLS information to function SIPPEER and CHANNEL function
Olle Johansson
committed
* \todo If tcpenable=yes, we must open a TCP socket on the same address as the IP for UDP.
* The tcpbindaddr config option should only be used to open ADDITIONAL ports
* So we should propably go back to
Olle Johansson
committed
* bindaddr= the default address to bind to. If tcpenable=yes, then bind this to both udp and TCP
* if tlsenable=yes, open TLS port (provided we also have cert)
* tcpbindaddr = extra address for additional TCP connections
* tlsbindaddr = extra address for additional TCP/TLS connections
* udpbindaddr = extra address for additional UDP connections
* These three options should take multiple IP/port pairs
* Note: Since opening additional listen sockets is a *new* feature we do not have today
* the XXXbindaddr options needs to be disabled until we have support for it
Olle Johansson
committed
* \todo re-evaluate the transport= setting in sip.conf. This is right now not well
* thought of. If a device in sip.conf contacts us via TCP, we should not switch transport,
* even if udp is the configured first transport.
Olle Johansson
committed
* \todo Be prepared for one outbound and another incoming socket per pvt. This applies
* specially to communication with other peers (proxies).
* \todo We need to test TCP sessions with SIP proxies and in regards
* to the SIP outbound specs.
* \todo ;transport=tls was deprecated in RFC3261 and should not be used at all. See section 26.2.2.
Olle Johansson
committed
*
* \todo If the message is smaller than the given Content-length, the request should get a 400 Bad request
* message. If it's a response, it should be dropped. (RFC 3261, Section 18.3)
* \todo Since we have had multidomain support in Asterisk for quite a while, we need to support
* multiple domains in our TLS implementation, meaning one socket and one cert per domain
* \todo Selection of transport for a request needs to be done after we've parsed all route headers,
* also considering outbound proxy options.
* First request: Outboundproxy, routes, (reg contact or URI. If URI doesn't have port: DNS naptr, srv, AAA)
* Intermediate requests: Outboundproxy(only when forced), routes, contact/uri
* DNS naptr support is crucial. A SIP uri might lead to a TLS connection.
* Also note that due to outbound proxy settings, a SIPS uri might have to be sent on UDP (not to recommend though)
* \todo Default transports are set to UDP, which cause the wrong behaviour when contacting remote
* devices directly from the dialplan. UDP is only a fallback if no other method works,
* in order to be compatible with RFC2543 (SIP/1.0) devices. For transactions that exceed the
* MTU (like INIVTE with video, audio and RTT) TCP should be preferred.
Olle Johansson
committed
*
* When dialling unconfigured peers (with no port number) or devices in external domains
* NAPTR records MUST be consulted to find configured transport. If they are not found,
* SRV records for both TCP and UDP should be checked. If there's a record for TCP, use that.
* If there's no record for TCP, then use UDP as a last resort. If there's no SRV records,
* \note this only applies if there's no outbound proxy configured for the session. If an outbound
* proxy is configured, these procedures might apply for locating the proxy and determining
* the transport to use for communication with the proxy.
* \par Other bugs to fix ----
* __set_address_from_contact(const char *fullcontact, struct sockaddr_in *sin, int tcp)
* - sets TLS port as default for all TCP connections, unless other port is given in contact.
* parse_register_contact(struct sip_pvt *pvt, struct sip_peer *peer, struct sip_request *req)
* - assumes that the contact the UA registers is using the same transport as the REGISTER request, which is
Olle Johansson
committed
* a bad guess.
* - Does not save any information about TCP/TLS connected devices, which is a severe BUG, as discussed on the mailing list.
* get_destination(struct sip_pvt *p, struct sip_request *oreq)
* - Doesn't store the information that we got an incoming SIPS request in the channel, so that
* we can require a secure signalling path OUT of Asterisk (on SIP or IAX2). Possibly, the call should
* fail on in-secure signalling paths if there's no override in our configuration. At least, provide a
* channel variable in the dialplan.
* get_refer_info(struct sip_pvt *transferer, struct sip_request *outgoing_req)
* - As above, if we have a SIPS: uri in the refer-to header
* - Does not check transport in refer_to uri.
Olle Johansson
committed
*/
Jason Parker
committed
/*** MODULEINFO
<use type="module">res_crypto</use>
Joshua Colp
committed
<use type="module">res_http_websocket</use>
<support_level>extended</support_level>
Jason Parker
committed
***/
Russell Bryant
committed
/*! \page sip_session_timers SIP Session Timers in Asterisk Chan_sip
The SIP Session-Timers is an extension of the SIP protocol that allows end-points and proxies to
refresh a session periodically. The sessions are kept alive by sending a RE-INVITE or UPDATE
request at a negotiated interval. If a session refresh fails then all the entities that support Session-
Timers clear their internal session state. In addition, UAs generate a BYE request in order to clear
the state in the proxies and the remote UA (this is done for the benefit of SIP entities in the path
that do not support Session-Timers).
The Session-Timers can be configured on a system-wide, per-user, or per-peer basis. The peruser/
per-peer settings override the global settings. The following new parameters have been
added to the sip.conf file.
session-timers=["accept", "originate", "refuse"]
session-expires=[integer]
session-minse=[integer]
session-refresher=["uas", "uac"]
The session-timers parameter in sip.conf defines the mode of operation of SIP session-timers feature in
Asterisk. The Asterisk can be configured in one of the following three modes:
1. Accept :: In the "accept" mode, the Asterisk server honors session-timers requests
made by remote end-points. A remote end-point can request Asterisk to engage
session-timers by either sending it an INVITE request with a "Supported: timer"
header in it or by responding to Asterisk's INVITE with a 200 OK that contains
Session-Expires: header in it. In this mode, the Asterisk server does not
Russell Bryant
committed
request session-timers from remote end-points. This is the default mode.
2. Originate :: In the "originate" mode, the Asterisk server requests the remote
Russell Bryant
committed
end-points to activate session-timers in addition to honoring such requests
made by the remote end-pints. In order to get as much protection as possible
against hanging SIP channels due to network or end-point failures, Asterisk
resends periodic re-INVITEs even if a remote end-point does not support
the session-timers feature.
3. Refuse :: In the "refuse" mode, Asterisk acts as if it does not support session-
timers for inbound or outbound requests. If a remote end-point requests
session-timers in a dialog, then Asterisk ignores that request unless it's
noted as a requirement (Require: header), in which case the INVITE is
Russell Bryant
committed
rejected with a 420 Bad Extension response.
*/
Kevin P. Fleming
committed
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
Kevin P. Fleming
committed
#include <signal.h>
#include <sys/signal.h>
#include <regex.h>
Kevin P. Fleming
committed
#include "asterisk/paths.h" /* need ast_config_AST_SYSTEM_NAME */
Kevin P. Fleming
committed
#include "asterisk/lock.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/udptl.h"
Kevin P. Fleming
committed
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/pickup.h"
#include "asterisk/parking.h"
Kevin P. Fleming
committed
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj2.h"
Kevin P. Fleming
committed
#include "asterisk/dnsmgr.h"
Kevin P. Fleming
committed
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
Olle Johansson
committed
#include "asterisk/localtime.h"
Russell Bryant
committed
#include "asterisk/abstract_jb.h"
#include "asterisk/threadstorage.h"
#include "asterisk/translate.h"
Russell Bryant
committed
#include "asterisk/ast_version.h"
#include "asterisk/data.h"
#include "asterisk/message.h"
Tilghman Lesher
committed
#include "sip/include/globals.h"
#include "sip/include/config_parser.h"
#include "sip/include/reqresp_parser.h"
#include "sip/include/sip_utils.h"
#include "asterisk/sdp_srtp.h"
#include "asterisk/ccss.h"
#include "asterisk/xml.h"
Tilghman Lesher
committed
#include "sip/include/dialog.h"
#include "sip/include/dialplan_functions.h"
#include "sip/include/security_events.h"
#include "sip/include/route.h"
#include "asterisk/sip_api.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_system.h"
#include "asterisk/features_config.h"
David M. Lee
committed
#include "asterisk/http_websocket.h"
#include "asterisk/format_cache.h"
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
/*** DOCUMENTATION
<application name="SIPDtmfMode" language="en_US">
<synopsis>
Change the dtmfmode for a SIP call.
</synopsis>
<syntax>
<parameter name="mode" required="true">
<enumlist>
<enum name="inband" />
<enum name="info" />
<enum name="rfc2833" />
</enumlist>
</parameter>
</syntax>
<description>
<para>Changes the dtmfmode for a SIP call.</para>
</description>
</application>
<application name="SIPAddHeader" language="en_US">
<synopsis>
Add a SIP header to the outbound call.
</synopsis>
<syntax argsep=":">
<parameter name="Header" required="true" />
<parameter name="Content" required="true" />
</syntax>
<description>
<para>Adds a header to a SIP call placed with DIAL.</para>
<para>Remember to use the X-header if you are adding non-standard SIP
headers, like <literal>X-Asterisk-Accountcode:</literal>. Use this with care.
Adding the wrong headers may jeopardize the SIP dialog.</para>
<para>Always returns <literal>0</literal>.</para>
</description>
</application>
<application name="SIPRemoveHeader" language="en_US">
<synopsis>
Remove SIP headers previously added with SIPAddHeader
</synopsis>
<syntax>
<parameter name="Header" required="false" />
</syntax>
<description>
<para>SIPRemoveHeader() allows you to remove headers which were previously
added with SIPAddHeader(). If no parameter is supplied, all previously added
headers will be removed. If a parameter is supplied, only the matching headers
will be removed.</para>
<para>For example you have added these 2 headers:</para>
<para>SIPAddHeader(P-Asserted-Identity: sip:foo@bar);</para>
<para>SIPAddHeader(P-Preferred-Identity: sip:bar@foo);</para>
<para></para>
<para>// remove all headers</para>
<para>SIPRemoveHeader();</para>
<para>// remove all P- headers</para>
<para>SIPRemoveHeader(P-);</para>
<para>// remove only the PAI header (note the : at the end)</para>
<para>SIPRemoveHeader(P-Asserted-Identity:);</para>
<para></para>
<para>Always returns <literal>0</literal>.</para>
</description>
</application>
<application name="SIPSendCustomINFO" language="en_US">
<synopsis>
Send a custom INFO frame on specified channels.
</synopsis>
<syntax>
<parameter name="Data" required="true" />
<parameter name="UserAgent" required="false" />
</syntax>
<description>
<para>SIPSendCustomINFO() allows you to send a custom INFO message on all
active SIP channels or on channels with the specified User Agent. This
application is only available if TEST_FRAMEWORK is defined.</para>
</description>
</application>
<function name="SIP_HEADER" language="en_US">
<synopsis>
Gets the specified SIP header from an incoming INVITE message.
</synopsis>
<syntax>
<parameter name="name" required="true" />
<parameter name="number">
<para>If not specified, defaults to <literal>1</literal>.</para>
</parameter>
</syntax>
<description>
<para>Since there are several headers (such as Via) which can occur multiple
times, SIP_HEADER takes an optional second argument to specify which header with
that name to retrieve. Headers start at offset <literal>1</literal>.</para>
Matthew Jordan
committed
<para>Please observe that contents of the SDP (an attachment to the
SIP request) can't be accessed with this function.</para>
</description>
</function>
<function name="SIPPEER" language="en_US">
<synopsis>
Gets SIP peer information.
</synopsis>
<syntax>
<parameter name="peername" required="true" />
<parameter name="item">
<enumlist>
<enum name="ip">
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
</enum>
<enum name="port">
<para>The port number.</para>
</enum>
<enum name="mailbox">
<para>The configured mailbox.</para>
</enum>
<enum name="context">
<para>The configured context.</para>
</enum>
<enum name="expire">
<para>The epoch time of the next expire.</para>
</enum>
<enum name="dynamic">
<para>Is it dynamic? (yes/no).</para>
</enum>
<enum name="callerid_name">
<para>The configured Caller ID name.</para>
</enum>
<enum name="callerid_num">
<para>The configured Caller ID number.</para>
</enum>
<enum name="callgroup">
<para>The configured Callgroup.</para>
</enum>
<enum name="pickupgroup">
<para>The configured Pickupgroup.</para>
</enum>
<enum name="namedcallgroup">
<para>The configured Named Callgroup.</para>
</enum>
<enum name="namedpickupgroup">
<para>The configured Named Pickupgroup.</para>
</enum>
<enum name="codecs">
<para>The configured codecs.</para>
</enum>
<enum name="status">
<para>Status (if qualify=yes).</para>
</enum>
<enum name="regexten">
<para>Extension activated at registration.</para>
</enum>
<enum name="limit">
<para>Call limit (call-limit).</para>
</enum>
<enum name="busylevel">
<para>Configured call level for signalling busy.</para>
</enum>
<enum name="curcalls">
<para>Current amount of calls. Only available if call-limit is set.</para>
</enum>
<enum name="language">
<para>Default language for peer.</para>
</enum>
<enum name="accountcode">
<para>Account code for this peer.</para>
</enum>
<enum name="useragent">
<para>Current user agent header used by peer.</para>
Olle Johansson
committed
<enum name="maxforwards">
<para>The value used for SIP loop prevention in outbound requests</para>
</enum>
<enum name="chanvar[name]">
<para>A channel variable configured with setvar for this peer.</para>
</enum>
<enum name="codec[x]">
<para>Preferred codec index number <replaceable>x</replaceable> (beginning with zero).</para>
</enum>
</enumlist>
</parameter>
</syntax>
</function>
<function name="CHECKSIPDOMAIN" language="en_US">
<synopsis>
Checks if domain is a local domain.
</synopsis>
<syntax>
<parameter name="domain" required="true" />
</syntax>
<description>
<para>This function checks if the <replaceable>domain</replaceable> in the argument is configured
as a local SIP domain that this Asterisk server is configured to handle.
Returns the domain name if it is locally handled, otherwise an empty string.
Check the <literal>domain=</literal> configuration in <filename>sip.conf</filename>.</para>
</description>
</function>
<manager name="SIPpeers" language="en_US">
<synopsis>
List SIP peers (text format).
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
</syntax>
<description>
<para>Lists SIP peers in text format with details on current status.
<literal>Peerlist</literal> will follow as separate events, followed by a final event called
<literal>PeerlistComplete</literal>.</para>
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
</description>
</manager>
<manager name="SIPshowpeer" language="en_US">
<synopsis>
show SIP peer (text format).
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
<parameter name="Peer" required="true">
<para>The peer name you want to check.</para>
</parameter>
</syntax>
<description>
<para>Show one SIP peer with details on current status.</para>
</description>
</manager>
<manager name="SIPqualifypeer" language="en_US">
<synopsis>
Qualify SIP peers.
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
<parameter name="Peer" required="true">
<para>The peer name you want to qualify.</para>
</parameter>
</syntax>
<description>
<para>Qualify a SIP peer.</para>
</description>
<see-also>
<ref type="managerEvent">SIPQualifyPeerDone</ref>
</see-also>
</manager>
<manager name="SIPshowregistry" language="en_US">
<synopsis>
Show SIP registrations (text format).
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
</syntax>
<description>
<para>Lists all registration requests and status. Registrations will follow as separate
events followed by a final event called <literal>RegistrationsComplete</literal>.</para>
</description>
</manager>
<manager name="SIPnotify" language="en_US">
<synopsis>
Send a SIP notify.
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
<parameter name="Channel" required="true">
<para>Peer to receive the notify.</para>
</parameter>
<parameter name="Variable" required="true">
<para>At least one variable pair must be specified.
<replaceable>name</replaceable>=<replaceable>value</replaceable></para>
</parameter>
</syntax>
<description>
<para>Sends a SIP Notify event.</para>
<para>All parameters for this event must be specified in the body of this request
via multiple <literal>Variable: name=value</literal> sequences.</para>
</description>
</manager>
<manager name="SIPpeerstatus" language="en_US">
<synopsis>
Show the status of one or all of the sip peers.
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
<parameter name="Peer" required="false">
<para>The peer name you want to check.</para>
</parameter>
</syntax>
<description>
<para>Retrieves the status of one or all of the sip peers. If no peer name is specified, status
for all of the sip peers will be retrieved.</para>
</description>
</manager>
<info name="SIPMessageFromInfo" language="en_US" tech="SIP">
<para>The <literal>from</literal> parameter can be a configured peer name
or in the form of "display-name" <URI>.</para>
</info>
<info name="SIPMessageToInfo" language="en_US" tech="SIP">
<para>Specifying a prefix of <literal>sip:</literal> will send the
message as a SIP MESSAGE request.</para>
</info>
<managerEvent language="en_US" name="SIPQualifyPeerDone">
<managerEventInstance class="EVENT_FLAG_CALL">
<synopsis>Raised when SIPQualifyPeer has finished qualifying the specified peer.</synopsis>
<syntax>
<parameter name="Peer">
<para>The name of the peer.</para>
</parameter>
<parameter name="ActionID">
<para>This is only included if an ActionID Header was sent with the action request, in which case it will be that ActionID.</para>
</parameter>
</syntax>
<see-also>
<ref type="manager">SIPqualifypeer</ref>
</see-also>
</managerEventInstance>
</managerEvent>
<managerEvent language="en_US" name="SessionTimeout">
<managerEventInstance class="EVENT_FLAG_CALL">
<synopsis>Raised when a SIP session times out.</synopsis>
<syntax>
<parameter name="Source">
<para>The source of the session timeout.</para>
<enumlist>
<enum name="RTPTimeout" />
<enum name="SIPSessionTimer" />
</enumlist>
</parameter>
</syntax>
</managerEventInstance>
</managerEvent>
static int min_expiry = DEFAULT_MIN_EXPIRY; /*!< Minimum accepted registration time */
static int max_expiry = DEFAULT_MAX_EXPIRY; /*!< Maximum accepted registration time */
static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
Mark Michelson
committed
static int min_subexpiry = DEFAULT_MIN_EXPIRY; /*!< Minimum accepted subscription time */
static int max_subexpiry = DEFAULT_MAX_EXPIRY; /*!< Maximum accepted subscription time */
static int mwi_expiry = DEFAULT_MWI_EXPIRY;
static int unauth_sessions = 0;
static int authlimit = DEFAULT_AUTHLIMIT;
static int authtimeout = DEFAULT_AUTHTIMEOUT;
/*! \brief Global jitterbuffer configuration - by default, jb is disabled
* \note Values shown here match the defaults shown in sip.conf.sample */
Russell Bryant
committed
static struct ast_jb_conf default_jbconf =
{
.max_size = 200,
.resync_threshold = 1000,
.impl = "fixed",
.target_extra = 40,
Russell Bryant
committed
};
static struct ast_jb_conf global_jbconf; /*!< Global jitterbuffer configuration */
static const char config[] = "sip.conf"; /*!< Main configuration file */
static const char notify_config[] = "sip_notify.conf"; /*!< Configuration file for sending Notify with CLI commands to reconfigure or reboot phones */
Olle Johansson
committed
Olle Johansson
committed
/*! \brief Readable descriptions of device states.
Olle Johansson
committed
static const struct invstate2stringtable {
const enum invitestates state;
Olle Johansson
committed
} invitestate2string[] = {
{INV_NONE, "None" },
{INV_CALLING, "Calling (Trying)"},
{INV_PROCEEDING, "Proceeding "},
{INV_EARLY_MEDIA, "Early media"},
{INV_COMPLETED, "Completed (done)"},
{INV_CONFIRMED, "Confirmed (up)"},
{INV_TERMINATED, "Done"},
{INV_CANCELLED, "Cancelled"}
};
/*! \brief Subscription types that we support. We support
* - dialoginfo updates (really device status, not dialog info as was the original intent of the standard)
* - SIMPLE presence used for device status
* - Voicemail notification subscriptions
*/
Kevin P. Fleming
committed
static const struct cfsubscription_types {
enum subscriptiontype type;
const char * const event;
const char * const mediatype;
const char * const text;
} subscription_types[] = {
/* RFC 4235: SIP Dialog event package */
Kevin P. Fleming
committed
{ DIALOG_INFO_XML, "dialog", "application/dialog-info+xml", "dialog-info+xml" },
{ CPIM_PIDF_XML, "presence", "application/cpim-pidf+xml", "cpim-pidf+xml" }, /* RFC 3863 */
{ PIDF_XML, "presence", "application/pidf+xml", "pidf+xml" }, /* RFC 3863 */
Kevin P. Fleming
committed
{ XPIDF_XML, "presence", "application/xpidf+xml", "xpidf+xml" }, /* Pre-RFC 3863 with MS additions */
{ MWI_NOTIFICATION, "message-summary", "application/simple-message-summary", "mwi" } /* RFC 3842: Mailbox notification */
Kevin P. Fleming
committed
};
/*! \brief The core structure to setup dialogs. We parse incoming messages by using
* structure and then route the messages according to the type.
* \note Note that sip_methods[i].id == i must hold or the code breaks
static const struct cfsip_methods {
Kevin P. Fleming
committed
enum sipmethod id;
int need_rtp; /*!< when this is the 'primary' use for a pvt structure, does it need RTP? */
Russell Bryant
committed
enum can_create_dialog can_create;
} sip_methods[] = {
{ SIP_UNKNOWN, RTP, "-UNKNOWN-",CAN_CREATE_DIALOG },
{ SIP_RESPONSE, NO_RTP, "SIP/2.0", CAN_NOT_CREATE_DIALOG },
{ SIP_REGISTER, NO_RTP, "REGISTER", CAN_CREATE_DIALOG },
{ SIP_OPTIONS, NO_RTP, "OPTIONS", CAN_CREATE_DIALOG },
{ SIP_NOTIFY, NO_RTP, "NOTIFY", CAN_CREATE_DIALOG },
{ SIP_INVITE, RTP, "INVITE", CAN_CREATE_DIALOG },
{ SIP_ACK, NO_RTP, "ACK", CAN_NOT_CREATE_DIALOG },
{ SIP_PRACK, NO_RTP, "PRACK", CAN_NOT_CREATE_DIALOG },
{ SIP_BYE, NO_RTP, "BYE", CAN_NOT_CREATE_DIALOG },
{ SIP_REFER, NO_RTP, "REFER", CAN_CREATE_DIALOG },
{ SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE",CAN_CREATE_DIALOG },
{ SIP_MESSAGE, NO_RTP, "MESSAGE", CAN_CREATE_DIALOG },
{ SIP_UPDATE, NO_RTP, "UPDATE", CAN_NOT_CREATE_DIALOG },
{ SIP_INFO, NO_RTP, "INFO", CAN_NOT_CREATE_DIALOG },
{ SIP_CANCEL, NO_RTP, "CANCEL", CAN_NOT_CREATE_DIALOG },
{ SIP_PUBLISH, NO_RTP, "PUBLISH", CAN_CREATE_DIALOG },
{ SIP_PING, NO_RTP, "PING", CAN_CREATE_DIALOG_UNSUPPORTED_METHOD }
Mark Michelson
committed
/*! \brief Diversion header reasons
*
* The core defines a bunch of constants used to define
* redirecting reasons. This provides a translation table
* between those and the strings which may be present in
* a SIP Diversion header
*/
static const struct sip_reasons {
enum AST_REDIRECTING_REASON code;
char * const text;
} sip_reason_table[] = {
{ AST_REDIRECTING_REASON_UNKNOWN, "unknown" },
{ AST_REDIRECTING_REASON_USER_BUSY, "user-busy" },
{ AST_REDIRECTING_REASON_NO_ANSWER, "no-answer" },
{ AST_REDIRECTING_REASON_UNAVAILABLE, "unavailable" },
{ AST_REDIRECTING_REASON_UNCONDITIONAL, "unconditional" },
{ AST_REDIRECTING_REASON_TIME_OF_DAY, "time-of-day" },
{ AST_REDIRECTING_REASON_DO_NOT_DISTURB, "do-not-disturb" },
{ AST_REDIRECTING_REASON_DEFLECTION, "deflection" },
{ AST_REDIRECTING_REASON_FOLLOW_ME, "follow-me" },
{ AST_REDIRECTING_REASON_OUT_OF_ORDER, "out-of-service" },
{ AST_REDIRECTING_REASON_AWAY, "away" },
{ AST_REDIRECTING_REASON_CALL_FWD_DTE, "unknown"},
{ AST_REDIRECTING_REASON_SEND_TO_VM, "send_to_vm"},
Mark Michelson
committed
};
/*! \name DefaultSettings
Default setttings are used as a channel setting and as a default when
configuring devices
static char default_language[MAX_LANGUAGE]; /*!< Default language setting for new channels */
static char default_callerid[AST_MAX_EXTENSION]; /*!< Default caller ID for sip messages */
static char default_mwi_from[80]; /*!< Default caller ID for MWI updates */
static char default_fromdomain[AST_MAX_EXTENSION]; /*!< Default domain on outound messages */
static int default_fromdomainport; /*!< Default domain port on outbound messages */
static char default_notifymime[AST_MAX_EXTENSION]; /*!< Default MIME media type for MWI notify messages */
static char default_vmexten[AST_MAX_EXTENSION]; /*!< Default From Username on MWI updates */
static int default_qualify; /*!< Default Qualify= setting */
static int default_keepalive; /*!< Default keepalive= setting */
Kevin P. Fleming
committed
static char default_mohinterpret[MAX_MUSICCLASS]; /*!< Global setting for moh class to use when put on hold */
static char default_mohsuggest[MAX_MUSICCLASS]; /*!< Global setting for moh class to suggest when putting
Kevin P. Fleming
committed
* a bridged channel on hold */
static char default_parkinglot[AST_MAX_CONTEXT]; /*!< Parkinglot */
static char default_engine[256]; /*!< Default RTP engine */
static int default_maxcallbitrate; /*!< Maximum bitrate for call */
Olle Johansson
committed
static char default_zone[MAX_TONEZONE_COUNTRY]; /*!< Default tone zone for channels created from the SIP driver */
static unsigned int default_transports; /*!< Default Transports (enum ast_transport) that are acceptable */
static unsigned int default_primary_transport; /*!< Default primary Transport (enum ast_transport) for outbound connections to devices */
static struct sip_settings sip_cfg; /*!< SIP configuration data.
\note in the future we could have multiple of these (per domain, per device group etc) */
Olle Johansson
committed
/*!< use this macro when ast_uri_decode is dependent on pedantic checking to be on. */
#define SIP_PEDANTIC_DECODE(str) \
if (sip_cfg.pedanticsipchecking && !ast_strlen_zero(str)) { \
ast_uri_decode(str, ast_uri_sip_user); \
static unsigned int chan_idx; /*!< used in naming sip channel */
static int global_match_auth_username; /*!< Match auth username if available instead of From: Default off. */
static int global_relaxdtmf; /*!< Relax DTMF */
static int global_prematuremediafilter; /*!< Enable/disable premature frames in a call (causing 183 early media) */
static int global_rtptimeout; /*!< Time out call if no RTP */
static int global_rtpholdtimeout; /*!< Time out call if no RTP during hold */
static int global_rtpkeepalive; /*!< Send RTP keepalives */
static int global_reg_timeout; /*!< Global time between attempts for outbound registrations */
static int global_regattempts_max; /*!< Registration attempts before giving up */
static int global_reg_retry_403; /*!< Treat 403 responses to registrations as 401 responses */
static int global_shrinkcallerid; /*!< enable or disable shrinking of caller id */
static int global_callcounter; /*!< Enable call counters for all devices. This is currently enabled by setting the peer
* call-limit to INT_MAX. When we remove the call-limit from the code, we can make it
* with just a boolean flag in the device structure */
static unsigned int global_tos_sip; /*!< IP type of service for SIP packets */
static unsigned int global_tos_audio; /*!< IP type of service for audio RTP packets */
static unsigned int global_tos_video; /*!< IP type of service for video RTP packets */
static unsigned int global_tos_text; /*!< IP type of service for text RTP packets */
static unsigned int global_cos_sip; /*!< 802.1p class of service for SIP packets */
static unsigned int global_cos_audio; /*!< 802.1p class of service for audio RTP packets */
static unsigned int global_cos_video; /*!< 802.1p class of service for video RTP packets */
static unsigned int global_cos_text; /*!< 802.1p class of service for text RTP packets */
static unsigned int recordhistory; /*!< Record SIP history. Off by default */
static unsigned int dumphistory; /*!< Dump history to verbose before destroying SIP dialog */
static char global_useragent[AST_MAX_EXTENSION]; /*!< Useragent for the SIP channel */
static char global_sdpsession[AST_MAX_EXTENSION]; /*!< SDP session name for the SIP channel */
static char global_sdpowner[AST_MAX_EXTENSION]; /*!< SDP owner name for the SIP channel */
static int global_authfailureevents; /*!< Whether we send authentication failure manager events or not. Default no. */
static int global_t1; /*!< T1 time */
static int global_t1min; /*!< T1 roundtrip time minimum */
static int global_timer_b; /*!< Timer B - RFC 3261 Section 17.1.1.2 */
static unsigned int global_autoframing; /*!< Turn autoframing on or off. */
static int global_qualifyfreq; /*!< Qualify frequency */
static int global_qualify_gap; /*!< Time between our group of peer pokes */
static int global_qualify_peers; /*!< Number of peers to poke at a given time */
static enum st_mode global_st_mode; /*!< Mode of operation for Session-Timers */
static enum st_refresher_param global_st_refresher; /*!< Session-Timer refresher */
static int global_min_se; /*!< Lowest threshold for session refresh interval */
static int global_max_se; /*!< Highest threshold for session refresh interval */
static int global_store_sip_cause; /*!< Whether the MASTER_CHANNEL(HASH(SIP_CAUSE,[chan_name])) var should be set */
static int global_dynamic_exclude_static = 0; /*!< Exclude static peers from contact registrations */
static unsigned char global_refer_addheaders; /*!< Add extra headers to outgoing REFER */
/*!
* We use libxml2 in order to parse XML that may appear in the body of a SIP message. Currently,
* the only usage is for parsing PIDF bodies of incoming PUBLISH requests in the call-completion
* event package. This variable is set at module load time and may be checked at runtime to determine
* if XML parsing support was found.
*/
static int can_parse_xml;
*
* \bug These counters are not handled in a thread-safe way ast_atomic_fetchadd_int()
* should be used to modify these values.
*/
static int speerobjs = 0; /*!< Static peers */
static int rpeerobjs = 0; /*!< Realtime peers */
static int apeerobjs = 0; /*!< Autocreated peer objects */
Mark Spencer
committed
static struct ast_flags global_flags[3] = {{0}}; /*!< global SIP_ flags */
static unsigned int global_t38_maxdatagram; /*!< global T.38 FaxMaxDatagram override */
static struct stasis_subscription *network_change_sub; /*!< subscription id for network change events */
Jonathan Rose
committed
static struct stasis_subscription *acl_change_sub; /*!< subscription id for named ACL system change events */
static int network_change_sched_id = -1;
static char used_context[AST_MAX_CONTEXT]; /*!< name of automatically created context for unloading */
Russell Bryant
committed
AST_MUTEX_DEFINE_STATIC(netlock);
/*! \brief Protect the monitoring thread, so only one process can kill or start it, and not
AST_MUTEX_DEFINE_STATIC(monlock);
AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
/*! \brief This is the thread for the monitor which checks for input on the channels
static pthread_t monitor_thread = AST_PTHREADT_NULL;
static int sip_reloading = FALSE; /*!< Flag for avoiding multiple reloads at the same time */
static enum channelreloadreason sip_reloadreason; /*!< Reason for last reload/load of configuration */
struct ast_sched_context *sched; /*!< The scheduling context */
static struct io_context *io; /*!< The IO context */
static int *sipsock_read_id; /*!< ID of IO entry for sipsock FD */
static AST_LIST_HEAD_STATIC(domain_list, domain); /*!< The SIP domain list */
Mark Spencer
committed
Olle Johansson
committed
AST_LIST_HEAD_NOLOCK(sip_history_head, sip_history); /*!< history list, entry in sip_pvt */
static enum sip_debug_e sipdebug;
/*! \brief extra debugging for 'text' related events.
* At the moment this is set together with sip_debug_console.
* \note It should either go away or be implemented properly.
*/
static int sipdebug_text;
Russell Bryant
committed
static const struct _map_x_s referstatusstrings[] = {
{ REFER_IDLE, "<none>" },
{ REFER_SENT, "Request sent" },
{ REFER_RECEIVED, "Request received" },
{ REFER_CONFIRMED, "Confirmed" },
{ REFER_ACCEPTED, "Accepted" },
{ REFER_RINGING, "Target ringing" },
{ REFER_200OK, "Done" },
{ REFER_FAILED, "Failed" },
{ REFER_NOAUTH, "Failed - auth failure" },
{ -1, NULL} /* terminator */
};
/* --- Hash tables of various objects --------*/
#ifdef LOW_MEMORY
static const int HASH_PEER_SIZE = 17;
static const int HASH_DIALOG_SIZE = 17;
static const int HASH_REGISTRY_SIZE = 17;
#else
static const int HASH_PEER_SIZE = 563; /*!< Size of peer hash table, prime number preferred! */
static const int HASH_DIALOG_SIZE = 563;
static const int HASH_REGISTRY_SIZE = 563;
#endif
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
static const struct {
enum ast_cc_service_type service;
const char *service_string;
} sip_cc_service_map [] = {
[AST_CC_NONE] = { AST_CC_NONE, "" },
[AST_CC_CCBS] = { AST_CC_CCBS, "BS" },
[AST_CC_CCNR] = { AST_CC_CCNR, "NR" },
[AST_CC_CCNL] = { AST_CC_CCNL, "NL" },
};
static const struct {
enum sip_cc_notify_state state;
const char *state_string;
} sip_cc_notify_state_map [] = {
[CC_QUEUED] = {CC_QUEUED, "cc-state: queued"},
[CC_READY] = {CC_READY, "cc-state: ready"},
};
AST_LIST_HEAD_STATIC(epa_static_data_list, epa_backend);
/*!
* Used to create new entity IDs by ESCs.
*/
static int esc_etag_counter;
static const int DEFAULT_PUBLISH_EXPIRES = 3600;
#ifdef HAVE_LIBXML2
static int cc_esc_publish_handler(struct sip_pvt *pvt, struct sip_request *req, struct event_state_compositor *esc, struct sip_esc_entry *esc_entry);
static const struct sip_esc_publish_callbacks cc_esc_publish_callbacks = {
.initial_handler = cc_esc_publish_handler,
.modify_handler = cc_esc_publish_handler,
};
#endif
/*!
* \brief The Event State Compositors
*
* An Event State Compositor is an entity which
* accepts PUBLISH requests and acts appropriately
* based on these requests.
*
* The actual event_state_compositor structure is simply
* an ao2_container of sip_esc_entrys. When an incoming
* PUBLISH is received, we can match the appropriate sip_esc_entry
* using the entity ID of the incoming PUBLISH.
*/
static struct event_state_compositor {
enum subscriptiontype event;
const char * name;
const struct sip_esc_publish_callbacks *callbacks;
struct ao2_container *compositor;
} event_state_compositors [] = {
#ifdef HAVE_LIBXML2
{CALL_COMPLETION, "call-completion", &cc_esc_publish_callbacks},
#endif
};
struct state_notify_data {
int state;
struct ao2_container *device_state_info;
int presence_state;
const char *presence_subtype;
const char *presence_message;
};
static const int ESC_MAX_BUCKETS = 37;
/*!
* \details
Stefan Schmidt
committed
* Here we implement the container for dialogs which are in the
* dialog_needdestroy state to iterate only through the dialogs
* unlink them instead of iterate through all dialogs
*/
struct ao2_container *dialogs_needdestroy;
/*!
* \details
Stefan Schmidt
committed
* Here we implement the container for dialogs which have rtp
* traffic and rtptimeout, rtpholdtimeout or rtpkeepalive
* set. We use this container instead the whole dialog list.
*/
struct ao2_container *dialogs_rtpcheck;
/*!
* \details
* Here we implement the container for dialogs (sip_pvt), defining
* generic wrapper functions to ease the transition from the current
* implementation (a single linked list) to a different container.
* In addition to a reference to the container, we need functions to lock/unlock
* the container and individual items, and functions to add/remove
* references to the individual items.
*/
static struct ao2_container *dialogs;
#define sip_pvt_lock(x) ao2_lock(x)
#define sip_pvt_trylock(x) ao2_trylock(x)
#define sip_pvt_unlock(x) ao2_unlock(x)
/*! \brief The table of TCP threads */
static struct ao2_container *threadt;
/*! \brief The peer list: Users, Peers and Friends */
static struct ao2_container *peers;
static struct ao2_container *peers_by_ip;