Newer
Older
Kevin P. Fleming
committed
/*
* Asterisk -- An open source telephony toolkit.
* Copyright (C) 1999 - 2006, 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
Terry Wilson
committed
* \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.
Olle Johansson
committed
*
* ******** 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
*
* \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
* 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
*
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 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.
Olle Johansson
committed
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
*
* \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.
*/
Jason Parker
committed
/*** MODULEINFO
<depend>chan_local</depend>
***/
Russell Bryant
committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*! \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.
*/
Kevin P. Fleming
committed
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
Kevin P. Fleming
committed
#include <sys/ioctl.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
#include <regex.h>
#include <time.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/channel.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/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"
Kevin P. Fleming
committed
#include "asterisk/dnsmgr.h"
Kevin P. Fleming
committed
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/netsock.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/cel.h"
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*** 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>
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
<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>
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
<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>
478
479
480
481
482
483
484
485
486
487
488
489
490
491
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
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
<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>
Olle Johansson
committed
/* Arguments for find_peer */
Russell Bryant
committed
#define FINDUSERS (1 << 0)
#define FINDPEERS (1 << 1)
#define FINDALLDEVICES (FINDUSERS | FINDPEERS)
Olle Johansson
committed
#define SIPBUFSIZE 512 /*!< Buffer size for many operations */
#define SIP_RESERVED ";/?:@&=+$,# " /*!< Reserved characters in the username part of the URI */
#define DEFAULT_MIN_EXPIRY 60
#define DEFAULT_MAX_EXPIRY 3600
#define DEFAULT_MWI_EXPIRY 3600
#define DEFAULT_REGISTRATION_TIMEOUT 20
#define DEFAULT_MAX_FORWARDS "70"
/* guard limit must be larger than guard secs */
Mark Spencer
committed
/* 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
#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
Joshua Colp
committed
#define CALLERID_UNKNOWN "Anonymous"
#define FROMDOMAIN_INVALID "anonymous.invalid"
#define DEFAULT_MAXMS 2000 /*!< Qualification: Must be faster than 2 seconds by default */
Russell Bryant
committed
#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) */
Tilghman Lesher
committed
#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 */
Russell Bryant
committed
#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 */
Russell Bryant
committed
static struct ast_jb_conf default_jbconf =
{
Russell Bryant
committed
.max_size = -1,
.resync_threshold = -1,
.impl = ""
};
static struct ast_jb_conf global_jbconf; /*!< Global jitterbuffer configuration */
Russell Bryant
committed
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 */
Kevin P. Fleming
committed
#define RTP 1
#define NO_RTP 0
/*! \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
committed
enum sip_result {
AST_SUCCESS = 0, /*!< FALSE means success, funny enough */
AST_FAILURE = -1, /*!< Failure code */
Olle Johansson
committed
};
Olle Johansson
committed
/*! \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 */
Olle Johansson
committed
};
Olle Johansson
committed
/*! \brief Readable descriptions of device states.
\note Should be aligned to above table as index */
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 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 */
enum xmittype {
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 */
Kevin P. Fleming
committed
enum subscriptiontype {
NONE = 0,
XPIDF_XML,
DIALOG_INFO_XML,
CPIM_PIDF_XML,
Kevin P. Fleming
committed
PIDF_XML,
MWI_NOTIFICATION
Kevin P. Fleming
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
*/
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[] = {
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
};
Kevin P. Fleming
committed
/*! \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.
*/
PROXY_AUTH = 407,
WWW_AUTH = 401,
/*! \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,
Brett Bryant
committed
AUTH_BAD_TRANSPORT = -8,
};
/*! \brief States for outbound registrations (with register= lines in sip.conf */
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
*/
REG_STATE_REGSENT, /*!< Registration request sent
* \note sent initial request, waiting for an ack or a timeout to
* retransmit the initial request.
*/
REG_STATE_AUTHSENT, /*!< We have tried to authenticate
* \note entered after transmit_register with auth info,
* waiting for an ack.
*/
Joshua Colp
committed
REG_STATE_REGISTERED, /*!< Registered and done */
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).
*/
REG_STATE_TIMEOUT, /*!< Registration timed out *
* \note XXX unused */
REG_STATE_NOAUTH, /*!< We have no accepted credentials
* \note fatal - no chance to proceed */
REG_STATE_FAILED, /*!< Registration failed after several tries
* \note fatal - no chance to proceed */
Russell Bryant
committed
/*! \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 */
};
/*! \brief Define some implemented SIP transports
\note Asterisk does not support SCTP or UDP/DTLS
*/
Brett Bryant
committed
enum sip_transport {
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 */
Brett Bryant
committed
};
Russell Bryant
committed
/*! \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
Olle Johansson
committed
* 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 */
Olle Johansson
committed
enum sip_transport transport;
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 */
};
Olle Johansson
committed
/*! \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. */
Russell Bryant
committed
enum can_create_dialog {
CAN_NOT_CREATE_DIALOG,
CAN_CREATE_DIALOG,
CAN_CREATE_DIALOG_UNSUPPORTED_METHOD,
};
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
/*! \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
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_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
#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)
Olle Johansson
committed
#define SIP_OPT_FROMCHANGE (1 << 17)
#define SIP_OPT_RECLISTINV (1 << 18)
#define SIP_OPT_RECLISTSUB (1 << 19)
Olle Johansson
committed
#define SIP_OPT_OUTBOUND (1 << 20)
#define SIP_OPT_UNKNOWN (1 << 21)
Russell Bryant
committed
/*! \brief List of well-known SIP options. If we get this in a require,
we should check the list and answer accordingly. */
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" },
Olle Johansson
committed
/* 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" },
Olle Johansson
committed
/* Disable the REFER subscription, RFC 4488 */
{ SIP_OPT_NOREFERSUB, NOT_SUPPORTED, "norefersub" },
Olle Johansson
committed
/* 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" },
Olle Johansson
committed
/* 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" },