Skip to content
Snippets Groups Projects
chan_sip.c 938 KiB
Newer Older
  • Learn to ignore specific revisions
  •  * Asterisk -- An open source telephony toolkit.
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Copyright (C) 1999 - 2006, Digium, Inc.
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Mark Spencer <markster@digium.com>
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * 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.
     *
    
    Mark Spencer's avatar
    Mark Spencer committed
     * 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
     *
    
    Olle Johansson's avatar
    Olle Johansson committed
     * Implementation of RFC 3261 - without S/MIME, and experimental TCP and TLS support
    
     * Configuration file \link Config_sip sip.conf \endlink
    
    Olle Johansson's avatar
    Olle Johansson committed
     * ********** IMPORTANT *
     * \note TCP/TLS support is EXPERIMENTAL and WILL CHANGE. This applies to configuration
     *	settings, dialplan commands and dialplans apps/functions
    
    Olle Johansson's avatar
    Olle Johansson committed
     * 
    
     * ******** General TODO:s
    
     * \todo Better support of forking
    
     * \todo VIA branch tag transaction checking
     * \todo Transaction support
    
     * \todo Asterisk should send a non-100 provisional response every minute to keep proxies
     *  from cancelling the transaction (RFC 3261 13.3.1.1). See bug #11157.
    
     * 
     * ******** Wishlist: Improvements
     * - Support of SIP domains for devices, so that we match on username@domain in the From: header
     * - Connect registrations with a specific device on the incoming call. It's not done
    
    Russell Bryant's avatar
    Russell Bryant committed
     *   automatically in Asterisk
    
    Olle Johansson's avatar
    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
    
    Olle Johansson's avatar
    Olle Johansson committed
     * dialog or starts a new SIP dialog.
     * 
    
     * 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
    
    Olle Johansson's avatar
    Olle Johansson committed
     * 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.
    
    Olle Johansson's avatar
    Olle Johansson committed
     *
     * 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
     * in rtp.c 
     * 
     * \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
    
    /*!  
     * \page sip_tcp_tls SIP TCP and TLS support
     * 
    
     * \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 SIPCHANINFO
     * \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
     *		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
     *		
     * \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.
     *	
     * \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.
    
     *
     * \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.
     *
     *	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 
     *	  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.
     */
    
    
    /*!  \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 
    		request session-timers from remote end-points. This is the default mode.
    	2. Originate :: In the "originate" mode, the Asterisk server requests the remote 
    		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 
    		rejected with a 420 Bad Extension response.
    
    */
    
    #include "asterisk.h"
    
    ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <ctype.h>
    
    #include <sys/ioctl.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/signal.h>
    #include <regex.h>
    
    #include "asterisk/network.h"
    
    #include "asterisk/paths.h"	/* need ast_config_AST_SYSTEM_NAME */
    
    #include "asterisk/lock.h"
    #include "asterisk/channel.h"
    #include "asterisk/config.h"
    #include "asterisk/module.h"
    #include "asterisk/pbx.h"
    #include "asterisk/sched.h"
    #include "asterisk/io.h"
    
    #include "asterisk/rtp_engine.h"
    
    #include "asterisk/acl.h"
    #include "asterisk/manager.h"
    #include "asterisk/callerid.h"
    #include "asterisk/cli.h"
    #include "asterisk/app.h"
    #include "asterisk/musiconhold.h"
    #include "asterisk/dsp.h"
    #include "asterisk/features.h"
    #include "asterisk/srv.h"
    #include "asterisk/astdb.h"
    #include "asterisk/causes.h"
    #include "asterisk/utils.h"
    #include "asterisk/file.h"
    #include "asterisk/astobj.h"
    
    /* 
       Uncomment the define below,  if you are having refcount related memory leaks.
       With this uncommented, this module will generate a file, /tmp/refs, which contains
       a history of the ao2_ref() calls. To be useful, all calls to ao2_* functions should
       be modified to ao2_t_* calls, and include a tag describing what is happening with 
       enough detail, to make pairing up a reference count increment with its corresponding decrement.
       The refcounter program in utils/ can be invaluable in highlighting objects that are not
       balanced, along with the complete history for that object.
       In normal operation, the macros defined will throw away the tags, so they do not 
       affect the speed of the program at all. They can be considered to be documentation.
    */
    /* #define  REF_DEBUG 1 */
    #include "asterisk/astobj2.h"
    
    #include "asterisk/linkedlists.h"
    
    #include "asterisk/stringfields.h"
    
    #include "asterisk/monitor.h"
    
    #include "asterisk/threadstorage.h"
    
    #include "asterisk/translate.h"
    
    #include "asterisk/event.h"
    
    #include "asterisk/tcptls.h"
    
    #include "asterisk/stun.h"
    
    #include "asterisk/cel.h"
    
    #include "asterisk/strings.h"
    
    /*** 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>
    
    	<function name="SIP_HEADER" language="en_US">
    		<synopsis>
    			Gets the specified SIP header.
    		</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>
    		</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">
    						<para>(default) The ip address.</para>
    					</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="codecs">
    						<para>The configured codecs.</para>
    					</enum>
    					<enum name="status">
    						<para>Status (if qualify=yes).</para>
    					</enum>
    					<enum name="regexten">
    						<para>Registration extension.</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 id for peer.</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>
    		<description />
    	</function>
    	<function name="SIPCHANINFO" language="en_US">
    		<synopsis>
    			Gets the specified SIP parameter from the current channel.
    		</synopsis>
    		<syntax>
    			<parameter name="item" required="true">
    				<enumlist>
    					<enum name="peerip">
    						<para>The IP address of the peer.</para>
    					</enum>
    					<enum name="recvip">
    						<para>The source IP address of the peer.</para>
    					</enum>
    					<enum name="from">
    						<para>The URI from the <literal>From:</literal> header.</para>
    					</enum>
    					<enum name="uri">
    						<para>The URI from the <literal>Contact:</literal> header.</para>
    					</enum>
    					<enum name="useragent">
    						<para>The useragent.</para>
    					</enum>
    					<enum name="peername">
    						<para>The name of the peer.</para>
    					</enum>
    					<enum name="t38passthrough">
    						<para><literal>1</literal> if T38 is offered or enabled in this channel,
    						otherwise <literal>0</literal>.</para>
    					</enum>
    				</enumlist>
    			</parameter>
    		</syntax>
    		<description />
    	</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.
    			Peerlist will follow as separate events, followed by a final event called
    			PeerlistComplete.</para>
    		</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>
    	</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 RegistrationsComplete.</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 Variable: name=value sequences.</para>
    		</description>
    	</manager>
    
    #ifndef FALSE
    
    #endif
    
    #ifndef TRUE
    
    #define FINDUSERS (1 << 0)
    #define FINDPEERS (1 << 1)
    #define FINDALLDEVICES (FINDUSERS | FINDPEERS)
    
    #define	SIPBUFSIZE		512		/*!< Buffer size for many operations */
    
    #define XMIT_ERROR		-2
    
    
    #define SIP_RESERVED ";/?:@&=+$,# "		/*!< Reserved characters in the username part of the URI */
    
    Mark Spencer's avatar
    Mark Spencer committed
    /* #define VOCAL_DATA_HACK */
    
    Mark Spencer's avatar
    Mark Spencer committed
    #define DEFAULT_DEFAULT_EXPIRY  120
    
    #define DEFAULT_MIN_EXPIRY      60
    #define DEFAULT_MAX_EXPIRY      3600
    
    #define DEFAULT_REGISTRATION_TIMEOUT 20
    #define DEFAULT_MAX_FORWARDS    "70"
    
    
    /* guard limit must be larger than guard secs */
    
    /* guard min must be < 1000, and should be >= 250 */
    
    #define EXPIRY_GUARD_SECS       15                /*!< How long before expiry do we reregister */
    #define EXPIRY_GUARD_LIMIT      30                /*!< Below here, we use EXPIRY_GUARD_PCT instead of 
    
    	                                                 EXPIRY_GUARD_SECS */
    
    #define EXPIRY_GUARD_MIN        500                /*!< This is the minimum guard time applied. If 
                                                       GUARD_PCT turns out to be lower than this, it 
                                                       will use this time instead.
                                                       This is in milliseconds. */
    #define EXPIRY_GUARD_PCT        0.20                /*!< Percentage of expires timeout to use when 
                                                        below EXPIRY_GUARD_LIMIT */
    #define DEFAULT_EXPIRY 900                          /*!< Expire slowly */
    
    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;
    
    static int mwi_expiry = DEFAULT_MWI_EXPIRY;
    
    #define DEFAULT_QUALIFY_GAP   100
    #define DEFAULT_QUALIFY_PEERS 1
    
    #define CALLERID_UNKNOWN             "Anonymous"
    #define FROMDOMAIN_INVALID           "anonymous.invalid"
     
    
    #define DEFAULT_MAXMS                2000             /*!< Qualification: Must be faster than 2 seconds by default */
    
    #define DEFAULT_QUALIFYFREQ          60 * 1000        /*!< Qualification: How often to check for the host to be up */
    
    #define DEFAULT_FREQ_NOTOK           10 * 1000        /*!< Qualification: How often to check, if the host is down... */
    
    #define DEFAULT_RETRANS              1000             /*!< How frequently to retransmit Default: 2 * 500 ms in RFC 3261 */
    #define MAX_RETRANS                  6                /*!< Try only 6 times for retransmissions, a total of 7 transmissions */
    
    #define DEFAULT_TIMER_T1                 500              /*!< SIP timer T1 (according to RFC 3261) */
    #define SIP_TRANS_TIMEOUT            64 * DEFAULT_TIMER_T1 /*!< SIP request timeout (rfc 3261) 64*T1 
    
                                                          \todo Use known T1 for timeout (peerpoke)
                                                          */
    
    #define DEFAULT_TRANS_TIMEOUT        -1               /*!< Use default SIP transaction timeout */
    
    #define MAX_AUTHTRIES                3                /*!< Try authentication three times, then fail */
    
    #define SIP_MAX_HEADERS              64               /*!< Max amount of SIP headers to read */
    #define SIP_MAX_LINES                64               /*!< Max amount of lines in SIP attachment (like SDP) */
    
    #define SIP_MIN_PACKET               4096             /*!< Initialize size of memory to allocate for packets */
    
    #define MAX_HISTORY_ENTRIES 	     50	              /*!< Max entires in the history list for a sip_pvt */
    
    #define INITIAL_CSEQ                 101              /*!< Our initial sip sequence number */
    
    #define DEFAULT_MAX_SE               1800             /*!< Session-Timer Default Session-Expires period (RFC 4028) */
    #define DEFAULT_MIN_SE               90               /*!< Session-Timer Default Min-SE period (RFC 4028) */
    
    
    #define SDP_MAX_RTPMAP_CODECS        32               /*!< Maximum number of codecs allowed in received SDP */
    
    
    /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
    
    static struct ast_jb_conf default_jbconf =
    {
    
    	.flags = 0,
    
    	.max_size = -1,
    	.resync_threshold = -1,
    	.impl = ""
    };
    
    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 */
    
    /*! \brief Authorization scheme for call transfers 
    
    \note Not a bitfield flag, since there are plans for other modes,
    	like "only allow transfers for authenticated devices" */
    enum transfermodes {
    
    	TRANSFER_OPENFORALL,            /*!< Allow all SIP transfers */
    	TRANSFER_CLOSED,                /*!< Allow no SIP transfers */
    
    Olle Johansson's avatar
    Olle Johansson committed
    /*! \brief The result of a lot of functions */
    
    	AST_SUCCESS = 0,		/*!< FALSE means success, funny enough */
    	AST_FAILURE = -1,		/*!< Failure code */
    
    /*! \brief States for the INVITE transaction, not the dialog 
    	\note this is for the INVITE that sets up the dialog
    */
    enum invitestates {
    
    	INV_NONE = 0,	        /*!< No state at all, maybe not an INVITE dialog */
    	INV_CALLING = 1,	/*!< Invite sent, no answer */
    	INV_PROCEEDING = 2,	/*!< We got/sent 1xx message */
    	INV_EARLY_MEDIA = 3,    /*!< We got 18x message with to-tag back */
    	INV_COMPLETED = 4,	/*!< Got final response with error. Wait for ACK, then CONFIRMED */
    	INV_CONFIRMED = 5,	/*!< Confirmed response - we've got an ack (Incoming calls only) */
    	INV_TERMINATED = 6,	/*!< Transaction done - either successful (AST_STATE_UP) or failed, but done 
    				     The only way out of this is a BYE from one side */
    	INV_CANCELLED = 7,	/*!< Transaction cancelled by client or server in non-terminated state */
    
    /*! \brief Readable descriptions of device states.
           \note Should be aligned to above table as index */
    static const struct invstate2stringtable {
    	const enum invitestates state;
    
    	const char *desc;
    
    } 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"}
    };
    
    
    Olle Johansson's avatar
    Olle Johansson committed
    /*! \brief When sending a SIP message, we can send with a few options, depending on
    	type of SIP request. UNRELIABLE is moslty used for responses to repeated requests,
    	where the original response would be sent RELIABLE in an INVITE transaction */
    
    	XMIT_CRITICAL = 2,              /*!< Transmit critical SIP message reliably, with re-transmits.
                                                  If it fails, it's critical and will cause a teardown of the session */
    	XMIT_RELIABLE = 1,              /*!< Transmit SIP message reliably, with re-transmits */
    	XMIT_UNRELIABLE = 0,            /*!< Transmit SIP message without bothering with re-transmits */
    };
    
    
    /*! \brief Results from the parse_register() function */
    
    enum parse_register_result {
    	PARSE_REGISTER_FAILED,
    	PARSE_REGISTER_UPDATE,
    	PARSE_REGISTER_QUERY,
    
    /*! \brief Type of subscription, based on the packages we do support, see \ref subscription_types */
    
    enum subscriptiontype { 
    	NONE = 0,
    	XPIDF_XML,
    	DIALOG_INFO_XML,
    	CPIM_PIDF_XML,
    
    Olle Johansson's avatar
    Olle Johansson committed
    /*! \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
    */
    
    static const struct cfsubscription_types {
    	enum subscriptiontype type;
    	const char * const event;
    	const char * const mediatype;
    	const char * const text;
    } subscription_types[] = {
    
    Olle Johansson's avatar
    Olle Johansson committed
    	{ NONE,		   "-",        "unknown",	             "unknown" },
    
    Olle Johansson's avatar
    Olle Johansson committed
     	/* RFC 4235: SIP Dialog event package */
    
    	{ 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 */
    
    	{ 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 */
    
    /*! \brief Authentication types - proxy or www authentication 
    	\note Endpoints, like Asterisk, should always use WWW authentication to
    	allow multiple authentications in the same call - to the proxy and
    	to the end point.
    */
    
    enum sip_auth_type {
    
    /*! \brief Authentication result from check_auth* functions */
    enum check_auth_result {
    
    	AUTH_DONT_KNOW = -100,	/*!< no result, need to check further */
    		/* XXX maybe this is the same as AUTH_NOT_FOUND */
    
    
    	AUTH_SUCCESSFUL = 0,
    	AUTH_CHALLENGE_SENT = 1,
    	AUTH_SECRET_FAILED = -1,
    	AUTH_USERNAME_MISMATCH = -2,
    
    	AUTH_NOT_FOUND = -3,	/*!< returned by register_verify */
    
    	AUTH_FAKE_AUTH = -4,
    	AUTH_UNKNOWN_DOMAIN = -5,
    
    	AUTH_PEER_NOT_DYNAMIC = -6,
    	AUTH_ACL_FAILED = -7,
    
    	AUTH_RTP_FAILED = 9,
    
    /*! \brief States for outbound registrations (with register= lines in sip.conf */
    
    Olle Johansson's avatar
    Olle Johansson committed
    enum sipregistrystate {
    
    	REG_STATE_UNREGISTERED = 0,	/*!< We are not registered 
    
    		 *  \note Initial state. We should have a timeout scheduled for the initial
    
    		 * (or next) registration transmission, calling sip_reregister
    		 */
    
    
    Olle Johansson's avatar
    Olle Johansson committed
    	REG_STATE_REGSENT,	/*!< Registration request sent 
    		 * \note sent initial request, waiting for an ack or a timeout to
    
    		 * retransmit the initial request.
    		*/
    
    
    Olle Johansson's avatar
    Olle Johansson committed
    	REG_STATE_AUTHSENT,	/*!< We have tried to authenticate 
    		 * \note entered after transmit_register with auth info,
    
    	REG_STATE_REGISTERED,	/*!< Registered and done */
    
    Olle Johansson's avatar
    Olle Johansson committed
    	REG_STATE_REJECTED,	/*!< Registration rejected *
    		 * \note only used when the remote party has an expire larger than
    
    		 * our max-expire. This is a final state from which we do not
    		 * recover (not sure how correctly).
    		 */
    
    
    Olle Johansson's avatar
    Olle Johansson committed
    	REG_STATE_TIMEOUT,	/*!< Registration timed out *
    		* \note XXX unused */
    
    Olle Johansson's avatar
    Olle Johansson committed
    	REG_STATE_NOAUTH,	/*!< We have no accepted credentials
    		 * \note fatal - no chance to proceed */
    
    Olle Johansson's avatar
    Olle Johansson committed
    	REG_STATE_FAILED,	/*!< Registration failed after several tries
    		 * \note fatal - no chance to proceed */
    
    /*! \brief Modes in which Asterisk can be configured to run SIP Session-Timers */
    enum st_mode {
            SESSION_TIMER_MODE_INVALID = 0, /*!< Invalid value */ 
            SESSION_TIMER_MODE_ACCEPT,      /*!< Honor inbound Session-Timer requests */
            SESSION_TIMER_MODE_ORIGINATE,   /*!< Originate outbound and honor inbound requests */
            SESSION_TIMER_MODE_REFUSE       /*!< Ignore inbound Session-Timers requests */
    };
    
    /*! \brief The entity playing the refresher role for Session-Timers */
    enum st_refresher {
            SESSION_TIMER_REFRESHER_AUTO,    /*!< Negotiated                      */
            SESSION_TIMER_REFRESHER_UAC,     /*!< Session is refreshed by the UAC */
            SESSION_TIMER_REFRESHER_UAS      /*!< Session is refreshed by the UAS */
    };
    
    
    Olle Johansson's avatar
    Olle Johansson committed
    /*! \brief Define some implemented SIP transports 
    	\note Asterisk does not support SCTP or UDP/DTLS 
    */
    
    Olle Johansson's avatar
    Olle Johansson committed
    	SIP_TRANSPORT_UDP = 1,		/*!< Unreliable transport for SIP, needs retransmissions */
    	SIP_TRANSPORT_TCP = 1 << 1,	/*!< Reliable, but unsecure */
    	SIP_TRANSPORT_TLS = 1 << 2,	/*!< TCP/TLS - reliable and secure transport for signalling */
    
    /*! \brief definition of a sip proxy server
     *
    
     * For outbound proxies, a sip_peer will contain a reference to a 
     * dynamically allocated instance of a sip_proxy. A sip_pvt may also
     * contain a reference to a peer's outboundproxy, or it may contain
    
     * a reference to the sip_cfg.outboundproxy.
    
     */
    struct sip_proxy {
    	char name[MAXHOSTNAMELEN];      /*!< DNS name of domain/host or IP */
    	struct sockaddr_in ip;          /*!< Currently used IP address and port */
    	time_t last_dnsupdate;          /*!< When this was resolved */
    
    	int force;                      /*!< If it's an outbound proxy, Force use of this outbound proxy for all outbound requests */
    	/* Room for a SRV record chain based on the name */
    };
    
    
    /*! \brief argument for the 'show channels|subscriptions' callback. */
    struct __show_chan_arg { 
    	int fd;
    	int subscriptions;
    	int numchans;   /* return value */
    };
    
    
    
    /*! \brief States whether a SIP message can create a dialog in Asterisk. */
    
    enum can_create_dialog {
    	CAN_NOT_CREATE_DIALOG,
    	CAN_CREATE_DIALOG,
    	CAN_CREATE_DIALOG_UNSUPPORTED_METHOD,
    };
    
    /*! \brief SIP Request methods known by Asterisk 
    
       \note Do _NOT_ make any changes to this enum, or the array following it;
       if you think you are doing the right thing, you are probably
       not doing the right thing. If you think there are changes
       needed, get someone else to review them first _before_
       submitting a patch. If these two lists do not match properly
       bad things will happen.
    */
    
    enum sipmethod {
    	SIP_UNKNOWN,		/*!< Unknown response */
    	SIP_RESPONSE,		/*!< Not request, response to outbound request */
    	SIP_REGISTER,		/*!< Registration to the mothership, tell us where you are located */
    	SIP_OPTIONS,		/*!< Check capabilities of a device, used for "ping" too */
    	SIP_NOTIFY,		/*!< Status update, Part of the event package standard, result of a SUBSCRIBE or a REFER */
    	SIP_INVITE,		/*!< Set up a session */
    	SIP_ACK,		/*!< End of a three-way handshake started with INVITE. */
    	SIP_PRACK,		/*!< Reliable pre-call signalling. Not supported in Asterisk. */
    	SIP_BYE,		/*!< End of a session */
    	SIP_REFER,		/*!< Refer to another URI (transfer) */
    	SIP_SUBSCRIBE,		/*!< Subscribe for updates (voicemail, session status, device status, presence) */
    	SIP_MESSAGE,		/*!< Text messaging */
    	SIP_UPDATE,		/*!< Update a dialog. We can send UPDATE; but not accept it */
    	SIP_INFO,		/*!< Information updates during a session */
    	SIP_CANCEL,		/*!< Cancel an INVITE */
    	SIP_PUBLISH,		/*!< Not supported in Asterisk */
    	SIP_PING,		/*!< Not supported at all, no standard but still implemented out there */
    };
    
    
    /*! \brief Settings for the 'notifycid' option, see sip.conf.sample for details. */
    enum notifycid_setting {
    	DISABLED       = 0,
    	ENABLED        = 1,
    	IGNORE_CONTEXT = 2,
    };
    
    
    /*! \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 */
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    static const struct  cfsip_methods { 
    
    	int need_rtp;		/*!< when this is the 'primary' use for a pvt structure, does it need RTP? */
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	char * const text;
    
    	{ 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_UNSUPPORTED_METHOD },
    	{ SIP_PING,	 NO_RTP, "PING", 	CAN_CREATE_DIALOG_UNSUPPORTED_METHOD }
    
    /*!  Define SIP option tags, used in Require: and Supported: headers 
     	We need to be aware of these properties in the phones to use 
    
    	the replace: header. We should not do that without knowing
    	that the other end supports it... 
    	This is nothing we can configure, we learn by the dialog
    	Supported: header on the REGISTER (peer) or the INVITE
    	(other devices)
    	We are not using many of these today, but will in the future.
    	This is documented in RFC 3261
    */
    #define SUPPORTED		1
    #define NOT_SUPPORTED		0
    
    
    /* SIP options */
    
    #define SIP_OPT_REPLACES	(1 << 0)
    #define SIP_OPT_100REL		(1 << 1)
    #define SIP_OPT_TIMER		(1 << 2)
    #define SIP_OPT_EARLY_SESSION	(1 << 3)
    #define SIP_OPT_JOIN		(1 << 4)
    #define SIP_OPT_PATH		(1 << 5)
    #define SIP_OPT_PREF		(1 << 6)
    #define SIP_OPT_PRECONDITION	(1 << 7)
    #define SIP_OPT_PRIVACY		(1 << 8)
    #define SIP_OPT_SDP_ANAT	(1 << 9)
    #define SIP_OPT_SEC_AGREE	(1 << 10)
    #define SIP_OPT_EVENTLIST	(1 << 11)
    #define SIP_OPT_GRUU		(1 << 12)
    #define SIP_OPT_TARGET_DIALOG	(1 << 13)
    
    #define SIP_OPT_NOREFERSUB	(1 << 14)
    #define SIP_OPT_HISTINFO	(1 << 15)
    #define SIP_OPT_RESPRIORITY	(1 << 16)
    
    #define SIP_OPT_FROMCHANGE	(1 << 17)
    #define SIP_OPT_RECLISTINV	(1 << 18)
    #define SIP_OPT_RECLISTSUB	(1 << 19)
    
    #define SIP_OPT_OUTBOUND	(1 << 20)
    #define SIP_OPT_UNKNOWN		(1 << 21)
    
    /*! \brief List of well-known SIP options. If we get this in a require,
    
       we should check the list and answer accordingly. */
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    static const struct cfsip_options {
    
    	int id;			/*!< Bitmap ID */
    	int supported;		/*!< Supported by Asterisk ? */
    	char * const text;	/*!< Text id, as in standard */
    
    } sip_options[] = {	/* XXX used in 3 places */
    
    	/* RFC3262: PRACK 100% reliability */
    	{ SIP_OPT_100REL,	NOT_SUPPORTED,	"100rel" },	
    	/* RFC3959: SIP Early session support */
    	{ SIP_OPT_EARLY_SESSION, NOT_SUPPORTED,	"early-session" },
    
    	/* SIMPLE events:  RFC4662 */
    	{ SIP_OPT_EVENTLIST,	NOT_SUPPORTED,	"eventlist" },
    	/* RFC 4916- Connected line ID updates */
    	{ SIP_OPT_FROMCHANGE,	NOT_SUPPORTED,	"from-change" },
    	/* GRUU: Globally Routable User Agent URI's */
    	{ SIP_OPT_GRUU,		NOT_SUPPORTED,	"gruu" },
    	/* RFC4244 History info */
    	{ SIP_OPT_HISTINFO,	NOT_SUPPORTED,	"histinfo" },
    
    	/* RFC3911: SIP Join header support */
    
    	{ SIP_OPT_JOIN,		NOT_SUPPORTED,	"join" },
    
    	/* Disable the REFER subscription, RFC 4488 */
    	{ SIP_OPT_NOREFERSUB,	NOT_SUPPORTED,	"norefersub" },
    
    	/* SIP outbound - the final NAT battle - draft-sip-outbound */
    	{ SIP_OPT_OUTBOUND,	NOT_SUPPORTED,	"outbound" },
    
    	/* RFC3327: Path support */
    	{ SIP_OPT_PATH,		NOT_SUPPORTED,	"path" },
    	/* RFC3840: Callee preferences */
    	{ SIP_OPT_PREF,		NOT_SUPPORTED,	"pref" },
    	/* RFC3312: Precondition support */
    	{ SIP_OPT_PRECONDITION,	NOT_SUPPORTED,	"precondition" },
    	/* RFC3323: Privacy with proxies*/
    	{ SIP_OPT_PRIVACY,	NOT_SUPPORTED,	"privacy" },
    
    	/* RFC-ietf-sip-uri-list-conferencing-02.txt conference invite lists */
    	{ SIP_OPT_RECLISTINV,	NOT_SUPPORTED,	"recipient-list-invite" },
    	/* RFC-ietf-sip-uri-list-subscribe-02.txt - subscription lists */
    	{ SIP_OPT_RECLISTSUB,	NOT_SUPPORTED,	"recipient-list-subscribe" },