|
|
@ -449,13 +449,20 @@ static const struct cfsip_options {
|
|
|
|
/*! \brief SIP Extensions we support */
|
|
|
|
/*! \brief SIP Extensions we support */
|
|
|
|
#define SUPPORTED_EXTENSIONS "replaces"
|
|
|
|
#define SUPPORTED_EXTENSIONS "replaces"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Standard SIP port from RFC 3261. DO NOT CHANGE THIS */
|
|
|
|
|
|
|
|
#define STANDARD_SIP_PORT 5060
|
|
|
|
|
|
|
|
/* Note: in many SIP headers, absence of a port number implies port 5060,
|
|
|
|
|
|
|
|
* and this is why we cannot change the above constant.
|
|
|
|
|
|
|
|
* There is a limited number of places in asterisk where we could,
|
|
|
|
|
|
|
|
* in principle, use a different "default" port number, but
|
|
|
|
|
|
|
|
* we do not support this feature at the moment.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* Default values, set and reset in reload_config before reading configuration */
|
|
|
|
/* Default values, set and reset in reload_config before reading configuration */
|
|
|
|
/* These are default values in the source. There are other recommended values in the
|
|
|
|
/* These are default values in the source. There are other recommended values in the
|
|
|
|
sip.conf.sample for new installations. These may differ to keep backwards compatibility,
|
|
|
|
sip.conf.sample for new installations. These may differ to keep backwards compatibility,
|
|
|
|
yet encouraging new behaviour on new installations
|
|
|
|
yet encouraging new behaviour on new installations
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
#define DEFAULT_SIP_PORT 5060 /*!< From RFC 3261 (former 2543) */
|
|
|
|
|
|
|
|
#define DEFAULT_CONTEXT "default"
|
|
|
|
#define DEFAULT_CONTEXT "default"
|
|
|
|
#define DEFAULT_MOHINTERPRET "default"
|
|
|
|
#define DEFAULT_MOHINTERPRET "default"
|
|
|
|
#define DEFAULT_MOHSUGGEST ""
|
|
|
|
#define DEFAULT_MOHSUGGEST ""
|
|
|
@ -527,6 +534,7 @@ static char global_useragent[AST_MAX_EXTENSION]; /*!< Useragent for the SIP chan
|
|
|
|
static int allow_external_domains; /*!< Accept calls to external SIP domains? */
|
|
|
|
static int allow_external_domains; /*!< Accept calls to external SIP domains? */
|
|
|
|
static int global_callevents; /*!< Whether we send manager events or not */
|
|
|
|
static int global_callevents; /*!< Whether we send manager events or not */
|
|
|
|
static int global_t1min; /*!< T1 roundtrip time minimum */
|
|
|
|
static int global_t1min; /*!< T1 roundtrip time minimum */
|
|
|
|
|
|
|
|
static int global_autoframing; /*!< ?????????? */
|
|
|
|
static enum transfermodes global_allowtransfer; /*!< SIP Refer restriction scheme */
|
|
|
|
static enum transfermodes global_allowtransfer; /*!< SIP Refer restriction scheme */
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Codecs that we support by default: */
|
|
|
|
/*! \brief Codecs that we support by default: */
|
|
|
@ -543,7 +551,6 @@ static int regobjs = 0; /*!< Registry objects */
|
|
|
|
|
|
|
|
|
|
|
|
static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */
|
|
|
|
static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */
|
|
|
|
|
|
|
|
|
|
|
|
static int global_autoframing = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Protect the SIP dialog list (of sip_pvt's) */
|
|
|
|
/*! \brief Protect the SIP dialog list (of sip_pvt's) */
|
|
|
|
AST_MUTEX_DEFINE_STATIC(iflock);
|
|
|
|
AST_MUTEX_DEFINE_STATIC(iflock);
|
|
|
@ -2101,7 +2108,7 @@ static int send_response(struct sip_pvt *p, struct sip_request *req, enum xmitty
|
|
|
|
if (sip_debug_test_pvt(p)) {
|
|
|
|
if (sip_debug_test_pvt(p)) {
|
|
|
|
const struct sockaddr_in *dst = sip_real_dst(p);
|
|
|
|
const struct sockaddr_in *dst = sip_real_dst(p);
|
|
|
|
|
|
|
|
|
|
|
|
ast_verbose("%sTransmitting (%s) to %s:%d:\n%s\n---\n",
|
|
|
|
ast_verbose("\n<--- %sTransmitting (%s) to %s:%d --->\n%s\n<------------>\n",
|
|
|
|
reliable ? "Reliably " : "", sip_nat_mode(p),
|
|
|
|
reliable ? "Reliably " : "", sip_nat_mode(p),
|
|
|
|
ast_inet_ntoa(dst->sin_addr),
|
|
|
|
ast_inet_ntoa(dst->sin_addr),
|
|
|
|
ntohs(dst->sin_port), req->data);
|
|
|
|
ntohs(dst->sin_port), req->data);
|
|
|
@ -2506,13 +2513,33 @@ static struct sip_user *find_user(const char *name, int realtime)
|
|
|
|
return u;
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Set nat mode on the various data sockets */
|
|
|
|
|
|
|
|
static void do_setnat(struct sip_pvt *p, int natflags)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *mode = natflags ? "On" : "Off";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (p->rtp) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", mode);
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->rtp, natflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->vrtp) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", mode);
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->vrtp, natflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->udptl) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", mode);
|
|
|
|
|
|
|
|
ast_udptl_setnat(p->udptl, natflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief Create address structure from peer reference.
|
|
|
|
/*! \brief Create address structure from peer reference.
|
|
|
|
* return -1 on error, 0 on success.
|
|
|
|
* return -1 on error, 0 on success.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
|
|
|
|
static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int natflags;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
|
|
|
|
if ((peer->addr.sin_addr.s_addr || peer->defaddr.sin_addr.s_addr) &&
|
|
|
|
(!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) {
|
|
|
|
(!peer->maxms || ((peer->lastms >= 0) && (peer->lastms <= peer->maxms)))) {
|
|
|
|
dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
|
|
|
|
dialog->sa = (peer->addr.sin_addr.s_addr) ? peer->addr : peer->defaddr;
|
|
|
@ -2546,26 +2573,17 @@ static int create_addr_from_peer(struct sip_pvt *dialog, struct sip_peer *peer)
|
|
|
|
ast_udptl_destroy(dialog->udptl);
|
|
|
|
ast_udptl_destroy(dialog->udptl);
|
|
|
|
dialog->udptl = NULL;
|
|
|
|
dialog->udptl = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
natflags = ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE;
|
|
|
|
do_setnat(dialog, ast_test_flag(&dialog->flags[0], SIP_NAT) & SIP_NAT_ROUTE );
|
|
|
|
|
|
|
|
|
|
|
|
if (dialog->rtp) {
|
|
|
|
if (dialog->rtp) {
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", natflags ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_rtp_setnat(dialog->rtp, natflags);
|
|
|
|
|
|
|
|
ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
|
|
|
|
ast_rtp_setdtmf(dialog->rtp, ast_test_flag(&dialog->flags[0], SIP_DTMF) != SIP_DTMF_INFO);
|
|
|
|
ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
|
|
|
|
ast_rtp_setdtmfcompensate(dialog->rtp, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dialog->vrtp) {
|
|
|
|
if (dialog->vrtp) {
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", natflags ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_rtp_setnat(dialog->vrtp, natflags);
|
|
|
|
|
|
|
|
ast_rtp_setdtmf(dialog->vrtp, 0);
|
|
|
|
ast_rtp_setdtmf(dialog->vrtp, 0);
|
|
|
|
ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
|
|
|
|
ast_rtp_setdtmfcompensate(dialog->vrtp, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dialog->udptl) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", natflags ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_udptl_setnat(dialog->udptl, natflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Frame packetization */
|
|
|
|
/* Set Frame packetization */
|
|
|
|
if (dialog->rtp) {
|
|
|
|
if (dialog->rtp) {
|
|
|
|
ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
|
|
|
|
ast_rtp_codec_setpref(dialog->rtp, &dialog->prefs);
|
|
|
@ -2645,7 +2663,7 @@ static int create_addr(struct sip_pvt *dialog, const char *opeer)
|
|
|
|
return res;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hostn = peer;
|
|
|
|
hostn = peer;
|
|
|
|
portno = port ? atoi(port) : DEFAULT_SIP_PORT;
|
|
|
|
portno = port ? atoi(port) : STANDARD_SIP_PORT;
|
|
|
|
if (srvlookup) {
|
|
|
|
if (srvlookup) {
|
|
|
|
char service[MAXHOSTNAMELEN];
|
|
|
|
char service[MAXHOSTNAMELEN];
|
|
|
|
int tportno;
|
|
|
|
int tportno;
|
|
|
@ -2907,7 +2925,7 @@ static void __sip_destroy(struct sip_pvt *p, int lockowner)
|
|
|
|
static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char name[256];
|
|
|
|
char name[256];
|
|
|
|
int *inuse, *call_limit, *inringing = NULL;
|
|
|
|
int *inuse, *call_limit, *inringing;
|
|
|
|
int outgoing = ast_test_flag(&fup->flags[0], SIP_OUTGOING);
|
|
|
|
int outgoing = ast_test_flag(&fup->flags[0], SIP_OUTGOING);
|
|
|
|
struct sip_user *u = NULL;
|
|
|
|
struct sip_user *u = NULL;
|
|
|
|
struct sip_peer *p = NULL;
|
|
|
|
struct sip_peer *p = NULL;
|
|
|
@ -2921,19 +2939,12 @@ static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
|
|
|
|
|
|
|
|
ast_copy_string(name, fup->username, sizeof(name));
|
|
|
|
ast_copy_string(name, fup->username, sizeof(name));
|
|
|
|
|
|
|
|
|
|
|
|
/* Check the list of users */
|
|
|
|
/* Check the list of users only for incoming calls */
|
|
|
|
if (!outgoing) /* Only check users for incoming calls */
|
|
|
|
if (!outgoing && (u = find_user(name, 1)) ) {
|
|
|
|
u = find_user(name, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (u) {
|
|
|
|
|
|
|
|
inuse = &u->inUse;
|
|
|
|
inuse = &u->inUse;
|
|
|
|
call_limit = &u->call_limit;
|
|
|
|
call_limit = &u->call_limit;
|
|
|
|
p = NULL;
|
|
|
|
inringing = NULL;
|
|
|
|
} else {
|
|
|
|
} else if ( (p = find_peer(fup->peername, NULL, 1) ) ) { /* Try to find peer */
|
|
|
|
/* Try to find peer */
|
|
|
|
|
|
|
|
if (!p)
|
|
|
|
|
|
|
|
p = find_peer(fup->peername, NULL, 1);
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
|
|
|
|
inuse = &p->inUse;
|
|
|
|
inuse = &p->inUse;
|
|
|
|
call_limit = &p->call_limit;
|
|
|
|
call_limit = &p->call_limit;
|
|
|
|
inringing = &p->inRinging;
|
|
|
|
inringing = &p->inRinging;
|
|
|
@ -2943,7 +2954,7 @@ static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
ast_log(LOG_DEBUG, "%s is not a local device, no call limit\n", name);
|
|
|
|
ast_log(LOG_DEBUG, "%s is not a local device, no call limit\n", name);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(event) {
|
|
|
|
switch(event) {
|
|
|
|
/* incoming and outgoing affects the inUse counter */
|
|
|
|
/* incoming and outgoing affects the inUse counter */
|
|
|
|
case DEC_CALL_LIMIT:
|
|
|
|
case DEC_CALL_LIMIT:
|
|
|
@ -2966,6 +2977,7 @@ static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
ast_log(LOG_DEBUG, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
|
|
|
|
ast_log(LOG_DEBUG, "Call %s %s '%s' removed from call limit %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *call_limit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case INC_CALL_RINGING:
|
|
|
|
case INC_CALL_RINGING:
|
|
|
|
case INC_CALL_LIMIT:
|
|
|
|
case INC_CALL_LIMIT:
|
|
|
|
if (*call_limit > 0 ) {
|
|
|
|
if (*call_limit > 0 ) {
|
|
|
@ -2991,6 +3003,7 @@ static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
ast_log(LOG_DEBUG, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *inuse, *call_limit);
|
|
|
|
ast_log(LOG_DEBUG, "Call %s %s '%s' is %d out of %d\n", outgoing ? "to" : "from", u ? "user":"peer", name, *inuse, *call_limit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case DEC_CALL_RINGING:
|
|
|
|
case DEC_CALL_RINGING:
|
|
|
|
if (inringing) {
|
|
|
|
if (inringing) {
|
|
|
|
if (ast_test_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING)) {
|
|
|
|
if (ast_test_flag(&fup->flags[1], SIP_PAGE2_INC_RINGING)) {
|
|
|
@ -3002,15 +3015,15 @@ static int update_call_counter(struct sip_pvt *fup, int event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event);
|
|
|
|
ast_log(LOG_ERROR, "update_call_counter(%s, %d) called with no event!\n", name, event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p)
|
|
|
|
if (p) {
|
|
|
|
ast_device_state_changed("SIP/%s", p->name);
|
|
|
|
ast_device_state_changed("SIP/%s", p->name);
|
|
|
|
if (u)
|
|
|
|
|
|
|
|
ASTOBJ_UNREF(u, sip_destroy_user);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
ASTOBJ_UNREF(p, sip_destroy_peer);
|
|
|
|
ASTOBJ_UNREF(p, sip_destroy_peer);
|
|
|
|
|
|
|
|
} else /* u must be set */
|
|
|
|
|
|
|
|
ASTOBJ_UNREF(u, sip_destroy_user);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -3713,12 +3726,16 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const char *my_name; /* pick a good name */
|
|
|
|
if (title)
|
|
|
|
if (title)
|
|
|
|
ast_string_field_build(tmp, name, "SIP/%s-%08x", title, (int)(long) i);
|
|
|
|
my_name = title;
|
|
|
|
else if (strchr(i->fromdomain,':'))
|
|
|
|
else if ( (my_name = strchr(i->fromdomain,':')) )
|
|
|
|
ast_string_field_build(tmp, name, "SIP/%s-%08x", strchr(i->fromdomain,':') + 1, (int)(long) i);
|
|
|
|
my_name++; /* skip ':' */
|
|
|
|
else
|
|
|
|
else
|
|
|
|
ast_string_field_build(tmp, name, "SIP/%s-%08x", i->fromdomain, (int)(long) i);
|
|
|
|
my_name = i->fromdomain;
|
|
|
|
|
|
|
|
ast_string_field_build(tmp, name, "SIP/%s-%08x", my_name, (int)(long) i);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
|
|
|
|
if (ast_test_flag(&i->flags[0], SIP_DTMF) == SIP_DTMF_INBAND) {
|
|
|
|
i->vad = ast_dsp_new();
|
|
|
|
i->vad = ast_dsp_new();
|
|
|
@ -4141,17 +4158,10 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (useglobal_nat && sin) {
|
|
|
|
if (useglobal_nat && sin) {
|
|
|
|
int natflags;
|
|
|
|
|
|
|
|
/* Setup NAT structure according to global settings if we have an address */
|
|
|
|
/* Setup NAT structure according to global settings if we have an address */
|
|
|
|
ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT);
|
|
|
|
ast_copy_flags(&p->flags[0], &global_flags[0], SIP_NAT);
|
|
|
|
p->recv = *sin;
|
|
|
|
p->recv = *sin;
|
|
|
|
natflags = ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE;
|
|
|
|
do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT) & SIP_NAT_ROUTE);
|
|
|
|
if (p->rtp)
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->rtp, natflags);
|
|
|
|
|
|
|
|
if (p->vrtp)
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->vrtp, natflags);
|
|
|
|
|
|
|
|
if (p->udptl)
|
|
|
|
|
|
|
|
ast_udptl_setnat(p->udptl, natflags);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (p->method != SIP_REGISTER)
|
|
|
|
if (p->method != SIP_REGISTER)
|
|
|
@ -5317,14 +5327,14 @@ static void set_destination(struct sip_pvt *p, char *uri)
|
|
|
|
/* XXX bug here if string has been trimmed to sizeof(hostname) */
|
|
|
|
/* XXX bug here if string has been trimmed to sizeof(hostname) */
|
|
|
|
h += hn - 1;
|
|
|
|
h += hn - 1;
|
|
|
|
|
|
|
|
|
|
|
|
/* Is "port" present? if not default to DEFAULT_SIP_PORT */
|
|
|
|
/* Is "port" present? if not default to STANDARD_SIP_PORT */
|
|
|
|
if (*h == ':') {
|
|
|
|
if (*h == ':') {
|
|
|
|
/* Parse port */
|
|
|
|
/* Parse port */
|
|
|
|
++h;
|
|
|
|
++h;
|
|
|
|
port = strtol(h, &h, 10);
|
|
|
|
port = strtol(h, &h, 10);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
port = DEFAULT_SIP_PORT;
|
|
|
|
port = STANDARD_SIP_PORT;
|
|
|
|
|
|
|
|
|
|
|
|
/* Got the hostname:port - but maybe there's a "maddr=" to override address? */
|
|
|
|
/* Got the hostname:port - but maybe there's a "maddr=" to override address? */
|
|
|
|
maddr = strstr(h, "maddr=");
|
|
|
|
maddr = strstr(h, "maddr=");
|
|
|
@ -6293,7 +6303,7 @@ static void extract_uri(struct sip_pvt *p, struct sip_request *req)
|
|
|
|
static void build_contact(struct sip_pvt *p)
|
|
|
|
static void build_contact(struct sip_pvt *p)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/* Construct Contact: header */
|
|
|
|
/* Construct Contact: header */
|
|
|
|
if (ourport != DEFAULT_SIP_PORT) /* Needs to be 5060, according to the RFC */
|
|
|
|
if (ourport != STANDARD_SIP_PORT)
|
|
|
|
ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip), ourport);
|
|
|
|
ast_string_field_build(p, our_contact, "<sip:%s%s%s:%d>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip), ourport);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip));
|
|
|
|
ast_string_field_build(p, our_contact, "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(p->ourip));
|
|
|
@ -6389,31 +6399,25 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
|
|
|
|
char tmp[BUFSIZ/2];
|
|
|
|
char tmp[BUFSIZ/2];
|
|
|
|
char tmp2[BUFSIZ/2];
|
|
|
|
char tmp2[BUFSIZ/2];
|
|
|
|
const char *l = NULL, *n = NULL;
|
|
|
|
const char *l = NULL, *n = NULL;
|
|
|
|
int x;
|
|
|
|
const char *urioptions = "";
|
|
|
|
char urioptions[256]="";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) {
|
|
|
|
if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) {
|
|
|
|
char onlydigits = TRUE;
|
|
|
|
const char *s = p->username; /* being a string field, cannot be NULL */
|
|
|
|
x=0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Test p->username against allowed characters in AST_DIGIT_ANY
|
|
|
|
/* Test p->username against allowed characters in AST_DIGIT_ANY
|
|
|
|
If it matches the allowed characters list, then sipuser = ";user=phone"
|
|
|
|
If it matches the allowed characters list, then sipuser = ";user=phone"
|
|
|
|
If not, then sipuser = ""
|
|
|
|
If not, then sipuser = ""
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
/* + is allowed in first position in a tel: uri */
|
|
|
|
/* + is allowed in first position in a tel: uri */
|
|
|
|
if (p->username && p->username[0] == '+')
|
|
|
|
if (*s == '+')
|
|
|
|
x=1;
|
|
|
|
s++;
|
|
|
|
|
|
|
|
for (; *s; s++) {
|
|
|
|
for (; x < strlen(p->username); x++) {
|
|
|
|
if (!strchr(AST_DIGIT_ANYNUM, *s) )
|
|
|
|
if (!strchr(AST_DIGIT_ANYNUM, p->username[x])) {
|
|
|
|
|
|
|
|
onlydigits = FALSE;
|
|
|
|
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* If we have only digits, add ;user=phone to the uri */
|
|
|
|
/* If we have only digits, add ;user=phone to the uri */
|
|
|
|
if (onlydigits)
|
|
|
|
if (*s)
|
|
|
|
strcpy(urioptions, ";user=phone");
|
|
|
|
urioptions = ";user=phone";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -6452,7 +6456,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
|
|
|
|
l = tmp2;
|
|
|
|
l = tmp2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (ourport != DEFAULT_SIP_PORT && ast_strlen_zero(p->fromdomain)) /* Needs to be 5060 */
|
|
|
|
if (ourport != STANDARD_SIP_PORT && ast_strlen_zero(p->fromdomain))
|
|
|
|
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), ourport, p->tag);
|
|
|
|
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s:%d>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), ourport, p->tag);
|
|
|
|
else
|
|
|
|
else
|
|
|
|
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), p->tag);
|
|
|
|
snprintf(from, sizeof(from), "\"%s\" <sip:%s@%s>;tag=%s", n, l, S_OR(p->fromdomain, ast_inet_ntoa(p->ourip)), p->tag);
|
|
|
@ -6473,7 +6477,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
|
|
|
|
ast_build_string(&invite, &invite_max, "%s@", n);
|
|
|
|
ast_build_string(&invite, &invite_max, "%s@", n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_build_string(&invite, &invite_max, "%s", p->tohost);
|
|
|
|
ast_build_string(&invite, &invite_max, "%s", p->tohost);
|
|
|
|
if (ntohs(p->sa.sin_port) != DEFAULT_SIP_PORT) /* Needs to be 5060 */
|
|
|
|
if (ntohs(p->sa.sin_port) != STANDARD_SIP_PORT)
|
|
|
|
ast_build_string(&invite, &invite_max, ":%d", ntohs(p->sa.sin_port));
|
|
|
|
ast_build_string(&invite, &invite_max, ":%d", ntohs(p->sa.sin_port));
|
|
|
|
ast_build_string(&invite, &invite_max, "%s", urioptions);
|
|
|
|
ast_build_string(&invite, &invite_max, "%s", urioptions);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -6555,29 +6559,23 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
|
|
|
|
add_header(&req, "Require", "replaces");
|
|
|
|
add_header(&req, "Require", "replaces");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (p->options && !ast_strlen_zero(p->options->distinctive_ring))
|
|
|
|
|
|
|
|
add_header(&req, "Alert-Info", p->options->distinctive_ring);
|
|
|
|
|
|
|
|
add_header(&req, "Allow", ALLOWED_METHODS);
|
|
|
|
add_header(&req, "Allow", ALLOWED_METHODS);
|
|
|
|
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
|
|
|
|
add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
|
|
|
|
if (p->options && p->options->addsipheaders ) {
|
|
|
|
if (p->options && p->options->addsipheaders && p->owner) {
|
|
|
|
struct ast_channel *ast;
|
|
|
|
struct ast_channel *ast = p->owner; /* The owner channel */
|
|
|
|
struct varshead *headp = NULL;
|
|
|
|
struct varshead *headp = &ast->varshead;
|
|
|
|
const struct ast_var_t *current;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ast = p->owner; /* The owner channel */
|
|
|
|
|
|
|
|
if (ast) {
|
|
|
|
|
|
|
|
char *headdup;
|
|
|
|
|
|
|
|
headp = &ast->varshead;
|
|
|
|
|
|
|
|
if (!headp)
|
|
|
|
if (!headp)
|
|
|
|
ast_log(LOG_WARNING,"No Headp for the channel...ooops!\n");
|
|
|
|
ast_log(LOG_WARNING,"No Headp for the channel...ooops!\n");
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
|
|
|
|
const struct ast_var_t *current;
|
|
|
|
AST_LIST_TRAVERSE(headp, current, entries) {
|
|
|
|
AST_LIST_TRAVERSE(headp, current, entries) {
|
|
|
|
/* SIPADDHEADER: Add SIP header to outgoing call */
|
|
|
|
/* SIPADDHEADER: Add SIP header to outgoing call */
|
|
|
|
if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) {
|
|
|
|
if (!strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) {
|
|
|
|
char *content, *end;
|
|
|
|
char *content, *end;
|
|
|
|
const char *header = ast_var_value(current);
|
|
|
|
const char *header = ast_var_value(current);
|
|
|
|
|
|
|
|
char *headdup = ast_strdupa(header);
|
|
|
|
|
|
|
|
|
|
|
|
headdup = ast_strdupa(header);
|
|
|
|
|
|
|
|
/* Strip of the starting " (if it's there) */
|
|
|
|
/* Strip of the starting " (if it's there) */
|
|
|
|
if (*headdup == '"')
|
|
|
|
if (*headdup == '"')
|
|
|
|
headdup++;
|
|
|
|
headdup++;
|
|
|
@ -6597,7 +6595,6 @@ static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sdp) {
|
|
|
|
if (sdp) {
|
|
|
|
if (p->udptl && p->t38.state == T38_LOCAL_DIRECT) {
|
|
|
|
if (p->udptl && p->t38.state == T38_LOCAL_DIRECT) {
|
|
|
|
ast_udptl_offered_from_local(p->udptl, 1);
|
|
|
|
ast_udptl_offered_from_local(p->udptl, 1);
|
|
|
@ -7458,7 +7455,7 @@ static int set_address_from_contact(struct sip_pvt *pvt)
|
|
|
|
*pt++ = '\0';
|
|
|
|
*pt++ = '\0';
|
|
|
|
port = atoi(pt);
|
|
|
|
port = atoi(pt);
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
port = DEFAULT_SIP_PORT;
|
|
|
|
port = STANDARD_SIP_PORT;
|
|
|
|
|
|
|
|
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
|
/* We should only do this if it's a name, not an IP */
|
|
|
|
/* We should only do this if it's a name, not an IP */
|
|
|
@ -7565,7 +7562,7 @@ static enum parse_register_result parse_register_contact(struct sip_pvt *pvt, st
|
|
|
|
*pt++ = '\0';
|
|
|
|
*pt++ = '\0';
|
|
|
|
port = atoi(pt);
|
|
|
|
port = atoi(pt);
|
|
|
|
} else
|
|
|
|
} else
|
|
|
|
port = DEFAULT_SIP_PORT;
|
|
|
|
port = STANDARD_SIP_PORT;
|
|
|
|
oldsin = peer->addr;
|
|
|
|
oldsin = peer->addr;
|
|
|
|
if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE)) {
|
|
|
|
if (!ast_test_flag(&peer->flags[0], SIP_NAT_ROUTE)) {
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
|
/* XXX This could block for a long time XXX */
|
|
|
@ -8595,7 +8592,7 @@ static void check_via(struct sip_pvt *p, struct sip_request *req)
|
|
|
|
memset(&p->sa, 0, sizeof(p->sa));
|
|
|
|
memset(&p->sa, 0, sizeof(p->sa));
|
|
|
|
p->sa.sin_family = AF_INET;
|
|
|
|
p->sa.sin_family = AF_INET;
|
|
|
|
memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
|
|
|
|
memcpy(&p->sa.sin_addr, hp->h_addr, sizeof(p->sa.sin_addr));
|
|
|
|
p->sa.sin_port = htons(pt ? atoi(pt) : DEFAULT_SIP_PORT);
|
|
|
|
p->sa.sin_port = htons(pt ? atoi(pt) : STANDARD_SIP_PORT);
|
|
|
|
|
|
|
|
|
|
|
|
if (sip_debug_test_pvt(p)) {
|
|
|
|
if (sip_debug_test_pvt(p)) {
|
|
|
|
const struct sockaddr_in *dst = sip_real_dst(p);
|
|
|
|
const struct sockaddr_in *dst = sip_real_dst(p);
|
|
|
@ -8699,7 +8696,6 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
|
|
|
|
char calleridname[50];
|
|
|
|
char calleridname[50];
|
|
|
|
int debug=sip_debug_test_addr(sin);
|
|
|
|
int debug=sip_debug_test_addr(sin);
|
|
|
|
struct ast_variable *tmpvar = NULL, *v = NULL;
|
|
|
|
struct ast_variable *tmpvar = NULL, *v = NULL;
|
|
|
|
int usenatroute;
|
|
|
|
|
|
|
|
char *uri2 = ast_strdupa(uri);
|
|
|
|
char *uri2 = ast_strdupa(uri);
|
|
|
|
|
|
|
|
|
|
|
|
/* Terminate URI */
|
|
|
|
/* Terminate URI */
|
|
|
@ -8784,23 +8780,8 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
|
|
|
|
ast_string_field_set(p, cid_num, tmp);
|
|
|
|
ast_string_field_set(p, cid_num, tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
usenatroute = ast_test_flag(&p->flags[0], SIP_NAT_ROUTE);
|
|
|
|
do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE) );
|
|
|
|
|
|
|
|
|
|
|
|
if (p->rtp) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", usenatroute ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->rtp, usenatroute);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->vrtp) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", usenatroute ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->vrtp, usenatroute);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->udptl) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", usenatroute ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_udptl_setnat(p->udptl, usenatroute);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(res = check_auth(p, req, user->name, user->secret, user->md5secret, sipmethod, uri2, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
|
|
|
|
if (!(res = check_auth(p, req, user->name, user->secret, user->md5secret, sipmethod, uri2, reliable, ast_test_flag(req, SIP_PKT_IGNORE)))) {
|
|
|
|
sip_cancel_destroy(p);
|
|
|
|
sip_cancel_destroy(p);
|
|
|
|
ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
|
|
|
|
ast_copy_flags(&p->flags[0], &user->flags[0], SIP_FLAGS_TO_COPY);
|
|
|
@ -8906,22 +8887,8 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
|
|
|
|
ast_shrink_phone_number(tmp);
|
|
|
|
ast_shrink_phone_number(tmp);
|
|
|
|
ast_string_field_set(p, cid_num, tmp);
|
|
|
|
ast_string_field_set(p, cid_num, tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
usenatroute = ast_test_flag(&p->flags[0], SIP_NAT_ROUTE);
|
|
|
|
do_setnat(p, ast_test_flag(&p->flags[0], SIP_NAT_ROUTE));
|
|
|
|
if (p->rtp) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on RTP to %s\n", usenatroute ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->rtp, usenatroute);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->vrtp) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on VRTP to %s\n", usenatroute ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_rtp_setnat(p->vrtp, usenatroute);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (p->udptl) {
|
|
|
|
|
|
|
|
if (option_debug)
|
|
|
|
|
|
|
|
ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %s\n", usenatroute ? "On" : "Off");
|
|
|
|
|
|
|
|
ast_udptl_setnat(p->udptl, usenatroute);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_string_field_set(p, peersecret, peer->secret);
|
|
|
|
ast_string_field_set(p, peersecret, peer->secret);
|
|
|
|
ast_string_field_set(p, peermd5secret, peer->md5secret);
|
|
|
|
ast_string_field_set(p, peermd5secret, peer->md5secret);
|
|
|
|
ast_string_field_set(p, subscribecontext, peer->subscribecontext);
|
|
|
|
ast_string_field_set(p, subscribecontext, peer->subscribecontext);
|
|
|
@ -10000,7 +9967,7 @@ static int sip_show_registry(int fd, int argc, char *argv[])
|
|
|
|
ast_cli(fd, FORMAT2, "Host", "Username", "Refresh", "State", "Reg.Time");
|
|
|
|
ast_cli(fd, FORMAT2, "Host", "Username", "Refresh", "State", "Reg.Time");
|
|
|
|
ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do {
|
|
|
|
ASTOBJ_CONTAINER_TRAVERSE(®l, 1, do {
|
|
|
|
ASTOBJ_RDLOCK(iterator);
|
|
|
|
ASTOBJ_RDLOCK(iterator);
|
|
|
|
snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : DEFAULT_SIP_PORT);
|
|
|
|
snprintf(host, sizeof(host), "%s:%d", iterator->hostname, iterator->portno ? iterator->portno : STANDARD_SIP_PORT);
|
|
|
|
if (iterator->regtime) {
|
|
|
|
if (iterator->regtime) {
|
|
|
|
ast_localtime(&iterator->regtime, &tm, NULL);
|
|
|
|
ast_localtime(&iterator->regtime, &tm, NULL);
|
|
|
|
strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm);
|
|
|
|
strftime(tmpdat, sizeof(tmpdat), "%a, %d %b %Y %T", &tm);
|
|
|
@ -14330,12 +14297,11 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
|
|
|
|
struct sockaddr_in sin = { 0, };
|
|
|
|
struct sockaddr_in sin = { 0, };
|
|
|
|
struct sip_pvt *p;
|
|
|
|
struct sip_pvt *p;
|
|
|
|
int res;
|
|
|
|
int res;
|
|
|
|
socklen_t len;
|
|
|
|
socklen_t len = sizeof(sin);
|
|
|
|
int nounlock;
|
|
|
|
int nounlock;
|
|
|
|
int recount = 0;
|
|
|
|
int recount = 0;
|
|
|
|
unsigned int lockretry = 100;
|
|
|
|
int lockretry;
|
|
|
|
|
|
|
|
|
|
|
|
len = sizeof(sin);
|
|
|
|
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
memset(&req, 0, sizeof(req));
|
|
|
|
res = recvfrom(sipsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
|
|
|
|
res = recvfrom(sipsock, req.data, sizeof(req.data) - 1, 0, (struct sockaddr *)&sin, &len);
|
|
|
|
if (res < 0) {
|
|
|
|
if (res < 0) {
|
|
|
@ -14359,22 +14325,19 @@ static int sipsock_read(int *id, int fd, short events, void *ignore)
|
|
|
|
if (pedanticsipchecking)
|
|
|
|
if (pedanticsipchecking)
|
|
|
|
req.len = lws2sws(req.data, req.len); /* Fix multiline headers */
|
|
|
|
req.len = lws2sws(req.data, req.len); /* Fix multiline headers */
|
|
|
|
if (ast_test_flag(&req, SIP_PKT_DEBUG))
|
|
|
|
if (ast_test_flag(&req, SIP_PKT_DEBUG))
|
|
|
|
ast_verbose("\n<-- SIP read from %s:%d: \n%s\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), req.data);
|
|
|
|
ast_verbose("\n<--- SIP read from %s:%d --->\n%s\n<------------->\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), req.data);
|
|
|
|
|
|
|
|
|
|
|
|
parse_request(&req);
|
|
|
|
parse_request(&req);
|
|
|
|
req.method = find_sip_method(req.rlPart1);
|
|
|
|
req.method = find_sip_method(req.rlPart1);
|
|
|
|
if (ast_test_flag(&req, SIP_PKT_DEBUG)) {
|
|
|
|
|
|
|
|
|
|
|
|
if (ast_test_flag(&req, SIP_PKT_DEBUG))
|
|
|
|
ast_verbose("--- (%d headers %d lines)%s ---\n", req.headers, req.lines, (req.headers + req.lines == 0) ? " Nat keepalive" : "");
|
|
|
|
ast_verbose("--- (%d headers %d lines)%s ---\n", req.headers, req.lines, (req.headers + req.lines == 0) ? " Nat keepalive" : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (req.headers < 2) {
|
|
|
|
if (req.headers < 2) /* Must have at least two headers */
|
|
|
|
/* Must have at least two headers */
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Process request, with netlock held */
|
|
|
|
/* Process request, with netlock held, and with usual deadlock avoidance */
|
|
|
|
retrylock:
|
|
|
|
for (lockretry = 100; lockretry > 0; lockretry--) {
|
|
|
|
ast_mutex_lock(&netlock);
|
|
|
|
ast_mutex_lock(&netlock);
|
|
|
|
|
|
|
|
|
|
|
|
/* Find the active SIP dialog or create a new one */
|
|
|
|
/* Find the active SIP dialog or create a new one */
|
|
|
@ -14382,18 +14345,19 @@ retrylock:
|
|
|
|
if (p == NULL) {
|
|
|
|
if (p == NULL) {
|
|
|
|
if (option_debug)
|
|
|
|
if (option_debug)
|
|
|
|
ast_log(LOG_DEBUG, "Invalid SIP message - rejected , no callid, len %d\n", req.len);
|
|
|
|
ast_log(LOG_DEBUG, "Invalid SIP message - rejected , no callid, len %d\n", req.len);
|
|
|
|
} else {
|
|
|
|
ast_mutex_unlock(&netlock);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
/* Go ahead and lock the owner if it has one -- we may need it */
|
|
|
|
/* Go ahead and lock the owner if it has one -- we may need it */
|
|
|
|
/* becaues this is deadlock-prone, we need to try and unlock if failed */
|
|
|
|
/* becaues this is deadlock-prone, we need to try and unlock if failed */
|
|
|
|
if (p->owner && ast_channel_trylock(p->owner)) {
|
|
|
|
if (!p->owner || !ast_channel_trylock(p->owner))
|
|
|
|
|
|
|
|
break; /* locking succeeded */
|
|
|
|
if (option_debug)
|
|
|
|
if (option_debug)
|
|
|
|
ast_log(LOG_DEBUG, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
|
|
|
|
ast_log(LOG_DEBUG, "Failed to grab owner channel lock, trying again. (SIP call %s)\n", p->callid);
|
|
|
|
ast_mutex_unlock(&p->lock);
|
|
|
|
ast_mutex_unlock(&p->lock);
|
|
|
|
ast_mutex_unlock(&netlock);
|
|
|
|
ast_mutex_unlock(&netlock);
|
|
|
|
/* Sleep for a very short amount of time */
|
|
|
|
/* Sleep for a very short amount of time */
|
|
|
|
usleep(1);
|
|
|
|
usleep(1);
|
|
|
|
if (--lockretry)
|
|
|
|
|
|
|
|
goto retrylock;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p->recv = sin;
|
|
|
|
p->recv = sin;
|
|
|
|
|
|
|
|
|
|
|
@ -14401,7 +14365,7 @@ retrylock:
|
|
|
|
append_history(p, "Rx", "%s / %s / %s", req.data, get_header(&req, "CSeq"), req.rlPart2);
|
|
|
|
append_history(p, "Rx", "%s / %s / %s", req.data, get_header(&req, "CSeq"), req.rlPart2);
|
|
|
|
|
|
|
|
|
|
|
|
if (!lockretry) {
|
|
|
|
if (!lockretry) {
|
|
|
|
ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", p->owner->name ? p->owner->name : "- no channel name ??? - ");
|
|
|
|
ast_log(LOG_ERROR, "We could NOT get the channel lock for %s! \n", S_OR(p->owner->name, "- no channel name ??? - "));
|
|
|
|
ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid);
|
|
|
|
ast_log(LOG_ERROR, "SIP transaction failed: %s \n", p->callid);
|
|
|
|
transmit_response(p, "503 Server error", &req); /* We must respond according to RFC 3261 sec 12.2 */
|
|
|
|
transmit_response(p, "503 Server error", &req); /* We must respond according to RFC 3261 sec 12.2 */
|
|
|
|
/* XXX We could add retry-after to make sure they come back */
|
|
|
|
/* XXX We could add retry-after to make sure they come back */
|
|
|
@ -14418,7 +14382,6 @@ retrylock:
|
|
|
|
if (p->owner && !nounlock)
|
|
|
|
if (p->owner && !nounlock)
|
|
|
|
ast_channel_unlock(p->owner);
|
|
|
|
ast_channel_unlock(p->owner);
|
|
|
|
ast_mutex_unlock(&p->lock);
|
|
|
|
ast_mutex_unlock(&p->lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_mutex_unlock(&netlock);
|
|
|
|
ast_mutex_unlock(&netlock);
|
|
|
|
if (recount)
|
|
|
|
if (recount)
|
|
|
|
ast_update_use_count();
|
|
|
|
ast_update_use_count();
|
|
|
@ -15335,7 +15298,7 @@ static void set_peer_defaults(struct sip_peer *peer)
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
peer->expire = -1;
|
|
|
|
peer->expire = -1;
|
|
|
|
peer->pokeexpire = -1;
|
|
|
|
peer->pokeexpire = -1;
|
|
|
|
peer->addr.sin_port = htons(DEFAULT_SIP_PORT);
|
|
|
|
peer->addr.sin_port = htons(STANDARD_SIP_PORT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
|
|
|
|
ast_copy_flags(&peer->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
|
|
|
|
ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
|
|
|
|
ast_copy_flags(&peer->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
|
|
|
@ -15513,7 +15476,7 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, str
|
|
|
|
else {
|
|
|
|
else {
|
|
|
|
ast_copy_string(peer->tohost, v->value, sizeof(peer->tohost));
|
|
|
|
ast_copy_string(peer->tohost, v->value, sizeof(peer->tohost));
|
|
|
|
if (!peer->addr.sin_port)
|
|
|
|
if (!peer->addr.sin_port)
|
|
|
|
peer->addr.sin_port = htons(DEFAULT_SIP_PORT);
|
|
|
|
peer->addr.sin_port = htons(STANDARD_SIP_PORT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (!strcasecmp(v->name, "defaultip")) {
|
|
|
|
} else if (!strcasecmp(v->name, "defaultip")) {
|
|
|
@ -15689,9 +15652,9 @@ static int reload_config(enum channelreloadreason reason)
|
|
|
|
memset(&localaddr, 0, sizeof(localaddr));
|
|
|
|
memset(&localaddr, 0, sizeof(localaddr));
|
|
|
|
memset(&externip, 0, sizeof(externip));
|
|
|
|
memset(&externip, 0, sizeof(externip));
|
|
|
|
memset(&default_prefs, 0 , sizeof(default_prefs));
|
|
|
|
memset(&default_prefs, 0 , sizeof(default_prefs));
|
|
|
|
outboundproxyip.sin_port = htons(DEFAULT_SIP_PORT);
|
|
|
|
outboundproxyip.sin_port = htons(STANDARD_SIP_PORT);
|
|
|
|
outboundproxyip.sin_family = AF_INET; /* Type of address: IPv4 */
|
|
|
|
outboundproxyip.sin_family = AF_INET; /* Type of address: IPv4 */
|
|
|
|
ourport = DEFAULT_SIP_PORT;
|
|
|
|
ourport = STANDARD_SIP_PORT;
|
|
|
|
srvlookup = DEFAULT_SRVLOOKUP;
|
|
|
|
srvlookup = DEFAULT_SRVLOOKUP;
|
|
|
|
global_tos_sip = DEFAULT_TOS_SIP;
|
|
|
|
global_tos_sip = DEFAULT_TOS_SIP;
|
|
|
|
global_tos_audio = DEFAULT_TOS_AUDIO;
|
|
|
|
global_tos_audio = DEFAULT_TOS_AUDIO;
|
|
|
@ -15721,6 +15684,7 @@ static int reload_config(enum channelreloadreason reason)
|
|
|
|
pedanticsipchecking = DEFAULT_PEDANTIC;
|
|
|
|
pedanticsipchecking = DEFAULT_PEDANTIC;
|
|
|
|
global_mwitime = DEFAULT_MWITIME;
|
|
|
|
global_mwitime = DEFAULT_MWITIME;
|
|
|
|
autocreatepeer = DEFAULT_AUTOCREATEPEER;
|
|
|
|
autocreatepeer = DEFAULT_AUTOCREATEPEER;
|
|
|
|
|
|
|
|
global_autoframing = 0;
|
|
|
|
global_allowguest = DEFAULT_ALLOWGUEST;
|
|
|
|
global_allowguest = DEFAULT_ALLOWGUEST;
|
|
|
|
global_rtptimeout = 0;
|
|
|
|
global_rtptimeout = 0;
|
|
|
|
global_rtpholdtimeout = 0;
|
|
|
|
global_rtpholdtimeout = 0;
|
|
|
@ -16114,7 +16078,7 @@ static int reload_config(enum channelreloadreason reason)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!ntohs(bindaddr.sin_port))
|
|
|
|
if (!ntohs(bindaddr.sin_port))
|
|
|
|
bindaddr.sin_port = ntohs(DEFAULT_SIP_PORT);
|
|
|
|
bindaddr.sin_port = ntohs(STANDARD_SIP_PORT);
|
|
|
|
bindaddr.sin_family = AF_INET;
|
|
|
|
bindaddr.sin_family = AF_INET;
|
|
|
|
ast_mutex_lock(&netlock);
|
|
|
|
ast_mutex_lock(&netlock);
|
|
|
|
if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) {
|
|
|
|
if ((sipsock > -1) && (memcmp(&old_bindaddr, &bindaddr, sizeof(struct sockaddr_in)))) {
|
|
|
@ -16690,9 +16654,9 @@ static int sip_reload(int fd, int argc, char *argv[])
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
ast_mutex_lock(&sip_reload_lock);
|
|
|
|
ast_mutex_lock(&sip_reload_lock);
|
|
|
|
if (sip_reloading) {
|
|
|
|
if (sip_reloading)
|
|
|
|
ast_verbose("Previous SIP reload not yet done\n");
|
|
|
|
ast_verbose("Previous SIP reload not yet done\n");
|
|
|
|
} else {
|
|
|
|
else {
|
|
|
|
sip_reloading = TRUE;
|
|
|
|
sip_reloading = TRUE;
|
|
|
|
if (fd)
|
|
|
|
if (fd)
|
|
|
|
sip_reloadreason = CHANNEL_CLI_RELOAD;
|
|
|
|
sip_reloadreason = CHANNEL_CLI_RELOAD;
|
|
|
@ -16929,6 +16893,7 @@ static int load_module(void)
|
|
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief PBX unload module API */
|
|
|
|
static int unload_module(void)
|
|
|
|
static int unload_module(void)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct sip_pvt *p, *pl;
|
|
|
|
struct sip_pvt *p, *pl;
|
|
|
@ -16936,20 +16901,26 @@ static int unload_module(void)
|
|
|
|
/* First, take us out of the channel type list */
|
|
|
|
/* First, take us out of the channel type list */
|
|
|
|
ast_channel_unregister(&sip_tech);
|
|
|
|
ast_channel_unregister(&sip_tech);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Unregister dial plan functions */
|
|
|
|
ast_custom_function_unregister(&sipchaninfo_function);
|
|
|
|
ast_custom_function_unregister(&sipchaninfo_function);
|
|
|
|
ast_custom_function_unregister(&sippeer_function);
|
|
|
|
ast_custom_function_unregister(&sippeer_function);
|
|
|
|
ast_custom_function_unregister(&sip_header_function);
|
|
|
|
ast_custom_function_unregister(&sip_header_function);
|
|
|
|
ast_custom_function_unregister(&checksipdomain_function);
|
|
|
|
ast_custom_function_unregister(&checksipdomain_function);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Unregister dial plan applications */
|
|
|
|
ast_unregister_application(app_dtmfmode);
|
|
|
|
ast_unregister_application(app_dtmfmode);
|
|
|
|
ast_unregister_application(app_sipaddheader);
|
|
|
|
ast_unregister_application(app_sipaddheader);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Unregister CLI commands */
|
|
|
|
ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry));
|
|
|
|
ast_cli_unregister_multiple(cli_sip, sizeof(cli_sip) / sizeof(struct ast_cli_entry));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Disconnect from the RTP subsystem */
|
|
|
|
ast_rtp_proto_unregister(&sip_rtp);
|
|
|
|
ast_rtp_proto_unregister(&sip_rtp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Disconnect from UDPTL */
|
|
|
|
ast_udptl_proto_unregister(&sip_udptl);
|
|
|
|
ast_udptl_proto_unregister(&sip_udptl);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Unregister AMI actions */
|
|
|
|
ast_manager_unregister("SIPpeers");
|
|
|
|
ast_manager_unregister("SIPpeers");
|
|
|
|
ast_manager_unregister("SIPshowpeer");
|
|
|
|
ast_manager_unregister("SIPshowpeer");
|
|
|
|
|
|
|
|
|
|
|
|