Newer
Older
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Implementation of Session Initiation Protocol
*
* Copyright (C) 2004 - 2005, Digium, Inc.
* Mark Spencer <markster@digium.com>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
Kevin P. Fleming
committed
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk.h"
Kevin P. Fleming
committed
Kevin P. Fleming
committed
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/lock.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.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/acl.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"
#include "asterisk/dnsmgr.h"
Kevin P. Fleming
committed
#include "asterisk/astosp.h"
#ifndef DEFAULT_USERAGENT
#define DEFAULT_USERAGENT "Asterisk PBX"
#endif
#define VIDEO_CODEC_MASK 0x1fc0000 /* Video codecs from H.261 thru AST_FORMAT_MAX_VIDEO */
#ifndef IPTOS_MINCOST
#define IPTOS_MINCOST 0x02
#endif
#define DEFAULT_DEFAULT_EXPIRY 120
#define DEFAULT_MAX_EXPIRY 3600
#define DEFAULT_REGISTRATION_TIMEOUT 20
Kevin P. Fleming
committed
#define DEFAULT_REGATTEMPTS_MAX 10
/* 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
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 */
static int max_expiry = DEFAULT_MAX_EXPIRY;
static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
Martin Pycko
committed
#define CALLERID_UNKNOWN "Unknown"
#define DEFAULT_MAXMS 2000 /* Must be faster than 2 seconds by default */
#define DEFAULT_FREQ_OK 60 * 1000 /* How often to check for the host to be up */
#define DEFAULT_FREQ_NOTOK 10 * 1000 /* How often to check, if the host is down... */
Kevin P. Fleming
committed
#define DEFAULT_RETRANS 2000 /* How frequently to retransmit */
#define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
#define DEBUG_READ 0 /* Recieved data */
#define DEBUG_SEND 1 /* Transmit data */
static const char desc[] = "Session Initiation Protocol (SIP)";
static const char channeltype[] = "SIP";
static const char config[] = "sip.conf";
static const char notify_config[] = "sip_notify.conf";
#define SIP_REGISTER 1
#define SIP_OPTIONS 2
#define SIP_NOTIFY 3
#define SIP_INVITE 4
#define SIP_ACK 5
#define SIP_PRACK 6
#define SIP_BYE 7
#define SIP_REFER 8
#define SIP_SUBSCRIBE 9
#define SIP_MESSAGE 10
#define SIP_UPDATE 11
#define SIP_INFO 12
#define SIP_CANCEL 13
#define SIP_PUBLISH 14
#define SIP_RESPONSE 100
Kevin P. Fleming
committed
#define RTP 1
#define NO_RTP 0
const struct cfsip_methods {
int id;
Kevin P. Fleming
committed
int need_rtp; /* when this is the 'primary' use for a pvt structure, does it need RTP? */
char *text;
} sip_methods[] = {
Kevin P. Fleming
committed
{ 0, RTP, "-UNKNOWN-" },
{ SIP_REGISTER, NO_RTP, "REGISTER" },
{ SIP_OPTIONS, NO_RTP, "OPTIONS" },
{ SIP_NOTIFY, NO_RTP, "NOTIFY" },
{ SIP_INVITE, RTP, "INVITE" },
{ SIP_ACK, NO_RTP, "ACK" },
{ SIP_PRACK, NO_RTP, "PRACK" },
{ SIP_BYE, NO_RTP, "BYE" },
{ SIP_REFER, NO_RTP, "REFER" },
{ SIP_SUBSCRIBE, NO_RTP, "SUBSCRIBE" },
{ SIP_MESSAGE, NO_RTP, "MESSAGE" },
{ SIP_UPDATE, NO_RTP, "UPDATE" },
{ SIP_INFO, NO_RTP, "INFO" },
{ SIP_CANCEL, NO_RTP, "CANCEL" },
{ SIP_PUBLISH, NO_RTP, "PUBLISH" }
/* Structure for conversion between compressed SIP and "normal" SIP */
static struct cfalias {
char *fullname;
char *shortname;
} aliases[] = {
{ "Content-Type", "c" },
{ "Content-Encoding", "e" },
{ "From", "f" },
{ "Call-ID", "i" },
{ "Contact", "m" },
{ "Content-Length", "l" },
{ "Subject", "s" },
{ "To", "t" },
{ "Supported", "k" },
{ "Refer-To", "r" },
{ "Referred-By", "b" },
{ "Allow-Events", "u" },
{ "Event", "o" },
{ "Via", "v" },
};
#define DEFAULT_SIP_PORT 5060 /* From RFC 3261 (former 2543) */
#define SIP_MAX_PACKET 4096 /* Also from RFC 3261 (2543), should sub headers tho */
#define ALLOWED_METHODS "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY"
Mark Spencer
committed
static char default_useragent[AST_MAX_EXTENSION] = DEFAULT_USERAGENT;
#define DEFAULT_CONTEXT "default"
static char default_context[AST_MAX_EXTENSION] = DEFAULT_CONTEXT;
Mark Spencer
committed
static char default_language[MAX_LANGUAGE] = "";
#define DEFAULT_CALLERID "asterisk"
static char default_callerid[AST_MAX_EXTENSION] = DEFAULT_CALLERID;
Mark Spencer
committed
static char default_fromdomain[AST_MAX_EXTENSION] = "";
Mark Spencer
committed
#define DEFAULT_NOTIFYMIME "application/simple-message-summary"
static char default_notifymime[AST_MAX_EXTENSION] = DEFAULT_NOTIFYMIME;
static int default_qualify = 0; /* Default Qualify= setting */
static struct ast_flags global_flags = {0}; /* global SIP_ flags */
static struct ast_flags global_flags_page2 = {0}; /* more global SIP_ flags */
static int srvlookup = 0; /* SRV Lookup on or off. Default is off, RFC behavior is on */
static int pedanticsipchecking = 0; /* Extra checking ? Default off */
static int autocreatepeer = 0; /* Auto creation of peers at registration? Default off. */
Mark Spencer
committed
static int global_rtptimeout = 0;
Mark Spencer
committed
static int global_rtpholdtimeout = 0;
static int global_rtpkeepalive = 0;
Kevin P. Fleming
committed
static int global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT;
static int global_regattempts_max = DEFAULT_REGATTEMPTS_MAX;
Mark Spencer
committed
/* Object counters */
static int suserobjs = 0;
static int ruserobjs = 0;
static int speerobjs = 0;
static int rpeerobjs = 0;
static int apeerobjs = 0;
static int regobjs = 0;
static int global_allowguest = 1; /* allow unauthenticated users/peers to connect? */
#define DEFAULT_MWITIME 10
static int global_mwitime = DEFAULT_MWITIME; /* Time between MWI checks for peers */
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
/* Protect the monitoring thread, so only one process can kill or start it, and not
when it's doing something critical. */
AST_MUTEX_DEFINE_STATIC(netlock);
AST_MUTEX_DEFINE_STATIC(monlock);
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use. */
static pthread_t monitor_thread = AST_PTHREADT_NULL;
/* Codecs that we support by default: */
Mark Spencer
committed
static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
static struct sockaddr_in outboundproxyip;
static struct sockaddr_in debugaddr;
static int videosupport = 0;
static int compactheaders = 0; /* send compact sip headers */
static int recordhistory = 0; /* Record SIP history. Off by default */
Mark Spencer
committed
Mark Spencer
committed
static char global_musicclass[MAX_LANGUAGE] = ""; /* Global music on hold class */
#define DEFAULT_REALM "asterisk"
static char global_realm[MAXHOSTNAMELEN] = DEFAULT_REALM; /* Default realm */
static char regcontext[AST_MAX_EXTENSION] = ""; /* Context for auto-extensions */
#define DEFAULT_EXPIRY 900
static int expiry = DEFAULT_EXPIRY;
static struct sched_context *sched;
static struct io_context *io;
/* The private structures of the sip channels are linked for
selecting outgoing channels */
#define SIP_MAX_HEADERS 64
#define SIP_MAX_LINES 64
#define DEC_IN_USE 0
#define INC_IN_USE 1
#define DEC_OUT_USE 2
#define INC_OUT_USE 3
static struct ast_codec_pref prefs;
/* sip_request: The data grabbed from the UDP socket */
char *rlPart1; /* SIP Method Name or "SIP/2.0" protocol version */
char *rlPart2; /* The Request URI or Response Status */
int len; /* Length */
int headers; /* # of SIP Headers */
int method; /* Method of this request */
Kevin P. Fleming
committed
int lines; /* SDP Content */
char *line[SIP_MAX_LINES];
char data[SIP_MAX_PACKET];
};
/* Parameters to the transmit_invite function */
struct sip_invite_param {
char *distinctive_ring;
char *osptoken;
int addsipheaders;
char *vxml_url;
char *auth;
char *authheader;
};
struct sip_route {
struct sip_route *next;
char hop[0];
};
/* sip_history: Structure for saving transactions within a SIP dialog */
Mark Spencer
committed
struct sip_history {
char event[80];
struct sip_history *next;
};
/* sip_auth: Creadentials for authentication to other SIP services */
struct sip_auth {
char realm[AST_MAX_EXTENSION]; /* Realm in which these credentials are valid */
char username[256]; /* Username */
char secret[256]; /* Secret */
char md5secret[256]; /* MD5Secret */
struct sip_auth *next; /* Next auth structure in list */
};
#define SIP_ALREADYGONE (1 << 0) /* Whether or not we've already been destroyed by our peer */
#define SIP_NEEDDESTROY (1 << 1) /* if we need to be destroyed */
#define SIP_NOVIDEO (1 << 2) /* Didn't get video in invite, don't offer */
#define SIP_RINGING (1 << 3) /* Have sent 180 ringing */
#define SIP_PROGRESS_SENT (1 << 4) /* Have sent 183 message progress */
#define SIP_NEEDREINVITE (1 << 5) /* Do we need to send another reinvite? */
#define SIP_PENDINGBYE (1 << 6) /* Need to send bye after we ack? */
#define SIP_GOTREFER (1 << 7) /* Got a refer? */
#define SIP_PROMISCREDIR (1 << 8) /* Promiscuous redirection */
#define SIP_TRUSTRPID (1 << 9) /* Trust RPID headers? */
#define SIP_USEREQPHONE (1 << 10) /* Add user=phone to numeric URI. Default off */
Mark Spencer
committed
#define SIP_REALTIME (1 << 11) /* Flag for realtime users */
#define SIP_USECLIENTCODE (1 << 12) /* Trust X-ClientCode info message */
#define SIP_OUTGOING (1 << 13) /* Is this an outgoing call? */
Mark Spencer
committed
#define SIP_SELFDESTRUCT (1 << 14)
#define SIP_DYNAMIC (1 << 15) /* Is this a dynamic peer? */
/* --- Choices for DTMF support in SIP channel */
#define SIP_DTMF (3 << 16) /* three settings, uses two bits */
#define SIP_DTMF_RFC2833 (0 << 16) /* RTP DTMF */
#define SIP_DTMF_INBAND (1 << 16) /* Inband audio, only for ULAW/ALAW */
#define SIP_DTMF_INFO (2 << 16) /* SIP Info messages */
/* NAT settings */
#define SIP_NAT (3 << 18) /* four settings, uses two bits */
#define SIP_NAT_NEVER (0 << 18) /* No nat support */
#define SIP_NAT_RFC3581 (1 << 18)
#define SIP_NAT_ROUTE (2 << 18)
#define SIP_NAT_ALWAYS (3 << 18)
/* re-INVITE related settings */
#define SIP_REINVITE (3 << 20) /* two bits used */
#define SIP_CAN_REINVITE (1 << 20) /* allow peers to be reinvited to send media directly p2p */
#define SIP_REINVITE_UPDATE (2 << 20) /* use UPDATE (RFC3311) when reinviting this peer */
/* "insecure" settings */
#define SIP_INSECURE_PORT (1 << 22) /* don't require matching port for incoming requests */
#define SIP_INSECURE_INVITE (1 << 23) /* don't require authentication for incoming INVITEs */
/* Sending PROGRESS in-band settings */
#define SIP_PROG_INBAND (3 << 24) /* three settings, uses two bits */
#define SIP_PROG_INBAND_NEVER (0 << 24)
#define SIP_PROG_INBAND_NO (1 << 24)
#define SIP_PROG_INBAND_YES (2 << 24)
/* Open Settlement Protocol authentication */
#define SIP_OSPAUTH (3 << 26) /* three settings, uses two bits */
#define SIP_OSPAUTH_NO (0 << 26)
#define SIP_OSPAUTH_YES (1 << 26)
#define SIP_OSPAUTH_EXCLUSIVE (2 << 26)
#define SIP_CALL_ONHOLD (1 << 28)
#define SIP_CALL_LIMIT (1 << 29)
#define SIP_PAGE2_RTCACHEFRIENDS (1 << 0)
#define SIP_PAGE2_RTNOUPDATE (1 << 1)
#define SIP_PAGE2_RTAUTOCLEAR (1 << 2)
static int global_rtautoclear = 120;
/* sip_pvt: PVT structures are used for each SIP conversation, ie. a call */
ast_mutex_t lock; /* Channel private lock */
int method; /* SIP method of this packet */
char callid[80]; /* Global CallID */
char randdata[80]; /* Random data */
struct ast_codec_pref prefs; /* codec prefs */
unsigned int ocseq; /* Current outgoing seqno */
unsigned int icseq; /* Current incoming seqno */
ast_group_t pickupgroup; /* Pickup group */
int lastinvite; /* Last Cseq of invite */
int capability; /* Special capability (codec) */
int jointcapability; /* Supported capability at both ends (codecs ) */
int peercapability; /* Supported peer capability */
int prefcodec; /* Preferred codec (outbound only) */
int callingpres; /* Calling presentation */
int authtries; /* Times we've tried to authenticate */
int expiry; /* How long we take to expire */
int branch; /* One random number */
int tag; /* Another random number */
int sessionid; /* SDP Session ID */
int sessionversion; /* SDP Session Version */
struct sockaddr_in sa; /* Our peer */
struct sockaddr_in redirip; /* Where our RTP should be going if not to us */
struct sockaddr_in vredirip; /* Where our Video RTP should be going if not to us */
int redircodecs; /* Redirect codecs */
struct sockaddr_in recv; /* Received as */
struct in_addr ourip; /* Our IP */
struct ast_channel *owner; /* Who owns us */
char exten[AST_MAX_EXTENSION]; /* Extension where to start */
char refer_to[AST_MAX_EXTENSION]; /* Place to store REFER-TO extension */
char referred_by[AST_MAX_EXTENSION]; /* Place to store REFERRED-BY extension */
char refer_contact[AST_MAX_EXTENSION]; /* Place to store Contact info from a REFER extension */
struct sip_pvt *refer_call; /* Call we are referring */
struct sip_route *route; /* Head of linked list of routing steps (fm Record-Route) */
int route_persistant; /* Is this the "real" route? */
char from[256]; /* The From: header */
char useragent[256]; /* User agent in SIP request */
char context[AST_MAX_EXTENSION]; /* Context for this call */
char fromdomain[MAXHOSTNAMELEN]; /* Domain to show in the from field */
char fromuser[AST_MAX_EXTENSION]; /* User to show in the user field */
char fromname[AST_MAX_EXTENSION]; /* Name to show in the user field */
char tohost[MAXHOSTNAMELEN]; /* Host we should put in the "to" field */
char language[MAX_LANGUAGE]; /* Default language for this call */
char musicclass[MAX_LANGUAGE]; /* Music on Hold class */
char rdnis[256]; /* Referring DNIS */
char theirtag[256]; /* Their tag */
char username[256]; /* [user] name */
char peername[256]; /* [peer] name, not set if [user] */
char authname[256]; /* Who we use for authentication */
char uri[256]; /* Original requested URI */
char okcontacturi[256]; /* URI from the 200 OK on INVITE */
char peersecret[256]; /* Password */
struct sip_auth *peerauth; /* Realm authentication */
char cid_num[256]; /* Caller*ID */
char cid_name[256]; /* Caller*ID */
char via[256]; /* Via: header */
char fullcontact[128]; /* The Contact: that the UA registers with us */
char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */
char our_contact[256]; /* Our contact header */
char realm[MAXHOSTNAMELEN]; /* Authorization realm */
char nonce[256]; /* Authorization nonce */
char opaque[256]; /* Opaque nonsense */
char qop[80]; /* Quality of Protection, since SIP wasn't complicated enough yet. */
char domain[MAXHOSTNAMELEN]; /* Authorization domain */
char lastmsg[256]; /* Last Message sent/received */
int amaflags; /* AMA Flags */
int pendinginvite; /* Any pending invite */
#ifdef OSP_SUPPORT
int osphandle; /* OSP Handle for call */
time_t ospstart; /* OSP Start time */
#endif
struct sip_request initreq; /* Initial request */
int maxtime; /* Max time for first response */
int maxforwards; /* keep the max-forwards info */
int initid; /* Auto-congest ID if appropriate */
int autokillid; /* Auto-kill ID */
time_t lastrtprx; /* Last RTP received */
time_t lastrtptx; /* Last RTP sent */
int rtptimeout; /* RTP timeout time */
int rtpholdtimeout; /* RTP timeout when on hold */
int rtpkeepalive; /* Send RTP packets for keepalive */
int subscribed; /* Is this call a subscription? */
int dialogver;
struct ast_dsp *vad; /* Voice Activation Detection dsp */
struct sip_peer *peerpoke; /* If this calls is to poke a peer, which one */
struct sip_registry *registry; /* If this is a REGISTER call, to which registry */
struct ast_rtp *rtp; /* RTP Session */
struct ast_rtp *vrtp; /* Video RTP session */
struct sip_pkt *packets; /* Packets scheduled for re-transmission */
struct sip_history *history; /* History of this SIP dialog */
struct ast_variable *chanvars; /* Channel variables to set for call */
struct sip_pvt *next; /* Next call in chain */
#define FLAG_RESPONSE (1 << 0)
#define FLAG_FATAL (1 << 1)
/* sip packet - read in sipsock_read, transmitted in send_request */
struct sip_pkt *next; /* Next packet */
int retrans; /* Retransmission number */
int seqno; /* Sequence number */
unsigned int flags; /* non-zero if this is a response packet (e.g. 200 OK) */
struct sip_pvt *owner; /* Owner call */
int retransid; /* Retransmission ID */
int packetlen; /* Length of packet */
/* Structure for SIP user data. User's place calls to us */
struct sip_user {
/* Users who can access various contexts */
Mark Spencer
committed
ASTOBJ_COMPONENTS(struct sip_user);
char secret[80]; /* Password */
char md5secret[80]; /* Password in md5 */
char context[AST_MAX_EXTENSION]; /* Default context for incoming calls */
char cid_num[80]; /* Caller ID num */
char cid_name[80]; /* Caller ID name */
char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */
char language[MAX_LANGUAGE]; /* Default language for this user */
char musicclass[MAX_LANGUAGE]; /* Music on Hold class */
char useragent[256]; /* User agent in SIP request */
struct ast_codec_pref prefs; /* codec prefs */
ast_group_t callgroup; /* Call group */
ast_group_t pickupgroup; /* Pickup Group */
Kevin P. Fleming
committed
struct ast_flags flags_page2; /* SIP_PAGE2 flags */
int amaflags; /* AMA flags for billing */
int callingpres; /* Calling id presentation */
int capability; /* Codec capability */
int inUse; /* Number of calls in use */
int incominglimit; /* Limit of incoming calls */
int outUse; /* disabled */
int outgoinglimit; /* disabled */
struct ast_ha *ha; /* ACL setting */
struct ast_variable *chanvars; /* Variables to set for channel created by user */
/* Structure for SIP peer data, we place calls to peers if registred or fixed IP address (host) */
ASTOBJ_COMPONENTS(struct sip_peer); /* name, refcount, objflags, object pointers */
/* peer->name is the unique name of this object */
char secret[80]; /* Password */
char md5secret[80]; /* Password in MD5 */
struct sip_auth *auth; /* Realm authentication list */
char context[AST_MAX_EXTENSION]; /* Default context for incoming calls */
char username[80]; /* Temporary username until registration */
char accountcode[AST_MAX_ACCOUNT_CODE]; /* Account code */
int amaflags; /* AMA Flags (for billing) */
char tohost[MAXHOSTNAMELEN]; /* If not dynamic, IP address */
char regexten[AST_MAX_EXTENSION]; /* Extension to register (if regcontext is used) */
char fromuser[80]; /* From: user when calling this peer */
char fromdomain[MAXHOSTNAMELEN]; /* From: domain when calling this peer */
char fullcontact[256]; /* Contact registred with us (not in sip.conf) */
char cid_num[80]; /* Caller ID num */
char cid_name[80]; /* Caller ID name */
int callingpres; /* Calling id presentation */
int inUse; /* Number of calls in use */
int incominglimit; /* Limit of incoming calls */
int outUse; /* disabled */
int outgoinglimit; /* disabled */
char mailbox[AST_MAX_EXTENSION]; /* Mailbox setting for MWI checks */
char language[MAX_LANGUAGE]; /* Default language for prompts */
char musicclass[MAX_LANGUAGE]; /* Music on Hold class */
char useragent[256]; /* User agent in SIP request (saved from registration) */
struct ast_codec_pref prefs; /* codec prefs */
time_t lastmsgcheck; /* Last time we checked for MWI */
struct ast_flags flags_page2; /* SIP_PAGE2 flags */
int expire; /* When to expire this peer registration */
int expiry; /* Duration of registration */
int capability; /* Codec capability */
int rtptimeout; /* RTP timeout */
int rtpholdtimeout; /* RTP Hold Timeout */
int rtpkeepalive; /* Send RTP packets for keepalive */
ast_group_t callgroup; /* Call group */
ast_group_t pickupgroup; /* Pickup group */
struct ast_dnsmgr_entry *dnsmgr;/* DNS refresh manager for peer */
struct sockaddr_in addr; /* IP address of peer */
/* Qualification */
struct sip_pvt *call; /* Call pointer */
int pokeexpire; /* When to expire poke (qualify= checking) */
int lastms; /* How long last response took (in ms), or -1 for no response */
int maxms; /* Max ms we will accept for the host to be up, 0 to not monitor */
struct timeval ps; /* Ping send time */
struct sockaddr_in defaddr; /* Default IP address, used until registration */
struct ast_ha *ha; /* Access control list */
struct ast_variable *chanvars; /* Variables to set for channel created by user */
AST_MUTEX_DEFINE_STATIC(sip_reload_lock);
static int sip_reloading = 0;
/* States for outbound registrations (with register= lines in sip.conf */
#define REG_STATE_UNREGISTERED 0
#define REG_STATE_REGSENT 1
#define REG_STATE_AUTHSENT 2
#define REG_STATE_REGISTERED 3
#define REG_STATE_REJECTED 4
#define REG_STATE_TIMEOUT 5
#define REG_STATE_NOAUTH 6
#define REG_STATE_FAILED 7
/* sip_registry: Registrations with other SIP proxies */
Mark Spencer
committed
ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1);
int portno; /* Optional port override */
char username[80]; /* Who we are registering as */
char authuser[80]; /* Who we *authenticate* as */
char hostname[MAXHOSTNAMELEN]; /* Domain or host we register to */
char secret[80]; /* Password or key name in []'s */
char contact[256]; /* Contact extension */
Kevin P. Fleming
committed
int regattempts; /* Number of attempts */
int timeout; /* sched id of sip_reg_timeout */
int refresh; /* How often to refresh */
struct sip_pvt *call; /* create a sip_pvt structure for each outbound "registration call" in progress */
int regstate; /* Registration state (see above) */
int callid_valid; /* 0 means we haven't chosen callid for this registry yet. */
char callid[80]; /* Global CallID for this registry */
unsigned int ocseq; /* Sequence number we got to for REGISTERs for this registry */
struct sockaddr_in us; /* Who the server thinks we are */
Mark Spencer
committed
/* Saved headers */
char realm[MAXHOSTNAMELEN]; /* Authorization realm */
Mark Spencer
committed
char nonce[256]; /* Authorization nonce */
char domain[MAXHOSTNAMELEN]; /* Authorization domain */
Mark Spencer
committed
char opaque[256]; /* Opaque nonsense */
char qop[80]; /* Quality of Protection. */
char lastmsg[256]; /* Last Message sent/received */
/*--- The user list: Users and friends ---*/
static struct ast_user_list {
Mark Spencer
committed
ASTOBJ_CONTAINER_COMPONENTS(struct sip_user);
/*--- The peer list: Peers and Friends ---*/
static struct ast_peer_list {
Mark Spencer
committed
ASTOBJ_CONTAINER_COMPONENTS(struct sip_peer);
/*--- The register list: Other SIP proxys we register with and call ---*/
static struct ast_register_list {
Mark Spencer
committed
ASTOBJ_CONTAINER_COMPONENTS(struct sip_registry);
static int __sip_do_register(struct sip_registry *r);
static struct sockaddr_in externip;
static char externhost[MAXHOSTNAMELEN] = "";
Mark Spencer
committed
static time_t externexpire = 0;
static int externrefresh = 10;
Mark Spencer
committed
static struct ast_ha *localaddr;
/* The list of manual NOTIFY types we know how to send */
struct ast_config *notify_types;
static struct sip_auth *authl; /* Authentication list */
static struct ast_frame *sip_read(struct ast_channel *ast);
static int transmit_response(struct sip_pvt *p, char *msg, struct sip_request *req);
static int transmit_response_with_sdp(struct sip_pvt *p, char *msg, struct sip_request *req, int retrans);
Kevin P. Fleming
committed
static int transmit_response_with_auth(struct sip_pvt *p, char *msg, struct sip_request *req, char *rand, int reliable, char *header, int stale);
static int transmit_request(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
static int transmit_request_with_auth(struct sip_pvt *p, int sipmethod, int inc, int reliable, int newbranch);
static int transmit_invite(struct sip_pvt *p, int sipmethod, int sendsdp, struct sip_invite_param *options, int init);
static int transmit_reinvite_with_sdp(struct sip_pvt *p);
static int transmit_info_with_digit(struct sip_pvt *p, char digit);
Mark Spencer
committed
static int transmit_message_with_text(struct sip_pvt *p, const char *text);
static int transmit_refer(struct sip_pvt *p, const char *dest);
static int sip_sipredirect(struct sip_pvt *p, const char *dest);
static struct sip_peer *temp_peer(const char *name);
static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init);
static void free_old_route(struct sip_route *route);
static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int digest_len);
static int update_user_counter(struct sip_pvt *fup, int event);
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int realtime);
static struct sip_user *build_user(const char *name, struct ast_variable *v, int realtime);
static int sip_do_reload(void);
static int expire_register(void *data);
static struct ast_channel *sip_request(const char *type, int format, void *data, int *cause);
static int sip_devicestate(void *data);
Mark Spencer
committed
static int sip_sendtext(struct ast_channel *ast, const char *text);
static int sip_call(struct ast_channel *ast, char *dest, int timeout);
static int sip_hangup(struct ast_channel *ast);
static int sip_answer(struct ast_channel *ast);
static struct ast_frame *sip_read(struct ast_channel *ast);
static int sip_write(struct ast_channel *ast, struct ast_frame *frame);
static int sip_indicate(struct ast_channel *ast, int condition);
Mark Spencer
committed
static int sip_transfer(struct ast_channel *ast, const char *dest);
static int sip_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static int sip_senddigit(struct ast_channel *ast, char digit);
static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */
static struct sip_auth *add_realm_authentication(struct sip_auth *authlist, char *configuration, int lineno); /* Add realm authentication in list */
static struct sip_auth *find_realm_authentication(struct sip_auth *authlist, char *realm); /* Find authentication for a specific realm */
/* Definition of this channel for channel registration */
static const struct ast_channel_tech sip_tech = {
.type = channeltype,
.description = "Session Initiation Protocol (SIP)",
.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
Mark Spencer
committed
.properties = AST_CHAN_TP_WANTSJITTER,
.requester = sip_request,
.devicestate = sip_devicestate,
.call = sip_call,
.hangup = sip_hangup,
.answer = sip_answer,
.read = sip_read,
.write = sip_write,
.write_video = sip_write,
.indicate = sip_indicate,
.transfer = sip_transfer,
.fixup = sip_fixup,
.send_digit = sip_senddigit,
.bridge = ast_rtp_bridge,
.send_text = sip_sendtext,
};
/*--- find_sip_method: Find SIP method from header */
int find_sip_method(char *msg)
{
int i, res = 0;
/* Strictly speaking, SIP methods are case SENSITIVE, but we don't check */
for (i=1;(i < (sizeof(sip_methods) / sizeof(sip_methods[0]))) && !res; i++) {
if (!strcasecmp(sip_methods[i].text, msg))
res = sip_methods[i].id;
}
return res;
}
/*--- sip_debug_test_addr: See if we pass debug IP filter */
static inline int sip_debug_test_addr(struct sockaddr_in *addr)
{
if (sipdebug == 0)
return 0;
if (debugaddr.sin_addr.s_addr) {
if (((ntohs(debugaddr.sin_port) != 0)
&& (debugaddr.sin_port != addr->sin_port))
|| (debugaddr.sin_addr.s_addr != addr->sin_addr.s_addr))
return 0;
}
return 1;
}
/*--- sip_debug_test_pvt: Test PVT for debugging output */
static inline int sip_debug_test_pvt(struct sip_pvt *p)
{
return sip_debug_test_addr(((ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE) ? &p->recv : &p->sa));
/*--- __sip_xmit: Transmit SIP message ---*/
static int __sip_xmit(struct sip_pvt *p, char *data, int len)
{
int res;
char iabuf[INET_ADDRSTRLEN];
if (ast_test_flag(p, SIP_NAT) & SIP_NAT_ROUTE)
res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->recv, sizeof(struct sockaddr_in));
else
res=sendto(sipsock, data, len, 0, (struct sockaddr *)&p->sa, sizeof(struct sockaddr_in));
Mark Spencer
committed
ast_log(LOG_WARNING, "sip_xmit of %p (len %d) to %s returned %d: %s\n", data, len, ast_inet_ntoa(iabuf, sizeof(iabuf), p->sa.sin_addr), res, strerror(errno));
static void sip_destroy(struct sip_pvt *p);
/*--- build_via: Build a Via header for a request ---*/
static void build_via(struct sip_pvt *p, char *buf, int len)
{
char iabuf[INET_ADDRSTRLEN];
/* z9hG4bK is a magic cookie. See RFC 3261 section 8.1.1.7 */
if (ast_test_flag(p, SIP_NAT) != SIP_NAT_NEVER)
snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x;rport", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
else /* Work around buggy UNIDEN UIP200 firmware */
snprintf(buf, len, "SIP/2.0/UDP %s:%d;branch=z9hG4bK%08x", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip), ourport, p->branch);
}
/*--- ast_sip_ouraddrfor: NAT fix - decide which IP address to use for ASterisk server? ---*/
/* Only used for outbound registrations */
static int ast_sip_ouraddrfor(struct in_addr *them, struct in_addr *us)
{
Mark Spencer
committed
* Using the localaddr structure built up with localnet statements
* apply it to their address to see if we need to substitute our
* externip or can get away with our internal bindaddr
*/
struct sockaddr_in theirs;
theirs.sin_addr = *them;
if (localaddr && externip.sin_addr.s_addr &&
ast_apply_ha(localaddr, &theirs)) {
char iabuf[INET_ADDRSTRLEN];
if (externexpire && (time(NULL) >= externexpire)) {
struct ast_hostent ahp;
struct hostent *hp;
time(&externexpire);
externexpire += externrefresh;
if ((hp = ast_gethostbyname(externhost, &ahp))) {
memcpy(&externip.sin_addr, hp->h_addr, sizeof(externip.sin_addr));
} else
ast_log(LOG_NOTICE, "Warning: Re-lookup of '%s' failed!\n", externhost);
}
memcpy(us, &externip.sin_addr, sizeof(struct in_addr));
Mark Spencer
committed
ast_inet_ntoa(iabuf, sizeof(iabuf), *(struct in_addr *)&them->s_addr);
ast_log(LOG_DEBUG, "Target address %s is not local, substituting externip\n", iabuf);
Mark Spencer
committed
}
else if (bindaddr.sin_addr.s_addr)
memcpy(us, &bindaddr.sin_addr, sizeof(struct in_addr));
else
return ast_ouraddrfor(them, us);
return 0;
}
/*--- append_history: Append to SIP dialog history */
Mark Spencer
committed
static int append_history(struct sip_pvt *p, char *event, char *data)
{
struct sip_history *hist, *prev;
char *c;
if (!recordhistory)
return 0;
if(!(hist = malloc(sizeof(struct sip_history)))) {
ast_log(LOG_WARNING, "Can't allocate memory for history");
return 0;
}
memset(hist, 0, sizeof(struct sip_history));
snprintf(hist->event, sizeof(hist->event), "%-15s %s", event, data);
/* Trim up nicely */
c = hist->event;
while(*c) {
if ((*c == '\r') || (*c == '\n')) {
*c = '\0';
break;
Mark Spencer
committed
}
c++;
}
/* Enqueue into history */
prev = p->history;
if (prev) {
while(prev->next)
prev = prev->next;
prev->next = hist;
} else {
p->history = hist;
Mark Spencer
committed
}
return 0;
}
/*--- retrans_pkt: Retransmit SIP message if no answer ---*/
struct sip_pkt *pkt=data, *prev, *cur;
char iabuf[INET_ADDRSTRLEN];
ast_mutex_lock(&pkt->owner->lock);
if (pkt->retrans < MAX_RETRANS) {
pkt->retrans++;
if (sip_debug_test_pvt(pkt->owner)) {
if (ast_test_flag(pkt->owner, SIP_NAT) & SIP_NAT_ROUTE)
ast_verbose("Retransmitting #%d (NAT) to %s:%d:\n%s\n---\n", pkt->retrans, ast_inet_ntoa(iabuf, sizeof(iabuf), pkt->owner->recv.sin_addr), ntohs(pkt->owner->recv.sin_port), pkt->data);
ast_verbose("Retransmitting #%d (no NAT) to %s:%d:\n%s\n---\n", pkt->retrans, ast_inet_ntoa(iabuf, sizeof(iabuf), pkt->owner->sa.sin_addr), ntohs(pkt->owner->sa.sin_port), pkt->data);
Mark Spencer
committed
append_history(pkt->owner, "ReTx", pkt->data);
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
res = 1;
ast_log(LOG_WARNING, "Maximum retries exceeded on call %s for seqno %d (%s %s)\n", pkt->owner->callid, pkt->seqno, (ast_test_flag(pkt, FLAG_FATAL)) ? "Critical" : "Non-critical", (ast_test_flag(pkt, FLAG_RESPONSE)) ? "Response" : "Request");
append_history(pkt->owner, "MaxRetries", (ast_test_flag(pkt, FLAG_FATAL)) ? "(Critical)" : "(Non-critical)");
while(pkt->owner->owner && ast_mutex_trylock(&pkt->owner->owner->lock)) {
ast_mutex_unlock(&pkt->owner->lock);
usleep(1);
ast_mutex_lock(&pkt->owner->lock);
}
if (pkt->owner->owner) {
ast_set_flag(pkt->owner, SIP_ALREADYGONE);
Mark Spencer
committed
ast_queue_hangup(pkt->owner->owner);
ast_mutex_unlock(&pkt->owner->owner->lock);
} else {
/* If no owner, destroy now */
ast_set_flag(pkt->owner, SIP_NEEDDESTROY);
/* In any case, go ahead and remove the packet */
prev = NULL;
cur = pkt->owner->packets;
while(cur) {
if (cur == pkt)
break;
prev = cur;
cur = cur->next;
}
if (cur) {
if (prev)
prev->next = cur->next;
else
pkt->owner->packets = cur->next;
ast_mutex_unlock(&pkt->owner->lock);
free(cur);
pkt = NULL;
} else
ast_log(LOG_WARNING, "Weird, couldn't find packet owner!\n");
ast_mutex_unlock(&pkt->owner->lock);
/*--- __sip_reliable_xmit: transmit packet with retransmits ---*/
static int __sip_reliable_xmit(struct sip_pvt *p, int seqno, int resp, char *data, int len, int fatal)
pkt = malloc(sizeof(struct sip_pkt) + len + 1);
if (!pkt)
return -1;
memset(pkt, 0, sizeof(struct sip_pkt));
memcpy(pkt->data, data, len);
pkt->packetlen = len;
pkt->next = p->packets;
pkt->owner = p;
pkt->seqno = seqno;
pkt->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, pkt);
pkt->next = p->packets;
p->packets = pkt;
__sip_xmit(pkt->owner, pkt->data, pkt->packetlen);
if (!strncasecmp(pkt->data, "INVITE", 6)) {
/* Note this is a pending invite */
p->pendinginvite = seqno;
}
/*--- __sip_autodestruct: Kill a call (called by scheduler) ---*/
static int __sip_autodestruct(void *data)
{
struct sip_pvt *p = data;
p->autokillid = -1;
ast_log(LOG_DEBUG, "Auto destroying call '%s'\n", p->callid);
Mark Spencer
committed
append_history(p, "AutoDestroy", "");
if (p->owner) {
ast_log(LOG_WARNING, "Autodestruct on call '%s' with owner in place\n", p->callid);
Mark Spencer
committed
ast_queue_hangup(p->owner);
} else {
sip_destroy(p);
}
return 0;
}
/*--- sip_scheddestroy: Schedule destruction of SIP call ---*/
static int sip_scheddestroy(struct sip_pvt *p, int ms)
{
Mark Spencer
committed
char tmp[80];
if (sip_debug_test_pvt(p))
ast_verbose("Scheduling destruction of call '%s' in %d ms\n", p->callid, ms);